]> git.sur5r.net Git - openldap/commitdiff
Import experimental referral implementation from OPENLDAP_DEVEL_REFERRALS.
authorKurt Zeilenga <kurt@openldap.org>
Fri, 16 Jul 1999 02:45:46 +0000 (02:45 +0000)
committerKurt Zeilenga <kurt@openldap.org>
Fri, 16 Jul 1999 02:45:46 +0000 (02:45 +0000)
Includes support for update referral for each replicated backend.
Reworked replication test to use update referral.
Includes major rewrite of response encoding codes (result.c).
Includes reworked alias support and eliminates old suffix alias codes
(can be emulated using named alias).
Includes (untested) support for the Manage DSA IT control.
Works in LDAPv2 world.  Still testing in LDAPv3 world.
Added default referral (test009) test.

116 files changed:
build/main.dsw
clients/tools/ldapdelete.c
clients/tools/ldapmodify.c
clients/tools/ldapmodrdn.c
clients/tools/ldapsearch.c
doc/man/man1/ldapdelete.1
doc/man/man1/ldapmodify.1
doc/man/man1/ldapmodrdn.1
doc/man/man1/ldapsearch.1
doc/man/man5/slapd.conf.5
include/ldap.h
libraries/libldbm/libldbm.dsp
servers/slapd/Makefile.in
servers/slapd/abandon.c
servers/slapd/aclparse.c
servers/slapd/add.c
servers/slapd/back-bdb2/add.c
servers/slapd/back-bdb2/alias.c
servers/slapd/back-bdb2/bind.c
servers/slapd/back-bdb2/compare.c
servers/slapd/back-bdb2/delete.c
servers/slapd/back-bdb2/dn2id.c
servers/slapd/back-bdb2/group.c
servers/slapd/back-bdb2/modify.c
servers/slapd/back-bdb2/modrdn.c
servers/slapd/back-bdb2/proto-back-bdb2.h
servers/slapd/back-bdb2/search.c
servers/slapd/back-ldap/bind.c
servers/slapd/back-ldap/search.c
servers/slapd/back-ldbm/add.c
servers/slapd/back-ldbm/alias.c
servers/slapd/back-ldbm/bind.c
servers/slapd/back-ldbm/compare.c
servers/slapd/back-ldbm/delete.c
servers/slapd/back-ldbm/dn2id.c
servers/slapd/back-ldbm/group.c
servers/slapd/back-ldbm/modify.c
servers/slapd/back-ldbm/modrdn.c
servers/slapd/back-ldbm/proto-back-ldbm.h
servers/slapd/back-ldbm/search.c
servers/slapd/back-passwd/search.c
servers/slapd/back-perl/add.c
servers/slapd/back-perl/compare.c
servers/slapd/back-perl/delete.c
servers/slapd/back-perl/modify.c
servers/slapd/back-perl/modrdn.c
servers/slapd/back-perl/search.c
servers/slapd/back-perl/unbind.c
servers/slapd/back-shell/add.c
servers/slapd/back-shell/bind.c
servers/slapd/back-shell/compare.c
servers/slapd/back-shell/delete.c
servers/slapd/back-shell/modify.c
servers/slapd/back-shell/modrdn.c
servers/slapd/back-shell/result.c
servers/slapd/back-shell/search.c
servers/slapd/back-shell/unbind.c
servers/slapd/back-tcl/tcl_add.c
servers/slapd/back-tcl/tcl_bind.c
servers/slapd/back-tcl/tcl_compare.c
servers/slapd/back-tcl/tcl_delete.c
servers/slapd/back-tcl/tcl_modify.c
servers/slapd/back-tcl/tcl_modrdn.c
servers/slapd/back-tcl/tcl_search.c
servers/slapd/back-tcl/tcl_unbind.c
servers/slapd/back-tcl/tcl_util.c
servers/slapd/backend.c
servers/slapd/bind.c
servers/slapd/charray.c
servers/slapd/compare.c
servers/slapd/config.c
servers/slapd/configinfo.c
servers/slapd/controls.c
servers/slapd/delete.c
servers/slapd/extended.c
servers/slapd/init.c
servers/slapd/libslapd.dsp
servers/slapd/modify.c
servers/slapd/modrdn.c
servers/slapd/monitor.c
servers/slapd/proto-slap.h
servers/slapd/result.c
servers/slapd/root_dse.c
servers/slapd/schema.c
servers/slapd/schema/core.schema
servers/slapd/search.c
servers/slapd/slap.h
servers/slapd/slapd.at.conf
servers/slapd/slapd.dsp
servers/slapd/slapd.dsw
servers/slapd/slapd.oc.conf
servers/slapd/suffixalias.c [deleted file]
servers/slapd/tools/Makefile.in
servers/slapd/tools/ldbmcat.dsp
servers/slapd/tools/ldbmtest.c
servers/slapd/tools/ldbmtest.dsp
servers/slapd/tools/mimic.c
tests/data/referrals.ldif [new file with mode: 0644]
tests/data/slapd-acl.conf
tests/data/slapd-bdb2-ref-slave.conf [new file with mode: 0644]
tests/data/slapd-bdb2-repl-master.conf
tests/data/slapd-bdb2-repl-slave.conf
tests/data/slapd-ref-slave.conf [new file with mode: 0644]
tests/data/slapd-repl-master.conf
tests/data/slapd-repl-slave.conf
tests/data/slapd.at.conf
tests/data/slapd.oc.conf
tests/scripts/defines.sh
tests/scripts/test002-populate
tests/scripts/test003-search
tests/scripts/test004-modify
tests/scripts/test005-modrdn
tests/scripts/test006-acls
tests/scripts/test007-replication
tests/scripts/test008-concurrency
tests/scripts/test009-referral [new file with mode: 0755]

index 7ba7d7be6b8734f4e66adcaeef57637044d7952a..e728552c96b0d24dd2771836159c04b24265e446 100644 (file)
@@ -272,6 +272,21 @@ Package=<4>
     Begin Project Dependency
     Project_Dep_Name libldbm
     End Project Dependency
+    Begin Project Dependency
+    Project_Dep_Name backldbm
+    End Project Dependency
+    Begin Project Dependency
+    Project_Dep_Name libslapd
+    End Project Dependency
+    Begin Project Dependency
+    Project_Dep_Name liblber
+    End Project Dependency
+    Begin Project Dependency
+    Project_Dep_Name libldap_r
+    End Project Dependency
+    Begin Project Dependency
+    Project_Dep_Name liblutil
+    End Project Dependency
 }}}
 
 ###############################################################################
@@ -284,6 +299,30 @@ Package=<5>
 
 Package=<4>
 {{{
+    Begin Project Dependency
+    Project_Dep_Name backldbm
+    End Project Dependency
+    Begin Project Dependency
+    Project_Dep_Name liblber
+    End Project Dependency
+    Begin Project Dependency
+    Project_Dep_Name libldap_r
+    End Project Dependency
+    Begin Project Dependency
+    Project_Dep_Name libldbm
+    End Project Dependency
+    Begin Project Dependency
+    Project_Dep_Name liblutil
+    End Project Dependency
+    Begin Project Dependency
+    Project_Dep_Name libslapd
+    End Project Dependency
+    Begin Project Dependency
+    Project_Dep_Name libavl
+    End Project Dependency
+    Begin Project Dependency
+    Project_Dep_Name libldif
+    End Project Dependency
 }}}
 
 ###############################################################################
index 72d550df2ff628d7d5b8e91836f2eda2ee340c9a..ddd80e399b72ce524dbf729a9fb00ba6684a102b 100644 (file)
@@ -29,17 +29,17 @@ static int dodelete LDAP_P((
 int
 main( int argc, char **argv )
 {
-       char            *usage = "usage: %s [-n] [-v] [-k] [-W] [-d debug-level] [-f file] [-h ldaphost] [-P version] [-p ldapport] [-D binddn] [-w passwd] [dn]...\n";
+       char            *usage = "usage: %s [-n] [-v] [-k] [-W] [-M[M]] [-d debug-level] [-f file] [-h ldaphost] [-P version] [-p ldapport] [-D binddn] [-w passwd] [dn]...\n";
     char               buf[ 4096 ];
     FILE               *fp;
-       int             i, rc, authmethod, want_bindpw, version, debug;
+       int             i, rc, authmethod, want_bindpw, version, debug, manageDSAit;
 
-    not = verbose = contoper = want_bindpw = debug = 0;
+    not = verbose = contoper = want_bindpw = debug = manageDSAit = 0;
     fp = NULL;
     authmethod = LDAP_AUTH_SIMPLE;
        version = -1;
 
-    while (( i = getopt( argc, argv, "WnvkKch:P:p:D:w:d:f:" )) != EOF ) {
+    while (( i = getopt( argc, argv, "WMnvkKch:P:p:D:w:d:f:" )) != EOF ) {
        switch( i ) {
        case 'k':       /* kerberos bind */
 #ifdef HAVE_KERBEROS
@@ -96,6 +96,10 @@ main( int argc, char **argv )
        case 'v':       /* verbose mode */
            verbose++;
            break;
+       case 'M':
+               /* enable Manage DSA IT */
+               manageDSAit++;
+               break;
        case 'W':
                want_bindpw++;
                break;
@@ -164,6 +168,28 @@ main( int argc, char **argv )
        return( EXIT_FAILURE );
     }
 
+       if ( manageDSAit ) {
+               int err;
+               LDAPControl c;
+               LDAPControl *ctrls[2];
+               ctrls[0] = &c;
+               ctrls[1] = NULL;
+
+               c.ldctl_oid = LDAP_CONTROL_MANAGEDSAIT;
+               c.ldctl_value.bv_val = NULL;
+               c.ldctl_value.bv_len = 0;
+               c.ldctl_iscritical = manageDSAit > 1;
+
+               err = ldap_set_option( ld, LDAP_OPT_SERVER_CONTROLS, &ctrls );
+
+               if( err != LDAP_OPT_SUCCESS ) {
+                       fprintf( stderr, "Could not set Manage DSA IT Control\n" );
+                       if( c.ldctl_iscritical ) {
+                               exit( EXIT_FAILURE );
+                       }
+               }
+       }
+
     if ( fp == NULL ) {
        for ( ; optind < argc; ++optind ) {
            rc = dodelete( ld, argv[ optind ] );
index dc150e31f0332a3cacc385e3ba2d34c19d8065db..36edc0d29f67a8de1c7263609b1b1e98963fa6a4 100644 (file)
@@ -72,12 +72,13 @@ usage( const char *prog )
 {
     fprintf( stderr,
                 "Add or modify entries from an LDAP server\n\n"
-            "usage: %s [-abcknrvF] [-d debug-level] [-P version] [-h ldaphost]\n"
+            "usage: %s [-abcknrvF] [-M[M]] [-d debug-level] [-P version] [-h ldaphost]\n"
             "            [-p ldapport] [-D binddn] [-w passwd] [ -f file | < entryfile ]\n"
             "       a    - add values (default%s)\n"
             "       b    - read values from files (for binary attributes)\n"
             "       c    - continuous operation\n"
             "       D    - bind DN\n"
+                "       M    - enable Manage DSA IT control (-MM for critical)\n"
             "       d    - debug level\n"
             "       f    - read from file\n"
             "       F    - force all changes records to be used\n"
@@ -97,7 +98,7 @@ main( int argc, char **argv )
 {
     char               *infile, *rbuf, *start, *p, *q;
     FILE               *fp;
-       int             rc, i, use_ldif, authmethod, version, want_bindpw, debug;
+       int             rc, i, use_ldif, authmethod, version, want_bindpw, debug, manageDSAit;
 
     if (( prog = strrchr( argv[ 0 ], *LDAP_DIRSEP )) == NULL ) {
        prog = argv[ 0 ];
@@ -112,11 +113,11 @@ main( int argc, char **argv )
     new = ( strcmp( prog, "ldapadd" ) == 0 );
 
     infile = NULL;
-    not = verbose = valsfromfiles = want_bindpw = debug = 0;
+    not = verbose = valsfromfiles = want_bindpw = debug = manageDSAit = 0;
     authmethod = LDAP_AUTH_SIMPLE;
        version = -1;
 
-    while (( i = getopt( argc, argv, "WFabckKnrtvh:p:D:w:d:f:P:" )) != EOF ) {
+    while (( i = getopt( argc, argv, "WFMabckKnrtvh:p:D:w:d:f:P:" )) != EOF ) {
        switch( i ) {
        case 'a':       /* add */
            new = 1;
@@ -182,6 +183,10 @@ main( int argc, char **argv )
        case 'v':       /* verbose mode */
            verbose++;
            break;
+       case 'M':
+               /* enable Manage DSA IT */
+               manageDSAit++;
+               break;
        case 'W':
                want_bindpw++;
                break;
@@ -259,6 +264,28 @@ main( int argc, char **argv )
 
     rc = 0;
 
+       if ( manageDSAit ) {
+               int err;
+               LDAPControl c;
+               LDAPControl *ctrls[2];
+               ctrls[0] = &c;
+               ctrls[1] = NULL;
+
+               c.ldctl_oid = LDAP_CONTROL_MANAGEDSAIT;
+               c.ldctl_value.bv_val = NULL;
+               c.ldctl_value.bv_len = 0;
+               c.ldctl_iscritical = manageDSAit > 1;
+
+               err = ldap_set_option( ld, LDAP_OPT_SERVER_CONTROLS, &ctrls );
+
+               if( err != LDAP_OPT_SUCCESS ) {
+                       fprintf( stderr, "Could not set Manage DSA IT Control\n" );
+                       if( c.ldctl_iscritical ) {
+                               exit( EXIT_FAILURE );
+                       }
+               }
+       }
+
     while (( rc == 0 || contoper ) &&
                ( rbuf = read_one_record( fp )) != NULL ) {
        /*
index a3571863ad8beeca17056b14a6b24ca559561810..d7c98d3854d71d3e734dabe471f725d76c699797 100644 (file)
@@ -44,20 +44,20 @@ static int domodrdn LDAP_P((
 int
 main(int argc, char **argv)
 {
-       char            *usage = "usage: %s [-nvkWc] [-d debug-level] [-h ldaphost] [-P version] [-p ldapport] [-D binddn] [-w passwd] [ -f file | < entryfile | dn newrdn ] [-s newSuperior]\n";
+       char            *usage = "usage: %s [-nvkWc] [-M[M]] [-d debug-level] [-h ldaphost] [-P version] [-p ldapport] [-D binddn] [-w passwd] [ -f file | < entryfile | dn newrdn ] [-s newSuperior]\n";
     char               *myname,*infile, *entrydn, *rdn, buf[ 4096 ];
     FILE               *fp;
-       int             rc, i, remove, havedn, authmethod, version, want_bindpw, debug;
+       int             rc, i, remove, havedn, authmethod, version, want_bindpw, debug, manageDSAit;
     char       *newSuperior=NULL;
 
     infile = NULL;
-    not = contoper = verbose = remove = want_bindpw = debug = 0;
+    not = contoper = verbose = remove = want_bindpw = debug = manageDSAit = 0;
     authmethod = LDAP_AUTH_SIMPLE;
        version = -1;
 
     myname = (myname = strrchr(argv[0], '/')) == NULL ? argv[0] : ++myname;
 
-    while (( i = getopt( argc, argv, "WkKcnvrh:P:p:D:w:d:f:s:" )) != EOF ) {
+    while (( i = getopt( argc, argv, "WkKMcnvrh:P:p:D:w:d:f:s:" )) != EOF ) {
        switch( i ) {
        case 'k':       /* kerberos bind */
 #ifdef HAVE_KERBEROS
@@ -116,6 +116,10 @@ main(int argc, char **argv)
        case 'r':       /* remove old RDN */
            remove++;
            break;
+       case 'M':
+               /* enable Manage DSA IT */
+               manageDSAit++;
+               break;
        case 'W':
                want_bindpw++;
                break;
@@ -217,6 +221,28 @@ main(int argc, char **argv)
        return( EXIT_FAILURE );
     }
 
+       if ( manageDSAit ) {
+               int err;
+               LDAPControl c;
+               LDAPControl *ctrls[2];
+               ctrls[0] = &c;
+               ctrls[1] = NULL;
+
+               c.ldctl_oid = LDAP_CONTROL_MANAGEDSAIT;
+               c.ldctl_value.bv_val = NULL;
+               c.ldctl_value.bv_len = 0;
+               c.ldctl_iscritical = manageDSAit > 1;
+
+               err = ldap_set_option( ld, LDAP_OPT_SERVER_CONTROLS, &ctrls );
+
+               if( err != LDAP_OPT_SUCCESS ) {
+                       fprintf( stderr, "Could not set Manage DSA IT Control\n" );
+                       if( c.ldctl_iscritical ) {
+                               exit( EXIT_FAILURE );
+                       }
+               }
+       }
+
     rc = 0;
     if (havedn)
        rc = domodrdn(ld, entrydn, rdn, remove, newSuperior);
index 54e4b244295f7a3e97fa1b106863065659cfe94b..be840ee596e1551bfa4ae7ca11774743a563ac63 100644 (file)
@@ -22,7 +22,9 @@ usage( char *s )
     fprintf( stderr, "usage: %s [options] filter [attributes...]\nwhere:\n", s );
     fprintf( stderr, "    filter\tRFC-1558 compliant LDAP search filter\n" );
     fprintf( stderr, "    attributes\twhitespace-separated list of attributes to retrieve\n" );
-    fprintf( stderr, "\t\t(if no attribute list is given, all are retrieved)\n" );
+    fprintf( stderr, "\t\t*          -- all user attributes\n" );
+    fprintf( stderr, "\t\tempty list -- all non-operational attributes\n" );
+    fprintf( stderr, "\t\t1.1        -- no attributes\n" );
     fprintf( stderr, "options:\n" );
     fprintf( stderr, "    -n\t\tshow what would be done but don't actually search\n" );
     fprintf( stderr, "    -v\t\trun in verbose mode (diagnostics to standard output)\n" );
@@ -31,9 +33,8 @@ usage( char *s )
     fprintf( stderr, "    -A\t\tretrieve attribute names only (no values)\n" );
     fprintf( stderr, "    -B\t\tdo not suppress printing of non-ASCII values\n" );
     fprintf( stderr, "    -L\t\tprint entries in LDIF format (-B is implied)\n" );
-#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_REFERRALS
+    fprintf( stderr, "    -M\t\tenable Manage DSA IT control (-MM implies critical)\n" );
     fprintf( stderr, "    -R\t\tdo not automatically follow referrals\n" );
-#endif /* LDAP_API_FEATURE_X_OPENLDAP_V2_REFERRALS */
     fprintf( stderr, "    -d level\tset LDAP debugging level to `level'\n" );
     fprintf( stderr, "    -F sep\tprint `sep' instead of `=' between attribute names and values\n" );
     fprintf( stderr, "    -S attr\tsort the results by attribute `attr'\n" );
@@ -89,21 +90,21 @@ main( int argc, char **argv )
 {
     char               *infile, *filtpattern, **attrs, line[ BUFSIZ ];
     FILE               *fp;
-    int                        rc, i, first, scope, deref, attrsonly;
+    int                        rc, i, first, scope, deref, attrsonly, manageDSAit;
     int                        referrals, timelimit, sizelimit, debug;
        int             authmethod, version, want_bindpw;
     LDAP               *ld;
 
     infile = NULL;
     debug = verbose = allow_binary = not = vals2tmp =
-           attrsonly = ldif = want_bindpw = 0;
+           attrsonly = manageDSAit = ldif = want_bindpw = 0;
 
        deref = referrals = sizelimit = timelimit = version = -1;
 
        scope = LDAP_SCOPE_SUBTREE;
     authmethod = LDAP_AUTH_SIMPLE;
 
-    while (( i = getopt( argc, argv, "WKknuvtRABLD:s:f:h:b:d:P:p:F:a:w:l:z:S:")) != EOF ) {
+    while (( i = getopt( argc, argv, "WKknuvtMRABLD:s:f:h:b:d:P:p:F:a:w:l:z:S:")) != EOF ) {
        switch( i ) {
        case 'n':       /* do Not do any searches */
            ++not;
@@ -134,6 +135,10 @@ main( int argc, char **argv )
        case 't':       /* write attribute values to /tmp files */
            ++vals2tmp;
            break;
+       case 'M':
+               /* enable Manage DSA IT */
+               manageDSAit++;
+               break;
        case 'R':       /* don't automatically chase referrals */
                referrals = (int) LDAP_OPT_OFF;
            break;
@@ -339,6 +344,28 @@ main( int argc, char **argv )
        fprintf( stderr, "\n" );
     }
 
+       if ( manageDSAit ) {
+               int err;
+               LDAPControl c;
+               LDAPControl *ctrls[2];
+               ctrls[0] = &c;
+               ctrls[1] = NULL;
+
+               c.ldctl_oid = LDAP_CONTROL_MANAGEDSAIT;
+               c.ldctl_value.bv_val = NULL;
+               c.ldctl_value.bv_len = 0;
+               c.ldctl_iscritical = manageDSAit > 1;
+
+               err = ldap_set_option( ld, LDAP_OPT_SERVER_CONTROLS, &ctrls );
+
+               if( err != LDAP_OPT_SUCCESS ) {
+                       fprintf( stderr, "Could not set Manage DSA IT Control\n" );
+                       if( c.ldctl_iscritical ) {
+                               exit( EXIT_FAILURE );
+                       }
+               }
+       }
+
     if ( infile == NULL ) {
        rc = dosearch( ld, base, scope, attrs, attrsonly, filtpattern, "" );
     } else {
index 859623b1d8e4fe477765a6995aba86b6d97af210..492de1020211c58a79ef00dc0ef76df6b3166099 100644 (file)
@@ -14,6 +14,8 @@ ldapdelete \- ldap delete entry tool
 [\c
 .BR \-c ]
 [\c
+.BR \-M[M] ]
+[\c
 .BI \-d \ debuglevel\fR]
 [\c
 .BI \-f \ file\fR]
@@ -71,6 +73,11 @@ Continuous operation mode.  Errors  are  reported,  but
 will  continue  with  deletions.   The default is to exit after
 reporting an error.
 .TP
+.B \-M[M]
+Enable manage DSA IT control.
+.B \-MM
+makes control critical.
+.TP
 .BI \-d \ debuglevel
 Set the LDAP debugging level to \fIdebuglevel\fP.
 .B ldapdelete
index 2b7e4b84b3c860c032944197bdf0344ad04dc979..8da1462d447205b26da4bb5b5ed2138cad4bec17 100644 (file)
@@ -18,6 +18,8 @@ ldapmodify, ldapadd \- ldap modify entry and ldap add entry tools
 [\c
 .BR \-k ]
 [\c
+.BR \-M[M] ]
+[\c
 .BI \-d \ debuglevel\fR]
 [\c
 .BI \-D \ binddn\fR]
@@ -124,6 +126,11 @@ lines that begin with
 (by default, replica: lines are compared against the LDAP server host
 and port in use to decide if a replog record should actually be applied).
 .TP
+.B \-M[M]
+Enable manage DSA IT control.
+.B \-MM
+makes control critical.
+.TP
 .BI \-d \ debuglevel
 Set the LDAP debugging level to \fIdebuglevel\fP.
 .B ldapmodify
index 43caf29114652da66d4266c43af934968c217e1d..1d9dd12e2139fbaede09748fd9f3b6cb9ecf349f 100644 (file)
@@ -16,6 +16,8 @@ ldapmodrdn \- ldap modify entry RDN tool
 [\c
 .BR \-c ]
 [\c
+.BR \-M[M] ]
+[\c
 .BI \-d \ debuglevel\fR]
 [\c
 .BI \-D \ binddn\fR]
@@ -74,6 +76,11 @@ Continuous operation mode.  Errors  are  reported,  but ldapmodify
 will  continue  with  modifications.   The default is to exit after
 reporting an error.
 .TP
+.B \-M[M]
+Enable manage DSA IT control.
+.B \-MM
+makes control critical.
+.TP
 .B \-d debuglevel
 Set the LDAP debugging level to \fIdebuglevel\fP.
 .B ldapmodrdn
index 38e4db98e28494d8332e7a9cab4925309122eb60..96b38ea6f969e0ad472f852e0e5dd41fedc86c26 100644 (file)
@@ -22,6 +22,8 @@ ldapsearch \- ldap search tool
 [\c
 .BR \-L ]
 [\c
+.BR \-M[M] ]
+[\c
 .BR \-R ]
 [\c
 .BI \-d \ debuglevel\fR]
@@ -114,6 +116,11 @@ Display search results in
 format.  This option also turns on the -B option, and causes the -F option
 to be ignored.
 .TP
+.B \-M[M]
+Enable manage DSA IT control.
+.B \-MM
+makes control critical.
+.TP
 .B \-R
 Do not automatically follow referrals returned while searching.
 .B ldapsearch
index 7bca55ba17c450b91a64d3738c78d09b56fa1620..a075970637307aaef5377bad6caf4e2d7d4af535 100644 (file)
@@ -198,6 +198,7 @@ used in conjunction with the schemacheck option.
 Specify the referral to pass back when
 .BR slapd (8)
 cannot find a local database to handle a request.
+If specified multiple times, each url is provided.
 .TP
 .B schemacheck { on | off }
 Turn schema checking on or off. The default is on.
@@ -284,6 +285,12 @@ It specifies the DN allowed to make changes to the replica (typically,
 this is the DN
 .BR slurpd (8)
 binds as when making changes to the replica).
+.TP
+.B updateref <url>
+Specify the referral to pass back when
+.BR slapd (8)
+is asked to modify a replicated local database.
+If specified multiple times, each url is provided.
 .SH LDBM BACKEND-SPECIFIC OPTIONS
 Options in this category only apply to the LDBM backend database. That is,
 they must follow a "database ldbm" line and come before any subsequent
index 1cadf3ba38b5873aba1764bb85033b525e400a7d..397e63db5d6b0ae31193934827d8907503d3bf68 100644 (file)
@@ -167,6 +167,8 @@ typedef struct ldapcontrol {
 #define LDAP_CHASE_SUBORDINATE_REFERRALS       0x0020
 #define LDAP_CHASE_EXTERNAL_REFERRALS  0x0040
 
+#define LDAP_CONTROL_MANAGEDSAIT "2.16.16.840.1.113730.3.4.2"
+
 /* LDAP Unsolicited Notifications */
 #define        LDAP_NOTICE_DISCONNECT  "1.3.6.1.4.1.1466.20036"
 
index ec1fd56843d204732775494b87d307625e1e6fd9..60e83203495f68055406922c4634eb363361c257 100644 (file)
@@ -90,7 +90,7 @@ BSC32=bscmake.exe
 # ADD BSC32 /nologo
 LIB32=link.exe -lib
 # ADD BASE LIB32 /nologo /out:"..\Debug\oldbm32.lib"
-# ADD LIB32 /nologo /out:"..\Debug\oldbm32.lib"
+# ADD LIB32 /nologo /out:"..\SDebug\oldbm32.lib"
 
 !ELSEIF  "$(CFG)" == "libldbm - Win32 Single Release"
 
@@ -111,7 +111,7 @@ BSC32=bscmake.exe
 # ADD BSC32 /nologo
 LIB32=link.exe -lib
 # ADD BASE LIB32 /nologo /out:"..\Release\oldbm32.lib"
-# ADD LIB32 /nologo /out:"..\Release\oldbm32.lib"
+# ADD LIB32 /nologo /out:"..\SRelease\oldbm32.lib"
 
 !ENDIF 
 
index c3bd8a51c0c4780aa456f68cb325a9e005d827bb..2e0aa857827306750759eb289e4c7aeba7dc48e7 100644 (file)
@@ -10,7 +10,7 @@ SRCS  = main.c daemon.c connection.c search.c filter.c add.c charray.c \
                value.c ava.c bind.c unbind.c abandon.c filterentry.c \
                phonetic.c acl.c str2filter.c aclparse.c init.c user.c \
                repl.c lock.c controls.c extended.c \
-               suffixalias.c schema.c schemaparse.c monitor.c configinfo.c \
+               schema.c schemaparse.c monitor.c configinfo.c \
                root_dse.c module.c
 OBJS   = main.o daemon.o connection.o search.o filter.o add.o charray.o \
                attr.o entry.o config.o backend.o result.o operation.o \
@@ -18,7 +18,7 @@ OBJS  = main.o daemon.o connection.o search.o filter.o add.o charray.o \
                value.o ava.o bind.o unbind.o abandon.o filterentry.o \
                phonetic.o acl.o str2filter.o aclparse.o init.o user.o \
                repl.o lock.o controls.o extended.o \
-               suffixalias.o schema.o schemaparse.o monitor.o configinfo.o \
+               schema.o schemaparse.o monitor.o configinfo.o \
                root_dse.o module.o
 
 LDAP_INCDIR= ../../include
index bac282e2b3c576f90f4864b3e5edf624cd9ab58a..3069ed7452d25de19f04a6aa593c999a3d86afff 100644 (file)
@@ -28,7 +28,7 @@ do_abandon(
        ber_int_t               id;
        Operation       *o;
        Operation       **oo;
-       int rc;
+       int rc, notfound;
 
        Debug( LDAP_DEBUG_TRACE, "do_abandon\n", 0, 0, 0 );
 
@@ -52,21 +52,28 @@ do_abandon(
 
        Debug( LDAP_DEBUG_ARGS, "do_abandon: id %d\n", id, 0 ,0 );
 
+       if( id <= 0 ) {
+               Debug( LDAP_DEBUG_ANY,
+                       "do_abandon: bad msgid %ld\n", (long) id, 0, 0 );
+               return LDAP_SUCCESS;
+       }
+
+       notfound = 1; /* not found */
+       ldap_pvt_thread_mutex_lock( &conn->c_mutex );
        /*
         * find the operation being abandoned and set the o_abandon
         * flag.  It's up to the backend to periodically check this
         * flag and abort the operation at a convenient time.
         */
 
-       ldap_pvt_thread_mutex_lock( &conn->c_mutex );
-
        for ( o = conn->c_ops; o != NULL; o = o->o_next ) {
                if ( o->o_msgid == id ) {
                        ldap_pvt_thread_mutex_lock( &o->o_abandonmutex );
                        o->o_abandon = 1;
                        ldap_pvt_thread_mutex_unlock( &o->o_abandonmutex );
 
-                       goto found_it;
+                       notfound = 0;
+                       goto done;
                }
        }
 
@@ -81,13 +88,14 @@ do_abandon(
                o = *oo;
                *oo = (*oo)->o_next;
                slap_op_free( o );
-
-               goto found_it;
+               notfound = 0;
        }
 
-       Debug( LDAP_DEBUG_TRACE, "do_abandon: op not found\n", 0, 0, 0 );
-
-found_it:
+done:
        ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
+
+       Debug( LDAP_DEBUG_TRACE, "do_abandon: op=%ld %sfound\n",
+               id, notfound ? "not " : "", 0 );
+
        return LDAP_SUCCESS;
 }
index e32e5ee67564449905e6c4050b1065be532e433f..3c69482fce31c16db8b448f813eea942b9d04d2f 100644 (file)
@@ -330,6 +330,7 @@ access2str( int access )
                strcat( buf, "read" );
        } else if ( ACL_IS_WRITE(access) ) {
                strcat( buf, "write" );
+
        } else {
                strcat( buf, "unknown" );
        }
index e2438a5d3ba713d160efe1fdb53155a5f5e1d1e6..cfff625602d4a1bae1e6c9ced059ffcb7eb45807 100644 (file)
@@ -38,7 +38,7 @@ do_add( Connection *conn, Operation *op )
        if( op->o_bind_in_progress ) {
                Debug( LDAP_DEBUG_ANY, "do_add: SASL bind in progress.\n", 0, 0, 0 );
                send_ldap_result( conn, op, LDAP_SASL_BIND_IN_PROGRESS, NULL,
-                   "SASL bind in progress" );
+                   "SASL bind in progress", NULL, NULL );
                return LDAP_SASL_BIND_IN_PROGRESS;
        }
 
@@ -89,8 +89,8 @@ do_add( Connection *conn, Operation *op )
                if ( vals == NULL ) {
                        Debug( LDAP_DEBUG_ANY, "no values for type %s\n", type,
                            0, 0 );
-                       send_ldap_result( conn, op,
-                               LDAP_PROTOCOL_ERROR, NULL, "no values for type" );
+                       send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR,
+                               NULL, "no values for type", NULL, NULL );
                        free( type );
                        entry_free( e );
                        return LDAP_PROTOCOL_ERROR;
@@ -127,8 +127,8 @@ do_add( Connection *conn, Operation *op )
        be = select_backend( e->e_ndn );
        if ( be == NULL ) {
                entry_free( e );
-               send_ldap_result( conn, op, LDAP_PARTIAL_RESULTS, NULL,
-                   default_referral );
+               send_ldap_result( conn, op, LDAP_REFERRAL, NULL,
+                   NULL, default_referral, NULL );
                return rc;
        }
 
@@ -155,14 +155,14 @@ do_add( Connection *conn, Operation *op )
 
                } else {
                        entry_free( e );
-                       send_ldap_result( conn, op, rc = LDAP_PARTIAL_RESULTS, NULL,
-                           default_referral );
+                       send_ldap_result( conn, op, rc = LDAP_REFERRAL, NULL, NULL,
+                               be->be_update_refs ? be->be_update_refs : default_referral, NULL );
                }
        } else {
            Debug( LDAP_DEBUG_ARGS, "    do_add: HHH\n", 0, 0, 0 );
                entry_free( e );
-               send_ldap_result( conn, op, rc = LDAP_UNWILLING_TO_PERFORM, NULL,
-                   "Function not implemented" );
+               send_ldap_result( conn, op, rc = LDAP_UNWILLING_TO_PERFORM,
+                       NULL, "Function not implemented", NULL, NULL );
        }
 
        return rc;
index 1f51d43d52e6a80088cacab3800abbc2d7f5e3f6..5c72225f76e7b9d997fa59314ecd1297fcd25772 100644 (file)
@@ -32,7 +32,8 @@ bdb2i_back_add_internal(
 
        if ( ( bdb2i_dn2id( be, e->e_ndn ) ) != NOID ) {
                entry_free( e );
-               send_ldap_result( conn, op, LDAP_ALREADY_EXISTS, "", "" );
+               send_ldap_result( conn, op, LDAP_ALREADY_EXISTS,
+                       NULL, NULL, NULL, NULL );
                return( -1 );
        }
 
@@ -41,8 +42,8 @@ bdb2i_back_add_internal(
                        0, 0, 0 );
 
                entry_free( e );
-               send_ldap_result( conn, op, LDAP_OBJECT_CLASS_VIOLATION, "",
-                   "" );
+               send_ldap_result( conn, op, LDAP_OBJECT_CLASS_VIOLATION,
+                       NULL, NULL, NULL, NULL );
                return( -1 );
        }
 
@@ -55,19 +56,37 @@ bdb2i_back_add_internal(
        pdn = dn_parent( be, e->e_ndn );
 
        if( pdn != NULL && *pdn != '\0' && !be_issuffix(be, "") ) {
-               char *matched = NULL;
+               Entry *matched = NULL;
 
                assert( *pdn != '\0' );
 
                /* get parent with writer lock */
                if ( (p = bdb2i_dn2entry_w( be, pdn, &matched )) == NULL ) {
-                       Debug( LDAP_DEBUG_TRACE, "parent does not exist\n", 0,
-                           0, 0 );
+                       char *matched_dn;
+                       struct berval **refs;
+
+                       if( matched != NULL ) {
+                               matched_dn = ch_strdup( matched->e_dn );
+                               refs = is_entry_referral( matched )
+                                       ? get_entry_referrals( be, conn, op, matched )
+                                       : NULL;
+
+                               bdb2i_cache_return_entry_w( &li->li_cache, matched ); 
+
+                       } else {
+                               matched_dn = NULL;
+                               refs = default_referral;
+                       }
+
+                       Debug( LDAP_DEBUG_TRACE, "parent does not exist\n",
+                               0, 0, 0 );
+
                        send_ldap_result( conn, op, LDAP_NO_SUCH_OBJECT,
-                           matched, "" );
+                           matched_dn, NULL, NULL, NULL );
 
                        if ( matched != NULL ) {
-                               free( matched );
+                               ber_bvecfree( refs );
+                               free( matched_dn );
                        }
 
                        entry_free( e );
@@ -77,21 +96,54 @@ bdb2i_back_add_internal(
 
                free(pdn);
 
-               if ( matched != NULL ) {
-                       free( matched );
-               }
-
                if ( ! access_allowed( be, conn, op, p,
                        "children", NULL, ACL_WRITE ) )
                {
+                       /* free parent and writer lock */
+                       bdb2i_cache_return_entry_w( &li->li_cache, p ); 
+
                        Debug( LDAP_DEBUG_TRACE, "no access to parent\n", 0,
                            0, 0 );
                        send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
-                           "", "" );
+                           NULL, NULL, NULL, NULL );
+
+                       entry_free( e );
+                       return -1;
+               }
+
+
+               if ( is_entry_alias( p ) ) {
+                       /* parent is an alias, don't allow add */
+
+                       /* free parent and writer lock */
+                       bdb2i_cache_return_entry_w( &li->li_cache, p ); 
+
+                       Debug( LDAP_DEBUG_TRACE, "parent is alias\n", 0,
+                           0, 0 );
+                       send_ldap_result( conn, op, LDAP_ALIAS_PROBLEM,
+                           NULL, NULL, NULL, NULL );
+
+                       entry_free( e );
+                       return -1;
+               }
+
+               if ( is_entry_referral( p ) ) {
+                       /* parent is an referral, don't allow add */
+                       char *matched_dn = ch_strdup( matched->e_dn );
+                       struct berval **refs = is_entry_referral( matched )
+                                       ? get_entry_referrals( be, conn, op, matched )
+                                       : NULL;
 
                        /* free parent and writer lock */
                        bdb2i_cache_return_entry_w( &li->li_cache, p ); 
 
+                       Debug( LDAP_DEBUG_TRACE, "parent is referral\n", 0,
+                           0, 0 );
+                       send_ldap_result( conn, op, LDAP_REFERRAL,
+                           matched_dn, NULL, refs, NULL );
+
+                       ber_bvecfree( refs );
+                       free( matched_dn );
                        entry_free( e );
                        return -1;
                }
@@ -109,7 +161,7 @@ bdb2i_back_add_internal(
                                0, 0 );
 
                        send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
-                           "", "" );
+                           NULL, NULL, NULL, NULL );
 
                        entry_free( e );
                        return -1;
@@ -142,11 +194,9 @@ bdb2i_back_add_internal(
                /* free the entry */
                entry_free( e );
 
-               if(rc > 0) {
-                       send_ldap_result( conn, op, LDAP_ALREADY_EXISTS, "", "" );
-               } else {
-                       send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
-               }
+               send_ldap_result( conn, op,
+                       rc > 0 ? LDAP_ALREADY_EXISTS : LDAP_OPERATIONS_ERROR,
+                       NULL, NULL, NULL, NULL );
 
                return( -1 );
        }
@@ -162,7 +212,8 @@ bdb2i_back_add_internal(
        if ( bdb2i_id2children_add( be, p, e ) != 0 ) {
                Debug( LDAP_DEBUG_TRACE, "bdb2i_id2children_add failed\n", 0,
                    0, 0 );
-               send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
+               send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+                       NULL, NULL, NULL, NULL );
 
                bdb2i_stop_timing( be->bd_info, time1, "ADD-ID2CHILDREN", conn, op );
 
@@ -182,7 +233,8 @@ bdb2i_back_add_internal(
        if ( bdb2i_index_add_entry( be, e ) != 0 ) {
                Debug( LDAP_DEBUG_TRACE, "bdb2i_index_add_entry failed\n", 0,
                    0, 0 );
-               send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
+               send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+                       NULL, NULL, NULL, NULL );
 
                bdb2i_stop_timing( be->bd_info, time1, "ADD-INDEX", conn, op );
 
@@ -197,7 +249,8 @@ bdb2i_back_add_internal(
        if ( bdb2i_dn2id_add( be, e->e_ndn, e->e_id ) != 0 ) {
                Debug( LDAP_DEBUG_TRACE, "bdb2i_dn2id_add failed\n", 0,
                    0, 0 );
-               send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
+               send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+                       NULL, NULL, NULL, NULL );
 
                bdb2i_stop_timing( be->bd_info, time1, "ADD-DN2ID", conn, op );
 
@@ -213,7 +266,8 @@ bdb2i_back_add_internal(
                Debug( LDAP_DEBUG_TRACE, "bdb2i_id2entry_add failed\n", 0,
                    0, 0 );
                (void) bdb2i_dn2id_delete( be, e->e_ndn );
-               send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
+               send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+                       NULL, NULL, NULL, NULL );
 
                bdb2i_stop_timing( be->bd_info, time1, "ADD-ID2ENTRY", conn, op );
 
@@ -222,7 +276,8 @@ bdb2i_back_add_internal(
 
        bdb2i_stop_timing( be->bd_info, time1, "ADD-ID2ENTRY", conn, op );
 
-       send_ldap_result( conn, op, LDAP_SUCCESS, "", "" );
+       send_ldap_result( conn, op, LDAP_SUCCESS,
+                       NULL, NULL, NULL, NULL );
        rc = 0;
 
 return_results:;
@@ -255,10 +310,9 @@ bdb2_back_add(
        bdb2i_start_timing( be->bd_info, &time1 );
 
        if ( bdb2i_enter_backend_w( &lock ) != 0 ) {
-
-               send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
+               send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+                       NULL, NULL, NULL, NULL );
                return( -1 );
-
        }
 
        /*  check, if a new default attribute index will be created,
index beb1fb9dc6e7ca6fa3481e4921d9a25defd1b686..89834748fd2d53a8030ff4b3c8903467526acae0 100644 (file)
@@ -1,13 +1,6 @@
 /*
- * Copyright (c) 1998 Will Ballantyne, ITSD, Government of BC
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that this notice is preserved and that due credit is given
- * to ITSD, Government of BC. The name of ITSD
- * may not be used to endorse or promote products derived from this
- * software without specific prior written permission. This software
- * is provided ``as is'' without express or implied warranty.
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
  */
 
 #include "portable.h"
 #include "back-bdb2.h"
 #include "proto-back-bdb2.h"
 
-/*
- * given an alias object, dereference it to its end point.
- * Entry returned has reader lock or is NULL.  Starting entry is not released.
- */
-Entry *bdb2i_derefAlias_r ( BackendDB     *be,
-                   Connection  *conn,
-                   Operation   *op,
-                   Entry       *e)
+static char* get_alias_dn(
+       Entry *e,
+       int *err,
+       char **errmsg );
+
+static char* new_superior(
+       char *dn,
+       char *oldSup,
+       char *newSup );
+
+static int dnlist_subordinate(
+       char** dnlist,
+       char *dn );
+
+Entry *bdb2i_deref_r(
+       Backend*        be,
+       Entry*          alias,
+       char*           dn,
+       int*            err,
+       Entry**         matched,
+       char**          text )
 {
-  /* to free cache entries */
-  struct ldbminfo *li = (struct ldbminfo *) be->be_private;
-  Attribute *a;
-  int       depth;
-  char      *matched;
-  Entry     *origDN = e;
-
-  if (!e) return NULL;  /* be sure we have a starting entry */
-
-  Debug( LDAP_DEBUG_TRACE, "<= checking for alias for dn %s\n", e->e_dn, 0, 0 );
-
-  /*
-   * try to deref fully, up to a maximum depth.  If the max depth exceeded
-   * then send an error
-   */
-  for ( depth = 0;
-       ( ( a = attr_find( e->e_attrs, "aliasedobjectname" ) ) != NULL) &&
-         ( depth < be->be_maxDerefDepth );
-       ++depth) 
-  {
-
-    /* 
-     * make sure there is a defined aliasedobjectname.  
-     * can only have one value so just use first value (0) in the attr list. 
-     */            
-    if (a->a_vals[0] && a->a_vals[0]->bv_val) {
-      char *newDN, *oldDN;
-
-      Debug( LDAP_DEBUG_TRACE, "<= %s is an alias for %s\n", 
-            e->e_dn, a->a_vals[0]->bv_val, 0 );
-      newDN = ch_strdup (a->a_vals[0]->bv_val);
-      oldDN = ch_strdup (e->e_ndn);
-
-      /* 
-       * release past lock if not original
-       */
-      if ( (depth > 0) && e ) {
-          bdb2i_cache_return_entry_r(&li->li_cache, e);        
-      }
-
-      /* make sure new and old DN are not same to avoid loops */
-      dn_normalize_case (newDN);
-      if ( strcmp (newDN, oldDN) == 0 ) {
-       
-               Debug( LDAP_DEBUG_TRACE, 
-               "<= %s alias is same as current %s\n", 
-               oldDN, newDN, 0 );
-               send_ldap_result( conn, op, LDAP_ALIAS_DEREF_PROBLEM, "",
-                               "Circular alias" );
-               free (newDN);
-               free (oldDN);
-               break;
-      }
-
-      /* make sure new and original are not same to avoid deadlocks */
-      if ( strcmp (newDN, origDN->e_ndn) == 0 ) {
-               Debug( LDAP_DEBUG_TRACE, 
-               "<= %s alias is same as original %s\n", 
-               oldDN, origDN->e_ndn, 0 );
-               send_ldap_result( conn, op, LDAP_ALIAS_DEREF_PROBLEM, "",
-                               "Circular alias" );
-               free (newDN);
-               free (oldDN);
-               break;
-      }
-
-      /*
-       * ok, so what happens if there is an alias in the DN of a dereferenced
-       * alias object?  
-       */
-      if ( (e = bdb2i_dn2entry_r( be, newDN, &matched )) == NULL ) {
-
-               /* could not deref return error  */
-               Debug( LDAP_DEBUG_TRACE, 
-               "<= %s is a dangling alias to %s\n", 
-               oldDN, newDN, 0 );
-               send_ldap_result( conn, op, LDAP_ALIAS_DEREF_PROBLEM, "",
-                               "Dangling Alias" );
-
-                       if(matched != NULL) free(matched);
-       free (newDN);
-       free (oldDN);
-               break;
-      }
-
-      free (newDN);
-      free (oldDN);
-    }
-    else {
-      /*
-       * there was an aliasedobjectname defined but no data.
-       * this can't happen, right?
-       */
-               Debug( LDAP_DEBUG_TRACE, 
-               "<= %s has no data in aliasedobjectname attribute\n", 
-               (e && e->e_dn) ? e->e_dn : "(null)", 0, 0 );
-               send_ldap_result( conn, op, LDAP_ALIAS_PROBLEM, "",
-                               "Alias missing aliasedobjectname" );
-               break;
-    }
-  }
-
-  /*
-   * warn if we pulled out due to exceeding the maximum deref depth
-   */
-  if ( depth >= be->be_maxDerefDepth ) {
-    Debug( LDAP_DEBUG_TRACE, 
-          "<= deref(\"%s\") exceeded maximum deref depth (%d) at \"%s\"\n", 
-          origDN->e_dn ? origDN->e_dn : "(null)",
-               be->be_maxDerefDepth,
-               (e && e->e_ndn) ? e->e_ndn : "(null)");
-    send_ldap_result( conn, op, LDAP_ALIAS_DEREF_PROBLEM, "",
-                       "Maximum alias dereference depth exceeded" );
-  }
-
-  return e;
+       struct ldbminfo *li = (struct ldbminfo *) be->be_private;
+       Entry *entry;
+       Entry *sup;
+       unsigned depth;
+       char **dnlist;
+
+       assert( ( alias != NULL && dn == NULL ) || ( alias == NULL && dn != NULL ) );
+
+       *matched = NULL;
+       *err = LDAP_SUCCESS;
+       *text = NULL;
+
+       if( alias == NULL ) {
+               dn = ch_strdup( dn );
+               entry = bdb2i_dn2entry_r( be, dn, &sup );
+
+       } else {
+               dn = ch_strdup( alias->e_ndn );
+               entry = alias;
+               sup = NULL;
+       }
+
+       dnlist = NULL;
+       charray_add( &dnlist, dn );
+
+       for( depth=0 ; ; depth++ ) {
+               if( entry != NULL ) {
+                       Entry *newe;
+                       char *aliasDN;
+
+                       /* have entry, may be an alias */
+
+                       if( !is_entry_alias( entry ) ) {
+                               /* entry is not an alias */
+                               break;
+                       }
+
+                       /* entry is alias */
+                       if( depth > be->be_max_deref_depth ) {
+                               *matched = entry;
+                               entry = NULL;
+                               *err = LDAP_ALIAS_DEREF_PROBLEM;
+                               *text = "maximum deref depth exceeded";
+                               break;
+                       }
+
+                       /* deref entry */
+                       aliasDN = get_alias_dn( entry, err, text );
+
+                       if( aliasDN == NULL ) {
+                               *matched = entry;
+                               entry = NULL;
+                               break;
+                       }
+
+                       /* check if aliasDN is a subordinate of any DN in our list */
+                       if( dnlist_subordinate( dnlist, aliasDN ) ) {
+                               *matched = entry;
+                               entry = NULL;
+                               *err = LDAP_ALIAS_PROBLEM;
+                               *text = "circular alias";
+                               break;
+                       }
+
+                       /* attempt to dereference alias */
+
+                       newe = bdb2i_dn2entry_r( be, aliasDN, &sup );
+
+                       if( newe != NULL ) {
+                               free( dn );
+                               bdb2i_cache_return_entry_r(&li->li_cache, entry );
+                               entry = newe;
+                               dn = ch_strdup( entry->e_ndn );
+                               charray_add( &dnlist, dn );
+                               continue;
+
+                       }
+                       
+                       if ( sup != NULL ) {
+                               bdb2i_cache_return_entry_r(&li->li_cache, entry );
+                               entry = NULL;
+                               continue;
+                       }
+
+                       /* no newe and no superior, we're done */
+                       break;
+
+               } else if( sup != NULL ) {
+                       /* have superior, may be an alias */
+                       Entry *newe;
+                       Entry *newSup;
+                       char *supDN;
+                       char *aliasDN;
+
+                       if( !is_entry_alias( sup ) ) {
+                               /* entry is not an alias */
+                               *matched = sup;
+                               sup = NULL;
+                               break;
+                       }
+
+                       /* entry is alias */
+                       if( depth > be->be_max_deref_depth ) {
+                               *matched = sup;
+                               entry = NULL;
+                               *err = LDAP_ALIAS_DEREF_PROBLEM;
+                               *text = "maximum deref depth exceeded";
+                               break;
+                       }
+
+                       /* deref entry */
+                       supDN = get_alias_dn( sup, err, text );
+
+                       if( supDN == NULL ) {
+                               *matched = sup;
+                               break;
+                       }
+
+                       aliasDN = new_superior( dn, sup->e_ndn, supDN );
+
+                       if( aliasDN == NULL ) {
+                               free(aliasDN);
+                               *matched = sup;
+                               *err = LDAP_ALIAS_PROBLEM;
+                               *text = "superior alias problem";
+                               break;
+                       }
+
+                       /* check if aliasDN is a subordinate of any DN in our list */
+                       if( dnlist_subordinate( dnlist, aliasDN ) ) {
+                               free(aliasDN);
+                               *matched = entry;
+                               entry = NULL;
+                               *err = LDAP_ALIAS_PROBLEM;
+                               *text = "subordinate circular alias";
+                               break;
+                       }
+
+                       /* attempt to dereference alias */
+                       newe = bdb2i_dn2entry_r( be, aliasDN, &newSup );
+
+                       if( newe != NULL ) {
+                               free(aliasDN);
+                               free( dn );
+                               bdb2i_cache_return_entry_r(&li->li_cache, sup );
+                               entry = newe;
+                               dn = ch_strdup( entry->e_ndn );
+                               charray_add( &dnlist, dn );
+                               continue;
+
+                       }
+                       
+                       if ( newSup != NULL ) {
+                               free( dn );
+                               bdb2i_cache_return_entry_r(&li->li_cache, sup );
+                               sup = newSup;
+                               dn = aliasDN;
+                               continue;
+                       }
+
+                       break;
+
+               } else {
+                       /* no newe and no superior, we're done */
+                       break;
+               }
+       }
+
+       free( dn );
+       return entry;
 }
 
-/*
- * given a DN fully deref it and return the real DN or original DN if it fails
- * This involves finding the last matched part then reconstructing forward
- * e.g. 
- * ou=MyOU,o=MyAliasedOrg,c=MyCountry where o=MyAliasedOrg is an alias for o=MyOrg
- * loop starts with newDN = ou=MyOU,o=MyAliasedOrg,c=MyCountry
- *   dn2entry_r on newDN gives null entry and o=MyAliasedOrg,c=MyCountry matched
- *   dn2entry_r on matched gives o=MyAliasedOrg,c=MyCountry entry
- *   remainder is ou=MyOU
- *   dereferencing o=MyAliasedOrg,c=MyCountry yields entry o=MyOrg,c=MyCountry
- *   release lock on o=MyAliasedOrg,c=MyCountry entry
- *   reconstructed dn is ou=MyOU,o=MyOrg,c=MyCountry
- *   release lock on o=MyOrg,c=MyCountry entry
- */
-char *bdb2i_derefDN ( BackendDB     *be,
-                Connection  *conn,
-                Operation   *op,
-                char        *dn
-)
-{
-  struct ldbminfo *li = (struct ldbminfo *) be->be_private;
-  char         *matched = 0;
-  char         *newDN = NULL;
-  int  depth, i;
-  Entry        *eMatched;
-  Entry        *eDeref;
-  Entry         *eNew;
-  
-  if (!dn) return NULL;
-
-  Debug( LDAP_DEBUG_TRACE, 
-        "<= dereferencing dn: \"%s\"\n", 
-        dn, 0, 0 );
-  
-  newDN = ch_strdup ( dn );
-
-  /* while we don't have a matched dn, deref the DN */
-  for ( depth = 0;
-       ( (eMatched = bdb2i_dn2entry_r( be, newDN, &matched )) == NULL) &&
-         (depth < be->be_maxDerefDepth);
-       ++depth ) {
-    
-    if ((matched != NULL) && *matched) {       
-      char *submatch;
-      
-      /* 
-       * make sure there actually is an entry for the matched part 
-       */
-      if ( (eMatched = bdb2i_dn2entry_r( be, matched, &submatch )) != NULL) {
-       char  *remainder; /* part before the aliased part */
-       int  rlen = strlen(newDN) - strlen(matched);
-       
-       Debug( LDAP_DEBUG_TRACE, "<= matched %s\n", matched, 0, 0 );
-       
-       remainder = ch_malloc (rlen + 1);
-       strncpy ( remainder, newDN, rlen );
-       remainder[rlen] = '\0';
-       
-       Debug( LDAP_DEBUG_TRACE, "<= remainder %s\n", remainder, 0, 0 );
-       
-       if ((eNew = bdb2i_derefAlias_r( be, conn, op, eMatched )) == NULL) {
-         free (matched);
-         matched = NULL;
-         free (newDN);
-         newDN = NULL;
-         free (remainder);
-         remainder = NULL;
-
-               bdb2i_cache_return_entry_r(&li->li_cache, eMatched);
-               eMatched = NULL;
-         break; /*  no associated entry, dont deref */
+
+static char* get_alias_dn(
+       Entry *e,
+       int *err,
+       char **errmsg )
+{      
+       Attribute *a = attr_find( e->e_attrs, "aliasedobjectname" );
+
+       if( a == NULL ) {
+               /*
+                * there was an aliasedobjectname defined but no data.
+                */
+               *err = LDAP_ALIAS_PROBLEM;
+               *errmsg = "alias missing aliasedObjectName attribute";
+               return NULL;
        }
-       else {
-
-         Debug( LDAP_DEBUG_TRACE, "<= l&g we have %s vs %s \n", matched, eNew->e_dn, 0 );
-
-         i = strcasecmp (matched, eNew->e_dn);
-          /* free reader lock */
-          bdb2i_cache_return_entry_r(&li->li_cache, eNew);
-
-               free (matched);
-               matched = NULL;
-
-         if (! i) {
-           /* newDN same as old so not an alias, no need to go further */
-           free (newDN);
-           newDN = NULL;
-           free (remainder);
-
-               bdb2i_cache_return_entry_r(&li->li_cache, eMatched);
-               eMatched = NULL;
-           break;
-         }
-
-         /* 
-          * we have dereferenced the aliased part so put
-          * the new dn together
-          */
-         free (newDN);
-         newDN = ch_malloc (strlen(eMatched->e_dn) + rlen + 1);
-         strcpy (newDN, remainder);
-         strcat (newDN, eMatched->e_dn);
-         Debug( LDAP_DEBUG_TRACE, "<= expanded to %s\n", newDN, 0, 0 );
-
-         free (remainder);
+
+       /* 
+        * aliasedObjectName should be SINGLE-VALUED with a single value. 
+        */                     
+       if ( a->a_vals[0] == NULL || a->a_vals[0]->bv_val != NULL ) {
+               /*
+                * there was an aliasedobjectname defined but no data.
+                */
+               *err = LDAP_ALIAS_PROBLEM;
+               *errmsg = "alias missing aliasedObjectName value";
+               return NULL;
        }
-        /* free reader lock */
-        bdb2i_cache_return_entry_r(&li->li_cache, eMatched);
-      }
-      else {
-       if(submatch != NULL) free(submatch);
-       break; /* there was no entry for the matched part */
-      }
-    }
-    else {
-      break; /* there was no matched part */
-    }
-  }
-  
-       /* release lock if a match terminated the loop, there should be no
-        * outstanding locks at this point
-        */
-  if(eMatched != NULL) {
-    /* free reader lock */
-    bdb2i_cache_return_entry_r(&li->li_cache, eMatched);
-  }
-
-  /*
-   * the final part of the DN might be an alias so try to dereference it.
-   * e.g. if we had started with dn = o=MyAliasedOrg,c=MyCountry the dn would match
-   * and the above loop complete but we would still be left with an aliased DN.
-   */
-  if (newDN != NULL) {
-    if ( (eNew = bdb2i_dn2entry_r( be, newDN, &matched )) != NULL) {
-      if ((eDeref = bdb2i_derefAlias_r( be, conn, op, eNew )) != NULL) {
-        free (newDN);
-        newDN = ch_strdup (eDeref->e_dn);
-        /* free reader lock */
-        bdb2i_cache_return_entry_r(&li->li_cache, eDeref);
-      }
-      /* free reader lock */
-      bdb2i_cache_return_entry_r(&li->li_cache, eNew);
-    }
-  }
-       if (matched != NULL) free(matched);
-  
-  /*
-   * warn if we exceeded the max depth as the resulting DN may not be dereferenced
-   */
-  if (depth >= be->be_maxDerefDepth) {
-       if (newDN) {
-       Debug( LDAP_DEBUG_TRACE, 
-               "<= max deref depth exceeded in derefDN for \"%s\", result \"%s\"\n", 
-               dn, newDN, 0 );
-               free (newDN);
-               newDN = NULL;
-       } else {
-               Debug( LDAP_DEBUG_TRACE,
-                       "<= max deref depth exceeded in derefDN for \"%s\", result NULL\n",
-                       dn, 0, 0 );
+
+       if( a->a_vals[1] != NULL ) {
+               *err = LDAP_ALIAS_PROBLEM;
+               *errmsg = "alias has multivalued aliasedObjectName";
+               return NULL;
        }
-    send_ldap_result( conn, op, LDAP_ALIAS_DEREF_PROBLEM, "",
-                     "Maximum alias dereference depth exceeded for base" );
-  }
 
-  if (newDN == NULL) {
-    newDN = ch_strdup ( dn );
-  }
-  
-  Debug( LDAP_DEBUG_TRACE, "<= returning deref DN of \"%s\"\n", newDN, 0, 0 ); 
+       return a->a_vals[0]->bv_val;
+}
+
+static char* new_superior(
+       char *dn,
+       char *oldSup,
+       char *newSup )
+{
+       char *newDN;
+       size_t dnlen, olen, nlen;
+       assert( dn && oldSup && newSup );
+
+       dnlen = strlen( dn );
+       olen = strlen( oldSup );
+       nlen = strlen( newSup );
+
+       newDN = ch_malloc( dnlen - olen + nlen + 1 );
+
+       memcpy( newDN, dn, dnlen - olen );
+       memcpy( &newDN[dnlen - olen], newSup, nlen );
+       newDN[dnlen - olen + nlen] = '\0';
 
-  return newDN;
+       return newDN;
 }
+
+static int dnlist_subordinate(
+       char** dnlist,
+       char *dn )
+{
+       int i;
+       assert( dnlist );
+
+       for( i = 0; dnlist[i] != NULL; i++ ) {
+               if( dn_issuffix( dnlist[i], dn ) ) {
+                       return 1;
+               }
+       }
+
+       return 0;
+}
+
index db0cf7bf62ff2f5cdba07868f6f1da414397a5f8..5f2ae0d9a268afcfe1b4347a8d2e303454381de0 100644 (file)
@@ -74,7 +74,7 @@ bdb2i_back_bind_internal(
        Entry           *e;
        Attribute       *a;
        int             rc;
-       char            *matched;
+       Entry           *matched;
 #ifdef HAVE_KERBEROS
        char            krbname[MAX_K_NAME_SZ + 1];
        AUTH_DAT        ad;
@@ -86,12 +86,26 @@ bdb2i_back_bind_internal(
 
        /* get entry with reader lock */
        if ( (e = bdb2i_dn2entry_r( be, dn, &matched )) == NULL ) {
+               char *matched_dn = NULL;
+               struct berval **refs = NULL;
+
+               if ( matched != NULL ) {
+                       matched_dn = ch_strdup( matched->e_dn );
+                       refs = is_entry_referral( matched )
+                               ? get_entry_referrals( be, conn, op, matched )
+                               : NULL;
+                       bdb2i_cache_return_entry_r( &li->li_cache, matched );
+               } else {
+                       refs = default_referral;
+               }
+
                /* allow noauth binds */
                rc = 1;
                if ( method == LDAP_AUTH_SIMPLE ) {
                        if( cred->bv_len == 0 ) {
                                /* SUCCESS */
-                               send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL );
+                               send_ldap_result( conn, op, LDAP_SUCCESS,
+                                       NULL, NULL, NULL, NULL );
 
                        } else if ( be_isroot_pw( be, dn, cred ) ) {
                                /* front end will send result */
@@ -99,27 +113,30 @@ bdb2i_back_bind_internal(
                                rc = 0;
 
                        } else {
-                               send_ldap_result( conn, op,
-                                       LDAP_NO_SUCH_OBJECT, matched, NULL );
+                               send_ldap_result( conn, op, LDAP_REFERRAL,
+                                       matched_dn, NULL, refs, NULL );
                        }
 
                } else if ( method == LDAP_AUTH_SASL ) {
                        if( mech != NULL && strcasecmp(mech,"DIGEST-MD5") == 0 ) {
                                /* insert DIGEST calls here */
-                               send_ldap_result( conn, op,
-                                       LDAP_AUTH_METHOD_NOT_SUPPORTED, NULL, NULL );
+                               send_ldap_result( conn, op, LDAP_AUTH_METHOD_NOT_SUPPORTED,
+                                       NULL, NULL, NULL, NULL );
 
                        } else {
-                               send_ldap_result( conn, op,
-                                       LDAP_AUTH_METHOD_NOT_SUPPORTED, NULL, NULL );
+                               send_ldap_result( conn, op, LDAP_AUTH_METHOD_NOT_SUPPORTED,
+                                       NULL, NULL, NULL, NULL );
                        }
 
                } else {
-                       send_ldap_result( conn, op, LDAP_NO_SUCH_OBJECT, matched, NULL );
+                       send_ldap_result( conn, op, LDAP_REFERRAL,
+                               matched_dn, NULL, refs, NULL );
                        rc = 1;
                }
+
                if ( matched != NULL ) {
-                       free( matched );
+                       ber_bvecfree( refs );
+                       free( matched_dn );
                }
                return( rc );
        }
@@ -131,7 +148,38 @@ bdb2i_back_bind_internal(
        if ( ! access_allowed( be, conn, op, e,
                "entry", NULL, ACL_AUTH ) )
        {
-               send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS, "", "" );
+               send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
+                       NULL, NULL, NULL, NULL );
+               rc = 1;
+               goto return_results;
+       }
+
+       if ( is_entry_alias( e ) ) {
+               /* entry is a alias, don't allow bind */
+               Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0,
+                       0, 0 );
+
+               send_ldap_result( conn, op, LDAP_ALIAS_PROBLEM,
+                       NULL, NULL, NULL, NULL );
+
+               rc = 1;
+               goto return_results;
+       }
+
+
+       if ( is_entry_referral( e ) ) {
+               /* entry is a referral, don't allow bind */
+               struct berval **refs = get_entry_referrals( be,
+                       conn, op, e );
+
+               Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0,
+                       0, 0 );
+
+               send_ldap_result( conn, op, LDAP_REFERRAL,
+                       e->e_dn, NULL, refs, NULL );
+
+               ber_bvecfree( refs );
+
                rc = 1;
                goto return_results;
        }
@@ -139,7 +187,8 @@ bdb2i_back_bind_internal(
        switch ( method ) {
        case LDAP_AUTH_SIMPLE:
                if ( cred->bv_len == 0 ) {
-                       send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL );
+                       send_ldap_result( conn, op, LDAP_SUCCESS,
+                               NULL, NULL, NULL, NULL );
 
                        /* stop front end from sending result */
                        rc = 1;
@@ -158,14 +207,15 @@ bdb2i_back_bind_internal(
                if ( ! access_allowed( be, conn, op, e,
                        "userpassword", NULL, ACL_AUTH ) )
                {
-                       send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS, "", "" );
+                       send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
+                               NULL, NULL, NULL, NULL);
                        rc = 1;
                        goto return_results;
                }
 
                if ( (a = attr_find( e->e_attrs, "userpassword" )) == NULL ) {
                        send_ldap_result( conn, op, LDAP_INAPPROPRIATE_AUTH,
-                           NULL, NULL );
+                               NULL, NULL, NULL, NULL);
 
                        /* stop front end from sending result */
                        rc = 1;
@@ -175,7 +225,7 @@ bdb2i_back_bind_internal(
                if ( crypted_value_find( a->a_vals, cred, a->a_syntax, 0, cred ) != 0 )
                {
                        send_ldap_result( conn, op, LDAP_INVALID_CREDENTIALS,
-                               NULL, NULL );
+                               NULL, NULL, NULL, NULL);
                        /* stop front end from sending result */
                        rc = 1;
                        goto return_results;
@@ -187,7 +237,7 @@ bdb2i_back_bind_internal(
        case LDAP_AUTH_KRBV41:
                if ( bdb2i_krbv4_ldap_auth( be, cred, &ad ) != LDAP_SUCCESS ) {
                        send_ldap_result( conn, op, LDAP_INVALID_CREDENTIALS,
-                           NULL, NULL );
+                               NULL, NULL, NULL, NULL);
                        rc = 1;
                        goto return_results;
                }
@@ -195,7 +245,8 @@ bdb2i_back_bind_internal(
                if ( ! access_allowed( be, conn, op, e,
                        "krbname", NULL, ACL_AUTH ) )
                {
-                       send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS, "", "" );
+                       send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
+                               NULL, NULL, NULL, NULL);
                        rc = 1;
                        goto return_results;
                }
@@ -212,7 +263,7 @@ bdb2i_back_bind_internal(
                                break;
                        }
                        send_ldap_result( conn, op, LDAP_INAPPROPRIATE_AUTH,
-                           NULL, NULL );
+                               NULL, NULL, NULL, NULL);
                        rc = 1;
                        goto return_results;
                } else {        /* look for krbName match */
@@ -222,8 +273,8 @@ bdb2i_back_bind_internal(
                        krbval.bv_len = strlen( krbname );
 
                        if ( value_find( a->a_vals, &krbval, a->a_syntax, 3 ) != 0 ) {
-                               send_ldap_result( conn, op,
-                                   LDAP_INVALID_CREDENTIALS, NULL, NULL );
+                               send_ldap_result( conn, op, LDAP_INVALID_CREDENTIALS,
+                                       NULL, NULL, NULL, NULL);
                                rc = 1;
                                goto return_results;
                        }
@@ -232,7 +283,8 @@ bdb2i_back_bind_internal(
                break;
 
        case LDAP_AUTH_KRBV42:
-               send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL );
+               send_ldap_result( conn, op, LDAP_SUCCESS,
+                       NULL, NULL, NULL, NULL );
                /* stop front end from sending result */
                rc = 1;
                goto return_results;
@@ -243,7 +295,7 @@ bdb2i_back_bind_internal(
 
        default:
                send_ldap_result( conn, op, LDAP_STRONG_AUTH_NOT_SUPPORTED,
-                   NULL, "auth method not supported" );
+                   NULL, "auth method not supported", NULL, NULL );
                rc = 1;
                goto return_results;
        }
@@ -277,10 +329,9 @@ bdb2_back_bind(
        bdb2i_start_timing( be->bd_info, &time1 );
 
        if ( bdb2i_enter_backend_r( &lock ) != 0 ) {
-
-               send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
+               send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+                       NULL, NULL, NULL, NULL );
                return( 1 );
-
        }
 
        ret = bdb2i_back_bind_internal( be, conn, op, dn, method, mech, cred, edn );
index 2c07093416cfe03ac1afc0801cdd857a43e1548d..f2fa1dd164f82db2250f9aa8976a5d66ecadae92 100644 (file)
@@ -21,38 +21,77 @@ bdb2i_back_compare_internal(
 )
 {
        struct ldbminfo *li = (struct ldbminfo *) be->be_private;
-       char            *matched;
+       Entry           *matched;
        Entry           *e;
        Attribute       *a;
        int             rc;
+       int             manageDSAit = get_manageDSAit( op );
 
        /* get entry with reader lock */
        if ( (e = bdb2i_dn2entry_r( be, dn, &matched )) == NULL ) {
-               send_ldap_result( conn, op, LDAP_NO_SUCH_OBJECT, matched, "" );
+               char *matched_dn = NULL;
+               struct berval **refs = NULL;
+
+               if ( matched != NULL ) {
+                       matched_dn = ch_strdup( matched->e_dn );
+                       refs = is_entry_referral( matched )
+                               ? get_entry_referrals( be, conn, op, matched )
+                               : NULL;
+                       bdb2i_cache_return_entry_r( &li->li_cache, matched );
+               } else {
+                       refs = default_referral;
+               }
+
+               send_ldap_result( conn, op, LDAP_REFERRAL,
+                       matched_dn, NULL, refs, NULL );
+
+               if( matched != NULL ) {
+                       ber_bvecfree( refs );
+                       free( matched_dn );
+               }
 
-               if(matched == NULL) free(matched);
                return( 1 );
        }
 
-       /* check for deleted */
+       if (!manageDSAit && is_entry_referral( e ) ) {
+               /* entry is a referral, don't allow add */
+               struct berval **refs = get_entry_referrals( be,
+                       conn, op, e );
+
+               Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0,
+                       0, 0 );
+
+               send_ldap_result( conn, op, LDAP_REFERRAL,
+                       e->e_dn, NULL, refs, NULL );
+
+               ber_bvecfree( refs );
+
+               rc = 1;
+               goto return_results;
+       }
+
        if ( ! access_allowed( be, conn, op, e,
                ava->ava_type, &ava->ava_value, ACL_COMPARE ) )
        {
-               send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS, "", "" );
+               send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
+                       NULL, NULL, NULL, NULL );
                rc = 1;
                goto return_results;
        }
 
        if ( (a = attr_find( e->e_attrs, ava->ava_type )) == NULL ) {
-               send_ldap_result( conn, op, LDAP_NO_SUCH_ATTRIBUTE, "", "" );
+               send_ldap_result( conn, op, LDAP_NO_SUCH_ATTRIBUTE,
+                       NULL, NULL, NULL, NULL );
                rc = 1;
                goto return_results;
        }
 
        if ( value_find( a->a_vals, &ava->ava_value, a->a_syntax, 1 ) == 0 ) 
-               send_ldap_result( conn, op, LDAP_COMPARE_TRUE, "", "" );
+               send_ldap_result( conn, op, LDAP_COMPARE_TRUE,
+                       NULL, NULL, NULL, NULL );
        else
-               send_ldap_result( conn, op, LDAP_COMPARE_FALSE, "", "" );
+               send_ldap_result( conn, op, LDAP_COMPARE_FALSE,
+                       NULL, NULL, NULL, NULL );
 
        rc = 0;
 
@@ -80,7 +119,8 @@ bdb2_back_compare(
 
        if ( bdb2i_enter_backend_r( &lock ) != 0 ) {
 
-               send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
+               send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+                       NULL, NULL, NULL, NULL );
                return( 1 );
 
        }
index b00c155ec309615d66af41bc552d6bb872de94fb..ca36c2bacff0501616aa555c0be664263ef8c533 100644 (file)
@@ -20,31 +20,63 @@ bdb2i_back_delete_internal(
 )
 {
        struct ldbminfo *li = (struct ldbminfo *) be->be_private;
-       char    *matched = NULL;
+       Entry   *matched = NULL;
        char    *pdn = NULL;
        Entry   *e, *p = NULL;
-       int     rc = -1;
+       int     rc = -1, manageDSAit;
 
        Debug(LDAP_DEBUG_ARGS, "==> bdb2i_back_delete: %s\n", dn, 0, 0);
 
        /* get entry with writer lock */
        if ( (e = bdb2i_dn2entry_w( be, dn, &matched )) == NULL ) {
+               char *matched_dn = NULL;
+               struct berval **refs = NULL;
+
                Debug(LDAP_DEBUG_ARGS, "<=- bdb2i_back_delete: no such object %s\n",
                        dn, 0, 0);
-               send_ldap_result( conn, op, LDAP_NO_SUCH_OBJECT, matched, "" );
+
                if ( matched != NULL ) {
-                       free( matched );
+                       matched_dn = ch_strdup( matched->e_dn );
+                       refs = is_entry_referral( matched )
+                               ? get_entry_referrals( be, conn, op, matched )
+                               : NULL;
+                       bdb2i_cache_return_entry_r( &li->li_cache, matched );
+               } else {
+                       refs = default_referral;
                }
+
+               send_ldap_result( conn, op, LDAP_REFERRAL,
+                       matched_dn, NULL, refs, NULL );
+
+               if( matched != NULL ) {
+                       ber_bvecfree( refs );
+                       free( matched_dn );
+               }
+
                return( -1 );
        }
 
-       /* check for deleted */
+       if (!manageDSAit && is_entry_referral( e ) ) {
+               /* entry is a referral, don't allow add */
+               struct berval **refs = get_entry_referrals( be,
+                       conn, op, e );
+
+               Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0,
+                       0, 0 );
+
+               send_ldap_result( conn, op, LDAP_REFERRAL,
+                       e->e_dn, NULL, refs, NULL );
+
+               ber_bvecfree( refs );
+               goto return_results;
+       }
+
 
        if ( bdb2i_has_children( be, e ) ) {
                Debug(LDAP_DEBUG_ARGS, "<=- bdb2i_back_delete: non leaf %s\n",
                        dn, 0, 0);
-               send_ldap_result( conn, op, LDAP_NOT_ALLOWED_ON_NONLEAF, "",
-                   "" );
+               send_ldap_result( conn, op, LDAP_NOT_ALLOWED_ON_NONLEAF,
+                       NULL, NULL, NULL, NULL );
                goto return_results;
        }
 
@@ -55,7 +87,8 @@ bdb2i_back_delete_internal(
                Debug(LDAP_DEBUG_ARGS,
                        "<=- bdb2i_back_delete: insufficient access %s\n",
                        dn, 0, 0);
-               send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS, "", "" );
+               send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
+                       NULL, NULL, NULL, NULL );
                goto return_results;
        }
 #endif
@@ -66,7 +99,7 @@ bdb2i_back_delete_internal(
                        Debug( LDAP_DEBUG_TRACE,
                                "<=- bdb2i_back_delete: parent does not exist\n", 0, 0, 0);
                        send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
-                               "", "");
+                               NULL, NULL, NULL, NULL );
                        goto return_results;
                }
 
@@ -77,7 +110,7 @@ bdb2i_back_delete_internal(
                        Debug( LDAP_DEBUG_TRACE,
                                "<=- bdb2i_back_delete: no access to parent\n", 0, 0, 0 );
                        send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
-                               "", "" );
+                               NULL, NULL, NULL, NULL );
                        goto return_results;
                }
 
@@ -87,7 +120,7 @@ bdb2i_back_delete_internal(
                        Debug( LDAP_DEBUG_TRACE,
                                "<=- bdb2i_back_delete: no parent & not root\n", 0, 0, 0);
                        send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
-                               "", "");
+                               NULL, NULL, NULL, NULL );
                        goto return_results;
                }
        }
@@ -96,7 +129,8 @@ bdb2i_back_delete_internal(
                Debug(LDAP_DEBUG_ARGS,
                        "<=- bdb2i_back_delete: operations error %s\n",
                        dn, 0, 0);
-               send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "","" );
+               send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+                               NULL, NULL, NULL, NULL );
                goto return_results;
        }
 
@@ -105,7 +139,8 @@ bdb2i_back_delete_internal(
                Debug(LDAP_DEBUG_ARGS,
                        "<=- bdb2i_back_delete: operations error %s\n",
                        dn, 0, 0);
-               send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
+               send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+                       NULL, NULL, NULL, NULL );
                goto return_results;
        }
 
@@ -114,11 +149,13 @@ bdb2i_back_delete_internal(
                Debug(LDAP_DEBUG_ARGS,
                        "<=- bdb2i_back_delete: operations error %s\n",
                        dn, 0, 0);
-               send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
+               send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+                       NULL, NULL, NULL, NULL );
                goto return_results;
        }
 
-       send_ldap_result( conn, op, LDAP_SUCCESS, "", "" );
+       send_ldap_result( conn, op, LDAP_SUCCESS,
+               NULL, NULL, NULL, NULL );
        rc = 0;
 
 return_results:;
@@ -155,10 +192,9 @@ bdb2_back_delete(
        bdb2i_start_timing( be->bd_info, &time1 );
 
        if ( bdb2i_enter_backend_w( &lock ) != 0 ) {
-
-               send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
+               send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+                       NULL, NULL, NULL, NULL );
                return( -1 );
-
        }
 
        ret = bdb2i_back_delete_internal( be, conn, op, dn );
index 470eb6a142ebe7067b08711a8e33dc866f99f78a..e77cabfa20f6f8d3200938571e72bcf2c80b094a 100644 (file)
@@ -156,7 +156,7 @@ Entry *
 bdb2i_dn2entry_rw(
     BackendDB  *be,
     char       *dn,
-    char       **matched,
+    Entry      **matched,
     int         rw
 )
 {
@@ -168,7 +168,10 @@ bdb2i_dn2entry_rw(
        Debug(LDAP_DEBUG_TRACE, "dn2entry_%s: dn: \"%s\"\n",
                rw ? "w" : "r", dn, 0);
 
-       *matched = NULL;
+       if( matched != NULL ) {
+               /* caller cares about match */
+               *matched = NULL;
+       }
 
        if ( (id = bdb2i_dn2id( be, dn )) != NOID &&
                (e = bdb2i_id2entry_rw( be, id, rw )) != NULL )
@@ -184,24 +187,17 @@ bdb2i_dn2entry_rw(
                /* treat as if NOID was found */
        }
 
-       /* stop when we get to the suffix */
-       if ( be_issuffix( be, dn ) ) {
-               return( NULL );
-       }
+       /* caller doesn't care about match */
+       if( matched == NULL ) return NULL;
 
        /* entry does not exist - see how much of the dn does exist */
+       /* dn_parent checks returns NULL if dn is suffix */
        if ( (pdn = dn_parent( be, dn )) != NULL ) {
                /* get entry with reader lock */
                if ( (e = bdb2i_dn2entry_r( be, pdn, matched )) != NULL ) {
-                       if(*matched != NULL) {
-                               free(*matched);
-                       }
-                       *matched = pdn;
-                       /* free entry with reader lock */
-                       bdb2i_cache_return_entry_r( &li->li_cache, e );
-               } else {
-                       free( pdn );
+                       *matched = e;
                }
+               free( pdn );
        }
 
        return( NULL );
index fc3377cc35816742eb8d07acc0dd9f6297a8f9d3..6e393757e3558d081ed4b607d68d4267bddf48c3 100644 (file)
@@ -26,93 +26,116 @@ bdb2i_back_group_internal(
        char    *groupattrName
 )
 {
-        struct ldbminfo *li = (struct ldbminfo *) be->be_private;    
-        Entry        *e;
-        char        *matched;
-        Attribute   *objectClass;
-        Attribute   *member;
-        int          rc;
-
-       Debug( LDAP_DEBUG_TRACE,
+       struct ldbminfo *li = (struct ldbminfo *) be->be_private;    
+       Entry *e;
+       int rc = 1;
+       Attribute *attr;
+       struct berval bv;
+
+       Debug( LDAP_DEBUG_ARGS,
                "=> bdb2i_back_group: gr dn: \"%s\"\n",
                gr_ndn, 0, 0 ); 
-       Debug( LDAP_DEBUG_TRACE,
+       Debug( LDAP_DEBUG_ARGS,
                "=> bdb2i_back_group: op dn: \"%s\"\n",
                op_ndn, 0, 0 ); 
-       Debug( LDAP_DEBUG_TRACE,
+       Debug( LDAP_DEBUG_ARGS,
                "=> bdb2i_back_group: objectClass: \"%s\" attrName: \"%s\"\n", 
                objectclassValue, groupattrName, 0 ); 
 
-       Debug( LDAP_DEBUG_TRACE,
+       Debug( LDAP_DEBUG_ARGS,
                "=> bdb2i_back_group: tr dn: \"%s\"\n",
                target->e_ndn, 0, 0 ); 
 
        if (strcmp(target->e_ndn, gr_ndn) == 0) {
                /* we already have a LOCKED copy of the entry */
                e = target;
-               Debug( LDAP_DEBUG_ARGS,
+               Debug( LDAP_DEBUG_ARGS,
                        "=> bdb2i_back_group: target is group: \"%s\"\n",
                        gr_ndn, 0, 0 ); 
+
        } else {
                /* can we find group entry with reader lock */
-               if ((e = bdb2i_dn2entry_r(be, gr_ndn, &matched )) == NULL) {
-                       Debug( LDAP_DEBUG_TRACE,
-                               "=> bdb2i_back_group: cannot find group: \"%s\" matched: \"%s\"\n",
-                                       gr_ndn, (matched ? matched : ""), 0 ); 
-                       if (matched != NULL)
-                               free(matched);
+               if ((e = bdb2i_dn2entry_r(be, gr_ndn, NULL )) == NULL) {
+                       Debug( LDAP_DEBUG_ACL,
+                               "=> bdb2i_back_group: cannot find group: \"%s\"\n",
+                                       gr_ndn, 0, 0 ); 
                        return( 1 );
                }
-               Debug( LDAP_DEBUG_ARGS,
+
+               Debug( LDAP_DEBUG_ACL,
                        "=> bdb2i_back_group: found group: \"%s\"\n",
                        gr_ndn, 0, 0 ); 
-        }
+       }
 
+       /* find it's objectClass and member attribute values
+        * make sure this is a group entry
+        * finally test if we can find op_dn in the member attribute value list
+        */
+        
+       rc = 1;
 
-        /* check for deleted */
+       if ((attr = attr_find(e->e_attrs, "objectclass")) == NULL)  {
+               Debug( LDAP_DEBUG_ACL,
+                       "<= bdb2i_back_group: failed to find objectClass\n", 0, 0, 0 ); 
+               goto return_results;
+       }
 
-        /* find it's objectClass and member attribute values
-         * make sure this is a group entry
-         * finally test if we can find op_dn in the member attribute value list *
-         */
-        
-        rc = 1;
-        if ((objectClass = attr_find(e->e_attrs, "objectclass")) == NULL)  {
-            Debug( LDAP_DEBUG_TRACE, "<= bdb2i_back_group: failed to find objectClass\n", 0, 0, 0 ); 
-        }
-        else if ((member = attr_find(e->e_attrs, groupattrName)) == NULL) {
-            Debug( LDAP_DEBUG_TRACE, "<= bdb2i_back_group: failed to find %s\n", groupattrName, 0, 0 ); 
-        }
-        else {
-            struct berval bvObjectClass;
-            struct berval bvMembers;
-
-            Debug( LDAP_DEBUG_ARGS, "<= bdb2i_back_group: found objectClass and %s\n", groupattrName, 0, 0 ); 
-
-            bvObjectClass.bv_val = objectclassValue;
-            bvObjectClass.bv_len = strlen( bvObjectClass.bv_val );         
-
-            bvMembers.bv_val = op_ndn;
-            bvMembers.bv_len = strlen( op_ndn );         
-
-            if (value_find(objectClass->a_vals, &bvObjectClass, SYNTAX_CIS, 1) != 0) {
-                Debug( LDAP_DEBUG_TRACE,
-                                       "<= bdb2i_back_group: failed to find %s in objectClass\n", 
-                        objectclassValue, 0, 0 ); 
-            }
-            else if (value_find(member->a_vals, &bvMembers, SYNTAX_CIS, 1) != 0) {
-                Debug( LDAP_DEBUG_ACL,
-                                       "<= bdb2i_back_group: \"%s\" not in \"%s\": %s\n", 
-                                       op_ndn, gr_ndn, groupattrName ); 
-            }
-            else {
-                               Debug( LDAP_DEBUG_ACL,
-                                       "<= bdb2i_back_group: \"%s\" is in \"%s\": %s\n", 
-                                       op_ndn, gr_ndn, groupattrName ); 
-                rc = 0;
-            }
-        }
+       bv.bv_val = "ALIAS";
+       bv.bv_len = sizeof("ALIAS")-1;
+
+       if (value_find(attr->a_vals, &bv, attr->a_syntax, 1) != 0) {
+               Debug( LDAP_DEBUG_ACL,
+                       "<= bdb2i_back_group: group is an alias\n", 0, 0, 0 ); 
+               goto return_results;
+       }
+
+       bv.bv_val = "REFERRAL";
+       bv.bv_len = sizeof("REFERRAL")-1;
+
+       if (value_find(attr->a_vals, &bv, attr->a_syntax, 1) != 0) {
+               Debug( LDAP_DEBUG_ACL,
+                       "<= bdb2i_back_group: group is a referral\n", 0, 0, 0 ); 
+               goto return_results;
+       }
+
+       bv.bv_val = objectclassValue;
+       bv.bv_len = strlen( bv.bv_val );
+
+       if (value_find(attr->a_vals, &bv, attr->a_syntax, 1) != 0) {
+               Debug( LDAP_DEBUG_ACL,
+                       "<= bdb2i_back_group: failed to find %s in objectClass\n",
+                       objectclassValue, 0, 0 ); 
+               goto return_results;
+       }
+
+       if ((attr = attr_find(e->e_attrs, groupattrName)) == NULL) {
+               Debug( LDAP_DEBUG_ACL,
+                       "<= bdb2i_back_group: failed to find %s\n",
+                       groupattrName, 0, 0 ); 
+               goto return_results;
+       }
+
+       Debug( LDAP_DEBUG_ACL,
+               "<= bdb2i_back_group: found objectClass %s and %s\n",
+               objectclassValue, groupattrName, 0 ); 
+
+
+       bv.bv_val = op_ndn;
+       bv.bv_len = strlen( op_ndn );         
+
+       if (value_find( attr->a_vals, &bv, attr->a_syntax, 1) != 0 ) {
+               Debug( LDAP_DEBUG_ACL,
+                       "<= bdb2i_back_group: \"%s\" not in \"%s\": %s\n", 
+                       op_ndn, gr_ndn, groupattrName ); 
+               goto return_results;
+       }
+
+       Debug( LDAP_DEBUG_ACL,
+               "<= bdb2i_back_group: \"%s\" is in \"%s\": %s\n", 
+               op_ndn, gr_ndn, groupattrName ); 
+       rc = 0;
 
+return_results:
        if( target != e ) {
                /* free entry and reader lock */
                bdb2i_cache_return_entry_r( &li->li_cache, e );                 
index e158f6cdefe5d16473aef0b01e30fdc2cbf543b8..6dee5eeace02004e38859c6d19b59ad914ebecf3 100644 (file)
@@ -104,7 +104,8 @@ bdb2i_back_modify_internal(
        Debug(LDAP_DEBUG_ARGS, "bdb2i_back_modify:\n", 0, 0, 0);
 
        if ( (err = acl_check_modlist( be, conn, op, e, modlist )) != LDAP_SUCCESS ) {
-               send_ldap_result( conn, op, err, NULL, NULL );
+               send_ldap_result( conn, op, err,
+                       NULL, NULL, NULL, NULL );
                goto error_return;
        }
 
@@ -141,7 +142,8 @@ bdb2i_back_modify_internal(
 
                if ( err != LDAP_SUCCESS ) {
                        /* unlock entry, delete from cache */
-                       send_ldap_result( conn, op, err, NULL, NULL );
+                       send_ldap_result( conn, op, err,
+                               NULL, NULL, NULL, NULL );
                        goto error_return;
                }
        }
@@ -149,7 +151,8 @@ bdb2i_back_modify_internal(
        /* check that the entry still obeys the schema */
        if ( global_schemacheck && oc_schema_check( e ) != 0 ) {
                Debug( LDAP_DEBUG_ANY, "entry failed schema check\n", 0, 0, 0 );
-               send_ldap_result( conn, op, LDAP_OBJECT_CLASS_VIOLATION, NULL, NULL );
+               send_ldap_result( conn, op, LDAP_OBJECT_CLASS_VIOLATION,
+                       NULL, NULL, NULL, NULL );
                goto error_return;
        }
 
@@ -163,7 +166,8 @@ bdb2i_back_modify_internal(
 
        /* modify indexes */
        if ( bdb2i_index_add_mods( be, modlist, e->e_id ) != 0 ) {
-               send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL, NULL );
+               send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+                       NULL, NULL, NULL, NULL );
                goto error_return;
        }
 
@@ -177,16 +181,16 @@ bdb2i_back_modify_internal(
 
        /* change the entry itself */
        if ( bdb2i_id2entry_add( be, e ) != 0 ) {
-               send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL, NULL );
+               send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+                       NULL, NULL, NULL, NULL );
                goto error_return;
        }
 
-       send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL );
-       bdb2i_cache_return_entry_w( &li->li_cache, e );
+       send_ldap_result( conn, op, LDAP_SUCCESS,
+               NULL, NULL, NULL, NULL );
        return( 0 );
 
 error_return:;
-       bdb2i_cache_return_entry_w( &li->li_cache, e );
        return( -1 );
 }
 
@@ -203,17 +207,16 @@ bdb2_back_modify(
        DB_LOCK         lock;
        struct ldbminfo *li = (struct ldbminfo *) be->be_private;
        struct timeval  time1;
-       int             ret;
-       char            *matched;
+       int             ret, manageDSAit;
+       Entry           *matched;
        Entry           *e;
 
        bdb2i_start_timing( be->bd_info, &time1 );
 
        if ( bdb2i_enter_backend_w( &lock ) != 0 ) {
-
-               send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
+               send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+                       NULL, NULL, NULL, NULL );
                return( -1 );
-
        }
 
        /*  check, if a new default attribute index will be created,
@@ -228,19 +231,54 @@ bdb2_back_modify(
        }
 
        if ( (e = bdb2i_dn2entry_w( be, dn, &matched )) == NULL ) {
-               send_ldap_result( conn, op, LDAP_NO_SUCH_OBJECT, matched,
-                   NULL );
+               char *matched_dn = NULL;
+               struct berval **refs = NULL;
 
                if ( matched != NULL ) {
-                       free( matched );
+                       matched_dn = ch_strdup( matched->e_dn );
+                       refs = is_entry_referral( matched )
+                               ? get_entry_referrals( be, conn, op, matched )
+                               : NULL;
+                       bdb2i_cache_return_entry_r( &li->li_cache, matched );
+               } else {
+                       refs = default_referral;
+               }
+
+               send_ldap_result( conn, op, LDAP_REFERRAL,
+                       matched_dn, NULL, refs, NULL );
+
+               if( matched != NULL ) {
+                       ber_bvecfree( refs );
+                       free( matched_dn );
                }
 
                ret = -1;
+               goto done;
+       }
 
-       } else {
-               ret = bdb2i_back_modify_internal( be, conn, op, dn, modlist, e );
+       if (!manageDSAit && is_entry_referral( e ) ) {
+               /* entry is a referral, don't allow add */
+               struct berval **refs = get_entry_referrals( be,
+                       conn, op, e );
+
+               Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0,
+                       0, 0 );
+
+               send_ldap_result( conn, op, LDAP_REFERRAL,
+                       e->e_dn, NULL, refs, NULL );
+
+               bdb2i_cache_return_entry_w( &li->li_cache, e );
+
+               ber_bvecfree( refs );
+
+               ret = -1;
+               goto done;
        }
 
+       ret = bdb2i_back_modify_internal( be, conn, op, dn, modlist, e );
+       bdb2i_cache_return_entry_w( &li->li_cache, e );
+
+done:
        (void) bdb2i_leave_backend_w( lock );
        bdb2i_stop_timing( be->bd_info, time1, "MOD", conn, op );
 
index d2965a28c4d3749cd3bbd4b70dfc6b2956b52d0c..8054eed2c1a0e681142f2b2c73087cf8ffce501d 100644 (file)
@@ -36,12 +36,12 @@ bdb2i_back_modrdn_internal(
 )
 {
        struct ldbminfo *li = (struct ldbminfo *) be->be_private;
-       char            *matched = NULL;
+       Entry           *matched = NULL;
        char            *p_dn = NULL, *p_ndn = NULL;
        char            *new_dn = NULL, *new_ndn = NULL;
        char            sep[2];
        Entry           *e, *p = NULL;
-       int                     rc = -1;
+       int                     rc = -1, manageDSAit;
        /* Added to support LDAP v2 correctly (deleteoldrdn thing) */
        char            *new_rdn_val = NULL;    /* Val of new rdn */
        char            *new_rdn_type = NULL;   /* Type of new rdn */
@@ -65,13 +65,46 @@ bdb2i_back_modrdn_internal(
 
        /* get entry with writer lock */
        if ( (e = bdb2i_dn2entry_w( be, dn, &matched )) == NULL ) {
-               send_ldap_result( conn, op, LDAP_NO_SUCH_OBJECT, matched, "" );
+               char *matched_dn = NULL;
+               struct berval **refs = NULL;
+
                if ( matched != NULL ) {
-                       free( matched );
+                       matched_dn = ch_strdup( matched->e_dn );
+                       refs = is_entry_referral( matched )
+                               ? get_entry_referrals( be, conn, op, matched )
+                               : NULL;
+                       bdb2i_cache_return_entry_r( &li->li_cache, matched );
+               } else {
+                       refs = default_referral;
                }
+
+               send_ldap_result( conn, op, LDAP_REFERRAL,
+                       matched_dn, NULL, refs, NULL );
+
+               if( matched != NULL ) {
+                       ber_bvecfree( refs );
+                       free( matched_dn );
+               }
+
                return( -1 );
        }
 
+       if (!manageDSAit && is_entry_referral( e ) ) {
+               /* entry is a referral, don't allow add */
+               struct berval **refs = get_entry_referrals( be,
+                       conn, op, e );
+
+               Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0,
+                       0, 0 );
+
+               send_ldap_result( conn, op, LDAP_REFERRAL,
+                       e->e_dn, NULL, refs, NULL );
+
+               ber_bvecfree( refs );
+
+               goto return_results;
+       }
+
 #ifdef SLAPD_CHILD_MODIFICATION_WITH_ENTRY_ACL
                /* check parent for "children" acl */
        if ( ! access_allowed( be, conn, op, e,
@@ -80,7 +113,7 @@ bdb2i_back_modrdn_internal(
                Debug( LDAP_DEBUG_TRACE, "no access to entry\n", 0,
                        0, 0 );
                send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
-                       "", "" );
+                       NULL, NULL, NULL, NULL );
                goto return_results;
        }
 #endif
@@ -91,7 +124,7 @@ bdb2i_back_modrdn_internal(
                        Debug( LDAP_DEBUG_TRACE, "parent does not exist\n",
                                0, 0, 0);
                        send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
-                               "", "");
+                               NULL, NULL, NULL, NULL );
                        goto return_results;
                }
 
@@ -102,7 +135,7 @@ bdb2i_back_modrdn_internal(
                        Debug( LDAP_DEBUG_TRACE, "no access to parent\n", 0,
                                0, 0 );
                        send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
-                               "", "" );
+                               NULL, NULL, NULL, NULL );
                        goto return_results;
                }
 
@@ -118,7 +151,7 @@ bdb2i_back_modrdn_internal(
                        Debug( LDAP_DEBUG_TRACE, "no parent & not root\n",
                                0, 0, 0);
                        send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
-                               "", "");
+                               NULL, NULL, NULL, NULL );
                        goto return_results;
                }
 
@@ -150,8 +183,8 @@ bdb2i_back_modrdn_internal(
                        Debug( LDAP_DEBUG_TRACE,
                               "ldbm_back_modrdn: newSup(ndn=%s) not here!\n",
                               np_ndn, 0, 0);
-                       send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "",
-                                         "");
+                       send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+                               NULL, NULL, NULL, NULL );
                        goto return_results;
                }
 
@@ -167,7 +200,7 @@ bdb2i_back_modrdn_internal(
                               "ldbm_back_modrdn: no wr to newSup children\n",
                               0, 0, 0 );
                        send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
-                                         "", "" );
+                               NULL, NULL, NULL, NULL );
                        goto return_results;
                }
 
@@ -191,7 +224,8 @@ bdb2i_back_modrdn_internal(
               new_ndn, 0, 0 );
 
        if ( (bdb2i_dn2id ( be, new_ndn ) ) != NOID ) {
-               send_ldap_result( conn, op, LDAP_ALREADY_EXISTS, NULL, NULL );
+               send_ldap_result( conn, op, LDAP_ALREADY_EXISTS,
+                       NULL, NULL, NULL, NULL );
                goto return_results;
        }
 
@@ -205,7 +239,8 @@ bdb2i_back_modrdn_internal(
 
        /* delete old one */
        if ( bdb2i_dn2id_delete( be, e->e_ndn ) != 0 ) {
-               send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL, NULL );
+               send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+                       NULL, NULL, NULL, NULL );
                goto return_results;
        }
 
@@ -218,7 +253,8 @@ bdb2i_back_modrdn_internal(
 
        /* add new one */
        if ( bdb2i_dn2id_add( be,  e->e_ndn, e->e_id ) != 0 ) {
-               send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL, NULL );
+               send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+                       NULL, NULL, NULL, NULL );
                goto return_results;
        }
 
@@ -231,7 +267,8 @@ bdb2i_back_modrdn_internal(
                Debug( LDAP_DEBUG_TRACE,
                       "ldbm_back_modrdn: can't figure out type of newrdn\n",
                       0, 0, 0 );
-               send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
+               send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+                       NULL, NULL, NULL, NULL );
                goto return_results;            
 
        }
@@ -241,7 +278,8 @@ bdb2i_back_modrdn_internal(
                Debug( LDAP_DEBUG_TRACE,
                       "ldbm_back_modrdn: can't figure out val of newrdn\n",
                       0, 0, 0 );
-               send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
+               send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+                       NULL, NULL, NULL, NULL );
                goto return_results;            
 
        }
@@ -257,7 +295,8 @@ bdb2i_back_modrdn_internal(
                Debug( LDAP_DEBUG_TRACE,
                       "ldbm_back_modrdn: can't figure out old_rdn from dn\n",
                       0, 0, 0 );
-               send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
+               send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+                       NULL, NULL, NULL, NULL );
                goto return_results;            
 
        }
@@ -267,7 +306,8 @@ bdb2i_back_modrdn_internal(
                Debug( LDAP_DEBUG_TRACE,
                       "ldbm_back_modrdn: can't figure out the old_rdn type\n",
                       0, 0, 0 );
-               send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
+               send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+                       NULL, NULL, NULL, NULL );
                goto return_results;            
                
        }
@@ -318,9 +358,8 @@ bdb2i_back_modrdn_internal(
                                Debug( LDAP_DEBUG_TRACE,
                                       "ldbm_back_modrdn: can't figure out old_rdn_val from old_rdn\n",
                                       0, 0, 0 );
-                               send_ldap_result( conn, op,
-                                                 LDAP_OPERATIONS_ERROR,
-                                                 "", "" );
+                               send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+                                       NULL, NULL, NULL, NULL );
                                goto return_results;            
 
 
@@ -373,17 +412,20 @@ bdb2i_back_modrdn_internal(
        /* id2entry index */
        if ( bdb2i_id2entry_add( be, e ) != 0 ) {
                entry_free( e );
-               send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
+               send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+                       NULL, NULL, NULL, NULL );
                goto return_results_after;
        }
 
-       send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL );
+       send_ldap_result( conn, op, LDAP_SUCCESS,
+               NULL, NULL, NULL, NULL );
        rc = 0;
        goto return_results_after;      
 
 return_results:
        if( new_dn != NULL ) free( new_dn );
        if( new_ndn != NULL ) free( new_ndn );
+
 return_results_after:
        /* NOTE:
         * new_dn and new_ndn are not deallocated because they are used by
@@ -392,8 +434,6 @@ return_results_after:
        if( p_dn != NULL ) free( p_dn );
        if( p_ndn != NULL ) free( p_ndn );
 
-       if( matched != NULL ) free( matched );
-
        /* LDAP v2 supporting correct attribute handling. */
        if( new_rdn_type != NULL ) free(new_rdn_type);
        if( new_rdn_val != NULL ) free(new_rdn_val);
@@ -436,8 +476,8 @@ bdb2_back_modrdn(
        bdb2i_start_timing( be->bd_info, &time1 );
 
        if ( bdb2i_enter_backend_w( &lock ) != 0 ) {
-
-               send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
+               send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+                       NULL, NULL, NULL, NULL );
                return( -1 );
 
        }
index c3135c68b9d97eeebee6bc95db6dd7736a4f34f5..e6ac08c6e620941e0a5e7bbfe11c0661cf4bc7be 100644 (file)
@@ -17,16 +17,19 @@ int bdb2i_release_add_lock LDAP_P(());
 /*
  * alias.c
  */
-Entry *bdb2i_derefAlias_r LDAP_P((
-       BackendDB   *be,
-       Connection      *conn,
-       Operation       *op,
-       Entry       *e ));
-char *bdb2i_derefDN LDAP_P((
-       BackendDB   *be,
-       Connection  *conn,
-       Operation   *op,
-       char        *dn ));
+
+Entry * bdb2i_deref_r LDAP_P((
+       Backend *be,
+       Entry *e,
+       char *dn,
+       int *err,
+       Entry **matched,
+       char **text ));
+
+#define deref_entry_r( be, e, err, matched, text ) \
+       bdb2i_deref_r( be, e, NULL, err, matched, text )
+#define deref_dn_r( be, dn, err, matched, text ) \
+       bdb2i_deref_r( be, NULL, dn, err, matched, text )
 
 /*
  * attr.c
@@ -74,8 +77,12 @@ int bdb2i_dn2id_add LDAP_P(( BackendDB *be, char *dn, ID id ));
 ID bdb2i_dn2id LDAP_P(( BackendDB *be, char *dn ));
 int bdb2i_dn2id_delete LDAP_P(( BackendDB *be, char *dn ));
 
-Entry * bdb2i_dn2entry_rw LDAP_P(( BackendDB *be, char *dn, char **matched,
- int rw ));
+Entry * bdb2i_dn2entry_rw LDAP_P((
+       BackendDB *be,
+       char *dn,
+       Entry **matched,
+       int rw ));
+
 #define bdb2i_dn2entry_r(be, dn, m) bdb2i_dn2entry_rw((be), (dn), (m), 0)
 #define bdb2i_dn2entry_w(be, dn, m) bdb2i_dn2entry_rw((be), (dn), (m), 1)
 
index 28fed4863aa2d30c0b28a8638fc76cc611ba7bd1..63d709475cde4632ed4f4d83cdf9924b15a4bdb0 100644 (file)
 #include "back-bdb2.h"
 #include "proto-back-bdb2.h"
 
-static ID_BLOCK        *base_candidates(BackendDB *be, Connection *conn, Operation *op, char *base, Filter *filter, char **attrs, int attrsonly, char **matched, int *err);
-static ID_BLOCK        *onelevel_candidates(BackendDB *be, Connection *conn, Operation *op, char *base, Filter *filter, char **attrs, int attrsonly, char **matched, int *err);
-static ID_BLOCK        *subtree_candidates(BackendDB *be, Connection *conn, Operation *op, char *base, Filter *filter, char **attrs, int attrsonly, char **matched, Entry *e, int *err, int lookupbase);
-
-#define GRABSIZE       BUFSIZ
-
-#define MAKE_SPACE( n ) { \
-       if ( rcur + (n) > rbuf + rmaxsize ) { \
-               int     offset = rcur - rbuf; \
-               rbuf =  ch_realloc( rbuf, rmaxsize + GRABSIZE ); \
-               rmaxsize += GRABSIZE; \
-               rcur = rbuf + offset; \
-       } \
-}
+static ID_BLOCK *base_candidate(
+       Backend *be, Entry *e );
+
+static ID_BLOCK *search_candidates(
+       Backend *be, Entry *e, Filter *filter,
+       int scope, int deref, int manageDSAit );
 
 static int
 bdb2i_back_search_internal(
@@ -44,19 +36,76 @@ bdb2i_back_search_internal(
 )
 {
        struct ldbminfo *li = (struct ldbminfo *) be->be_private;
-       int             err;
+       int             rc, err;
+       char *text;
        time_t          stoptime;
        ID_BLOCK                *candidates;
        ID              id;
        Entry           *e;
-       Attribute       *ref;
-       char            *matched = NULL;
-       int             rmaxsize, nrefs;
-       char            *rbuf, *rcur;
+       struct berval **v2refs = NULL;
+       Entry   *matched = NULL;
+       char    *realbase = NULL;
        int             nentries = 0;
-       char            *realBase;
+       int             manageDSAit = get_manageDSAit( op );
+
+       Debug(LDAP_DEBUG_TRACE, "=> bdb2_back_search\n", 0, 0, 0);
+
+       /* get entry with reader lock */
+       if ( deref & LDAP_DEREF_FINDING ) {
+               e = deref_dn_r( be, base, &err, &matched, &text );
+
+       } else {
+               e = bdb2i_dn2entry_r( be, base, &matched );
+               err = e != NULL ? LDAP_SUCCESS : LDAP_REFERRAL;
+               text = NULL;
+       }
+
+       if ( e == NULL ) {
+               char *matched_dn = NULL;
+               struct berval **refs = NULL;
+
+               if ( matched != NULL ) {
+                       matched_dn = ch_strdup( matched->e_dn );
+
+                       refs = is_entry_referral( matched )
+                               ? get_entry_referrals( be, conn, op, matched )
+                               : NULL;
+
+                       bdb2i_cache_return_entry_r( &li->li_cache, matched );
+               } else {
+                       refs = default_referral;
+               }
+
+               send_ldap_result( conn, op, err,
+                       matched_dn, text, refs, NULL );
+
+               if( matched != NULL ) {
+                       ber_bvecfree( refs );
+                       free( matched_dn );
+               }
+
+               return 1;
+       }
+
+       if (!manageDSAit && is_entry_referral( e ) ) {
+               /* entry is a referral, don't allow add */
+               char *matched_dn = ch_strdup( e->e_dn );
+               struct berval **refs = get_entry_referrals( be,
+                       conn, op, e );
+
+               bdb2i_cache_return_entry_r( &li->li_cache, e );
+
+               Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0,
+                   0, 0 );
 
-       Debug(LDAP_DEBUG_ARGS, "=> bdb2i_back_search\n", 0, 0, 0);
+               send_ldap_result( conn, op, LDAP_REFERRAL,
+                   matched_dn, NULL, refs, NULL );
+
+               ber_bvecfree( refs );
+               free( matched_dn );
+
+               return 1;
+       }
 
        if ( tlimit == 0 && be_isroot( be, op->o_ndn ) ) {
                tlimit = -1;    /* allow root to set no limit */
@@ -65,6 +114,7 @@ bdb2i_back_search_internal(
                    be->be_timelimit : tlimit;
                stoptime = op->o_time + tlimit;
        }
+
        if ( slimit == 0 && be_isroot( be, op->o_ndn ) ) {
                slimit = -1;    /* allow root to set no limit */
        } else {
@@ -72,220 +122,183 @@ bdb2i_back_search_internal(
                    be->be_sizelimit : slimit;
        }
 
-       /*
-        * check and apply aliasing where the dereferencing applies to
-        * the subordinates of the base
-        */
-
-       switch ( deref ) {
-       case LDAP_DEREF_FINDING:
-       case LDAP_DEREF_ALWAYS:
-               realBase = bdb2i_derefDN ( be, conn, op, base );
-               break;
-       default:
-               realBase = ch_strdup(base);
-       }
+       if ( scope == LDAP_SCOPE_BASE) {
+               candidates = base_candidate( be, e );
 
-       (void) dn_normalize_case( realBase );
-
-       Debug( LDAP_DEBUG_TRACE, "using base \"%s\"\n",
-               realBase, 0, 0 );
-
-       switch ( scope ) {
-       case LDAP_SCOPE_BASE:
-               candidates = base_candidates( be, conn, op, realBase, filter,
-                   attrs, attrsonly, &matched, &err );
-               break;
-
-       case LDAP_SCOPE_ONELEVEL:
-               candidates = onelevel_candidates( be, conn, op, realBase, filter,
-                   attrs, attrsonly, &matched, &err );
-               break;
-
-       case LDAP_SCOPE_SUBTREE:
-               candidates = subtree_candidates( be, conn, op, realBase, filter,
-                   attrs, attrsonly, &matched, NULL, &err, 1 );
-               break;
-
-       default:
-               send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR, "",
-                   "Bad scope" );
-               if( realBase != NULL) {
-                       free( realBase );
-               }
-               return( -1 );
+       } else {
+               candidates = search_candidates( be, e, filter,
+                   scope, deref, manageDSAit );
        }
 
-       /* null candidates means we could not find the base object */
+       /* need normalized dn below */
+       realbase = ch_strdup( e->e_ndn );
+       bdb2i_cache_return_entry_r( &li->li_cache, e );
+
        if ( candidates == NULL ) {
-               send_ldap_result( conn, op, err, matched, "" );
-               if ( matched != NULL ) {
-                       free( matched );
-               }
-               if( realBase != NULL) {
-                       free( realBase );
-               }
-               return( -1 );
-       }
+               /* no candidates */
+               Debug( LDAP_DEBUG_TRACE, "no candidates\n", 0,
+                   0, 0 );
+
+               send_search_result( conn, op,
+                       LDAP_SUCCESS,
+                       NULL, NULL, NULL, NULL, 0 );
 
-       if ( matched != NULL ) {
-               free( matched );
+               rc = 1;
+               goto done;
        }
 
-       rmaxsize = 0;
-       nrefs = 0;
-       rbuf = rcur = NULL;
-       MAKE_SPACE( sizeof("Referral:") + 1 );
-       strcpy( rbuf, "Referral:" );
-       rcur = strchr( rbuf, '\0' );
        for ( id = bdb2i_idl_firstid( candidates ); id != NOID;
-           id = bdb2i_idl_nextid( candidates, id ) ) {
+           id = bdb2i_idl_nextid( candidates, id ) )
+       {
+               int             scopeok = 0;
+
                /* check for abandon */
                ldap_pvt_thread_mutex_lock( &op->o_abandonmutex );
+
                if ( op->o_abandon ) {
                        ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
-                       bdb2i_idl_free( candidates );
-                       free( rbuf );
-                       if( realBase != NULL) {
-                               free( realBase );
-                       }
-                       return( 0 );
+                       rc = 0;
+                       goto done;
                }
+
                ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
 
                /* check time limit */
                if ( tlimit != -1 && slap_get_time() > stoptime ) {
-                       send_ldap_search_result( conn, op,
-                           LDAP_TIMELIMIT_EXCEEDED, NULL, nrefs > 0 ? rbuf :
-                           NULL, nentries );
-                       bdb2i_idl_free( candidates );
-                       free( rbuf );
-                       if( realBase != NULL) {
-                               free( realBase );
-                       }
-                       return( 0 );
+                       send_search_result( conn, op, LDAP_TIMELIMIT_EXCEEDED,
+                               NULL, NULL, v2refs, NULL, nentries );
+                       rc = 0;
+                       goto done;
                }
 
                /* get the entry with reader lock */
-               if ( (e = bdb2i_id2entry_r( be, id )) == NULL ) {
-                       Debug( LDAP_DEBUG_ARGS, "candidate %ld not found\n",
-                              id, 0, 0 );
-                       continue;
+               e = bdb2i_id2entry_r( be, id );
+
+               if ( e == NULL ) {
+                       Debug( LDAP_DEBUG_ARGS, "search: candidate %ld not found\n",
+                               id, 0, 0 );
+
+                       goto loop_continue;
+               }
+
+               if ( deref & LDAP_DEREF_SEARCHING && is_entry_alias( e ) ) {
+                       Entry *matched;
+                       int err;
+                       char *text;
+                       
+                       e = deref_entry_r( be, e, &err, &matched, &text );
+
+                       if( e == NULL ) {
+                               e = matched;
+                               goto loop_continue;
+                       }
+
+                       if( e->e_id == id ) {
+                               /* circular loop */
+                               goto loop_continue;
+                       }
+
+                       /* need to skip alias which deref into scope */
+                       if( scope & LDAP_SCOPE_ONELEVEL ) {
+                               char *pdn = dn_parent( NULL, e->e_ndn );
+                               if ( pdn != NULL ) {
+                                       if( strcmp( pdn, realbase ) ) {
+                                               free( pdn );
+                                               goto loop_continue;
+                                       }
+                                       free(pdn);
+                               }
+
+                       } else if ( dn_issuffix( e->e_ndn, realbase ) ) {
+                               /* alias is within scope */
+                               Debug( LDAP_DEBUG_ARGS, "search: \"%s\" in subtree\n",
+                                       e->e_dn, 0, 0 );
+                               goto loop_continue;
+                       }
+
+                       scopeok = 1;
                }
 
                /*
                 * if it's a referral, add it to the list of referrals. only do
-                * this for subtree searches, and don't check the filter explicitly
-                * here since it's only a candidate anyway.
+                * this for non-base searches, and don't check the filter
+                * explicitly here since it's only a candidate anyway.
                 */
-               if ( scope == LDAP_SCOPE_SUBTREE &&
-                       e->e_ndn != NULL &&
-                       strncmp( e->e_ndn, "REF=", 4 ) == 0 &&
-                       (ref = attr_find( e->e_attrs, "ref" )) != NULL )
+               if ( !manageDSAit && scope != LDAP_SCOPE_BASE &&
+                       is_entry_referral( e ) )
                {
-                       int     i;
+                       struct berval **refs = get_entry_referrals(
+                               be, conn, op, e );
 
-                       if ( ref->a_vals == NULL ) {
-                               Debug( LDAP_DEBUG_ANY, "null ref in (%s)\n", 
-                                       e->e_dn, 0, 0 );
-                       } else {
-                               for ( i = 0; ref->a_vals[i] != NULL; i++ ) {
-                                       /* referral + newline + null */
-                                       MAKE_SPACE( ref->a_vals[i]->bv_len + 2 );
-                                       *rcur++ = '\n';
-                                       strncpy( rcur, ref->a_vals[i]->bv_val,
-                                               ref->a_vals[i]->bv_len );
-                                       rcur = rcur + ref->a_vals[i]->bv_len;
-                                       *rcur = '\0';
-                                       nrefs++;
-                               }
-                       }
+                       send_search_reference( be, conn, op,
+                               e, refs, scope, NULL, &v2refs );
 
-               /* otherwise it's an entry - see if it matches the filter */
-               } else {
-                       /* if it matches the filter and scope, send it */
-                       if ( test_filter( be, conn, op, e, filter ) == 0 ) {
-                               int             scopeok;
-                               char    *dn;
+                       ber_bvecfree( refs );
 
-                               /* check scope */
-                               scopeok = 1;
-                               if ( scope == LDAP_SCOPE_ONELEVEL ) {
-                                       if ( (dn = dn_parent( be, e->e_dn )) != NULL ) {
-                                               (void) dn_normalize_case( dn );
-                                               scopeok = (dn == realBase)
-                                                       ? 1
-                                                       : (strcmp( dn, realBase ) ? 0 : 1 );
-                                               free( dn );
-                                       } else {
-                                               scopeok = (realBase == NULL || *realBase == '\0');
-                                       }
-                               } else if ( scope == LDAP_SCOPE_SUBTREE ) {
-                                       dn = ch_strdup( e->e_ndn );
-                                       scopeok = dn_issuffix( dn, realBase );
+                       goto loop_continue;
+               }
+
+               /* if it matches the filter and scope, send it */
+               if ( test_filter( be, conn, op, e, filter ) == 0 ) {
+                       char    *dn;
+
+                       /* check scope */
+                       if ( !scopeok && scope == LDAP_SCOPE_ONELEVEL ) {
+                               if ( (dn = dn_parent( be, e->e_ndn )) != NULL ) {
+                                       (void) dn_normalize_case( dn );
+                                       scopeok = (dn == realbase)
+                                               ? 1
+                                               : (strcmp( dn, realbase ) ? 0 : 1 );
                                        free( dn );
+
+                               } else {
+                                       scopeok = (realbase == NULL || *realbase == '\0');
                                }
 
-                               if ( scopeok ) {
-                                       /* check size limit */
-                                       if ( --slimit == -1 ) {
-                                               bdb2i_cache_return_entry_r( &li->li_cache, e );
-                                               send_ldap_search_result( conn, op,
-                                                       LDAP_SIZELIMIT_EXCEEDED, NULL,
-                                                       nrefs > 0 ? rbuf : NULL, nentries );
-                                               bdb2i_idl_free( candidates );
-                                               free( rbuf );
-
-                                               if( realBase != NULL) {
-                                                       free( realBase );
-                                               }
-                                               return( 0 );
-                                       }
+                       } else if ( !scopeok && scope == LDAP_SCOPE_SUBTREE ) {
+                               dn = ch_strdup( e->e_ndn );
+                               scopeok = dn_issuffix( dn, realbase );
+                               free( dn );
 
-                                       /*
-                                        * check and apply aliasing where the dereferencing applies to
-                                        * the subordinates of the base
-                                        */
-                                       switch ( deref ) {
-                                       case LDAP_DEREF_SEARCHING:
-                                       case LDAP_DEREF_ALWAYS:
-                                               {
-                                                       Entry *newe = bdb2i_derefAlias_r( be, conn, op, e );
-                                                       if ( newe == NULL ) { /* problem with the alias */
-                                                               bdb2i_cache_return_entry_r( &li->li_cache, e );
-                                                               e = NULL;
-                                                       }
-                                                       else if ( newe != e ) { /* reassign e */
-                                                               bdb2i_cache_return_entry_r( &li->li_cache, e );
-                                                               e = newe;
-                                                       }
-                                               }
-                                               break;
-                                       }
+                       } else {
+                               scopeok = 1;
+                       }
 
-                                       if (e) {
-                                               switch ( send_search_entry( be, conn, op, e,
-                                                       attrs, attrsonly, 0 ) ) {
-                                               case 0:         /* entry sent ok */
-                                                       nentries++;
-                                                       break;
-                                               case 1:         /* entry not sent */
-                                                       break;
-                                               case -1:        /* connection closed */
-                                                       bdb2i_cache_return_entry_r( &li->li_cache, e );
-                                                       bdb2i_idl_free( candidates );
-                                                       free( rbuf );
-
-                                                       if( realBase != NULL) {
-                                                               free( realBase );
-                                                       }
-                                                       return( 0 );
-                                               }
+                       if ( scopeok ) {
+                               /* check size limit */
+                               if ( --slimit == -1 ) {
+                                       bdb2i_cache_return_entry_r( &li->li_cache, e );
+                                       send_search_result( conn, op,
+                                               LDAP_SIZELIMIT_EXCEEDED, NULL, NULL,
+                                               v2refs, NULL, nentries );
+                                       rc = 0;
+                                       goto done;
+                               }
+
+                               if (e) {
+                                       switch ( send_search_entry( be, conn, op, e,
+                                               attrs, attrsonly, 0, NULL ) ) {
+                                       case 0:         /* entry sent ok */
+                                               nentries++;
+                                               break;
+                                       case 1:         /* entry not sent */
+                                               break;
+                                       case -1:        /* connection closed */
+                                               bdb2i_cache_return_entry_r( &li->li_cache, e );
+                                               rc = 0;
+                                               goto done;
                                        }
                                }
+                       } else {
+                               Debug( LDAP_DEBUG_TRACE, "candidate %ld scope not okay\n",
+                                       id, 0, 0 );
                        }
+               } else {
+                       Debug( LDAP_DEBUG_TRACE, "candidate %ld does match filter\n",
+                               id, 0, 0 );
                }
 
+loop_continue:
                if( e != NULL ) {
                        /* free reader lock */
                        bdb2i_cache_return_entry_r( &li->li_cache, e );
@@ -293,21 +306,19 @@ bdb2i_back_search_internal(
 
                ldap_pvt_thread_yield();
        }
+       send_search_result( conn, op,
+               v2refs == NULL ? LDAP_SUCCESS : LDAP_REFERRAL,
+               NULL, NULL, v2refs, NULL, nentries );
+
+       rc = 0;
+
+done:
        bdb2i_idl_free( candidates );
-       if ( nrefs > 0 ) {
-               send_ldap_search_result( conn, op, LDAP_PARTIAL_RESULTS, NULL,
-                   rbuf, nentries );
-       } else {
-               send_ldap_search_result( conn, op, LDAP_SUCCESS, NULL, NULL,
-                   nentries );
-       }
-       free( rbuf );
 
-       if( realBase != NULL) {
-               free( realBase );
-       }
+       ber_bvecfree( v2refs );
+       if( realbase ) free( realbase );
 
-       return( 0 );
+       return rc;
 }
 
 
@@ -335,8 +346,8 @@ bdb2_back_search(
        bdb2i_start_timing( be->bd_info, &time1 );
 
        if ( bdb2i_enter_backend_r( &lock ) != 0 ) {
-
-               send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
+               send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+                       NULL, NULL, NULL, NULL );
                return( -1 );
 
        }
@@ -352,191 +363,126 @@ bdb2_back_search(
 
 
 static ID_BLOCK *
-base_candidates(
-    BackendDB  *be,
-    Connection *conn,
-    Operation  *op,
-    char       *base,
-    Filter     *filter,
-    char       **attrs,
-    int                attrsonly,
-    char       **matched,
-    int                *err
+base_candidate(
+    Backend    *be,
+       Entry   *e
 )
 {
-       struct ldbminfo *li = (struct ldbminfo *) be->be_private;
        ID_BLOCK                *idl;
-       Entry           *e;
-
-       Debug(LDAP_DEBUG_TRACE, "base_candidates: base: \"%s\"\n", base, 0, 0);
 
-       *err = LDAP_SUCCESS;
-
-       /* get entry with reader lock */
-       if ( (e = bdb2i_dn2entry_r( be, base, matched )) == NULL ) {
-               *err = LDAP_NO_SUCH_OBJECT;
-               return( NULL );
-       }
-
-       /* check for deleted */
+       Debug(LDAP_DEBUG_TRACE, "base_candidates: base: \"%s\"\n",
+               e->e_dn, 0, 0);
 
        idl = bdb2i_idl_alloc( 1 );
        bdb2i_idl_insert( &idl, e->e_id, 1 );
 
-
-       /* free reader lock */
-       bdb2i_cache_return_entry_r( &li->li_cache, e );
-
        return( idl );
 }
 
 static ID_BLOCK *
-onelevel_candidates(
-    BackendDB  *be,
-    Connection *conn,
-    Operation  *op,
-    char       *base,
+search_candidates(
+    Backend    *be,
+    Entry      *e,
     Filter     *filter,
-    char       **attrs,
-    int                attrsonly,
-    char       **matched,
-    int                *err
+    int                scope,
+       int             deref,
+       int             manageDSAit
 )
 {
        struct ldbminfo *li = (struct ldbminfo *) be->be_private;
-       Entry           *e = NULL;
-       Filter          *f;
-       char            buf[20];
        ID_BLOCK                *candidates;
+       Filter          *f, *rf, *af, *lf;
 
-       Debug(LDAP_DEBUG_TRACE, "onelevel_candidates: base: \"%s\"\n", base, 0, 0);
+       Debug(LDAP_DEBUG_TRACE, "search_candidates: base=\"%s\" s=%d d=%d\n",
+               e->e_ndn, scope, deref );
 
-       *err = LDAP_SUCCESS;
+       f = NULL;
 
-       /* get the base object with reader lock */
-       if ( base != NULL && *base != '\0' &&
-               (e = bdb2i_dn2entry_r( be, base, matched )) == NULL )
-       {
-               *err = LDAP_NO_SUCH_OBJECT;
-               return( NULL );
+       if( !manageDSAit ) {
+               /* match referrals */
+               rf = (Filter *) ch_malloc( sizeof(Filter) );
+               rf->f_next = NULL;
+               rf->f_choice = LDAP_FILTER_OR;
+               rf->f_or = (Filter *) ch_malloc( sizeof(Filter) );
+               rf->f_or->f_choice = LDAP_FILTER_EQUALITY;
+               rf->f_or->f_avtype = ch_strdup( "objectclass" );
+               rf->f_or->f_avvalue.bv_val = ch_strdup( "REFERRAL" );
+               rf->f_or->f_avvalue.bv_len = sizeof("REFERRAL")-1;
+               rf->f_or->f_next = filter;
+               f = rf;
+       } else {
+               rf = NULL;
+               f = filter;
        }
 
-       /*
-        * modify the filter to be something like this:
-        *
-        *      parent=baseobject & originalfilter
-        */
-
-       f = (Filter *) ch_malloc( sizeof(Filter) );
-       f->f_next = NULL;
-       f->f_choice = LDAP_FILTER_AND;
-       f->f_and = (Filter *) ch_malloc( sizeof(Filter) );
-       f->f_and->f_choice = LDAP_FILTER_EQUALITY;
-       f->f_and->f_ava.ava_type = ch_strdup( "id2children" );
-       sprintf( buf, "%ld", e != NULL ? e->e_id : 0 );
-       f->f_and->f_ava.ava_value.bv_val = ch_strdup( buf );
-       f->f_and->f_ava.ava_value.bv_len = strlen( buf );
-       f->f_and->f_next = filter;
-
-       /* from here, it's just like subtree_candidates */
-       candidates = subtree_candidates( be, conn, op, base, f, attrs,
-           attrsonly, matched, e, err, 0 );
-
-       /* free up just the filter stuff we allocated above */
-       f->f_and->f_next = NULL;
-       filter_free( f );
-
-       /* free entry and reader lock */
-       if( e != NULL ) {
-               bdb2i_cache_return_entry_r( &li->li_cache, e );
+       if( deref & LDAP_DEREF_SEARCHING ) {
+               /* match aliases */
+               af = (Filter *) ch_malloc( sizeof(Filter) );
+               af->f_next = NULL;
+               af->f_choice = LDAP_FILTER_OR;
+               af->f_or = (Filter *) ch_malloc( sizeof(Filter) );
+               af->f_or->f_choice = LDAP_FILTER_EQUALITY;
+               af->f_or->f_avtype = ch_strdup( "objectclass" );
+               af->f_or->f_avvalue.bv_val = ch_strdup( "ALIAS" );
+               af->f_or->f_avvalue.bv_len = sizeof("ALIAS")-1;
+               af->f_or->f_next = f;
+               f = af;
+       } else {
+               af = NULL;
        }
-       return( candidates );
-}
 
-static ID_BLOCK *
-subtree_candidates(
-    BackendDB  *be,
-    Connection *conn,
-    Operation  *op,
-    char       *base,
-    Filter     *filter,
-    char       **attrs,
-    int                attrsonly,
-    char       **matched,
-    Entry      *e,
-    int                *err,
-    int                lookupbase
-)
-{
-       struct ldbminfo *li = (struct ldbminfo *) be->be_private;
-       Filter          *f, **filterarg_ptr;
-       ID_BLOCK                *candidates;
+       if ( scope == LDAP_SCOPE_SUBTREE ) {
+               lf = (Filter *) ch_malloc( sizeof(Filter) );
+               lf->f_next = NULL;
+               lf->f_choice = LDAP_FILTER_AND;
+               lf->f_and = (Filter *) ch_malloc( sizeof(Filter) );
 
-       Debug(LDAP_DEBUG_TRACE, "subtree_candidates: base: \"%s\" %s\n",
-               base ? base : "NULL", lookupbase ? "lookupbase" : "", 0);
-
-       /*
-        * get the base object - unless we already have it (from one-level).
-        * also, unless this is a one-level search or a subtree search
-        * starting at the very top of our subtree, we need to modify the
-        * filter to be something like this:
-        *
-        *      dn=*baseobjectdn & (originalfilter | ref=*)
-        *
-        * the "objectclass=referral" part is used to select referrals to return
-        */
-
-       *err = LDAP_SUCCESS;
-       f = NULL;
-       if ( lookupbase ) {
-               e = NULL;
+               lf->f_and->f_choice = LDAP_FILTER_SUBSTRINGS;
+               lf->f_and->f_sub_type = ch_strdup( "dn" );
+               lf->f_and->f_sub_initial = NULL;
+               lf->f_and->f_sub_any = NULL;
+               lf->f_and->f_sub_final = ch_strdup( e->e_ndn );
 
-               if ( base != NULL && *base != '\0' &&
-                       (e = bdb2i_dn2entry_r( be, base, matched )) == NULL )
-               {
-                       *err = LDAP_NO_SUCH_OBJECT;
-                       return( NULL );
-               }
+               lf->f_and->f_next = f;
+               f = lf;
 
-               if (e) {
-                       bdb2i_cache_return_entry_r( &li->li_cache, e );
-               }
+       } else if ( scope == LDAP_SCOPE_ONELEVEL ) {
+               char buf[16];
 
-               f = (Filter *) ch_malloc( sizeof(Filter) );
-               f->f_next = NULL;
-               f->f_choice = LDAP_FILTER_OR;
-               f->f_or = (Filter *) ch_malloc( sizeof(Filter) );
-               f->f_or->f_choice = LDAP_FILTER_EQUALITY;
-               f->f_or->f_avtype = ch_strdup( "objectclass" );
-               /* Patch to use normalized uppercase */
-               f->f_or->f_avvalue.bv_val = ch_strdup( "REFERRAL" );
-               f->f_or->f_avvalue.bv_len = strlen( "REFERRAL" );
-               filterarg_ptr = &f->f_or->f_next;
-               *filterarg_ptr = filter;
-               filter = f;
-
-               if ( ! be_issuffix( be, base ) ) {
-                       f = (Filter *) ch_malloc( sizeof(Filter) );
-                       f->f_next = NULL;
-                       f->f_choice = LDAP_FILTER_AND;
-                       f->f_and = (Filter *) ch_malloc( sizeof(Filter) );
-                       f->f_and->f_choice = LDAP_FILTER_SUBSTRINGS;
-                       f->f_and->f_sub_type = ch_strdup( "dn" );
-                       f->f_and->f_sub_initial = NULL;
-                       f->f_and->f_sub_any = NULL;
-                       f->f_and->f_sub_final = ch_strdup( base );
-                       value_normalize( f->f_and->f_sub_final, SYNTAX_CIS );
-                       f->f_and->f_next = filter;
-                       filter = f;
-               }
+               lf = (Filter *) ch_malloc( sizeof(Filter) );
+               lf->f_next = NULL;
+               lf->f_choice = LDAP_FILTER_AND;
+               lf->f_and = (Filter *) ch_malloc( sizeof(Filter) );
+
+               lf->f_and->f_choice = LDAP_FILTER_EQUALITY;
+               lf->f_and->f_ava.ava_type = ch_strdup( "id2children" );
+               sprintf( buf, "%ld", e != NULL ? e->e_id : 0 );
+               lf->f_and->f_ava.ava_value.bv_val = ch_strdup( buf );
+               lf->f_and->f_ava.ava_value.bv_len = strlen( buf );
+
+               lf->f_and->f_next = f;
+               f = lf;
+
+       } else {
+               lf = NULL;
        }
 
-       candidates = bdb2i_filter_candidates( be, filter );
+       candidates = bdb2i_filter_candidates( be, f );
+
+       /* free up filter additions we allocated above */
+       if( lf != NULL ) {
+               lf->f_and->f_next = NULL;
+               filter_free( lf );
+       }
+
+       if( af != NULL ) {
+               af->f_or->f_next = NULL;
+               filter_free( af );
+       }
 
-       /* free up just the parts we allocated above */
-       if ( f != NULL ) {
-               *filterarg_ptr = NULL;
-               filter_free( f );
+       if( rf != NULL ) {
+               rf->f_or->f_next = NULL;
+               filter_free( rf );
        }
 
        return( candidates );
index 26632c82466b25fc4d9a6635d04502878bb0079d..d57364a6373080dd372a2cd0298648a25620ad94 100644 (file)
@@ -75,8 +75,8 @@ ldap_back_getconn(struct ldapinfo *li, Connection *conn, Operation *op)
        if (!lc) {
                ld = ldap_init(li->host, li->port);
                if (!ld) {
-                       send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL,
-                       "ldap_init failed" );
+                       send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+                               NULL, "ldap_init failed", NULL, NULL );
                        return( NULL );
                }
                lc = (struct ldapconn *)ch_malloc(sizeof(struct ldapconn));
@@ -112,7 +112,7 @@ ldap_back_op_result(struct ldapconn *lc, Operation *op)
        ldap_get_option(lc->ld, LDAP_OPT_ERROR_NUMBER, &err);
        ldap_get_option(lc->ld, LDAP_OPT_ERROR_STRING, &msg);
        ldap_get_option(lc->ld, LDAP_OPT_MATCHED_DN, &match);
-       send_ldap_result( lc->conn, op, err, match, msg);
+       send_ldap_result( lc->conn, op, err, match, msg, NULL, NULL );
        free(match);
        free(msg);
        return( (err==LDAP_SUCCESS) ? 0 : -1 );
index 6145a0704d83adcdf917abb0079fc1a183f5a633..c742248c5ee3cb6ae516418e15f57df221557f40 100644 (file)
@@ -116,7 +116,8 @@ fail:               return( ldap_back_op_result(lc, op) );
        if (rc == -1)
                goto fail;
 
-       send_ldap_search_result( conn, op, sres, match, err, i );
+       send_search_result( conn, op, sres,
+               match, err, NULL, NULL, i );
        if (match)
                free(match);
        if (err)
@@ -158,7 +159,7 @@ ldap_send_entry(
                if (!attr->a_vals)
                        attr->a_vals = &dummy;
        }
-       send_search_entry( be, lc->conn, op, &ent, attrs, attrsonly, 0 );
+       send_search_entry( be, lc->conn, op, &ent, attrs, attrsonly, 0, NULL );
        for (;ent.e_attrs;) {
                attr=ent.e_attrs;
                ent.e_attrs = attr->a_next;
index 6173a78c925f2c463f8627e7c453a84166a445e1..c6f85169c69f3a80892529da57f3ff69307ff60d 100644 (file)
@@ -33,7 +33,8 @@ ldbm_back_add(
        if ( ( dn2id( be, e->e_ndn ) ) != NOID ) {
                ldap_pvt_thread_mutex_unlock(&li->li_add_mutex);
                entry_free( e );
-               send_ldap_result( conn, op, LDAP_ALREADY_EXISTS, "", "" );
+               send_ldap_result( conn, op, LDAP_ALREADY_EXISTS,
+                       NULL, NULL, NULL, NULL );
                return( -1 );
        }
 
@@ -44,8 +45,8 @@ ldbm_back_add(
                        0, 0, 0 );
 
                entry_free( e );
-               send_ldap_result( conn, op, LDAP_OBJECT_CLASS_VIOLATION, "",
-                   "" );
+               send_ldap_result( conn, op, LDAP_OBJECT_CLASS_VIOLATION,
+                       NULL, NULL, NULL, NULL );
                return( -1 );
        }
 
@@ -58,20 +59,38 @@ ldbm_back_add(
        pdn = dn_parent( be, e->e_ndn );
 
        if( pdn != NULL && *pdn != '\0' && !be_issuffix(be, "") ) {
-               char *matched = NULL;
+               Entry *matched = NULL;
 
                assert( *pdn != '\0' );
 
                /* get parent with writer lock */
                if ( (p = dn2entry_w( be, pdn, &matched )) == NULL ) {
+                       char *matched_dn;
+                       struct berval **refs;
+
                        ldap_pvt_thread_mutex_unlock(&li->li_add_mutex);
-                       Debug( LDAP_DEBUG_TRACE, "parent does not exist\n", 0,
-                           0, 0 );
-                       send_ldap_result( conn, op, LDAP_NO_SUCH_OBJECT,
-                           matched, "" );
 
                        if ( matched != NULL ) {
-                               free( matched );
+                               matched_dn = ch_strdup( matched->e_dn );
+                               refs = is_entry_referral( matched )
+                                       ? get_entry_referrals( be, conn, op, matched )
+                                       : NULL;
+                               cache_return_entry_r( &li->li_cache, matched );
+
+                       } else {
+                               matched_dn = NULL;
+                               refs = default_referral;
+                       }
+
+                       Debug( LDAP_DEBUG_TRACE, "parent does not exist\n",
+                               0, 0, 0 );
+
+                       send_ldap_result( conn, op, LDAP_REFERRAL,
+                           matched_dn, NULL, refs, NULL );
+
+                       if( matched != NULL ) {
+                               ber_bvecfree( refs );
+                               free( matched_dn );
                        }
 
                        entry_free( e );
@@ -84,25 +103,59 @@ ldbm_back_add(
 
                free(pdn);
 
-               if ( matched != NULL ) {
-                       free( matched );
-               }
-
                if ( ! access_allowed( be, conn, op, p,
                        "children", NULL, ACL_WRITE ) )
                {
+                       /* free parent and writer lock */
+                       cache_return_entry_w( &li->li_cache, p ); 
+
                        Debug( LDAP_DEBUG_TRACE, "no access to parent\n", 0,
                            0, 0 );
                        send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
-                           "", "" );
+                           NULL, NULL, NULL, NULL );
+
+
+                       entry_free( e );
+                       return -1;
+               }
+
+               if ( is_entry_alias( p ) ) {
+                       /* parent is an alias, don't allow add */
 
                        /* free parent and writer lock */
-                       cache_return_entry_w( &li->li_cache, p ); 
+                       cache_return_entry_w( &li->li_cache, p );
+
+                       Debug( LDAP_DEBUG_TRACE, "parent is alias\n", 0,
+                           0, 0 );
+
+                       send_ldap_result( conn, op, LDAP_ALIAS_PROBLEM,
+                           NULL, NULL, NULL, NULL );
 
                        entry_free( e );
                        return -1;
                }
 
+               if ( is_entry_referral( p ) ) {
+                       /* parent is a referral, don't allow add */
+                       char *matched_dn = ch_strdup( p->e_dn );
+                       struct berval **refs = is_entry_referral( p )
+                               ? get_entry_referrals( be, conn, op, p )
+                               : NULL;
+
+                       /* free parent and writer lock */
+                       cache_return_entry_w( &li->li_cache, p );
+
+                       Debug( LDAP_DEBUG_TRACE, "parent is referral\n", 0,
+                           0, 0 );
+                       send_ldap_result( conn, op, LDAP_REFERRAL,
+                           matched_dn, NULL, refs, NULL );
+
+                       ber_bvecfree( refs );
+                       free( matched_dn );
+                       entry_free( e );
+                       return -1;
+               }
+
        } else {
                if(pdn != NULL) {
                        assert( *pdn == '\0' );
@@ -118,7 +171,7 @@ ldbm_back_add(
                                        0, 0 );
 
                        send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
-                           "", "" );
+                           NULL, NULL, NULL, NULL );
 
                        entry_free( e );
                        return -1;
@@ -160,11 +213,9 @@ ldbm_back_add(
                /* free the entry */
                entry_free( e );
 
-               if(rc > 0) {
-                       send_ldap_result( conn, op, LDAP_ALREADY_EXISTS, "", "" );
-               } else {
-                       send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
-               }
+               send_ldap_result( conn, op,
+                       rc > 0 ? LDAP_ALREADY_EXISTS : LDAP_OPERATIONS_ERROR,
+                       NULL, NULL, NULL, NULL );
 
                return( -1 );
        }
@@ -178,7 +229,8 @@ ldbm_back_add(
        if ( id2children_add( be, p, e ) != 0 ) {
                Debug( LDAP_DEBUG_TRACE, "id2children_add failed\n", 0,
                    0, 0 );
-               send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
+               send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+                       NULL, NULL, NULL, NULL );
 
                goto return_results;
        }
@@ -192,7 +244,8 @@ ldbm_back_add(
        if ( index_add_entry( be, e ) != 0 ) {
                Debug( LDAP_DEBUG_TRACE, "index_add_entry failed\n", 0,
                    0, 0 );
-               send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
+               send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+                       NULL, NULL, NULL, NULL );
 
                goto return_results;
        }
@@ -201,7 +254,8 @@ ldbm_back_add(
        if ( dn2id_add( be, e->e_ndn, e->e_id ) != 0 ) {
                Debug( LDAP_DEBUG_TRACE, "dn2id_add failed\n", 0,
                    0, 0 );
-               send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
+               send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+                       NULL, NULL, NULL, NULL );
 
                goto return_results;
        }
@@ -211,12 +265,14 @@ ldbm_back_add(
                Debug( LDAP_DEBUG_TRACE, "id2entry_add failed\n", 0,
                    0, 0 );
                (void) dn2id_delete( be, e->e_ndn );
-               send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
+               send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+                       NULL, NULL, NULL, NULL );
 
                goto return_results;
        }
 
-       send_ldap_result( conn, op, LDAP_SUCCESS, "", "" );
+       send_ldap_result( conn, op, LDAP_SUCCESS,
+               NULL, NULL, NULL, NULL );
        rc = 0;
 
 return_results:;
index 93efcf6ca45a9db797a3cf4fa02107b4df496643..470ba0a7e1236c95a47bb371d957a1016d60e42b 100644 (file)
@@ -1,13 +1,6 @@
 /*
- * Copyright (c) 1998 Will Ballantyne, ITSD, Government of BC
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that this notice is preserved and that due credit is given
- * to ITSD, Government of BC. The name of ITSD
- * may not be used to endorse or promote products derived from this
- * software without specific prior written permission. This software
- * is provided ``as is'' without express or implied warranty.
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
  */
 
 #include "portable.h"
 #include "back-ldbm.h"
 #include "proto-back-ldbm.h"
 
-/*
- * given an alias object, dereference it to its end point.
- * Entry returned has reader lock or is NULL.  Starting entry is not released.
- */
-Entry *derefAlias_r ( Backend     *be,
-                   Connection  *conn,
-                   Operation   *op,
-                   Entry       *e)
+
+static char* get_alias_dn(
+       Entry *e,
+       int *err,
+       char **errmsg );
+
+static char* new_superior(
+       char *dn,
+       char *oldSup,
+       char *newSup );
+
+static int dnlist_subordinate(
+       char** dnlist,
+       char *dn );
+
+Entry *deref_internal_r(
+       Backend*        be,
+       Entry*          alias,
+       char*           dn,
+       int*            err,
+       Entry**         matched,
+       char**          text )
+{
+       struct ldbminfo *li = (struct ldbminfo *) be->be_private;
+       Entry *entry;
+       Entry *sup;
+       unsigned depth;
+       char **dnlist;
+
+       assert( ( alias != NULL && dn == NULL ) || ( alias == NULL && dn != NULL ) );
+
+       *matched = NULL;
+       *err = LDAP_SUCCESS;
+       *text = NULL;
+
+       if( alias == NULL ) {
+               dn = ch_strdup( dn );
+               entry = dn2entry_r( be, dn, &sup );
+
+       } else {
+               dn = ch_strdup( alias->e_ndn );
+               entry = alias;
+               sup = NULL;
+       }
+
+       dnlist = NULL;
+       charray_add( &dnlist, dn );
+
+       for( depth=0 ; ; depth++ ) {
+               if( entry != NULL ) {
+                       Entry *newe;
+                       char *aliasDN;
+
+                       /* have entry, may be an alias */
+
+                       if( !is_entry_alias( entry ) ) {
+                               /* entry is not an alias */
+                               break;
+                       }
+
+                       /* entry is alias */
+                       if( depth > be->be_max_deref_depth ) {
+                               *matched = entry;
+                               entry = NULL;
+                               *err = LDAP_ALIAS_DEREF_PROBLEM;
+                               *text = "maximum deref depth exceeded";
+                               break;
+                       }
+
+                       /* deref entry */
+                       aliasDN = get_alias_dn( entry, err, text );
+
+                       if( aliasDN == NULL ) {
+                               *matched = entry;
+                               entry = NULL;
+                               break;
+                       }
+
+                       /* check if aliasDN is a subordinate of any DN in our list */
+                       if( dnlist_subordinate( dnlist, aliasDN ) ) {
+                               *matched = entry;
+                               entry = NULL;
+                               *err = LDAP_ALIAS_PROBLEM;
+                               *text = "circular alias";
+                               break;
+                       }
+
+                       /* attempt to dereference alias */
+
+                       newe = dn2entry_r( be, aliasDN, &sup );
+
+                       if( newe != NULL ) {
+                               free( dn );
+                               cache_return_entry_r(&li->li_cache, entry );
+                               entry = newe;
+                               dn = ch_strdup( entry->e_ndn );
+                               charray_add( &dnlist, dn );
+                               continue;
+
+                       }
+                       
+                       if ( sup != NULL ) {
+                               cache_return_entry_r(&li->li_cache, entry );
+                               entry = NULL;
+                               continue;
+                       }
+
+                       /* no newe and no superior, we're done */
+                       break;
+
+               } else if( sup != NULL ) {
+                       /* have superior, may be an alias */
+                       Entry *newe;
+                       Entry *newSup;
+                       char *supDN;
+                       char *aliasDN;
+
+                       if( !is_entry_alias( sup ) ) {
+                               /* entry is not an alias */
+                               *matched = sup;
+                               sup = NULL;
+                               break;
+                       }
+
+                       /* entry is alias */
+                       if( depth > be->be_max_deref_depth ) {
+                               *matched = sup;
+                               entry = NULL;
+                               *err = LDAP_ALIAS_DEREF_PROBLEM;
+                               *text = "maximum deref depth exceeded";
+                               break;
+                       }
+
+                       /* deref entry */
+                       supDN = get_alias_dn( sup, err, text );
+
+                       if( supDN == NULL ) {
+                               *matched = sup;
+                               break;
+                       }
+
+                       aliasDN = new_superior( dn, sup->e_ndn, supDN );
+
+                       if( aliasDN == NULL ) {
+                               free(aliasDN);
+                               *matched = sup;
+                               *err = LDAP_ALIAS_PROBLEM;
+                               *text = "superior alias problem";
+                               break;
+                       }
+
+                       /* check if aliasDN is a subordinate of any DN in our list */
+                       if( dnlist_subordinate( dnlist, aliasDN ) ) {
+                               free(aliasDN);
+                               *matched = entry;
+                               entry = NULL;
+                               *err = LDAP_ALIAS_PROBLEM;
+                               *text = "subordinate circular alias";
+                               break;
+                       }
+
+                       /* attempt to dereference alias */
+                       newe = dn2entry_r( be, aliasDN, &newSup );
+
+                       if( newe != NULL ) {
+                               free(aliasDN);
+                               free( dn );
+                               cache_return_entry_r(&li->li_cache, sup );
+                               entry = newe;
+                               dn = ch_strdup( entry->e_ndn );
+                               charray_add( &dnlist, dn );
+                               continue;
+
+                       }
+                       
+                       if ( newSup != NULL ) {
+                               free( dn );
+                               cache_return_entry_r(&li->li_cache, sup );
+                               sup = newSup;
+                               dn = aliasDN;
+                               continue;
+                       }
+
+                       break;
+
+               } else {
+                       /* no newe and no superior, we're done */
+                       break;
+               }
+       }
+
+       free( dn );
+       return entry;
+}
+
+
+static char* get_alias_dn(
+       Entry *e,
+       int *err,
+       char **errmsg )
+{      
+       Attribute *a = attr_find( e->e_attrs, "aliasedobjectname" );
+
+       if( a == NULL ) {
+               /*
+                * there was an aliasedobjectname defined but no data.
+                */
+               *err = LDAP_ALIAS_PROBLEM;
+               *errmsg = "alias missing aliasedObjectName attribute";
+               return NULL;
+       }
+
+       /* 
+        * aliasedObjectName should be SINGLE-VALUED with a single value. 
+        */                     
+       if ( a->a_vals[0] == NULL || a->a_vals[0]->bv_val != NULL ) {
+               /*
+                * there was an aliasedobjectname defined but no data.
+                */
+               *err = LDAP_ALIAS_PROBLEM;
+               *errmsg = "alias missing aliasedObjectName value";
+               return NULL;
+       }
+
+       if( a->a_vals[1] != NULL ) {
+               *err = LDAP_ALIAS_PROBLEM;
+               *errmsg = "alias has multivalued aliasedObjectName";
+               return NULL;
+       }
+
+       return a->a_vals[0]->bv_val;
+}
+
+char* new_superior(
+       char *dn,
+       char *oldSup,
+       char *newSup )
 {
-  struct ldbminfo *li = (struct ldbminfo *) be->be_private; /* to free cache entries */
-  Attribute *a;
-  int       depth;
-  char      *matched;
-  Entry     *origDN = e;
-
-  if (!e) return NULL;  /* be sure we have a starting entry */
-
-  Debug( LDAP_DEBUG_TRACE, "<= checking for alias for dn %s\n", e->e_dn, 0, 0 );
-
-  /*
-   * try to deref fully, up to a maximum depth.  If the max depth exceeded
-   * then send an error
-   */
-  for ( depth = 0;
-       ( ( a = attr_find( e->e_attrs, "aliasedobjectname" ) ) != NULL) &&
-         ( depth < be->be_maxDerefDepth );
-       ++depth) 
-  {
-
-    /* 
-     * make sure there is a defined aliasedobjectname.  
-     * can only have one value so just use first value (0) in the attr list. 
-     */            
-    if (a->a_vals[0] && a->a_vals[0]->bv_val) {
-      char *newDN, *oldDN;
-
-      Debug( LDAP_DEBUG_TRACE, "<= %s is an alias for %s\n", 
-            e->e_dn, a->a_vals[0]->bv_val, 0 );
-      newDN = ch_strdup (a->a_vals[0]->bv_val);
-      oldDN = ch_strdup (e->e_ndn);
-
-      /* 
-       * release past lock if not original
-       */
-      if ( (depth > 0) && e ) {
-          cache_return_entry_r(&li->li_cache, e);      
-      }
-
-      /* make sure new and old DN are not same to avoid loops */
-      dn_normalize_case (newDN);
-      if ( strcmp (newDN, oldDN) == 0 ) {
-       
-       Debug( LDAP_DEBUG_TRACE, 
-              "<= %s alias is same as current %s\n", 
-              oldDN, newDN, 0 );
-       send_ldap_result( conn, op, LDAP_ALIAS_DEREF_PROBLEM, "",
-                         "Circular alias" );
-       free (newDN);
-       free (oldDN);
-       break;
-      }
-
-      /* make sure new and original are not same to avoid deadlocks */
-      if ( strcmp (newDN, origDN->e_ndn) == 0 ) {
-       Debug( LDAP_DEBUG_TRACE, 
-              "<= %s alias is same as original %s\n", 
-              oldDN, origDN->e_ndn, 0 );
-       send_ldap_result( conn, op, LDAP_ALIAS_DEREF_PROBLEM, "",
-                         "Circular alias" );
-       free (newDN);
-       free (oldDN);
-       break;
-      }
-
-      /*
-       * ok, so what happens if there is an alias in the DN of a dereferenced
-       * alias object?  
-       */
-      if ( (e = dn2entry_r( be, newDN, &matched )) == NULL ) {
-
-       /* could not deref return error  */
-       Debug( LDAP_DEBUG_TRACE, 
-              "<= %s is a dangling alias to %s\n", 
-              oldDN, newDN, 0 );
-       send_ldap_result( conn, op, LDAP_ALIAS_DEREF_PROBLEM, "",
-                         "Dangling Alias" );
-
-       if (matched != NULL) free(matched);
-       free (newDN);
-       free (oldDN);
-       break;
-      }
-
-      free (newDN);
-      free (oldDN);
-    }
-    else {
-      /*
-       * there was an aliasedobjectname defined but no data.
-       * this can't happen, right?
-       */
-       Debug( LDAP_DEBUG_TRACE, 
-              "<= %s has no data in aliasedobjectname attribute\n", 
-              (e && e->e_dn) ? e->e_dn : "(null)", 0, 0 );
-       send_ldap_result( conn, op, LDAP_ALIAS_PROBLEM, "",
-                         "Alias missing aliasedobjectname" );
-       break;
-    }
-  }
-
-  /*
-   * warn if we pulled out due to exceeding the maximum deref depth
-   */
-  if ( depth >= be->be_maxDerefDepth ) {
-    Debug( LDAP_DEBUG_TRACE, 
-          "<= deref(\"%s\") exceeded maximum deref depth (%d) at \"%s\"\n", 
-          origDN->e_dn ? origDN->e_dn : "(null)", 
-          be->be_maxDerefDepth, 
-          (e && e->e_ndn) ? e->e_ndn : "(null)");
-    send_ldap_result( conn, op, LDAP_ALIAS_DEREF_PROBLEM, "",
-                       "Maximum alias dereference depth exceeded" );
-  }
-
-  return e;
+       char *newDN;
+       size_t dnlen, olen, nlen;
+       assert( dn && oldSup && newSup );
+
+       dnlen = strlen( dn );
+       olen = strlen( oldSup );
+       nlen = strlen( newSup );
+
+       newDN = ch_malloc( dnlen - olen + nlen + 1 );
+
+       memcpy( newDN, dn, dnlen - olen );
+       memcpy( &newDN[dnlen - olen], newSup, nlen );
+       newDN[dnlen - olen + nlen] = '\0';
+
+       return newDN;
 }
 
-/*
- * given a DN fully deref it and return the real DN or original DN if it fails
- * This involves finding the last matched part then reconstructing forward
- * e.g. 
- * ou=MyOU,o=MyAliasedOrg,c=MyCountry where o=MyAliasedOrg is an alias for o=MyOrg
- * loop starts with newDN = ou=MyOU,o=MyAliasedOrg,c=MyCountry
- *   dn2entry_r on newDN gives null entry and o=MyAliasedOrg,c=MyCountry matched
- *   dn2entry_r on matched gives o=MyAliasedOrg,c=MyCountry entry
- *   remainder is ou=MyOU
- *   dereferencing o=MyAliasedOrg,c=MyCountry yields entry o=MyOrg,c=MyCountry
- *   release lock on o=MyAliasedOrg,c=MyCountry entry
- *   reconstructed dn is ou=MyOU,o=MyOrg,c=MyCountry
- *   release lock on o=MyOrg,c=MyCountry entry
- */
-char *derefDN ( Backend     *be,
-                Connection  *conn,
-                Operation   *op,
-                char        *dn
-)
+static int dnlist_subordinate(
+       char** dnlist,
+       char *dn )
 {
-  struct ldbminfo *li = (struct ldbminfo *) be->be_private;
-  char         *matched = 0;
-  char         *newDN = NULL;
-  int  depth, i;
-  Entry        *eMatched;
-  Entry        *eDeref;
-  Entry         *eNew;
-  
-  if (!dn) return NULL; 
-
-  Debug( LDAP_DEBUG_TRACE, 
-        "<= dereferencing dn: \"%s\"\n", 
-        dn, 0, 0 );
-  
-  newDN = ch_strdup ( dn );
-
-  /* while we don't have a matched dn, deref the DN */
-  for ( depth = 0;
-       ( (eMatched = dn2entry_r( be, newDN, &matched )) == NULL) &&
-         (depth < be->be_maxDerefDepth);
-       ++depth ) {
-    
-    if ((matched != NULL) && *matched) {       
-      char *submatch;
-   
-      /* 
-       * make sure there actually is an entry for the matched part 
-       */
-      if ( (eMatched = dn2entry_r( be, matched, &submatch )) != NULL) {
-       char  *remainder; /* part before the aliased part */
-       int  rlen = strlen(newDN) - strlen(matched);
-       
-       Debug( LDAP_DEBUG_TRACE, "<= matched %s\n", matched, 0, 0 );
-       
-       remainder = ch_malloc (rlen + 1);
-       strncpy ( remainder, newDN, rlen );
-       remainder[rlen] = '\0';
-       
-       Debug( LDAP_DEBUG_TRACE, "<= remainder %s\n", remainder, 0, 0 );
-       
-       if ((eNew = derefAlias_r( be, conn, op, eMatched )) == NULL) {
-         free (matched);
-         matched = NULL;
-         free (newDN);
-         newDN = NULL;
-         free (remainder);
-         remainder = NULL;
-         
-         cache_return_entry_r(&li->li_cache, eMatched);
-         eMatched = NULL;
-         break; /*  no associated entry, dont deref */
-       }
-       else {
-
-         Debug( LDAP_DEBUG_TRACE, "<= l&g we have %s vs %s \n", matched, eNew->e_dn, 0 );
-
-         i = strcasecmp (matched, eNew->e_dn);
-          /* free reader lock */
-          cache_return_entry_r(&li->li_cache, eNew);
-
-         free (matched);
-         matched = NULL;
-
-         if (! i) {
-           /* newDN same as old so not an alias, no need to go further */
-           free (newDN);
-           newDN = NULL;
-           free (remainder);
-
-           cache_return_entry_r(&li->li_cache, eMatched);
-           eMatched = NULL;
-           break;
-         }
-
-         /* 
-          * we have dereferenced the aliased part so put
-          * the new dn together
-          */
-         free (newDN);
-         newDN = ch_malloc (strlen(eMatched->e_dn) + rlen + 1);
-         strcpy (newDN, remainder);
-         strcat (newDN, eMatched->e_dn);
-         Debug( LDAP_DEBUG_TRACE, "<= expanded to %s\n", newDN, 0, 0 );
-
-         free (remainder);
+       int i;
+       assert( dnlist );
+
+       for( i = 0; dnlist[i] != NULL; i++ ) {
+               if( dn_issuffix( dnlist[i], dn ) ) {
+                       return 1;
+               }
        }
-       /* free reader lock */
-       cache_return_entry_r(&li->li_cache, eMatched);
-      }
-      else {
-       if(submatch != NULL) free(submatch);
-       break; /* there was no entry for the matched part */
-      }
-    }
-    else {
-      break; /* there was no matched part */
-    }
-  }
-  
-  /* release lock if a match terminated the loop, there should be no
-   * outstanding locks at this point
-   */
-  if(eMatched != NULL) {
-    /* free reader lock */
-    cache_return_entry_r(&li->li_cache, eMatched);
-  }
-
-  /*
-   * the final part of the DN might be an alias so try to dereference it.
-   * e.g. if we had started with dn = o=MyAliasedOrg,c=MyCountry the dn would match
-   * and the above loop complete but we would still be left with an aliased DN.
-   */
-  if (newDN != NULL) {
-    if ( (eNew = dn2entry_r( be, newDN, &matched )) != NULL) {
-      if ((eDeref = derefAlias_r( be, conn, op, eNew )) != NULL) {
-        free (newDN);
-        newDN = ch_strdup (eDeref->e_dn);
-        /* free reader lock */
-        cache_return_entry_r(&li->li_cache, eDeref);
-      }
-      /* free reader lock */
-      cache_return_entry_r(&li->li_cache, eNew);
-    }
-  }
-  if (matched != NULL) free(matched);
-  
-  /*
-   * warn if we exceeded the max depth as the resulting DN may not be dereferenced
-   */
-  if (depth >= be->be_maxDerefDepth) {
-    if (newDN) {
-      Debug( LDAP_DEBUG_TRACE, 
-            "<= max deref depth exceeded in derefDN for \"%s\", result \"%s\"\n", 
-            dn, newDN, 0 );
-      free (newDN);
-      newDN = NULL;
-    }
-    else {
-      Debug( LDAP_DEBUG_TRACE, 
-            "<= max deref depth exceeded in derefDN for \"%s\", result NULL\n", 
-            dn, 0, 0 );
-    }
-    send_ldap_result( conn, op, LDAP_ALIAS_DEREF_PROBLEM, "",
-                     "Maximum alias dereference depth exceeded for base" );
-  }
-
-  if (newDN == NULL) {
-    newDN = ch_strdup ( dn );
-  }
-  
-  Debug( LDAP_DEBUG_TRACE, "<= returning deref DN of \"%s\"\n", newDN, 0, 0 ); 
-
-  return newDN;
+
+       return 0;
 }
+
index 1821c9b4cc5f25ec71ee4fb53d75f1e08b520b13..dad6b9e2ac7127bc02a2b481863ad827c031cdbf 100644 (file)
@@ -74,7 +74,7 @@ ldbm_back_bind(
        Entry           *e;
        Attribute       *a;
        int             rc;
-       char            *matched;
+       Entry           *matched;
 #ifdef HAVE_KERBEROS
        char            krbname[MAX_K_NAME_SZ + 1];
        AUTH_DAT        ad;
@@ -86,39 +86,57 @@ ldbm_back_bind(
 
        /* get entry with reader lock */
        if ( (e = dn2entry_r( be, dn, &matched )) == NULL ) {
+               char *matched_dn = NULL;
+               struct berval **refs = NULL;
+
+               if( matched != NULL ) {
+                       matched_dn = ch_strdup( matched->e_dn );
+
+                       refs = is_entry_referral( matched )
+                               ? get_entry_referrals( be, conn, op, matched )
+                               : NULL;
+
+                       cache_return_entry_r( &li->li_cache, matched );
+               } else {
+                       refs = default_referral;
+               }
+
                /* allow noauth binds */
                rc = 1;
                if ( method == LDAP_AUTH_SIMPLE ) {
                        if( cred->bv_len == 0 ) {
                                /* SUCCESS */
-                               send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL );
+                               send_ldap_result( conn, op, LDAP_SUCCESS,
+                                       NULL, NULL, NULL, NULL );
 
                        } else if ( be_isroot_pw( be, dn, cred ) ) {
                                *edn = ch_strdup( be_root_dn( be ) );
                                rc = 0; /* front end will send result */
 
                        } else {
-                               send_ldap_result( conn, op,
-                                       LDAP_NO_SUCH_OBJECT, matched, NULL );
+                               send_ldap_result( conn, op, LDAP_REFERRAL,
+                                       matched_dn, NULL, refs, NULL );
                        }
 
                } else if ( method == LDAP_AUTH_SASL ) {
                        if( mech != NULL && strcasecmp(mech,"DIGEST-MD5") == 0 ) {
                                /* insert DIGEST calls here */
-                               send_ldap_result( conn, op,
-                                       LDAP_AUTH_METHOD_NOT_SUPPORTED, NULL, NULL );
+                               send_ldap_result( conn, op, LDAP_AUTH_METHOD_NOT_SUPPORTED,
+                                       NULL, NULL, NULL, NULL );
                                
                        } else {
-                               send_ldap_result( conn, op,
-                                       LDAP_AUTH_METHOD_NOT_SUPPORTED, NULL, NULL );
+                               send_ldap_result( conn, op, LDAP_AUTH_METHOD_NOT_SUPPORTED,
+                                       NULL, NULL, NULL, NULL );
                        }
 
                } else {
-                       send_ldap_result( conn, op, LDAP_NO_SUCH_OBJECT, matched, NULL );
+                       send_ldap_result( conn, op, LDAP_REFERRAL,
+                               matched_dn, NULL, refs, NULL );
                }
 
                if ( matched != NULL ) {
-                       free( matched );
+                       ber_bvecfree( refs );
+                       free( matched_dn );
                }
                return( rc );
        }
@@ -130,7 +148,37 @@ ldbm_back_bind(
        if ( ! access_allowed( be, conn, op, e,
                "entry", NULL, ACL_AUTH ) )
        {
-               send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS, "", "" );
+               send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
+                       NULL, NULL, NULL, NULL );
+               rc = 1;
+               goto return_results;
+       }
+
+       if ( is_entry_alias( e ) ) {
+               /* entry is an alias, don't allow bind */
+               Debug( LDAP_DEBUG_TRACE, "entry is alias\n", 0,
+                   0, 0 );
+
+               send_ldap_result( conn, op, LDAP_ALIAS_PROBLEM,
+                   NULL, NULL, NULL, NULL );
+
+               rc = 1;
+               goto return_results;
+       }
+
+       if ( is_entry_referral( e ) ) {
+               /* entry is a referral, don't allow bind */
+               struct berval **refs = get_entry_referrals( be,
+                       conn, op, e );
+
+               Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0,
+                   0, 0 );
+
+               send_ldap_result( conn, op, LDAP_REFERRAL,
+                   e->e_dn, NULL, refs, NULL );
+
+               ber_bvecfree( refs );
+
                rc = 1;
                goto return_results;
        }
@@ -138,7 +186,8 @@ ldbm_back_bind(
        switch ( method ) {
        case LDAP_AUTH_SIMPLE:
                if ( cred->bv_len == 0 ) {
-                       send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL );
+                       send_ldap_result( conn, op, LDAP_SUCCESS,
+                               NULL, NULL, NULL, NULL );
 
                        /* stop front end from sending result */
                        rc = 1;
@@ -157,14 +206,15 @@ ldbm_back_bind(
                if ( ! access_allowed( be, conn, op, e,
                        "userpassword", NULL, ACL_AUTH ) )
                {
-                       send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS, "", "" );
+                       send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
+                               NULL, NULL, NULL, NULL );
                        rc = 1;
                        goto return_results;
                }
 
                if ( (a = attr_find( e->e_attrs, "userpassword" )) == NULL ) {
                        send_ldap_result( conn, op, LDAP_INAPPROPRIATE_AUTH,
-                           NULL, NULL );
+                           NULL, NULL, NULL, NULL );
 
                        /* stop front end from sending result */
                        rc = 1;
@@ -174,7 +224,7 @@ ldbm_back_bind(
                if ( crypted_value_find( a->a_vals, cred, a->a_syntax, 0, cred ) != 0 )
                {
                        send_ldap_result( conn, op, LDAP_INVALID_CREDENTIALS,
-                               NULL, NULL );
+                               NULL, NULL, NULL, NULL );
                        /* stop front end from sending result */
                        rc = 1;
                        goto return_results;
@@ -188,14 +238,15 @@ ldbm_back_bind(
                if ( ! access_allowed( be, conn, op, e,
                        "krbname", NULL, ACL_AUTH ) )
                {
-                       send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS, "", "" );
+                       send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
+                               NULL, NULL, NULL, NULL );
                        rc = 1;
                        goto return_results;
                }
 
                if ( krbv4_ldap_auth( be, cred, &ad ) != LDAP_SUCCESS ) {
                        send_ldap_result( conn, op, LDAP_INVALID_CREDENTIALS,
-                           NULL, NULL );
+                           NULL, NULL, NULL, NULL );
                        rc = 1;
                        goto return_results;
                }
@@ -203,7 +254,8 @@ ldbm_back_bind(
                if ( ! access_allowed( be, conn, op, e,
                        "krbname", NULL, ACL_AUTH ) )
                {
-                       send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS, "", "" );
+                       send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
+                               NULL, NULL, NULL, NULL );
                        rc = 1;
                        goto return_results;
                }
@@ -221,7 +273,7 @@ ldbm_back_bind(
                                break;
                        }
                        send_ldap_result( conn, op, LDAP_INAPPROPRIATE_AUTH,
-                           NULL, NULL );
+                           NULL, NULL, NULL, NULL );
                        rc = 1;
                        goto return_results;
 
@@ -233,7 +285,8 @@ ldbm_back_bind(
 
                        if ( value_find( a->a_vals, &krbval, a->a_syntax, 3 ) != 0 ) {
                                send_ldap_result( conn, op,
-                                   LDAP_INVALID_CREDENTIALS, NULL, NULL );
+                                   LDAP_INVALID_CREDENTIALS,
+                                       NULL, NULL, NULL, NULL );
                                rc = 1;
                                goto return_results;
                        }
@@ -242,7 +295,8 @@ ldbm_back_bind(
                break;
 
        case LDAP_AUTH_KRBV42:
-               send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL );
+               send_ldap_result( conn, op, LDAP_SUCCESS,
+                       NULL, NULL, NULL, NULL );
                /* stop front end from sending result */
                rc = 1;
                goto return_results;
@@ -253,7 +307,7 @@ ldbm_back_bind(
 
        default:
                send_ldap_result( conn, op, LDAP_STRONG_AUTH_NOT_SUPPORTED,
-                   NULL, "auth method not supported" );
+                   NULL, "auth method not supported", NULL, NULL );
                rc = 1;
                goto return_results;
        }
index fc6e17144419ad430ae5ac6ac9e3b9f5e31e4d36..acc5571e5addbdac4cc7d7ae9e0c5bf0c40406c4 100644 (file)
@@ -21,38 +21,77 @@ ldbm_back_compare(
 )
 {
        struct ldbminfo *li = (struct ldbminfo *) be->be_private;
-       char            *matched;
+       Entry           *matched;
        Entry           *e;
        Attribute       *a;
        int             rc;
+       int             manageDSAit = get_manageDSAit( op );
 
        /* get entry with reader lock */
        if ( (e = dn2entry_r( be, dn, &matched )) == NULL ) {
-               send_ldap_result( conn, op, LDAP_NO_SUCH_OBJECT, matched, "" );
+               char *matched_dn = NULL;
+               struct berval **refs = NULL;
+
+               if ( matched != NULL ) {
+                       matched_dn = ch_strdup( matched->e_dn );
+                       refs = is_entry_referral( matched )
+                               ? get_entry_referrals( be, conn, op, matched )
+                               : NULL;
+                       cache_return_entry_r( &li->li_cache, matched );
+               } else {
+                       refs = default_referral;
+               }
+
+               send_ldap_result( conn, op, LDAP_REFERRAL,
+                       matched_dn, NULL, refs, NULL );
+
+               if( matched != NULL ) {
+                       ber_bvecfree( refs );
+                       free( matched_dn );
+               }
 
-               if(matched == NULL) free(matched);
                return( 1 );
        }
 
-       /* check for deleted */
+       if (!manageDSAit && is_entry_referral( e ) ) {
+               /* entry is a referral, don't allow add */
+               struct berval **refs = get_entry_referrals( be,
+                       conn, op, e );
+
+               Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0,
+                   0, 0 );
+
+               send_ldap_result( conn, op, LDAP_REFERRAL,
+                   e->e_dn, NULL, refs, NULL );
+
+               ber_bvecfree( refs );
+
+               rc = 1;
+               goto return_results;
+       }
+
        if ( ! access_allowed( be, conn, op, e,
                ava->ava_type, &ava->ava_value, ACL_COMPARE ) )
        {
-               send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS, "", "" );
+               send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
+                       NULL, NULL, NULL, NULL );
                rc = 1;
                goto return_results;
        }
 
        if ( (a = attr_find( e->e_attrs, ava->ava_type )) == NULL ) {
-               send_ldap_result( conn, op, LDAP_NO_SUCH_ATTRIBUTE, "", "" );
+               send_ldap_result( conn, op, LDAP_NO_SUCH_ATTRIBUTE,
+                       NULL, NULL, NULL, NULL );
                rc = 1;
                goto return_results;
        }
 
        if ( value_find( a->a_vals, &ava->ava_value, a->a_syntax, 1 ) == 0 ) 
-               send_ldap_result( conn, op, LDAP_COMPARE_TRUE, "", "" );
+               send_ldap_result( conn, op, LDAP_COMPARE_TRUE,
+                       NULL, NULL, NULL, NULL );
        else
-               send_ldap_result( conn, op, LDAP_COMPARE_FALSE, "", "" );
+               send_ldap_result( conn, op, LDAP_COMPARE_FALSE,
+                       NULL, NULL, NULL, NULL );
 
        rc = 0;
 
index d0be72d6c62fcd9578bcae1c6f607f82220dd43c..53bdd22f7ce89163521825ce43b44903e1bece9a 100644 (file)
@@ -20,33 +20,42 @@ ldbm_back_delete(
 )
 {
        struct ldbminfo *li = (struct ldbminfo *) be->be_private;
-       char    *matched = NULL;
+       Entry   *matched = NULL;
        char    *pdn = NULL;
        Entry   *e, *p = NULL;
        int rootlock = 0;
        int     rc = -1;
+       int             manageDSAit = get_manageDSAit( op );
 
        Debug(LDAP_DEBUG_ARGS, "==> ldbm_back_delete: %s\n", dn, 0, 0);
 
        /* get entry with writer lock */
        if ( (e = dn2entry_w( be, dn, &matched )) == NULL ) {
+               char *matched_dn = NULL;
+               struct berval **refs = NULL;
+
                Debug(LDAP_DEBUG_ARGS, "<=- ldbm_back_delete: no such object %s\n",
                        dn, 0, 0);
-               send_ldap_result( conn, op, LDAP_NO_SUCH_OBJECT, matched, "" );
+
                if ( matched != NULL ) {
-                       free( matched );
+                       matched_dn = ch_strdup( matched->e_dn );
+                       refs = is_entry_referral( matched )
+                               ? get_entry_referrals( be, conn, op, matched )
+                               : NULL;
+                       cache_return_entry_r( &li->li_cache, matched );
+               } else {
+                       refs = default_referral;
                }
-               return( -1 );
-       }
 
-       /* check for deleted */
+               send_ldap_result( conn, op, LDAP_REFERRAL,
+                       matched_dn, NULL, refs, NULL );
 
-       if ( has_children( be, e ) ) {
-               Debug(LDAP_DEBUG_ARGS, "<=- ldbm_back_delete: non leaf %s\n",
-                       dn, 0, 0);
-               send_ldap_result( conn, op, LDAP_NOT_ALLOWED_ON_NONLEAF, "",
-                   "" );
-               goto return_results;
+               if ( matched != NULL ) {
+                       ber_bvecfree( refs );
+                       free( matched_dn );
+               }
+
+               return( -1 );
        }
 
 #ifdef SLAPD_CHILD_MODIFICATION_WITH_ENTRY_ACL
@@ -56,11 +65,39 @@ ldbm_back_delete(
                Debug(LDAP_DEBUG_ARGS,
                        "<=- ldbm_back_delete: insufficient access %s\n",
                        dn, 0, 0);
-               send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS, "", "" );
+               send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
+                       NULL, NULL, NULL, NULL );
                goto return_results;
        }
 #endif
 
+    if ( !manageDSAit && is_entry_referral( e ) ) {
+               /* parent is a referral, don't allow add */
+               /* parent is an alias, don't allow add */
+               struct berval **refs = get_entry_referrals( be,
+                       conn, op, e );
+
+               Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0,
+                   0, 0 );
+
+               send_ldap_result( conn, op, LDAP_REFERRAL,
+                   e->e_dn, NULL, refs, NULL );
+
+               ber_bvecfree( refs );
+
+               rc = 1;
+               goto return_results;
+       }
+
+
+       if ( has_children( be, e ) ) {
+               Debug(LDAP_DEBUG_ARGS, "<=- ldbm_back_delete: non leaf %s\n",
+                       dn, 0, 0);
+               send_ldap_result( conn, op, LDAP_NOT_ALLOWED_ON_NONLEAF,
+                       NULL, NULL, NULL, NULL );
+               goto return_results;
+       }
+
        /* delete from parent's id2children entry */
        if( (pdn = dn_parent( be, e->e_ndn )) != NULL ) {
                if( (p = dn2entry_w( be, pdn, &matched )) == NULL) {
@@ -68,7 +105,7 @@ ldbm_back_delete(
                                "<=- ldbm_back_delete: parent does not exist\n",
                                0, 0, 0);
                        send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
-                               "", "");
+                               NULL, NULL, NULL, NULL );
                        goto return_results;
                }
 
@@ -80,7 +117,7 @@ ldbm_back_delete(
                                "<=- ldbm_back_delete: no access to parent\n", 0,
                                0, 0 );
                        send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
-                               "", "" );
+                               NULL, NULL, NULL, NULL );
                        goto return_results;
                }
 
@@ -91,7 +128,7 @@ ldbm_back_delete(
                                "<=- ldbm_back_delete: no parent & not root\n",
                                0, 0, 0);
                        send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
-                               "", "");
+                               NULL, NULL, NULL, NULL );
                        goto return_results;
                }
 
@@ -103,7 +140,8 @@ ldbm_back_delete(
                Debug(LDAP_DEBUG_ARGS,
                        "<=- ldbm_back_delete: operations error %s\n",
                        dn, 0, 0);
-               send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "","" );
+               send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+                       NULL, NULL, NULL, NULL );
                goto return_results;
        }
 
@@ -112,7 +150,8 @@ ldbm_back_delete(
                Debug(LDAP_DEBUG_ARGS,
                        "<=- ldbm_back_delete: operations error %s\n",
                        dn, 0, 0);
-               send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
+               send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+                       NULL, NULL, NULL, NULL );
                goto return_results;
        }
 
@@ -121,11 +160,13 @@ ldbm_back_delete(
                Debug(LDAP_DEBUG_ARGS,
                        "<=- ldbm_back_delete: operations error %s\n",
                        dn, 0, 0);
-               send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
+               send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+                       NULL, NULL, NULL, NULL );
                goto return_results;
        }
 
-       send_ldap_result( conn, op, LDAP_SUCCESS, "", "" );
+       send_ldap_result( conn, op, LDAP_SUCCESS,
+               NULL, NULL, NULL, NULL );
        rc = 0;
 
 return_results:;
index a29557e11db5e22264917eee85bb35369b4b5574..c361418e3c7f12cd6ae55a444e1cbb6d5578fcef 100644 (file)
@@ -156,7 +156,7 @@ Entry *
 dn2entry_rw(
     Backend    *be,
     char       *dn,
-    char       **matched,
+    Entry      **matched,
     int         rw
 )
 {
@@ -168,7 +168,10 @@ dn2entry_rw(
        Debug(LDAP_DEBUG_TRACE, "dn2entry_%s: dn: \"%s\"\n",
                rw ? "w" : "r", dn, 0);
 
-       *matched = NULL;
+       if( matched != NULL ) {
+               /* caller cares about match */
+               *matched = NULL;
+       }
 
        if ( (id = dn2id( be, dn )) != NOID &&
                (e = id2entry_rw( be, id, rw )) != NULL )
@@ -184,26 +187,19 @@ dn2entry_rw(
                /* treat as if NOID was found */
        }
 
-       /* stop when we get to the suffix */
-       if ( be_issuffix( be, dn ) ) {
-               return( NULL );
-       }
+       /* caller doesn't care about match */
+       if( matched == NULL ) return NULL;
 
        /* entry does not exist - see how much of the dn does exist */
+       /* dn_parent checks returns NULL if dn is suffix */
        if ( (pdn = dn_parent( be, dn )) != NULL ) {
                /* get entry with reader lock */
                if ( (e = dn2entry_r( be, pdn, matched )) != NULL ) {
-                       if(*matched != NULL) {
-                               free(*matched);
-                       }
-                       *matched = pdn;
-                       /* free entry with reader lock */
-                       cache_return_entry_r( &li->li_cache, e );
-               } else {
-                       free( pdn );
+                       *matched = e;
                }
+               free( pdn );
        }
 
-       return( NULL );
+       return NULL;
 }
 
index 652892c82809fa182c6a5287e96eec7ef91efeed..c890cc49e169b918f6bc91f37f638dec90571a3c 100644 (file)
@@ -26,24 +26,24 @@ ldbm_back_group(
        char    *groupattrName
 )
 {
-        struct ldbminfo *li = (struct ldbminfo *) be->be_private;    
-        Entry        *e;
-        char        *matched;
-        Attribute   *objectClass;
-        Attribute   *member;
-        int          rc;
-
-       Debug( LDAP_DEBUG_TRACE,
+       struct ldbminfo *li = (struct ldbminfo *) be->be_private;    
+       Entry        *e;
+       int          rc = 1;
+
+       Attribute   *attr;
+       struct berval bv;
+
+       Debug( LDAP_DEBUG_ARGS,
                "=> ldbm_back_group: gr dn: \"%s\"\n",
                gr_ndn, 0, 0 ); 
-       Debug( LDAP_DEBUG_TRACE,
+       Debug( LDAP_DEBUG_ARGS,
                "=> ldbm_back_group: op dn: \"%s\"\n",
                op_ndn, 0, 0 ); 
-       Debug( LDAP_DEBUG_TRACE,
+       Debug( LDAP_DEBUG_ARGS,
                "=> ldbm_back_group: objectClass: \"%s\" attrName: \"%s\"\n", 
                objectclassValue, groupattrName, 0 ); 
 
-       Debug( LDAP_DEBUG_TRACE,
+       Debug( LDAP_DEBUG_ARGS,
                "=> ldbm_back_group: tr dn: \"%s\"\n",
                target->e_ndn, 0, 0 ); 
 
@@ -52,73 +52,99 @@ ldbm_back_group(
                e = target;
                Debug( LDAP_DEBUG_ARGS,
                        "=> ldbm_back_group: target is group: \"%s\"\n",
-                       gr_ndn, 0, 0 ); 
+                       gr_ndn, 0, 0 );
+
        } else {
                /* can we find group entry with reader lock */
-               if ((e = dn2entry_r(be, gr_ndn, &matched )) == NULL) {
-                       Debug( LDAP_DEBUG_TRACE,
-                               "=> ldbm_back_group: cannot find group: \"%s\" matched: \"%s\"\n",
-                                       gr_ndn, (matched ? matched : ""), 0 ); 
-                       if (matched != NULL)
-                               free(matched);
+               if ((e = dn2entry_r(be, gr_ndn, NULL )) == NULL) {
+                       Debug( LDAP_DEBUG_ACL,
+                               "=> ldbm_back_group: cannot find group: \"%s\"\n",
+                                       gr_ndn, 0, 0 ); 
                        return( 1 );
                }
-               Debug( LDAP_DEBUG_ARGS,
+               
+               Debug( LDAP_DEBUG_ACL,
                        "=> ldbm_back_group: found group: \"%s\"\n",
                        gr_ndn, 0, 0 ); 
-        }
+    }
 
+       /* find it's objectClass and member attribute values
+        * make sure this is a group entry
+        * finally test if we can find op_dn in the member attribute value list *
+        */
+        
+       rc = 1;
+        
+       if ((attr = attr_find(e->e_attrs, "objectclass")) == NULL)  {
+               Debug( LDAP_DEBUG_ACL,
+                       "<= ldbm_back_group: failed to find objectClass\n", 0, 0, 0 );
+               goto return_results;
+       }
+       
+       bv.bv_val = "ALIAS";
+       bv.bv_len = sizeof("ALIAS")-1;
+
+       if ( value_find(attr->a_vals, &bv, attr->a_syntax, 1) == 0) {
+               Debug( LDAP_DEBUG_ACL,
+                       "<= ldbm_back_group: group is an alias\n", 0, 0, 0 );
+               goto return_results;
+       }
 
-        /* check for deleted */
+       bv.bv_val = "REFERRAL";
+       bv.bv_len = sizeof("REFERRAL")-1;
 
-        /* find it's objectClass and member attribute values
-         * make sure this is a group entry
-         * finally test if we can find op_dn in the member attribute value list *
-         */
-        
-        rc = 1;
-        if ((objectClass = attr_find(e->e_attrs, "objectclass")) == NULL)  {
-            Debug( LDAP_DEBUG_TRACE, "<= ldbm_back_group: failed to find objectClass\n", 0, 0, 0 ); 
-        }
-        else if ((member = attr_find(e->e_attrs, groupattrName)) == NULL) {
-            Debug( LDAP_DEBUG_TRACE, "<= ldbm_back_group: failed to find %s\n", groupattrName, 0, 0 ); 
-        }
-        else {
-            struct berval bvObjectClass;
-            struct berval bvMembers;
-
-            Debug( LDAP_DEBUG_ARGS, "<= ldbm_back_group: found objectClass and %s\n", groupattrName, 0, 0 ); 
-
-            bvObjectClass.bv_val = objectclassValue;
-            bvObjectClass.bv_len = strlen( bvObjectClass.bv_val );         
-
-            bvMembers.bv_val = op_ndn;
-            bvMembers.bv_len = strlen( op_ndn );         
-
-            if (value_find(objectClass->a_vals, &bvObjectClass, SYNTAX_CIS, 1) != 0) {
-                Debug( LDAP_DEBUG_TRACE,
-                                       "<= ldbm_back_group: failed to find %s in objectClass\n", 
-                        objectclassValue, 0, 0 ); 
-            }
-            else if (value_find(member->a_vals, &bvMembers, SYNTAX_CIS, 1) != 0) {
-                Debug( LDAP_DEBUG_ACL,
-                                       "<= ldbm_back_group: \"%s\" not in \"%s\": %s\n", 
-                                       op_ndn, gr_ndn, groupattrName ); 
-            }
-            else {
-                               Debug( LDAP_DEBUG_ACL,
-                                       "<= ldbm_back_group: \"%s\" is in \"%s\": %s\n", 
-                                       op_ndn, gr_ndn, groupattrName ); 
-                rc = 0;
-            }
-        }
+       if ( value_find(attr->a_vals, &bv, attr->a_syntax, 1) == 0) {
+               Debug( LDAP_DEBUG_ACL,
+                       "<= ldbm_back_group: group is a referral\n",
+                       0, 0, 0 );
+               goto return_results;
+       }
+
+       bv.bv_val = objectclassValue;
+       bv.bv_len = strlen( bv.bv_val );         
+
+       if (value_find(attr->a_vals, &bv, attr->a_syntax, 1) != 0) {
+               Debug( LDAP_DEBUG_ACL,
+                       "<= ldbm_back_group: failed to find %s in objectClass\n", 
+                               objectclassValue, 0, 0 ); 
+               goto return_results;
+       }
+
+       if ((attr = attr_find(e->e_attrs, groupattrName)) == NULL) {
+               Debug( LDAP_DEBUG_ACL,
+                       "<= ldbm_back_group: failed to find %s\n",
+                       groupattrName, 0, 0 ); 
+               goto return_results;
+       }
+
+       Debug( LDAP_DEBUG_ACL,
+               "<= ldbm_back_group: found objectClass %s and %s\n",
+               objectclassValue, groupattrName, 0 ); 
+
+       bv.bv_val = op_ndn;
+       bv.bv_len = strlen( op_ndn );         
+
+       if( value_find( attr->a_vals, &bv, attr->a_syntax, 1) != 0 )
+       {
+               Debug( LDAP_DEBUG_ACL,
+                       "<= ldbm_back_group: \"%s\" not in \"%s\": %s\n", 
+                       op_ndn, gr_ndn, groupattrName ); 
+               goto return_results;
+       }
+
+       Debug( LDAP_DEBUG_ACL,
+               "<= ldbm_back_group: \"%s\" is in \"%s\": %s\n", 
+               op_ndn, gr_ndn, groupattrName ); 
+
+       rc = 0;
 
+return_results:
        if( target != e ) {
                /* free entry and reader lock */
                cache_return_entry_r( &li->li_cache, e );                 
        }
 
-       Debug( LDAP_DEBUG_ARGS, "ldbm_back_group: rc: %d\n", rc, 0, 0 ); 
+       Debug( LDAP_DEBUG_TRACE, "ldbm_back_group: rc=%d\n", rc, 0, 0 ); 
        return(rc);
 }
 
index 9ae82205434f763885580543596d5067d22d348f..d9e9b8ed4c9b2e7935f8d47d037c9e886690ab0a 100644 (file)
@@ -120,8 +120,10 @@ int ldbm_modify_internal(
 
 
        if ( (err = acl_check_modlist( be, conn, op, e, modlist ))
-            != LDAP_SUCCESS ) {
-               send_ldap_result( conn, op, err, NULL, NULL );
+            != LDAP_SUCCESS )
+       {
+               send_ldap_result( conn, op, err,
+                       NULL, NULL, NULL, NULL );
                return -1;
        }
 
@@ -173,7 +175,8 @@ int ldbm_modify_internal(
 
                if ( err != LDAP_SUCCESS ) {
                        /* unlock entry, delete from cache */
-                       send_ldap_result( conn, op, err, NULL, NULL );
+                       send_ldap_result( conn, op, err,
+                               NULL, NULL, NULL, NULL );
                        return -1;
                }
        }
@@ -181,7 +184,8 @@ int ldbm_modify_internal(
        /* check that the entry still obeys the schema */
        if ( global_schemacheck && oc_schema_check( e ) != 0 ) {
                Debug( LDAP_DEBUG_ANY, "entry failed schema check\n", 0, 0, 0 );
-               send_ldap_result( conn, op, LDAP_OBJECT_CLASS_VIOLATION, NULL, NULL );
+               send_ldap_result( conn, op, LDAP_OBJECT_CLASS_VIOLATION,
+                       NULL, NULL, NULL, NULL );
                return -1;
        }
 
@@ -195,7 +199,8 @@ int ldbm_modify_internal(
 
        /* modify indexes */
        if ( index_add_mods( be, modlist, e->e_id ) != 0 ) {
-               send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL, NULL );
+               send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+                       NULL, NULL, NULL, NULL );
                return -1;
        }
 
@@ -222,35 +227,69 @@ ldbm_back_modify(
 )
 {
        struct ldbminfo *li = (struct ldbminfo *) be->be_private;
-       char            *matched;
+       Entry           *matched;
        Entry           *e;
+       int             manageDSAit = get_manageDSAit( op );
 
        Debug(LDAP_DEBUG_ARGS, "ldbm_back_modify:\n", 0, 0, 0);
 
        /* acquire and lock entry */
        if ( (e = dn2entry_w( be, dn, &matched )) == NULL ) {
-               send_ldap_result( conn, op, LDAP_NO_SUCH_OBJECT, matched,
-                   NULL );
+               char* matched_dn = NULL;
+               struct berval **refs = NULL;
+
                if ( matched != NULL ) {
-                       free( matched );
+                       matched_dn = ch_strdup( matched->e_dn );
+                       refs = is_entry_referral( matched )
+                               ? get_entry_referrals( be, conn, op, matched )
+                               : NULL;
+                       cache_return_entry_r( &li->li_cache, matched );
+               } else {
+                       refs = default_referral;
                }
+
+               send_ldap_result( conn, op, LDAP_REFERRAL,
+                       matched_dn, NULL, refs, NULL );
+
+               if ( matched != NULL ) {
+                       ber_bvecfree( refs );
+                       free( matched_dn );
+               }
+
                return( -1 );
        }
 
+    if ( !manageDSAit && is_entry_referral( e ) ) {
+               /* parent is a referral, don't allow add */
+               /* parent is an alias, don't allow add */
+               struct berval **refs = get_entry_referrals( be,
+                       conn, op, e );
+
+               Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0,
+                   0, 0 );
+
+               send_ldap_result( conn, op, LDAP_REFERRAL,
+                   e->e_dn, NULL, refs, NULL );
+
+               ber_bvecfree( refs );
+
+               goto error_return;
+       }
+       
        /* Modify the entry */
        if ( ldbm_modify_internal( be, conn, op, dn, modlist, e ) != 0 ) {
-
                goto error_return;
-
        }
 
        /* change the entry itself */
        if ( id2entry_add( be, e ) != 0 ) {
-               send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL, NULL );
+               send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+                       NULL, NULL, NULL, NULL );
                goto error_return;
        }
 
-       send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL );
+       send_ldap_result( conn, op, LDAP_SUCCESS,
+               NULL, NULL, NULL, NULL );
        cache_return_entry_w( &li->li_cache, e );
        return( 0 );
 
index 5a606acb9bae4f4ebb536f7f8b9b0db58c10dc2a..4f743c473c16a9352ff905dec096e9d108c0e36c 100644 (file)
@@ -39,10 +39,10 @@ ldbm_back_modrdn(
 )
 {
        struct ldbminfo *li = (struct ldbminfo *) be->be_private;
-       char            *matched = NULL;
        char            *p_dn = NULL, *p_ndn = NULL;
        char            *new_dn = NULL, *new_ndn = NULL;
        Entry           *e, *p = NULL;
+       Entry           *matched = NULL;
        int                     rootlock = 0;
        int                     rc = -1;
        /* Added to support LDAP v2 correctly (deleteoldrdn thing) */
@@ -62,7 +62,7 @@ ldbm_back_modrdn(
        struct berval   del_bv;                 /* Stores old rdn att */
        struct berval   *del_bvals[2];          /* Stores old rdn att */
        LDAPModList     mod[2];                 /* Used to delete old rdn */
-
+       int             manageDSAit = get_manageDSAit( op );
 
        Debug( LDAP_DEBUG_TRACE, "==>ldbm_back_modrdn(newSuperior=%s)\n",
               (newSuperior ? newSuperior : "NULL"),
@@ -70,29 +70,62 @@ ldbm_back_modrdn(
 
        /* get entry with writer lock */
        if ( (e = dn2entry_w( be, dn, &matched )) == NULL ) {
-               send_ldap_result( conn, op, LDAP_NO_SUCH_OBJECT, matched, "" );
+               char* matched_dn = NULL;
+               struct berval** refs = NULL;
+
+               if( matched != NULL ) {
+                       matched_dn = strdup( matched->e_dn );
+                       refs = is_entry_referral( matched )
+                               ? get_entry_referrals( be, conn, op, matched )
+                               : NULL;
+                       cache_return_entry_r( &li->li_cache, matched );
+               } else {
+                       refs = default_referral;
+               }
+
+               send_ldap_result( conn, op, LDAP_REFERRAL,
+                       matched_dn, NULL, refs, NULL );
+
                if ( matched != NULL ) {
-                       free( matched );
+                       ber_bvecfree( refs );
+                       free( matched_dn );
                }
+
                return( -1 );
        }
 
 #ifdef SLAPD_CHILD_MODIFICATION_WITH_ENTRY_ACL
-               /* check parent for "children" acl */
        if ( ! access_allowed( be, conn, op, e,
                "entry", NULL, ACL_WRITE ) )
        {
                Debug( LDAP_DEBUG_TRACE, "no access to entry\n", 0,
                        0, 0 );
                send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
-                       "", "" );
+                       NULL, NULL, NULL, NULL );
                goto return_results;
        }
 #endif
 
+       if (!manageDSAit && is_entry_referral( e ) ) {
+               /* parent is a referral, don't allow add */
+               /* parent is an alias, don't allow add */
+               struct berval **refs = get_entry_referrals( be,
+                       conn, op, e );
+
+               Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0,
+                   0, 0 );
+
+               send_ldap_result( conn, op, LDAP_REFERRAL,
+                   e->e_dn, NULL, refs, NULL );
+
+               ber_bvecfree( refs );
+
+               goto return_results;
+       }
+
        if ( (p_ndn = dn_parent( be, e->e_ndn )) != NULL ) {
 
-               /* Make sure parent entry exist and we can write its 
+               /* Make sure parent entry exist and we can write its 
                 * children.
                 */
 
@@ -100,7 +133,7 @@ ldbm_back_modrdn(
                        Debug( LDAP_DEBUG_TRACE, "parent does not exist\n",
                                0, 0, 0);
                        send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
-                               "", "");
+                               NULL, NULL, NULL, NULL );
                        goto return_results;
                }
 
@@ -111,7 +144,7 @@ ldbm_back_modrdn(
                        Debug( LDAP_DEBUG_TRACE, "no access to parent\n", 0,
                                0, 0 );
                        send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
-                               "", "" );
+                               NULL, NULL, NULL, NULL );
                        goto return_results;
                }
 
@@ -131,7 +164,7 @@ ldbm_back_modrdn(
                        Debug( LDAP_DEBUG_TRACE, "no parent & not root\n",
                                0, 0, 0);
                        send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
-                               "", "");
+                               NULL, NULL, NULL, NULL );
                        goto return_results;
                }
 
@@ -162,12 +195,11 @@ ldbm_back_modrdn(
                /* Get Entry with dn=newSuperior. Does newSuperior exist? */
 
                if( (np = dn2entry_w( be, np_ndn, &matched )) == NULL) {
-
                        Debug( LDAP_DEBUG_TRACE,
                               "ldbm_back_modrdn: newSup(ndn=%s) not here!\n",
                               np_ndn, 0, 0);
-                       send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "",
-                                         "");
+                       send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+                               NULL, NULL, NULL, NULL );
                        goto return_results;
                }
 
@@ -183,7 +215,30 @@ ldbm_back_modrdn(
                               "ldbm_back_modrdn: no wr to newSup children\n",
                               0, 0, 0 );
                        send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
-                                         "", "" );
+                               NULL, NULL, NULL, NULL );
+                       goto return_results;
+               }
+
+               if ( is_entry_alias( np ) ) {
+                       /* entry is an alias, don't allow bind */
+                       Debug( LDAP_DEBUG_TRACE, "entry is alias\n", 0,
+                           0, 0 );
+
+                       send_ldap_result( conn, op, LDAP_ALIAS_PROBLEM,
+                           NULL, NULL, NULL, NULL );
+
+                       goto return_results;
+               }
+
+               if ( is_entry_referral( np ) ) {
+                       /* parent is a referral, don't allow add */
+                       /* parent is an alias, don't allow add */
+                       Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0,
+                               0, 0 );
+
+                       send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+                           NULL, NULL, NULL, NULL );
+
                        goto return_results;
                }
 
@@ -191,9 +246,7 @@ ldbm_back_modrdn(
                       "ldbm_back_modrdn: wr to new parent's children OK\n",
                       0, 0 , 0 );
 
-
                new_parent_dn = np_dn;
-
        }
        
        /* Build target dn and make sure target entry doesn't exist already. */
@@ -207,7 +260,8 @@ ldbm_back_modrdn(
               new_ndn, 0, 0 );
 
        if (dn2id ( be, new_ndn ) != NOID) {
-               send_ldap_result( conn, op, LDAP_ALREADY_EXISTS, NULL, NULL );
+               send_ldap_result( conn, op, LDAP_ALREADY_EXISTS,
+                       NULL, NULL, NULL, NULL );
                goto return_results;
        }
 
@@ -225,7 +279,8 @@ ldbm_back_modrdn(
 
        /* delete old one */
        if ( dn2id_delete( be, e->e_ndn ) != 0 ) {
-               send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL, NULL );
+               send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+                       NULL, NULL, NULL, NULL );
                goto return_results;
        }
 
@@ -237,7 +292,8 @@ ldbm_back_modrdn(
 
        /* add new one */
        if ( dn2id_add( be, e->e_ndn, e->e_id ) != 0 ) {
-               send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL, NULL );
+               send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+                       NULL, NULL, NULL, NULL );
                goto return_results;
        }
 
@@ -251,7 +307,8 @@ ldbm_back_modrdn(
                Debug( LDAP_DEBUG_TRACE,
                       "ldbm_back_modrdn: can't figure out type of newrdn\n",
                       0, 0, 0 );
-               send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
+               send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+                       NULL, NULL, NULL, NULL );
                goto return_results;            
 
        }
@@ -261,7 +318,8 @@ ldbm_back_modrdn(
                Debug( LDAP_DEBUG_TRACE,
                       "ldbm_back_modrdn: can't figure out val of newrdn\n",
                       0, 0, 0 );
-               send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
+               send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+                       NULL, NULL, NULL, NULL );
                goto return_results;            
 
        }
@@ -277,7 +335,8 @@ ldbm_back_modrdn(
                Debug( LDAP_DEBUG_TRACE,
                       "ldbm_back_modrdn: can't figure out old_rdn from dn\n",
                       0, 0, 0 );
-               send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
+               send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+                       NULL, NULL, NULL, NULL );
                goto return_results;            
 
        }
@@ -287,7 +346,8 @@ ldbm_back_modrdn(
                Debug( LDAP_DEBUG_TRACE,
                       "ldbm_back_modrdn: can't figure out the old_rdn type\n",
                       0, 0, 0 );
-               send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
+               send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+                       NULL, NULL, NULL, NULL );
                goto return_results;            
                
        }
@@ -323,7 +383,6 @@ ldbm_back_modrdn(
                /* Remove old rdn value if required */
 
                if (deleteoldrdn) {
-
                        /* Get value of old rdn */
        
                        if ((old_rdn_val = rdn_attr_value( old_rdn ))
@@ -332,12 +391,9 @@ ldbm_back_modrdn(
                                Debug( LDAP_DEBUG_TRACE,
                                       "ldbm_back_modrdn: can't figure out old_rdn_val from old_rdn\n",
                                       0, 0, 0 );
-                               send_ldap_result( conn, op,
-                                                 LDAP_OPERATIONS_ERROR,
-                                                 "", "" );
+                               send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+                                       NULL, NULL, NULL, NULL );
                                goto return_results;            
-
-
                        }
 
                        del_bvals[0] = &del_bv;         /* Array of bervals */
@@ -374,8 +430,8 @@ ldbm_back_modrdn(
                       "ldbm_back_modrdn: not fully implemented...\n",
                       0, 0, 0 );
   
-               send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL,
-                                 NULL );
+               send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+                       NULL, NULL, NULL, NULL );
                goto return_results;
 
        }
@@ -397,11 +453,13 @@ ldbm_back_modrdn(
        /* id2entry index */
        if ( id2entry_add( be, e ) != 0 ) {
                entry_free( e );
-               send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
+               send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+                       NULL, NULL, NULL, NULL );
                goto return_results_after;
        }
 
-       send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL );
+       send_ldap_result( conn, op, LDAP_SUCCESS,
+               NULL, NULL, NULL, NULL );
        rc = 0;
        goto return_results_after;      
 
index a5066eff8b14b8c00a0d1b193e9e2fe4404f92b3..6c2f90da0aab5adc20052e4c8e1fb39f664339a1 100644 (file)
@@ -10,16 +10,18 @@ LDAP_BEGIN_DECL
 /*
  * alias.c
  */
-Entry *derefAlias_r LDAP_P((
-       Backend     *be,
-       Connection      *conn,
-       Operation       *op,
-       Entry       *e ));
-char *derefDN LDAP_P((
-       Backend     *be,
-       Connection  *conn,
-       Operation   *op,
-       char        *dn ));
+Entry *deref_internal_r LDAP_P((
+       Backend *be,
+       Entry *e,
+       char *dn,
+       int *err,
+       Entry **matched,
+       char **text ));
+
+#define deref_entry_r( be, e, err, matched, text ) \
+       deref_internal_r( be, e, NULL, err, matched, text )
+#define deref_dn_r( be, dn, err, matched, text ) \
+       deref_internal_r( be, NULL, dn, err, matched, text)
 
 /*
  * attr.c
@@ -71,7 +73,7 @@ int dn2id_add LDAP_P(( Backend *be, char *dn, ID id ));
 ID dn2id LDAP_P(( Backend *be, char *dn ));
 int dn2id_delete LDAP_P(( Backend *be, char *dn ));
 
-Entry * dn2entry_rw LDAP_P(( Backend *be, char *dn, char **matched, int rw ));
+Entry * dn2entry_rw LDAP_P(( Backend *be, char *dn, Entry **matched, int rw ));
 #define dn2entry_r(be, dn, m) dn2entry_rw((be), (dn), (m), 0)
 #define dn2entry_w(be, dn, m) dn2entry_rw((be), (dn), (m), 1)
 
index 7ab4f5f7617f16c58479f4508db67514a2553081..dbbf761487bcf9632cccc1cd43fdc61d7052e3c7 100644 (file)
 #include "back-ldbm.h"
 #include "proto-back-ldbm.h"
 
-static ID_BLOCK        *base_candidates(Backend *be, Connection *conn, Operation *op, char *base, Filter *filter, char **attrs, int attrsonly, char **matched, int *err);
-static ID_BLOCK        *onelevel_candidates(Backend *be, Connection *conn, Operation *op, char *base, Filter *filter, char **attrs, int attrsonly, char **matched, int *err);
-static ID_BLOCK        *subtree_candidates(Backend *be, Connection *conn, Operation *op, char *base, Filter *filter, char **attrs, int attrsonly, char **matched, Entry *e, int *err, int lookupbase);
-
-#define GRABSIZE       BUFSIZ
-
-#define MAKE_SPACE( n ) { \
-       if ( rcur + (n) > rbuf + rmaxsize ) { \
-               int     offset = rcur - rbuf; \
-               rbuf =  ch_realloc( rbuf, rmaxsize + GRABSIZE ); \
-               rmaxsize += GRABSIZE; \
-               rcur = rbuf + offset; \
-       } \
-}
+static ID_BLOCK        *base_candidate(
+       Backend *be, Entry *e );
+
+static ID_BLOCK        *search_candidates(
+       Backend *be, Entry *e, Filter *filter,
+       int scope, int deref, int manageDSAit );
+
 
 int
 ldbm_back_search(
@@ -43,19 +36,76 @@ ldbm_back_search(
 )
 {
        struct ldbminfo *li = (struct ldbminfo *) be->be_private;
-       int             err;
+       int             rc, err;
+       char *text;
        time_t          stoptime;
        ID_BLOCK                *candidates;
        ID              id;
        Entry           *e;
-       Attribute       *ref;
-       char            *matched = NULL;
-       int             rmaxsize, nrefs;
-       char            *rbuf, *rcur;
+       struct berval **v2refs = NULL;
+       Entry   *matched = NULL;
+       char    *realbase = NULL;
        int             nentries = 0;
-       char            *realBase;
+       int             manageDSAit = get_manageDSAit( op );
+
+       Debug(LDAP_DEBUG_TRACE, "=> ldbm_back_search\n", 0, 0, 0);
+
+       /* get entry with reader lock */
+       if ( deref & LDAP_DEREF_FINDING ) {
+               e = deref_dn_r( be, base, &err, &matched, &text );
 
-       Debug(LDAP_DEBUG_ARGS, "=> ldbm_back_search\n", 0, 0, 0);
+       } else {
+               e = dn2entry_r( be, base, &matched );
+               err = e != NULL ? LDAP_SUCCESS : LDAP_REFERRAL;
+               text = NULL;
+       }
+
+       if ( e == NULL ) {
+               char *matched_dn = NULL;
+               struct berval **refs = NULL;
+
+               if ( matched != NULL ) {
+                       matched_dn = ch_strdup( matched->e_dn );
+
+                       refs = is_entry_referral( matched )
+                               ? get_entry_referrals( be, conn, op, matched )
+                               : NULL;
+
+                       cache_return_entry_r( &li->li_cache, matched );
+               } else {
+                       refs = default_referral;
+               }
+
+               send_ldap_result( conn, op, err,
+                       matched_dn, text, refs, NULL );
+
+               if( matched != NULL ) {
+                       ber_bvecfree( refs );
+                       free( matched_dn );
+               }
+
+               return 1;
+       }
+
+       if (!manageDSAit && is_entry_referral( e ) ) {
+               /* entry is a referral, don't allow add */
+               char *matched_dn = ch_strdup( e->e_dn );
+               struct berval **refs = get_entry_referrals( be,
+                       conn, op, e );
+
+               cache_return_entry_r( &li->li_cache, e );
+
+               Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0,
+                   0, 0 );
+
+               send_ldap_result( conn, op, LDAP_REFERRAL,
+                   matched_dn, NULL, refs, NULL );
+
+               ber_bvecfree( refs );
+               free( matched_dn );
+
+               return 1;
+       }
 
        if ( tlimit == 0 && be_isroot( be, op->o_ndn ) ) {
                tlimit = -1;    /* allow root to set no limit */
@@ -64,6 +114,7 @@ ldbm_back_search(
                    be->be_timelimit : tlimit;
                stoptime = op->o_time + tlimit;
        }
+
        if ( slimit == 0 && be_isroot( be, op->o_ndn ) ) {
                slimit = -1;    /* allow root to set no limit */
        } else {
@@ -71,220 +122,183 @@ ldbm_back_search(
                    be->be_sizelimit : slimit;
        }
 
-       /*
-        * check and apply aliasing where the dereferencing applies to
-        * the subordinates of the base
-        */
-
-       switch ( deref ) {
-       case LDAP_DEREF_FINDING:
-       case LDAP_DEREF_ALWAYS:
-               realBase = derefDN ( be, conn, op, base );
-               break;
-       default:
-               realBase = ch_strdup(base);
-       }
-
-       (void) dn_normalize_case( realBase );
-
-       Debug( LDAP_DEBUG_TRACE, "using base \"%s\"\n",
-               realBase, 0, 0 );
-
-       switch ( scope ) {
-       case LDAP_SCOPE_BASE:
-               candidates = base_candidates( be, conn, op, realBase, filter,
-                   attrs, attrsonly, &matched, &err );
-               break;
+       if ( scope == LDAP_SCOPE_BASE) {
+               candidates = base_candidate( be, e );
 
-       case LDAP_SCOPE_ONELEVEL:
-               candidates = onelevel_candidates( be, conn, op, realBase, filter,
-                   attrs, attrsonly, &matched, &err );
-               break;
-
-       case LDAP_SCOPE_SUBTREE:
-               candidates = subtree_candidates( be, conn, op, realBase, filter,
-                   attrs, attrsonly, &matched, NULL, &err, 1 );
-               break;
-
-       default:
-               send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR, "",
-                   "Bad scope" );
-               if( realBase != NULL) {
-                       free( realBase );
-               }
-               return( -1 );
+       } else {
+               candidates = search_candidates( be, e, filter,
+                   scope, deref, manageDSAit );
        }
 
-       /* null candidates means we could not find the base object */
+       /* need normalized dn below */
+       realbase = ch_strdup( e->e_ndn );
+       cache_return_entry_r( &li->li_cache, e );
+
        if ( candidates == NULL ) {
-               send_ldap_result( conn, op, err, matched, "" );
-               if ( matched != NULL ) {
-                       free( matched );
-               }
-               if( realBase != NULL) {
-                       free( realBase );
-               }
-               return( -1 );
-       }
+               /* no candidates */
+               Debug( LDAP_DEBUG_TRACE, "no candidates\n", 0,
+                   0, 0 );
+
+               send_search_result( conn, op,
+                       LDAP_SUCCESS,
+                       NULL, NULL, NULL, NULL, 0 );
 
-       if ( matched != NULL ) {
-               free( matched );
+               rc = 1;
+               goto done;
        }
 
-       rmaxsize = 0;
-       nrefs = 0;
-       rbuf = rcur = NULL;
-       MAKE_SPACE( sizeof("Referral:") + 1 );
-       strcpy( rbuf, "Referral:" );
-       rcur = strchr( rbuf, '\0' );
        for ( id = idl_firstid( candidates ); id != NOID;
-           id = idl_nextid( candidates, id ) ) {
+           id = idl_nextid( candidates, id ) )
+       {
+               int             scopeok = 0;
 
                /* check for abandon */
                ldap_pvt_thread_mutex_lock( &op->o_abandonmutex );
+
                if ( op->o_abandon ) {
                        ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
-                       idl_free( candidates );
-                       free( rbuf );
-                       if( realBase != NULL) {
-                               free( realBase );
-                       }
-                       return( 0 );
+                       rc = 0;
+                       goto done;
                }
+
                ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
 
                /* check time limit */
                if ( tlimit != -1 && slap_get_time() > stoptime ) {
-                       send_ldap_search_result( conn, op,
-                           LDAP_TIMELIMIT_EXCEEDED, NULL, nrefs > 0 ? rbuf :
-                           NULL, nentries );
-                       idl_free( candidates );
-                       free( rbuf );
-                       if( realBase != NULL) {
-                               free( realBase );
-                       }
-                       return( 0 );
+                       send_search_result( conn, op, LDAP_TIMELIMIT_EXCEEDED,
+                               NULL, NULL, v2refs, NULL, nentries );
+                       rc = 0;
+                       goto done;
                }
 
                /* get the entry with reader lock */
-               if ( (e = id2entry_r( be, id )) == NULL ) {
-                       Debug( LDAP_DEBUG_ARGS, "candidate %ld not found\n",
-                              id, 0, 0 );
-                       continue;
+               e = id2entry_r( be, id );
+
+               if ( e == NULL ) {
+                       Debug( LDAP_DEBUG_ARGS, "search: candidate %ld not found\n",
+                               id, 0, 0 );
+
+                       goto loop_continue;
+               }
+
+               if ( deref & LDAP_DEREF_SEARCHING && is_entry_alias( e ) ) {
+                       Entry *matched;
+                       int err;
+                       char *text;
+                       
+                       e = deref_entry_r( be, e, &err, &matched, &text );
+
+                       if( e == NULL ) {
+                               e = matched;
+                               goto loop_continue;
+                       }
+
+                       if( e->e_id == id ) {
+                               /* circular loop */
+                               goto loop_continue;
+                       }
+
+                       /* need to skip alias which deref into scope */
+                       if( scope & LDAP_SCOPE_ONELEVEL ) {
+                               char *pdn = dn_parent( NULL, e->e_ndn );
+                               if ( pdn != NULL ) {
+                                       if( strcmp( pdn, realbase ) ) {
+                                               free( pdn );
+                                               goto loop_continue;
+                                       }
+                                       free(pdn);
+                               }
+
+                       } else if ( dn_issuffix( e->e_ndn, realbase ) ) {
+                               /* alias is within scope */
+                               Debug( LDAP_DEBUG_ARGS, "search: \"%s\" in subtree\n",
+                                       e->e_dn, 0, 0 );
+                               goto loop_continue;
+                       }
+
+                       scopeok = 1;
                }
 
                /*
                 * if it's a referral, add it to the list of referrals. only do
-                * this for subtree searches, and don't check the filter explicitly
-                * here since it's only a candidate anyway.
+                * this for non-base searches, and don't check the filter
+                * explicitly here since it's only a candidate anyway.
                 */
-               if ( scope == LDAP_SCOPE_SUBTREE &&
-                       e->e_ndn != NULL &&
-                       strncmp( e->e_ndn, "REF=", 4 ) == 0 &&
-                       (ref = attr_find( e->e_attrs, "ref" )) != NULL )
+               if ( !manageDSAit && scope != LDAP_SCOPE_BASE &&
+                       is_entry_referral( e ) )
                {
-                       int     i;
+                       struct berval **refs = get_entry_referrals(
+                               be, conn, op, e );
 
-                       if ( ref->a_vals == NULL ) {
-                               Debug( LDAP_DEBUG_ANY, "null ref in (%s)\n", 
-                                       e->e_dn, 0, 0 );
-                       } else {
-                               for ( i = 0; ref->a_vals[i] != NULL; i++ ) {
-                                       /* referral + newline + null */
-                                       MAKE_SPACE( ref->a_vals[i]->bv_len + 2 );
-                                       *rcur++ = '\n';
-                                       strncpy( rcur, ref->a_vals[i]->bv_val,
-                                               ref->a_vals[i]->bv_len );
-                                       rcur = rcur + ref->a_vals[i]->bv_len;
-                                       *rcur = '\0';
-                                       nrefs++;
-                               }
-                       }
+                       send_search_reference( be, conn, op,
+                               e, refs, scope, NULL, &v2refs );
 
-               /* otherwise it's an entry - see if it matches the filter */
-               } else {
-                       /* if it matches the filter and scope, send it */
-                       if ( test_filter( be, conn, op, e, filter ) == 0 ) {
-                               int             scopeok;
-                               char    *dn;
+                       ber_bvecfree( refs );
 
-                               /* check scope */
-                               scopeok = 1;
-                               if ( scope == LDAP_SCOPE_ONELEVEL ) {
-                                       if ( (dn = dn_parent( be, e->e_dn )) != NULL ) {
-                                               (void) dn_normalize_case( dn );
-                                               scopeok = (dn == realBase)
-                                                       ? 1
-                                                       : (strcmp( dn, realBase ) ? 0 : 1 );
-                                               free( dn );
-                                       } else {
-                                               scopeok = (realBase == NULL || *realBase == '\0');
-                                       }
-                               } else if ( scope == LDAP_SCOPE_SUBTREE ) {
-                                       dn = ch_strdup( e->e_ndn );
-                                       scopeok = dn_issuffix( dn, realBase );
+                       goto loop_continue;
+               }
+
+               /* if it matches the filter and scope, send it */
+               if ( test_filter( be, conn, op, e, filter ) == 0 ) {
+                       char    *dn;
+
+                       /* check scope */
+                       if ( !scopeok && scope == LDAP_SCOPE_ONELEVEL ) {
+                               if ( (dn = dn_parent( be, e->e_ndn )) != NULL ) {
+                                       (void) dn_normalize_case( dn );
+                                       scopeok = (dn == realbase)
+                                               ? 1
+                                               : (strcmp( dn, realbase ) ? 0 : 1 );
                                        free( dn );
+
+                               } else {
+                                       scopeok = (realbase == NULL || *realbase == '\0');
                                }
 
-                               if ( scopeok ) {
-                                       /* check size limit */
-                                       if ( --slimit == -1 ) {
-                                               cache_return_entry_r( &li->li_cache, e );
-                                               send_ldap_search_result( conn, op,
-                                                       LDAP_SIZELIMIT_EXCEEDED, NULL,
-                                                       nrefs > 0 ? rbuf : NULL, nentries );
-                                               idl_free( candidates );
-                                               free( rbuf );
-
-                                               if( realBase != NULL) {
-                                                       free( realBase );
-                                               }
-                                               return( 0 );
-                                       }
+                       } else if ( !scopeok && scope == LDAP_SCOPE_SUBTREE ) {
+                               dn = ch_strdup( e->e_ndn );
+                               scopeok = dn_issuffix( dn, realbase );
+                               free( dn );
+
+                       } else {
+                               scopeok = 1;
+                       }
+
+                       if ( scopeok ) {
+                               /* check size limit */
+                               if ( --slimit == -1 ) {
+                                       cache_return_entry_r( &li->li_cache, e );
+                                       send_search_result( conn, op,
+                                               LDAP_SIZELIMIT_EXCEEDED, NULL, NULL,
+                                               v2refs, NULL, nentries );
+                                       rc = 0;
+                                       goto done;
+                               }
 
-                                       /*
-                                        * check and apply aliasing where the dereferencing applies to
-                                        * the subordinates of the base
-                                        */
-                                       switch ( deref ) {
-                                       case LDAP_DEREF_SEARCHING:
-                                       case LDAP_DEREF_ALWAYS:
-                                               {
-                                                       Entry *newe = derefAlias_r( be, conn, op, e );
-                                                       if ( newe == NULL ) { /* problem with the alias */
-                                                               cache_return_entry_r( &li->li_cache, e );
-                                                               e = NULL;
-                                                       }
-                                                       else if ( newe != e ) { /* reassign e */
-                                                               cache_return_entry_r( &li->li_cache, e );
-                                                               e = newe;
-                                                       }       
-                                               }
+                               if (e) {
+                                       switch ( send_search_entry( be, conn, op, e,
+                                               attrs, attrsonly, 0, NULL ) ) {
+                                       case 0:         /* entry sent ok */
+                                               nentries++;
                                                break;
-                                       }
-                                       if (e) {
-                                               switch ( send_search_entry( be, conn, op, e,
-                                                       attrs, attrsonly, 0 ) ) {
-                                               case 0:         /* entry sent ok */
-                                                       nentries++;
-                                                       break;
-                                               case 1:         /* entry not sent */
-                                                       break;
-                                               case -1:        /* connection closed */
-                                                       cache_return_entry_r( &li->li_cache, e );
-                                                       idl_free( candidates );
-                                                       free( rbuf );
-
-                                                       if( realBase != NULL) {
-                                                               free( realBase );
-                                                       }
-                                                       return( 0 );
-                                               }
+                                       case 1:         /* entry not sent */
+                                               break;
+                                       case -1:        /* connection closed */
+                                               cache_return_entry_r( &li->li_cache, e );
+                                               rc = 0;
+                                               goto done;
                                        }
                                }
+                       } else {
+                               Debug( LDAP_DEBUG_TRACE, "candidate %ld scope not okay\n",
+                                       id, 0, 0 );
                        }
+               } else {
+                       Debug( LDAP_DEBUG_TRACE, "candidate %ld does match filter\n",
+                               id, 0, 0 );
                }
 
+loop_continue:
                if( e != NULL ) {
                        /* free reader lock */
                        cache_return_entry_r( &li->li_cache, e );
@@ -292,209 +306,142 @@ ldbm_back_search(
 
                ldap_pvt_thread_yield();
        }
+       send_search_result( conn, op,
+               v2refs == NULL ? LDAP_SUCCESS : LDAP_REFERRAL,
+               NULL, NULL, v2refs, NULL, nentries );
+
+       rc = 0;
+
+done:
        idl_free( candidates );
-       if ( nrefs > 0 ) {
-               send_ldap_search_result( conn, op, LDAP_PARTIAL_RESULTS, NULL,
-                   rbuf, nentries );
-       } else {
-               send_ldap_search_result( conn, op, LDAP_SUCCESS, NULL, NULL,
-                   nentries );
-       }
-       free( rbuf );
 
-       if( realBase != NULL) {
-               free( realBase );
-       }
+       ber_bvecfree( v2refs );
+       if( realbase ) free( realbase );
 
-       return( 0 );
+       return rc;
 }
 
 static ID_BLOCK *
-base_candidates(
+base_candidate(
     Backend    *be,
-    Connection *conn,
-    Operation  *op,
-    char       *base,
-    Filter     *filter,
-    char       **attrs,
-    int                attrsonly,
-    char       **matched,
-    int                *err
+       Entry   *e
 )
 {
-       struct ldbminfo *li = (struct ldbminfo *) be->be_private;
        ID_BLOCK                *idl;
-       Entry           *e;
-
-       Debug(LDAP_DEBUG_TRACE, "base_candidates: base: \"%s\"\n", base, 0, 0);
 
-       *err = LDAP_SUCCESS;
-
-       /* get entry with reader lock */
-       if ( (e = dn2entry_r( be, base, matched )) == NULL ) {
-               *err = LDAP_NO_SUCH_OBJECT;
-               return( NULL );
-       }
-
-       /* check for deleted */
+       Debug(LDAP_DEBUG_TRACE, "base_candidates: base: \"%s\"\n",
+               e->e_dn, 0, 0);
 
        idl = idl_alloc( 1 );
        idl_insert( &idl, e->e_id, 1 );
 
-
-       /* free reader lock */
-       cache_return_entry_r( &li->li_cache, e );
-
        return( idl );
 }
 
 static ID_BLOCK *
-onelevel_candidates(
+search_candidates(
     Backend    *be,
-    Connection *conn,
-    Operation  *op,
-    char       *base,
+    Entry      *e,
     Filter     *filter,
-    char       **attrs,
-    int                attrsonly,
-    char       **matched,
-    int                *err
+    int                scope,
+       int             deref,
+       int             manageDSAit
 )
 {
        struct ldbminfo *li = (struct ldbminfo *) be->be_private;
-       Entry           *e = NULL;
-       Filter          *f;
-       char            buf[20];
        ID_BLOCK                *candidates;
+       Filter          *f, *rf, *af, *lf;
 
-       Debug(LDAP_DEBUG_TRACE, "onelevel_candidates: base: \"%s\"\n", base, 0, 0);
+       Debug(LDAP_DEBUG_TRACE, "search_candidates: base=\"%s\" s=%d d=%d\n",
+               e->e_ndn, scope, deref );
 
-       *err = LDAP_SUCCESS;
+       f = NULL;
 
-       /* get the base object with reader lock */
-       if ( base != NULL && *base != '\0' &&
-               (e = dn2entry_r( be, base, matched )) == NULL )
-       {
-               *err = LDAP_NO_SUCH_OBJECT;
-               return( NULL );
+       if( !manageDSAit ) {
+               /* match referrals */
+               rf = (Filter *) ch_malloc( sizeof(Filter) );
+               rf->f_next = NULL;
+               rf->f_choice = LDAP_FILTER_OR;
+               rf->f_or = (Filter *) ch_malloc( sizeof(Filter) );
+               rf->f_or->f_choice = LDAP_FILTER_EQUALITY;
+               rf->f_or->f_avtype = ch_strdup( "objectclass" );
+               rf->f_or->f_avvalue.bv_val = ch_strdup( "REFERRAL" );
+               rf->f_or->f_avvalue.bv_len = sizeof("REFERRAL")-1;
+               rf->f_or->f_next = filter;
+               f = rf;
+       } else {
+               rf = NULL;
+               f = filter;
        }
 
-       /*
-        * modify the filter to be something like this:
-        *
-        *      parent=baseobject & originalfilter
-        */
-
-       f = (Filter *) ch_malloc( sizeof(Filter) );
-       f->f_next = NULL;
-       f->f_choice = LDAP_FILTER_AND;
-       f->f_and = (Filter *) ch_malloc( sizeof(Filter) );
-       f->f_and->f_choice = LDAP_FILTER_EQUALITY;
-       f->f_and->f_ava.ava_type = ch_strdup( "id2children" );
-       sprintf( buf, "%ld", e != NULL ? e->e_id : 0 );
-       f->f_and->f_ava.ava_value.bv_val = ch_strdup( buf );
-       f->f_and->f_ava.ava_value.bv_len = strlen( buf );
-       f->f_and->f_next = filter;
-
-       /* from here, it's just like subtree_candidates */
-       candidates = subtree_candidates( be, conn, op, base, f, attrs,
-           attrsonly, matched, e, err, 0 );
-
-       /* free up just the filter stuff we allocated above */
-       f->f_and->f_next = NULL;
-       filter_free( f );
-
-       /* free entry and reader lock */
-       if( e != NULL ) {
-               cache_return_entry_r( &li->li_cache, e );
+       if( deref & LDAP_DEREF_SEARCHING ) {
+               /* match aliases */
+               af = (Filter *) ch_malloc( sizeof(Filter) );
+               af->f_next = NULL;
+               af->f_choice = LDAP_FILTER_OR;
+               af->f_or = (Filter *) ch_malloc( sizeof(Filter) );
+               af->f_or->f_choice = LDAP_FILTER_EQUALITY;
+               af->f_or->f_avtype = ch_strdup( "objectclass" );
+               af->f_or->f_avvalue.bv_val = ch_strdup( "ALIAS" );
+               af->f_or->f_avvalue.bv_len = sizeof("ALIAS")-1;
+               af->f_or->f_next = f;
+               f = af;
+       } else {
+               af = NULL;
        }
-       return( candidates );
-}
 
-static ID_BLOCK *
-subtree_candidates(
-    Backend    *be,
-    Connection *conn,
-    Operation  *op,
-    char       *base,
-    Filter     *filter,
-    char       **attrs,
-    int                attrsonly,
-    char       **matched,
-    Entry      *e,
-    int                *err,
-    int                lookupbase
-)
-{
-       struct ldbminfo *li = (struct ldbminfo *) be->be_private;
-       Filter          *f, **filterarg_ptr;
-       ID_BLOCK                *candidates;
+       if ( scope == LDAP_SCOPE_SUBTREE ) {
+               lf = (Filter *) ch_malloc( sizeof(Filter) );
+               lf->f_next = NULL;
+               lf->f_choice = LDAP_FILTER_AND;
+               lf->f_and = (Filter *) ch_malloc( sizeof(Filter) );
 
-       Debug(LDAP_DEBUG_TRACE, "subtree_candidates: base: \"%s\" %s\n",
-               base ? base : "NULL", lookupbase ? "lookupbase" : "", 0);
-
-       /*
-        * get the base object - unless we already have it (from one-level).
-        * also, unless this is a one-level search or a subtree search
-        * starting at the very top of our subtree, we need to modify the
-        * filter to be something like this:
-        *
-        *      dn=*baseobjectdn & (originalfilter | ref=*)
-        *
-        * the "objectclass=referral" part is used to select referrals to return
-        */
-
-       *err = LDAP_SUCCESS;
-       f = NULL;
-       if ( lookupbase ) {
-               e = NULL;
+               lf->f_and->f_choice = LDAP_FILTER_SUBSTRINGS;
+               lf->f_and->f_sub_type = ch_strdup( "dn" );
+               lf->f_and->f_sub_initial = NULL;
+               lf->f_and->f_sub_any = NULL;
+               lf->f_and->f_sub_final = ch_strdup( e->e_ndn );
 
-               if ( base != NULL && *base != '\0' &&
-                       (e = dn2entry_r( be, base, matched )) == NULL )
-               {
-                       *err = LDAP_NO_SUCH_OBJECT;
-                       return( NULL );
-               }
+               lf->f_and->f_next = f;
+               f = lf;
 
-               if (e) {
-                       cache_return_entry_r( &li->li_cache, e );
-               }
+       } else if ( scope == LDAP_SCOPE_ONELEVEL ) {
+               char buf[16];
 
-               f = (Filter *) ch_malloc( sizeof(Filter) );
-               f->f_next = NULL;
-               f->f_choice = LDAP_FILTER_OR;
-               f->f_or = (Filter *) ch_malloc( sizeof(Filter) );
-               f->f_or->f_choice = LDAP_FILTER_EQUALITY;
-               f->f_or->f_avtype = ch_strdup( "objectclass" );
-               /* Patch to use normalized uppercase */
-               f->f_or->f_avvalue.bv_val = ch_strdup( "REFERRAL" );
-               f->f_or->f_avvalue.bv_len = strlen( "REFERRAL" );
-               filterarg_ptr = &f->f_or->f_next;
-               *filterarg_ptr = filter;
-               filter = f;
-
-               if ( ! be_issuffix( be, base ) ) {
-                       f = (Filter *) ch_malloc( sizeof(Filter) );
-                       f->f_next = NULL;
-                       f->f_choice = LDAP_FILTER_AND;
-                       f->f_and = (Filter *) ch_malloc( sizeof(Filter) );
-                       f->f_and->f_choice = LDAP_FILTER_SUBSTRINGS;
-                       f->f_and->f_sub_type = ch_strdup( "dn" );
-                       f->f_and->f_sub_initial = NULL;
-                       f->f_and->f_sub_any = NULL;
-                       f->f_and->f_sub_final = ch_strdup( base );
-                       value_normalize( f->f_and->f_sub_final, SYNTAX_CIS );
-                       f->f_and->f_next = filter;
-                       filter = f;
-               }
+               lf = (Filter *) ch_malloc( sizeof(Filter) );
+               lf->f_next = NULL;
+               lf->f_choice = LDAP_FILTER_AND;
+               lf->f_and = (Filter *) ch_malloc( sizeof(Filter) );
+
+               lf->f_and->f_choice = LDAP_FILTER_EQUALITY;
+               lf->f_and->f_ava.ava_type = ch_strdup( "id2children" );
+               sprintf( buf, "%ld", e != NULL ? e->e_id : 0 );
+               lf->f_and->f_ava.ava_value.bv_val = ch_strdup( buf );
+               lf->f_and->f_ava.ava_value.bv_len = strlen( buf );
+
+               lf->f_and->f_next = f;
+               f = lf;
+
+       } else {
+               lf = NULL;
        }
 
-       candidates = filter_candidates( be, filter );
+       candidates = filter_candidates( be, f );
+
+       /* free up filter additions we allocated above */
+       if( lf != NULL ) {
+               lf->f_and->f_next = NULL;
+               filter_free( lf );
+       }
+
+       if( af != NULL ) {
+               af->f_or->f_next = NULL;
+               filter_free( af );
+       }
 
-       /* free up just the parts we allocated above */
-       if ( f != NULL ) {
-               *filterarg_ptr = NULL;
-               filter_free( f );
+       if( rf != NULL ) {
+               rf->f_or->f_next = NULL;
+               filter_free( rf );
        }
 
        return( candidates );
index 0eea43fe99baa67c6c1418564f3cdc284163e105..231d6648692ed6f2abc99cacc1306265f084ef30 100644 (file)
@@ -35,12 +35,13 @@ passwd_back_search(
     int                attrsonly
 )
 {
-       int sent = 0;
        struct passwd   *pw;
        Entry           *e;
        char            *s;
        time_t          stoptime;
-       int err = LDAP_NO_SUCH_OBJECT;
+
+       int sent = 0;
+       int err = LDAP_SUCCESS;
 
        char *rdn = NULL;
        char *parent = NULL;
@@ -68,43 +69,47 @@ passwd_back_search(
                vals[0] = &val;
                vals[1] = NULL;
 
-               /* Create an entry corresponding to the base DN */
-               e = (Entry *) ch_calloc(1, sizeof(Entry));
-               e->e_attrs = NULL;
-               e->e_dn = strdup(base);
-
-               /* Use the first attribute of the DN
-                * as an attribute within the entry itself.
-                */
-               rdn = dn_rdn(NULL, base);
+               matched = ch_strdup( base );
 
-               if( rdn == NULL || (s = strchr(rdn, '=')) == NULL ) {
-                       err = LDAP_INVALID_DN_SYNTAX;
-                       goto done;
-               }
+               if( scope != LDAP_SCOPE_ONELEVEL ) {
+                       /* Create an entry corresponding to the base DN */
+                       e = (Entry *) ch_calloc(1, sizeof(Entry));
+                       e->e_attrs = NULL;
+                       e->e_dn = ch_strdup( base );
 
-               val.bv_val = rdn_attr_value(rdn);
-               val.bv_len = strlen( val.bv_val );
-               attr_merge( e, rdn_attr_type(rdn), vals );
+                       /* Use the first attribute of the DN
+                       * as an attribute within the entry itself.
+                       */
+                       rdn = dn_rdn(NULL, base);
 
-               free(rdn);
-               rdn = NULL;
+                       if( rdn == NULL || (s = strchr(rdn, '=')) == NULL ) {
+                               err = LDAP_INVALID_DN_SYNTAX;
+                               goto done;
+                       }
 
-               /* Every entry needs an objectclass. We don't really
-                * know if our hardcoded choice here agrees with the
-                * DN that was configured for this backend, but it's
-                * better than nothing.
-                *
-                * should be a configuratable item
-                */
-               val.bv_val = "organizationalUnit";
-               val.bv_len = strlen( val.bv_val );
-               attr_merge( e, "objectClass", vals );
+                       val.bv_val = rdn_attr_value(rdn);
+                       val.bv_len = strlen( val.bv_val );
+                       attr_merge( e, rdn_attr_type(rdn), vals );
+
+                       free(rdn);
+                       rdn = NULL;
+
+                       /* Every entry needs an objectclass. We don't really
+                        * know if our hardcoded choice here agrees with the
+                        * DN that was configured for this backend, but it's
+                        * better than nothing.
+                        *
+                        * should be a configuratable item
+                        */
+                       val.bv_val = "organizationalUnit";
+                       val.bv_len = strlen( val.bv_val );
+                       attr_merge( e, "objectClass", vals );
        
-               if ( test_filter( be, conn, op, e, filter ) == 0 ) {
-                       send_search_entry( be, conn, op, e, attrs, attrsonly, 0 );
-                       matched = strdup( be->be_suffix[0] );
-                       sent++;
+                       if ( test_filter( be, conn, op, e, filter ) == 0 ) {
+                               send_search_entry( be, conn, op,
+                                       e, attrs, attrsonly, 0, NULL );
+                               sent++;
+                       }
                }
 
                if ( scope != LDAP_SCOPE_BASE ) {
@@ -123,7 +128,7 @@ passwd_back_search(
                                /* check time limit */
                                if ( slap_get_time() > stoptime ) {
                                        send_ldap_result( conn, op, LDAP_TIMELIMIT_EXCEEDED,
-                                       NULL, NULL );
+                                       NULL, NULL, NULL, NULL );
                                        endpwent();
                                        return( 0 );
                                }
@@ -134,12 +139,13 @@ passwd_back_search(
                                        /* check size limit */
                                        if ( --slimit == -1 ) {
                                                send_ldap_result( conn, op, LDAP_SIZELIMIT_EXCEEDED,
-                                               NULL, NULL );
+                                               NULL, NULL, NULL, NULL );
                                                endpwent();
                                                return( 0 );
                                        }
 
-                                       send_search_entry( be, conn, op, e, attrs, attrsonly, 0 );
+                                       send_search_entry( be, conn, op,
+                                               e, attrs, attrsonly, 0, NULL );
                                        sent++;
                                }
 
@@ -155,13 +161,25 @@ passwd_back_search(
                 * anything deeper than that.
                 */
                if( !be_issuffix( be, parent ) ) {
+                       int i;
+                       for( i=0; be->be_suffix[i] != NULL; i++ ) {
+                               if( dn_issuffix( base, be->be_suffix[i] ) ) {
+                                       matched = ch_strdup( be->be_suffix[i] );
+                                       break;
+                               }
+                       }
+                       err = LDAP_NO_SUCH_OBJECT;
+                       goto done;
+               }
+
+               if( scope == LDAP_SCOPE_ONELEVEL ) {
                        goto done;
                }
 
                rdn = dn_rdn( NULL, base );
 
                if ( (user = rdn_attr_value(rdn)) == NULL) {
-                       err = LDAP_INVALID_DN_SYNTAX;
+                       err = LDAP_OPERATIONS_ERROR;
                        goto done;
                }
 
@@ -170,13 +188,17 @@ passwd_back_search(
                }
 
                if ( (pw = getpwnam( user )) == NULL ) {
+                       matched = parent;
+                       parent = NULL;
+                       err = LDAP_NO_SUCH_OBJECT;
                        goto done;
                }
 
                e = pw2entry( be, pw, rdn );
 
                if ( test_filter( be, conn, op, e, filter ) == 0 ) {
-                       send_search_entry( be, conn, op, e, attrs, attrsonly, 0 );
+                       send_search_entry( be, conn, op,
+                               e, attrs, attrsonly, 0, NULL );
                        sent++;
                }
 
@@ -184,12 +206,9 @@ passwd_back_search(
        }
 
 done:
-       if( sent ) {
-               send_ldap_result( conn, op, LDAP_SUCCESS, "", "" );
-
-       } else {
-               send_ldap_result( conn, op, err, matched, NULL );
-       }
+       send_ldap_result( conn, op,
+               err, err == LDAP_NO_SUCH_OBJECT ? matched : NULL, NULL,
+               NULL, NULL );
 
        if( matched != NULL ) free( matched );
        if( parent != NULL ) free( parent );
index 9b4e09f7dfec32905461cffb4092d92c23bd68aa..89193b499a4c9ee833fddb2dc91e7098e76f3120 100644 (file)
@@ -61,10 +61,12 @@ perl_back_add(
        ldap_pvt_thread_mutex_unlock( &perl_interpreter_mutex );        
 
        if( return_code != 0 ) {
-               send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
+               send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+                       NULL, NULL, NULL, NULL );
 
        } else {
-               send_ldap_result( conn, op, LDAP_SUCCESS, "", "" );
+               send_ldap_result( conn, op, LDAP_SUCCESS,
+                       NULL, NULL, NULL, NULL );
        }
 
        Debug( LDAP_DEBUG_ANY, "Here ADD\n", 0, 0, 0 );
index 17429d10bca7461bb74c5309fe3b6e254659738d..482cdd06d58e039d89603a8939b8aa899bab75da 100644 (file)
@@ -40,7 +40,7 @@ perl_back_compare(
        PerlBackend *perl_back = (PerlBackend *)be->be_private;
 
        send_ldap_result( conn, op, LDAP_UNWILLING_TO_PERFORM,
-               "", "not yet implemented" );
+               NULL, "not yet implemented", NULL, NULL );
 
 #ifdef notdef
        ldap_pvt_thread_mutex_lock( &perl_interpreter_mutex );  
@@ -70,10 +70,10 @@ perl_back_compare(
        ldap_pvt_thread_mutex_unlock( &perl_interpreter_mutex );        
 
        if( return_code != 0 ) {
-               send_ldap_result( conn, op, LDAP_COMPARE_TRUE, "", "" );
+               send_ldap_result( conn, op, LDAP_COMPARE_TRUE, NULL, NULL );
 
        } else {
-               send_ldap_result( conn, op, LDAP_COMPARE_FALSE, "", "" );
+               send_ldap_result( conn, op, LDAP_COMPARE_FALSE, NULL, NULL );
        }
 #endif
 
index 956cc594c76411945c83b0a10bd0053868051140..53acb19945995b639731f51031b38aeff3dffd0b 100644 (file)
@@ -60,10 +60,12 @@ perl_back_delete(
        ldap_pvt_thread_mutex_unlock( &perl_interpreter_mutex );        
 
        if( return_code != 0 ) {
-               send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
+               send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+                       NULL, NULL, NULL, NULL );
 
        } else {
-               send_ldap_result( conn, op, LDAP_SUCCESS, "", "" );
+               send_ldap_result( conn, op, LDAP_SUCCESS,
+                       NULL, NULL, NULL, NULL );
        }
 
        Debug( LDAP_DEBUG_ANY, "Here DELETE\n", 0, 0, 0 );
index 8ee8b825734da813e89085e1398aa58bf3205826..025823e08114833e7199f035f3b820abbc5029b1 100644 (file)
@@ -93,10 +93,12 @@ perl_back_modify(
        ldap_pvt_thread_mutex_unlock( &perl_interpreter_mutex );
 
        if( return_code != 0 ) {
-               send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
+               send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+                       NULL, NULL, NULL, NULL );
 
        } else {
-               send_ldap_result( conn, op, LDAP_SUCCESS, "", "" );
+               send_ldap_result( conn, op, LDAP_SUCCESS,
+                       NULL, NULL, NULL, NULL );
        }
 
        Debug( LDAP_DEBUG_ANY, "Perl MODIFY\n", 0, 0, 0 );
index 11188290993c0535fd441ccef6c167cd7707c0d0..5fa8bca1231fd552ad7ec091a74e58685a138537 100644 (file)
@@ -81,10 +81,12 @@ perl_back_modrdn(
        ldap_pvt_thread_mutex_unlock( &perl_interpreter_mutex );
        
        if( return_code != 0 ) {
-               send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
+               send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+                       NULL, NULL, NULL, NULL );
 
        } else {
-               send_ldap_result( conn, op, LDAP_SUCCESS, "", "" );
+               send_ldap_result( conn, op, LDAP_SUCCESS,
+                       NULL, NULL, NULL, NULL );
        }
 
        Debug( LDAP_DEBUG_ANY, "Perl MODRDN\n", 0, 0, 0 );
index 7117f4b985e01cc9f1ae2ac58500b0935bc168c1..16648d658c409ea603e7f68741dcafe8f93e08a7 100644 (file)
@@ -86,13 +86,8 @@ perl_back_search(
                                        Debug( LDAP_DEBUG_ANY, "str2entry(%s) failed\n", buf, 0, 0 );
 
                                } else {
-                                       send_search_entry( be,
-                                                          conn,
-                                                          op,
-                                                          e,
-                                                          attrs,
-                                                          attrsonly,
-                                                          0 );
+                                       send_search_entry( be, conn, op,
+                                               e, attrs, attrsonly, 0, NULL );
                                                         
                                        entry_free( e );
                                }
@@ -118,10 +113,12 @@ perl_back_search(
        ldap_pvt_thread_mutex_unlock( &perl_interpreter_mutex );        
 
        if( return_code != 0 ) {
-               send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
+               send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+                       NULL, NULL, NULL, NULL );
 
        } else {
-               send_ldap_result( conn, op, LDAP_SUCCESS, "", "" );
+               send_ldap_result( conn, op, LDAP_SUCCESS,
+                       NULL, NULL, NULL, NULL );
        }
 }
 
index dad9499230699f6e31b63b4a371cd7186ef846d5..9d972195c626c3f191c77f5dd89f73fc320328ad 100644 (file)
@@ -34,8 +34,6 @@ perl_back_unbind(
        Operation *op
 )
 {
-       send_ldap_result( conn, op, LDAP_UNWILLING_TO_PERFORM,
-               "", "not yet implemented" );
        Debug( LDAP_DEBUG_TRACE, "Perl UNBIND\n", 0, 0, 0 );
        return 0;
 }
index 61752d3278b9174b697901c0a912aac5ec523c59..9c033e7be853b8d73811bd3a0f7332b703db0bff 100644 (file)
@@ -24,13 +24,13 @@ shell_back_add(
 
        if ( si->si_add == NULL ) {
                send_ldap_result( conn, op, LDAP_UNWILLING_TO_PERFORM, NULL,
-                   "add not implemented" );
+                   "add not implemented", NULL, NULL );
                return( -1 );
        }
 
        if ( (op->o_private = (void *) forkandexec( si->si_add, &rfp, &wfp )) == (void *) -1 ) {
                send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL,
-                   "could not fork/exec" );
+                   "could not fork/exec", NULL, NULL );
                return( -1 );
        }
 
index 5e2e195ef546447404b6490ea239b371fa4c33d9..1b61eeb778a584bdc624c72b9d71a6696cc3b4f6 100644 (file)
@@ -30,14 +30,14 @@ shell_back_bind(
 
        if ( si->si_bind == NULL ) {
                send_ldap_result( conn, op, LDAP_UNWILLING_TO_PERFORM, NULL,
-                   "bind not implemented" );
+                   "bind not implemented", NULL, NULL );
                return( -1 );
        }
 
        if ( (op->o_private = (void *) forkandexec( si->si_bind, &rfp, &wfp ))
            == (void *) -1 ) {
                send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL,
-                   "could not fork/exec" );
+                   "could not fork/exec", NULL, NULL );
                return( -1 );
        }
 
index 1b724055f5833368f5b9c93a8156a15f3b1425b6..c59ac342893e672c7c613a9fe9a582a8b9b1e324 100644 (file)
@@ -24,14 +24,14 @@ shell_back_compare(
 
        if ( si->si_compare == NULL ) {
                send_ldap_result( conn, op, LDAP_UNWILLING_TO_PERFORM, NULL,
-                   "compare not implemented" );
+                   "compare not implemented", NULL, NULL );
                return( -1 );
        }
 
        if ( (op->o_private = (void *) forkandexec( si->si_compare, &rfp, &wfp ))
            == (void *) -1 ) {
                send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL,
-                   "could not fork/exec" );
+                   "could not fork/exec", NULL, NULL );
                return( -1 );
        }
 
index be989ec9c5d6759da1dfea7a63c817a91e72e234..1956969fbec3a25da323ed6a8f175ddc773ac1f6 100644 (file)
@@ -23,14 +23,14 @@ shell_back_delete(
 
        if ( si->si_delete == NULL ) {
                send_ldap_result( conn, op, LDAP_UNWILLING_TO_PERFORM, NULL,
-                   "delete not implemented" );
+                   "delete not implemented", NULL, NULL );
                return( -1 );
        }
 
        if ( (op->o_private = (void *) forkandexec( si->si_delete, &rfp, &wfp ))
            == (void *) -1 ) {
                send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL,
-                   "could not fork/exec" );
+                   "could not fork/exec", NULL, NULL );
                return( -1 );
        }
 
index 178b1eb031b599d62b50c9dc54ce0d2c5eef2a8c..ebaa3f10e960246e5935060bdd5a7b9fa8218e73 100644 (file)
@@ -25,14 +25,14 @@ shell_back_modify(
 
        if ( si->si_modify == NULL ) {
                send_ldap_result( conn, op, LDAP_UNWILLING_TO_PERFORM, NULL,
-                   "modify not implemented" );
+                   "modify not implemented", NULL, NULL );
                return( -1 );
        }
 
        if ( (op->o_private = (void *) forkandexec( si->si_modify, &rfp, &wfp ))
            == (void *) -1 ) {
                send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL,
-                   "could not fork/exec" );
+                   "could not fork/exec", NULL, NULL );
                return( -1 );
        }
 
index d42742ca4ccc6f04813ffe2142c80f139612a3cd..c04e83a3757427705094778fd0c58ef48958d055 100644 (file)
@@ -39,14 +39,14 @@ shell_back_modrdn(
 
        if ( si->si_modrdn == NULL ) {
                send_ldap_result( conn, op, LDAP_UNWILLING_TO_PERFORM, NULL,
-                   "modrdn not implemented" );
+                   "modrdn not implemented", NULL, NULL );
                return( -1 );
        }
 
        if ( (op->o_private = (void *) forkandexec( si->si_modrdn, &rfp, &wfp ))
            == (void *) -1 ) {
                send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL,
-                   "could not fork/exec" );
+                   "could not fork/exec", NULL, NULL );
                return( -1 );
        }
 
index dfb479e36cae3b7295119c8bf71a5252e5d28b19..7e895001ac01db06de939057c468339bae9a5b28 100644 (file)
@@ -59,7 +59,7 @@ read_and_send_results(
                                    buf, 0, 0 );
                        } else {
                                send_search_entry( be, conn, op, e, attrs,
-                                   attrsonly, 0 );
+                                   attrsonly, 0, NULL );
                                entry_free( e );
                        }
 
@@ -70,7 +70,7 @@ read_and_send_results(
 
        /* otherwise, front end will send this result */
        if ( err != 0 || op->o_tag != LDAP_REQ_BIND ) {
-               send_ldap_result( conn, op, err, matched, info );
+               send_ldap_result( conn, op, err, matched, info, NULL, NULL );
        }
 
        free( buf );
index dc26be2d08a809e9bb117a81e740df466ac8a210..6f2bbb8d74fb58905ce2e25901778b7e992b7074 100644 (file)
@@ -34,14 +34,14 @@ shell_back_search(
 
        if ( si->si_search == NULL ) {
                send_ldap_result( conn, op, LDAP_UNWILLING_TO_PERFORM, NULL,
-                   "search not implemented" );
+                   "search not implemented", NULL, NULL );
                return( -1 );
        }
 
        if ( (op->o_private = (void *) forkandexec( si->si_search, &rfp, &wfp ))
            == (void *) -1 ) {
                send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL,
-                   "could not fork/exec" );
+                   "could not fork/exec", NULL, NULL );
                return( -1 );
        }
 
index 6e8d1009c1bc4c8c1520d91dbdeed7c23b9c2492..f90792d8760661a27c470f6d7b480d96e3fef745 100644 (file)
@@ -22,14 +22,14 @@ shell_back_unbind(
 
        if ( si->si_unbind == NULL ) {
                send_ldap_result( conn, op, LDAP_UNWILLING_TO_PERFORM, NULL,
-                   "unbind not implemented" );
+                   "unbind not implemented", NULL, NULL );
                return 0;
        }
 
        if ( (op->o_private = (void *) forkandexec( si->si_unbind, &rfp, &wfp ))
            == (void *) -1 ) {
                send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL,
-                   "could not fork/exec" );
+                   "could not fork/exec", NULL, NULL );
                return 0;
        }
 
index d964dc80609f6f6a62d3e51b79efcd388047d9d3..d341c22317b2a20aaad7f8143af88c05804e129a 100644 (file)
@@ -1,6 +1,6 @@
 /* add.c - tcl add routine
  *
- * $Id: tcl_add.c,v 1.4 1999/02/19 06:55:20 bcollins Exp $
+ * $Id: tcl_add.c,v 1.5.6.1 1999/07/09 18:02:59 kdz Exp $
  *
  * Copyright 1999, Ben Collins <bcollins@debian.org>, All rights reserved.
  *
@@ -31,7 +31,7 @@ tcl_back_add (
 
        if (ti->ti_add == NULL) {
                send_ldap_result (conn, op, LDAP_UNWILLING_TO_PERFORM, NULL,
-                       "add not implemented");
+                       "add not implemented", NULL );
                return (-1);
        }
 
@@ -63,7 +63,7 @@ tcl_back_add (
 
        if (err != LDAP_SUCCESS)
                send_ldap_result (conn, op, err, NULL,
-                       "internal backend error");
+                       "internal backend error", NULL );
 
        free (results);
        return (err);
index 31abd6d1da8b3cc6e071db6cc6f50dac28ecb391..7326d129a1f0834f5edfbf70de80e6869c4fe9a2 100644 (file)
@@ -1,6 +1,6 @@
 /* bind.c - tcl bind routines
  *
- * $Id: tcl_bind.c,v 1.5 1999/02/28 04:55:48 bcollins Exp $
+ * $Id: tcl_bind.c,v 1.6.2.1 1999/07/09 18:02:59 kdz Exp $
  *
  * Copyright 1999, Ben Collins <bcollins@debian.org>, All rights reserved.
  *
@@ -37,7 +37,7 @@ tcl_back_bind (
 
        if (ti->ti_bind == NULL) {
                send_ldap_result (conn, op, LDAP_UNWILLING_TO_PERFORM, NULL,
-                       "bind not implemented");
+                       "bind not implemented", NULL );
                return (-1);
        }
 
@@ -67,7 +67,7 @@ tcl_back_bind (
 
        if (err != LDAP_SUCCESS)
                send_ldap_result (conn, op, err, NULL,
-                       "internal backend error");
+                       "internal backend error", NULL );
 
        free (results);
        return (err);
index 7cd87affda03b5e0c564ec1143558565506e5a1f..2982abe69d2b5949d4d2d7cc42e96f7341ed02b6 100644 (file)
@@ -1,6 +1,6 @@
 /* compare.c - tcl compare routines
  *
- * $Id: tcl_compare.c,v 1.4 1999/02/19 06:55:20 bcollins Exp $
+ * $Id: tcl_compare.c,v 1.5.6.1 1999/07/09 18:02:59 kdz Exp $
  *
  * Copyright 1999, Ben Collins <bcollins@debian.org>, All rights reserved.
  *
@@ -32,7 +32,7 @@ tcl_back_compare (
 
        if (ti->ti_compare == NULL) {
                send_ldap_result (conn, op, LDAP_UNWILLING_TO_PERFORM, NULL,
-                       "compare not implemented");
+                       "compare not implemented", NULL );
                return (-1);
        }
 
@@ -63,7 +63,7 @@ tcl_back_compare (
 
        if (err != LDAP_SUCCESS)
                send_ldap_result (conn, op, err, NULL,
-                       "internal backend error");
+                       "internal backend error", NULL );
 
        free (results);
        return (err);
index 805297833244b859abe15230621af22c1b248791..464292c720b671ada80aa7c67655dffbd1a17f12 100644 (file)
@@ -1,6 +1,6 @@
 /* delete.c - tcl delete routines
  *
- * $Id: tcl_delete.c,v 1.4 1999/02/19 06:55:20 bcollins Exp $
+ * $Id: tcl_delete.c,v 1.5.6.1 1999/07/09 18:02:59 kdz Exp $
  *
  * Copyright 1999, Ben Collins <bcollins@debian.org>, All rights reserved.
  *
@@ -30,7 +30,7 @@ tcl_back_delete (
 
        if (ti->ti_delete == NULL) {
                send_ldap_result (conn, op, LDAP_UNWILLING_TO_PERFORM, NULL,
-                       "delete not implemented");
+                       "delete not implemented", NULL );
                return (-1);
        }
 
@@ -59,7 +59,7 @@ tcl_back_delete (
 
        if (err != LDAP_SUCCESS)
                send_ldap_result (conn, op, err, NULL,
-                       "internal backend error");
+                       "internal backend error", NULL );
 
        free (results);
        return (err);
index 047a7fbd41f740cbd3dddf6505c83c755bfaad0f..ac9a130c50f84e7a039b79718a0b71da3171b098 100644 (file)
@@ -1,6 +1,6 @@
 /* modify.c - tcl modify routines
  *
- * $Id: tcl_modify.c,v 1.4 1999/02/19 06:55:20 bcollins Exp $
+ * $Id: tcl_modify.c,v 1.5.6.1 1999/07/09 18:02:59 kdz Exp $
  *
  * Copyright 1999, Ben Collins <bcollins@debian.org>, All rights reserved.
  *
@@ -32,7 +32,7 @@ tcl_back_modify (
 
        if (ti->ti_modify == NULL) {
                send_ldap_result (conn, op, LDAP_UNWILLING_TO_PERFORM, NULL,
-                       "modify not implemented");
+                       "modify not implemented", NULL );
                return (-1);
        }
 
@@ -110,7 +110,7 @@ tcl_back_modify (
 
        if (err != LDAP_SUCCESS)
                send_ldap_result (conn, op, err, NULL,
-                       "internal backend error");
+                       "internal backend error", NULL );
 
        free (results);
        return (err);
index e6af8b2b0340dd6fa9a0e6942ec6c4e1c0ad27ac..ffe18f9bc464efa3726367c6ef0a5c09ef94d83c 100644 (file)
@@ -1,6 +1,6 @@
 /* modrdn.c - tcl modify rdn routines
  *
- * $Id: tcl_modrdn.c,v 1.6 1999/03/05 02:42:46 gomez Exp $
+ * $Id: tcl_modrdn.c,v 1.7.6.1 1999/07/09 18:02:59 kdz Exp $
  *
  * Copyright 1999, Ben Collins <bcollins@debian.org>, All rights reserved.
  *
@@ -47,7 +47,7 @@ tcl_back_modrdn (
 
        if (ti->ti_modrdn == NULL) {
                send_ldap_result (conn, op, LDAP_UNWILLING_TO_PERFORM, NULL,
-                       "modrdn not implemented");
+                       "modrdn not implemented", NULL );
                return (-1);
        }
 
@@ -84,7 +84,7 @@ tcl_back_modrdn (
 
        if (err != LDAP_SUCCESS)
                send_ldap_result (conn, op, err, NULL,
-                       "internal backend error");
+                       "internal backend error", NULL );
 
        free (results);
        return (err);
index bbf95dad3c1f950afbd1d774fffb27d8db0eb339..5058bdbc9a09a413f82f1c45af1d356fabc023bc 100644 (file)
@@ -1,6 +1,6 @@
 /* search.c - tcl search routines
  *
- * $Id: tcl_search.c,v 1.4 1999/02/19 06:55:20 bcollins Exp $
+ * $Id: tcl_search.c,v 1.5.6.1 1999/07/09 18:02:59 kdz Exp $
  *
  * Copyright 1999, Ben Collins <bcollins@debian.org>, All rights reserved.
  *
@@ -40,7 +40,7 @@ tcl_back_search (
 
        if (ti->ti_search == NULL) {
                send_ldap_result (conn, op, LDAP_UNWILLING_TO_PERFORM, NULL,
-                       "search not implemented");
+                       "search not implemented", NULL );
                return (-1);
        }
 
@@ -80,7 +80,7 @@ tcl_back_search (
 
        if (err != LDAP_SUCCESS)
                send_ldap_result (conn, op, err, NULL,
-                       "internal backend error");
+                       "internal backend error", NULL );
 
        free (results);
        return (err);
index d30aea3f1ba0718cd5ab7bd234bd91cefd792c25..b75969cf751460c3a8e5b7c037b50c9d96acf39e 100644 (file)
@@ -1,6 +1,6 @@
 /* unbind.c - tcl unbind routines
  *
- * $Id: tcl_unbind.c,v 1.4 1999/02/19 06:55:20 bcollins Exp $
+ * $Id: tcl_unbind.c,v 1.5.6.1 1999/07/09 18:02:59 kdz Exp $
  *
  * Copyright 1999, Ben Collins <bcollins@debian.org>, All rights reserved.
  *
@@ -29,8 +29,6 @@ tcl_back_unbind (
        struct tclinfo *ti = (struct tclinfo *) be->be_private;
 
        if (ti->ti_unbind == NULL) {
-               send_ldap_result (conn, op, LDAP_UNWILLING_TO_PERFORM, NULL,
-                       "unbind not implemented");
                return (-1);
        }
 
index cdff332fc3d95a2a4fb41fc440674ed4acec9179..634009aa4bb6d2710e48897352cdd0ff4d46edfe 100644 (file)
@@ -1,6 +1,6 @@
 /* result.c - tcl backend utility functions
  *
- * $Id: tcl_util.c,v 1.5 1999/02/28 04:55:49 bcollins Exp $
+ * $Id: tcl_util.c,v 1.6.2.2 1999/07/14 00:54:37 kdz Exp $
  *
  * Copyright 1999, Ben Collins <bcollins@debian.org>, All rights reserved.
  *
@@ -47,7 +47,7 @@ interp_send_results (
        if (code != TCL_OK) {
                argcPtr = 0;
                send_ldap_result (conn, op, LDAP_UNWILLING_TO_PERFORM, NULL,
-                       "internal backend error");
+                       "internal backend error", NULL );
                return -1;
        }
        for (i = 0; i < argcPtr; i++) {
@@ -80,7 +80,7 @@ interp_send_results (
                                        buf, 0, 0);
                        } else {
                                send_search_entry (be, conn, op, e, attrs,
-                                       attrsonly, 0 );
+                                       attrsonly, 0, NULL );
                                entry_free (e);
                        }
 
@@ -94,7 +94,7 @@ interp_send_results (
         * otherwise, front end will send this result 
         */
        if (err != 0 || op->o_tag != LDAP_REQ_BIND) {
-               send_ldap_result (conn, op, err, matched, info);
+               send_ldap_result (conn, op, err, matched, info, NULL );
        }
 
        free (buf);
index 7b143a08e01965394f1479f583ae012293cb84a6..3b5b51fe77898d4efd32be601ed969918dfba6cf 100644 (file)
@@ -437,26 +437,6 @@ select_backend( char * dn )
                }
        }
 
-        /* if no proper suffix could be found then check for aliases */
-        for ( i = 0; i < nbackends; i++ ) {
-                for ( j = 0; 
-                     backends[i].be_suffixAlias != NULL && 
-                      backends[i].be_suffixAlias[j] != NULL; 
-                     j += 2 )
-                {
-                        len = strlen( backends[i].be_suffixAlias[j] );
-
-                        if ( len > dnlen ) {
-                                continue;
-                        }
-
-                        if ( strcmp( backends[i].be_suffixAlias[j],
-                            dn + (dnlen - len) ) == 0 ) {
-                                return( &backends[i] );
-                        }
-                }
-        }
-
 #ifdef LDAP_ALLOW_NULL_SEARCH_BASE
        /* Add greg@greg.rim.or.jp
         * It's quick hack for cheap client
index 4ab5de594abb86beddde59b0f07ef32228bb37ae..c8daed7bfe2bab60394ff27c11edfd81d114a4d0 100644 (file)
@@ -158,8 +158,8 @@ do_bind(
 
        if ( version < LDAP_VERSION_MIN || version > LDAP_VERSION_MAX ) {
                Debug( LDAP_DEBUG_ANY, "unknown version %d\n", version, 0, 0 );
-               send_ldap_result( conn, op,
-                       rc = LDAP_PROTOCOL_ERROR, NULL, "version not supported" );
+               send_ldap_result( conn, op, rc = LDAP_PROTOCOL_ERROR,
+                       NULL, "version not supported", NULL, NULL );
                goto cleanup;
        }
 
@@ -178,7 +178,7 @@ do_bind(
                                "do_bind: no sasl mechanism provided\n",
                                version, 0, 0 );
                        send_ldap_result( conn, op, rc = LDAP_AUTH_METHOD_NOT_SUPPORTED,
-                               NULL, "no sasl mechanism provided" );
+                               NULL, "no sasl mechanism provided", NULL, NULL );
                        goto cleanup;
                }
 
@@ -187,7 +187,7 @@ do_bind(
                                "do_bind: sasl mechanism \"%s\" not supported.\n",
                                mech, 0, 0 );
                        send_ldap_result( conn, op, rc = LDAP_AUTH_METHOD_NOT_SUPPORTED,
-                               NULL, "sasl mechanism not supported" );
+                               NULL, "sasl mechanism not supported", NULL, NULL );
                        goto cleanup;
                }
 
@@ -242,7 +242,8 @@ do_bind(
                 * we already forced connection to "anonymous", we just
                 * need to send success
                 */
-               send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL );
+               send_ldap_result( conn, op, LDAP_SUCCESS,
+                       NULL, NULL, NULL, NULL );
                goto cleanup;
        }
 
@@ -255,15 +256,15 @@ do_bind(
        if ( (be = select_backend( ndn )) == NULL ) {
                if ( cred.bv_len == 0 ) {
                        send_ldap_result( conn, op, LDAP_SUCCESS,
-                               NULL, NULL );
+                               NULL, NULL, NULL, NULL );
 
-               } else if ( default_referral && *default_referral ) {
-                       send_ldap_result( conn, op, rc = LDAP_PARTIAL_RESULTS,
-                               NULL, default_referral );
+               } else if ( default_referral ) {
+                       send_ldap_result( conn, op, rc = LDAP_REFERRAL,
+                               NULL, NULL, default_referral, NULL );
 
                } else {
                        send_ldap_result( conn, op, rc = LDAP_INVALID_CREDENTIALS,
-                               NULL, default_referral );
+                               NULL, NULL, NULL, NULL );
                }
 
                goto cleanup;
@@ -273,8 +274,6 @@ do_bind(
                /* alias suffix */
                char *edn;
 
-               ndn = suffixAlias( ndn, op, be );
-
                if ( (*be->be_bind)( be, conn, op, ndn, method, mech, &cred, &edn ) == 0 ) {
                        ldap_pvt_thread_mutex_lock( &conn->c_mutex );
 
@@ -294,15 +293,16 @@ do_bind(
                        ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
 
                        /* send this here to avoid a race condition */
-                       send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL );
+                       send_ldap_result( conn, op, LDAP_SUCCESS,
+                               NULL, NULL, NULL, NULL );
 
                } else if (edn != NULL) {
                        free( edn );
                }
 
        } else {
-               send_ldap_result( conn, op, rc = LDAP_UNWILLING_TO_PERFORM, NULL,
-                   "Function not implemented" );
+               send_ldap_result( conn, op, rc = LDAP_UNWILLING_TO_PERFORM,
+                       NULL, "Function not implemented", NULL, NULL );
        }
 
 cleanup:
index 6ce0999294c0fcbfe36462c978a0072efefe7345..e972d22ec426f8f2c5ec8f618b77c8e29bbbb5e3 100644 (file)
@@ -109,6 +109,35 @@ charray_dup( char **a )
        return( new );
 }
 
+
+char *
+charray2str( char **a )
+{
+       char *s;
+       int i;
+       size_t cur, len = 0;
+
+       if( a == NULL ) return NULL;
+
+       for( i=0 ; a[i] != NULL ; i++ ) {
+               len += strlen( a[i] );
+       }
+
+       if( len == 0 ) return NULL;
+
+       s = ch_malloc( len + 1 );
+
+       cur = 0;
+       for( i=0 ; a[i] != NULL ; i++ ) {
+               len = strlen( a[i] );
+               strncpy( &s[cur], a[i], len );
+               cur += len;
+       }
+       s[len] = '\0';
+       return s;
+}
+
+
 char **
 str2charray( char *str, char *brkstr )
 {
index 028a4f44d0c3c133b6266bf7153276e864b86d07..29a7c8096231a3af61bd4ae902584c6591309169 100644 (file)
@@ -34,8 +34,8 @@ do_compare(
        if( op->o_bind_in_progress ) {
                Debug( LDAP_DEBUG_ANY, "do_compare: SASL bind in progress.\n",
                        0, 0, 0 );
-               send_ldap_result( conn, op, LDAP_SASL_BIND_IN_PROGRESS, NULL,
-                   "SASL bind in progress" );
+               send_ldap_result( conn, op, LDAP_SASL_BIND_IN_PROGRESS,
+                       NULL, "SASL bind in progress", NULL, NULL );
                return LDAP_SASL_BIND_IN_PROGRESS;
        }
 
@@ -85,19 +85,16 @@ do_compare(
                free( ndn );
                ava_free( &ava, 0 );
 
-               send_ldap_result( conn, op, rc = LDAP_PARTIAL_RESULTS, NULL,
-                   default_referral );
+               send_ldap_result( conn, op, rc = LDAP_REFERRAL,
+                       NULL, NULL, default_referral, NULL );
                return 1;
        }
 
-       /* alias suffix if approp */
-       ndn = suffixAlias( ndn, op, be );
-
        if ( be->be_compare ) {
                (*be->be_compare)( be, conn, op, ndn, &ava );
        } else {
-               send_ldap_result( conn, op, rc = LDAP_UNWILLING_TO_PERFORM, NULL,
-                   "Function not implemented" );
+               send_ldap_result( conn, op, rc = LDAP_UNWILLING_TO_PERFORM,
+                       NULL, "Function not implemented", NULL, NULL );
        }
 
        free( ndn );
index 2b9a05f920482cd57ca4d7b95a9666d7066ef50b..ce402b1c8cc15148490c88ea89942b6ae6b4a4b9 100644 (file)
@@ -47,9 +47,15 @@ read_config( char *fname )
        char    *cargv[MAXARGS];
        int     lineno, i, rc;
 
+       struct berval *vals[2];
+       struct berval val;
+
        static BackendInfo *bi = NULL;
        static BackendDB        *be = NULL;
 
+       vals[0] = &val;
+       vals[1] = NULL;
+
        if ( (fp = fopen( fname, "r" )) == NULL ) {
                ldap_syslog = 1;
                Debug( LDAP_DEBUG_ANY,
@@ -121,7 +127,7 @@ read_config( char *fname )
                        be = backend_db_init( cargv[1] );
 
                /* assign a default depth limit for alias deref */
-               be->be_maxDerefDepth = SLAPD_DEFAULT_MAXDEREFDEPTH; 
+               be->be_max_deref_depth = SLAPD_DEFAULT_MAXDEREFDEPTH; 
 
                /* get pid file name */
                } else if ( strcasecmp( cargv[0], "pidfile" ) == 0 ) {
@@ -219,54 +225,9 @@ read_config( char *fname )
                                free( dn );
                        }
 
-                /* set database suffixAlias */
-                } else if ( strcasecmp( cargv[0], "suffixAlias" ) == 0 ) {
-                        if ( cargc < 2 ) {
-                                Debug( LDAP_DEBUG_ANY,
-                    "%s: line %d: missing alias and aliased_dn in \"suffixAlias <alias> <aliased_dn>\" line\n",
-                                    fname, lineno, 0 );
-                                return( 1 );
-                        } else if ( cargc < 3 ) {
-                                Debug( LDAP_DEBUG_ANY,
-                    "%s: line %d: missing aliased_dn in \"suffixAlias <alias> <aliased_dn>\" line\n",
-                                    fname, lineno, 0 );
-                                return( 1 );
-                        } else if ( cargc > 3 ) {
-                                Debug( LDAP_DEBUG_ANY,
-    "%s: line %d: extra cruft in suffixAlias line (ignored)\n",
-                                    fname, lineno, 0 );
-                        }
-                        if ( be == NULL ) {
-                                Debug( LDAP_DEBUG_ANY,
-"%s: line %d: suffixAlias line must appear inside a database definition (ignored)\n",
-                                    fname, lineno, 0 );
-                        } else {
-                                char *alias, *aliased_dn;
-
-                                                               alias = ch_strdup( cargv[1] );
-                                (void) dn_normalize( alias );
-
-                                aliased_dn = ch_strdup( cargv[2] );
-                                (void) dn_normalize( aliased_dn );
-
-
-                                                               if ( strcasecmp( alias, aliased_dn) == 0 ) {
-                                       Debug( LDAP_DEBUG_ANY,
-"%s: line %d: suffixAlias %s is not different from aliased dn (ignored)\n",
-                                    fname, lineno, alias );
-                                                               } else {
-                                       (void) dn_normalize_case( alias );
-                                       (void) dn_normalize_case( aliased_dn );
-                                       charray_add( &be->be_suffixAlias, alias );
-                                       charray_add( &be->be_suffixAlias, aliased_dn );
-                                                               }
-
-                                                               free(alias);
-                                                               free(aliased_dn);
-                        }
-
                /* set max deref depth */
                } else if ( strcasecmp( cargv[0], "maxDerefDepth" ) == 0 ) {
+                                       int i;
                        if ( cargc < 2 ) {
                                Debug( LDAP_DEBUG_ANY,
                    "%s: line %d: missing depth in \"maxDerefDepth <depth>\" line\n",
@@ -277,9 +238,14 @@ read_config( char *fname )
                                Debug( LDAP_DEBUG_ANY,
 "%s: line %d: depth line must appear inside a database definition (ignored)\n",
                                    fname, lineno, 0 );
+                       } else if ((i = atoi(cargv[i])) < 0) {
+                               Debug( LDAP_DEBUG_ANY,
+"%s: line %d: depth must be positive (ignored)\n",
+                                   fname, lineno, 0 );
+
                        } else {
-                           be->be_maxDerefDepth = atoi (cargv[1]);
-                       }
+                           be->be_max_deref_depth = i;
+                                          }
 
 
                /* set magic "root" dn for this database */
@@ -343,10 +309,10 @@ read_config( char *fname )
                                    fname, lineno, 0 );
                                return( 1 );
                        }
-                       default_referral = (char *) ch_malloc( strlen( cargv[1] )
-                           + sizeof("Referral:\n") + 1 );
-                       strcpy( default_referral, "Referral:\n" );
-                       strcat( default_referral, cargv[1] );
+
+                       vals[0]->bv_val = cargv[1];
+                       vals[0]->bv_len = strlen( vals[0]->bv_val );
+                       value_add( &default_referral, vals );
 
                /* specify locale */
                } else if ( strcasecmp( cargv[0], "locale" ) == 0 ) {
@@ -500,6 +466,27 @@ read_config( char *fname )
                                (void) dn_normalize_case( be->be_update_ndn );
                        }
 
+               } else if ( strcasecmp( cargv[0], "updateref" ) == 0 ) {
+                       if ( cargc < 2 ) {
+                               Debug( LDAP_DEBUG_ANY,
+                   "%s: line %d: missing dn in \"updateref <ldapurl>\" line\n",
+                                   fname, lineno, 0 );
+                               return( 1 );
+                       }
+                       if ( be == NULL ) {
+                               Debug( LDAP_DEBUG_ANY,
+"%s: line %d: updateref line must appear inside a database definition (ignored)\n",
+                                   fname, lineno, 0 );
+                       } else if ( be->be_update_ndn == NULL ) {
+                               Debug( LDAP_DEBUG_ANY,
+"%s: line %d: updateref line must after updatedn (ignored)\n",
+                                   fname, lineno, 0 );
+                       } else {
+                               vals[0]->bv_val = cargv[1];
+                               vals[0]->bv_len = strlen( vals[0]->bv_val );
+                               value_add( &be->be_update_refs, vals );
+                       }
+
                /* replication log file to which changes are appended */
                } else if ( strcasecmp( cargv[0], "replogfile" ) == 0 ) {
                        if ( cargc < 2 ) {
index ee6d63fd50ebdb17fe77541fdab5ed5a37b3d39e..4d85b2b62764c17f89be0c2741433165f2ed821d 100644 (file)
@@ -56,15 +56,10 @@ config_info( Connection *conn, Operation *op )
                attr_merge( e, "database", vals );
        }
 
-       if ( default_referral != NULL ) {
-               strcpy( buf, default_referral );
-               val.bv_val = buf;
-               val.bv_len = strlen( buf );
-               attr_merge( e, "database", vals );
-       }
-
-       send_search_entry( &backends[0], conn, op, e, NULL, 0, 1 );
-       send_ldap_search_result( conn, op, LDAP_SUCCESS, NULL, NULL, 1 );
+       send_search_entry( &backends[0], conn, op, e,
+               NULL, 0, 1, NULL );
+       send_search_result( conn, op, LDAP_SUCCESS,
+               NULL, NULL, NULL, NULL, 1 );
 
        entry_free( e );
 }
index 1afb52038a8f6c6092693063ab1a87b7117d1e5d..37361cb47cde7e2493b63fdea4aec6e0afb12cda 100644 (file)
@@ -17,6 +17,7 @@
 #include "../../libraries/liblber/lber-int.h"
 
 char *supportedControls[] = {
+       LDAP_CONTROL_MANAGEDSAIT,
        NULL
 };
 
@@ -154,9 +155,29 @@ return_results:
                if( rc == -1 ) {
                        send_ldap_disconnect( conn, op, rc, errmsg );
                } else {
-                       send_ldap_result( conn, op, rc, NULL, errmsg );
+                       send_ldap_result( conn, op, rc,
+                               NULL, errmsg, NULL, NULL );
                }
        }
 
        return rc;
 }
+
+
+int get_manageDSAit( Operation *op )
+{
+       int i;
+       if( op == NULL || op->o_ctrls == NULL ) {
+               return 0;
+       }
+
+       for( i=0; op->o_ctrls[i] != NULL; i++ ) {
+               if( strcmp( LDAP_CONTROL_MANAGEDSAIT, op->o_ctrls[i]->ldctl_oid )
+                       == 0 )
+               {
+                       return 1;
+               }
+       }
+
+       return 0;
+}
\ No newline at end of file
index 4d0d7fb0764b8383faf970b722dc6613f8bb7a11..2b2d41cfaaad047528eb7a394ff88d42d1b86cf6 100644 (file)
@@ -34,8 +34,8 @@ do_delete(
        if( op->o_bind_in_progress ) {
                Debug( LDAP_DEBUG_ANY, "do_delete: SASL bind in progress.\n",
                        0, 0, 0 );
-               send_ldap_result( conn, op, LDAP_SASL_BIND_IN_PROGRESS, NULL,
-                   "SASL bind in progress" );
+               send_ldap_result( conn, op, LDAP_SASL_BIND_IN_PROGRESS,
+                       NULL, "SASL bind in progress", NULL, NULL );
                return LDAP_SASL_BIND_IN_PROGRESS;
        }
 
@@ -71,14 +71,11 @@ do_delete(
         */
        if ( (be = select_backend( ndn )) == NULL ) {
                free( ndn );
-               send_ldap_result( conn, op, rc = LDAP_PARTIAL_RESULTS, NULL,
-                   default_referral );
+               send_ldap_result( conn, op, rc = LDAP_REFERRAL,
+                       NULL, NULL, default_referral, NULL );
                return rc;
        }
 
-       /* alias suffix if approp */
-       ndn = suffixAlias( ndn, op, be );
-
        /*
         * do the delete if 1 && (2 || 3)
         * 1) there is a delete function implemented in this backend;
@@ -94,12 +91,12 @@ do_delete(
                                replog( be, LDAP_REQ_DELETE, ndn, NULL, 0 );
                        }
                } else {
-                       send_ldap_result( conn, op, rc = LDAP_PARTIAL_RESULTS, NULL,
-                           default_referral );
+                       send_ldap_result( conn, op, rc = LDAP_REFERRAL, NULL, NULL,
+                               be->be_update_refs ? be->be_update_refs : default_referral, NULL );
                }
        } else {
-               send_ldap_result( conn, op, rc = LDAP_UNWILLING_TO_PERFORM, NULL,
-                   "Function not implemented" );
+               send_ldap_result( conn, op, rc = LDAP_UNWILLING_TO_PERFORM,
+                       NULL, "Function not implemented", NULL, NULL );
        }
 
        free( ndn );
index d813cf25011abf35716dc08cb37b787d275375ec..a9143e4ed8d6ab539b7de7c899654d8b03e5a53e 100644 (file)
@@ -73,8 +73,8 @@ do_extended(
        if( !charray_inlist( supportedExtensions, reqoid ) ) {
                Debug( LDAP_DEBUG_ANY, "do_extended: unsupported operation \"%s\"\n",
                        reqoid, 0 ,0 );
-               send_ldap_result( conn, op, rc = LDAP_PROTOCOL_ERROR, NULL,
-                   "unsuppored operation" );
+               send_ldap_result( conn, op, rc = LDAP_PROTOCOL_ERROR,
+                       NULL, "unsuppored extended operation", NULL, NULL );
                goto done;
        }
 
@@ -98,7 +98,7 @@ do_extended(
        Debug( LDAP_DEBUG_ARGS, "do_extended: oid \"%s\"\n", reqoid, 0 ,0 );
 
        send_ldap_result( conn, op, rc = LDAP_PROTOCOL_ERROR,
-               NULL, "unsupported extended operation" );
+               NULL, "unsupported extended operation", NULL, NULL );
 
 done:
        if ( reqoid != NULL ) {
index 0990d4b533bfa5f201ece1ffef1612042e9dd8c1..dc5091066331c30df0bd8eec0bbc602b66d470ff 100644 (file)
@@ -23,7 +23,7 @@ int           ldap_syslog;
 #endif
 
 int            ldap_syslog_level = LOG_DEBUG;
-char           *default_referral;
+struct berval **default_referral = NULL;
 int            g_argc;
 char           **g_argv;
 
@@ -45,7 +45,9 @@ long                  num_ops_completed;
 ldap_pvt_thread_mutex_t        num_ops_mutex;
 
 long                   num_entries_sent;
+long                   num_refs_sent;
 long                   num_bytes_sent;
+long                   num_pdu_sent;
 ldap_pvt_thread_mutex_t        num_sent_mutex;
 /*
  * these mutexes must be used when calling the entry2str()
index 898d368c6a256c68606e9b066134768aae059fc9..9c6ddefdd6bd839d028790dd888c00162a110dfd 100644 (file)
@@ -272,10 +272,6 @@ SOURCE=.\str2filter.c
 # End Source File
 # Begin Source File
 
-SOURCE=.\suffixalias.c
-# End Source File
-# Begin Source File
-
 SOURCE=.\unbind.c
 # End Source File
 # Begin Source File
index ccae24d41f0a5f51d3d70c2359f464a59623f394..340263037e9b70fa23d79c7d67b2fe5d4ba58c56 100644 (file)
@@ -45,8 +45,8 @@ do_modify(
        if( op->o_bind_in_progress ) {
                Debug( LDAP_DEBUG_ANY, "do_modify: SASL bind in progress.\n",
                        0, 0, 0 );
-               send_ldap_result( conn, op, LDAP_SASL_BIND_IN_PROGRESS, NULL,
-                   "SASL bind in progress" );
+               send_ldap_result( conn, op, LDAP_SASL_BIND_IN_PROGRESS,
+                       NULL, "SASL bind in progress", NULL, NULL );
                return LDAP_SASL_BIND_IN_PROGRESS;
        }
 
@@ -112,7 +112,7 @@ do_modify(
                    (*modtail)->ml_op != LDAP_MOD_REPLACE )
                {
                        send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR,
-                           NULL, "unrecognized modify operation" );
+                           NULL, "unrecognized modify operation", NULL, NULL );
                        free( ndn );
                        modlist_free( modlist );
                        return LDAP_PROTOCOL_ERROR;
@@ -122,7 +122,7 @@ do_modify(
                        && (*modtail)->ml_op != LDAP_MOD_DELETE )
                {
                        send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR,
-                           NULL, "unrecognized modify operation" );
+                           NULL, "unrecognized modify operation", NULL, NULL );
                        free( ndn );
                        modlist_free( modlist );
                        return LDAP_PROTOCOL_ERROR;
@@ -161,14 +161,11 @@ do_modify(
        if ( (be = select_backend( ndn )) == NULL ) {
                free( ndn );
                modlist_free( modlist );
-               send_ldap_result( conn, op, rc = LDAP_PARTIAL_RESULTS, NULL,
-                   default_referral );
+               send_ldap_result( conn, op, rc = LDAP_REFERRAL,
+                       NULL, NULL, default_referral, NULL );
                return rc;
        }
 
-       /* alias suffix if approp */
-       ndn = suffixAlias ( ndn, op, be );
-
        /*
         * do the modify if 1 && (2 || 3)
         * 1) there is a modify function implemented in this backend;
@@ -186,12 +183,12 @@ do_modify(
 
                /* send a referral */
                } else {
-                       send_ldap_result( conn, op, rc = LDAP_PARTIAL_RESULTS, NULL,
-                           default_referral );
+                       send_ldap_result( conn, op, rc = LDAP_REFERRAL, NULL, NULL,
+                               be->be_update_refs ? be->be_update_refs : default_referral, NULL );
                }
        } else {
-               send_ldap_result( conn, op, rc = LDAP_UNWILLING_TO_PERFORM, NULL,
-                   "Function not implemented" );
+               send_ldap_result( conn, op, rc = LDAP_UNWILLING_TO_PERFORM,
+                   NULL, "Function not implemented", NULL, NULL );
        }
 
        free( ndn );
index c80a605fbd3ffcd58ad41ded1a1908150e65a4d4..482a9bdd74447d17b21bfa24e274f89a0b293f93 100644 (file)
@@ -53,8 +53,8 @@ do_modrdn(
        if( op->o_bind_in_progress ) {
                Debug( LDAP_DEBUG_ANY, "do_modrdn: SASL bind in progress.\n",
                        0, 0, 0 );
-               send_ldap_result( conn, op, LDAP_SASL_BIND_IN_PROGRESS, NULL,
-                   "SASL bind in progress" );
+               send_ldap_result( conn, op, LDAP_SASL_BIND_IN_PROGRESS,
+                       NULL, "SASL bind in progress", NULL, NULL );
                return LDAP_SASL_BIND_IN_PROGRESS;
        }
 
@@ -161,8 +161,8 @@ do_modrdn(
                        free( newrdn );
                        free( newSuperior );
                        free( nnewSuperior );
-                       send_ldap_result( conn, op, LDAP_PARTIAL_RESULTS, NULL,
-                                         default_referral );
+                       send_ldap_result( conn, op, LDAP_REFERRAL,
+                               NULL, NULL, default_referral, NULL );
                        return 0;
                }
        }
@@ -183,8 +183,8 @@ do_modrdn(
                free( newrdn ); 
                free( newSuperior );
                free( nnewSuperior );
-               send_ldap_result( conn, op, rc = LDAP_PARTIAL_RESULTS, NULL,
-                   default_referral );
+               send_ldap_result( conn, op, rc = LDAP_REFERRAL,
+                       NULL, NULL, default_referral, NULL );
                return rc;
        }
 
@@ -203,16 +203,12 @@ do_modrdn(
                free( nnewSuperior );
                
                send_ldap_result( conn, op, rc = LDAP_AFFECTS_MULTIPLE_DSAS,
-                                 NULL, "" );
+                       NULL, NULL, NULL, NULL );
            
                return rc;
 
        }
 
-
-       /* alias suffix if approp */
-       ndn = suffixAlias( ndn, op, be );
-
        /*
         * do the add if 1 && (2 || 3)
         * 1) there is an add function implemented in this backend;
@@ -231,12 +227,12 @@ do_modrdn(
                                    deloldrdn );
                        }
                } else {
-                       send_ldap_result( conn, op, rc = LDAP_PARTIAL_RESULTS, NULL,
-                           default_referral );
+                       send_ldap_result( conn, op, rc = LDAP_REFERRAL, NULL, NULL,
+                               be->be_update_refs ? be->be_update_refs : default_referral, NULL );
                }
        } else {
-               send_ldap_result( conn, op, rc = LDAP_UNWILLING_TO_PERFORM, NULL,
-                   "Function not implemented" );
+               send_ldap_result( conn, op, rc = LDAP_UNWILLING_TO_PERFORM,
+                       NULL, "Function not implemented", NULL, NULL );
        }
 
        free( ndn );
index a5a5274f120f1cab29df8750ea0fa999cb3e9e72..855a2e8dc047852be6fd9064b114e79851f7c99a 100644 (file)
@@ -139,55 +139,69 @@ monitor_info( Connection *conn, Operation *op )
        sprintf( buf, "%d", nconns );
        val.bv_val = buf;
        val.bv_len = strlen( buf );
-       attr_merge( e, "currentconnections", vals );
+       attr_merge( e, "currentConnections", vals );
 
        sprintf( buf, "%ld", connections_nextid() );
        val.bv_val = buf;
        val.bv_len = strlen( buf );
-       attr_merge( e, "totalconnections", vals );
+       attr_merge( e, "totalConnections", vals );
 
        sprintf( buf, "%ld", (long) dtblsize );
        val.bv_val = buf;
        val.bv_len = strlen( buf );
-       attr_merge( e, "dtablesize", vals );
+       attr_merge( e, "dTableSize", vals );
 
        sprintf( buf, "%d", nwritewaiters );
        val.bv_val = buf;
        val.bv_len = strlen( buf );
-       attr_merge( e, "writewaiters", vals );
+       attr_merge( e, "writeWaiters", vals );
 
        sprintf( buf, "%d", nreadwaiters );
        val.bv_val = buf;
        val.bv_len = strlen( buf );
-       attr_merge( e, "readwaiters", vals );
+       attr_merge( e, "readWaiters", vals );
 
        ldap_pvt_thread_mutex_lock(&num_ops_mutex);
        sprintf( buf, "%ld", num_ops_initiated );
        ldap_pvt_thread_mutex_unlock(&num_ops_mutex);
        val.bv_val = buf;
        val.bv_len = strlen( buf );
-       attr_merge( e, "opsinitiated", vals );
+       attr_merge( e, "opsInitiated", vals );
 
        ldap_pvt_thread_mutex_lock(&num_ops_mutex);
        sprintf( buf, "%ld", num_ops_completed );
        ldap_pvt_thread_mutex_unlock(&num_ops_mutex);
        val.bv_val = buf;
        val.bv_len = strlen( buf );
-       attr_merge( e, "opscompleted", vals );
+       attr_merge( e, "opsCompleted", vals );
 
        ldap_pvt_thread_mutex_lock(&num_sent_mutex);
        sprintf( buf, "%ld", num_entries_sent );
        ldap_pvt_thread_mutex_unlock(&num_sent_mutex);
        val.bv_val = buf;
        val.bv_len = strlen( buf );
-       attr_merge( e, "entriessent", vals );
+       attr_merge( e, "entriesSent", vals );
+
+       ldap_pvt_thread_mutex_lock(&num_sent_mutex);
+       sprintf( buf, "%ld", num_refs_sent );
+       ldap_pvt_thread_mutex_unlock(&num_sent_mutex);
+       val.bv_val = buf;
+       val.bv_len = strlen( buf );
+       attr_merge( e, "referencesSent", vals );
+
+       ldap_pvt_thread_mutex_lock(&num_sent_mutex);
+       sprintf( buf, "%ld", num_pdu_sent );
+       ldap_pvt_thread_mutex_unlock(&num_sent_mutex);
+       val.bv_val = buf;
+       val.bv_len = strlen( buf );
+       attr_merge( e, "pduSent", vals );
 
        ldap_pvt_thread_mutex_lock(&num_sent_mutex);
        sprintf( buf, "%ld", num_bytes_sent );
        ldap_pvt_thread_mutex_unlock(&num_sent_mutex);
        val.bv_val = buf;
        val.bv_len = strlen( buf );
-       attr_merge( e, "bytessent", vals );
+       attr_merge( e, "bytesSent", vals );
 
        currenttime = slap_get_time();
 
@@ -228,8 +242,10 @@ monitor_info( Connection *conn, Operation *op )
        attr_merge( e, "concurrency", vals );
 #endif
 
-       send_search_entry( &backends[0], conn, op, e, NULL, 0, 1 );
-       send_ldap_search_result( conn, op, LDAP_SUCCESS, NULL, NULL, 1 );
+       send_search_entry( &backends[0], conn, op, e,
+               NULL, 0, 1, NULL );
+       send_search_result( conn, op, LDAP_SUCCESS,
+               NULL, NULL, NULL, NULL, 1 );
 
        entry_free( e );
 }
index 442f2f450a4e9699b760e749236b7986025e58ce..4931978ea528974fde750ef35b4cc1ba9f0330b0 100644 (file)
@@ -119,6 +119,7 @@ void charray_free LDAP_P(( char **array ));
 int charray_inlist LDAP_P(( char **a, char *s ));
 char ** charray_dup LDAP_P(( char **a ));
 char ** str2charray LDAP_P(( char *str, char *brkstr ));
+char * charray2str LDAP_P(( char **a ));
 
 /*
  * controls.c
@@ -128,6 +129,8 @@ int get_ctrls LDAP_P((
        Operation *op,
        int senderrors ));
 
+int get_manageDSAit LDAP_P(( Operation *op ));
+
 /*
  * config.c
  */
@@ -257,17 +260,40 @@ void replog LDAP_P(( Backend *be, int optype, char *dn, void *change, int flag )
  * result.c
  */
 
+struct berval **get_entry_referrals LDAP_P((
+       Backend *be, Connection *conn, Operation *op,
+       Entry *e ));
+
 void send_ldap_result LDAP_P((
        Connection *conn, Operation *op,
-       int err, char *matched, char *text ));
+       int err, char *matched, char *text,
+       struct berval **refs,
+       LDAPControl **ctrls ));
 
 void send_ldap_disconnect LDAP_P((
        Connection *conn, Operation *op,
        int err, char *text ));
 
-void send_ldap_search_result LDAP_P((
+void send_search_result LDAP_P((
        Connection *conn, Operation *op,
-       int err, char *matched, char *text, int nentries ));
+       int err, char *matched, char *text,
+       struct berval **refs,
+       LDAPControl **ctrls,
+       int nentries ));
+
+int send_search_reference LDAP_P((
+       Backend *be, Connection *conn, Operation *op,
+       Entry *e, struct berval **refs, int scope,
+       LDAPControl **ctrls,
+       struct berval ***v2refs ));
+
+int send_search_entry LDAP_P((
+       Backend *be, Connection *conn, Operation *op,
+       Entry *e, char **attrs, int attrsonly, int opattrs,
+       LDAPControl **ctrls ));
+
+int str2result LDAP_P(( char *s,
+       int *code, char **matched, char **info ));
 
 /*
  * schema.c
@@ -286,6 +312,10 @@ int mr_add LDAP_P((LDAP_MATCHING_RULE *mr, slap_mr_normalize_func *normalize, sl
 void schema_info LDAP_P((Connection *conn, Operation *op, char **attrs, int attrsonly));
 int schema_init LDAP_P((void));
 
+int is_entry_objectclass LDAP_P(( Entry *, char* objectclass ));
+#define is_entry_alias(e)              is_entry_objectclass((e), "ALIAS")
+#define is_entry_referral(e)   is_entry_objectclass((e), "REFERRAL")
+
 
 /*
  * schemaparse.c
@@ -314,11 +344,6 @@ int value_cmp LDAP_P(( struct berval *v1, struct berval *v2, int syntax,
 int value_find LDAP_P(( struct berval **vals, struct berval *v, int syntax,
        int normalize ));
 
-/*
- * suffixAlias.c
- */
-char *suffixAlias LDAP_P(( char *dn, Operation *op, Backend *be ));
-
 /*
  * user.c
  */
@@ -330,7 +355,7 @@ void slap_init_user LDAP_P(( char *username, char *groupname ));
  * Other...
  */
 
-extern char            *default_referral;
+extern struct berval **default_referral;
 extern char            *replogfile;
 extern const char Versionstr[];
 extern int             active_threads;
@@ -347,7 +372,9 @@ extern int          ldap_syslog;
 
 extern ldap_pvt_thread_mutex_t num_sent_mutex;
 extern long            num_bytes_sent;
+extern long            num_pdu_sent;
 extern long            num_entries_sent;
+extern long            num_refs_sent;
 
 extern ldap_pvt_thread_mutex_t num_ops_mutex;
 extern long            num_ops_completed;
@@ -373,10 +400,10 @@ extern ldap_pvt_thread_mutex_t    gmtime_mutex;
 
 extern struct acl              *global_acl;
 
-extern int     slap_init LDAP_P((int mode, char* name));
-extern int     slap_startup LDAP_P((int dbnum));
-extern int     slap_shutdown LDAP_P((int dbnum));
-extern int     slap_destroy LDAP_P((void));
+int    slap_init LDAP_P((int mode, char* name));
+int    slap_startup LDAP_P((int dbnum));
+int    slap_shutdown LDAP_P((int dbnum));
+int    slap_destroy LDAP_P((void));
 
 struct sockaddr_in;
 
@@ -416,11 +443,6 @@ extern int do_search LDAP_P((Connection *conn, Operation *op));
 extern int     do_unbind LDAP_P((Connection *conn, Operation *op));
 extern int     do_extended LDAP_P((Connection *conn, Operation *op));
 
-extern int send_search_entry LDAP_P((
-       Backend *be, Connection *conn, Operation *op,
-       Entry *e, char **attrs, int attrsonly, int opattrs ));
-
-extern int str2result LDAP_P(( char *s, int *code, char **matched, char **info ));
 
 extern ber_socket_t dtblsize;
 
index 764bc2e6d72e0fbd456b05e9fae8089cb4a949e8..246a00776413aa7e1403ab024b71ff630e1ab054 100644 (file)
 #include <ac/signal.h>
 #include <ac/string.h>
 #include <ac/time.h>
-#include <ac/unistd.h>         /* get close() */
+#include <ac/unistd.h>
 
 #include "slap.h"
 
 /* we need LBER internals */
 #include "../../libraries/liblber/lber-int.h"
 
-static void
-send_ldap_result2(
-    Connection *conn,
-    Operation  *op,
-       int             disconnect,
-    ber_int_t  err,
-    char       *matched,
-    char       *text,
-    int                nentries
-)
+static char *v2ref( struct berval **ref )
 {
-       BerElement      *ber;
-       int             rc;
-       ber_tag_t       tag;
-       ber_len_t       bytes;
-       int     msgid;
+       size_t len, i;
+       char *v2;
 
-       assert( !LDAP_API_ERROR( err ) );
+       if(ref == NULL) return NULL;
 
-       if ( err == LDAP_PARTIAL_RESULTS && (text == NULL || *text == '\0') )
-               err = LDAP_NO_SUCH_OBJECT;
+       len = sizeof("Referral:");
+       v2 = ch_strdup("Referral:");
 
-       if( disconnect ) {
-               msgid = 0;      /* unsolicited */
-               if ( op->o_protocol > LDAP_VERSION3 ) {
-                       tag = LDAP_RES_EXTENDED;
-               }
-
-#define LDAP_UNSOLICITED_ERROR(e) \
-       (  (e) == LDAP_PROTOCOL_ERROR \
-       || (e) == LDAP_STRONG_AUTH_REQUIRED \
-       || (e) == LDAP_UNAVAILABLE )
+       for( i=0; ref[i] != NULL; i++ ) {
+               v2 = ch_realloc( v2, len + ref[i]->bv_len + 1 );
+               v2[len-1] = '\n';
+               memcpy(&v2[len], ref[i]->bv_val, ref[i]->bv_len );
+               len += ref[i]->bv_len;
+       }
 
-               assert( LDAP_UNSOLICITED_ERROR( err ) );
+       v2[len-1] = '\0';
+       return v2;
+}
 
-       } else {
-               msgid = op->o_msgid;
-
-               switch ( op->o_tag ) {
-               case LDAP_REQ_ABANDON:
-               case LDAP_REQ_UNBIND:
-               case LBER_ERROR:
-                       tag = LBER_SEQUENCE;
-                       msgid = 0;
-                       assert( LDAP_UNSOLICITED_ERROR( err ) );
-                       break;
+static ber_tag_t req2res( ber_tag_t tag )
+{
+       switch( tag ) {
+       case LDAP_REQ_ADD:
+       case LDAP_REQ_BIND:
+       case LDAP_REQ_COMPARE:
+       case LDAP_REQ_EXTENDED:
+       case LDAP_REQ_MODIFY:
+       case LDAP_REQ_MODRDN:
+               tag++;
+               break;
+
+       case LDAP_REQ_DELETE:
+               tag = LDAP_RES_DELETE;
+               break;
+
+       case LDAP_REQ_ABANDON:
+       case LDAP_REQ_UNBIND:
+               tag = LBER_SEQUENCE;
+               break;
+
+       case LDAP_REQ_SEARCH:
+               tag = LDAP_RES_SEARCH_RESULT;
+               break;
+
+       default:
+               assert( 0 );
+               tag = LBER_ERROR;
+       }
+       return tag;
+}
 
-               case LDAP_REQ_SEARCH:
-                       tag = LDAP_RES_SEARCH_RESULT;
-                       break;
+static void trim_refs_urls(
+       struct berval **refs )
+{
+       unsigned i;
 
-               case LDAP_REQ_DELETE:
-                       tag = LDAP_RES_DELETE;
-                       break;
+       if( refs == NULL ) return;
 
-               default:
-                       tag = op->o_tag + 1;
-                       break;
+       for( i=0; refs[i] != NULL; i++ ) {
+               if(     refs[i]->bv_len > sizeof("ldap://") &&
+                       strncasecmp( refs[i]->bv_val, "ldap://",
+                               sizeof("ldap://")-1 ) == 0 )
+               {
+                       unsigned j;
+                       for( j=sizeof("ldap://"); j<refs[i]->bv_len ; j++ ) {
+                               if( refs[i]->bv_val[j] = '/' ) {
+                                       refs[i]->bv_val[j] = '\0';
+                                       refs[i]->bv_len = j;
+                                       break;
+                               }
+                       }
                }
        }
+}
 
+struct berval **get_entry_referrals(
+       Backend *be,
+       Connection *conn,
+       Operation *op,
+       Entry *e )
+{
+       Attribute *attr;
+       struct berval **refs;
+       unsigned i, j;
 
-       ber = ber_alloc_t( LBER_USE_DER );
+       attr = attr_find( e->e_attrs, "ref" );
 
-       if ( ber == NULL ) {
-               Debug( LDAP_DEBUG_ANY, "ber_alloc failed\n", 0, 0, 0 );
-               return;
+       if( attr == NULL ) return NULL;
+
+       for( i=0; attr->a_vals[i] != NULL; i++ ) {
+               /* count references */
        }
 
-#ifdef LDAP_CONNECTIONLESS
-       if ( op->o_cldap ) {
-               rc = ber_printf( ber, "{is{t{ess}}}", msgid, "", tag,
-                   err, matched ? matched : "", text ? text : "" );
-       } else
-#endif
-       if( tag == LDAP_RES_EXTENDED ) {
-               rc = ber_printf( ber, "{it{esss}}",
-                       msgid, tag, err,
-                       "", text ? text : "",
-                       LDAP_NOTICE_DISCONNECT );
+       if( i < 1 ) return NULL;
 
-       } else {
-               rc = ber_printf( ber, "{it{ess}}",
-                       msgid, tag, err,
-                       matched ? matched : "", text ? text : "" );
+       refs = ch_malloc( i + 1 );
+
+       for( i=0, j=0; attr->a_vals[i] != NULL; i++ ) {
+               unsigned k;
+               struct berval *ref = ber_bvdup( attr->a_vals[i] );
+
+               /* trim the label */
+               for( k=0; k<ref->bv_len; k++ ) {
+                       if( isspace(ref->bv_val[k]) ) {
+                               ref->bv_val[k] = '\0';
+                               ref->bv_len = k;
+                               break;
+                       }
+               }
+
+               if(     ref->bv_len > 0 ) {
+                       refs[j++] = ref;
+
+               } else {
+                       ber_bvfree( ref );
+               }
        }
 
-       if ( rc == -1 ) {
-               Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 );
-               return;
+       refs[j] = NULL;
+
+       if( j == 0 ) {
+               ber_bvecfree( refs );
+               refs = NULL;
        }
 
+       /* we should check that a referral value exists... */
+
+       return refs;
+}
+
+static long send_ldap_ber(
+       Connection *conn,
+       BerElement *ber )
+{
+       ber_len_t bytes = ber_pvt_ber_bytes( ber );
+
        /* write only one pdu at a time - wait til it's our turn */
        ldap_pvt_thread_mutex_lock( &conn->c_write_mutex );
 
-       /* lock the connection */
+       /* lock the connection */ 
        ldap_pvt_thread_mutex_lock( &conn->c_mutex );
 
        /* write the pdu */
-       bytes = ber_pvt_ber_bytes( ber );
-
-       while ( 1 ) {
+       while( 1 ) {
                int err;
 
                if ( connection_state_closing( conn ) ) {
                        ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
                        ldap_pvt_thread_mutex_unlock( &conn->c_write_mutex );
-                       return;
+                       return 0;
                }
 
                if ( ber_flush( conn->c_sb, ber, 1 ) == 0 ) {
@@ -147,7 +191,7 @@ send_ldap_result2(
 
                        ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
                        ldap_pvt_thread_mutex_unlock( &conn->c_write_mutex );
-                       return;
+                       return( -1 );
                }
 
                /* wait for socket to be write-ready */
@@ -161,31 +205,126 @@ send_ldap_result2(
        ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
        ldap_pvt_thread_mutex_unlock( &conn->c_write_mutex );
 
+       return bytes;
+}
+
+static void
+send_ldap_response(
+    Connection *conn,
+    Operation  *op,
+       ber_tag_t       tag,
+       ber_int_t       msgid,
+    ber_int_t  err,
+    char       *matched,
+    char       *text,
+       struct berval   **ref,
+       char    *resoid,
+       struct berval   *resdata,
+       LDAPControl **ctrls
+)
+{
+       BerElement      *ber;
+       int             rc;
+       long    bytes;
+
+       assert( ctrls == NULL ); /* ctrls not implemented */
+
+       ber = ber_alloc_t( LBER_USE_DER );
+
+       Debug( LDAP_DEBUG_TRACE, "send_ldap_response: tag=%ld msgid=%ld err=%ld\n",
+               (long) tag, (long) msgid, (long) err );
+
+       if ( ber == NULL ) {
+               Debug( LDAP_DEBUG_ANY, "ber_alloc failed\n", 0, 0, 0 );
+               return;
+       }
+
+#ifdef LDAP_CONNECTIONLESS
+       if ( op->o_cldap ) {
+               rc = ber_printf( ber, "{is{t{ess}}}", msgid, "", tag,
+                   err, matched ? matched : "", text ? text : "" );
+       } else
+#endif
+       {
+               rc = ber_printf( ber, "{it{ess",
+                       msgid, tag, err,
+                       matched == NULL ? "" : matched,
+                       text == NULL ? "" : text );
+
+               if( rc != -1 && ref != NULL ) {
+                       rc = ber_printf( ber, "{V}", ref );
+               }
+
+               if( rc != -1 && resoid != NULL ) {
+                       rc = ber_printf( ber, "s", resoid );
+               }
+
+               if( rc != -1 && resdata != NULL ) {
+                       rc = ber_printf( ber, "O", resdata );
+
+               }
+
+               if( rc != -1 ) {
+                       rc = ber_printf( ber, "}}" );
+               }
+       }
+
+       if ( rc == -1 ) {
+               Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 );
+               return;
+       }
+
+       /* send BER */
+       bytes = send_ldap_ber( conn, ber );
+
+       if ( bytes < 0 ) {
+               Debug( LDAP_DEBUG_ANY,
+                       "send_ldap_response: ber write failed\n",
+                       0, 0, 0 );
+               return;
+       }
+
        ldap_pvt_thread_mutex_lock( &num_sent_mutex );
        num_bytes_sent += bytes;
+       num_pdu_sent++;
        ldap_pvt_thread_mutex_unlock( &num_sent_mutex );
-
-       Statslog( LDAP_DEBUG_STATS,
-           "conn=%ld op=%ld RESULT err=%ld tag=%lu nentries=%d\n",
-               (long) conn->c_connid, (long) op->o_opid,
-               (long) err, (long) tag, nentries );
-
        return;
 }
 
+
 void
-send_ldap_result(
+send_ldap_disconnect(
     Connection *conn,
     Operation  *op,
     ber_int_t  err,
-    char       *matched,
     char       *text
 )
 {
-       assert( !LDAP_API_ERROR( err ) );
+       ber_tag_t tag;
+       ber_int_t msgid;
+       char *reqoid;
 
-       Debug( LDAP_DEBUG_TRACE, "send_ldap_result %d:%s:%s\n",
-               err, matched ?  matched : "", text ? text : "" );
+#define LDAP_UNSOLICITED_ERROR(e) \
+       (  (e) == LDAP_PROTOCOL_ERROR \
+       || (e) == LDAP_STRONG_AUTH_REQUIRED \
+       || (e) == LDAP_UNAVAILABLE )
+
+       assert( LDAP_UNSOLICITED_ERROR( err ) );
+
+       Debug( LDAP_DEBUG_TRACE,
+               "send_ldap_disconnect %d:%s\n",
+               err, text ? text : "", NULL );
+
+       if ( op->o_protocol < LDAP_VERSION3 ) {
+               reqoid = NULL;
+               tag = req2res( op->o_tag );
+               msgid = (tag != LBER_SEQUENCE) ? op->o_msgid : 0;
+
+       } else {
+               reqoid = LDAP_NOTICE_DISCONNECT;
+               tag = LDAP_RES_EXTENDED;
+               msgid = 0;
+       }
 
 #ifdef LDAP_CONNECTIONLESS
        if ( op->o_cldap ) {
@@ -197,22 +336,54 @@ send_ldap_result(
                    0 );
        }
 #endif
-       send_ldap_result2( conn, op, 0, err, matched, text, 0 );
+       send_ldap_response( conn, op, tag, msgid,
+               err, NULL, text, NULL,
+               reqoid, NULL, NULL );
+
+       Statslog( LDAP_DEBUG_STATS,
+           "conn=%ld op=%ld DISCONNECT err=%ld tag=%lu text=%s\n",
+               (long) conn->c_connid, (long) op->o_opid,
+               (long) tag, (long) err, text );
 }
 
 void
-send_ldap_disconnect(
+send_ldap_result(
     Connection *conn,
     Operation  *op,
     ber_int_t  err,
-    char       *text
+    char       *matched,
+    char       *text,
+       struct berval **ref,
+       LDAPControl **ctrls
 )
 {
+       ber_tag_t tag;
+       ber_int_t msgid;
+       char *tmp = NULL;
+
        assert( !LDAP_API_ERROR( err ) );
 
-       Debug( LDAP_DEBUG_TRACE,
-               "send_ldap_disconnect %d:%s\n",
-               err, text ? text : "", NULL );
+       Debug( LDAP_DEBUG_TRACE, "send_ldap_result %d:%s:%s\n",
+               err, matched ?  matched : "", text ? text : "" );
+
+       assert( err != LDAP_PARTIAL_RESULTS );
+
+       if( op->o_tag != LDAP_REQ_SEARCH ) {
+               trim_refs_urls( ref );
+       }
+
+       if ( err == LDAP_REFERRAL ) {
+               if( ref == NULL ) {
+                       err = LDAP_NO_SUCH_OBJECT;
+               } else if ( op->o_protocol < LDAP_VERSION3 ) {
+                       err = LDAP_PARTIAL_RESULTS;
+                       tmp = text = v2ref( ref );
+                       ref = NULL;
+               }
+       }
+
+       tag = req2res( op->o_tag );
+       msgid = (tag != LBER_SEQUENCE) ? op->o_msgid : 0;
 
 #ifdef LDAP_CONNECTIONLESS
        if ( op->o_cldap ) {
@@ -224,25 +395,88 @@ send_ldap_disconnect(
                    0 );
        }
 #endif
-       send_ldap_result2( conn, op, 0, err, NULL, text, 0 );
+
+       send_ldap_response( conn, op, tag, msgid,
+               err, matched, text, ref,
+               NULL, NULL, ctrls );
+
+       Statslog( LDAP_DEBUG_STATS,
+           "conn=%ld op=%ld RESULT err=%ld tag=%lu text=%s\n",
+               (long) conn->c_connid, (long) op->o_opid,
+               (long) err, (long) tag, text );
+
+       if( tmp != NULL ) {
+               free(tmp);
+       }
 }
 
+
 void
-send_ldap_search_result(
+send_search_result(
     Connection *conn,
     Operation  *op,
     ber_int_t  err,
     char       *matched,
-    char       *text,
+       char    *text,
+    struct berval **refs,
+       LDAPControl **ctrls,
     int                nentries
 )
 {
+       ber_tag_t tag;
+       ber_int_t msgid;
+       char *tmp = NULL;
+       assert( !LDAP_API_ERROR( err ) );
+
        Debug( LDAP_DEBUG_TRACE, "send_ldap_search_result %d:%s:%s\n",
                err, matched ?  matched : "", text ? text : "" );
 
-       send_ldap_result2( conn, op, 0, err, matched, text, nentries );
+       assert( err != LDAP_PARTIAL_RESULTS );
+
+       trim_refs_urls( refs );
+
+       if( op->o_protocol < LDAP_VERSION3 ) {
+               /* send references in search results */
+               if( err == LDAP_REFERRAL ) {
+                       err = LDAP_PARTIAL_RESULTS;
+                       tmp = text = v2ref( refs );
+                       refs = NULL;
+               }
+
+       } else {
+               /* don't send references in search results */
+               if( err == LDAP_REFERRAL ) {
+                       err = LDAP_SUCCESS;
+                       refs = NULL;
+               }
+       }
+
+       tag = req2res( op->o_tag );
+       msgid = (tag != LBER_SEQUENCE) ? op->o_msgid : 0;
+
+#ifdef LDAP_CONNECTIONLESS
+       if ( op->o_cldap ) {
+               ber_pvt_sb_udp_set_dst( &conn->c_sb, &op->o_clientaddr );
+               Debug( LDAP_DEBUG_TRACE, "UDP response to %s port %d\n", 
+                   inet_ntoa(((struct sockaddr_in *)
+                   &op->o_clientaddr)->sin_addr ),
+                   ((struct sockaddr_in *) &op->o_clientaddr)->sin_port,
+                   0 );
+       }
+#endif
+
+       send_ldap_response( conn, op, tag, msgid,
+               err, matched, text, refs,
+               NULL, NULL, ctrls );
+
+       Statslog( LDAP_DEBUG_STATS,
+           "conn=%ld op=%ld SEARCH RESULT err=%ld tag=%lu text=%s\n",
+               (long) conn->c_connid, (long) op->o_opid,
+               (long) err, (long) tag, text );
+
 }
 
+
 int
 send_search_entry(
     Backend    *be,
@@ -251,7 +485,8 @@ send_search_entry(
     Entry      *e,
     char       **attrs,
     int                attrsonly,
-       int             opattrs
+       int             opattrs,
+       LDAPControl **ctrls
 )
 {
        BerElement      *ber;
@@ -259,6 +494,7 @@ send_search_entry(
        int             i, rc=-1, bytes;
        struct acl      *acl;
        char            *edn;
+       int             allattrs;
 
        Debug( LDAP_DEBUG_TRACE, "=> send_search_entry (%s)\n", e->e_dn, 0, 0 );
 
@@ -287,8 +523,8 @@ send_search_entry(
 
        if ( ber == NULL ) {
                Debug( LDAP_DEBUG_ANY, "ber_alloc failed\n", 0, 0, 0 );
-               send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL,
-                       "ber_alloc" );
+               send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+                       NULL, "allocating BER error", NULL, NULL );
                goto error_return;
        }
 
@@ -298,25 +534,28 @@ send_search_entry(
        if ( rc == -1 ) {
                Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 );
                ber_free( ber, 1 );
-               send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL,
-                   "ber_printf dn" );
+               send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+                   NULL, "encoding dn error", NULL, NULL );
                goto error_return;
        }
 
+       /* check for special all user attributes ("*") attribute */
+       allattrs = attrs == NULL
+               ? 1
+               : charray_inlist( attrs, LDAP_ALL_USER_ATTRIBUTES );
+
        for ( a = e->e_attrs; a != NULL; a = a->a_next ) {
                regmatch_t       matches[MAXREMATCHES];
 
                if ( attrs == NULL ) {
                        /* all addrs request, skip operational attributes */
-                       if( !opattrs && oc_check_operational_attr( a->a_type )) {
+                       if( !opattrs && oc_check_operational_attr( a->a_type ) ) {
                                continue;
                        }
 
                } else {
                        /* specific addrs requested */
-                       if ( !charray_inlist( attrs, a->a_type )
-                               && !charray_inlist( attrs, LDAP_ALL_USER_ATTRIBUTES ) )
-                       {
+                       if ( !allattrs && !charray_inlist( attrs, a->a_type ) ) {
                                continue;
                        }
                }
@@ -334,7 +573,7 @@ send_search_entry(
                        Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 );
                        ber_free( ber, 1 );
                        send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
-                           NULL, "ber_printf type" );
+                           NULL, "encoding type error", NULL, NULL );
                        goto error_return;
                }
 
@@ -351,9 +590,8 @@ send_search_entry(
                                        Debug( LDAP_DEBUG_ANY,
                                            "ber_printf failed\n", 0, 0, 0 );
                                        ber_free( ber, 1 );
-                                       send_ldap_result( conn, op,
-                                           LDAP_OPERATIONS_ERROR, NULL,
-                                           "ber_printf value" );
+                                       send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+                                               NULL, "encoding value error", NULL, NULL );
                                        goto error_return;
                                }
                        }
@@ -363,7 +601,7 @@ send_search_entry(
                        Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 );
                        ber_free( ber, 1 );
                        send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
-                           NULL, "ber_printf type end" );
+                           NULL, "encode end error", NULL, NULL );
                        goto error_return;
                }
        }
@@ -373,67 +611,116 @@ send_search_entry(
        if ( rc == -1 ) {
                Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 );
                ber_free( ber, 1 );
-               send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL,
-                   "ber_printf entry end" );
+               send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+                       NULL, "encode entry end error", NULL, NULL );
                return( 1 );
        }
 
-       bytes = ber_pvt_ber_bytes( ber );
+       bytes = send_ldap_ber( conn, ber );
 
-       /* write only one pdu at a time - wait til it's our turn */
-       ldap_pvt_thread_mutex_lock( &conn->c_write_mutex );
+       if ( bytes < 0 ) {
+               Debug( LDAP_DEBUG_ANY,
+                       "send_ldap_response: ber write failed\n",
+                       0, 0, 0 );
+               return -1;
+       }
 
-       /* lock the connection */ 
-       ldap_pvt_thread_mutex_lock( &conn->c_mutex );
+       ldap_pvt_thread_mutex_lock( &num_sent_mutex );
+       num_bytes_sent += bytes;
+       num_entries_sent++;
+       num_pdu_sent++;
+       ldap_pvt_thread_mutex_unlock( &num_sent_mutex );
 
-       /* write the pdu */
-       while( 1 ) {
-               int err;
+       Statslog( LDAP_DEBUG_STATS2, "conn=%ld op=%ld ENTRY dn=\"%s\"\n",
+           (long) conn->c_connid, (long) op->o_opid, e->e_dn, 0, 0 );
 
-               if ( connection_state_closing( conn ) ) {
-                       ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
-                       ldap_pvt_thread_mutex_unlock( &conn->c_write_mutex );
-                       return 0;
-               }
+       Debug( LDAP_DEBUG_TRACE, "<= send_search_entry\n", 0, 0, 0 );
 
-               if ( ber_flush( conn->c_sb, ber, 1 ) == 0 ) {
-                       break;
-               }
+       rc = 0;
 
-               err = errno;
+error_return:;
+       return( rc );
+}
 
-               /*
-                * we got an error.  if it's ewouldblock, we need to
-                * wait on the socket being writable.  otherwise, figure
-                * it's a hard error and return.
-                */
+int
+send_search_reference(
+    Backend    *be,
+    Connection *conn,
+    Operation  *op,
+    Entry      *e,
+       struct berval **refs,
+       int scope,
+       LDAPControl **ctrls,
+    struct berval ***v2refs
+)
+{
+       BerElement      *ber;
+       int rc;
+       int bytes;
 
-               Debug( LDAP_DEBUG_CONNS, "ber_flush failed errno %d msg (%s)\n",
-                   err, err > -1 && err < sys_nerr ? sys_errlist[err]
-                   : "unknown", 0 );
+       Debug( LDAP_DEBUG_TRACE, "=> send_search_entry (%s)\n", e->e_dn, 0, 0 );
 
-               if ( err != EWOULDBLOCK && err != EAGAIN ) {
-                       connection_closing( conn );
+       if ( ! access_allowed( be, conn, op, e,
+               "entry", NULL, ACL_READ ) )
+       {
+               Debug( LDAP_DEBUG_ACL,
+                       "send_search_reference: access to entry not allowed\n",
+                   0, 0, 0 );
+               return( 1 );
+       }
 
-                       ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
-                       ldap_pvt_thread_mutex_unlock( &conn->c_write_mutex );
-                       return( -1 );
+       if ( ! access_allowed( be, conn, op, e,
+               "ref", NULL, ACL_READ ) )
+       {
+               Debug( LDAP_DEBUG_ACL,
+                       "send_search_reference: access to reference not allowed\n",
+                   0, 0, 0 );
+               return( 1 );
+       }
+
+       if( refs == NULL ) {
+               Debug( LDAP_DEBUG_ANY,
+                       "send_search_reference: null ref in (%s)\n", 
+                       e->e_dn, 0, 0 );
+               return( 1 );
+       }
+
+       if( op->o_protocol < LDAP_VERSION3 ) {
+               /* save the references for the result */
+               if( *refs == NULL ) {
+                       value_add( v2refs, refs );
                }
+               return 0;
+       }
 
-               /* wait for socket to be write-ready */
-               conn->c_writewaiter = 1;
-               slapd_set_write( ber_pvt_sb_get_desc( conn->c_sb ), 1 );
+       ber = ber_alloc_t( LBER_USE_DER );
 
-               ldap_pvt_thread_cond_wait( &conn->c_write_cv, &conn->c_mutex );
-               conn->c_writewaiter = 0;
+       if ( ber == NULL ) {
+               Debug( LDAP_DEBUG_ANY,
+                       "send_search_reference: ber_alloc failed\n", 0, 0, 0 );
+               send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+                       NULL, "alloc BER error", NULL, NULL );
+               return -1;
        }
 
-       ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
-       ldap_pvt_thread_mutex_unlock( &conn->c_write_mutex );
+       rc = ber_printf( ber, "{it{V}}", op->o_msgid,
+               LDAP_RES_SEARCH_REFERENCE, refs );
+
+       if ( rc == -1 ) {
+               Debug( LDAP_DEBUG_ANY,
+                       "send_search_reference: ber_printf failed\n", 0, 0, 0 );
+               ber_free( ber, 1 );
+               send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+                       NULL, "encode dn error", NULL, NULL );
+               return -1;
+       }
+
+       bytes = send_ldap_ber( conn, ber );
 
        ldap_pvt_thread_mutex_lock( &num_sent_mutex );
        num_bytes_sent += bytes;
-       num_entries_sent++;
+       num_refs_sent++;
+       num_pdu_sent++;
        ldap_pvt_thread_mutex_unlock( &num_sent_mutex );
 
        Statslog( LDAP_DEBUG_STATS2, "conn=%ld op=%ld ENTRY dn=\"%s\"\n",
@@ -441,12 +728,10 @@ send_search_entry(
 
        Debug( LDAP_DEBUG_TRACE, "<= send_search_entry\n", 0, 0, 0 );
 
-       rc = 0;
-
-error_return:;
-       return( rc );
+       return 0;
 }
 
+
 int
 str2result(
     char       *s,
index 540d218d1363740b68537f526de6306329048859..25d5f7ddbfdd9ba9bf1353bc52d7f2960ddfa29e 100644 (file)
@@ -93,9 +93,14 @@ root_dse_info( Connection *conn, Operation *op, char **attrs, int attrsonly )
                attr_merge( e, "supportedSASLMechanism", vals );
        }
 
+       if ( default_referral != NULL ) {
+               attr_merge( e, "ref", default_referral );
+       }
 
-       send_search_entry( &backends[0], conn, op, e, attrs, attrsonly, 1 );
-       send_ldap_search_result( conn, op, LDAP_SUCCESS, NULL, NULL, 1 );
+       send_search_entry( &backends[0], conn, op,
+               e, attrs, attrsonly, 1, NULL );
+       send_search_result( conn, op, LDAP_SUCCESS,
+               NULL, NULL, NULL, NULL, 1 );
 
        entry_free( e );
 }
index e71913e0e66b868fac3235491b20ca69c5372b20..e2e2294d56093413c6d85a73b8ca5a6f34f5737d 100644 (file)
@@ -1143,8 +1143,10 @@ schema_info( Connection *conn, Operation *op, char **attrs, int attrsonly )
                return;
        }
        
-       send_search_entry( &backends[0], conn, op, e, attrs, attrsonly, 0 );
-       send_ldap_search_result( conn, op, LDAP_SUCCESS, NULL, NULL, 1 );
+       send_search_entry( &backends[0], conn, op,
+               e, attrs, attrsonly, 0, NULL );
+       send_search_result( conn, op, LDAP_SUCCESS,
+               NULL, NULL, NULL, NULL, 1 );
 
        entry_free( e );
 }
@@ -1179,3 +1181,35 @@ oc_print( ObjectClass *oc )
 }
 
 #endif
+
+
+int is_entry_objectclass(
+       Entry*  e,
+       char*   oc)
+{
+       Attribute *attr;
+       struct berval bv;
+
+       if( e == NULL || oc == NULL || *oc == '\0' )
+               return 0;
+
+       /*
+        * find objectClass attribute
+        */
+       attr = attr_find(e->e_attrs, "objectclass");
+
+       if( attr == NULL ) {
+               /* no objectClass attribute */
+               return 0;
+       }
+
+       bv.bv_val = oc;
+       bv.bv_len = strlen( bv.bv_val );
+
+       if( value_find(attr->a_vals, &bv, attr->a_syntax, 1) != 0) {
+               /* entry is not of this objectclass */
+               return 0;
+       }
+
+       return 1;
+}
\ No newline at end of file
index fa5c8900a606a78f137f2c298ad66ca849097101..18d5430be43bcfb91a8788917d9e61705ceb231c 100644 (file)
@@ -432,3 +432,14 @@ objectclass ( 2.5.6.20 NAME 'dmd' SUP top STRUCTURAL MUST ( dmdName )
 
 objectclass ( 1.3.6.1.4.1.1466.101.120.111 NAME 'extensibleObject'
       SUP top AUXILIARY )
+
+#
+# From draft-ietf-ldapext-nameref-00.txt
+#      used to represent referrals in the directory
+#
+attribute ( 2.16.840.1.113730.3.1.34 NAME 'ref' DESC 'URL Reference'
+       EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.1466.115.121.1.26
+       USAGE distributedOperation )
+
+objectclass ( 2.16.840.1.113730.3.2.6 NAME 'referral'
+       SUP top STRUCTURAL MAY ( ref ) )
index 38f44be01cc651c3f81486aa7eec93ef53c6dc85..b9906a12c9111a69bc617ac4c4c24559c530977f 100644 (file)
@@ -41,8 +41,8 @@ do_search(
        if( op->o_bind_in_progress ) {
                Debug( LDAP_DEBUG_ANY, "do_search: SASL bind in progress.\n",
                        0, 0, 0 );
-               send_ldap_result( conn, op, LDAP_SASL_BIND_IN_PROGRESS, NULL,
-                   "SASL bind in progress" );
+               send_ldap_result( conn, op, LDAP_SASL_BIND_IN_PROGRESS,
+                       NULL, "SASL bind in progress", NULL, NULL );
                return LDAP_SASL_BIND_IN_PROGRESS;
        }
 
@@ -80,10 +80,27 @@ do_search(
                goto return_results;
        }
 
-       if ( scope != LDAP_SCOPE_BASE && scope != LDAP_SCOPE_ONELEVEL
-           && scope != LDAP_SCOPE_SUBTREE ) {
-               send_ldap_disconnect( conn, op,
-                       LDAP_PROTOCOL_ERROR, "decoding error" );
+       switch( scope ) {
+       case LDAP_SCOPE_BASE:
+       case LDAP_SCOPE_ONELEVEL:
+       case LDAP_SCOPE_SUBTREE:
+               break;
+       default:
+               send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR,
+                       NULL, "invalid scope", NULL, NULL );
+               rc = -1;
+               goto return_results;
+       }
+
+       switch( deref ) {
+       case LDAP_DEREF_NEVER:
+       case LDAP_DEREF_FINDING:
+       case LDAP_DEREF_SEARCHING:
+       case LDAP_DEREF_ALWAYS:
+               break;
+       default:
+               send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR,
+                       NULL, "invalid deref", NULL, NULL );
                rc = -1;
                goto return_results;
        }
@@ -100,7 +117,8 @@ do_search(
                        send_ldap_disconnect( conn, op,
                                LDAP_PROTOCOL_ERROR, "decode error" );
                } else {
-                       send_ldap_result( conn, op, err, NULL, "Bad search filter" );
+                       send_ldap_result( conn, op, err,
+                               NULL, "Bad search filter", NULL, NULL );
                }
                goto return_results;
        }
@@ -137,7 +155,6 @@ do_search(
            "conn=%d op=%d SRCH base=\"%s\" scope=%d filter=\"%s\"\n",
            conn->c_connid, op->o_opid, base, scope, fstr );
 
-#if defined( SLAPD_MONITOR_DN ) || defined( SLAPD_CONFIG_DN ) || defined( SLAPD_SCHEMA_DN )
        if ( scope == LDAP_SCOPE_BASE ) {
 #if defined( SLAPD_MONITOR_DN )
                if ( strcmp( base, SLAPD_MONITOR_DN ) == 0 ) {
@@ -145,24 +162,25 @@ do_search(
                        goto return_results;
                }
 #endif
+
 #if defined( SLAPD_CONFIG_DN )
                if ( strcmp( base, SLAPD_CONFIG_DN ) == 0 ) {
                        config_info( conn, op );
                        goto return_results;
                }
 #endif
+
 #if defined( SLAPD_SCHEMA_DN )
                if ( strcmp( base, SLAPD_SCHEMA_DN ) == 0 ) {
                        schema_info( conn, op, attrs, attrsonly );
                        goto return_results;
                }
 #endif
-       }
-#endif /* monitor or config or schema dn */
 
-       if ( strcmp( base, LDAP_ROOT_DSE ) == 0 && scope == LDAP_SCOPE_BASE ) {
-               root_dse_info( conn, op, attrs, attrsonly );
-               goto return_results;
+               if ( strcmp( base, LDAP_ROOT_DSE ) == 0 ) {
+                       root_dse_info( conn, op, attrs, attrsonly );
+                       goto return_results;
+               }
        }
 
        /*
@@ -171,22 +189,19 @@ do_search(
         * if we don't hold it.
         */
        if ( (be = select_backend( base )) == NULL ) {
-               send_ldap_result( conn, op, rc = LDAP_PARTIAL_RESULTS, NULL,
-                   default_referral );
+               send_ldap_result( conn, op, rc = LDAP_REFERRAL,
+                       NULL, NULL, default_referral, NULL );
 
                goto return_results;
        }
 
-       /* translate the base if it matches an aliased base part */
-       base = suffixAlias ( base, op, be );
-
        /* actually do the search and send the result(s) */
        if ( be->be_search ) {
                (*be->be_search)( be, conn, op, base, scope, deref, sizelimit,
                    timelimit, filter, fstr, attrs, attrsonly );
        } else {
-               send_ldap_result( conn, op, rc = LDAP_UNWILLING_TO_PERFORM, NULL,
-                   "Function not implemented" );
+               send_ldap_result( conn, op, rc = LDAP_UNWILLING_TO_PERFORM,
+                       NULL, "Function not implemented", NULL, NULL );
        }
 
 return_results:;
index 41438d271df089b16798ad2b7da7bd51c21a6721..d7fd7eb4c4aa5276d63e762d7ccb4e5a66ef0700 100644 (file)
@@ -193,11 +193,11 @@ typedef struct entry {
 struct access {
 
 #define ACL_NONE               0x0001
-#define ACL_AUTH               0x0002
-#define ACL_COMPARE            0x0004
-#define ACL_SEARCH             0x0008
-#define ACL_READ               0x0010
-#define ACL_WRITE              0x0020
+#define ACL_AUTH               0x0004
+#define ACL_COMPARE            0x0008
+#define ACL_SEARCH             0x0010
+#define ACL_READ               0x0020
+#define ACL_WRITE              0x0040
 #define ACL_PRIV_MASK  0x00ff
 
 #define ACL_SELF               0x4000
@@ -394,12 +394,11 @@ struct backend_db {
        /* these should be renamed from be_ to bd_ */
        char    **be_suffix;    /* the DN suffixes of data in this backend */
        char    **be_nsuffix;   /* the normalized DN suffixes in this backend */
-       char    **be_suffixAlias;       /* the DN suffix aliases of data in this backend */
        char    *be_root_dn;    /* the magic "root" dn for this db      */
        char    *be_root_ndn;   /* the magic "root" normalized dn for this db   */
        char    *be_root_pw;    /* the magic "root" password for this db        */
        int     be_readonly;    /* 1 => db is in "read only" mode          */
-       int     be_maxDerefDepth;       /* limit for depth of an alias deref  */
+       unsigned int be_max_deref_depth;       /* limit for depth of an alias deref  */
        int     be_sizelimit;   /* size limit for this backend             */
        int     be_timelimit;   /* time limit for this backend             */
        struct acl *be_acl;     /* access control list for this backend    */
@@ -407,6 +406,7 @@ struct backend_db {
        char    **be_replica;   /* replicas of this backend (in master)    */
        char    *be_replogfile; /* replication log file (in master)        */
        char    *be_update_ndn; /* allowed to make changes (in replicas)   */
+       struct berval **be_update_refs; /* where to refer modifying clients to */
        int     be_lastmod;     /* keep track of lastmodified{by,time}     */
 
        char    *be_realm;
index c3c8b136b0d79050ed64f1740278ad4c0b716adc..01451706ffd02bdeed5f3f3ae1aca5eb5c31396e 100644 (file)
@@ -3,6 +3,7 @@ attribute       personalsignature                       bin
 attribute      jpegphoto                               bin
 attribute      audio                                   bin
 attribute      labeledurl                              ces
+attribute      ref                                             ces
 attribute      userpassword                            ces
 attribute      telephonenumber                         tel
 attribute      facsimiletelephonenumber        fax     tel
index a8c39ef68b874815d501c0f981b965de207a9308..ebe7203c0f9c69a8b614a9ae0857aeb981e755a7 100644 (file)
@@ -53,7 +53,7 @@ BSC32=bscmake.exe
 # ADD BSC32 /nologo
 LINK32=link.exe
 # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
-# ADD LINK32 hs_regex.lib libdb.lib wsock32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 hs_regex.lib libdb.lib ws2_32.lib /nologo /subsystem:console /machine:I386
 
 !ELSEIF  "$(CFG)" == "slapd - Win32 Debug"
 
@@ -77,7 +77,7 @@ BSC32=bscmake.exe
 # ADD BSC32 /nologo
 LINK32=link.exe
 # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 hs_regex.lib libdb.lib wsock32.lib advapi32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 hs_regex.lib libdb.lib ws2_32.lib advapi32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
 
 !ELSEIF  "$(CFG)" == "slapd - Win32 Single Debug"
 
@@ -102,7 +102,7 @@ BSC32=bscmake.exe
 # ADD BSC32 /nologo
 LINK32=link.exe
 # ADD BASE LINK32 hs_regexd.lib libdbs.lib wsock32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 hs_regex.lib libdb.lib wsock32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 hs_regex.lib libdb.lib ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
 
 !ELSEIF  "$(CFG)" == "slapd - Win32 Single Release"
 
@@ -127,7 +127,7 @@ BSC32=bscmake.exe
 # ADD BSC32 /nologo
 LINK32=link.exe
 # ADD BASE LINK32 hs_regex.lib libdb.lib wsock32.lib /nologo /subsystem:console /machine:I386
-# ADD LINK32 hs_regex.lib libdb.lib wsock32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 hs_regex.lib libdb.lib ws2_32.lib /nologo /subsystem:console /machine:I386
 
 !ENDIF 
 
index e9c636c214035b8e168a3a101546b960ee354030..b3c3ca4ded913e90af50504075fbd4e11c822ead 100644 (file)
@@ -102,6 +102,18 @@ Package=<4>
 
 ###############################################################################
 
+Project: "setup"=..\..\include\setup.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
 Project: "slapd"=.\slapd.dsp - Package Owner=<4>
 
 Package=<5>
@@ -134,6 +146,9 @@ Package=<4>
     Begin Project Dependency
     Project_Dep_Name libslapd
     End Project Dependency
+    Begin Project Dependency
+    Project_Dep_Name setup
+    End Project Dependency
 }}}
 
 ###############################################################################
index 5759eb6da1fd1c3decc22d8808b18087bfefc3e7..56d90c531d2b1c9ad9f9a59cafcaf53cb5296438 100644 (file)
@@ -7,6 +7,11 @@ objectclass alias
                aliasedObjectName,
                objectClass
 
+objectclass referral
+       requires
+               ref,
+               objectClass
+
 objectclass dcobject
        requires
                objectClass,
diff --git a/servers/slapd/suffixalias.c b/servers/slapd/suffixalias.c
deleted file mode 100644 (file)
index 8751d83..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright 1999 The OpenLDAP Foundation, All Rights Reserved.
- *
- * COPYING RESTRICTIONS APPLY, see COPYRIGHT file in the top level
- * directory of this package.
- */
-/* Portions
- * Copyright (c) 1998 Will Ballantyne, ITSD, Government of BC
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that this notice is preserved and that due credit is given
- * to ITSD, Government of BC. The name of ITSD
- * may not be used to endorse or promote products derived from this
- * software without specific prior written permission. This software
- * is provided ``as is'' without express or implied warranty.
- */
-
-#include "portable.h"
-
-#include <stdio.h>
-#include <ac/string.h>
-#include <ac/socket.h>
-#include "slap.h"
-
-/* 
- * given a normalized uppercased dn (or root part), return an aliased dn if any of the 
- * alias suffixes match
- */
-char *suffixAlias (char *dn, Operation *op, Backend *be)
-{
-       int     i, dnLength;
-
-       if(dn == NULL) return NULL;
-
-       dnLength = strlen ( dn );
-        for ( i = 0;
-              be->be_suffixAlias != NULL && be->be_suffixAlias[i] != NULL;
-              i += 2) {
-                int aliasLength = strlen (be->be_suffixAlias[i]);
-               int diff = dnLength - aliasLength;
-
-               if ( diff < 0 ) {
-                       /* alias is longer than dn */
-                       continue;
-               } else if ( diff > 0 ) {
-                       if ( ! DNSEPARATOR(dn[diff-1]) ) {
-                               /* boundary is not at a DN separator */
-                               continue;
-                       }
-                       /* At a DN Separator */
-                       /* XXX or an escaped separator... oh well */
-               }
-
-               if (!strcmp(be->be_suffixAlias[i], &dn[diff])) {
-                        char *oldDN = dn;
-                       dn = ch_malloc( diff + strlen(be->be_suffixAlias[i+1]) + 1 );
-                       strncpy( dn, oldDN, diff );
-                       strcpy( &dn[diff], be->be_suffixAlias[i+1] );
-                       Debug( LDAP_DEBUG_ARGS, "SuffixAlias: converted \"%s\" to \"%s\"\n",
-                               oldDN, dn, 0);
-                        free (oldDN);
-                       break;
-               }
-       }
-       return dn;
-}
index 917a1e0c36c48c78a7cfc716c5a45f83492890fc..70ffa26384f28b91609afb27862f9ae8f340c494 100644 (file)
@@ -50,7 +50,7 @@ OBJS2 = mimic.o \
                ../module.o ../aclparse.o ../schema.o ../filterentry.o \
                ../acl.o ../phonetic.o ../attr.o ../value.o ../entry.o \
                ../dn.o ../filter.o ../str2filter.o ../ava.o ../init.o \
-               ../schemaparse.o
+               ../controls.o ../schemaparse.o
 
 all-local: build-ldbm build-bdb2 build-edb2ldif build-chlog2replog
 
index ab55b065f8159240f4678989a8c54a482196e417..e74b773e511d8b8700a325d045df65f319499935 100644 (file)
@@ -126,7 +126,7 @@ BSC32=bscmake.exe
 # ADD BSC32 /nologo
 LINK32=link.exe
 # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib libdb.lib /nologo /subsystem:console /machine:I386 /libpath:"..\..\..\libraries\Release"
-# ADD LINK32 libdb.lib /nologo /subsystem:console /machine:I386 /libpath:"..\..\..\libraries\Release"
+# ADD LINK32 libdbs.lib /nologo /subsystem:console /machine:I386 /libpath:"..\..\..\libraries\Release"
 
 !ENDIF 
 
@@ -140,5 +140,9 @@ LINK32=link.exe
 
 SOURCE=.\ldbmcat.c
 # End Source File
+# Begin Source File
+
+SOURCE=.\mimic.c
+# End Source File
 # End Target
 # End Project
index dcf169f5a4959ba685ea30a6c4dd32f4d423b95c..afe0588fca31997e07ac074b5d35b5cf1d6c74d6 100644 (file)
@@ -205,6 +205,7 @@ main( int argc, char **argv )
                        free_and_close( dbc, key, data );
                        break;
 
+#ifndef HAVE_WINSOCK
                case 'e':       /* edit an entry */
                        if ( (dbc = openchoice( buf[1], LDBM_WRITER, 1, NULL ))
                            == NULL ) {
@@ -243,6 +244,7 @@ main( int argc, char **argv )
 
                        free_and_close( dbc, key, data );
                        break;
+#endif
 
                case 'a':       /* add an entry */
                        if ( (dbc = openchoice( buf[1], LDBM_WRITER, 1, NULL ))
@@ -499,6 +501,7 @@ get_entry( FILE *fp, Datum *data )
        data->dsize = psize + 1;
 }
 
+#ifndef HAVE_WINSOCK
 static void
 edit_entry( char c, Datum *data )
 {
@@ -565,6 +568,7 @@ edit_entry( char c, Datum *data )
        fclose( fp );
        unlink( tmpname );
 }
+#endif
 
 static struct dbcache *
 openfile( char *name, int namesiz, int mode, int verbose, char c )
index 3f193c44153b4bbb6ba555599b6bf617a41898bb..6bd91f19b970ed4f0f89e298284bf0774c819248 100644 (file)
@@ -54,7 +54,7 @@ BSC32=bscmake.exe
 # ADD BSC32 /nologo
 LINK32=link.exe
 # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
-# ADD LINK32 libdb.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 libdb.lib hs_regex.lib ws2_32.lib /nologo /subsystem:console /machine:I386
 
 !ELSEIF  "$(CFG)" == "ldbmtest - Win32 Debug"
 
@@ -70,7 +70,7 @@ LINK32=link.exe
 # PROP Ignore_Export_Lib 0
 # PROP Target_Dir ""
 # ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MD /W3 /Gm /GX /Zi /Od /I "..\..\..\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "..\..\..\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
 # ADD BASE RSC /l 0x409 /d "_DEBUG"
 # ADD RSC /l 0x409 /d "_DEBUG"
 BSC32=bscmake.exe
@@ -78,7 +78,7 @@ BSC32=bscmake.exe
 # ADD BSC32 /nologo
 LINK32=link.exe
 # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 libdb.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 libdb.lib hs_regex.lib ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
 
 !ELSEIF  "$(CFG)" == "ldbmtest - Win32 Single Debug"
 
@@ -102,7 +102,7 @@ BSC32=bscmake.exe
 # ADD BSC32 /nologo
 LINK32=link.exe
 # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 libdb.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 libdbs.lib hs_regex.lib ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
 
 !ELSEIF  "$(CFG)" == "ldbmtest - Win32 Single Release"
 
@@ -126,7 +126,7 @@ BSC32=bscmake.exe
 # ADD BSC32 /nologo
 LINK32=link.exe
 # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
-# ADD LINK32 libdb.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 libdbs.lib hs_regex.lib ws2_32.lib /nologo /subsystem:console /machine:I386
 
 !ENDIF 
 
@@ -140,5 +140,9 @@ LINK32=link.exe
 
 SOURCE=.\ldbmtest.c
 # End Source File
+# Begin Source File
+
+SOURCE=.\mimic.c
+# End Source File
 # End Target
 # End Project
index be5a177ab7b7530ffe7da65d197b39b42a16aa70..ea598b18c6392b6cb39f819fb326814a760f8175 100644 (file)
@@ -23,25 +23,40 @@ int str2result(
     return 0;
 }
 
+void
+send_ldap_disconnect(
+    Connection *conn,
+    Operation  *op,
+    ber_int_t  err,
+    char       *text
+)
+{
+       assert(0);
+}
+
 void
 send_ldap_result(
        Connection  *conn, 
        Operation   *op,
        int     err,
        char    *matched,
-       char    *text
+       char    *text,
+       struct berval **refs,
+       LDAPControl **ctrls
 )        
 {
        assert(0);
 }
 
 void
-send_ldap_search_result(
+send_search_result(
        Connection  *conn, 
        Operation   *op,
        int     err,
        char    *matched,
        char    *text,
+       struct berval **refs,
+       LDAPControl **ctrls,
        int             nentries
 )        
 {
@@ -56,9 +71,32 @@ send_search_entry(
        Entry   *e,
        char    **attrs,
        int             attrsonly,
-       int             opattrs
+       int             opattrs,
+       LDAPControl **ctrls
 )        
 {
        assert(0);
        return -1;
 }
+
+int send_search_reference(
+       Backend *be,
+       Connection  *conn, 
+       Operation   *op,
+       Entry   *e,
+       struct berval **refs,
+       int scope,
+       LDAPControl **ctrls,
+       struct berval ***v2refs
+)
+{
+       assert(0);
+       return -1;
+}
+
+struct berval **get_entry_referrals(
+       Backend *be, Connection *conn, Operation *op, Entry *e )
+{
+       assert(0);
+       return NULL;
+}
diff --git a/tests/data/referrals.ldif b/tests/data/referrals.ldif
new file mode 100644 (file)
index 0000000..9e605ac
--- /dev/null
@@ -0,0 +1,50 @@
+dn: c=US
+c: US
+objectclass: country
+
+dn: o=ABC, c=US
+o: ABC
+ref: ldap//hostA/o=abc,c=us    HostA
+ref: ldap//hostB/o=abc,c=us    HostB
+objectclass: referral
+objectclass: extensibleObject
+
+dn: o=XYZ, c=US
+o: XYZ
+ref: ldap//hostC/o=xyz,c=us    HostC
+objectclass: referral
+objectclass: extensibleObject
+
+dn: o=Alias, c=US
+o: Alias
+aliasedObjectName: o=University of Michigan, c=US
+objectclass: alias
+objectclass: extensibleObject
+
+dn: o=University of Michigan, c=US
+o: University of Michigan
+objectclass: organization
+
+dn: cn=Manager, o=University of Michigan, c=US
+cn: Manager
+cn: Directory Manager
+cn: Dir Man
+sn: Manager
+description: Manager of the directory
+userpassword: secret
+objectclass: person
+
+dn: cn=Alias, o=University of Michigan, c=US
+cn: Alias
+aliasedobjectname: cn=Manager, o=University of Michigan, c=US
+objectclass: extensibleObject
+
+dn: cn=Circular, o=University of Michigan, c=US
+cn: Circular
+aliasedobjectname: cn=Circular, o=University of Michigan, c=US
+objectclass: extensibleObject
+
+dn: cn=Subordinate, o=University of Michigan, c=US
+cn: Subordinate
+aliasedobjectname: cn=Subordinate, cn=Alias, o=University of Michigan, c=US
+objectclass: extensibleObject
index 69fb8b260127a5a1e8fc66979a016e72db4c4814..8e0e328b9d86cd72a7de96388e84921833b6aa12 100644 (file)
@@ -22,6 +22,11 @@ index                default         none
 lastmod                on
 defaultaccess  none
 
+#
+# normal installations should protect root dse,
+# cn=monitor, cn=schema, and cn=config
+#
+
 access         to attr=objectclass
                by * read
 
diff --git a/tests/data/slapd-bdb2-ref-slave.conf b/tests/data/slapd-bdb2-ref-slave.conf
new file mode 100644 (file)
index 0000000..1495bfd
--- /dev/null
@@ -0,0 +1,28 @@
+#
+# slave slapd config -- for default referral testing
+#
+include                ./data/slapd.at.conf
+include                ./data/slapd.oc.conf
+schemacheck    off
+pidfile     ./test-repl/slapd.pid
+argsfile    ./test-repl/slapd.args
+
+#######################################################################
+# ldbm database definitions
+#######################################################################
+
+referral       "ldap://localhost:9009/"
+
+backend     bdb2
+home        ./test-db
+
+database       bdb2
+cachesize      0
+suffix         "o=University of Mich, c=US"
+directory      ./test-repl
+rootdn         "cn=Manager, o=University of Mich, c=US"
+rootpw         secret
+index          cn,sn,uid       pres,eq,approx
+index          default         none
+# index                default         pres,eq,approx
+lastmod                on
index 3fca276902b1977297446dea292a9480e0d5d57b..5491bcd7b96fa3781e77b7b0a9f951c5694cdb07 100644 (file)
@@ -28,6 +28,6 @@ lastmod               on
 replogfile     ./test-db/slapd.replog
 
 replica                host=localhost:9010
-               binddn="cn=Manager, o=University of Michigan, c=US"
+               binddn="cn=Replica, o=University of Michigan, c=US"
                bindmethod=simple
                credentials=secret
index 3782b628af2b9d55a0fdc0658516942a6e3cceee..7051425d15a4b51426d29257844ab771c246064b 100644 (file)
@@ -7,6 +7,8 @@ schemacheck     off
 pidfile     ./test-repl/slapd.pid
 argsfile    ./test-repl/slapd.args
 
+referral    "ldap://localhost:9009/"
+
 #######################################################################
 # ldbm database definitions
 #######################################################################
@@ -18,9 +20,10 @@ database     bdb2
 cachesize      0
 suffix         "o=University of Michigan, c=US"
 directory      ./test-repl
-rootdn         "cn=Manager, o=University of Michigan, c=US"
+rootdn         "cn=Replica, o=University of Michigan, c=US"
 rootpw         secret
-updatedn       "cn=Manager, o=University of Michigan, c=US"
+updatedn       "cn=Replica, o=University of Michigan, c=US"
+updateref   "ldap://localhost:9009/o=University%20of%20Michigan,c=US"
 index          cn,sn,uid       pres,eq,approx
 index          default         none
 # index                default         pres,eq,approx
diff --git a/tests/data/slapd-ref-slave.conf b/tests/data/slapd-ref-slave.conf
new file mode 100644 (file)
index 0000000..9fa77fb
--- /dev/null
@@ -0,0 +1,25 @@
+#
+# slave slapd config -- for default referral testing
+#
+include                ./data/slapd.at.conf
+include                ./data/slapd.oc.conf
+schemacheck    off
+pidfile     ./test-repl/slapd.pid
+argsfile    ./test-repl/slapd.args
+
+#######################################################################
+# ldbm database definitions
+#######################################################################
+
+referral       "ldap://localhost:9009/"
+
+database       ldbm
+cachesize      0
+suffix         "o=University of Mich, c=US"
+directory      ./test-repl
+rootdn         "cn=Manager, o=University of Mich, c=US"
+rootpw         secret
+index          cn,sn,uid       pres,eq,approx
+index          default         none
+# index                default         pres,eq,approx
+lastmod                on
index c3e1657285e10edfd9827f4dd340ec2161f0069c..d0220ddd08aa7db016ac1f9ca2d5cccd8e9beaa5 100644 (file)
@@ -25,6 +25,6 @@ lastmod               on
 replogfile     ./test-db/slapd.replog
 
 replica                host=localhost:9010
-               binddn="cn=Manager, o=University of Michigan, c=US"
+               binddn="cn=Replica, o=University of Michigan, c=US"
                bindmethod=simple
                credentials=secret
index 886a987edb0883529c958d4e844011ead4661444..02fc97d6f8d25e1b3399edc6b6dbd48cb60f2c8e 100644 (file)
@@ -7,6 +7,8 @@ schemacheck     off
 pidfile     ./test-repl/slapd.pid
 argsfile    ./test-repl/slapd.args
 
+referral       "ldap://localhost:9009/"
+
 #######################################################################
 # ldbm database definitions
 #######################################################################
@@ -15,9 +17,10 @@ database     ldbm
 cachesize      0
 suffix         "o=University of Michigan, c=US"
 directory      ./test-repl
-rootdn         "cn=Manager, o=University of Michigan, c=US"
+rootdn         "cn=Replica, o=University of Michigan, c=US"
 rootpw         secret
-updatedn       "cn=Manager, o=University of Michigan, c=US"
+updatedn       "cn=Replica, o=University of Michigan, c=US"
+updateref      "ldap://localhost:9009/o=University%20of%20Michigan,c=US"
 index          cn,sn,uid       pres,eq,approx
 index          default         none
 # index                default         pres,eq,approx
index c3c8b136b0d79050ed64f1740278ad4c0b716adc..01451706ffd02bdeed5f3f3ae1aca5eb5c31396e 100644 (file)
@@ -3,6 +3,7 @@ attribute       personalsignature                       bin
 attribute      jpegphoto                               bin
 attribute      audio                                   bin
 attribute      labeledurl                              ces
+attribute      ref                                             ces
 attribute      userpassword                            ces
 attribute      telephonenumber                         tel
 attribute      facsimiletelephonenumber        fax     tel
index 02e3b2bdb17d175a2859cd7dd37eaba22d5f24cb..fe077cdfa3d4a6326c872bf1c0d634230f0e3b40 100644 (file)
@@ -7,6 +7,11 @@ objectclass alias
                aliasedObjectName,
                objectClass
 
+objectclass referral
+       requires
+               ref,
+               objectClass
+
 objectclass country
        requires
                objectClass,
index 736d3ad75d41760e6b069088bf5c3b2554fde0ca..4f5256e0d23cf19198bbf0d95d41404044b2a32f 100755 (executable)
@@ -8,6 +8,7 @@ if test "$BACKEND" = "bdb2" ; then
        ACLCONF=$DATADIR/slapd-bdb2-acl.conf
        MASTERCONF=$DATADIR/slapd-bdb2-repl-master.conf
        SLAVECONF=$DATADIR/slapd-bdb2-repl-slave.conf
+       REFSLAVECONF=$DATADIR/slapd-bdb2-ref-slave.conf
        TIMING="-t"
 else
        LDIF2LDBM=../servers/slapd/tools/ldif2ldbm
@@ -15,6 +16,7 @@ else
        ACLCONF=$DATADIR/slapd-acl.conf
        MASTERCONF=$DATADIR/slapd-repl-master.conf
        SLAVECONF=$DATADIR/slapd-repl-slave.conf
+       REFSLAVECONF=$DATADIR/slapd-ref-slave.conf
 fi
 
 if test "$LDAP_PROTO" ; then
@@ -41,8 +43,10 @@ DBDIR=./test-db
 REPLDIR=./test-repl
 LDIF=$DATADIR/test.ldif
 LDIFORDERED=$DATADIR/test-ordered.ldif
+MONITOR="cn=monitor"
 BASEDN="o=University of Michigan, c=US"
 MANAGERDN="cn=Manager, o=University of Michigan, c=US"
+UPDATEDN="cn=Replica, o=University of Michigan, c=US"
 PASSWD=secret
 BABSDN="cn=Barbara Jensen, ou=Information Technology Division, ou=People, o=University of Michigan, c=US"
 BJORNSDN="cn=Bjorn Jensen, ou=Information Technology Division, ou=People, o=University of Michigan, c=US"
index 80a0479a6fc5d64df291b7b59383d58aae35bfb3..d12e14accf74afdb13d2f02d3cc757fbbb1fa036 100755 (executable)
@@ -22,8 +22,8 @@ PID=$!
 
 echo "Using ldapsearch to check that slapd is running..."
 for i in 0 1 2 3 4 5; do
-       $LDAPSEARCH -L -b "$BASEDN" -h localhost -p $PORT \
-               'cn=Monitor' > /dev/null 2>&1
+       $LDAPSEARCH -L -s base -b "$MONITOR" -h localhost -p $PORT \
+               'objectclass=*' > /dev/null 2>&1
        RC=$?
        if test $RC = 1 ; then
                echo "Waiting 5 seconds for slapd to start..."
index 03179910f6be4b5ce667c27868a1c666533e490e..7c1942879d06c74606611611f2702a8818c5cfcc 100755 (executable)
@@ -30,8 +30,8 @@ PID=$!
 
 echo "Testing slapd searching..."
 for i in 0 1 2 3 4 5; do
-       $LDAPSEARCH -L -S "" -b "$BASEDN" -h localhost -p $PORT \
-               'cn=Manager' > /dev/null 2>&1
+       $LDAPSEARCH -L -s base -b "$MONITOR" -h localhost -p $PORT \
+               'objectclass=*' > /dev/null 2>&1
        RC=$?
        if test $RC = 1 ; then
                echo "Waiting 5 seconds for slapd to start..."
index fa3bc019851a5302226fa44b0d63a00676f49d58..b21483a3febd59e1eccebbfb01aba5f726215414 100755 (executable)
@@ -30,8 +30,8 @@ PID=$!
 
 echo "Testing slapd modify operations..."
 for i in 0 1 2 3 4 5; do
-       $LDAPSEARCH -L -S "" -b "$BASEDN" -h localhost -p $PORT \
-               'cn=Manager' > /dev/null 2>&1
+       $LDAPSEARCH -L -s base -b "$MONITOR" -h localhost -p $PORT \
+               'objectclass=*' > /dev/null 2>&1
        RC=$?
        if test $RC = 1 ; then
                echo "Waiting 5 seconds for slapd to start..."
index a6115be9f2da00b383e14d65991fd9f489a37b3e..5dc9f3cdfe124afa819d22593d31cc0aeacc36df 100755 (executable)
@@ -31,8 +31,8 @@ echo "Testing slapd modrdn operations..."
 
 # Make sure we can search the database
 for i in 0 1 2 3 4 5; do
-       $LDAPSEARCH -L -S "" -b "$BASEDN" -h localhost -p $PORT \
-               'cn=Manager' > /dev/null 2>&1
+       $LDAPSEARCH -L -s base -b "$MONITOR" -h localhost -p $PORT \
+               'objectclass=*' > /dev/null 2>&1
        RC=$?
        if test $RC = 1 ; then
                echo "Waiting 5 seconds for slapd to start..."
index 58d12154074923e69fd9a3a2e8135243cb724661..05323fc619fce9620e4a6c0f780351c38605e8af 100755 (executable)
@@ -30,8 +30,8 @@ PID=$!
 
 echo "Testing slapd access control..."
 for i in 0 1 2 3 4 5; do
-       $LDAPSEARCH -L -S "" -b "$BASEDN" -h localhost -p $PORT \
-               'cn=Monitor' > /dev/null 2>&1
+       $LDAPSEARCH -L -s base -b "$MONITOR" -h localhost -p $PORT \
+               'objectclass=*' > /dev/null 2>&1
        RC=$?
        if test $RC = 1 ; then
                echo "Waiting 5 seconds for slapd to start..."
index 8a79f7d3e099f0d112a63c9b1fafc307648c7385..9e400f8f93d4183bc4c0a049c94a8dc2dc22761f 100755 (executable)
@@ -43,8 +43,8 @@ SLAVEPID=$!
 
 echo "Using ldapsearch to check that master slapd is running..."
 for i in 0 1 2 3 4 5; do
-       $LDAPSEARCH -L -b "$BASEDN" -h localhost -p $PORT \
-               'cn=Monitor' > /dev/null 2>&1
+       $LDAPSEARCH -L -s base -b "$MONITOR" -h localhost -p $PORT \
+               'objectclass=*' > /dev/null 2>&1
        RC=$?
        if test $RC = 1 ; then
                echo "Waiting 5 seconds for slapd to start..."
@@ -54,8 +54,8 @@ done
 
 echo "Using ldapsearch to check that slave slapd is running..."
 for i in 0 1 2 3 4 5; do
-       $LDAPSEARCH -L -b "$BASEDN" -h localhost -p $SLAVEPORT \
-               'cn=Monitor' > /dev/null 2>&1
+       $LDAPSEARCH -L -s base -b "$MONITOR" -h localhost -p $PORT \
+               'objectclass=*' > /dev/null 2>&1
        RC=$?
        if test $RC = 1 ; then
                echo "Waiting 5 seconds for slapd to start..."
@@ -67,7 +67,7 @@ echo "Starting slurpd..."
 $SLURPD -f $MASTERCONF -d 4 -t $REPLDIR > $SLURPLOG 2>&1 &
 SLURPPID=$!
 
-echo "Using ldapadd to populate the database..."
+echo "Using ldapadd to populate the master directory..."
 $LDAPADD -D "$MANAGERDN" -h localhost -p $PORT -w $PASSWD < \
        $LDIFORDERED > /dev/null 2>&1
 RC=$?
@@ -77,12 +77,16 @@ if test $RC != 0 ; then
        exit $RC
 fi
 
-echo "Using ldapmodify to modify the database..."
+echo "Waiting 15 seconds for slurpd to send changes..."
+sleep 15
+
+echo "Using ldapmodify to modify slave directory..."
+
 #
 # Do some modifications
 #
 
-$LDAPMODIFY -v -D "$MANAGERDN" -h localhost -p $PORT -w $PASSWD > \
+$LDAPMODIFY -v -D "$MANAGERDN" -h localhost -p $SLAVEPORT -w $PASSWD > \
        /dev/null 2>&1 << EOMODS
 dn: cn=James A Jones 1, ou=Alumni Association, ou=People, o=University of Michigan, c=US
 changetype: modify
index 6ac569b08f67441df02b81fb431bdde08d79fe4a..5b8958fc823bf55d1509cda79131fe28cdb83358 100755 (executable)
@@ -34,8 +34,16 @@ echo "Starting slapd on TCP/IP port $PORT..."
 $SLAPD -f $CONF -p $PORT -d $LVL $TIMING > $MASTERLOG 2>&1 &
 PID=$!
 
-echo "Waiting 5 seconds for slapd to start..."
-sleep 5
+echo "Using ldapsearch to check that slapd is running..."
+for i in 0 1 2 3 4 5; do
+       $LDAPSEARCH -L -s base -b "$MONITOR" -h localhost -p $PORT \
+               'objectclass=*' > /dev/null 2>&1
+       RC=$?
+       if test $RC = 1 ; then
+               echo "Waiting 5 seconds for slapd to start..."
+               sleep 5
+       fi
+done
 
 echo "Using tester for concurrent server access..."
 $SLAPDTESTER -b "$BASEDN" -P "$PROGDIR" -d "$DATADIR" -h localhost -p $PORT -D "$MANAGERDN" -w $PASSWD -l 50
diff --git a/tests/scripts/test009-referral b/tests/scripts/test009-referral
new file mode 100755 (executable)
index 0000000..05bdd22
--- /dev/null
@@ -0,0 +1,126 @@
+#! /bin/sh
+
+#
+# Test default referral
+#
+
+if test $# -eq 0 ; then
+       SRCDIR="."
+else
+       SRCDIR=$1; shift
+fi
+if test $# -eq 1 ; then
+       BACKEND=$1; shift
+fi
+
+echo "running defines.sh $SRCDIR $BACKEND"
+. $SRCDIR/scripts/defines.sh
+
+echo "Cleaning up in $DBDIR and $REPLDIR ..."
+
+rm -f $DBDIR/[!C]*
+rm -f $REPLDIR/[!C]*
+
+echo "Running ldif2ldbm to build slapd database..."
+$LDIF2LDBM -f $CONF -i $LDIF -e ../servers/slapd/tools
+RC=$?
+if test $RC != 0 ; then
+       echo "ldif2ldbm failed!"
+       exit $RC
+fi
+
+echo "Starting master slapd on TCP/IP port $PORT..."
+$SLAPD -f $CONF -p $PORT -d $LVL $TIMING > $MASTERLOG 2>&1 &
+PID=$!
+
+echo "Starting slave slapd on TCP/IP port $SLAVEPORT..."
+$SLAPD -f $REFSLAVECONF -p $SLAVEPORT -d $LVL $TIMING > $SLAVELOG 2>&1 &
+SLAVEPID=$!
+
+echo "Testing for master slapd..."
+for i in 0 1 2 3 4 5; do
+       $LDAPSEARCH -L -s base -b "$MONITOR" -h localhost -p $PORT \
+               'objectclass=*' > /dev/null 2>&1
+       RC=$?
+       if test $RC = 1 ; then
+               echo "Waiting 5 seconds for slapd to start..."
+               sleep 5
+       fi
+done
+
+if test $RC != 0 ; then
+       echo "ldapsearch failed!"
+       kill -HUP $PID
+       exit $RC
+fi
+
+echo "Testing for slave slapd..."
+for i in 0 1 2 3 4 5; do
+       $LDAPSEARCH -L -s base -b "$MONITOR" -h localhost -p $SLAVEPORT \
+               'objectclass=*' > /dev/null 2>&1
+       RC=$?
+       if test $RC = 1 ; then
+               echo "Waiting 5 seconds for slapd to start..."
+               sleep 5
+       fi
+done
+
+cat /dev/null > $SEARCHOUT
+
+echo "Testing exact searching..."
+$LDAPSEARCH -L -S "" -b "$BASEDN" -h localhost -p $SLAVEPORT \
+       'sn=jensen' >> $SEARCHOUT 2>&1
+if test $RC != 0 ; then
+       echo "ldapsearch failed!"
+       kill -HUP $PID $SLAVEPID
+       exit $RC
+fi
+
+echo "Testing OR searching..."
+$LDAPSEARCH -L -S "" -b "$BASEDN" -h localhost -p $SLAVEPORT \
+       '(|(objectclass=rfc822mailgroup)(sn=jones))' >> $SEARCHOUT 2>&1
+if test $RC != 0 ; then
+       echo "ldapsearch failed!"
+       kill -HUP $PID $SLAVEPID
+       exit $RC
+fi
+
+echo "Testing AND matching and ends-with searching..."
+$LDAPSEARCH -L -S "" -b "$BASEDN" -h localhost -p $SLAVEPORT \
+       '(&(objectclass=rfc822mailgroup)(cn=A*))' >> $SEARCHOUT 2>&1
+if test $RC != 0 ; then
+       echo "ldapsearch failed!"
+       kill -HUP $PID $SLAVEPID
+       exit $RC
+fi
+
+echo "Testing NOT searching..."
+$LDAPSEARCH -L -S "" -b "$BASEDN" -h localhost -p $SLAVEPORT \
+       '(!(objectclass=person))' >> $SEARCHOUT 2>&1
+if test $RC != 0 ; then
+       echo "ldapsearch failed!"
+       kill -HUP $PID $SLAVEPID
+       exit $RC
+fi
+
+kill -HUP $PID $SLAVEPID
+
+TESTOUT=$SEARCHOUT
+LDIF=$SEARCHOUTMASTER
+
+echo "Filtering ldapsearch results..."
+. $SRCDIR/scripts/acfilter.sh < $SEARCHOUT > $SEARCHFLT
+echo "Filtering original ldif used to create database..."
+. $SRCDIR/scripts/acfilter.sh < $LDIF > $LDIFFLT
+echo "Comparing filter output..."
+cmp $SEARCHFLT $LDIFFLT
+
+if test $? != 0 ; then
+       echo "Comparison failed"
+       exit 1
+fi
+
+echo ">>>>> Test succeeded"
+
+
+exit 0