]> git.sur5r.net Git - openldap/commitdiff
Sync with HEAD
authorKurt Zeilenga <kurt@openldap.org>
Mon, 15 May 2006 19:04:33 +0000 (19:04 +0000)
committerKurt Zeilenga <kurt@openldap.org>
Mon, 15 May 2006 19:04:33 +0000 (19:04 +0000)
133 files changed:
CHANGES
build/mkrelease
build/version.var
clients/tools/ldapdelete.c
clients/tools/ldapsearch.c
configure
configure.in
contrib/slapd-modules/passwd/README
contrib/slapd-modules/passwd/radius.c [new file with mode: 0644]
doc/guide/admin/slapdconf2.sdf
doc/guide/admin/slapdconfig.sdf
doc/man/man5/slapd-ldap.5
doc/man/man5/slapd-meta.5
doc/man/man5/slapd-null.5
doc/man/man5/slapd-shell.5
doc/man/man5/slapd.access.5
doc/man/man5/slapd.conf.5
doc/man/man5/slapo-accesslog.5
doc/man/man8/slapcat.8
doc/man/man8/slapd.8
doc/man/man8/slappasswd.8
include/ldap.h
include/ldap_int_thread.h
include/ldap_log.h
include/ldap_pvt.h
include/ldap_pvt_thread.h
include/ldap_rq.h
include/portable.hin
libraries/libldap/cancel.c
libraries/libldap/cyrus.c
libraries/libldap/kbind.c
libraries/libldap/ldap-int.h
libraries/libldap/open.c
libraries/libldap/options.c
libraries/libldap/ppolicy.c
libraries/libldap/request.c
libraries/libldap/result.c
libraries/libldap/sort.c
libraries/libldap/tls.c
libraries/libldap/url.c
libraries/libldap_r/Makefile.in
libraries/libldap_r/rmutex.c [new file with mode: 0644]
libraries/libldap_r/rq.c
libraries/libldap_r/thr_debug.c
libraries/libldap_r/threads.c
libraries/libldap_r/tpool.c
libraries/liblutil/utils.c
servers/slapd/acl.c
servers/slapd/aclparse.c
servers/slapd/ad.c
servers/slapd/alock.c
servers/slapd/back-bdb/add.c
servers/slapd/back-bdb/delete.c
servers/slapd/back-bdb/idl.c
servers/slapd/back-bdb/init.c
servers/slapd/back-bdb/modify.c
servers/slapd/back-bdb/modrdn.c
servers/slapd/back-bdb/tools.c
servers/slapd/back-ldap/back-ldap.h
servers/slapd/back-ldap/bind.c
servers/slapd/back-ldap/chain.c
servers/slapd/back-ldap/config.c
servers/slapd/back-ldap/init.c
servers/slapd/back-ldap/proto-ldap.h
servers/slapd/back-ldif/ldif.c
servers/slapd/back-meta/add.c
servers/slapd/back-meta/back-meta.h
servers/slapd/back-meta/bind.c
servers/slapd/back-meta/candidates.c
servers/slapd/back-meta/compare.c
servers/slapd/back-meta/config.c
servers/slapd/back-meta/conn.c
servers/slapd/back-meta/delete.c
servers/slapd/back-meta/init.c
servers/slapd/back-meta/modify.c
servers/slapd/back-meta/modrdn.c
servers/slapd/back-meta/search.c
servers/slapd/back-meta/unbind.c
servers/slapd/back-monitor/database.c
servers/slapd/back-null/null.c
servers/slapd/back-sql/schema-map.c
servers/slapd/back-sql/sql-wrap.c
servers/slapd/backend.c
servers/slapd/backglue.c
servers/slapd/bconfig.c
servers/slapd/config.c
servers/slapd/config.h
servers/slapd/connection.c
servers/slapd/controls.c
servers/slapd/daemon.c
servers/slapd/dn.c
servers/slapd/init.c
servers/slapd/ldapsync.c
servers/slapd/main.c
servers/slapd/overlays/Makefile.in
servers/slapd/overlays/accesslog.c
servers/slapd/overlays/auditlog.c
servers/slapd/overlays/constraint.c [new file with mode: 0644]
servers/slapd/overlays/dynlist.c
servers/slapd/overlays/ppolicy.c
servers/slapd/overlays/refint.c
servers/slapd/overlays/retcode.c
servers/slapd/overlays/rwm.c
servers/slapd/overlays/syncprov.c
servers/slapd/overlays/unique.c
servers/slapd/passwd.c
servers/slapd/proto-slap.h
servers/slapd/referral.c
servers/slapd/result.c
servers/slapd/root_dse.c
servers/slapd/saslauthz.c
servers/slapd/slap.h
servers/slapd/slapacl.c
servers/slapd/slapi/slapi_overlay.c
servers/slapd/slappasswd.c
servers/slapd/syncrepl.c
tests/data/slapd-ldapglue.conf
tests/data/slapd-ldapgluegroups.conf
tests/data/slapd-ldapgluepeople.conf
tests/data/slapd-ppolicy.conf
tests/data/slapd-pw.conf
tests/data/slapd-schema.conf
tests/data/slapd-valsort.conf
tests/data/slapd-whoami.conf
tests/data/slapd2.conf
tests/progs/slapd-bind.c
tests/progs/slapd-tester.c
tests/scripts/conf.sh
tests/scripts/defines.sh
tests/scripts/test005-modrdn
tests/scripts/test020-proxycache
tests/scripts/test033-glue-syncrepl
tests/scripts/test042-valsort

diff --git a/CHANGES b/CHANGES
index ee1d10efdd82fad867427fb5b3b02689e77949e6..662a23f7f96a769ce80ef599e0b16b89d9b446d0 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,5 +1,5 @@
 OpenLDAP 2.4 Change Log
 
-OpenLDAP 2.4.0alpha Release
+OpenLDAP 2.4.1alpha Engineering
        Changes not tracked
 
index f8fdaaba11b40b9fa3e8d0d122c31a177fa8dad1..d9fa395ed51837d0de3472531f430970f23aaccf 100755 (executable)
@@ -58,6 +58,11 @@ else
        echo "No guide"
 fi
 
+if test -e $RELNAME/libraries/liblunicode/ucdata/uctable.h ; then
+       echo "touching uctable.h..."
+       touch $RELNAME/libraries/liblunicode/ucdata/uctable.h
+fi
+
 if test ! -e $RELNAME/build/version.sh ; then
        echo "No build version"
        OL_STRING="something"
index 2e333efc15aaa660e830b7f21ea2e90aedc3c06f..79ef06ca9659415864812146c57db6a6b65dee36 100644 (file)
@@ -15,7 +15,7 @@
 ol_package=OpenLDAP
 ol_major=2
 ol_minor=4
-ol_patch=0alpha
+ol_patch=X
 ol_api_inc=20400
 ol_api_current=0
 ol_api_revision=0
index 8bbc1c46635ca5426e083295d8aab4e1fd7629b0..2e7d42f82b6ddf4709942b6229fec25b78e6db2a 100644 (file)
@@ -261,8 +261,10 @@ static int dodelete(
                return rc;
        }
 
-       if( verbose || code != LDAP_SUCCESS ||
-               (matcheddn && *matcheddn) || (text && *text) || (refs && *refs) )
+       if( code != LDAP_SUCCESS ) {
+               tool_perror( "ldap_delete", code, NULL, matcheddn, text, refs );
+       } else if ( verbose && 
+               ((matcheddn && *matcheddn) || (text && *text) || (refs && *refs) ))
        {
                printf( _("Delete Result: %s (%d)\n"),
                        ldap_err2string( code ), code );
index 6eca59dbc77b01a5077019d205cbef15efeb6f05..04840c421881d098d885c54ea045f6f710238aa3 100644 (file)
@@ -899,10 +899,17 @@ getNextPage:
        }
 
        if (ldif < 2 ) {
+               char    *realbase = base;
+
+               if ( realbase == NULL ) {
+                       ldap_get_option( ld, LDAP_OPT_DEFBASE, (void **)&realbase );
+               }
+               
                printf( "#\n" );
                printf(_("# LDAPv%d\n"), protocol);
-               printf(_("# base <%s> with scope %s\n"),
-                       base ? base : "",
+               printf(_("# base <%s>%s with scope %s\n"),
+                       realbase ? realbase : "",
+                       ( realbase == NULL || realbase != base ) ? " (default)" : "",
                        ((scope == LDAP_SCOPE_BASE) ? "baseObject"
                                : ((scope == LDAP_SCOPE_ONELEVEL) ? "oneLevel"
                                : ((scope == LDAP_SCOPE_SUBORDINATE) ? "children"
@@ -943,6 +950,10 @@ getNextPage:
                }
 
                printf( _("\n#\n\n") );
+
+               if ( realbase && realbase != base ) {
+                       ldap_memfree( realbase );
+               }
        }
 
        if ( infile == NULL ) {
@@ -1512,12 +1523,27 @@ static int print_result(
 
        if( text ) {
                if( *text ) {
-               if( !ldif ) {
-                       tool_write_ldif( LDIF_PUT_TEXT, "text",
-                               text, strlen(text) );
-               } else {
-                       fprintf( stderr, _("Additional information: %s\n"), text );
-               }
+                       if( !ldif ) {
+                               if ( err == LDAP_PARTIAL_RESULTS ) {
+                                       char    *line;
+
+                                       for ( line = text; line != NULL; ) {
+                                               char    *next = strchr( line, '\n' );
+
+                                               tool_write_ldif( LDIF_PUT_TEXT,
+                                                       "text", line,
+                                                       next ? next - line : strlen( line ) );
+
+                                               line = next ? next + 1 : NULL;
+                                       }
+
+                               } else {
+                                       tool_write_ldif( LDIF_PUT_TEXT, "text",
+                                               text, strlen(text) );
+                               }
+                       } else {
+                               fprintf( stderr, _("Additional information: %s\n"), text );
+                       }
                }
 
                ber_memfree( text );
index b5a4f68816471ddbad5412de1bbdb4b65759999f..8f4964e5c038d78b52f83a442b821646fd2e1360 100755 (executable)
--- a/configure
+++ b/configure
@@ -1,5 +1,5 @@
 #! /bin/sh
-# From configure.in OpenLDAP: pkg/ldap/configure.in,v 1.631.2.1 2006/04/11 16:07:14 kurt Exp .
+# From configure.in OpenLDAP: pkg/ldap/configure.in,v 1.633 2006/04/29 08:09:31 hyc Exp .
 # Guess values for system-dependent variables and create Makefiles.
 # Generated by GNU Autoconf 2.59.
 #
@@ -465,7 +465,7 @@ ac_includes_default="\
 # include <unistd.h>
 #endif"
 
-ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS build build_cpu build_vendor build_os host host_cpu host_vendor host_os target target_cpu target_vendor target_os INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA CYGPATH_W PACKAGE VERSION ACLOCAL AUTOCONF AUTOMAKE AUTOHEADER MAKEINFO install_sh STRIP ac_ct_STRIP INSTALL_STRIP_PROGRAM mkdir_p AWK SET_MAKE am__leading_dot AMTAR am__tar am__untar OPENLDAP_LIBRELEASE OPENLDAP_LIBVERSION OPENLDAP_RELEASE_DATE top_builddir ldap_subdir CC AR CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT DEPDIR am__include am__quote AMDEP_TRUE AMDEP_FALSE AMDEPBACKSLASH CCDEPMODE am__fastdepCC_TRUE am__fastdepCC_FALSE EGREP LN_S ECHO ac_ct_AR RANLIB ac_ct_RANLIB DLLTOOL ac_ct_DLLTOOL AS ac_ct_AS OBJDUMP ac_ct_OBJDUMP CPP LIBTOOL PERLBIN OL_MKDEP OL_MKDEP_FLAGS LTSTATIC LIBOBJS LIBSRCS PLAT WITH_SASL WITH_TLS WITH_MODULES_ENABLED WITH_ACI_ENABLED BUILD_THREAD BUILD_LIBS_DYNAMIC BUILD_SLAPD BUILD_SLAPI SLAPD_SLAPI_DEPEND BUILD_BDB BUILD_DNSSRV BUILD_HDB BUILD_LDAP BUILD_META BUILD_MONITOR BUILD_NULL BUILD_PASSWD BUILD_RELAY BUILD_PERL BUILD_SHELL BUILD_SQL BUILD_ACCESSLOG BUILD_AUDITLOG BUILD_DDS BUILD_DENYOP BUILD_DYNGROUP BUILD_DYNLIST BUILD_LASTMOD BUILD_PPOLICY BUILD_PROXYCACHE BUILD_REFINT BUILD_RETCODE BUILD_RWM BUILD_SEQMOD BUILD_SYNCPROV BUILD_TRANSLUCENT BUILD_UNIQUE BUILD_VALSORT BUILD_SLURPD LDAP_LIBS SLAPD_LIBS SLURPD_LIBS BDB_LIBS LTHREAD_LIBS LUTIL_LIBS WRAP_LIBS SLAPD_MODULES_CPPFLAGS SLAPD_MODULES_LDFLAGS SLAPD_NO_STATIC SLAPD_STATIC_BACKENDS SLAPD_DYNAMIC_BACKENDS SLAPD_STATIC_OVERLAYS SLAPD_DYNAMIC_OVERLAYS PERL_CPPFLAGS SLAPD_PERL_LDFLAGS MOD_PERL_LDFLAGS KRB4_LIBS KRB5_LIBS SASL_LIBS TLS_LIBS MODULES_LIBS SLAPI_LIBS LIBSLAPI LIBSLAPITOOLS AUTH_LIBS ICU_LIBS SLAPD_SLP_LIBS SLAPD_GMP_LIBS SLAPD_SQL_LDFLAGS SLAPD_SQL_LIBS SLAPD_SQL_INCLUDES LTLIBOBJS'
+ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS build build_cpu build_vendor build_os host host_cpu host_vendor host_os target target_cpu target_vendor target_os INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA CYGPATH_W PACKAGE VERSION ACLOCAL AUTOCONF AUTOMAKE AUTOHEADER MAKEINFO install_sh STRIP ac_ct_STRIP INSTALL_STRIP_PROGRAM mkdir_p AWK SET_MAKE am__leading_dot AMTAR am__tar am__untar OPENLDAP_LIBRELEASE OPENLDAP_LIBVERSION OPENLDAP_RELEASE_DATE top_builddir ldap_subdir CC AR CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT DEPDIR am__include am__quote AMDEP_TRUE AMDEP_FALSE AMDEPBACKSLASH CCDEPMODE am__fastdepCC_TRUE am__fastdepCC_FALSE EGREP LN_S ECHO ac_ct_AR RANLIB ac_ct_RANLIB DLLTOOL ac_ct_DLLTOOL AS ac_ct_AS OBJDUMP ac_ct_OBJDUMP CPP LIBTOOL PERLBIN OL_MKDEP OL_MKDEP_FLAGS LTSTATIC LIBOBJS LIBSRCS PLAT WITH_SASL WITH_TLS WITH_MODULES_ENABLED WITH_ACI_ENABLED BUILD_THREAD BUILD_LIBS_DYNAMIC BUILD_SLAPD BUILD_SLAPI SLAPD_SLAPI_DEPEND BUILD_BDB BUILD_DNSSRV BUILD_HDB BUILD_LDAP BUILD_META BUILD_MONITOR BUILD_NULL BUILD_PASSWD BUILD_RELAY BUILD_PERL BUILD_SHELL BUILD_SQL BUILD_ACCESSLOG BUILD_AUDITLOG BUILD_CONSTRAINT BUILD_DDS BUILD_DENYOP BUILD_DYNGROUP BUILD_DYNLIST BUILD_LASTMOD BUILD_PPOLICY BUILD_PROXYCACHE BUILD_REFINT BUILD_RETCODE BUILD_RWM BUILD_SEQMOD BUILD_SYNCPROV BUILD_TRANSLUCENT BUILD_UNIQUE BUILD_VALSORT BUILD_SLURPD LDAP_LIBS SLAPD_LIBS SLURPD_LIBS BDB_LIBS LTHREAD_LIBS LUTIL_LIBS WRAP_LIBS SLAPD_MODULES_CPPFLAGS SLAPD_MODULES_LDFLAGS SLAPD_NO_STATIC SLAPD_STATIC_BACKENDS SLAPD_DYNAMIC_BACKENDS SLAPD_STATIC_OVERLAYS SLAPD_DYNAMIC_OVERLAYS PERL_CPPFLAGS SLAPD_PERL_LDFLAGS MOD_PERL_LDFLAGS KRB4_LIBS KRB5_LIBS SASL_LIBS TLS_LIBS MODULES_LIBS SLAPI_LIBS LIBSLAPI LIBSLAPITOOLS AUTH_LIBS ICU_LIBS SLAPD_SLP_LIBS SLAPD_GMP_LIBS SLAPD_SQL_LDFLAGS SLAPD_SQL_LIBS SLAPD_SQL_INCLUDES LTLIBOBJS'
 ac_subst_files=''
 
 # Initialize some variables set by options.
@@ -1047,6 +1047,7 @@ SLAPD Overlay Options:
     --enable-overlays    enable all available overlays no|yes|mod
     --enable-accesslog   In-Directory Access Logging overlay no|yes|mod [no]
     --enable-auditlog    Audit Logging overlay no|yes|mod [no]
+    --enable-constraint          Attribute Constraint overlay no|yes|mod [no]
     --enable-dds         Dynamic Directory Services overlay no|yes|mod [no]
     --enable-denyop      Deny Operation overlay no|yes|mod [no]
     --enable-dyngroup    Dynamic Group overlay no|yes|mod [no]
@@ -3074,6 +3075,7 @@ fi;
 
 Overlays="accesslog \
        auditlog \
+       constraint \
        dds \
        denyop \
        dyngroup \
@@ -3165,6 +3167,30 @@ else
 fi;
 # end --enable-auditlog
 
+# OpenLDAP --enable-constraint
+
+       # Check whether --enable-constraint or --disable-constraint was given.
+if test "${enable_constraint+set}" = set; then
+  enableval="$enable_constraint"
+
+       ol_arg=invalid
+       for ol_val in no yes mod ; do
+               if test "$enableval" = "$ol_val" ; then
+                       ol_arg="$ol_val"
+               fi
+       done
+       if test "$ol_arg" = "invalid" ; then
+               { { echo "$as_me:$LINENO: error: bad value $enableval for --enable-constraint" >&5
+echo "$as_me: error: bad value $enableval for --enable-constraint" >&2;}
+   { (exit 1); exit 1; }; }
+       fi
+       ol_enable_constraint="$ol_arg"
+
+else
+       ol_enable_constraint=${ol_enable_overlays:-no}
+fi;
+# end --enable-constraint
+
 # OpenLDAP --enable-dds
 
        # Check whether --enable-dds or --disable-dds was given.
@@ -3794,6 +3820,7 @@ BUILD_SQL=no
 
 BUILD_ACCESSLOG=no
 BUILD_AUDITLOG=no
+BUILD_CONSTRAINT=no
 BUILD_DDS=no
 BUILD_DENYOP=no
 BUILD_DYNGROUP=no
@@ -5635,7 +5662,7 @@ ia64-*-hpux*)
   ;;
 *-*-irix6*)
   # Find out which ABI we are using.
-  echo '#line 5638 "configure"' > conftest.$ac_ext
+  echo '#line 5665 "configure"' > conftest.$ac_ext
   if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
@@ -7615,11 +7642,11 @@ else
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:7618: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:7645: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:7622: \$? = $ac_status" >&5
+   echo "$as_me:7649: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s "$ac_outfile"; then
      # The compiler can only warn and ignore the option if not recognized
      # So say no if there are warnings other than the usual output.
@@ -7877,11 +7904,11 @@ else
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:7880: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:7907: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:7884: \$? = $ac_status" >&5
+   echo "$as_me:7911: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s "$ac_outfile"; then
      # The compiler can only warn and ignore the option if not recognized
      # So say no if there are warnings other than the usual output.
@@ -7939,11 +7966,11 @@ else
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:7942: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:7969: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>out/conftest.err)
    ac_status=$?
    cat out/conftest.err >&5
-   echo "$as_me:7946: \$? = $ac_status" >&5
+   echo "$as_me:7973: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s out/conftest2.$ac_objext
    then
      # The compiler can only warn and ignore the option if not recognized
@@ -10187,7 +10214,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<EOF
-#line 10190 "configure"
+#line 10217 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -10285,7 +10312,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<EOF
-#line 10288 "configure"
+#line 10315 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -40173,6 +40200,22 @@ _ACEOF
 
 fi
 
+if test "$ol_enable_constraint" != no ; then
+       BUILD_CONSTRAINT=$ol_enable_constraint
+       if test "$ol_enable_constraint" = mod ; then
+               MFLAG=SLAPD_MOD_DYNAMIC
+               SLAPD_DYNAMIC_OVERLAYS="$SLAPD_DYNAMIC_OVERLAYS constraint.la"
+       else
+               MFLAG=SLAPD_MOD_STATIC
+               SLAPD_STATIC_OVERLAYS="$SLAPD_STATIC_OVERLAYS constraint.o"
+       fi
+
+cat >>confdefs.h <<_ACEOF
+#define SLAPD_OVER_CONSTRAINT $MFLAG
+_ACEOF
+
+fi
+
 if test "$ol_enable_dds" != no ; then
        BUILD_DDS=$ol_enable_dds
        if test "$ol_enable_dds" = mod ; then
@@ -40529,6 +40572,7 @@ fi
 
 
 
+
 
 
 # Check whether --with-xxinstall or --without-xxinstall was given.
@@ -41279,6 +41323,7 @@ s,@BUILD_SHELL@,$BUILD_SHELL,;t t
 s,@BUILD_SQL@,$BUILD_SQL,;t t
 s,@BUILD_ACCESSLOG@,$BUILD_ACCESSLOG,;t t
 s,@BUILD_AUDITLOG@,$BUILD_AUDITLOG,;t t
+s,@BUILD_CONSTRAINT@,$BUILD_CONSTRAINT,;t t
 s,@BUILD_DDS@,$BUILD_DDS,;t t
 s,@BUILD_DENYOP@,$BUILD_DENYOP,;t t
 s,@BUILD_DYNGROUP@,$BUILD_DYNGROUP,;t t
index 67925e43351ff505eacb70a97c6bcfb297dbac2f..425c8e52b6e931b5e601f1868821b7b0af62d4ad 100644 (file)
@@ -326,6 +326,7 @@ dnl ----------------------------------------------------------------
 dnl SLAPD Overlay Options
 Overlays="accesslog \
        auditlog \
+       constraint \
        dds \
        denyop \
        dyngroup \
@@ -351,6 +352,8 @@ OL_ARG_ENABLE(accesslog,[    --enable-accesslog       In-Directory Access Logging ov
        no, [no yes mod], ol_enable_overlays)
 OL_ARG_ENABLE(auditlog,[    --enable-auditlog    Audit Logging overlay],
        no, [no yes mod], ol_enable_overlays)
+OL_ARG_ENABLE(constraint,[    --enable-constraint        Attribute Constraint overlay],
+       no, [no yes mod], ol_enable_overlays)
 OL_ARG_ENABLE(dds,[    --enable-dds      Dynamic Directory Services overlay],
        no, [no yes mod], ol_enable_overlays)
 OL_ARG_ENABLE(denyop,[    --enable-denyop        Deny Operation overlay],
@@ -558,6 +561,7 @@ BUILD_SQL=no
 
 BUILD_ACCESSLOG=no
 BUILD_AUDITLOG=no
+BUILD_CONSTRAINT=no
 BUILD_DDS=no
 BUILD_DENYOP=no
 BUILD_DYNGROUP=no
@@ -2741,6 +2745,18 @@ if test "$ol_enable_auditlog" != no ; then
        AC_DEFINE_UNQUOTED(SLAPD_OVER_AUDITLOG,$MFLAG,[define for Audit Logging overlay])
 fi
 
+if test "$ol_enable_constraint" != no ; then
+       BUILD_CONSTRAINT=$ol_enable_constraint
+       if test "$ol_enable_constraint" = mod ; then
+               MFLAG=SLAPD_MOD_DYNAMIC
+               SLAPD_DYNAMIC_OVERLAYS="$SLAPD_DYNAMIC_OVERLAYS constraint.la"
+       else
+               MFLAG=SLAPD_MOD_STATIC
+               SLAPD_STATIC_OVERLAYS="$SLAPD_STATIC_OVERLAYS constraint.o"
+       fi
+       AC_DEFINE_UNQUOTED(SLAPD_OVER_CONSTRAINT,$MFLAG,[define for Attribute Constraint overlay])
+fi
+
 if test "$ol_enable_dds" != no ; then
        BUILD_DDS=$ol_enable_dds
        if test "$ol_enable_dds" = mod ; then
@@ -2982,6 +2998,7 @@ dnl backends
 dnl overlays
   AC_SUBST(BUILD_ACCESSLOG)
   AC_SUBST(BUILD_AUDITLOG)
+  AC_SUBST(BUILD_CONSTRAINT)
   AC_SUBST(BUILD_DDS)
   AC_SUBST(BUILD_DENYOP)
   AC_SUBST(BUILD_DYNGROUP)
index f6594cb44087c654f625d790c1b702e26431c4ca..ee288431bfe5e9b6dfeb529d34c004caafa1cbfd 100644 (file)
@@ -6,7 +6,7 @@ Public License.
 
 This directory contains native slapd plugins for password mechanisms that
 are not actively supported by the project. Currently this includes the
-Kerberos and Netscape MTA-MD5 password mechanisms.
+Kerberos, Netscape MTA-MD5 and RADIUS password mechanisms.
 
 To use the Kerberos plugin, add:
 
@@ -20,6 +20,15 @@ moduleload pw-netscape.so
 
 to your slapd configuration file.
 
+To use the RADIUS plugin, add:
+
+moduleload pw-radius.so
+
+to your slapd configuration file; optionally, the path to a configuration
+file can be appended in the form
+
+moduleload pw-radius.so config="/etc/radius.conf"
+
 No Makefile is provided. Use a command line similar to:
 
 gcc -shared -I../../../include -Wall -g -DHAVE_KRB5 -o pw-kerberos.so kerberos.c
@@ -32,3 +41,10 @@ The corresponding command for the Netscape plugin would be:
 
 gcc -shared -I../../../include -Wall -g -o pw-netscape.so netscape.c
 
+The corresponding command for the RADIUS plugin would be:
+
+gcc -shared -I../../../include -Wall -g -o pw-radius.so radius.c -lradius
+
+(Actually, you might want to statically link the RADIUS client library 
+libradius.a into the module).
+
diff --git a/contrib/slapd-modules/passwd/radius.c b/contrib/slapd-modules/passwd/radius.c
new file mode 100644 (file)
index 0000000..57b216c
--- /dev/null
@@ -0,0 +1,113 @@
+/* $OpenLDAP$ */
+/*
+ * Copyright 1998-2006 The OpenLDAP Foundation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted only as authorized by the OpenLDAP
+ * Public License.
+ *
+ * A copy of this license is available in the file LICENSE in the
+ * top-level directory of the distribution or, alternatively, at
+ * <http://www.OpenLDAP.org/license.html>.
+ */
+
+#include <stdio.h>
+
+#include <lber.h>
+#include <lber_pvt.h>  /* BER_BVC definition */
+#include "lutil.h"
+#include <ac/string.h>
+#include <ac/unistd.h>
+
+#include <radlib.h>
+
+static LUTIL_PASSWD_CHK_FUNC chk_radius;
+static const struct berval scheme = BER_BVC("{RADIUS}");
+static char *config_filename;
+
+static int
+chk_radius(
+       const struct berval     *sc,
+       const struct berval     *passwd,
+       const struct berval     *cred,
+       const char              **text )
+{
+       unsigned int            i;
+       int                     rc = LUTIL_PASSWD_ERR;
+
+       struct rad_handle       *h = NULL;
+
+       for ( i = 0; i < cred->bv_len; i++ ) {
+               if ( cred->bv_val[ i ] == '\0' ) {
+                       return LUTIL_PASSWD_ERR;        /* NUL character in cred */
+               }
+       }
+
+       if ( cred->bv_val[ i ] != '\0' ) {
+               return LUTIL_PASSWD_ERR;        /* cred must behave like a string */
+       }
+
+       for ( i = 0; i < passwd->bv_len; i++ ) {
+               if ( passwd->bv_val[ i ] == '\0' ) {
+                       return LUTIL_PASSWD_ERR;        /* NUL character in password */
+               }
+       }
+
+       if ( passwd->bv_val[ i ] != '\0' ) {
+               return LUTIL_PASSWD_ERR;        /* passwd must behave like a string */
+       }
+
+       h = rad_auth_open();
+       if ( h == NULL ) {
+               return LUTIL_PASSWD_ERR;
+       }
+
+       if ( rad_config( h, config_filename ) != 0 ) {
+               goto done;
+       }
+
+       if ( rad_create_request( h, RAD_ACCESS_REQUEST ) ) {
+               goto done;
+       }
+
+       if ( rad_put_string( h, RAD_USER_NAME, passwd->bv_val ) != 0 ) {
+               goto done;
+       }
+
+       if ( rad_put_string( h, RAD_USER_PASSWORD, cred->bv_val ) != 0 ) {
+               goto done;
+       }
+
+       if ( rad_send_request( h ) == RAD_ACCESS_ACCEPT ) {
+               rc = LUTIL_PASSWD_OK;
+       }
+
+done:;
+       rad_close( h );
+
+       return rc;
+}
+
+int
+init_module( int argc, char *argv[] )
+{
+       int     i;
+
+       for ( i = 0; i < argc; i++ ) {
+               if ( strncasecmp( argv[ i ], "config=", STRLENOF( "config=" ) ) == 0 ) {
+                       /* FIXME: what if multiple loads of same module?
+                        * does it make sense (e.g. override an existing one)? */
+                       if ( config_filename == NULL ) {
+                               config_filename = ber_strdup( &argv[ i ][ STRLENOF( "config=" ) ] );
+                       }
+
+               } else {
+                       fprintf( stderr, "init_module(radius): unknown arg#%d=\"%s\".\n",
+                               i, argv[ i ] );
+                       return 1;
+               }
+       }
+
+       return lutil_passwd_add( (struct berval *)&scheme, chk_radius, NULL );
+}
index 8ee5dc09571073c95f5c48a40db09774148eef37..b67916bac610f75fbc4057f721d862c817ea6339 100644 (file)
@@ -433,7 +433,7 @@ databases.
 This marks the beginning of a new {{TERM:BDB}} database instance.
 
 
-H4: olcAccess: to <what> [ by <who> <accesslevel> <control> ]+
+H4: olcAccess: to <what> [ by <who> [<accesslevel>] [<control>] ]+
 
 This directive grants access (specified by <accesslevel>) to a
 set of entries and/or attributes (specified by <what>) by one or
@@ -1013,7 +1013,7 @@ The general form of the olcAccess configuration is:
 
 >      olcAccess: <access directive>
 >      <access directive> ::= to <what>
->              [by <who> <access> <control>]+
+>              [by <who> [<access>] [<control>] ]+
 >      <what> ::= * |
 >              [dn[.<basic-style>]=<regex> | dn.<scope-style>=<DN>]
 >              [filter=<ldapfilter>] [attrs=<attrlist>]
index 08fc9a58d126e50f650830a9e0cdd426f490babb..091473e4649c2959fb1262cabb92c8b21be11ff3 100644 (file)
@@ -87,7 +87,7 @@ database definition.  Arguments that should be replaced
 by actual text are shown in brackets {{EX:<>}}.
 
 
-H4: access to <what> [ by <who> <accesslevel> <control> ]+
+H4: access to <what> [ by <who> [<accesslevel>] [<control>] ]+
 
 This directive grants access (specified by <accesslevel>) to a
 set of entries and/or attributes (specified by <what>) by one or
@@ -593,7 +593,7 @@ access configuration file directive. The general form of an
 access line is:
 
 >      <access directive> ::= access to <what>
->              [by <who> <access> <control>]+
+>              [by <who> [<access>] [<control>] ]+
 >      <what> ::= * |
 >              [dn[.<basic-style>]=<regex> | dn.<scope-style>=<DN>]
 >              [filter=<ldapfilter>] [attrs=<attrlist>]
index 192ab4fccccbcd4595102776e44380d346427857..0011354612c072516061d7c782d9c27ad2534e7e 100644 (file)
@@ -83,10 +83,10 @@ LDAP server to use.  Multiple URIs can be set in in a single
 argument, resulting in the underlying library automatically 
 call the first server of the list that responds, e.g. 
 
-\fBuri "ldap://host/ ldap://backup-host"\fP
+\fBuri "ldap://host/ ldap://backup-host/"\fP
 
 The URI list is space- or comma-separated.
-This statement is mandatory.
+.\"This statement is mandatory.
 .\".TP
 .\".B server <hostport>
 .\"Obsolete option; same as `uri ldap://<hostport>/'.
@@ -121,6 +121,33 @@ and
 .BR acl-passwd .
 .RE
 
+.TP
+.B chase-referrals {YES|no}
+enable/disable automatic referral chasing, which is delegated to the
+underlying libldap, with rebinding eventually performed if the
+\fBrebind-as-user\fP directive is used.  The default is to chase referrals.
+
+.TP
+.B conn-ttl <time>
+This directive causes a cached connection to be dropped an recreated
+after a given ttl, regardless of being idle or not.
+
+.TP
+.B idassert-authzFrom <authz-regexp>
+if defined, selects what
+.I local
+identities are authorized to exploit the identity assertion feature.
+The string
+.B <authz-regexp>
+follows the rules defined for the
+.I authzFrom
+attribute.
+See 
+.BR slapd.conf (5),
+section related to
+.BR authz-policy ,
+for details on the syntax of this field.
+
 .HP
 .hy 0
 .B idassert-bind
@@ -273,23 +300,25 @@ and
 .RE
 
 .TP
-.B idassert-authzFrom <authz-regexp>
-if defined, selects what
-.I local
-identities are authorized to exploit the identity assertion feature.
-The string
-.B <authz-regexp>
-follows the rules defined for the
-.I authzFrom
-attribute.
-See 
-.BR slapd.conf (5),
-section related to
-.BR authz-policy ,
-for details on the syntax of this field.
+.B idle-timeout <time>
+This directive causes a cached connection to be dropped an recreated
+after it has been idle for the specified time.
 
 .TP
-.B proxy-whoami {NO|yes}
+.B protocol\-version {0,2,3}
+This directive indicates what protocol version must be used to contact
+the remote server.
+If set to 0 (the default), the proxy uses the same protocol version 
+used by the client, otherwise the requested protocol is used.
+The proxy returns \fIunwillingToPerform\fP if an operation that is 
+incompatible with the requested protocol is attempted.
+
+.TP
+.B single\-conn {NO|yes}
+Discards current cached connection when the client rebinds.
+
+.TP
+.B proxy\-whoami {NO|yes}
 Turns on proxying of the WhoAmI extended operation. If this option is
 given, back-ldap will replace slapd's original WhoAmI routine with its
 own. On slapd sessions that were authenticated by back-ldap, the WhoAmI
@@ -303,21 +332,6 @@ If this option is given, the client's bind credentials are remembered
 for rebinds when chasing referrals.  Useful when
 \fBchase-referrals\fP is set to \fByes\fP, useless otherwise.
 
-.TP
-.B chase-referrals {YES|no}
-enable/disable automatic referral chasing, which is delegated to the
-underlying libldap, with rebinding eventually performed if the
-\fBrebind-as-user\fP directive is used.  The default is to chase referrals.
-
-.TP
-.B tls {[try-]start|[try-]propagate}
-execute the StartTLS extended operation when the connection is initialized;
-only works if the URI directive protocol scheme is not \fBldaps://\fP.
-\fBpropagate\fP issues the StartTLS operation only if the original
-connection did.
-The \fBtry-\fP prefix instructs the proxy to continue operations
-if the StartTLS operation failed; its use is highly deprecated.
-
 .TP
 .B t-f-support {NO|yes|discover}
 enable if the remote server supports absolute filters
@@ -342,14 +356,13 @@ the protocol does not provide any means to rollback the operation,
 so the client will not know if the operation eventually succeeded or not.
 
 .TP
-.B idle-timeout <time>
-This directive causes a cached connection to be dropped an recreated
-after it has been idle for the specified time.
-
-.TP
-.B conn-ttl <time>
-This directive causes a cached connection to be dropped an recreated
-after a given ttl, regardless of being idle or not.
+.B tls {[try-]start|[try-]propagate}
+execute the StartTLS extended operation when the connection is initialized;
+only works if the URI directive protocol scheme is not \fBldaps://\fP.
+\fBpropagate\fP issues the StartTLS operation only if the original
+connection did.
+The \fBtry-\fP prefix instructs the proxy to continue operations
+if the StartTLS operation failed; its use is highly deprecated.
 
 .SH BACKWARD COMPATIBILITY
 The LDAP backend has been heavily reworked between releases 2.2 and 2.3;
index 2bf1e8a0e83b1eda34e543577d498449ef400acc..8beab5adff09f1ba83804a2e5224bb6c773a74a4 100644 (file)
@@ -125,6 +125,17 @@ If this statement is set to \fBstop\fP, the search is terminated as soon
 as an error is returned by one target, and the error is immediately 
 propagated to the client.
 
+.TP
+.B protocol\-version {0,2,3}
+This directive indicates what protocol version must be used to contact
+the remote server.
+If set to 0 (the default), the proxy uses the same protocol version 
+used by the client, otherwise the requested protocol is used.
+The proxy returns \fIunwillingToPerform\fP if an operation that is 
+incompatible with the requested protocol is attempted.
+If set before any target specification, it affects all targets, unless
+overridden by any per-target directive.
+
 .TP
 .B pseudoroot-bind-defer {NO|yes}
 This directive, when set to 
@@ -137,6 +148,10 @@ identity to be deferred until actually needed by subsequent operations.
 If this option is given, the client's bind credentials are remembered
 for rebinds when chasing referrals.
 
+.TP
+.B single\-conn {NO|yes}
+Discards current cached connection when the client rebinds.
+
 .SH TARGET SPECIFICATION
 Target specification starts with a "uri" directive:
 
@@ -184,15 +199,6 @@ causes \fIl2.foo.com\fP to be contacted whenever \fIl1.foo.com\fP
 does not respond.
 .RE
 
-.TP
-.B subtree-exclude "<DN>"
-This directive instructs back-meta to ignore the current target
-for operations whose requestDN is subordinate to
-.BR DN .
-There may be multiple occurrences of the
-.B subtree-exclude
-directive for each of the targets.
-
 .TP
 .B acl-authcDN "<administrative DN for access control purposes>"
 DN which is used to query the target server for acl checking,
@@ -289,6 +295,15 @@ using the pseudorootdn/pseudorootpw directives is inherently unsafe.
 .B rewrite* ...
 The rewrite options are described in the "REWRITING" section.
 
+.TP
+.B subtree-exclude "<DN>"
+This directive instructs back-meta to ignore the current target
+for operations whose requestDN is subordinate to
+.BR DN .
+There may be multiple occurrences of the
+.B subtree-exclude
+directive for each of the targets.
+
 .TP
 .B suffixmassage "<virtual naming context>" "<real naming context>"
 All the directives starting with "rewrite" refer to the rewrite engine
index 93275f15f666e1999f44e55a0810be22f07548d6..e7220c7ee3526250e3b1f96127ae8c1481ce0b0f 100644 (file)
@@ -18,7 +18,8 @@ is surely the most useful part of
 .br
 - Updates return success (unless readonly is on) but do nothing.
 .br
-- Binds fail unless the database option "bind on" is given.
+- Binds other than as the rootdn fail unless the database option "bind
+on" is given.
 .br
 - The
 .BR slapadd (8)
index 3e5311efb103dcd7e2cd001220663040cdf8b163..1589b6557555d601403a282e63109a3f6bcc4bb1 100644 (file)
@@ -121,7 +121,10 @@ want the backend to handle.
 Operations for which a command is not supplied will be refused with an
 "unwilling to perform" error.
 .LP
-The commands - except \fBunbind\fP - should output:
+The \fBsearch\fP command should output the entries in LDIF format,
+each entry followed by a blank line, and after these the RESULT below.
+.LP
+All commands except \fBunbind\fP should then output:
 .RS
 .nf
 RESULT
@@ -130,9 +133,7 @@ matched: <matched DN>
 info: <text>
 .fi
 .RE
-where only RESULT is mandatory.
-The \fBsearch\fP RESULT should be preceded by the entries in LDIF
-format, each entry followed by a blank line.
+where only the RESULT line is mandatory.
 Lines starting with `#' or `DEBUG:' are ignored.
 .SH ACCESS CONTROL
 The
index cc8ac80572f639be629038886f7ff052dccf073e..fd3fa6dd864e57b7510216c284c0717cf3db48a9 100644 (file)
@@ -66,13 +66,57 @@ brackets <>.
 .SH THE ACCESS DIRECTIVE
 The structure of the access control directives is
 .TP
-.B access to <what> "[ by <who> <access> [ <control> ] ]+"
+.B access to <what> "[ by <who> [ <access> ] [ <control> ] ]+"
 Grant access (specified by 
 .BR <access> ) 
 to a set of entries and/or attributes (specified by 
 .BR <what> ) 
 by one or more requestors (specified by 
 .BR <who> ).
+
+.LP
+Lists of access directives are evaluated in the order they appear
+in \fIslapd.conf\fP.
+When a
+.B <what>
+clause matches the datum whose access is being evaluated, its
+.B <who>
+clause list is checked.
+When a
+.B <who>
+clause matches the accessor's properties, its
+.B <access>
+and
+.B <control>
+clauses are evaluated.
+Access control checking stops at the first match of the
+.B <what>
+and
+.B <who>
+clause, unless otherwise dictated by the
+.B <control>
+clause.
+Each
+.B <who>
+clause list is implicitly terminated by a
+.LP
+.nf
+       by * none stop
+.fi
+.LP
+clause that results in stopping the access control with no access 
+privileges granted.
+Each
+.B <what>
+clause list is implicitly terminated by a
+.LP
+.nf
+       access to *
+               by * none
+.fi
+.LP
+clause that results in granting no access privileges to an otherwise
+unspecified datum.
 .SH THE <WHAT> FIELD
 The field
 .BR <what>
@@ -80,7 +124,7 @@ specifies the entity the access control directive applies to.
 It can have the forms
 .LP
 .nf
-       [dn[.<dnstyle>]=]<dnpattern>
+       dn[.<dnstyle>]=<dnpattern>
        filter=<ldapfilter>
        attrs=<attrlist>[ val[/matchingRule][.<attrstyle>]=<attrval>]
 .fi
@@ -98,9 +142,6 @@ with
 The statement
 .B dn=<dnpattern>
 selects the entries based on their naming context.
-The 
-.B dn=
-part is optional.
 The
 .B <dnpattern>
 is a string representation of the entry's DN.
@@ -112,11 +153,7 @@ form is given.
 .LP
 The 
 .B <dnstyle> 
-is also optional; however, it is recommended to specify both the 
-.B dn=
-and the
-.B <dnstyle>
-to avoid ambiguities.
+is optional; however, it is recommended to specify it to avoid ambiguities.
 .B Base 
 (synonym of
 .BR baseObject ),
@@ -657,7 +694,7 @@ and
 set the minimum required Security Strength Factor (ssf) needed
 to grant access.  The value should be positive integer.
 .SH THE <ACCESS> FIELD
-The field
+The optional field
 .B <access> ::= [[real]self]{<level>|<priv>}
 determines the access level or the specific access privileges the
 .B who 
@@ -750,6 +787,7 @@ for disclose.
 More than one of the above privileges can be added in one statement.
 .B 0
 indicates no privileges and is used only by itself (e.g., +0).
+.LP
 If no access is given, it defaults to 
 .BR +0 .
 .SH THE <CONTROL> FIELD
index 32911db27a64fab89f3939b18912ad2c7929e880..3352e01d4aae20cdda490cb8bd1b655531a7895e 100644 (file)
@@ -1520,10 +1520,10 @@ in order to work over all of the glued databases. E.g.
 .hy 0
 .B syncrepl rid=<replica ID>
 .B provider=ldap[s]://<hostname>[:port]
+.B searchbase=<base DN>
 .B [type=refreshOnly|refreshAndPersist]
 .B [interval=dd:hh:mm:ss]
 .B [retry=[<retry interval> <# of retries>]+]
-.B [searchbase=<base DN>]
 .B [filter=<filter str>]
 .B [scope=sub|one|base|subord]
 .B [attrs=<attr list>]
@@ -1531,7 +1531,6 @@ in order to work over all of the glued databases. E.g.
 .B [sizelimit=<limit>]
 .B [timelimit=<limit>]
 .B [schemachecking=on|off]
-.B [starttls=yes|critical]
 .B [bindmethod=simple|sasl]
 .B [binddn=<dn>]
 .B [saslmech=<mech>]
@@ -1540,6 +1539,14 @@ in order to work over all of the glued databases. E.g.
 .B [credentials=<passwd>]
 .B [realm=<realm>]
 .B [secprops=<properties>]
+.B [starttls=yes|critical]
+.B [tls_cert=<file>]
+.B [tls_key=<file>]
+.B [tls_cacert=<file>]
+.B [tls_cacertdir=<path>]
+.B [tls_reqcert=never|allow|try|demand]
+.B [tls_ciphersuite=<ciphers>]
+.B [tls_crlcheck=none|peer|all]
 .B [logbase=<base DN>]
 .B [logfilter=<filter str>]
 .B [syncdata=default|accesslog|changelog]
@@ -1611,13 +1618,6 @@ The schema checking can be enforced at the LDAP Sync
 consumer site by turning on the
 .B schemachecking
 parameter. The default is off.
-The
-.B starttls
-parameter specifies use of the StartTLS extended operation
-to establish a TLS session before Binding to the provider. If the
-.B critical
-argument is supplied, the session will be aborted if the StartTLS request
-fails. Otherwise the syncrepl session continues without TLS.
 A
 .B bindmethod
 of 
@@ -1650,6 +1650,18 @@ option. A non default SASL realm can be set with the
 .B realm 
 option.
 
+The
+.B starttls
+parameter specifies use of the StartTLS extended operation
+to establish a TLS session before Binding to the provider. If the
+.B critical
+argument is supplied, the session will be aborted if the StartTLS request
+fails. Otherwise the syncrepl session continues without TLS.  Note that the
+main slapd TLS settings are not used by the syncrepl engine;
+by default the TLS parameters from ETCDIR/ldap.conf will be used.
+TLS settings may be specified here, in which case the ldap.conf settings
+will be completely ignored.
+
 Rather than replicating whole entries, the consumer can query logs of
 data modifications. This mode of operation is referred to as \fIdelta
 syncrepl\fP. In addition to the above parameters, the
index 2a28cd82a4986e10e8901d019313717aa89035b2..c27e4834706a9eb782a48c788dfbf97c03d827d9 100644 (file)
@@ -49,6 +49,17 @@ abandon, bind, unbind
 all operations
 .RE
 .TP
+.B logold <filter>
+Specify a filter for matching against Deleted and Modified entries. If
+the entry matches the filter, the old contents of the entry will be
+logged along with the current request.
+.TP
+.B logoldattr <attr> ...
+Specify a list of attributes whose old contents are always logged in
+Modify and ModRDN requests. Usually only the contents of attributes that were
+actually modified will be logged; by default no old attributes are logged
+for ModRDN requests.
+.TP
 .B logpurge <age> <interval>
 Specify the maximum age for log entries to be retained in the database,
 and how often to scan the database for old entries. Both the
@@ -94,6 +105,7 @@ succeed or not. The default is FALSE.
        overlay accesslog
        logdb cn=log
        logops writes reads
+       logold (objectclass=person)
 .fi
 
 .SH SCHEMA
@@ -103,7 +115,7 @@ overlay utilizes the "audit" schema described herein.
 This schema is specifically designed for
 .B accesslog
 auditing and is not intended to be used otherwise.  It is also
-noted that the schema describe here is
+noted that the schema described here is
 .I a work in
 .IR progress ,
 and hence subject to change without notice.
@@ -310,7 +322,12 @@ to its deletion. The values are formatted as
 attribute: value
 .RE
 .PD
-This option is not yet implemented.
+The
+.B reqOld
+attribute is only populated if the entry being deleted matches the
+configured
+.B logold
+filter.
 
 .LP
 .RS 4
@@ -329,7 +346,12 @@ attribute, which was already described above in the Add operation. It may
 optionally contain the previous contents of any modified attributes in the
 .B reqOld
 attribute, using the same format as described above for the Delete operation.
-This option is not yet implemented.
+The
+.B reqOld
+attribute is only populated if the entry being modified matches the
+configured
+.B logold
+filter.
 
 .LP
 .RS 4
@@ -338,7 +360,7 @@ This option is not yet implemented.
     DESC 'ModRDN operation'
     SUP auditWriteObject STRUCTURAL
     MUST ( reqNewRDN $ reqDeleteOldRDN )
-    MAY reqNewSuperior )
+    MAY ( reqNewSuperior $ reqOld ) )
 .RE
 .P
 The
@@ -357,6 +379,14 @@ The
 .B reqNewSuperior
 attribute carries the DN of the new parent entry if the request specified
 the new parent.
+The
+.B reqOld
+attribute is only populated if the entry being modified matches the
+configured
+.B logold
+filter and contains attributes in the
+.B logoldattr
+list.
 
 .LP
 .RS 4
index 3cba0bb71927f625ec1b015c6d57be4a34057781..4f80335d6613b9349c38a282dfcd753d5d3cf3ae 100644 (file)
@@ -33,12 +33,19 @@ Databases configured as
 .B subordinate
 of this one are also output, unless \fB-g\fP is specified.
 .LP
-The LDIF generated by this tool is suitable for use with
+The entry records are presented in database order, not superior first
+order.  The entry records will include all (user and operational)
+attributes stored in the database.  The entry records will not include
+dynamically generated attributes (such as subschemaSubentry).
+.LP
+The output of slapcat is intended to be used as input to
 .BR slapadd (8).
-As the entries are in database order, not superior first order,
-they cannot be loaded with
+The output of slapcat cannot generally be used as input to
 .BR ldapadd (1)
-without first being reordered.
+or other LDAP clients without first editing the output.
+This editing would normally include reordering the records
+into superior first order and removing no-user-modification
+operational attributes.
 .SH OPTIONS
 .TP
 .B \-v
index df0a82a9eef545ce483ce7f081331e5b48f1d9a9..f91a73233fcbc19126a0f8cb9708fede20436900 100644 (file)
@@ -13,6 +13,7 @@ slapd \- Stand-alone LDAP Daemon
 .B [\-F slapd\-config\-directory]
 .B [\-h URLs]
 .B [\-n service\-name] [\-s syslog\-level] [\-l syslog\-local\-user]
+.B [\-o option[=value]]
 .B [\-r directory]
 .B [\-u user] [\-g group]
 .B [\-c cookie]
@@ -85,7 +86,7 @@ If this option is specified, even with a zero argument,
 will not fork or disassociate from the invoking terminal.  Some general
 operation and status messages are printed for any value of \fIdebug\-level\fP.
 \fIdebug\-level\fP is taken as a bit string, with each bit corresponding to a
-different kind of debugging information.  See <ldap.h> for details.
+different kind of debugging information.  See <ldap_log.h> for details.
 Comma-separated arrays of friendly names can be specified to select
 debugging output of the corresponding debugging information.
 All the names recognized by the \fIloglevel\fP directive 
@@ -236,6 +237,30 @@ must be provided in order for any other specified values to be used.
 is the commit sequence number received by a previous synchronization
 and represents the state of the consumer replica content which the
 syncrepl engine will synchronize to the current provider content.
+.TP
+.BI \-o " option[=value]"
+This option provides a generic means to specify options without the need to reserve
+a separate letter for them.
+
+It supports the following options:
+.RS
+.TP
+slp={\fBon\fP|\fBoff\fP|\fIslp\-attrs\fP}
+When SLP support is compiled into slapd, disable it (
+.B off
+), enable it by registering at SLP DAs without specific SLP attributes (
+.B on
+), or with specific SLP attributes
+.I slp\-attrs
+that must be an SLP attribute list definition according to the SLP standard.
+
+For example, "-o slp=(tree=production),(server-type=OpenLDAP),(server-version=2.3.20)"
+registers at SLP DAs with the three SLP attributes tree, server-type and server-version
+that have the values given above.
+This allows to specifically query the SLP DAs for LDAP servers holding the
+.I production
+tree in case multiple trees are availabe.
+.RE
 .SH EXAMPLES
 To start 
 .I slapd
index 8cd7d8a58773cb22a2c26dc8a47e4689829d902e..9750da398aa00e0c4b6ddfe27c69ec1db052ae54 100644 (file)
@@ -8,9 +8,10 @@ slappasswd \- OpenLDAP password utility
 .B SBINDIR/slappasswd
 .B [\-v]
 .B [\-u]
-.B [\-s secret|\-T file]
+.B [\-g|\-s secret|\-T file]
 .B [\-h hash]
 .B [\-c salt-format]
+.B [\-n]
 .B 
 .LP
 .SH DESCRIPTION
@@ -35,20 +36,46 @@ by default.  This option is provided for forward compatibility.
 .TP
 .BI \-s " secret"
 The secret to hash.
-If this and
+If this,
+.B \-g
+and
 .B \-T
 are absent, the user will be prompted for the secret to hash.
+.BR \-s ,
+.B \-g
+and
+.B \-T
+and mutually exclusive flags.
+.TP
+.BI \-g
+Generate the secret.
+If this,
 .B \-s
 and
 .B \-T
+are absent, the user will be prompted for the secret to hash.
+.BR \-s ,
+.B \-g
+and
+.B \-T
 and mutually exclusive flags.
+If this is present,
+.I {CLEARTEXT}
+is used as scheme.
+.B \-g
+and
+.B \-h
+are mutually exclusive flags.
 .TP
 .BI \-T " file"
 Hash the contents of the file.
-If this and
+If this,
+.B \-g
+and
 .B \-s
 are absent, the user will be prompted for the secret to hash.
-.B \-s
+.BR \-s ,
+.B \-g
 and
 .B \-T
 and mutually exclusive flags.
@@ -87,6 +114,10 @@ uses the
 .B {CLEARTEXT}
 indicates that the new password should be added to userPassword as
 clear text.
+Unless
+.I {CLEARTEXT}
+is used, this flag is incompatible with
+.BR \-g .
 .TP
 .BI \-c " crypt-salt-format"
 Specify the format of the salt passed to
@@ -101,6 +132,10 @@ provides a two character salt and '$1$%.8s' tells some
 versions of crypt(3) to use an MD5 algorithm and provides
 8 random characters of salt.  The default is '%s', which
 provides 31 characters of salt.
+.TP
+.BI \-n
+Omit the trailing newline; useful to pipe the credentials
+into a command.
 .SH LIMITATIONS
 The practice storing hashed passwords in userPassword violates
 Standard Track (RFC 2256) schema specifications and may hinder
index dc9e9d2d0115d99d9731c9d167347d94d3e6c884..c567d6adcc0389b41f205d4b6d12286f1bf4dc33 100644 (file)
@@ -120,6 +120,7 @@ LDAP_BEGIN_DECL
 #define LDAP_OPT_URI                           0x5006
 #define LDAP_OPT_REFERRAL_URLS      0x5007  /* Referral URLs */
 #define LDAP_OPT_SOCKBUF            0x5008  /* sockbuf */
+#define LDAP_OPT_DEFBASE               0x5009  /* searchbase */
 
 /* OpenLDAP TLS options */
 #define LDAP_OPT_X_TLS                         0x6000
@@ -783,6 +784,19 @@ ldap_set_nextref_proc LDAP_P((
        LDAP_NEXTREF_PROC *nextref_proc,
        void *params ));
 
+/* V3 URLLIST Function Callback Prototype */
+typedef int (LDAP_URLLIST_PROC) LDAP_P((
+       LDAP *ld, 
+       LDAPURLDesc **urllist,
+       LDAPURLDesc **url,
+       void *params ));
+
+LDAP_F( int )
+ldap_set_urllist_proc LDAP_P((
+       LDAP *ld,
+       LDAP_URLLIST_PROC *urllist_proc,
+       void *params ));
+
 /*
  * in controls.c:
  */
index ccf293bf2a6c973a7a36cc80449f704b1fad15f5..46c79ae8de6d59b29b63961d5dd23c22070dd80f 100644 (file)
@@ -227,6 +227,7 @@ LDAP_F(int) ldap_int_thread_pool_shutdown ( void );
 typedef struct ldap_int_thread_pool_s * ldap_int_thread_pool_t;
 #endif
 
+typedef struct ldap_int_thread_rmutex_s * ldap_int_thread_rmutex_t;
 LDAP_END_DECL
 
 
index 33eac0f87d763ac5aeb74809fb5a0a136fe12d44..f414d45a03311b345de92a3ba32acc46bac08455 100644 (file)
@@ -226,7 +226,7 @@ extern void eb_syslog(int pri, const char *fmt, ...);
                        lutil_debug( ldap_debug, (level), (fmt), (arg1), (arg2), (arg3), (arg4), (arg5) ); \
        } while ( 0 )
 #define Debug( level, fmt, arg1, arg2, arg3 ) \
-               Log3( (level), (fmt), (arg1), (arg2), (arg3) )
+               Log3( (level), 0, (fmt), (arg1), (arg2), (arg3) )
 #define LogTest(level) ( ldap_debug & (level) )
 #endif /* ! LDAP_SYSLOG */
 #else /* ! LDAP_DEBUG */
index 7463c9ea273e6b3d0c74c470a79812c5a287837b..89fe20c6f0e1e434e075bc1a2ea80b15a2c2fdea 100644 (file)
@@ -41,10 +41,29 @@ ldap_pvt_url_scheme_port LDAP_P((
 
 struct ldap_url_desc; /* avoid pulling in <ldap.h> */
 
+#define LDAP_PVT_URL_PARSE_NONE                        (0x00U)
+#define LDAP_PVT_URL_PARSE_NOEMPTY_HOST                (0x01U)
+#define LDAP_PVT_URL_PARSE_DEF_PORT            (0x02U)
+#define LDAP_PVT_URL_PARSE_NOEMPTY_DN          (0x04U)
+#define LDAP_PVT_URL_PARSE_NODEF_SCOPE         (0x08U)
+#define        LDAP_PVT_URL_PARSE_HISTORIC             (LDAP_PVT_URL_PARSE_NODEF_SCOPE | LDAP_PVT_URL_PARSE_NOEMPTY_HOST | LDAP_PVT_URL_PARSE_DEF_PORT)
 LDAP_F( int )
 ldap_url_parse_ext LDAP_P((
        LDAP_CONST char *url,
-       struct ldap_url_desc **ludpp ));
+       struct ldap_url_desc **ludpp,
+       unsigned flags ));
+
+LDAP_F (int) ldap_url_parselist_ext LDAP_P((
+       struct ldap_url_desc **ludlist,
+       const char *url,
+       const char *sep,
+       unsigned flags ));
+
+LDAP_F (char *) ldap_url_list2urls LDAP_P((
+       struct ldap_url_desc *ludlist ));
+
+LDAP_F (void) ldap_free_urllist LDAP_P((
+       struct ldap_url_desc *ludlist ));
 
 LDAP_F( char * )
 ldap_pvt_ctime LDAP_P((
index 3f2d48fb11407a27ea387d056086ce945ec6f39f..fe8b5beb94d12f9c1a6accb45fb9ca23ae9246ff 100644 (file)
@@ -33,6 +33,7 @@ typedef ldap_int_thread_mutex_t               ldap_pvt_thread_mutex_t;
 typedef ldap_int_thread_cond_t         ldap_pvt_thread_cond_t;
 typedef ldap_int_thread_rdwr_t         ldap_pvt_thread_rdwr_t;
 #endif
+typedef ldap_int_thread_rmutex_t       ldap_pvt_thread_rmutex_t;
 #endif /* !LDAP_PVT_THREAD_H_DONE */
 
 #if 0 && defined(LDAP_DEVEL)
@@ -122,6 +123,24 @@ ldap_pvt_thread_mutex_trylock LDAP_P(( ldap_pvt_thread_mutex_t *mutex ));
 LDAP_F( int )
 ldap_pvt_thread_mutex_unlock LDAP_P(( ldap_pvt_thread_mutex_t *mutex ));
 
+LDAP_F( int )
+ldap_pvt_thread_rmutex_init LDAP_P(( ldap_pvt_thread_rmutex_t *rmutex ));
+
+LDAP_F( int )
+ldap_pvt_thread_rmutex_destroy LDAP_P(( ldap_pvt_thread_rmutex_t *rmutex ));
+
+LDAP_F( int )
+ldap_pvt_thread_rmutex_lock LDAP_P(( ldap_pvt_thread_rmutex_t *rmutex,
+       ldap_pvt_thread_t owner));
+
+LDAP_F( int )
+ldap_pvt_thread_rmutex_trylock LDAP_P(( ldap_pvt_thread_rmutex_t *rmutex,
+       ldap_pvt_thread_t owner));
+
+LDAP_F( int )
+ldap_pvt_thread_rmutex_unlock LDAP_P(( ldap_pvt_thread_rmutex_t *rmutex,
+       ldap_pvt_thread_t owner));
+
 LDAP_F( ldap_pvt_thread_t )
 ldap_pvt_thread_self LDAP_P(( void ));
 
@@ -233,7 +252,10 @@ ldap_pvt_thread_pool_context LDAP_P(( void ));
 LDAP_F( void )
 ldap_pvt_thread_pool_context_reset LDAP_P(( void *key ));
 
+LDAP_F( ldap_pvt_thread_t )
+ldap_pvt_thread_pool_tid LDAP_P(( void *ctx ));
+
 LDAP_END_DECL
 
 #define LDAP_PVT_THREAD_H_DONE
-#endif /* _LDAP_THREAD_H */
+#endif /* _LDAP_PVT_THREAD_H */
index 3e124778c9d4380129b1da9d2691e7d49f6988b5..1e3aea16f161a9dbd23eb52b8a9720c3e3854fc9 100644 (file)
@@ -63,7 +63,7 @@ ldap_pvt_runqueue_remove(
 LDAP_F( struct re_s* )
 ldap_pvt_runqueue_next_sched(
        struct runqueue_s* rq,
-       struct timeval** next_run
+       struct timeval* next_run
 );
 
 LDAP_F( void )
index 694555aca2b02915a32ef7ffd192156c2536ca19..4f976887ef62bfab5375881c2c6e414767d27788 100644 (file)
 /* define for Audit Logging overlay */
 #undef SLAPD_OVER_AUDITLOG
 
+/* define for Attribute Constraint overlay */
+#undef SLAPD_OVER_CONSTRAINT
+
 /* define for Dynamic Directory Services overlay */
 #undef SLAPD_OVER_DDS
 
index ef77a2d46f4b0d3b589645fd91455575a30f02a1..1d9b4c0546a5a07c2b303699aff77bed6d1072fa 100644 (file)
@@ -13,7 +13,7 @@
  * <http://www.OpenLDAP.org/license.html>.
  */
 /* ACKNOWLEDGEMENTS:
- * This program was orignally developed by Kurt D. Zeilenga for inclusion
+ * This program was originally developed by Kurt D. Zeilenga for inclusion
  * in OpenLDAP Software.
  */
 
index 6c82969f0957dfb8ca31eff6514a88661c35126d..936f44d35b53e33b3faa9bb6e0250065a30375c1 100644 (file)
@@ -602,23 +602,31 @@ ldap_int_sasl_bind(
                return ld->ld_errno;
        }
 
+       rc = 0;
+#ifdef LDAP_R_COMPILE
+       ldap_pvt_thread_mutex_lock( &ld->ld_req_mutex );
+#endif
        ber_sockbuf_ctrl( ld->ld_sb, LBER_SB_OPT_GET_FD, &sd );
 
        if ( sd == AC_SOCKET_INVALID ) {
                /* not connected yet */
-               int rc;
 
                rc = ldap_open_defconn( ld );
-               if( rc < 0 ) return ld->ld_errno;
 
-               ber_sockbuf_ctrl( ld->ld_defconn->lconn_sb,
-                       LBER_SB_OPT_GET_FD, &sd );
+               if ( rc == 0 ) {
+                       ber_sockbuf_ctrl( ld->ld_defconn->lconn_sb,
+                               LBER_SB_OPT_GET_FD, &sd );
 
-               if( sd == AC_SOCKET_INVALID ) {
-                       ld->ld_errno = LDAP_LOCAL_ERROR;
-                       return ld->ld_errno;
+                       if( sd == AC_SOCKET_INVALID ) {
+                               ld->ld_errno = LDAP_LOCAL_ERROR;
+                               rc = ld->ld_errno;
+                       }
                }
        }   
+#ifdef LDAP_R_COMPILE
+       ldap_pvt_thread_mutex_unlock( &ld->ld_req_mutex );
+#endif
+       if( rc != 0 ) return ld->ld_errno;
 
        oldctx = ld->ld_defconn->lconn_sasl_authctx;
 
index a7f05c2c56e0e9232c6b8f8df00470b9c08578a5..ef21432fddcf974d585ff2ae146cfc7702b3fa07 100644 (file)
@@ -255,12 +255,18 @@ ldap_get_kerberosv4_credentials(
                return( NULL );
        }
 
+       err = 0;
+#ifdef LDAP_R_COMPILE
+       ldap_pvt_thread_mutex_lock( &ld->ld_req_mutex );
+#endif
        if ( ber_sockbuf_ctrl( ld->ld_sb, LBER_SB_OPT_GET_FD, NULL ) == -1 ) {
                /* not connected yet */
-               int rc = ldap_open_defconn( ld );
-
-               if( rc < 0 ) return NULL;
+               err = ldap_open_defconn( ld );
        }
+#ifdef LDAP_R_COMPILE
+       ldap_pvt_thread_mutex_unlock( &ld->ld_req_mutex );
+#endif
+       if ( err < 0 ) return NULL;
 
        krbinstance = ld->ld_defconn->lconn_krbinstance;
 
index 99d7331122515804692c2d55de39e673749b1b39..9863b32b60c49a32cd054749ecec886a2012b061 100644 (file)
@@ -225,6 +225,8 @@ struct ldapoptions {
        void *ldo_rebind_params;
        LDAP_NEXTREF_PROC *ldo_nextref_proc;
        void *ldo_nextref_params;
+       LDAP_URLLIST_PROC *ldo_urllist_proc;
+       void *ldo_urllist_params;
 
        LDAP_BOOLEANS ldo_booleans;     /* boolean options */
 };
@@ -339,6 +341,8 @@ struct ldap {
 #define ld_rebind_params       ld_options.ldo_rebind_params
 #define ld_nextref_proc                ld_options.ldo_nextref_proc
 #define ld_nextref_params      ld_options.ldo_nextref_params
+#define ld_urllist_proc                ld_options.ldo_urllist_proc
+#define ld_urllist_params      ld_options.ldo_urllist_params
 
 #define ld_version             ld_options.ldo_version
 
@@ -525,8 +529,8 @@ LDAP_F (ber_int_t) ldap_send_initial_request( LDAP *ld, ber_tag_t msgtype,
 LDAP_F (BerElement *) ldap_alloc_ber_with_options( LDAP *ld );
 LDAP_F (void) ldap_set_ber_options( LDAP *ld, BerElement *ber );
 
-LDAP_F (int) ldap_send_server_request( LDAP *ld, BerElement *ber, ber_int_t msgid, LDAPRequest *parentreq, LDAPURLDesc *srvlist, LDAPConn *lc, LDAPreqinfo *bind );
-LDAP_F (LDAPConn *) ldap_new_connection( LDAP *ld, LDAPURLDesc *srvlist, int use_ldsb, int connect, LDAPreqinfo *bind );
+LDAP_F (int) ldap_send_server_request( LDAP *ld, BerElement *ber, ber_int_t msgid, LDAPRequest *parentreq, LDAPURLDesc **srvlist, LDAPConn *lc, LDAPreqinfo *bind );
+LDAP_F (LDAPConn *) ldap_new_connection( LDAP *ld, LDAPURLDesc **srvlist, int use_ldsb, int connect, LDAPreqinfo *bind );
 LDAP_F (LDAPRequest *) ldap_find_request_by_msgid( LDAP *ld, ber_int_t msgid );
 LDAP_F (void) ldap_free_request( LDAP *ld, LDAPRequest *lr );
 LDAP_F (void) ldap_free_connection( LDAP *ld, LDAPConn *lc, int force, int unbind );
@@ -589,11 +593,6 @@ LDAP_F (int) ldap_url_parselist LDAP_P((
        LDAPURLDesc **ludlist,
        const char *url ));
 
-LDAP_F (int) ldap_url_parselist_ext LDAP_P((
-       LDAPURLDesc **ludlist,
-       const char *url,
-       const char *sep ));
-
 LDAP_F (int) ldap_url_parsehosts LDAP_P((
        LDAPURLDesc **ludlist,
        const char *hosts,
@@ -602,12 +601,6 @@ LDAP_F (int) ldap_url_parsehosts LDAP_P((
 LDAP_F (char *) ldap_url_list2hosts LDAP_P((
        LDAPURLDesc *ludlist ));
 
-LDAP_F (char *) ldap_url_list2urls LDAP_P((
-       LDAPURLDesc *ludlist ));
-
-LDAP_F (void) ldap_free_urllist LDAP_P((
-       LDAPURLDesc *ludlist ));
-
 /*
  * in cyrus.c
  */
index d1eaf04b2ac6dd8b4696792ad2e8bb3cfe11c718..785260a5d8ec9c28f2b350c0ea9cd1b7e9f5feee 100644 (file)
 #include "ldap-int.h"
 #include "ldap_log.h"
 
+/* Caller should hold the req_mutex if simultaneous accesses are possible */
 int ldap_open_defconn( LDAP *ld )
 {
        ld->ld_defconn = ldap_new_connection( ld,
-               ld->ld_options.ldo_defludp, 1, 1, NULL );
+               &ld->ld_options.ldo_defludp, 1, 1, NULL );
 
        if( ld->ld_defconn == NULL ) {
                ld->ld_errno = LDAP_SERVER_DOWN;
index 1cfd9487b7dced4c1136e3496cecdd861ada4fa1..cca205a0d97b11f52dfeebc73b683fd71602b199 100644 (file)
@@ -31,6 +31,9 @@
 #define LDAP_OPT_NEXTREF_PROC 0x4e815d
 #define LDAP_OPT_NEXTREF_PARAMS 0x4e815e
 
+#define LDAP_OPT_URLLIST_PROC 0x4e816d
+#define LDAP_OPT_URLLIST_PARAMS 0x4e816e
+
 static const LDAPAPIFeatureInfo features[] = {
 #ifdef LDAP_API_FEATURE_X_OPENLDAP
        {       /* OpenLDAP Extensions API Feature */
@@ -230,6 +233,15 @@ ldap_get_option(
                * (char **) outvalue = ldap_url_list2urls(lo->ldo_defludp);
                return LDAP_OPT_SUCCESS;
 
+       case LDAP_OPT_DEFBASE:
+               if( lo->ldo_defbase == NULL ) {
+                       * (char **) outvalue = NULL;
+               } else {
+                       * (char **) outvalue = LDAP_STRDUP(lo->ldo_defbase);
+               }
+
+               return LDAP_OPT_SUCCESS;
+
        case LDAP_OPT_ERROR_NUMBER:
                if(ld == NULL) {
                        /* bad param */
@@ -466,7 +478,9 @@ ldap_set_option(
                                 * must want global default returned
                                 * to initial condition.
                                 */
-                               rc = ldap_url_parselist(&ludlist, "ldap://localhost/");
+                               rc = ldap_url_parselist_ext(&ludlist, "ldap://localhost/", NULL,
+                                       LDAP_PVT_URL_PARSE_NOEMPTY_HOST
+                                       | LDAP_PVT_URL_PARSE_DEF_PORT );
 
                        } else {
                                /*
@@ -493,13 +507,17 @@ ldap_set_option(
                        int rc = LDAP_OPT_SUCCESS;
 
                        if(urls != NULL) {
-                               rc = ldap_url_parselist(&ludlist, urls);
+                               rc = ldap_url_parselist_ext(&ludlist, urls, NULL,
+                                       LDAP_PVT_URL_PARSE_NOEMPTY_HOST
+                                       | LDAP_PVT_URL_PARSE_DEF_PORT );
                        } else if(ld == NULL) {
                                /*
                                 * must want global default returned
                                 * to initial condition.
                                 */
-                               rc = ldap_url_parselist(&ludlist, "ldap://localhost/");
+                               rc = ldap_url_parselist_ext(&ludlist, "ldap://localhost/", NULL,
+                                       LDAP_PVT_URL_PARSE_NOEMPTY_HOST
+                                       | LDAP_PVT_URL_PARSE_DEF_PORT );
 
                        } else {
                                /*
@@ -509,7 +527,7 @@ ldap_set_option(
                                ludlist = ldap_url_duplist(
                                        ldap_int_global_options.ldo_defludp);
                                if (ludlist == NULL)
-                                       rc = LDAP_NO_MEMORY;
+                                       rc = LDAP_URL_ERR_MEM;
                        }
 
                        switch (rc) {
@@ -534,7 +552,7 @@ ldap_set_option(
                                break;
                        }
 
-                       if (rc == LDAP_OPT_SUCCESS) {
+                       if (rc == LDAP_SUCCESS) {
                                if (lo->ldo_defludp != NULL)
                                        ldap_free_urllist(lo->ldo_defludp);
                                lo->ldo_defludp = ludlist;
@@ -542,6 +560,24 @@ ldap_set_option(
                        return rc;
                }
 
+       case LDAP_OPT_DEFBASE: {
+                       const char *newbase = (const char *) invalue;
+                       char *defbase = NULL;
+
+                       if ( newbase != NULL ) {
+                               defbase = LDAP_STRDUP( newbase );
+                               if ( defbase == NULL ) return LDAP_NO_MEMORY;
+
+                       } else if ( ld != NULL ) {
+                               defbase = LDAP_STRDUP( ldap_int_global_options.ldo_defbase );
+                               if ( defbase == NULL ) return LDAP_NO_MEMORY;
+                       }
+                       
+                       if ( lo->ldo_defbase != NULL )
+                               LDAP_FREE( lo->ldo_defbase );
+                       lo->ldo_defbase = defbase;
+               } return LDAP_OPT_SUCCESS;
+
        case LDAP_OPT_ERROR_STRING: {
                        const char *err = (const char *) invalue;
 
@@ -611,6 +647,14 @@ ldap_set_option(
                        lo->ldo_nextref_params = (void *)invalue;               
                } return LDAP_OPT_SUCCESS;
 
+       /* Only accessed from inside this function by ldap_set_urllist_proc() */
+       case LDAP_OPT_URLLIST_PROC: {
+                       lo->ldo_urllist_proc = (LDAP_URLLIST_PROC *)invalue;            
+               } return LDAP_OPT_SUCCESS;
+       case LDAP_OPT_URLLIST_PARAMS: {
+                       lo->ldo_urllist_params = (void *)invalue;               
+               } return LDAP_OPT_SUCCESS;
+
        /* read-only options */
        case LDAP_OPT_API_INFO:
        case LDAP_OPT_DESC:
@@ -706,3 +750,14 @@ ldap_set_nextref_proc( LDAP *ld, LDAP_NEXTREF_PROC *proc, void *params )
        rc = ldap_set_option( ld, LDAP_OPT_NEXTREF_PARAMS, (void *)params );
        return rc;
 }
+
+int
+ldap_set_urllist_proc( LDAP *ld, LDAP_URLLIST_PROC *proc, void *params )
+{
+       int rc;
+       rc = ldap_set_option( ld, LDAP_OPT_URLLIST_PROC, (void *)proc );
+       if( rc != LDAP_OPT_SUCCESS ) return rc;
+
+       rc = ldap_set_option( ld, LDAP_OPT_URLLIST_PARAMS, (void *)params );
+       return rc;
+}
index 8898a9f0cd92dbd89a94d9674bd7d02b8791ac0b..2551fb5876e1a81d027f1f579285ed0b2bc7b0d7 100644 (file)
 
 #ifdef LDAP_CONTROL_PASSWORDPOLICYREQUEST
 
-#define PPOLICY_WARNING 0xa0L
-#define PPOLICY_ERROR 0xa1L
+/* IMPLICIT TAGS, all context-specific */
+#define PPOLICY_WARNING 0xa0L  /* constructed + 0 */
+#define PPOLICY_ERROR 0x81L            /* primitive + 1 */
 
-#define PPOLICY_EXPIRE 0xa0L
-#define PPOLICY_GRACE  0xa1L
+#define PPOLICY_EXPIRE 0x80L   /* primitive + 0 */
+#define PPOLICY_GRACE  0x81L   /* primitive + 1 */
 
 /*---
    ldap_create_passwordpolicy_control
index c4a5514a1bc8ce08fd78a64e25aab185fdd32d90..2fa9f0f8abf6e4f37781b627d38e2d2e3e9cc139 100644 (file)
@@ -93,19 +93,25 @@ ldap_send_initial_request(
        BerElement *ber,
        ber_int_t msgid)
 {
-       int rc;
+       int rc = 1;
 
        Debug( LDAP_DEBUG_TRACE, "ldap_send_initial_request\n", 0, 0, 0 );
 
+#ifdef LDAP_R_COMPILE
+       ldap_pvt_thread_mutex_lock( &ld->ld_req_mutex );
+#endif
        if ( ber_sockbuf_ctrl( ld->ld_sb, LBER_SB_OPT_GET_FD, NULL ) == -1 ) {
                /* not connected yet */
-               int rc = ldap_open_defconn( ld );
-
-               if( rc < 0 ) {
-                       ber_free( ber, 1 );
-                       return( -1 );
-               }
+               rc = ldap_open_defconn( ld );
 
+       }
+#ifdef LDAP_R_COMPILE
+       ldap_pvt_thread_mutex_unlock( &ld->ld_req_mutex );
+#endif
+       if( rc < 0 ) {
+               ber_free( ber, 1 );
+               return( -1 );
+       } else if ( rc == 0 ) {
                Debug( LDAP_DEBUG_TRACE,
                        "ldap_open_defconn: successful\n",
                        0, 0, 0 );
@@ -174,7 +180,7 @@ ldap_send_server_request(
        BerElement *ber,
        ber_int_t msgid,
        LDAPRequest *parentreq,
-       LDAPURLDesc *srvlist,
+       LDAPURLDesc **srvlist,
        LDAPConn *lc,
        LDAPreqinfo *bind )
 {
@@ -190,7 +196,7 @@ ldap_send_server_request(
                if ( srvlist == NULL ) {
                        lc = ld->ld_defconn;
                } else {
-                       lc = find_connection( ld, srvlist, 1 );
+                       lc = find_connection( ld, *srvlist, 1 );
                        if ( lc == NULL ) {
                                if ( (bind != NULL) && (parentreq != NULL) ) {
                                        /* Remember the bind in the parent */
@@ -300,11 +306,10 @@ ldap_send_server_request(
 }
 
 LDAPConn *
-ldap_new_connection( LDAP *ld, LDAPURLDesc *srvlist, int use_ldsb,
+ldap_new_connection( LDAP *ld, LDAPURLDesc **srvlist, int use_ldsb,
        int connect, LDAPreqinfo *bind )
 {
        LDAPConn        *lc;
-       LDAPURLDesc     *srv;
 
        Debug( LDAP_DEBUG_TRACE, "ldap_new_connection %d %d %d\n",
                use_ldsb, connect, (bind != NULL) );
@@ -332,9 +337,17 @@ ldap_new_connection( LDAP *ld, LDAPURLDesc *srvlist, int use_ldsb,
        }
 
        if ( connect ) {
-               for ( srv = srvlist; srv != NULL; srv = srv->lud_next ) {
-                       if ( ldap_int_open_connection( ld, lc, srv, 0 ) != -1 )
+               LDAPURLDesc     **srvp, *srv = NULL;
+
+               for ( srvp = srvlist; *srvp != NULL; srvp = &(*srvp)->lud_next ) {
+                       if ( ldap_int_open_connection( ld, lc, *srvp, 0 ) != -1 )
                        {
+                               srv = *srvp;
+
+                               if ( ld->ld_urllist_proc ) {
+                                       ld->ld_urllist_proc( ld, srvlist, srvp, ld->ld_urllist_params );
+                               }
+
                                break;
                        }
                }
@@ -361,11 +374,7 @@ ldap_new_connection( LDAP *ld, LDAPURLDesc *srvlist, int use_ldsb,
        ldap_pvt_thread_mutex_unlock( &ld->ld_conn_mutex );
 #endif
 
-       /*
-        * XXX for now, we always do a synchronous bind.  This will have
-        * to change in the long run...
-        */
-       if ( bind != NULL) {
+       if ( bind != NULL ) {
                int             err = 0;
                LDAPConn        *savedefconn;
 
@@ -378,7 +387,7 @@ ldap_new_connection( LDAP *ld, LDAPURLDesc *srvlist, int use_ldsb,
                if ( ld->ld_rebind_proc != NULL) {
                        LDAPURLDesc     *srvfunc;
 
-                       srvfunc = ldap_url_dup( srvlist );
+                       srvfunc = ldap_url_dup( *srvlist );
                        if ( srvfunc == NULL ) {
                                ld->ld_errno = LDAP_NO_MEMORY;
                                err = -1;
@@ -741,14 +750,17 @@ ldap_free_request_int( LDAP *ld, LDAPRequest *lr )
 
        if ( lr->lr_ber != NULL ) {
                ber_free( lr->lr_ber, 1 );
+               lr->lr_ber = NULL;
        }
 
        if ( lr->lr_res_error != NULL ) {
                LDAP_FREE( lr->lr_res_error );
+               lr->lr_res_error = NULL;
        }
 
        if ( lr->lr_res_matched != NULL ) {
                LDAP_FREE( lr->lr_res_matched );
+               lr->lr_res_matched = NULL;
        }
 
        LDAP_FREE( lr );
@@ -882,8 +894,11 @@ ldap_chase_v3referrals( LDAP *ld, LDAPRequest *lr, char **refs, int sref, char *
        {
 
                /* Parse the referral URL */
-               if (( rc = ldap_url_parse_ext( refarray[i], &srv)) != LDAP_SUCCESS) {
-                       ld->ld_errno = rc;
+               rc = ldap_url_parse_ext( refarray[i], &srv, LDAP_PVT_URL_PARSE_NOEMPTY_DN );
+               if ( rc != LDAP_URL_SUCCESS ) {
+                       /* ldap_url_parse_ext() returns LDAP_URL_* errors
+                        * which do not map on API errors */
+                       ld->ld_errno = LDAP_PARAM_ERROR;
                        rc = -1;
                        goto done;
                }
@@ -895,12 +910,6 @@ ldap_chase_v3referrals( LDAP *ld, LDAPRequest *lr, char **refs, int sref, char *
                        goto done;
                }
 
-               /* treat ldap://hostpart and ldap://hostpart/ the same */
-               if ( srv->lud_dn && srv->lud_dn[0] == '\0' ) {
-                       LDAP_FREE( srv->lud_dn );
-                       srv->lud_dn = NULL;
-               }
-
                /* check connection for re-bind in progress */
                if (( lc = find_connection( ld, srv, 1 )) != NULL ) {
                        /* See if we've already requested this DN with this conn */
@@ -1014,7 +1023,7 @@ ldap_chase_v3referrals( LDAP *ld, LDAPRequest *lr, char **refs, int sref, char *
                ldap_pvt_thread_mutex_lock( &ld->ld_req_mutex );
 #endif
                rc = ldap_send_server_request( ld, ber, id,
-                       origreq, srv, NULL, &rinfo );
+                       origreq, &srv, NULL, &rinfo );
 #ifdef LDAP_R_COMPILE
                ldap_pvt_thread_mutex_unlock( &ld->ld_req_mutex );
 #endif
@@ -1146,21 +1155,16 @@ ldap_chase_referrals( LDAP *ld,
                        *p++ = '\0';
                }
 
-               rc = ldap_url_parse_ext( ref, &srv );
-
+               rc = ldap_url_parse_ext( ref, &srv, LDAP_PVT_URL_PARSE_NOEMPTY_DN );
                if ( rc != LDAP_URL_SUCCESS ) {
                        Debug( LDAP_DEBUG_TRACE,
-                           "ignoring unknown referral <%s>\n", ref, 0, 0 );
+                               "ignoring %s referral <%s>\n",
+                               ref, rc == LDAP_URL_ERR_BADSCHEME ? "unknown" : "incorrect", 0 );
                        rc = ldap_append_referral( ld, &unfollowed, ref );
                        *hadrefp = 1;
                        continue;
                }
 
-               if ( srv->lud_dn != NULL && srv->lud_dn == '\0' ) {
-                       LDAP_FREE( srv->lud_dn );
-                       srv->lud_dn = NULL;
-               }
-
                Debug( LDAP_DEBUG_TRACE,
                    "chasing LDAP referral: <%s>\n", ref, 0, 0 );
 
@@ -1206,7 +1210,7 @@ ldap_chase_referrals( LDAP *ld,
                ldap_pvt_thread_mutex_lock( &ld->ld_req_mutex );
 #endif
                rc = ldap_send_server_request( ld, ber, id,
-                       lr, srv, NULL, &rinfo );
+                       lr, &srv, NULL, &rinfo );
 #ifdef LDAP_R_COMPILE
                ldap_pvt_thread_mutex_unlock( &ld->ld_req_mutex );
 #endif
@@ -1282,8 +1286,7 @@ re_encode_request( LDAP *ld,
        ber_int_t       scope;
        int             rc;
        BerElement      tmpber, *ber;
-       struct berval           orig_dn;
-       char            *dn;
+       struct berval           dn;
 
        Debug( LDAP_DEBUG_TRACE,
            "re_encode_request: new msgid %ld, new dn <%s>\n",
@@ -1308,15 +1311,15 @@ re_encode_request( LDAP *ld,
        assert( tag != 0);
        if ( tag == LDAP_REQ_BIND ) {
                /* bind requests have a version number before the DN & other stuff */
-               rtag = ber_scanf( &tmpber, "{im" /*}*/, &ver, &orig_dn );
+               rtag = ber_scanf( &tmpber, "{im" /*}*/, &ver, &dn );
 
        } else if ( tag == LDAP_REQ_DELETE ) {
                /* delete requests don't have a DN wrapping sequence */
-               rtag = ber_scanf( &tmpber, "m", &orig_dn );
+               rtag = ber_scanf( &tmpber, "m", &dn );
 
        } else if ( tag == LDAP_REQ_SEARCH ) {
                /* search requests need to be re-scope-ed */
-               rtag = ber_scanf( &tmpber, "{me" /*"}"*/, &orig_dn, &scope );
+               rtag = ber_scanf( &tmpber, "{me" /*"}"*/, &dn, &scope );
 
                if( srv->lud_scope != LDAP_SCOPE_DEFAULT ) {
                        /* use the scope provided in reference */
@@ -1343,7 +1346,7 @@ re_encode_request( LDAP *ld,
                }
 
        } else {
-               rtag = ber_scanf( &tmpber, "{m" /*}*/, &orig_dn );
+               rtag = ber_scanf( &tmpber, "{m" /*}*/, &dn );
        }
 
        if( rtag == LBER_ERROR ) {
@@ -1351,24 +1354,25 @@ re_encode_request( LDAP *ld,
                return NULL;
        }
 
+       /* restore character zero'd out by ber_scanf*/
+       dn.bv_val[dn.bv_len] = tmpber.ber_tag;
+
        if (( ber = ldap_alloc_ber_with_options( ld )) == NULL ) {
                return NULL;
        }
 
-       if ( srv->lud_dn == NULL ) {
-               dn = orig_dn.bv_val;
-       } else {
-               dn = srv->lud_dn;
+       if ( srv->lud_dn ) {
+               ber_str2bv( srv->lud_dn, 0, 0, &dn );
        }
 
        if ( tag == LDAP_REQ_BIND ) {
-               rc = ber_printf( ber, "{it{is" /*}}*/, msgid, tag, ver, dn );
+               rc = ber_printf( ber, "{it{iO" /*}}*/, msgid, tag, ver, &dn );
        } else if ( tag == LDAP_REQ_DELETE ) {
-               rc = ber_printf( ber, "{itsN}", msgid, tag, dn );
+               rc = ber_printf( ber, "{itON}", msgid, tag, &dn );
        } else if ( tag == LDAP_REQ_SEARCH ) {
-               rc = ber_printf( ber, "{it{se" /*}}*/, msgid, tag, dn, scope );
+               rc = ber_printf( ber, "{it{Oe" /*}}*/, msgid, tag, &dn, scope );
        } else {
-               rc = ber_printf( ber, "{it{s" /*}}*/, msgid, tag, dn );
+               rc = ber_printf( ber, "{it{O" /*}}*/, msgid, tag, &dn );
        }
 
        if ( rc == -1 ) {
index 83b2e7eed17d49f73dbb478dbc2ce26183f662dc..04e5fdb96aab709a397ab53193a4fdc5a70adfd3 100644 (file)
@@ -458,28 +458,30 @@ retry:
 nextresp3:
 #endif
        tag = ber_get_next( lc->lconn_sb, &len, ber );
-       if ( tag == LDAP_TAG_MESSAGE ) {
+       switch ( tag ) {
+       case LDAP_TAG_MESSAGE:
                /*
                 * We read a complete message.
                 * The connection should no longer need this ber.
                 */
                lc->lconn_ber = NULL;
-       }
-       if ( tag != LDAP_TAG_MESSAGE ) {
-               if ( tag == LBER_DEFAULT) {
+               break;
+
+       case LBER_DEFAULT:
 #ifdef LDAP_DEBUG                 
-                       Debug( LDAP_DEBUG_CONNS,
-                               "ber_get_next failed.\n", 0, 0, 0 );
+               Debug( LDAP_DEBUG_CONNS,
+                       "ber_get_next failed.\n", 0, 0, 0 );
 #endif            
 #ifdef EWOULDBLOCK                     
-                       if (errno==EWOULDBLOCK) return LDAP_MSG_X_KEEP_LOOKING;
+               if ( errno == EWOULDBLOCK ) return LDAP_MSG_X_KEEP_LOOKING;
 #endif
 #ifdef EAGAIN
-                       if (errno == EAGAIN) return LDAP_MSG_X_KEEP_LOOKING;
+               if ( errno == EAGAIN ) return LDAP_MSG_X_KEEP_LOOKING;
 #endif
-                       ld->ld_errno = LDAP_SERVER_DOWN;
-                       return -1;
-               }
+               ld->ld_errno = LDAP_SERVER_DOWN;
+               return -1;
+
+       default:
                ld->ld_errno = LDAP_LOCAL_ERROR;
                return -1;
        }
@@ -793,7 +795,8 @@ lr->lr_res_matched ? lr->lr_res_matched : "" );
                                        ber_free( ber, 1 );
                                        ber = NULL;
                                        if ( build_result_ber( ld, &ber, lr )
-                                           == LBER_ERROR ) {
+                                           == LBER_ERROR )
+                                       {
                                                rc = -1; /* fatal error */
                                        }
                                }
index 9d8e5f8ba2a8a93bde3658101ebdc3ef9caea47c..b556fc955ec63be44df094e918084b2876280b9b 100644 (file)
@@ -158,7 +158,8 @@ ldap_sort_entries(
                LDAP_VFREE( et[i].et_vals );
        }
        *ep = ohead;
-               
+       (*chain)->lm_chain_tail = otail ? otail : etail;
+
        LDAP_FREE( (char *) et );
 
        return( 0 );
index 450db9d2d0922b4c76ddeac33f6f9a8814b6244a..9dfbd73ef478a126db7e71cc49dcfaf83dec1578 100644 (file)
@@ -822,7 +822,8 @@ ldap_int_tls_connect( LDAP *ld, LDAPConn *conn )
 #endif
                }
 
-               Debug( LDAP_DEBUG_ANY,"TLS: can't connect.\n",0,0,0);
+               Debug( LDAP_DEBUG_ANY,"TLS: can't connect: %s.\n",
+                       ld->ld_error ? ld->ld_error : "" ,0,0);
 
                ber_sockbuf_remove_io( sb, &sb_tls_sbio,
                        LBER_SBIOD_LEVEL_TRANSPORT );
index 4c27ed33f23c3dcdd40f701a2fa5d9db3c709c52..e35be8f9f0e4fd42097bbfc061d111028cc916fc 100644 (file)
@@ -759,7 +759,7 @@ ldap_url_desc2str( LDAPURLDesc *u )
 }
 
 int
-ldap_url_parse_ext( LDAP_CONST char *url_in, LDAPURLDesc **ludpp )
+ldap_url_parse_ext( LDAP_CONST char *url_in, LDAPURLDesc **ludpp, unsigned flags )
 {
 /*
  *  Pick apart the pieces of an LDAP URL.
@@ -772,6 +772,8 @@ ldap_url_parse_ext( LDAP_CONST char *url_in, LDAPURLDesc **ludpp )
        const char *url_tmp;
        char *url;
 
+       int     check_dn = 1;
+
        if( url_in == NULL || ludpp == NULL ) {
                return LDAP_URL_ERR_PARAM;
        }
@@ -825,7 +827,7 @@ ldap_url_parse_ext( LDAP_CONST char *url_in, LDAPURLDesc **ludpp )
        ludp->lud_port = 0;
        ludp->lud_dn = NULL;
        ludp->lud_attrs = NULL;
-       ludp->lud_scope = LDAP_SCOPE_DEFAULT;
+       ludp->lud_scope = ( flags & LDAP_PVT_URL_PARSE_NODEF_SCOPE ) ? LDAP_SCOPE_BASE : LDAP_SCOPE_DEFAULT;
        ludp->lud_filter = NULL;
        ludp->lud_exts = NULL;
 
@@ -879,6 +881,18 @@ ldap_url_parse_ext( LDAP_CONST char *url_in, LDAPURLDesc **ludpp )
                }
        }
 
+       if ( ( flags & LDAP_PVT_URL_PARSE_DEF_PORT ) && ludp->lud_port == 0 ) {
+               if ( strcmp( ludp->lud_scheme, "ldap" ) == 0 ) {
+                       ludp->lud_port = LDAP_PORT;
+#ifdef LDAP_CONNECTIONLESS
+               } else if ( strcmp( ludp->lud_scheme, "cldap" ) == 0 ) {
+                       ludp->lud_port = LDAP_PORT;
+#endif
+               } else if ( strcmp( ludp->lud_scheme, "ldaps" ) == 0 ) {
+                       ludp->lud_port = LDAPS_PORT;
+               }
+       }
+
        ldap_pvt_hex_unescape( url );
 
        /* If [ip address]:port syntax, url is [ip and we skip the [ */
@@ -890,6 +904,14 @@ ldap_url_parse_ext( LDAP_CONST char *url_in, LDAPURLDesc **ludpp )
                return LDAP_URL_ERR_MEM;
        }
 
+       if ( ( flags & LDAP_PVT_URL_PARSE_NOEMPTY_HOST )
+               && ludp->lud_host != NULL
+               && *ludp->lud_host == '\0' )
+       {
+               LDAP_FREE( ludp->lud_host );
+               ludp->lud_host = NULL;
+       }
+
        /*
         * Kludge.  ldap://111.222.333.444:389??cn=abc,o=company
         *
@@ -908,11 +930,15 @@ ldap_url_parse_ext( LDAP_CONST char *url_in, LDAPURLDesc **ludpp )
                                /* parse dn part */
                                ldap_pvt_hex_unescape( q );
                                ludp->lud_dn = LDAP_STRDUP( q );
-                       } else {
+
+                       } else if ( !( flags & LDAP_PVT_URL_PARSE_NOEMPTY_DN ) ) {
                                ludp->lud_dn = LDAP_STRDUP( "" );
+
+                       } else {
+                               check_dn = 0;
                        }
 
-                       if( ludp->lud_dn == NULL ) {
+                       if ( check_dn && ludp->lud_dn == NULL ) {
                                LDAP_FREE( url );
                                ldap_free_urldesc( ludp );
                                return LDAP_URL_ERR_MEM;
@@ -938,11 +964,15 @@ ldap_url_parse_ext( LDAP_CONST char *url_in, LDAPURLDesc **ludpp )
                /* parse dn part */
                ldap_pvt_hex_unescape( p );
                ludp->lud_dn = LDAP_STRDUP( p );
-       } else {
+
+       } else if ( !( flags & LDAP_PVT_URL_PARSE_NOEMPTY_DN ) ) {
                ludp->lud_dn = LDAP_STRDUP( "" );
+
+       } else {
+               check_dn = 0;
        }
 
-       if( ludp->lud_dn == NULL ) {
+       if( check_dn && ludp->lud_dn == NULL ) {
                LDAP_FREE( url );
                ldap_free_urldesc( ludp );
                return LDAP_URL_ERR_MEM;
@@ -1092,34 +1122,7 @@ ldap_url_parse_ext( LDAP_CONST char *url_in, LDAPURLDesc **ludpp )
 int
 ldap_url_parse( LDAP_CONST char *url_in, LDAPURLDesc **ludpp )
 {
-       int rc = ldap_url_parse_ext( url_in, ludpp );
-
-       if( rc != LDAP_URL_SUCCESS ) {
-               return rc;
-       }
-
-       if ((*ludpp)->lud_scope == LDAP_SCOPE_DEFAULT) {
-               (*ludpp)->lud_scope = LDAP_SCOPE_BASE;
-       }
-
-       if ((*ludpp)->lud_host != NULL && *(*ludpp)->lud_host == '\0') {
-               LDAP_FREE( (*ludpp)->lud_host );
-               (*ludpp)->lud_host = NULL;
-       }
-
-       if ((*ludpp)->lud_port == 0) {
-               if( strcmp((*ludpp)->lud_scheme, "ldap") == 0 ) {
-                       (*ludpp)->lud_port = LDAP_PORT;
-#ifdef LDAP_CONNECTIONLESS
-               } else if( strcmp((*ludpp)->lud_scheme, "cldap") == 0 ) {
-                       (*ludpp)->lud_port = LDAP_PORT;
-#endif
-               } else if( strcmp((*ludpp)->lud_scheme, "ldaps") == 0 ) {
-                       (*ludpp)->lud_port = LDAPS_PORT;
-               }
-       }
-
-       return rc;
+       return ldap_url_parse_ext( url_in, ludpp, LDAP_PVT_URL_PARSE_HISTORIC );
 }
 
 LDAPURLDesc *
@@ -1218,8 +1221,8 @@ ldap_url_duplist (LDAPURLDesc *ludlist)
 }
 
 static int
-ldap_url_parselist_int (LDAPURLDesc **ludlist, const char *url, const char *sep,
-       int (*url_parse)( const char *, LDAPURLDesc ** ) )
+ldap_url_parselist_int (LDAPURLDesc **ludlist, const char *url, const char *sep, unsigned flags )
+       
 {
        int i, rc;
        LDAPURLDesc *ludp;
@@ -1230,7 +1233,11 @@ ldap_url_parselist_int (LDAPURLDesc **ludlist, const char *url, const char *sep,
 
        *ludlist = NULL;
 
-       urls = ldap_str2charray(url, sep);
+       if ( sep == NULL ) {
+               sep = ", ";
+       }
+
+       urls = ldap_str2charray( url, sep );
        if (urls == NULL)
                return LDAP_URL_ERR_MEM;
 
@@ -1238,30 +1245,30 @@ ldap_url_parselist_int (LDAPURLDesc **ludlist, const char *url, const char *sep,
        for (i = 0; urls[i] != NULL; i++) ;
        /* ...and put them in the "stack" backward */
        while (--i >= 0) {
-               rc = url_parse( urls[i], &ludp );
+               rc = ldap_url_parse_ext( urls[i], &ludp, flags );
                if ( rc != 0 ) {
-                       ldap_charray_free(urls);
-                       ldap_free_urllist(*ludlist);
+                       ldap_charray_free( urls );
+                       ldap_free_urllist( *ludlist );
                        *ludlist = NULL;
                        return rc;
                }
                ludp->lud_next = *ludlist;
                *ludlist = ludp;
        }
-       ldap_charray_free(urls);
+       ldap_charray_free( urls );
        return LDAP_URL_SUCCESS;
 }
 
 int
 ldap_url_parselist (LDAPURLDesc **ludlist, const char *url )
 {
-       return ldap_url_parselist_int( ludlist, url, ", ", ldap_url_parse );
+       return ldap_url_parselist_int( ludlist, url, ", ", LDAP_PVT_URL_PARSE_HISTORIC );
 }
 
 int
-ldap_url_parselist_ext (LDAPURLDesc **ludlist, const char *url, const char *sep )
+ldap_url_parselist_ext (LDAPURLDesc **ludlist, const char *url, const char *sep, unsigned flags )
 {
-       return ldap_url_parselist_int( ludlist, url, sep, ldap_url_parse_ext );
+       return ldap_url_parselist_int( ludlist, url, sep, flags );
 }
 
 int
index 7ad2ceca35aeef689350b563d3855e95da12b81e..2629234e0f6986e3a0b8ddfeb25df054fb195a76 100644 (file)
@@ -29,10 +29,10 @@ XXSRCS    = apitest.c test.c \
        init.c options.c print.c string.c util-int.c schema.c \
        charray.c tls.c os-local.c dnssrv.c utf-8.c utf-8-conv.c \
        turn.c ppolicy.c dds.c txn.c
-SRCS   = threads.c rdwr.c tpool.c rq.c \
+SRCS   = threads.c rdwr.c rmutex.c tpool.c rq.c \
        thr_posix.c thr_cthreads.c thr_thr.c thr_lwp.c thr_nt.c \
        thr_pth.c thr_stub.c thr_debug.c
-OBJS   = threads.lo rdwr.lo tpool.lo  rq.lo \
+OBJS   = threads.lo rdwr.lo rmutex.lo tpool.lo  rq.lo \
        thr_posix.lo thr_cthreads.lo thr_thr.lo thr_lwp.lo thr_nt.lo \
        thr_pth.lo thr_stub.lo thr_debug.lo \
        bind.lo open.lo result.lo error.lo compare.lo search.lo \
diff --git a/libraries/libldap_r/rmutex.c b/libraries/libldap_r/rmutex.c
new file mode 100644 (file)
index 0000000..98529e4
--- /dev/null
@@ -0,0 +1,219 @@
+/* $OpenLDAP$ */
+/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
+ *
+ * Copyright 2006 The OpenLDAP Foundation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted only as authorized by the OpenLDAP
+ * Public License.
+ *
+ * A copy of this license is available in file LICENSE in the
+ * top-level directory of the distribution or, alternatively, at
+ * <http://www.OpenLDAP.org/license.html>.
+ */
+/* This work was initially developed by Howard Chu for inclusion
+ * in OpenLDAP Software.
+ */
+
+/*
+ * This is an implementation of recursive mutexes.
+ */
+
+#include "portable.h"
+
+#include <ac/stdlib.h>
+
+#include <ac/errno.h>
+#include <ac/string.h>
+#include <ac/time.h>
+
+#include "ldap-int.h"
+#include "ldap_pvt_thread.h" /* Get the thread interface */
+
+struct ldap_int_thread_rmutex_s {
+       ldap_pvt_thread_mutex_t ltrm_mutex;
+       ldap_pvt_thread_cond_t ltrm_cond;
+       ldap_pvt_thread_t ltrm_owner;
+       int ltrm_valid;
+#define LDAP_PVT_THREAD_RMUTEX_VALID   0x0cdb
+       int ltrm_depth;
+       int ltrm_waits;
+};
+
+static const ldap_pvt_thread_t tid_zero;
+
+int 
+ldap_pvt_thread_rmutex_init( ldap_pvt_thread_rmutex_t *rmutex )
+{
+       struct ldap_int_thread_rmutex_s *rm;
+
+       assert( rmutex != NULL );
+
+       rm = (struct ldap_int_thread_rmutex_s *) LDAP_CALLOC( 1,
+               sizeof( struct ldap_int_thread_rmutex_s ) );
+       if ( !rm )
+               return LDAP_NO_MEMORY;
+
+       /* we should check return results */
+       ldap_pvt_thread_mutex_init( &rm->ltrm_mutex );
+       ldap_pvt_thread_cond_init( &rm->ltrm_cond );
+
+       rm->ltrm_valid = LDAP_PVT_THREAD_RMUTEX_VALID;
+
+       *rmutex = rm;
+       return 0;
+}
+
+int 
+ldap_pvt_thread_rmutex_destroy( ldap_pvt_thread_rmutex_t *rmutex )
+{
+       struct ldap_int_thread_rmutex_s *rm;
+
+       assert( rmutex != NULL );
+       rm = *rmutex;
+
+       assert( rm != NULL );
+       assert( rm->ltrm_valid == LDAP_PVT_THREAD_RMUTEX_VALID );
+
+       if( rm->ltrm_valid != LDAP_PVT_THREAD_RMUTEX_VALID )
+               return LDAP_PVT_THREAD_EINVAL;
+
+       ldap_pvt_thread_mutex_lock( &rm->ltrm_mutex );
+
+       assert( rm->ltrm_depth >= 0 );
+       assert( rm->ltrm_waits >= 0 );
+
+       /* in use? */
+       if( rm->ltrm_depth > 0 || rm->ltrm_waits > 0 ) {
+               ldap_pvt_thread_mutex_unlock( &rm->ltrm_mutex );
+               return LDAP_PVT_THREAD_EBUSY;
+       }
+
+       rm->ltrm_valid = 0;
+
+       ldap_pvt_thread_mutex_unlock( &rm->ltrm_mutex );
+
+       ldap_pvt_thread_mutex_destroy( &rm->ltrm_mutex );
+       ldap_pvt_thread_cond_destroy( &rm->ltrm_cond );
+
+       LDAP_FREE(rm);
+       *rmutex = NULL;
+       return 0;
+}
+
+int ldap_pvt_thread_rmutex_lock( ldap_pvt_thread_rmutex_t *rmutex,
+       ldap_pvt_thread_t owner )
+{
+       struct ldap_int_thread_rmutex_s *rm;
+
+       assert( rmutex != NULL );
+       rm = *rmutex;
+
+       assert( rm != NULL );
+       assert( rm->ltrm_valid == LDAP_PVT_THREAD_RMUTEX_VALID );
+
+       if( rm->ltrm_valid != LDAP_PVT_THREAD_RMUTEX_VALID )
+               return LDAP_PVT_THREAD_EINVAL;
+
+       ldap_pvt_thread_mutex_lock( &rm->ltrm_mutex );
+
+       assert( rm->ltrm_depth >= 0 );
+       assert( rm->ltrm_waits >= 0 );
+
+       if( rm->ltrm_depth > 0 ) {
+               /* already locked */
+               if ( !ldap_pvt_thread_equal( rm->ltrm_owner, owner )) {
+                       rm->ltrm_waits++;
+                       do {
+                               ldap_pvt_thread_cond_wait( &rm->ltrm_cond,
+                                       &rm->ltrm_mutex );
+                       } while( rm->ltrm_depth > 0 );
+
+                       rm->ltrm_waits--;
+                       assert( rm->ltrm_waits >= 0 );
+                       rm->ltrm_owner = owner;
+               }
+       } else {
+               rm->ltrm_owner = owner;
+       }
+
+       rm->ltrm_depth++;
+
+       ldap_pvt_thread_mutex_unlock( &rm->ltrm_mutex );
+
+       return 0;
+}
+
+int ldap_pvt_thread_rmutex_trylock( ldap_pvt_thread_rmutex_t *rmutex,
+       ldap_pvt_thread_t owner )
+{
+       struct ldap_int_thread_rmutex_s *rm;
+
+       assert( rmutex != NULL );
+       rm = *rmutex;
+
+       assert( rm != NULL );
+       assert( rm->ltrm_valid == LDAP_PVT_THREAD_RMUTEX_VALID );
+
+       if( rm->ltrm_valid != LDAP_PVT_THREAD_RMUTEX_VALID )
+               return LDAP_PVT_THREAD_EINVAL;
+
+       ldap_pvt_thread_mutex_lock( &rm->ltrm_mutex );
+
+       assert( rm->ltrm_depth >= 0 );
+       assert( rm->ltrm_waits >= 0 );
+
+       if( rm->ltrm_depth > 0 ) {
+               if ( !ldap_pvt_thread_equal( owner, rm->ltrm_owner )) {
+                       ldap_pvt_thread_mutex_unlock( &rm->ltrm_mutex );
+                       return LDAP_PVT_THREAD_EBUSY;
+               }
+       } else {
+               rm->ltrm_owner = owner;
+       }
+
+       rm->ltrm_depth++;
+
+       ldap_pvt_thread_mutex_unlock( &rm->ltrm_mutex );
+
+       return 0;
+}
+
+int ldap_pvt_thread_rmutex_unlock( ldap_pvt_thread_rmutex_t *rmutex,
+       ldap_pvt_thread_t owner )
+{
+       struct ldap_int_thread_rmutex_s *rm;
+
+       assert( rmutex != NULL );
+       rm = *rmutex;
+
+       assert( rm != NULL );
+       assert( rm->ltrm_valid == LDAP_PVT_THREAD_RMUTEX_VALID );
+
+       if( rm->ltrm_valid != LDAP_PVT_THREAD_RMUTEX_VALID )
+               return LDAP_PVT_THREAD_EINVAL;
+
+       ldap_pvt_thread_mutex_lock( &rm->ltrm_mutex );
+
+       if( !ldap_pvt_thread_equal( owner, rm->ltrm_owner )) {
+               ldap_pvt_thread_mutex_unlock( &rm->ltrm_mutex );
+               return LDAP_PVT_THREAD_EINVAL;
+       }
+
+       rm->ltrm_depth--;
+       if ( !rm->ltrm_depth )
+               rm->ltrm_owner = tid_zero;
+
+       assert( rm->ltrm_depth >= 0 );
+       assert( rm->ltrm_waits >= 0 );
+
+       if ( !rm->ltrm_depth && rm->ltrm_waits ) {
+               ldap_pvt_thread_cond_signal( &rm->ltrm_cond );
+       }
+
+       ldap_pvt_thread_mutex_unlock( &rm->ltrm_mutex );
+
+       return 0;
+}
+
index 2ee0db61007b0d632bc302967a7b1f4b519ec5e7..e692c628ed1f2e52cd04b120f0dc556157a831c6 100644 (file)
@@ -99,20 +99,16 @@ ldap_pvt_runqueue_remove(
 struct re_s*
 ldap_pvt_runqueue_next_sched(
        struct runqueue_s* rq,
-       struct timeval** next_run
+       struct timeval* next_run
 )
 {
        struct re_s* entry;
 
        entry = LDAP_STAILQ_FIRST( &rq->task_list );
-       if ( entry == NULL ) {
-               *next_run = NULL;
-               return NULL;
-       } else if ( entry->next_sched.tv_sec == 0 ) {
-               *next_run = NULL;
+       if ( entry == NULL || entry->next_sched.tv_sec == 0 ) {
                return NULL;
        } else {
-               *next_run = &entry->next_sched;
+               *next_run = entry->next_sched;
                return entry;
        }
 }
index 142f9db23315dcb55d42e6883bcab058e2343bd0..3b99e838fc9fc40a962a598f87f9ed1c5da57e56 100644 (file)
@@ -141,6 +141,7 @@ static int threadID;
 enum { threadID = 0 };
 #endif
 static int nodebug, noabort, noerror, nosync, tracethreads;
+static int wrap_threads;
 static int options_done;
 
 
@@ -322,6 +323,7 @@ get_options( void )
        }
        unwrap_offset = -(wrap_offset = (wraptype == Wrap_adjptr));
 #endif
+       wrap_threads = (tracethreads || threadID || count);
        options_done = 1;
 }
 
@@ -620,6 +622,7 @@ adjust_count( int which, int adjust )
                resource_counts[which] += adjust;
                rc = ldap_int_thread_mutex_unlock( &resource_mutexes[which] );
                assert( rc == 0 );
+               break;
        case Count_reported:
                fputs( "== thr_debug: More thread activity after exit ==\n", stderr );
                count = Count_reported_more;
@@ -707,6 +710,51 @@ ldap_pvt_thread_sleep( unsigned int interval )
        return 0;
 }
 
+static void
+thread_exiting( const char *how, const char *msg )
+{
+       ldap_pvt_thread_t thread;
+       ERROR_IF( !threading_enabled, msg );
+       thread = ldap_pvt_thread_self();
+       if( tracethreads ) {
+               char buf[40];
+               fprintf( stderr, "== thr_debug: %s thread %s ==\n",
+                       how, thread_name( buf, sizeof(buf), thread ) );
+       }
+       if( threadID ) {
+               with_thread_info_lock({
+                       ldap_debug_thread_t *t = get_thread_info(
+                               &thread, msg );
+                       if( thread_info_detached( t ) )
+                               remove_thread_info( t, msg );
+               });
+       }
+       adjust_count( Idx_unexited_thread, -1 );
+}
+
+void
+ldap_pvt_thread_exit( void *retval )
+{
+       thread_exiting( "Exiting", "ldap_pvt_thread_exit" );
+       ldap_int_thread_exit( retval );
+}
+
+typedef struct {
+       void *(*start_routine)( void * );
+       void *arg;
+} ldap_debug_thread_call_t;
+
+static void *
+ldap_debug_thread_wrapper( void *arg )
+{
+       void *ret;
+       ldap_debug_thread_call_t call = *(ldap_debug_thread_call_t *)arg;
+       free( arg );
+       ret = call.start_routine( call.arg );
+       thread_exiting( "Returning from", "ldap_debug_thread_wrapper" );
+       return ret;
+}
+
 int
 ldap_pvt_thread_create(
        ldap_pvt_thread_t *thread,
@@ -718,6 +766,15 @@ ldap_pvt_thread_create(
        if( !options_done )
                get_options();
        ERROR_IF( !threading_enabled, "ldap_pvt_thread_create" );
+       if( wrap_threads ) {
+               ldap_debug_thread_call_t *call = malloc(
+                       sizeof( ldap_debug_thread_call_t ) );
+               assert( call != NULL );
+               call->start_routine = start_routine;
+               call->arg = arg;
+               start_routine = ldap_debug_thread_wrapper;
+               arg = call;
+       }
        if( threadID ) {
                with_thread_info_lock({
                        rc = ldap_int_thread_create( thread, detach, start_routine, arg );
@@ -745,29 +802,6 @@ ldap_pvt_thread_create(
        return rc;
 }
 
-void
-ldap_pvt_thread_exit( void *retval )
-{
-       ldap_pvt_thread_t thread;
-       ERROR_IF( !threading_enabled, "ldap_pvt_thread_exit" );
-       thread = ldap_pvt_thread_self();
-       if( tracethreads ) {
-               char buf[40];
-               fprintf( stderr, "== thr_debug: Exiting thread %s ==\n",
-                       thread_name( buf, sizeof(buf), thread ) );
-       }
-       if( threadID ) {
-               with_thread_info_lock({
-                       ldap_debug_thread_t *t = get_thread_info(
-                               &thread, "ldap_pvt_thread_exit" );
-                       if( thread_info_detached( t ) )
-                               remove_thread_info( t, "ldap_pvt_thread_exit" );
-               });
-       }
-       adjust_count( Idx_unexited_thread, -1 );
-       ldap_int_thread_exit( retval );
-}
-
 int
 ldap_pvt_thread_join( ldap_pvt_thread_t thread, void **thread_return )
 {
index 9caee1469bcfb8e502ae19e63bbdf544e0783fbc..b562a87d571e5f21695c8b13e08e2c96289eed0f 100644 (file)
@@ -38,6 +38,8 @@ int ldap_pvt_thread_initialize( void )
 {
        int rc;
        static int init = 0;
+       ldap_pvt_thread_rmutex_t rm;
+       ldap_pvt_thread_t tid;
 
        /* we only get one shot at this */
        if( init++ ) return -1;
@@ -50,6 +52,15 @@ int ldap_pvt_thread_initialize( void )
        if( rc ) return rc;
 #endif
 
+       /* kludge to pull symbol definitions in */
+       ldap_pvt_thread_rmutex_init( &rm );
+       tid = ldap_pvt_thread_self();
+       ldap_pvt_thread_rmutex_lock( &rm, tid );
+       ldap_pvt_thread_rmutex_trylock( &rm, tid );
+       ldap_pvt_thread_rmutex_unlock( &rm, tid );
+       ldap_pvt_thread_rmutex_unlock( &rm, tid );
+       ldap_pvt_thread_rmutex_destroy( &rm );
+
        return 0;
 }
 
index 31d27b7d3638ac32b2724b96f42b6d93bbca4cc4..4515d312ef6ff171e75b51df4b2d836792120150 100644 (file)
@@ -50,11 +50,16 @@ typedef struct ldap_int_thread_key_s {
 #define        MAXKEYS 32
 #define        LDAP_MAXTHR     1024    /* must be a power of 2 */
 
+typedef struct ldap_int_thread_userctx_s {
+       ldap_pvt_thread_t ltu_id;
+       ldap_int_thread_key_t ltu_key[MAXKEYS];
+} ldap_int_thread_userctx_t;
+
 static ldap_pvt_thread_t tid_zero;
 
 static struct {
        ldap_pvt_thread_t id;
-       ldap_int_thread_key_t *ctx;
+       ldap_int_thread_userctx_t *ctx;
 } thread_keys[LDAP_MAXTHR];
        
 
@@ -95,12 +100,13 @@ static void *ldap_int_thread_pool_wrapper( void *pool );
 
 static ldap_pvt_thread_t ldap_int_main_tid;
 
-static ldap_int_thread_key_t ldap_int_main_thrctx[LDAP_MAXTHR];
+static ldap_int_thread_userctx_t ldap_int_main_thrctx;
 
 int
 ldap_int_thread_pool_startup ( void )
 {
        ldap_int_main_tid = ldap_pvt_thread_self();
+       ldap_int_main_thrctx.ltu_id = ldap_int_main_tid;
 
        return ldap_pvt_thread_mutex_init(&ldap_pvt_thread_pool_mutex);
 }
@@ -111,7 +117,6 @@ ldap_int_thread_pool_shutdown ( void )
        struct ldap_int_thread_pool_s *pool;
 
        while ((pool = LDAP_STAILQ_FIRST(&ldap_int_thread_pool_list)) != NULL) {
-               LDAP_STAILQ_REMOVE_HEAD(&ldap_int_thread_pool_list, ltp_next);
                (ldap_pvt_thread_pool_destroy)(&pool, 0); /* ignore thr_debug macro */
        }
        ldap_pvt_thread_mutex_destroy(&ldap_pvt_thread_pool_mutex);
@@ -542,27 +547,26 @@ ldap_int_thread_pool_wrapper (
 {
        struct ldap_int_thread_pool_s *pool = xpool;
        ldap_int_thread_ctx_t *ctx;
-       ldap_int_thread_key_t ltc_key[MAXKEYS];
-       ldap_pvt_thread_t tid;
+       ldap_int_thread_userctx_t uctx;
        int i, keyslot, hash;
 
        if (pool == NULL)
                return NULL;
 
        for ( i=0; i<MAXKEYS; i++ ) {
-               ltc_key[i].ltk_key = NULL;
+               uctx.ltu_key[i].ltk_key = NULL;
        }
 
-       tid = ldap_pvt_thread_self();
+       uctx.ltu_id = ldap_pvt_thread_self();
 
        ldap_pvt_thread_mutex_lock(&pool->ltp_mutex);
 
        /* store pointer to our keys */
-       TID_HASH(tid, hash);
+       TID_HASH(uctx.ltu_id, hash);
        for (i = hash & (LDAP_MAXTHR-1);
-                               !ldap_pvt_thread_equal(thread_keys[i].id, tid);
+                               !ldap_pvt_thread_equal(thread_keys[i].id, uctx.ltu_id);
                                i = (i+1) & (LDAP_MAXTHR-1));
-       thread_keys[i].ctx = ltc_key;
+       thread_keys[i].ctx = &uctx;
        keyslot = i;
 
        while (pool->ltp_state != LDAP_INT_THREAD_POOL_STOPPING) {
@@ -610,7 +614,7 @@ ldap_int_thread_pool_wrapper (
                pool->ltp_active_count++;
                ldap_pvt_thread_mutex_unlock(&pool->ltp_mutex);
 
-               ctx->ltc_start_routine(ltc_key, ctx->ltc_arg);
+               ctx->ltc_start_routine(&uctx, ctx->ltc_arg);
 
 #ifdef LDAP_PVT_THREAD_POOL_SEM_LOAD_CONTROL
                ldap_lazy_sem_post( thread_pool_sem );
@@ -629,11 +633,11 @@ ldap_int_thread_pool_wrapper (
                }
        }
 
-       for ( i=0; i<MAXKEYS && ltc_key[i].ltk_key; i++ ) {
-               if (ltc_key[i].ltk_free)
-                       ltc_key[i].ltk_free(
-                               ltc_key[i].ltk_key,
-                               ltc_key[i].ltk_data );
+       for ( i=0; i<MAXKEYS && uctx.ltu_key[i].ltk_key; i++ ) {
+               if (uctx.ltu_key[i].ltk_free)
+                       uctx.ltu_key[i].ltk_free(
+                               uctx.ltu_key[i].ltk_key,
+                               uctx.ltu_key[i].ltk_data );
        }
 
        thread_keys[keyslot].ctx = NULL;
@@ -712,15 +716,15 @@ int ldap_pvt_thread_pool_getkey(
        void **data,
        ldap_pvt_thread_pool_keyfree_t **kfree )
 {
-       ldap_int_thread_key_t *ctx = xctx;
+       ldap_int_thread_userctx_t *ctx = xctx;
        int i;
 
        if ( !ctx || !data ) return EINVAL;
 
-       for ( i=0; i<MAXKEYS && ctx[i].ltk_key; i++ ) {
-               if ( ctx[i].ltk_key == key ) {
-                       *data = ctx[i].ltk_data;
-                       if ( kfree ) *kfree = ctx[i].ltk_free;
+       for ( i=0; i<MAXKEYS && ctx->ltu_key[i].ltk_key; i++ ) {
+               if ( ctx->ltu_key[i].ltk_key == key ) {
+                       *data = ctx->ltu_key[i].ltk_data;
+                       if ( kfree ) *kfree = ctx->ltu_key[i].ltk_free;
                        return 0;
                }
        }
@@ -733,16 +737,16 @@ int ldap_pvt_thread_pool_setkey(
        void *data,
        ldap_pvt_thread_pool_keyfree_t *kfree )
 {
-       ldap_int_thread_key_t *ctx = xctx;
+       ldap_int_thread_userctx_t *ctx = xctx;
        int i;
 
        if ( !ctx || !key ) return EINVAL;
 
        for ( i=0; i<MAXKEYS; i++ ) {
-               if ( !ctx[i].ltk_key || ctx[i].ltk_key == key ) {
-                       ctx[i].ltk_key = key;
-                       ctx[i].ltk_data = data;
-                       ctx[i].ltk_free = kfree;
+               if ( !ctx->ltu_key[i].ltk_key || ctx->ltu_key[i].ltk_key == key ) {
+                       ctx->ltu_key[i].ltk_key = key;
+                       ctx->ltu_key[i].ltk_data = data;
+                       ctx->ltu_key[i].ltk_free = kfree;
                        return 0;
                }
        }
@@ -755,17 +759,18 @@ int ldap_pvt_thread_pool_setkey(
 void ldap_pvt_thread_pool_purgekey( void *key )
 {
        int i, j;
-       ldap_int_thread_key_t *ctx;
+       ldap_int_thread_userctx_t *ctx;
 
        for ( i=0; i<LDAP_MAXTHR; i++ ) {
                if ( thread_keys[i].ctx ) {
                        ctx = thread_keys[i].ctx;
                        for ( j=0; j<MAXKEYS; j++ ) {
-                               if ( ctx[j].ltk_key == key ) {
-                                       if (ctx[j].ltk_free)
-                                               ctx[j].ltk_free( ctx[j].ltk_key, ctx[j].ltk_data );
-                                       ctx[j].ltk_key = NULL;
-                                       ctx[j].ltk_free = NULL;
+                               if ( ctx->ltu_key[j].ltk_key == key ) {
+                                       if (ctx->ltu_key[j].ltk_free)
+                                               ctx->ltu_key[j].ltk_free( ctx->ltu_key[j].ltk_key,
+                                               ctx->ltu_key[j].ltk_data );
+                                       ctx->ltu_key[j].ltk_key = NULL;
+                                       ctx->ltu_key[j].ltk_free = NULL;
                                        break;
                                }
                        }
@@ -787,7 +792,7 @@ void *ldap_pvt_thread_pool_context( )
 
        tid = ldap_pvt_thread_self();
        if ( ldap_pvt_thread_equal( tid, ldap_int_main_tid ))
-               return ldap_int_main_thrctx;
+               return &ldap_int_main_thrctx;
 
        TID_HASH( tid, hash );
        for (i = hash & (LDAP_MAXTHR-1);
@@ -800,13 +805,21 @@ void *ldap_pvt_thread_pool_context( )
 
 void ldap_pvt_thread_pool_context_reset( void *vctx )
 {
-       ldap_int_thread_key_t *ctx = vctx;
+       ldap_int_thread_userctx_t *ctx = vctx;
        int i;
 
-       for ( i=0; i<MAXKEYS && ctx[i].ltk_key; i++) {
-               if ( ctx[i].ltk_free )
-                       ctx[i].ltk_free( ctx[i].ltk_key, ctx[i].ltk_data );
-               ctx[i].ltk_key = NULL;
+       for ( i=0; i<MAXKEYS && ctx->ltu_key[i].ltk_key; i++) {
+               if ( ctx->ltu_key[i].ltk_free )
+                       ctx->ltu_key[i].ltk_free( ctx->ltu_key[i].ltk_key,
+                       ctx->ltu_key[i].ltk_data );
+               ctx->ltu_key[i].ltk_key = NULL;
        }
 }
+
+ldap_pvt_thread_t ldap_pvt_thread_pool_tid( void *vctx )
+{
+       ldap_int_thread_userctx_t *ctx = vctx;
+
+       return ctx->ltu_id;
+}
 #endif /* LDAP_THREAD_HAVE_TPOOL */
index cb92e59f247fe9bf229bd00db4ff153a543c0e54..c7ae35cd122a6e89de0421810baf8619a4782fbd 100644 (file)
@@ -247,14 +247,17 @@ int lutil_parsetime( char *atm, struct lutil_tm *tm )
                if (tm->tm_sec < 0 || tm->tm_sec > 61) break;
 
                /* Fractions of seconds */
-               for (i = 0, fracs = 0; isdigit((unsigned char) *ptr); ) {
-                       i*=10; i+= *ptr++ - '0';
-                       fracs++;
-               }
-               tm->tm_usec = i;
-               if (i) {
-                       for (i = fracs; i<6; i++)
-                               tm->tm_usec *= 10;
+               if ( *ptr == '.' ) {
+                       ptr++;
+                       for (i = 0, fracs = 0; isdigit((unsigned char) *ptr); ) {
+                               i*=10; i+= *ptr++ - '0';
+                               fracs++;
+                       }
+                       tm->tm_usec = i;
+                       if (i) {
+                               for (i = fracs; i<6; i++)
+                                       tm->tm_usec *= 10;
+                       }
                }
 
                /* Must be UTC */
@@ -362,6 +365,11 @@ lutil_atoux( unsigned *v, const char *s, int x )
        assert( s != NULL );
        assert( v != NULL );
 
+       /* strtoul() has an odd interface */
+       if ( s[ 0 ] == '-' ) {
+               return -1;
+       }
+
        u = strtoul( s, &next, x );
        if ( next == s || next[ 0 ] != '\0' ) {
                return -1;
@@ -404,6 +412,11 @@ lutil_atoulx( unsigned long *v, const char *s, int x )
        assert( s != NULL );
        assert( v != NULL );
 
+       /* strtoul() has an odd interface */
+       if ( s[ 0 ] == '-' ) {
+               return -1;
+       }
+
        ul = strtoul( s, &next, x );
        if ( next == s || next[ 0 ] != '\0' ) {
                return -1;
@@ -433,6 +446,11 @@ lutil_parse_time(
                unsigned long   u;
                char            *what;
 
+               /* strtoul() has an odd interface */
+               if ( s[ 0 ] == '-' ) {
+                       return -1;
+               }
+
                u = strtoul( s, &next, 10 );
                if ( next == s ) {
                        return -1;
index 6a2621da43b4434390e0748ff2c3549aab3db9ae..0044e6849ecfd40121b5dd8189f48aecf5b9ba27 100644 (file)
@@ -1681,15 +1681,15 @@ slap_acl_mask(
                        }
 
                        /* start out with nothing granted, nothing denied */
-                       ACL_INIT(tgrant);
-                       ACL_INIT(tdeny);
+                       ACL_INVALIDATE(tgrant);
+                       ACL_INVALIDATE(tdeny);
 
                        for ( da = b->a_dynacl; da; da = da->da_next ) {
                                slap_access_t   grant,
                                                deny;
 
-                               ACL_INIT(grant);
-                               ACL_INIT(deny);
+                               ACL_INVALIDATE(grant);
+                               ACL_INVALIDATE(deny);
 
                                Debug( LDAP_DEBUG_ACL, "    <= check a_dynacl: %s\n",
                                        da->da_name, 0, 0 );
index 0b018c1094143a80bcdfa6300034358f7b11ee82..48ec0cd7437d5959d54a0b5474773b46c6383633 100644 (file)
@@ -1784,6 +1784,7 @@ parse_acl(
                                /* out of arguments or plain stop */
 
                                ACL_PRIV_ASSIGN( b->a_access_mask, ACL_PRIV_ADDITIVE );
+                               ACL_PRIV_SET( b->a_access_mask, ACL_PRIV_NONE);
                                b->a_type = ACL_STOP;
 
                                access_append( &a->acl_access, b );
@@ -1794,6 +1795,7 @@ parse_acl(
                                /* plain continue */
 
                                ACL_PRIV_ASSIGN( b->a_access_mask, ACL_PRIV_ADDITIVE );
+                               ACL_PRIV_SET( b->a_access_mask, ACL_PRIV_NONE);
                                b->a_type = ACL_CONTINUE;
 
                                access_append( &a->acl_access, b );
@@ -1804,6 +1806,7 @@ parse_acl(
                                /* plain continue */
 
                                ACL_PRIV_ASSIGN(b->a_access_mask, ACL_PRIV_ADDITIVE);
+                               ACL_PRIV_SET( b->a_access_mask, ACL_PRIV_NONE);
                                b->a_type = ACL_BREAK;
 
                                access_append( &a->acl_access, b );
@@ -1814,6 +1817,7 @@ parse_acl(
                                /* we've gone too far */
                                --i;
                                ACL_PRIV_ASSIGN( b->a_access_mask, ACL_PRIV_ADDITIVE );
+                               ACL_PRIV_SET( b->a_access_mask, ACL_PRIV_NONE);
                                b->a_type = ACL_STOP;
 
                                access_append( &a->acl_access, b );
@@ -1821,16 +1825,19 @@ parse_acl(
                        }
 
                        /* get <access> */
-                       if ( strncasecmp( left, "self", STRLENOF( "self" ) ) == 0 ) {
-                               b->a_dn_self = 1;
-                               ACL_PRIV_ASSIGN( b->a_access_mask, str2accessmask( &left[ STRLENOF( "self" ) ] ) );
+                       {
+                               char    *lleft = left;
 
-                       } else if ( strncasecmp( left, "realself", STRLENOF( "realself" ) ) == 0 ) {
-                               b->a_realdn_self = 1;
-                               ACL_PRIV_ASSIGN( b->a_access_mask, str2accessmask( &left[ STRLENOF( "realself" ) ] ) );
+                               if ( strncasecmp( left, "self", STRLENOF( "self" ) ) == 0 ) {
+                                       b->a_dn_self = 1;
+                                       lleft = &left[ STRLENOF( "self" ) ];
 
-                       } else {
-                               ACL_PRIV_ASSIGN( b->a_access_mask, str2accessmask( left ) );
+                               } else if ( strncasecmp( left, "realself", STRLENOF( "realself" ) ) == 0 ) {
+                                       b->a_realdn_self = 1;
+                                       lleft = &left[ STRLENOF( "realself" ) ];
+                               }
+
+                               ACL_PRIV_ASSIGN( b->a_access_mask, str2accessmask( lleft ) );
                        }
 
                        if ( ACL_IS_INVALID( b->a_access_mask ) ) {
@@ -2131,7 +2138,10 @@ str2accessmask( const char *str )
                        } else if( TOLOWER((unsigned char) str[i]) == 'd' ) {
                                ACL_PRIV_SET(mask, ACL_PRIV_DISCLOSE);
 
-                       } else if( str[i] != '0' ) {
+                       } else if( str[i] == '0' ) {
+                               ACL_PRIV_SET(mask, ACL_PRIV_NONE);
+
+                       } else {
                                ACL_INVALIDATE(mask);
                                return mask;
                        }
@@ -2182,9 +2192,9 @@ acl_usage( void )
 {
        char *access =
                "<access clause> ::= access to <what> "
-                               "[ by <who> <access> [ <control> ] ]+ \n";
+                               "[ by <who> [ <access> ] [ <control> ] ]+ \n";
        char *what =
-               "<what> ::= * | [dn[.<dnstyle>]=<DN>] [filter=<filter>] [attrs=<attrspec>]\n"
+               "<what> ::= * | dn[.<dnstyle>=<DN>] [filter=<filter>] [attrs=<attrspec>]\n"
                "<attrspec> ::= <attrname> [val[/<matchingRule>][.<attrstyle>]=<value>] | <attrlist>\n"
                "<attrlist> ::= <attr> [ , <attrlist> ]\n"
                "<attr> ::= <attrname> | @<objectClass> | !<objectClass> | entry | children\n";
index 4ac9b6a8c042768c66d4632825fa8605ba45d021..c9601a3a10b33be83fd806f5a9ae55763d0d4c48 100644 (file)
@@ -124,20 +124,21 @@ int slap_str2ad(
 }
 
 static char *strchrlen(
-       const char *p, 
+       const char *beg, 
+       const char *end,
        const char ch, 
        int *len )
 {
-       int i;
+       const char *p;
 
-       for( i=0; p[i]; i++ ) {
-               if( p[i] == ch ) {
-                       *len = i;
-                       return (char *) &p[i];
+       for( p=beg; *p && p < end; p++ ) {
+               if( *p == ch ) {
+                       *len = p - beg;
+                       return (char *) p;
                }
        }
 
-       *len = i;
+       *len = p - beg;
        return NULL;
 }
 
@@ -148,7 +149,7 @@ int slap_bv2ad(
 {
        int rtn = LDAP_UNDEFINED_TYPE;
        AttributeDescription desc, *d2;
-       char *name, *options;
+       char *name, *options, *optn;
        char *opt, *next;
        int ntags;
        int tagslen;
@@ -201,11 +202,12 @@ int slap_bv2ad(
        ntags = 0;
        memset( tags, 0, sizeof( tags ));
        tagslen = 0;
+       optn = bv->bv_val + bv->bv_len;
 
        for( opt=options; opt != NULL; opt=next ) {
                int optlen;
                opt++; 
-               next = strchrlen( opt, ';', &optlen );
+               next = strchrlen( opt, optn, ';', &optlen );
 
                if( optlen == 0 ) {
                        *text = "zero length option is invalid";
@@ -443,19 +445,21 @@ static int is_ad_subtags(
        struct berval *subtagsbv, 
        struct berval *suptagsbv )
 {
-       const char *suptags, *supp, *supdelimp;
-       const char *subtags, *subp, *subdelimp;
+       const char *suptags, *supp, *supdelimp, *supn;
+       const char *subtags, *subp, *subdelimp, *subn;
        int  suplen, sublen;
 
        subtags =subtagsbv->bv_val;
        suptags =suptagsbv->bv_val;
+       subn = subtags + subtagsbv->bv_len;
+       supn = suptags + suptagsbv->bv_len;
 
        for( supp=suptags ; supp; supp=supdelimp ) {
-               supdelimp = strchrlen( supp, ';', &suplen );
+               supdelimp = strchrlen( supp, supn, ';', &suplen );
                if( supdelimp ) supdelimp++;
 
                for( subp=subtags ; subp; subp=subdelimp ) {
-                       subdelimp = strchrlen( subp, ';', &sublen );
+                       subdelimp = strchrlen( subp, subn, ';', &sublen );
                        if( subdelimp ) subdelimp++;
 
                        if ( suplen > sublen
index 461f4b556c1eeb0b32b6e7f95620c3ba610e3cb7..83e0fbd37f1f779dd0069f6ac14da19aab333ee0 100644 (file)
@@ -229,7 +229,7 @@ alock_read_slot ( alock_info_t * info,
        }
        
        if (alock_read_iattr (slotbuf) != ALOCK_MAGIC) {
-               return 1;
+               return -1;
        }
        slot_data->al_lock  = alock_read_iattr (slotbuf+8);
        slot_data->al_stamp = alock_read_iattr (slotbuf+16);
@@ -262,7 +262,8 @@ alock_write_slot ( alock_info_t * info,
        alock_write_iattr (slotbuf+16, slot_data->al_stamp);
        alock_write_iattr (slotbuf+24, slot_data->al_pid);
 
-       strncpy ((char *)slotbuf+32, slot_data->al_appname, ALOCK_MAX_APPNAME-1);
+       if (slot_data->al_appname)
+               strncpy ((char *)slotbuf+32, slot_data->al_appname, ALOCK_MAX_APPNAME-1);
        slotbuf[ALOCK_SLOT_SIZE-1] = '\0';
 
        res = lseek (info->al_fd, 
index 88b61cc819845fdb06bf0ec4520e06e30df039ef..fabf6b12c6ab917b2bcb3654b2362126c43e6d8e 100644 (file)
@@ -459,7 +459,7 @@ return_results:
        }
        op->o_private = NULL;
 
-       if( postread_ctrl != NULL ) {
+       if( postread_ctrl != NULL && (*postread_ctrl) != NULL ) {
                slap_sl_free( (*postread_ctrl)->ldctl_value.bv_val, op->o_tmpmemctx );
                slap_sl_free( *postread_ctrl, op->o_tmpmemctx );
        }
index 97c3c613ee8fe4b3e17f73a2b339f7af0ed407e4..2e715f8050f7fb31d5ca8c5f6a0146947f40b082 100644 (file)
@@ -571,7 +571,7 @@ return_results:
        send_ldap_result( op, rs );
        slap_graduate_commit_csn( op );
 
-       if( preread_ctrl != NULL ) {
+       if( preread_ctrl != NULL && (*preread_ctrl) != NULL ) {
                slap_sl_free( (*preread_ctrl)->ldctl_value.bv_val, op->o_tmpmemctx );
                slap_sl_free( *preread_ctrl, op->o_tmpmemctx );
        }
index 97cf1bd8e2c30d8a7b64aef2008137c22e41a653..9e55ef3ca3b44a6f6a595e5d070f51e82f4bc6f0 100644 (file)
@@ -1374,7 +1374,7 @@ int bdb_idl_append( ID *a, ID *b )
        return 0;
 }
 
-#if 0
+#if 1
 
 /* Quicksort + Insertion sort for small arrays */
 
index 6fe2a3060944d22cdfdf3f6abf5f8c6126b41dc2..e8c156298102e34fa0da4889a57f6348b344a01b 100644 (file)
@@ -551,6 +551,8 @@ bdb_back_initialize(
                LDAP_CONTROL_MANAGEDSAIT,
                LDAP_CONTROL_NOOP,
                LDAP_CONTROL_PAGEDRESULTS,
+               LDAP_CONTROL_PRE_READ,
+               LDAP_CONTROL_POST_READ,
                LDAP_CONTROL_SUBENTRIES,
                LDAP_CONTROL_X_PERMISSIVE_MODIFY,
 #ifdef LDAP_X_TXN
index 094f0915dc3837604c56d3b47e7c285bd5507f3b..9967bdb80637f24865dc25d9d11de84e8e3091e4 100644 (file)
@@ -649,11 +649,11 @@ done:
                bdb_unlocked_cache_return_entry_w (&bdb->bi_cache, e);
        }
 
-       if( preread_ctrl != NULL ) {
+       if( preread_ctrl != NULL && (*preread_ctrl) != NULL ) {
                slap_sl_free( (*preread_ctrl)->ldctl_value.bv_val, op->o_tmpmemctx );
                slap_sl_free( *preread_ctrl, op->o_tmpmemctx );
        }
-       if( postread_ctrl != NULL ) {
+       if( postread_ctrl != NULL && (*postread_ctrl) != NULL ) {
                slap_sl_free( (*postread_ctrl)->ldctl_value.bv_val, op->o_tmpmemctx );
                slap_sl_free( *postread_ctrl, op->o_tmpmemctx );
        }
index cb557832f8f8981d6cbad7fedf78e0a2fab6298e..6aececa31ef7629efc7df70c16b199213875c43f 100644 (file)
@@ -811,11 +811,11 @@ done:
        }
        op->o_private = NULL;
 
-       if( preread_ctrl != NULL ) {
+       if( preread_ctrl != NULL && (*preread_ctrl) != NULL ) {
                slap_sl_free( (*preread_ctrl)->ldctl_value.bv_val, op->o_tmpmemctx );
                slap_sl_free( *preread_ctrl, op->o_tmpmemctx );
        }
-       if( postread_ctrl != NULL ) {
+       if( postread_ctrl != NULL && (*postread_ctrl) != NULL ) {
                slap_sl_free( (*postread_ctrl)->ldctl_value.bv_val, op->o_tmpmemctx );
                slap_sl_free( *postread_ctrl, op->o_tmpmemctx );
        }
index 167f3c7e5e2b46d198a5e2114a5cba5933a87cf3..9c6e23ef7c889ce068fdae516d40297d6d57f162 100644 (file)
@@ -68,7 +68,8 @@ static int *bdb_tool_index_threads, bdb_tool_index_tcount;
 static void *bdb_tool_index_rec;
 static struct bdb_info *bdb_tool_info;
 static ldap_pvt_thread_mutex_t bdb_tool_index_mutex;
-static ldap_pvt_thread_cond_t bdb_tool_index_cond;
+static ldap_pvt_thread_cond_t bdb_tool_index_cond_main;
+static ldap_pvt_thread_cond_t bdb_tool_index_cond_work;
 
 static void * bdb_tool_index_task( void *ctx, void *ptr );
 
@@ -98,7 +99,8 @@ int bdb_tool_entry_open(
                if ( !bdb_tool_info ) {
                        int i;
                        ldap_pvt_thread_mutex_init( &bdb_tool_index_mutex );
-                       ldap_pvt_thread_cond_init( &bdb_tool_index_cond );
+                       ldap_pvt_thread_cond_init( &bdb_tool_index_cond_main );
+                       ldap_pvt_thread_cond_init( &bdb_tool_index_cond_work );
                        bdb_tool_index_threads = ch_malloc( slap_tool_thread_max * sizeof( int ));
                        bdb_tool_index_rec = ch_malloc( bdb->bi_nattrs * sizeof( IndexRec ));
                        bdb_tool_index_tcount = slap_tool_thread_max - 1;
@@ -122,7 +124,7 @@ int bdb_tool_entry_close(
                slapd_shutdown = 1;
                ldap_pvt_thread_mutex_lock( &bdb_tool_index_mutex );
                bdb_tool_index_tcount = slap_tool_thread_max - 1;
-               ldap_pvt_thread_cond_broadcast( &bdb_tool_index_cond );
+               ldap_pvt_thread_cond_broadcast( &bdb_tool_index_cond_work );
                ldap_pvt_thread_mutex_unlock( &bdb_tool_index_mutex );
        }
 
@@ -410,28 +412,32 @@ bdb_tool_index_add(
                ldap_pvt_thread_mutex_lock( &bdb_tool_index_mutex );
                /* Wait for all threads to be ready */
                while ( bdb_tool_index_tcount ) {
-                       ldap_pvt_thread_mutex_unlock( &bdb_tool_index_mutex );
-                       ldap_pvt_thread_yield();
-                       ldap_pvt_thread_mutex_lock( &bdb_tool_index_mutex );
+                       ldap_pvt_thread_cond_wait( &bdb_tool_index_cond_main, 
+                               &bdb_tool_index_mutex );
                }
                for ( i=1; i<slap_tool_thread_max; i++ )
                        bdb_tool_index_threads[i] = LDAP_BUSY;
                bdb_tool_index_tcount = slap_tool_thread_max - 1;
-               ldap_pvt_thread_cond_broadcast( &bdb_tool_index_cond );
+               ldap_pvt_thread_cond_broadcast( &bdb_tool_index_cond_work );
                ldap_pvt_thread_mutex_unlock( &bdb_tool_index_mutex );
                rc = bdb_index_recrun( op, bdb, ir, e->e_id, 0 );
                if ( rc )
                        return rc;
+               ldap_pvt_thread_mutex_lock( &bdb_tool_index_mutex );
                for ( i=1; i<slap_tool_thread_max; i++ ) {
                        if ( bdb_tool_index_threads[i] == LDAP_BUSY ) {
-                               ldap_pvt_thread_yield();
+                               ldap_pvt_thread_cond_wait( &bdb_tool_index_cond_main, 
+                                       &bdb_tool_index_mutex );
                                i--;
                                continue;
                        }
-                       if ( bdb_tool_index_threads[i] )
-                               return bdb_tool_index_threads[i];
+                       if ( bdb_tool_index_threads[i] ) {
+                               rc = bdb_tool_index_threads[i];
+                               break;
+                       }
                }
-               return 0;
+               ldap_pvt_thread_mutex_unlock( &bdb_tool_index_mutex );
+               return rc;
        } else {
                return bdb_index_entry_add( op, txn, e );
        }
@@ -1015,7 +1021,9 @@ bdb_tool_index_task( void *ctx, void *ptr )
        while ( 1 ) {
                ldap_pvt_thread_mutex_lock( &bdb_tool_index_mutex );
                bdb_tool_index_tcount--;
-               ldap_pvt_thread_cond_wait( &bdb_tool_index_cond,
+               if ( !bdb_tool_index_tcount )
+                       ldap_pvt_thread_cond_signal( &bdb_tool_index_cond_main );
+               ldap_pvt_thread_cond_wait( &bdb_tool_index_cond_work,
                        &bdb_tool_index_mutex );
                ldap_pvt_thread_mutex_unlock( &bdb_tool_index_mutex );
                if ( slapd_shutdown )
index 3fb58ba581184bbee1de890951388d1762c49cb5..e8e73cc462679fbcf91420b7c64af0bffa88f89c 100644 (file)
@@ -54,13 +54,15 @@ typedef struct ldapconn_t {
                } \
        } while ( 0 )
 
-#define        LDAP_BACK_FCONN_ISBOUND (0x01)
-#define        LDAP_BACK_FCONN_ISANON  (0x02)
+#define        LDAP_BACK_FCONN_ISBOUND (0x00000001U)
+#define        LDAP_BACK_FCONN_ISANON  (0x00000002U)
 #define        LDAP_BACK_FCONN_ISBMASK (LDAP_BACK_FCONN_ISBOUND|LDAP_BACK_FCONN_ISANON)
-#define        LDAP_BACK_FCONN_ISPRIV  (0x04)
-#define        LDAP_BACK_FCONN_ISTLS   (0x08)
-#define        LDAP_BACK_FCONN_BINDING (0x10)
-#define        LDAP_BACK_FCONN_TAINTED (0x20)
+#define        LDAP_BACK_FCONN_ISPRIV  (0x00000004U)
+#define        LDAP_BACK_FCONN_ISTLS   (0x00000008U)
+#define        LDAP_BACK_FCONN_BINDING (0x00000010U)
+#define        LDAP_BACK_FCONN_TAINTED (0x00000020U)
+
+/* 0x00FF0000 are reserved for back-meta */
 
 #define        LDAP_BACK_CONN_ISBOUND(lc)              LDAP_BACK_CONN_ISSET((lc), LDAP_BACK_FCONN_ISBOUND)
 #define        LDAP_BACK_CONN_ISBOUND_SET(lc)          LDAP_BACK_CONN_SET((lc), LDAP_BACK_FCONN_ISBOUND)
@@ -127,6 +129,11 @@ typedef struct ldapinfo_t {
        /* li_bvuri: an array of each single URI that is equivalent;
         * to be checked for the presence of a certain item */
        BerVarray       li_bvuri;
+       ldap_pvt_thread_mutex_t li_uri_mutex;
+
+       LDAP_REBIND_PROC        *li_rebind_f;
+       LDAP_URLLIST_PROC       *li_urllist_f;
+       void                    *li_urllist_p;
 
        slap_bindconf   li_acl;
 #define        li_acl_authcID  li_acl.sb_authcId
@@ -169,20 +176,23 @@ typedef struct ldapinfo_t {
 #define LDAP_BACK_RETRY_DEFAULT                (3)
 
        unsigned        li_flags;
-#define LDAP_BACK_F_NONE               0x00U
-#define LDAP_BACK_F_SAVECRED           0x01U
-#define LDAP_BACK_F_USE_TLS            0x02U
-#define LDAP_BACK_F_PROPAGATE_TLS      0x04U
-#define LDAP_BACK_F_TLS_CRITICAL       0x08U
+#define LDAP_BACK_F_NONE               0x0000U
+#define LDAP_BACK_F_SAVECRED           0x0001U
+#define LDAP_BACK_F_USE_TLS            0x0002U
+#define LDAP_BACK_F_PROPAGATE_TLS      0x0004U
+#define LDAP_BACK_F_TLS_CRITICAL       0x0008U
 #define LDAP_BACK_F_TLS_USE_MASK       (LDAP_BACK_F_USE_TLS|LDAP_BACK_F_TLS_CRITICAL)
 #define LDAP_BACK_F_TLS_PROPAGATE_MASK (LDAP_BACK_F_PROPAGATE_TLS|LDAP_BACK_F_TLS_CRITICAL)
 #define LDAP_BACK_F_TLS_MASK           (LDAP_BACK_F_TLS_USE_MASK|LDAP_BACK_F_TLS_PROPAGATE_MASK)
-#define LDAP_BACK_F_CHASE_REFERRALS    0x10U
-#define LDAP_BACK_F_PROXY_WHOAMI       0x20U
+#define LDAP_BACK_F_CHASE_REFERRALS    0x0010U
+#define LDAP_BACK_F_PROXY_WHOAMI       0x0020U
+
+#define        LDAP_BACK_F_SUPPORT_T_F_DISCOVER        0x0040U
+#define        LDAP_BACK_F_SUPPORT_T_F         0x0080U
+#define        LDAP_BACK_F_SUPPORT_T_F_MASK    (LDAP_BACK_F_SUPPORT_T_F|LDAP_BACK_F_SUPPORT_T_F_DISCOVER)
 
-#define        LDAP_BACK_F_SUPPORT_T_F                 0x80U
-#define        LDAP_BACK_F_SUPPORT_T_F_DISCOVER        0x40U
-#define        LDAP_BACK_F_SUPPORT_T_F_MASK            (LDAP_BACK_F_SUPPORT_T_F|LDAP_BACK_F_SUPPORT_T_F_DISCOVER)
+#define LDAP_BACK_F_MONITOR            0x0100U
+#define        LDAP_BACK_F_SINGLECONN          0x0200U
 
 #define        LDAP_BACK_ISSET(li,f)           ( ( (li)->li_flags & (f) ) == (f) )
 #define LDAP_BACK_SAVECRED(li)         LDAP_BACK_ISSET( (li), LDAP_BACK_F_SAVECRED )
@@ -191,6 +201,8 @@ typedef struct ldapinfo_t {
 #define LDAP_BACK_TLS_CRITICAL(li)     LDAP_BACK_ISSET( (li), LDAP_BACK_F_TLS_CRITICAL )
 #define LDAP_BACK_CHASE_REFERRALS(li)  LDAP_BACK_ISSET( (li), LDAP_BACK_F_CHASE_REFERRALS )
 #define LDAP_BACK_PROXY_WHOAMI(li)     LDAP_BACK_ISSET( (li), LDAP_BACK_F_PROXY_WHOAMI )
+#define LDAP_BACK_MONITOR(li)          LDAP_BACK_ISSET( (li), LDAP_BACK_F_MONITOR )
+#define        LDAP_BACK_SINGLECONN(li)        LDAP_BACK_ISSET( (li), LDAP_BACK_F_SINGLECONN )
 
        int             li_version;
 
index 131219683fc0db4b607ae0b9be4d11e7ad485cdb..d43d13df336b6f1ae1333bfc1bdfe7ee2c13603b 100644 (file)
 
 #define LDAP_CONTROL_OBSOLETE_PROXY_AUTHZ      "2.16.840.1.113730.3.4.12"
 
-static LDAP_REBIND_PROC        ldap_back_default_rebind;
+#if PRINT_CONNTREE > 0
+static void
+ravl_print( Avlnode *root, int depth )
+{
+       int             i;
+       ldapconn_t      *lc;
+       
+       if ( root == 0 ) {
+               return;
+       }
+       
+       ravl_print( root->avl_right, depth+1 );
+       
+       for ( i = 0; i < depth; i++ ) {
+               fprintf( stderr, "-" );
+       }
+
+       lc = root->avl_data;
+       fprintf( stderr, "lc=%p local=\"%s\" conn=%p %s refcnt=%d\n",
+               (void *)lc,
+               lc->lc_local_ndn.bv_val ? lc->lc_local_ndn.bv_val : "",
+               (void *)lc->lc_conn,
+               avl_bf2str( root->avl_bf ), lc->lc_refcnt );
+       
+       ravl_print( root->avl_left, depth+1 );
+}
 
-LDAP_REBIND_PROC       *ldap_back_rebind_f = ldap_back_default_rebind;
+static void
+myprint( Avlnode *root, char *msg )
+{
+       fprintf( stderr, "========> %s\n", msg );
+       
+       if ( root == 0 ) {
+               fprintf( stderr, "\tNULL\n" );
+
+       } else {
+               ravl_print( root, 0 );
+       }
+       
+       fprintf( stderr, "<======== %s\n", msg );
+}
+#endif /* PRINT_CONNTREE */
 
 static int
 ldap_back_proxy_authz_bind( ldapconn_t *lc, Operation *op, SlapReply *rs, ldap_back_send_t sendok );
@@ -103,7 +142,7 @@ ldap_back_bind( Operation *op, SlapReply *rs )
                                                lc->lc_cred.bv_len );
                        }
                        ber_bvreplace( &lc->lc_cred, &op->orb_cred );
-                       ldap_set_rebind_proc( lc->lc_ld, ldap_back_rebind_f, lc );
+                       ldap_set_rebind_proc( lc->lc_ld, li->li_rebind_f, lc );
                }
        }
 done:;
@@ -133,12 +172,42 @@ retry_lock:;
                                ldap_back_conndnlc_cmp );
                assert( tmplc == NULL || lc == tmplc );
 
+               /* delete all cached connections with the current connection */
+               if ( LDAP_BACK_SINGLECONN( li ) ) {
+                       while ( ( tmplc = avl_delete( &li->li_conninfo.lai_tree, (caddr_t)lc, ldap_back_conn_cmp ) ) != NULL )
+                       {
+                               Debug( LDAP_DEBUG_TRACE,
+                                       "=>ldap_back_bind: destroying conn %ld (refcnt=%u)\n",
+                                       LDAP_BACK_PCONN_ID( lc->lc_conn ), lc->lc_refcnt, 0 );
+
+                               if ( lc->lc_refcnt != 0 ) {
+                                       /* taint it */
+                                       LDAP_BACK_CONN_TAINTED_SET( tmplc );
+
+                               } else {
+                                       /*
+                                        * Needs a test because the handler may be corrupted,
+                                        * and calling ldap_unbind on a corrupted header results
+                                        * in a segmentation fault
+                                        */
+                                       ldap_back_conn_free( tmplc );
+                               }
+                       }
+               }
+
                if ( LDAP_BACK_CONN_ISBOUND( lc ) ) {
                        ber_bvreplace( &lc->lc_local_ndn, &op->o_req_ndn );
+                       if ( be_isroot_dn( op->o_bd, &op->o_req_ndn ) ) {
+                               lc->lc_conn = LDAP_BACK_PCONN_SET( op );
+                       }
                        lerr = avl_insert( &li->li_conninfo.lai_tree, (caddr_t)lc,
                                ldap_back_conndn_cmp, ldap_back_conndn_dup );
                }
 
+#if PRINT_CONNTREE > 0
+               myprint( li->li_conninfo.lai_tree, "ldap_back_bind" );
+#endif /* PRINT_CONNTREE */
+       
                ldap_pvt_thread_mutex_unlock( &li->li_conninfo.lai_mutex );
                switch ( lerr ) {
                case 0:
@@ -255,47 +324,6 @@ ldap_back_conndn_dup( void *c1, void *c2 )
        return 0;
 }
 
-#if PRINT_CONNTREE > 0
-static void
-ravl_print( Avlnode *root, int depth )
-{
-       int             i;
-       ldapconn_t      *lc;
-       
-       if ( root == 0 ) {
-               return;
-       }
-       
-       ravl_print( root->avl_right, depth+1 );
-       
-       for ( i = 0; i < depth; i++ ) {
-               fprintf( stderr, "-" );
-       }
-
-       lc = root->avl_data;
-       fprintf( stderr, "lc=%p local=\"%s\" conn=%p %s refcnt=%d\n",
-               (void *)lc, lc->lc_local_ndn.bv_val, (void *)lc->lc_conn,
-               avl_bf2str( root->avl_bf ), lc->lc_refcnt );
-       
-       ravl_print( root->avl_left, depth+1 );
-}
-
-static void
-myprint( Avlnode *root )
-{
-       fprintf( stderr, "========>\n" );
-       
-       if ( root == 0 ) {
-               fprintf( stderr, "\tNULL\n" );
-
-       } else {
-               ravl_print( root, 0 );
-       }
-       
-       fprintf( stderr, "<========\n" );
-}
-#endif /* PRINT_CONNTREE */
-
 int
 ldap_back_freeconn( Operation *op, ldapconn_t *lc, int dolock )
 {
@@ -478,11 +506,17 @@ ldap_back_prepare_conn( ldapconn_t **lcp, Operation *op, SlapReply *rs, ldap_bac
 
        assert( lcp != NULL );
 
+       ldap_pvt_thread_mutex_lock( &li->li_uri_mutex );
        rs->sr_err = ldap_initialize( &ld, li->li_uri );
+       ldap_pvt_thread_mutex_unlock( &li->li_uri_mutex );
        if ( rs->sr_err != LDAP_SUCCESS ) {
                goto error_return;
        }
 
+       if ( li->li_urllist_f ) {
+               ldap_set_urllist_proc( ld, li->li_urllist_f, li->li_urllist_p );
+       }
+
        /* Set LDAP version. This will always succeed: If the client
         * bound with a particular version, then so can we.
         */
@@ -511,8 +545,10 @@ ldap_back_prepare_conn( ldapconn_t **lcp, Operation *op, SlapReply *rs, ldap_bac
        }
 
 #ifdef HAVE_TLS
+       ldap_pvt_thread_mutex_lock( &li->li_uri_mutex );
        rs->sr_err = ldap_back_start_tls( ld, op->o_protocol, &is_tls,
                        li->li_uri, li->li_flags, li->li_nretries, &rs->sr_text );
+       ldap_pvt_thread_mutex_unlock( &li->li_uri_mutex );
        if ( rs->sr_err != LDAP_SUCCESS ) {
                ldap_unbind_ext( ld, NULL, NULL );
                goto error_return;
@@ -521,7 +557,7 @@ ldap_back_prepare_conn( ldapconn_t **lcp, Operation *op, SlapReply *rs, ldap_bac
 
        if ( *lcp == NULL ) {
                *lcp = (ldapconn_t *)ch_calloc( 1, sizeof( ldapconn_t ) );
-               (*lcp)->lc_flags= li->li_flags;
+               (*lcp)->lc_flags = li->li_flags;
        }
        (*lcp)->lc_ld = ld;
        (*lcp)->lc_refcnt = 1;
@@ -669,7 +705,7 @@ retry_lock:
                        ldap_back_conndn_cmp, ldap_back_conndn_dup );
 
 #if PRINT_CONNTREE > 0
-               myprint( li->li_conninfo.lai_tree );
+               myprint( li->li_conninfo.lai_tree, "ldap_back_getconn" );
 #endif /* PRINT_CONNTREE */
        
                ldap_pvt_thread_mutex_unlock( &li->li_conninfo.lai_mutex );
@@ -732,13 +768,16 @@ retry_lock:
                        Debug( LDAP_DEBUG_TRACE,
                                "=>ldap_back_getconn: %s.\n", buf, 0, 0 );
                }
+       
        }
 
+#ifdef HAVE_TLS
+done:;
+#endif /* HAVE_TLS */
        if ( li->li_idle_timeout && lc ) {
                lc->lc_time = op->o_time;
        }
 
-done:;
        return lc;
 }
 
@@ -896,8 +935,8 @@ retry_lock:;
 
                        if ( rc != LDAP_OPT_SUCCESS ) {
                                Debug( LDAP_DEBUG_ANY, "Error: ldap_set_option "
-                                       "(%s,SECPROPS,\"%s\") failed!\n",
-                                       li->li_uri, li->li_acl_secprops, 0 );
+                                       "(SECPROPS,\"%s\") failed!\n",
+                                       li->li_acl_secprops, 0, 0 );
                                goto done;
                        }
                }
@@ -975,6 +1014,7 @@ retry:;
                        }
                }
 
+               lc->lc_binding--;
                ldap_back_freeconn( op, lc, dolock );
                rs->sr_err = slap_map_api2result( rs );
 
@@ -1011,7 +1051,7 @@ ldap_back_dobind( ldapconn_t *lc, Operation *op, SlapReply *rs, ldap_back_send_t
  * This is a callback used for chasing referrals using the same
  * credentials as the original user on this session.
  */
-static int 
+int 
 ldap_back_default_rebind( LDAP *ld, LDAP_CONST char *url, ber_tag_t request,
        ber_int_t msgid, void *params )
 {
@@ -1040,6 +1080,41 @@ ldap_back_default_rebind( LDAP *ld, LDAP_CONST char *url, ber_tag_t request,
                        LDAP_SASL_SIMPLE, &lc->lc_cred, NULL, NULL, NULL );
 }
 
+/*
+ * ldap_back_default_urllist
+ */
+int 
+ldap_back_default_urllist(
+       LDAP            *ld,
+       LDAPURLDesc     **urllist,
+       LDAPURLDesc     **url,
+       void            *params )
+{
+       ldapinfo_t      *li = (ldapinfo_t *)params;
+       LDAPURLDesc     **urltail;
+
+       if ( urllist == url ) {
+               return LDAP_SUCCESS;
+       }
+
+       for ( urltail = &(*url)->lud_next; *urltail; urltail = &(*urltail)->lud_next )
+               /* count */ ;
+
+       *urltail = *urllist;
+       *urllist = *url;
+       *url = NULL;
+
+       ldap_pvt_thread_mutex_lock( &li->li_uri_mutex );
+       if ( li->li_uri ) {
+               ch_free( li->li_uri );
+       }
+
+       ldap_get_option( ld, LDAP_OPT_URI, (void *)&li->li_uri );
+       ldap_pvt_thread_mutex_unlock( &li->li_uri_mutex );
+
+       return LDAP_SUCCESS;
+}
+
 int
 ldap_back_op_result(
                ldapconn_t              *lc,
@@ -1158,11 +1233,13 @@ ldap_back_retry( ldapconn_t **lcp, Operation *op, SlapReply *rs, ldap_back_send_
        ldap_pvt_thread_mutex_lock( &li->li_conninfo.lai_mutex );
 
        if ( (*lcp)->lc_refcnt == 1 ) {
+               ldap_pvt_thread_mutex_lock( &li->li_uri_mutex );
                Debug( LDAP_DEBUG_ANY,
                        "%s ldap_back_retry: retrying URI=\"%s\" DN=\"%s\"\n",
                        op->o_log_prefix, li->li_uri,
                        BER_BVISNULL( &(*lcp)->lc_bound_ndn ) ?
                                "" : (*lcp)->lc_bound_ndn.bv_val );
+               ldap_pvt_thread_mutex_unlock( &li->li_uri_mutex );
 
                ldap_unbind_ext( (*lcp)->lc_ld, NULL, NULL );
                (*lcp)->lc_ld = NULL;
@@ -1227,7 +1304,10 @@ ldap_back_proxy_authz_bind( ldapconn_t *lc, Operation *op, SlapReply *rs, ldap_b
                goto done;
        }
 
-       if ( !BER_BVISNULL( &op->o_conn->c_ndn ) ) {
+       if ( op->o_tag == LDAP_REQ_BIND ) {
+               ndn = op->o_req_ndn;
+
+       } else if ( !BER_BVISNULL( &op->o_conn->c_ndn ) ) {
                ndn = op->o_conn->c_ndn;
 
        } else {
@@ -1652,6 +1732,11 @@ ldap_back_proxy_authz_ctrl(
                assertedID = slap_empty_bv;
        }
 
+       /* don't idassert the bound DN (ITS#4497) */
+       if ( dn_match( &assertedID, &lc->lc_bound_ndn ) ) {
+               goto done;
+       }
+
        if ( op->o_ctrls ) {
                for ( i = 0; op->o_ctrls[ i ]; i++ )
                        /* just count ctrls */ ;
index 6c041620757a5bd803cda79a3ee8377fff2ef9a6..ca6afdd2d6f9797f194031158da891d7594eb6a9 100644 (file)
@@ -381,7 +381,7 @@ Document: draft-ietf-ldapbis-protocol-27.txt
        
                /* parse reference and use 
                 * proto://[host][:port]/ only */
-               rc = ldap_url_parse_ext( ref->bv_val, &srv );
+               rc = ldap_url_parse_ext( ref->bv_val, &srv, LDAP_PVT_URL_PARSE_NONE );
                if ( rc != LDAP_URL_SUCCESS ) {
                        /* try next */
                        rc = LDAP_OTHER;
@@ -618,7 +618,7 @@ ldap_chain_response( Operation *op, SlapReply *rs )
 
                                /* parse reference and use
                                 * proto://[host][:port]/ only */
-                               rc = ldap_url_parse_ext( curr[0].bv_val, &srv );
+                               rc = ldap_url_parse_ext( curr[0].bv_val, &srv, LDAP_PVT_URL_PARSE_NONE );
                                if ( rc != LDAP_URL_SUCCESS ) {
                                        /* try next */
                                        rs->sr_err = LDAP_OTHER;
@@ -1550,6 +1550,7 @@ ldap_chain_db_init_common(
        BackendDB       *be )
 {
        BackendInfo     *bi = be->bd_info;
+       ldapinfo_t      *li;
        int             t;
 
        be->bd_info = lback;
@@ -1558,6 +1559,9 @@ ldap_chain_db_init_common(
        if ( t != 0 ) {
                return t;
        }
+       li = (ldapinfo_t *)be->be_private;
+       li->li_urllist_f = NULL;
+       li->li_urllist_p = NULL;
        be->bd_info = bi;
 
        return 0;
@@ -1590,6 +1594,8 @@ ldap_chain_db_init_one(
                return t;
        }
        li = (ldapinfo_t *)be->be_private;
+       li->li_urllist_f = NULL;
+       li->li_urllist_p = NULL;
 
        /* copy common data */
        li->li_nretries = lc->lc_common_li->li_nretries;
index ddf4e77ae086eb317106653bdf3c03f3b6f137a5..d270b40eab65115d9409f4b5ec45ac5fd0cbc5ef 100644 (file)
@@ -64,6 +64,7 @@ enum {
        LDAP_BACK_CFG_CONN_TTL,
        LDAP_BACK_CFG_NETWORK_TIMEOUT,
        LDAP_BACK_CFG_VERSION,
+       LDAP_BACK_CFG_SINGLECONN,
        LDAP_BACK_CFG_REWRITE,
 
        LDAP_BACK_CFG_LAST
@@ -250,6 +251,14 @@ static ConfigTable ldapcfg[] = {
                        "SYNTAX OMsInteger "
                        "SINGLE-VALUE )",
                NULL, NULL },
+       { "single-conn", "TRUE/FALSE", 2, 0, 0,
+               ARG_MAGIC|ARG_ON_OFF|LDAP_BACK_CFG_SINGLECONN,
+               ldap_back_cf_gen, "( OLcfgDbAt:3.19 "
+                       "NAME 'olcDbSingleConn' "
+                       "DESC 'cache a single connection per identity' "
+                       "SYNTAX OMsBoolean "
+                       "SINGLE-VALUE )",
+               NULL, NULL },
        { "suffixmassage", "[virtual]> <real", 2, 3, 0,
                ARG_STRING|ARG_MAGIC|LDAP_BACK_CFG_REWRITE,
                ldap_back_cf_gen, NULL, NULL, NULL },
@@ -284,6 +293,7 @@ static ConfigOCs ldapocs[] = {
                        "$ olcDbProxyWhoAmI "
                        "$ olcDbTimeout "
                        "$ olcDbIdleTimeout "
+                       "$ olcDbSingleConn "
                ") )",
                        Cft_Database, ldapcfg},
        { NULL, 0, NULL }
@@ -629,6 +639,10 @@ ldap_back_cf_gen( ConfigArgs *c )
                        c->value_int = li->li_version;
                        break;
 
+               case LDAP_BACK_CFG_SINGLECONN:
+                       c->value_int = LDAP_BACK_SINGLECONN( li );
+                       break;
+
                default:
                        /* FIXME: we need to handle all... */
                        assert( 0 );
@@ -722,6 +736,10 @@ ldap_back_cf_gen( ConfigArgs *c )
                        li->li_version = 0;
                        break;
 
+               case LDAP_BACK_CFG_SINGLECONN:
+                       li->li_flags &= ~LDAP_BACK_F_SINGLECONN;
+                       break;
+
                default:
                        /* FIXME: we need to handle all... */
                        assert( 0 );
@@ -747,7 +765,7 @@ ldap_back_cf_gen( ConfigArgs *c )
                }
 
                /* PARANOID: DN and more are not required nor allowed */
-               urlrc = ldap_url_parselist_ext( &lud, c->argv[ 1 ], ", \t" );
+               urlrc = ldap_url_parselist_ext( &lud, c->argv[ 1 ], ", \t", LDAP_PVT_URL_PARSE_NONE );
                if ( urlrc != LDAP_URL_SUCCESS ) {
                        char    *why;
 
@@ -811,7 +829,7 @@ ldap_back_cf_gen( ConfigArgs *c )
                                                "host and port allowed "
                                                "in \"uri <uri>\" statement "
                                                "for uri #%d of \"%s\"",
-                                               i, c->value_string );
+                                               i, c->argv[ 1 ] );
                                Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
                        }
                }
@@ -1323,16 +1341,25 @@ done_url:;
                } break;
 
        case LDAP_BACK_CFG_VERSION:
-               switch ( c->value_int ) {
-               case 0:
-               case LDAP_VERSION2:
-               case LDAP_VERSION3:
-                       li->li_version = c->value_int;
-                       break;
-
-               default:
+               if ( c->value_int != 0 && ( c->value_int < LDAP_VERSION_MIN || c->value_int > LDAP_VERSION_MAX ) ) {
+                       snprintf( c->msg, sizeof( c->msg ),
+                               "unsupported version \"%s\" "
+                               "in \"protocol-version <version>\"",
+                               c->argv[ 1 ] );
+                       Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
                        return 1;
                }
+
+               li->li_version = c->value_int;
+               break;
+
+       case LDAP_BACK_CFG_SINGLECONN:
+               if ( c->value_int ) {
+                       li->li_flags |= LDAP_BACK_F_SINGLECONN;
+
+               } else {
+                       li->li_flags &= ~LDAP_BACK_F_SINGLECONN;
+               }
                break;
 
        case LDAP_BACK_CFG_REWRITE:
index 77a10e78c8984185d400f530de9bf05128b48e62..765f201c21e1a0f8ce97667b23a0297dbb37570b 100644 (file)
@@ -103,6 +103,11 @@ ldap_back_db_init( Backend *be )
                return -1;
        }
 
+       li->li_rebind_f = ldap_back_default_rebind;
+       li->li_urllist_f = ldap_back_default_urllist;
+       li->li_urllist_p = li;
+       ldap_pvt_thread_mutex_init( &li->li_uri_mutex );
+
        BER_BVZERO( &li->li_acl_authcID );
        BER_BVZERO( &li->li_acl_authcDN );
        BER_BVZERO( &li->li_acl_passwd );
@@ -304,6 +309,7 @@ ldap_back_db_destroy(
 
                ldap_pvt_thread_mutex_unlock( &li->li_conninfo.lai_mutex );
                ldap_pvt_thread_mutex_destroy( &li->li_conninfo.lai_mutex );
+               ldap_pvt_thread_mutex_destroy( &li->li_uri_mutex );
        }
 
        ch_free( be->be_private );
index 153a25978a78214059d44bcea86cbc9a257cf43b..05d68832549e6ff20bc9cbae843202be0340bb5d 100644 (file)
@@ -81,7 +81,8 @@ extern int chain_initialize( void );
 extern int distproc_initialize( void );
 #endif
 
-extern LDAP_REBIND_PROC                *ldap_back_rebind_f;
+extern LDAP_REBIND_PROC                ldap_back_default_rebind;
+extern LDAP_URLLIST_PROC       ldap_back_default_urllist;
 
 LDAP_END_DECL
 
index dc1d88757ec6d7812a7663b3b4118c81ec09f076..db629ba55dae5c1a8f6bf9cd8891a7b4e7d2dbc0 100644 (file)
@@ -43,7 +43,7 @@ struct ldif_info {
        struct berval li_base_path;
        enumCookie li_tool_cookie;
        ID li_tool_current;
-       ldap_pvt_thread_mutex_t  li_mutex;
+       ldap_pvt_thread_rdwr_t  li_rdwr;
 };
 
 #ifdef _WIN32
@@ -157,7 +157,7 @@ static int spew_file(int fd, char * spew, int len) {
                writeres = write(fd, spew, len);
                if(writeres == -1) {
                        Debug( LDAP_DEBUG_ANY, "could not spew write: %s\n",
-                               strerror( errno ), 0, 0 );
+                               STRERROR( errno ), 0, 0 );
                        return -1;
                }
                else {
@@ -182,7 +182,7 @@ static int spew_entry(Entry * e, struct berval * path) {
                else
                        rs = LDAP_UNWILLING_TO_PERFORM;
                Debug( LDAP_DEBUG_ANY, "could not open \"%s\": %s\n",
-                       path->bv_val, strerror( errno ), 0 );
+                       path->bv_val, STRERROR( errno ), 0 );
        }
        else {
                struct berval rdn;
@@ -264,9 +264,9 @@ static Entry * get_entry(Operation *op, struct berval *base_path) {
        dn2path(&op->o_req_ndn, op->o_bd->be_nsuffix, base_path, &path);
        fd = open(path.bv_val, O_RDONLY);
        /* error opening file (mebbe should log error) */
-       if(fd == -1) {
-               Debug(LDAP_DEBUG_ANY, "failed to open file \"%s\": %s\n",
-                       path.bv_val, strerror(errno), 0 );
+       if ( fd == -1 && ( errno != ENOENT || op->o_tag != LDAP_REQ_ADD ) ) {
+               Debug( LDAP_DEBUG_ANY, "failed to open file \"%s\": %s\n",
+                       path.bv_val, STRERROR(errno), 0 );
        }
 
        if(path.bv_val != NULL)
@@ -308,7 +308,7 @@ static int r_enum_tree(enumCookie *ck, struct berval *path,
        if ( fd < 0 ) {
                Debug( LDAP_DEBUG_ANY,
                        "=> ldif_enum_tree: failed to open %s: %s\n",
-                       path->bv_val, strerror(errno), 0 );
+                       path->bv_val, STRERROR(errno), 0 );
                return LDAP_NO_SUCH_OBJECT;
        }
 
@@ -420,7 +420,7 @@ static int r_enum_tree(enumCookie *ck, struct berval *path,
                                if ( ptr ) {
                                        itmp.bv_len = ptr - itmp.bv_val;
                                        ber_dupbv( &bvl->num, &itmp );
-                                       bvl->inum = strtoul( itmp.bv_val, NULL, 0 );
+                                       bvl->inum = strtol( itmp.bv_val, NULL, 0 );
                                        itmp.bv_val[0] = '\0';
                                        bvl->off = itmp.bv_val - bvl->bv.bv_val;
                                }
@@ -507,7 +507,8 @@ static int apply_modify_to_entry(Entry * entry,
                                SlapReply * rs)
 {
        char textbuf[SLAP_TEXT_BUFLEN];
-       int rc = LDAP_UNWILLING_TO_PERFORM;
+       int rc = modlist ? LDAP_UNWILLING_TO_PERFORM : LDAP_SUCCESS;
+       int is_oc = 0;
        Modification *mods = NULL;
 
        if (!acl_check_modlist(op, entry, modlist)) {
@@ -517,6 +518,9 @@ static int apply_modify_to_entry(Entry * entry,
        for (; modlist != NULL; modlist = modlist->sml_next) {
                mods = &modlist->sml_mod;
 
+               if ( mods->sm_desc == slap_schema.si_ad_objectClass ) {
+                       is_oc = 1;
+               }
                switch (mods->sm_op) {
                case LDAP_MOD_ADD:
                        rc = modify_add_values(entry, mods,
@@ -566,13 +570,14 @@ static int apply_modify_to_entry(Entry * entry,
        }
        
        if(rc == LDAP_SUCCESS) {
-               if ( mods->sm_desc == slap_schema.si_ad_objectClass ) {
+               if ( is_oc ) {
                        entry->e_ocflags = 0;
                }
                /* check that the entry still obeys the schema */
-               rc = entry_schema_check(op, entry, NULL, 0,
+               rc = entry_schema_check( op, entry, NULL, 0,
                          &rs->sr_text, textbuf, sizeof( textbuf ) );
        }
+
        return rc;
 }
 
@@ -596,7 +601,7 @@ ldif_back_referrals( Operation *op, SlapReply *rs )
        }
 
        ni = (struct ldif_info *)op->o_bd->be_private;
-       ldap_pvt_thread_mutex_lock( &ni->li_mutex );
+       ldap_pvt_thread_rdwr_rlock( &ni->li_rdwr );
        entry = (Entry *)get_entry( op, &ni->li_base_path );
 
        /* no object is found for them */
@@ -619,7 +624,7 @@ ldif_back_referrals( Operation *op, SlapReply *rs )
                        entry = (Entry *)get_entry( op, &ni->li_base_path );
                }
 
-               ldap_pvt_thread_mutex_unlock( &ni->li_mutex );
+               ldap_pvt_thread_rdwr_runlock( &ni->li_rdwr );
 
                op->o_req_dn = odn;
                op->o_req_ndn = ondn;
@@ -669,7 +674,7 @@ ldif_back_referrals( Operation *op, SlapReply *rs )
                return rc;
        }
 
-       ldap_pvt_thread_mutex_unlock( &ni->li_mutex );
+       ldap_pvt_thread_rdwr_runlock( &ni->li_rdwr );
 
        if ( is_entry_referral( entry ) ) {
                /* entry is a referral */
@@ -712,7 +717,7 @@ ldif_back_bind( Operation *op, SlapReply *rs )
        Entry * entry = NULL;
 
        ni = (struct ldif_info *) op->o_bd->be_private;
-       ldap_pvt_thread_mutex_lock(&ni->li_mutex);
+       ldap_pvt_thread_rdwr_rlock(&ni->li_rdwr);
        entry = (Entry *) get_entry(op, &ni->li_base_path);
 
        /* no object is found for them */
@@ -745,7 +750,7 @@ ldif_back_bind( Operation *op, SlapReply *rs )
        goto return_result;
 
  return_result:
-       ldap_pvt_thread_mutex_unlock(&ni->li_mutex);
+       ldap_pvt_thread_rdwr_runlock(&ni->li_rdwr);
        if(return_val != 0)
                send_ldap_result( op, rs );
        if(entry != NULL)
@@ -760,9 +765,9 @@ static int ldif_back_search(Operation *op, SlapReply *rs)
 
        ck.op = op;
        ck.rs = rs;
-       ldap_pvt_thread_mutex_lock(&ni->li_mutex);
+       ldap_pvt_thread_rdwr_rlock(&ni->li_rdwr);
        rs->sr_err = enum_tree( &ck );
-       ldap_pvt_thread_mutex_unlock(&ni->li_mutex);
+       ldap_pvt_thread_rdwr_runlock(&ni->li_rdwr);
        send_ldap_result(op, rs);
 
        return rs->sr_err;
@@ -784,7 +789,7 @@ static int ldif_back_add(Operation *op, SlapReply *rs) {
                &rs->sr_text, textbuf, sizeof( textbuf ) );
        if ( rs->sr_err != LDAP_SUCCESS ) goto send_res;
                                
-       ldap_pvt_thread_mutex_lock(&ni->li_mutex);
+       ldap_pvt_thread_rdwr_wlock(&ni->li_rdwr);
 
        dn2path(&dn, &op->o_bd->be_nsuffix[0], &ni->li_base_path, &leaf_path);
 
@@ -808,7 +813,7 @@ static int ldif_back_add(Operation *op, SlapReply *rs) {
                                        rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
                                        rs->sr_text = "Could not create parent folder";
                                        Debug( LDAP_DEBUG_ANY, "could not create folder \"%s\": %s\n",
-                                               base.bv_val, strerror( errno ), 0 );
+                                               base.bv_val, STRERROR( errno ), 0 );
                                }
                        }
                        else
@@ -824,7 +829,7 @@ static int ldif_back_add(Operation *op, SlapReply *rs) {
                        else if ( statres == -1 ) {
                                rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
                                Debug( LDAP_DEBUG_ANY, "could not stat file \"%s\": %s\n",
-                                       leaf_path.bv_val, strerror( errno ), 0 );
+                                       leaf_path.bv_val, STRERROR( errno ), 0 );
                        }
                        else /* it already exists */
                                rs->sr_err = LDAP_ALREADY_EXISTS;
@@ -833,11 +838,12 @@ static int ldif_back_add(Operation *op, SlapReply *rs) {
                SLAP_FREE(leaf_path.bv_val);
        }
 
-       ldap_pvt_thread_mutex_unlock(&ni->li_mutex);
+       ldap_pvt_thread_rdwr_wunlock(&ni->li_rdwr);
 
 send_res:
        Debug( LDAP_DEBUG_TRACE, 
-                       "ldif_back_add: err: %d text: %s\n", rs->sr_err, rs->sr_text, 0);
+                       "ldif_back_add: err: %d text: %s\n", rs->sr_err, rs->sr_text ?
+                               rs->sr_text : "", 0);
        send_ldap_result(op, rs);
        slap_graduate_commit_csn( op );
        return 0;
@@ -852,7 +858,7 @@ static int ldif_back_modify(Operation *op, SlapReply *rs) {
 
        slap_mods_opattrs( op, &op->orm_modlist, 1 );
 
-       ldap_pvt_thread_mutex_lock(&ni->li_mutex);
+       ldap_pvt_thread_rdwr_wlock(&ni->li_rdwr);
        dn2path(&op->o_req_ndn, &op->o_bd->be_nsuffix[0], &ni->li_base_path,
                &path);
        entry = (Entry *) get_entry(op, &ni->li_base_path);
@@ -868,7 +874,7 @@ static int ldif_back_modify(Operation *op, SlapReply *rs) {
                        if(spew_res == -1) {
                                Debug( LDAP_DEBUG_ANY,
                                        "%s ldif_back_modify: could not output entry \"%s\": %s\n",
-                                       op->o_log_prefix, entry->e_name.bv_val, strerror( save_errno ) );
+                                       op->o_log_prefix, entry->e_name.bv_val, STRERROR( save_errno ) );
                                rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
                        }
                }
@@ -882,7 +888,7 @@ static int ldif_back_modify(Operation *op, SlapReply *rs) {
        if(path.bv_val != NULL)
                SLAP_FREE(path.bv_val);
        rs->sr_text = NULL;
-       ldap_pvt_thread_mutex_unlock(&ni->li_mutex);
+       ldap_pvt_thread_rdwr_wunlock(&ni->li_rdwr);
        send_ldap_result(op, rs);
        slap_graduate_commit_csn( op );
        return 0;
@@ -902,7 +908,7 @@ static int ldif_back_delete(Operation *op, SlapReply *rs) {
                slap_get_csn( op, &csn, 1 );
        }
 
-       ldap_pvt_thread_mutex_lock(&ni->li_mutex);
+       ldap_pvt_thread_rdwr_wlock(&ni->li_rdwr);
        dn2path(&op->o_req_ndn, &op->o_bd->be_nsuffix[0], &ni->li_base_path, &path);
 
        path.bv_val[path.bv_len - STRLENOF(LDIF)] = '\0';
@@ -924,7 +930,7 @@ static int ldif_back_delete(Operation *op, SlapReply *rs) {
                rs->sr_err = LDAP_SUCCESS;
 
        SLAP_FREE(path.bv_val);
-       ldap_pvt_thread_mutex_unlock(&ni->li_mutex);
+       ldap_pvt_thread_rdwr_wunlock(&ni->li_rdwr);
        send_ldap_result(op, rs);
        slap_graduate_commit_csn( op );
        return 0;
@@ -949,6 +955,7 @@ static int move_entry(Entry * entry, struct berval * ndn,
        else { /* do the modrdn */
                exists_res = open(newpath.bv_val, O_RDONLY);
                if(exists_res == -1 && errno == ENOENT) {
+                       ldap_pvt_thread_mutex_lock( &entry2str_mutex );
                        res = spew_entry(entry, &newpath);
                        if(res != -1) {
                                /* if this fails we should log something bad */
@@ -962,6 +969,7 @@ static int move_entry(Entry * entry, struct berval * ndn,
                                        res = LDAP_UNWILLING_TO_PERFORM;
                                unlink(newpath.bv_val); /* in case file was created */
                        }
+                       ldap_pvt_thread_mutex_unlock( &entry2str_mutex );
                }
                else if(exists_res) {
                        int close_res = close(exists_res);
@@ -993,20 +1001,31 @@ ldif_back_modrdn(Operation *op, SlapReply *rs)
 
        slap_mods_opattrs( op, &op->orr_modlist, 1 );
 
-       ldap_pvt_thread_mutex_lock( &ni->li_mutex );
-       ldap_pvt_thread_mutex_lock( &entry2str_mutex );
+       ldap_pvt_thread_rdwr_wlock( &ni->li_rdwr );
        entry = (Entry *) get_entry( op, &ni->li_base_path );
 
        /* build the mods to the entry */
        if ( entry != NULL ) {
                /* build new dn, and new ndn for the entry */
                if ( op->oq_modrdn.rs_newSup != NULL ) {
+                       struct berval   op_dn = op->o_req_dn,
+                                       op_ndn = op->o_req_ndn;
+                       Entry           *np;
+
                        /* new superior */
                        p_dn = *op->oq_modrdn.rs_newSup;
+                       op->o_req_dn = *op->oq_modrdn.rs_newSup;
+                       op->o_req_ndn = *op->oq_modrdn.rs_nnewSup;
+                       np = (Entry *)get_entry( op, &ni->li_base_path );
+                       op->o_req_dn = op_dn;
+                       op->o_req_ndn = op_ndn;
+                       if ( np == NULL ) {
+                               goto no_such_object;
+                       }
+                       entry_free( np );
                } else {
-                       p_dn = slap_empty_bv;
+                       dnParent( &entry->e_name, &p_dn );
                }
-               dnParent( &entry->e_name, &p_dn );
                build_new_dn( &new_dn, &p_dn, &op->oq_modrdn.rs_newrdn, NULL ); 
                dnNormalize( 0, NULL, NULL, &new_dn, &new_ndn, NULL );
                ber_memfree_x( entry->e_name.bv_val, NULL );
@@ -1025,6 +1044,7 @@ ldif_back_modrdn(Operation *op, SlapReply *rs)
                        rs->sr_err = res;
                }
        } else {
+no_such_object:;
                /* entry was null */
                rs->sr_err = LDAP_NO_SUCH_OBJECT;
        }
@@ -1033,8 +1053,7 @@ ldif_back_modrdn(Operation *op, SlapReply *rs)
                entry_free( entry );
        }
        rs->sr_text = "";
-       ldap_pvt_thread_mutex_unlock( &ni->li_mutex );
-       ldap_pvt_thread_mutex_unlock( &entry2str_mutex );
+       ldap_pvt_thread_rdwr_wunlock( &ni->li_rdwr );
        send_ldap_result( op, rs );
        slap_graduate_commit_csn( op );
        return 0;
@@ -1056,13 +1075,13 @@ int ldif_back_entry_get(
        assert( ndn != NULL );
        assert( !BER_BVISNULL( ndn ) );
 
-       ldap_pvt_thread_mutex_lock( &ni->li_mutex );
+       ldap_pvt_thread_rdwr_rlock( &ni->li_rdwr );
        op->o_req_dn = *ndn;
        op->o_req_ndn = *ndn;
        *ent = (Entry *) get_entry( op, &ni->li_base_path );
        op->o_req_dn = op_dn;
        op->o_req_ndn = op_ndn;
-       ldap_pvt_thread_mutex_unlock( &ni->li_mutex );
+       ldap_pvt_thread_rdwr_runlock( &ni->li_rdwr );
 
        if ( *ent && oc && !is_entry_objectclass_or_sub( *ent, oc ) ) {
                entry_free( *ent );
@@ -1188,7 +1207,7 @@ ldif_back_db_init( BackendDB *be )
        ni = ch_calloc( 1, sizeof(struct ldif_info) );
        be->be_private = ni;
        be->be_cf_ocs = ldifocs;
-       ldap_pvt_thread_mutex_init(&ni->li_mutex);
+       ldap_pvt_thread_rdwr_init(&ni->li_rdwr);
        return 0;
 }
 
@@ -1200,7 +1219,7 @@ ldif_back_db_destroy(
        struct ldif_info *ni = be->be_private;
 
        ch_free(ni->li_base_path.bv_val);
-       ldap_pvt_thread_mutex_destroy(&ni->li_mutex);
+       ldap_pvt_thread_rdwr_destroy(&ni->li_rdwr);
        free( be->be_private );
        return 0;
 }
index 2b089583742fc88de2ad7b87d6acd7c4e9588099..02a0093d5c9d65ec4a329ba58c1626e3076498f5 100644 (file)
@@ -63,7 +63,7 @@ meta_back_add( Operation *op, SlapReply *rs )
        /*
         * Rewrite the add dn, if needed
         */
-       dc.target = &mi->mi_targets[ candidate ];
+       dc.target = mi->mi_targets[ candidate ];
        dc.conn = op->o_conn;
        dc.rs = rs;
        dc.ctx = "addDN";
@@ -96,7 +96,7 @@ meta_back_add( Operation *op, SlapReply *rs )
                        mapped = a->a_desc->ad_cname;
 
                } else {
-                       ldap_back_map( &mi->mi_targets[ candidate ].mt_rwmap.rwm_at,
+                       ldap_back_map( &mi->mi_targets[ candidate ]->mt_rwmap.rwm_at,
                                        &a->a_desc->ad_cname, &mapped, BACKLDAP_MAP );
                        if ( BER_BVISNULL( &mapped ) || BER_BVISEMPTY( &mapped ) ) {
                                continue;
@@ -121,11 +121,11 @@ meta_back_add( Operation *op, SlapReply *rs )
                        for ( j = 0; !BER_BVISNULL( &a->a_vals[ j ] ); ) {
                                struct ldapmapping      *mapping;
 
-                               ldap_back_mapping( &mi->mi_targets[ candidate ].mt_rwmap.rwm_oc,
+                               ldap_back_mapping( &mi->mi_targets[ candidate ]->mt_rwmap.rwm_oc,
                                                &a->a_vals[ j ], &mapping, BACKLDAP_MAP );
 
                                if ( mapping == NULL ) {
-                                       if ( mi->mi_targets[ candidate ].mt_rwmap.rwm_oc.drop_missing ) {
+                                       if ( mi->mi_targets[ candidate ]->mt_rwmap.rwm_oc.drop_missing ) {
                                                continue;
                                        }
                                        attrs[ i ]->mod_bvalues[ j ] = &a->a_vals[ j ];
@@ -180,8 +180,8 @@ retry:;
                LDAPMessage     *res = NULL;
                int             rc;
 
-               if ( mi->mi_targets[ candidate ].mt_timeout[ LDAP_BACK_OP_ADD ] != 0 ) {
-                       tv.tv_sec = mi->mi_targets[ candidate ].mt_timeout[ LDAP_BACK_OP_ADD ];
+               if ( mi->mi_targets[ candidate ]->mt_timeout[ LDAP_BACK_OP_ADD ] != 0 ) {
+                       tv.tv_sec = mi->mi_targets[ candidate ]->mt_timeout[ LDAP_BACK_OP_ADD ];
                        tv.tv_usec = 0;
                        tvp = &tv;
                }
index cfb7790d81236d2b2b9700e368ad37acb7900cd8..0516f619f3ba3d27546664dd73d574f80b4f159d 100644 (file)
@@ -199,6 +199,14 @@ typedef struct metaconn_t {
 
 typedef struct metatarget_t {
        char                    *mt_uri;
+       ldap_pvt_thread_mutex_t mt_uri_mutex;
+
+       /* TODO: we might want to enable different strategies
+        * for different targets */
+       LDAP_REBIND_PROC        *mt_rebind_f;
+       LDAP_URLLIST_PROC       *mt_urllist_f;
+       void                    *mt_urllist_p;
+
        BerVarray               mt_subtree_exclude;
        int                     mt_scope;
 
@@ -247,9 +255,12 @@ typedef struct metainfo_t {
 #define META_DEFAULT_TARGET_NONE       (-1)
        int                     mi_nretries;
 
-       metatarget_t            *mi_targets;
+       metatarget_t            **mi_targets;
        metacandidates_t        *mi_candidates;
 
+       LDAP_REBIND_PROC        *mi_rebind_f;
+       LDAP_URLLIST_PROC       *mi_urllist_f;
+
        metadncache_t           mi_cache;
        
        ldap_avl_info_t         mi_conninfo;
@@ -257,8 +268,8 @@ typedef struct metainfo_t {
        unsigned                mi_flags;
 #define        li_flags                mi_flags
 /* uses flags as defined in <back-ldap/back-ldap.h> */
-#define        META_BACK_F_ONERR_STOP          0x00010000U
-#define        META_BACK_F_DEFER_ROOTDN_BIND   0x00020000U
+#define        META_BACK_F_ONERR_STOP          (0x00010000U)
+#define        META_BACK_F_DEFER_ROOTDN_BIND   (0x00020000U)
 
 #define        META_BACK_ONERR_STOP(mi)        ( (mi)->mi_flags & META_BACK_F_ONERR_STOP )
 #define        META_BACK_ONERR_CONTINUE(mi)    ( !META_BACK_ONERR_CONTINUE( (mi) ) )
@@ -434,7 +445,8 @@ meta_dncache_delete_entry(
 extern void
 meta_dncache_free( void *entry );
 
-extern LDAP_REBIND_PROC                *meta_back_rebind_f;
+extern LDAP_REBIND_PROC                meta_back_default_rebind;
+extern LDAP_URLLIST_PROC       meta_back_default_urllist;
 
 LDAP_END_DECL
 
index 1993e4aeb148c271017667f487315b5df6be25d8..9b654c75842305f78ba2e5b3c1087a81e224f5b9 100644 (file)
 #include "../back-ldap/back-ldap.h"
 #include "back-meta.h"
 
-static LDAP_REBIND_PROC        meta_back_default_rebind;
-
-/*
- * a module could register a replacement for this function
- */
-LDAP_REBIND_PROC       *meta_back_rebind_f = meta_back_default_rebind;
-
 int
 meta_back_bind( Operation *op, SlapReply *rs )
 {
@@ -115,6 +108,7 @@ meta_back_bind( Operation *op, SlapReply *rs )
         */
        mc->mc_authz_target = META_BOUND_NONE;
        for ( i = 0; i < mi->mi_ntargets; i++ ) {
+               metatarget_t    *mt = mi->mi_targets[ i ];
                int             lerr;
                Operation       op2 = *op;
                int             massage = 1;
@@ -144,7 +138,7 @@ meta_back_bind( Operation *op, SlapReply *rs )
                }
 
                if ( isroot ) {
-                       if ( BER_BVISNULL( &mi->mi_targets[ i ].mt_pseudorootdn ) )
+                       if ( BER_BVISNULL( &mt->mt_pseudorootdn ) )
                        {
                                metasingleconn_t        *msc = &mc->mc_conns[ i ];
 
@@ -167,9 +161,9 @@ meta_back_bind( Operation *op, SlapReply *rs )
                                continue;
                        }
 
-                       op2.o_req_dn = mi->mi_targets[ i ].mt_pseudorootdn;
-                       op2.o_req_ndn = mi->mi_targets[ i ].mt_pseudorootdn;
-                       op2.orb_cred = mi->mi_targets[ i ].mt_pseudorootpw;
+                       op2.o_req_dn = mt->mt_pseudorootdn;
+                       op2.o_req_ndn = mt->mt_pseudorootdn;
+                       op2.orb_cred = mt->mt_pseudorootpw;
                        op2.orb_method = LDAP_AUTH_SIMPLE;
 
                        massage = 0;
@@ -213,7 +207,33 @@ retry_lock:;
                                meta_back_conndn_cmp );
                        assert( tmpmc == mc );
 
+                       /* delete all cached connections with the current connection */
+                       if ( LDAP_BACK_SINGLECONN( mi ) ) {
+                               while ( ( tmpmc = avl_delete( &mi->mi_conninfo.lai_tree, (caddr_t)mc, meta_back_conn_cmp ) ) != NULL )
+                               {
+                                       Debug( LDAP_DEBUG_TRACE,
+                                               "=>meta_back_bind: destroying conn %ld (refcnt=%u)\n",
+                                               LDAP_BACK_PCONN_ID( mc->mc_conn ), mc->mc_refcnt, 0 );
+
+                                       if ( mc->mc_refcnt != 0 ) {
+                                               /* taint it */
+                                               LDAP_BACK_CONN_TAINTED_SET( tmpmc );
+
+                                       } else {
+                                               /*
+                                                * Needs a test because the handler may be corrupted,
+                                                * and calling ldap_unbind on a corrupted header results
+                                                * in a segmentation fault
+                                                */
+                                               meta_back_conn_free( tmpmc );
+                                       }
+                               }
+                       }
+
                        ber_bvreplace( &mc->mc_local_ndn, &op->o_req_ndn );
+                       if ( be_isroot_dn( op->o_bd, &op->o_req_ndn ) ) {
+                               mc->mc_conn = LDAP_BACK_PCONN_SET( op );
+                       }
                        lerr = avl_insert( &mi->mi_conninfo.lai_tree, (caddr_t)mc,
                                meta_back_conndn_cmp, meta_back_conndn_dup );
                        ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
@@ -274,7 +294,7 @@ meta_back_single_bind(
        int                     massage )
 {
        metainfo_t              *mi = ( metainfo_t * )op->o_bd->be_private;
-       metatarget_t            *mt = &mi->mi_targets[ candidate ];
+       metatarget_t            *mt = mi->mi_targets[ candidate ];
        struct berval           mdn = BER_BVNULL;
        metasingleconn_t        *msc = &mc->mc_conns[ candidate ];
        int                     msgid,
@@ -418,7 +438,7 @@ retry:;
 
        if ( LDAP_BACK_SAVECRED( mi ) ) {
                ber_bvreplace( &msc->msc_cred, &op->orb_cred );
-               ldap_set_rebind_proc( msc->msc_ld, meta_back_rebind_f, msc );
+               ldap_set_rebind_proc( msc->msc_ld, mt->mt_rebind_f, msc );
        }
 
        if ( mi->mi_cache.ttl != META_DNCACHE_DISABLED
@@ -450,7 +470,7 @@ meta_back_single_dobind(
        int                     dolock )
 {
        metainfo_t              *mi = ( metainfo_t * )op->o_bd->be_private;
-       metatarget_t            *mt = &mi->mi_targets[ candidate ];
+       metatarget_t            *mt = mi->mi_targets[ candidate ];
        metaconn_t              *mc = *mcp;
        metasingleconn_t        *msc = &mc->mc_conns[ candidate ];
        int                     rc;
@@ -465,14 +485,14 @@ meta_back_single_dobind(
         * meta_back_single_dobind() calls meta_back_single_bind()
         * if required.
         */
-       if ( be_isroot( op ) && !BER_BVISNULL( &mi->mi_targets[ candidate ].mt_pseudorootdn ) )
+       if ( be_isroot( op ) && !BER_BVISNULL( &mt->mt_pseudorootdn ) )
        {
                Operation       op2 = *op;
 
                op2.o_tag = LDAP_REQ_BIND;
-               op2.o_req_dn = mi->mi_targets[ candidate ].mt_pseudorootdn;
-               op2.o_req_ndn = mi->mi_targets[ candidate ].mt_pseudorootdn;
-               op2.orb_cred = mi->mi_targets[ candidate ].mt_pseudorootpw;
+               op2.o_req_dn = mt->mt_pseudorootdn;
+               op2.o_req_ndn = mt->mt_pseudorootdn;
+               op2.orb_cred = mt->mt_pseudorootpw;
                op2.orb_method = LDAP_AUTH_SIMPLE;
 
                rc = meta_back_single_bind( &op2, rs, *mcp, candidate, 0 );
@@ -577,7 +597,9 @@ retry:;
                                                mt, mc, candidate,
                                                LDAP_BACK_CONN_ISPRIV( mc ),
                                                LDAP_BACK_DONTSEND );
-                                       LDAP_BACK_CONN_BINDING_SET( msc );
+                                       if ( rc == LDAP_SUCCESS ) {
+                                               LDAP_BACK_CONN_BINDING_SET( msc );
+                                       }
 
                                } else {
                                        /* can't do anything about it */
@@ -665,7 +687,7 @@ meta_back_dobind(
        }
 
        for ( i = 0; i < mi->mi_ntargets; i++ ) {
-               metatarget_t            *mt = &mi->mi_targets[ i ];
+               metatarget_t            *mt = mi->mi_targets[ i ];
                metasingleconn_t        *msc = &mc->mc_conns[ i ];
                int                     rc, do_retry = 1;
 
@@ -721,9 +743,12 @@ retry:;
                                if ( meta_back_retry( op, rs, &mc, i, sendok ) ) {
                                        goto retry;
                                }
-                               ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex );
-                               LDAP_BACK_CONN_BINDING_CLEAR( msc );
-                               ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
+
+                               if ( mc != NULL ) {
+                                       ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex );
+                                       LDAP_BACK_CONN_BINDING_CLEAR( msc );
+                                       ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
+                               }
 
                                return 0;
                        }
@@ -802,7 +827,7 @@ send_err:;
  * This is a callback used for chasing referrals using the same
  * credentials as the original user on this session.
  */
-static int 
+int 
 meta_back_default_rebind(
        LDAP                    *ld,
        LDAP_CONST char         *url,
@@ -817,6 +842,43 @@ meta_back_default_rebind(
                        NULL, NULL, NULL );
 }
 
+/*
+ * meta_back_default_urllist
+ *
+ * This is a callback used for mucking with the urllist
+ */
+int 
+meta_back_default_urllist(
+       LDAP            *ld,
+       LDAPURLDesc     **urllist,
+       LDAPURLDesc     **url,
+       void            *params )
+{
+       metatarget_t    *mt = (metatarget_t *)params;
+       LDAPURLDesc     **urltail;
+
+       if ( urllist == url ) {
+               return LDAP_SUCCESS;
+       }
+
+       for ( urltail = &(*url)->lud_next; *urltail; urltail = &(*urltail)->lud_next )
+               /* count */ ;
+
+       *urltail = *urllist;
+       *urllist = *url;
+       *url = NULL;
+
+       ldap_pvt_thread_mutex_lock( &mt->mt_uri_mutex );
+       if ( mt->mt_uri ) {
+               ch_free( mt->mt_uri );
+       }
+
+       ldap_get_option( ld, LDAP_OPT_URI, (void *)&mt->mt_uri );
+       ldap_pvt_thread_mutex_unlock( &mt->mt_uri_mutex );
+
+       return LDAP_SUCCESS;
+}
+
 /*
  * FIXME: error return must be handled in a cleaner way ...
  */
@@ -837,6 +899,8 @@ meta_back_op_result(
                                *save_rmatch = NULL;
        void                    *rmatch_ctx = NULL;
 
+       assert( mc != NULL );
+
        if ( candidate != META_TARGET_NONE ) {
                metasingleconn_t        *msc = &mc->mc_conns[ candidate ];
 
index 794d1b3a471a80289ee7da64b0f055482d216210..27d3c2eaa16f4a6b0b5f280df29ce98ff92bad6b 100644 (file)
@@ -136,10 +136,12 @@ meta_back_select_unique_candidate(
 {
        int     i, candidate = META_TARGET_NONE;
 
-       for ( i = 0; i < mi->mi_ntargets; ++i ) {
-               if ( meta_back_is_candidate( &mi->mi_targets[ i ].mt_nsuffix,
-                               mi->mi_targets[ i ].mt_scope,
-                               mi->mi_targets[ i ].mt_subtree_exclude,
+       for ( i = 0; i < mi->mi_ntargets; i++ ) {
+               metatarget_t    *mt = mi->mi_targets[ i ];
+
+               if ( meta_back_is_candidate( &mt->mt_nsuffix,
+                               mt->mt_scope,
+                               mt->mt_subtree_exclude,
                                ndn, LDAP_SCOPE_BASE ) )
                {
                        if ( candidate == META_TARGET_NONE ) {
index 556984786c5b816ee10b31135be1b080f861aa06..cd6815bee7e3e5418fc2d54278f8bed1918f3d60 100644 (file)
@@ -83,7 +83,7 @@ meta_back_compare( Operation *op, SlapReply *rs )
                /*
                 * Rewrite the compare dn, if needed
                 */
-               dc.target = &mi->mi_targets[ i ];
+               dc.target = mi->mi_targets[ i ];
 
                switch ( ldap_back_dn_massage( &dc, &op->o_req_dn, &mdn ) ) {
                case LDAP_UNWILLING_TO_PERFORM:
@@ -98,7 +98,7 @@ meta_back_compare( Operation *op, SlapReply *rs )
                 * if attr is objectClass, try to remap the value
                 */
                if ( op->orc_ava->aa_desc == slap_schema.si_ad_objectClass ) {
-                       ldap_back_map( &mi->mi_targets[ i ].mt_rwmap.rwm_oc,
+                       ldap_back_map( &mi->mi_targets[ i ]->mt_rwmap.rwm_oc,
                                        &op->orc_ava->aa_value,
                                        &mapped_value, BACKLDAP_MAP );
 
@@ -109,7 +109,7 @@ meta_back_compare( Operation *op, SlapReply *rs )
                 * else try to remap the attribute
                 */
                } else {
-                       ldap_back_map( &mi->mi_targets[ i ].mt_rwmap.rwm_at,
+                       ldap_back_map( &mi->mi_targets[ i ]->mt_rwmap.rwm_at,
                                &op->orc_ava->aa_desc->ad_cname,
                                &mapped_attr, BACKLDAP_MAP );
                        if ( BER_BVISNULL( &mapped_attr ) || mapped_attr.bv_val[0] == '\0' ) {
index 822a352a4ce2ee6d5b3ea686de9417e5a01b6eae..abd351e70d469e49b59faba317379b604f994a91 100644 (file)
 
 static int
 meta_back_new_target( 
-       metatarget_t    *mt )
+       metatarget_t    **mtp )
 {
         struct ldapmapping     *mapping;
        char                    *rargv[ 3 ];
+       metatarget_t            *mt;
 
-       memset( mt, 0, sizeof( metatarget_t ) );
+       *mtp = NULL;
+
+       mt = ch_calloc( sizeof( metatarget_t ), 1 );
 
        mt->mt_rwmap.rwm_rw = rewrite_info_init( REWRITE_MODE_USE_DEFAULT );
        if ( mt->mt_rwmap.rwm_rw == NULL ) {
-                return -1;
+               ch_free( mt );
+               return -1;
        }
 
 
@@ -66,6 +70,10 @@ meta_back_new_target(
 
        ldap_back_map_init( &mt->mt_rwmap.rwm_at, &mapping );
 
+       ldap_pvt_thread_mutex_init( &mt->mt_uri_mutex );
+
+       *mtp = mt;
+
        return 0;
 }
 
@@ -107,6 +115,8 @@ meta_back_db_config(
                struct berval   dn;
                int             rc;
                int             c;
+
+               metatarget_t    *mt;
                
                switch ( argc ) {
                case 1:
@@ -136,8 +146,8 @@ meta_back_db_config(
                
                ++mi->mi_ntargets;
 
-               mi->mi_targets = ( metatarget_t * )ch_realloc( mi->mi_targets, 
-                       sizeof( metatarget_t ) * mi->mi_ntargets );
+               mi->mi_targets = ( metatarget_t ** )ch_realloc( mi->mi_targets, 
+                       sizeof( metatarget_t ) * mi->mi_ntargets );
                if ( mi->mi_targets == NULL ) {
                        Debug( LDAP_DEBUG_ANY,
        "%s: line %d: out of memory while storing server name"
@@ -154,19 +164,27 @@ meta_back_db_config(
                        return 1;
                }
 
-               mi->mi_targets[ i ].mt_nretries = mi->mi_nretries;
-               mi->mi_targets[ i ].mt_flags = mi->mi_flags;
-               mi->mi_targets[ i ].mt_version = mi->mi_version;
-               mi->mi_targets[ i ].mt_network_timeout = mi->mi_network_timeout;
-               mi->mi_targets[ i ].mt_bind_timeout = mi->mi_bind_timeout;
+               mt = mi->mi_targets[ i ];
+
+               mt->mt_rebind_f = mi->mi_rebind_f;
+               mt->mt_urllist_f = mi->mi_urllist_f;
+               mt->mt_urllist_p = mt;
+
+               mt->mt_nretries = mi->mi_nretries;
+               mt->mt_flags = mi->mi_flags;
+               mt->mt_version = mi->mi_version;
+               mt->mt_network_timeout = mi->mi_network_timeout;
+               mt->mt_bind_timeout = mi->mi_bind_timeout;
                for ( c = 0; c < LDAP_BACK_OP_LAST; c++ ) {
-                       mi->mi_targets[ i ].mt_timeout[ c ] = mi->mi_timeout[ c ];
+                       mt->mt_timeout[ c ] = mi->mi_timeout[ c ];
                }
 
                /*
                 * uri MUST be legal!
                 */
-               if ( ldap_url_parselist_ext( &ludp, argv[ 1 ], "\t" ) != LDAP_SUCCESS ) {
+               if ( ldap_url_parselist_ext( &ludp, argv[ 1 ], "\t",
+                       LDAP_PVT_URL_PARSE_NONE ) != LDAP_SUCCESS )
+               {
                        Debug( LDAP_DEBUG_ANY,
        "%s: line %d: unable to parse URI"
        " in \"uri <protocol>://<server>[:port]/<naming context>\" line\n",
@@ -206,8 +224,8 @@ meta_back_db_config(
                 * copies and stores uri and suffix
                 */
                ber_str2bv( ludp->lud_dn, 0, 0, &dn );
-               rc = dnPrettyNormal( NULL, &dn, &mi->mi_targets[ i ].mt_psuffix,
-                       &mi->mi_targets[ i ].mt_nsuffix, NULL );
+               rc = dnPrettyNormal( NULL, &dn, &mt->mt_psuffix,
+                       &mt->mt_nsuffix, NULL );
                if( rc != LDAP_SUCCESS ) {
                        Debug( LDAP_DEBUG_ANY, "%s: line %d: "
                                "target \"%s\" DN is invalid\n",
@@ -219,12 +237,12 @@ meta_back_db_config(
 
                switch ( ludp->lud_scope ) {
                case LDAP_SCOPE_DEFAULT:
-                       mi->mi_targets[ i ].mt_scope = LDAP_SCOPE_SUBTREE;
+                       mt->mt_scope = LDAP_SCOPE_SUBTREE;
                        break;
 
                case LDAP_SCOPE_SUBTREE:
                case LDAP_SCOPE_SUBORDINATE:
-                       mi->mi_targets[ i ].mt_scope = ludp->lud_scope;
+                       mt->mt_scope = ludp->lud_scope;
                        break;
 
                default:
@@ -246,9 +264,9 @@ meta_back_db_config(
                        }
                }
 
-               mi->mi_targets[ i ].mt_uri = ldap_url_list2urls( ludp );
+               mt->mt_uri = ldap_url_list2urls( ludp );
                ldap_free_urllist( ludp );
-               if ( mi->mi_targets[ i ].mt_uri == NULL) {
+               if ( mt->mt_uri == NULL) {
                        Debug( LDAP_DEBUG_ANY, "%s: line %d: no memory?\n",
                                fname, lineno, 0 );
                        return( 1 );
@@ -258,7 +276,7 @@ meta_back_db_config(
                 * uri MUST be a branch of suffix!
                 */
 #if 0 /* too strict a constraint */
-               if ( select_backend( &mi->mi_targets[ i ].suffix, 0, 0 ) != be ) {
+               if ( select_backend( &mt->mt_nsuffix, 0, 0 ) != be ) {
                        Debug( LDAP_DEBUG_ANY,
        "%s: line %d: <naming context> of URI does not refer to current backend"
        " in \"uri <protocol>://<server>[:port]/<naming context>\" line\n",
@@ -269,7 +287,7 @@ meta_back_db_config(
                /*
                 * uri MUST be a branch of a suffix!
                 */
-               if ( select_backend( &mi->mi_targets[ i ].mt_nsuffix, 0, 0 ) == NULL ) {
+               if ( select_backend( &mt->mt_nsuffix, 0, 0 ) == NULL ) {
                        Debug( LDAP_DEBUG_ANY,
        "%s: line %d: <naming context> of URI does not resolve to a backend"
        " in \"uri <protocol>://<server>[:port]/<naming context>\" line\n",
@@ -317,7 +335,7 @@ meta_back_db_config(
                        return( 1 );
                }
 
-               if ( !dnIsSuffix( &ndn, &mi->mi_targets[ i ].mt_nsuffix ) ) {
+               if ( !dnIsSuffix( &ndn, &mi->mi_targets[ i ]->mt_nsuffix ) ) {
                        Debug( LDAP_DEBUG_ANY, "%s: line %d: "
                                        "subtree-exclude DN=\"%s\" "
                                        "must be subtree of target\n",
@@ -326,12 +344,12 @@ meta_back_db_config(
                        return( 1 );
                }
 
-               if ( mi->mi_targets[ i ].mt_subtree_exclude != NULL ) {
+               if ( mi->mi_targets[ i ]->mt_subtree_exclude != NULL ) {
                        int             j;
 
-                       for ( j = 0; !BER_BVISNULL( &mi->mi_targets[ i ].mt_subtree_exclude[ j ] ); j++ )
+                       for ( j = 0; !BER_BVISNULL( &mi->mi_targets[ i ]->mt_subtree_exclude[ j ] ); j++ )
                        {
-                               if ( dnIsSuffix( &mi->mi_targets[ i ].mt_subtree_exclude[ j ], &ndn ) ) {
+                               if ( dnIsSuffix( &mi->mi_targets[ i ]->mt_subtree_exclude[ j ], &ndn ) ) {
                                        Debug( LDAP_DEBUG_ANY, "%s: line %d: "
                                                        "subtree-exclude DN=\"%s\" "
                                                        "is suffix of another subtree-exclude\n",
@@ -341,7 +359,7 @@ meta_back_db_config(
                                        ber_memfree( ndn.bv_val );
                                        return( 1 );
 
-                               } else if ( dnIsSuffix( &ndn, &mi->mi_targets[ i ].mt_subtree_exclude[ j ] ) ) {
+                               } else if ( dnIsSuffix( &ndn, &mi->mi_targets[ i ]->mt_subtree_exclude[ j ] ) ) {
                                        Debug( LDAP_DEBUG_ANY, "%s: line %d: "
                                                        "another subtree-exclude is suffix of "
                                                        "subtree-exclude DN=\"%s\"\n",
@@ -352,7 +370,7 @@ meta_back_db_config(
                        }
                }
 
-               ber_bvarray_add( &mi->mi_targets[ i ].mt_subtree_exclude, &ndn );
+               ber_bvarray_add( &mi->mi_targets[ i ]->mt_subtree_exclude, &ndn );
 
        /* default target directive */
        } else if ( strcasecmp( argv[ 0 ], "default-target" ) == 0 ) {
@@ -423,7 +441,7 @@ meta_back_db_config(
        } else if ( strcasecmp( argv[ 0 ], "network-timeout" ) == 0 ) {
                unsigned long   t;
                time_t          *tp = mi->mi_ntargets ?
-                               &mi->mi_targets[ mi->mi_ntargets - 1 ].mt_network_timeout
+                               &mi->mi_targets[ mi->mi_ntargets - 1 ]->mt_network_timeout
                                : &mi->mi_network_timeout;
 
                if ( argc != 2 ) {
@@ -505,7 +523,7 @@ meta_back_db_config(
        } else if ( strcasecmp( argv[ 0 ], "bind-timeout" ) == 0 ) {
                unsigned long   t;
                struct timeval  *tp = mi->mi_ntargets ?
-                               &mi->mi_targets[ mi->mi_ntargets - 1 ].mt_bind_timeout
+                               &mi->mi_targets[ mi->mi_ntargets - 1 ]->mt_bind_timeout
                                : &mi->mi_bind_timeout;
 
                switch ( argc ) {
@@ -564,7 +582,7 @@ meta_back_db_config(
                }
 
                ber_str2bv( argv[ 1 ], 0, 0, &dn );
-               if ( dnNormalize( 0, NULL, NULL, &dn, &mi->mi_targets[ i ].mt_binddn,
+               if ( dnNormalize( 0, NULL, NULL, &dn, &mi->mi_targets[ i ]->mt_binddn,
                        NULL ) != LDAP_SUCCESS )
                {
                        Debug( LDAP_DEBUG_ANY, "%s: line %d: "
@@ -601,7 +619,7 @@ meta_back_db_config(
                        /* FIXME: some day we'll need to throw an error */
                }
 
-               ber_str2bv( argv[ 1 ], 0L, 1, &mi->mi_targets[ i ].mt_bindpw );
+               ber_str2bv( argv[ 1 ], 0L, 1, &mi->mi_targets[ i ]->mt_bindpw );
                
        /* save bind creds for referral rebinds? */
        } else if ( strcasecmp( argv[ 0 ], "rebind-as-user" ) == 0 ) {
@@ -638,7 +656,7 @@ meta_back_db_config(
 
        } else if ( strcasecmp( argv[ 0 ], "chase-referrals" ) == 0 ) {
                unsigned        *flagsp = mi->mi_ntargets ?
-                               &mi->mi_targets[ mi->mi_ntargets - 1 ].mt_flags
+                               &mi->mi_targets[ mi->mi_ntargets - 1 ]->mt_flags
                                : &mi->mi_flags;
 
                if ( argc != 2 ) {
@@ -667,7 +685,7 @@ meta_back_db_config(
        
        } else if ( strcasecmp( argv[ 0 ], "tls" ) == 0 ) {
                unsigned        *flagsp = mi->mi_ntargets ?
-                               &mi->mi_targets[ mi->mi_ntargets - 1 ].mt_flags
+                               &mi->mi_targets[ mi->mi_ntargets - 1 ]->mt_flags
                                : &mi->mi_flags;
 
                if ( argc != 2 ) {
@@ -704,7 +722,7 @@ meta_back_db_config(
 
        } else if ( strcasecmp( argv[ 0 ], "t-f-support" ) == 0 ) {
                unsigned        *flagsp = mi->mi_ntargets ?
-                               &mi->mi_targets[ mi->mi_ntargets - 1 ].mt_flags
+                               &mi->mi_targets[ mi->mi_ntargets - 1 ]->mt_flags
                                : &mi->mi_flags;
 
                if ( argc != 2 ) {
@@ -783,10 +801,42 @@ meta_back_db_config(
                        return 1;
                }
 
+       /* single-conn? */
+       } else if ( strcasecmp( argv[ 0 ], "single-conn" ) == 0 ) {
+               if ( argc != 2 ) {
+                       Debug( LDAP_DEBUG_ANY,
+       "%s: line %d: \"single-conn {FALSE|true}\" takes 1 argument\n",
+                               fname, lineno, 0 );
+                       return( 1 );
+               }
+
+               if ( mi->mi_ntargets > 0 ) {
+                       Debug( LDAP_DEBUG_ANY,
+       "%s: line %d: \"single-conn\" must appear before target definitions\n",
+                               fname, lineno, 0 );
+                       return( 1 );
+               }
+
+               switch ( check_true_false( argv[ 1 ] ) ) {
+               case 0:
+                       mi->mi_flags &= ~LDAP_BACK_F_SINGLECONN;
+                       break;
+
+               case 1:
+                       mi->mi_flags |= LDAP_BACK_F_SINGLECONN;
+                       break;
+
+               default:
+                       Debug( LDAP_DEBUG_ANY,
+       "%s: line %d: \"single-conn {FALSE|true}\": invalid arg \"%s\".\n",
+                               fname, lineno, argv[ 1 ] );
+                       return 1;
+               }
+
        } else if ( strcasecmp( argv[ 0 ], "timeout" ) == 0 ) {
                char    *sep;
                time_t  *tv = mi->mi_ntargets ?
-                               mi->mi_targets[ mi->mi_ntargets - 1 ].mt_timeout
+                               mi->mi_targets[ mi->mi_ntargets - 1 ]->mt_timeout
                                : mi->mi_timeout;
                int     c;
 
@@ -870,7 +920,7 @@ meta_back_db_config(
                dn.bv_val = argv[ 1 ];
                dn.bv_len = strlen( argv[ 1 ] );
                if ( dnNormalize( 0, NULL, NULL, &dn,
-                       &mi->mi_targets[ i ].mt_pseudorootdn, NULL ) != LDAP_SUCCESS )
+                       &mi->mi_targets[ i ]->mt_pseudorootdn, NULL ) != LDAP_SUCCESS )
                {
                        Debug( LDAP_DEBUG_ANY, "%s: line %d: "
                                        "pseudoroot DN '%s' is invalid\n",
@@ -895,7 +945,7 @@ meta_back_db_config(
                            fname, lineno, 0 );
                        return 1;
                }
-               ber_str2bv( argv[ 1 ], 0L, 1, &mi->mi_targets[ i ].mt_pseudorootpw );
+               ber_str2bv( argv[ 1 ], 0L, 1, &mi->mi_targets[ i ]->mt_pseudorootpw );
        
        /* dn massaging */
        } else if ( strcasecmp( argv[ 0 ], "suffixmassage" ) == 0 ) {
@@ -978,7 +1028,7 @@ meta_back_db_config(
                 * FIXME: no extra rewrite capabilities should be added
                 * to the database
                 */
-               rc = suffix_massage_config( mi->mi_targets[ i ].mt_rwmap.rwm_rw,
+               rc = suffix_massage_config( mi->mi_targets[ i ]->mt_rwmap.rwm_rw,
                                &pvnc, &nvnc, &prnc, &nrnc );
 
                free( pvnc.bv_val );
@@ -999,7 +1049,7 @@ meta_back_db_config(
                        return 1;
                }
                
-               return rewrite_parse( mi->mi_targets[ i ].mt_rwmap.rwm_rw,
+               return rewrite_parse( mi->mi_targets[ i ]->mt_rwmap.rwm_rw,
                                fname, lineno, argc, argv );
 
        /* objectclass/attribute mapping */
@@ -1013,8 +1063,8 @@ meta_back_db_config(
                        return 1;
                }
 
-               return ldap_back_map_config( &mi->mi_targets[ i ].mt_rwmap.rwm_oc, 
-                               &mi->mi_targets[ i ].mt_rwmap.rwm_at,
+               return ldap_back_map_config( &mi->mi_targets[ i ]->mt_rwmap.rwm_oc, 
+                               &mi->mi_targets[ i ]->mt_rwmap.rwm_at,
                                fname, lineno, argc, argv );
 
        } else if ( strcasecmp( argv[ 0 ], "nretries" ) == 0 ) {
@@ -1047,12 +1097,12 @@ meta_back_db_config(
                        mi->mi_nretries = nretries;
 
                } else {
-                       mi->mi_targets[ i ].mt_nretries = nretries;
+                       mi->mi_targets[ i ]->mt_nretries = nretries;
                }
 
        } else if ( strcasecmp( argv[ 0 ], "protocol-version" ) == 0 ) {
                int     *version = mi->mi_ntargets ?
-                               &mi->mi_targets[ mi->mi_ntargets - 1 ].mt_version
+                               &mi->mi_targets[ mi->mi_ntargets - 1 ]->mt_version
                                : &mi->mi_version;
 
                if ( argc != 2 ) {
@@ -1069,13 +1119,7 @@ meta_back_db_config(
                        return 1;
                }
 
-               switch ( *version ) {
-               case 0:
-               case LDAP_VERSION2:
-               case LDAP_VERSION3:
-                       break;
-
-               default:
+               if ( *version != 0 && ( *version < LDAP_VERSION_MIN || *version > LDAP_VERSION_MAX ) ) {
                        Debug( LDAP_DEBUG_ANY,
        "%s: line %d: unsupported version \"%s\" in \"protocol-version <version>\"\n",
                                fname, lineno, argv[ 1 ] );
index 5a9930229119ada01a0717c963b90111d97947dd..5364650a07e5578ad88a937eab09313a39b88c2d 100644 (file)
@@ -37,7 +37,9 @@
 /*
  * Set PRINT_CONNTREE larger than 0 to dump the connection tree (debug only)
  */
+#ifndef PRINT_CONNTREE
 #define PRINT_CONNTREE 0
+#endif /* !PRINT_CONNTREE */
 
 /*
  * meta_back_conndn_cmp
@@ -148,7 +150,7 @@ static void
 ravl_print( Avlnode *root, int depth )
 {
        int             i;
-       metaconn_t      *mc = (metaconn_t *)root->avl_data;
+       metaconn_t      *mc;
        
        if ( root == 0 ) {
                return;
@@ -157,30 +159,32 @@ ravl_print( Avlnode *root, int depth )
        ravl_print( root->avl_right, depth + 1 );
        
        for ( i = 0; i < depth; i++ ) {
-               printf( "    " );
+               fprintf( stderr, "-" );
        }
 
-       printf( "c(%d%s%s) %d\n",
-               LDAP_BACK_PCONN_ID( mc->mc_conn ),
-               BER_BVISNULL( &mc->mc_local_ndn ) ? "" : ": ",
-               BER_BVISNULL( &mc->mc_local_ndn ) ? "" : mc->mc_local_ndn.bv_val,
-               root->avl_bf );
+       mc = (metaconn_t *)root->avl_data;
+       fprintf( stderr, "mc=%p local=\"%s\" conn=%p %s refcnt=%d\n",
+               (void *)mc,
+               mc->mc_local_ndn.bv_val ? mc->mc_local_ndn.bv_val : "",
+               (void *)mc->mc_conn,
+               avl_bf2str( root->avl_bf ), mc->mc_refcnt );
        
        ravl_print( root->avl_left, depth + 1 );
 }
 
 static void
-myprint( Avlnode *root )
+myprint( Avlnode *root, char *msg )
 {
-       printf( "********\n" );
+       fprintf( stderr, "========> %s\n", msg );
        
        if ( root == 0 ) {
-               printf( "\tNULL\n" );
+               fprintf( stderr, "\tNULL\n" );
+
        } else {
                ravl_print( root, 0 );
        }
        
-       printf( "********\n" );
+       fprintf( stderr, "<======== %s\n", msg );
 }
 #endif /* PRINT_CONNTREE */
 /*
@@ -263,6 +267,9 @@ meta_back_init_one_conn(
        int                     version;
        dncookie                dc;
        int                     isauthz = ( candidate == mc->mc_authz_target );
+#ifdef HAVE_TLS
+       int                     is_ldaps = 0;
+#endif /* HAVE_TLS */
 
        /*
         * Already init'ed
@@ -276,7 +283,12 @@ meta_back_init_one_conn(
        /*
         * Attempts to initialize the connection to the target ds
         */
+       ldap_pvt_thread_mutex_lock( &mt->mt_uri_mutex );
        rs->sr_err = ldap_initialize( &msc->msc_ld, mt->mt_uri );
+#ifdef HAVE_TLS
+       is_ldaps = ldap_is_ldaps_url( mt->mt_uri );
+#endif /* HAVE_TLS */
+       ldap_pvt_thread_mutex_unlock( &mt->mt_uri_mutex );
        if ( rs->sr_err != LDAP_SUCCESS ) {
                goto error_return;
        }
@@ -295,6 +307,7 @@ meta_back_init_one_conn(
                version = LDAP_VERSION3;
        }
        ldap_set_option( msc->msc_ld, LDAP_OPT_PROTOCOL_VERSION, &version );
+       ldap_set_urllist_proc( msc->msc_ld, mt->mt_urllist_f, mt->mt_urllist_p );
 
        /* automatically chase referrals ("chase-referrals [{yes|no}]" statement) */
        ldap_set_option( msc->msc_ld, LDAP_OPT_REFERRALS,
@@ -303,7 +316,7 @@ meta_back_init_one_conn(
 #ifdef HAVE_TLS
        /* start TLS ("tls [try-]{start|propagate}" statement) */
        if ( ( LDAP_BACK_USE_TLS( mi ) || ( op->o_conn->c_is_tls && LDAP_BACK_PROPAGATE_TLS( mi ) ) )
-                       && !ldap_is_ldaps_url( mt->mt_uri ) )
+                       && !is_ldaps )
        {
 #ifdef SLAP_STARTTLS_ASYNCHRONOUS
                /*
@@ -393,7 +406,8 @@ retry:;
                if ( rs->sr_err == LDAP_SERVER_DOWN
                                || ( rs->sr_err != LDAP_SUCCESS && LDAP_BACK_TLS_CRITICAL( mi ) ) )
                {
-                       ldap_unbind_ext_s( msc->msc_ld, NULL, NULL );
+                       ldap_unbind_ext( msc->msc_ld, NULL, NULL );
+                       msc->msc_ld = NULL;
                        goto error_return;
                }
        }
@@ -447,7 +461,8 @@ retry:;
                        if ( ldap_back_dn_massage( &dc, &op->o_conn->c_dn,
                                                &msc->msc_bound_ndn ) )
                        {
-                               ldap_unbind_ext_s( msc->msc_ld, NULL, NULL );
+                               ldap_unbind_ext( msc->msc_ld, NULL, NULL );
+                               msc->msc_ld = NULL;
                                goto error_return;
                        }
                        
@@ -495,7 +510,7 @@ meta_back_retry(
        ldap_back_send_t        sendok )
 {
        metainfo_t              *mi = ( metainfo_t * )op->o_bd->be_private;
-       metatarget_t            *mt = &mi->mi_targets[ candidate ];
+       metatarget_t            *mt = mi->mi_targets[ candidate ];
        metaconn_t              *mc = *mcp;
        metasingleconn_t        *msc = &mc->mc_conns[ candidate ];
        int                     rc = LDAP_UNAVAILABLE,
@@ -505,16 +520,21 @@ meta_back_retry(
 
        assert( mc->mc_refcnt > 0 );
        if ( mc->mc_refcnt == 1 ) {
-               char    buf[ SLAP_TEXT_BUFLEN ];
+               if ( LogTest( LDAP_DEBUG_ANY ) ) {
+                       char    buf[ SLAP_TEXT_BUFLEN ];
 
-               snprintf( buf, sizeof( buf ),
-                       "retrying URI=\"%s\" DN=\"%s\"",
-                       mt->mt_uri,
-                       BER_BVISNULL( &msc->msc_bound_ndn ) ?
-                               "" : msc->msc_bound_ndn.bv_val );
-               Debug( LDAP_DEBUG_ANY,
-                       "%s meta_back_retry[%d]: %s.\n",
-                       op->o_log_prefix, candidate, buf );
+                       ldap_pvt_thread_mutex_lock( &mt->mt_uri_mutex );
+                       snprintf( buf, sizeof( buf ),
+                               "retrying URI=\"%s\" DN=\"%s\"",
+                               mt->mt_uri,
+                               BER_BVISNULL( &msc->msc_bound_ndn ) ?
+                                       "" : msc->msc_bound_ndn.bv_val );
+                       ldap_pvt_thread_mutex_unlock( &mt->mt_uri_mutex );
+
+                       Debug( LDAP_DEBUG_ANY,
+                               "%s meta_back_retry[%d]: %s.\n",
+                               op->o_log_prefix, candidate, buf );
+               }
 
                meta_clear_one_candidate( msc );
                LDAP_BACK_CONN_ISBOUND_CLEAR( msc );
@@ -531,21 +551,42 @@ meta_back_retry(
                if ( rc == LDAP_SUCCESS ) {
                        rc = meta_back_single_dobind( op, rs, mcp, candidate,
                                sendok, mt->mt_nretries, 0 );
+
+                       Debug( LDAP_DEBUG_ANY,
+                               "%s meta_back_retry[%d]: "
+                               "meta_back_single_dobind=%d\n",
+                               op->o_log_prefix, candidate, rc );
+                       if ( rc == LDAP_SUCCESS ) {
+                               if ( be_isroot( op )  ) {
+                                       LDAP_BACK_CONN_ISBOUND_SET( msc );
+                               } else {
+                                       LDAP_BACK_CONN_ISANON_SET( msc );
+                               }
+                       }
                }
        }
 
        if ( rc != LDAP_SUCCESS ) {
+               SlapReply               *candidates = meta_back_candidates_get( op );
+
+               candidates[ candidate ].sr_err = rc;
+
                if ( *mcp != NULL ) {
                        if ( binding ) {
                                LDAP_BACK_CONN_BINDING_CLEAR( msc );
                        }
                        LDAP_BACK_CONN_TAINTED_SET( mc );
-                       meta_back_release_conn_lock( op, mc, 0 );
-                       *mcp = NULL;
+                       /* only release if mandatory; otherwise
+                        * let the caller do what's best before
+                        * releasing */
+                       if ( META_BACK_ONERR_STOP( mi ) ) {
+                               meta_back_release_conn_lock( op, mc, 0 );
+                               *mcp = NULL;
+                       }
                }
 
                if ( sendok ) {
-                       rs->sr_err = LDAP_UNAVAILABLE;
+                       rs->sr_err = rc;
                        rs->sr_text = NULL;
                        send_ldap_result( op, rs );
                }
@@ -645,9 +686,9 @@ meta_back_get_candidate(
                         * and a default target is defined, and it is
                         * a candidate, try using it (FIXME: YMMV) */
                        if ( mi->mi_defaulttarget != META_DEFAULT_TARGET_NONE
-                               && meta_back_is_candidate( &mi->mi_targets[ mi->mi_defaulttarget ].mt_nsuffix,
-                                               mi->mi_targets[ mi->mi_defaulttarget ].mt_scope,
-                                               mi->mi_targets[ mi->mi_defaulttarget ].mt_subtree_exclude,
+                               && meta_back_is_candidate( &mi->mi_targets[ mi->mi_defaulttarget ]->mt_nsuffix,
+                                               mi->mi_targets[ mi->mi_defaulttarget ]->mt_scope,
+                                               mi->mi_targets[ mi->mi_defaulttarget ]->mt_subtree_exclude,
                                                ndn, op->o_tag == LDAP_REQ_SEARCH ? op->ors_scope : LDAP_SCOPE_BASE ) )
                        {
                                candidate = mi->mi_defaulttarget;
@@ -717,9 +758,11 @@ meta_back_candidates_get( Operation *op )
        } else if ( mc->mc_ntargets < mi->mi_ntargets ) {
                /* NOTE: in the future, may want to allow back-config
                 * to add/remove targets from back-meta... */
-               mc->mc_ntargets = mi->mi_ntargets;
                mc->mc_candidates = ch_realloc( mc->mc_candidates,
-                               sizeof( SlapReply ) * mc->mc_ntargets );
+                               sizeof( SlapReply ) * mi->mi_ntargets );
+               memset( &mc->mc_candidates[ mc->mc_ntargets ], 0,
+                       sizeof( SlapReply ) * ( mi->mi_ntargets - mc->mc_ntargets ) );
+               mc->mc_ntargets = mi->mi_ntargets;
        }
 
        return mc->mc_candidates;
@@ -894,7 +937,7 @@ retry_lock:
                }
 
                for ( i = 0; i < mi->mi_ntargets; i++ ) {
-                       metatarget_t            *mt = &mi->mi_targets[ i ];
+                       metatarget_t            *mt = mi->mi_targets[ i ];
 
                        /*
                         * The target is activated; if needed, it is
@@ -1051,7 +1094,7 @@ retry_lock2:;
                 */
                ( void )meta_clear_unused_candidates( op, i );
 
-               mt = &mi->mi_targets[ i ];
+               mt = mi->mi_targets[ i ];
                msc = &mc->mc_conns[ i ];
 
                /*
@@ -1103,7 +1146,7 @@ retry_lock2:;
                }
 
                for ( i = 0; i < mi->mi_ntargets; i++ ) {
-                       metatarget_t            *mt = &mi->mi_targets[ i ];
+                       metatarget_t            *mt = mi->mi_targets[ i ];
                        metasingleconn_t        *msc = &mc->mc_conns[ i ];
 
                        if ( i == cached 
@@ -1205,7 +1248,7 @@ done:;
                                meta_back_conndn_cmp, meta_back_conndn_dup );
 
 #if PRINT_CONNTREE > 0
-               myprint( mi->mi_conninfo.lai_tree );
+               myprint( mi->mi_conninfo.lai_tree, "meta_back_getconn" );
 #endif /* PRINT_CONNTREE */
                
                ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
index d9461ac4e4d16aea618571e337c77235e5e42b2b..4d23793a8378a7d98df17b5ef20d05ef9f4f5106 100644 (file)
@@ -53,7 +53,7 @@ meta_back_delete( Operation *op, SlapReply *rs )
        /*
         * Rewrite the compare dn, if needed
         */
-       dc.target = &mi->mi_targets[ candidate ];
+       dc.target = mi->mi_targets[ candidate ];
        dc.conn = op->o_conn;
        dc.rs = rs;
        dc.ctx = "deleteDN";
@@ -78,8 +78,8 @@ retry:;
                LDAPMessage     *res = NULL;
                int             rc;
 
-               if ( mi->mi_targets[ candidate ].mt_timeout[ LDAP_BACK_OP_DELETE ] != 0 ) {
-                       tv.tv_sec = mi->mi_targets[ candidate ].mt_timeout[ LDAP_BACK_OP_DELETE ];
+               if ( mi->mi_targets[ candidate ]->mt_timeout[ LDAP_BACK_OP_DELETE ] != 0 ) {
+                       tv.tv_sec = mi->mi_targets[ candidate ]->mt_timeout[ LDAP_BACK_OP_DELETE ];
                        tv.tv_usec = 0;
                        tvp = &tv;
                }
index a4962515d32293af52dce399cfa4bcb03b84bde4..09f7007afc493f9a7a57fe351db58ae2205d21fd 100644 (file)
@@ -104,6 +104,9 @@ meta_back_db_init(
        mi->mi_bind_timeout.tv_sec = 0;
        mi->mi_bind_timeout.tv_usec = META_BIND_TIMEOUT;
 
+       mi->mi_rebind_f = meta_back_default_rebind;
+       mi->mi_urllist_f = meta_back_default_urllist;
+
        ldap_pvt_thread_mutex_init( &mi->mi_conninfo.lai_mutex );
        ldap_pvt_thread_mutex_init( &mi->mi_cache.mutex );
 
@@ -125,15 +128,17 @@ meta_back_db_open(
        int             i, rc;
 
        for ( i = 0; i < mi->mi_ntargets; i++ ) {
-               if ( mi->mi_targets[ i ].mt_flags & LDAP_BACK_F_SUPPORT_T_F_DISCOVER )
+               metatarget_t    *mt = mi->mi_targets[ i ];
+
+               if ( mt->mt_flags & LDAP_BACK_F_SUPPORT_T_F_DISCOVER )
                {
-                       mi->mi_targets[ i ].mt_flags &= ~LDAP_BACK_F_SUPPORT_T_F_DISCOVER;
-                       rc = slap_discover_feature( mi->mi_targets[ i ].mt_uri,
-                                       mi->mi_targets[ i ].mt_version,
+                       mt->mt_flags &= ~LDAP_BACK_F_SUPPORT_T_F_DISCOVER;
+                       rc = slap_discover_feature( mt->mt_uri,
+                                       mt->mt_version,
                                        slap_schema.si_ad_supportedFeatures->ad_cname.bv_val,
                                        LDAP_FEATURE_ABSOLUTE_FILTERS );
                        if ( rc == LDAP_COMPARE_TRUE ) {
-                               mi->mi_targets[ i ].mt_flags |= LDAP_BACK_F_SUPPORT_T_F;
+                               mt->mt_flags |= LDAP_BACK_F_SUPPORT_T_F;
                        }
                }
        }
@@ -194,6 +199,7 @@ target_free(
 {
        if ( mt->mt_uri ) {
                free( mt->mt_uri );
+               ldap_pvt_thread_mutex_destroy( &mt->mt_uri_mutex );
        }
        if ( mt->mt_subtree_exclude ) {
                ber_bvarray_free( mt->mt_subtree_exclude );
@@ -223,6 +229,8 @@ target_free(
        avl_free( mt->mt_rwmap.rwm_oc.map, mapping_free );
        avl_free( mt->mt_rwmap.rwm_at.remap, mapping_dst_free );
        avl_free( mt->mt_rwmap.rwm_at.map, mapping_free );
+
+       free( mt );
 }
 
 int
@@ -251,7 +259,7 @@ meta_back_db_destroy(
                 */
                if ( mi->mi_targets != NULL ) {
                        for ( i = 0; i < mi->mi_ntargets; i++ ) {
-                               target_free( &mi->mi_targets[ i ] );
+                               target_free( mi->mi_targets[ i ] );
                        }
 
                        free( mi->mi_targets );
index c17af5e928c675583d8805229255a9a499371025..2e11c5b696663bf169326f52606fc857c183974f 100644 (file)
@@ -59,7 +59,7 @@ meta_back_modify( Operation *op, SlapReply *rs )
        /*
         * Rewrite the modify dn, if needed
         */
-       dc.target = &mi->mi_targets[ candidate ];
+       dc.target = mi->mi_targets[ candidate ];
        dc.conn = op->o_conn;
        dc.rs = rs;
        dc.ctx = "modifyDN";
@@ -102,7 +102,7 @@ meta_back_modify( Operation *op, SlapReply *rs )
                        mapped = ml->sml_desc->ad_cname;
 
                } else {
-                       ldap_back_map( &mi->mi_targets[ candidate ].mt_rwmap.rwm_at,
+                       ldap_back_map( &mi->mi_targets[ candidate ]->mt_rwmap.rwm_at,
                                        &ml->sml_desc->ad_cname, &mapped,
                                        BACKLDAP_MAP );
                        if ( BER_BVISNULL( &mapped ) || BER_BVISEMPTY( &mapped ) ) {
@@ -129,11 +129,11 @@ meta_back_modify( Operation *op, SlapReply *rs )
                                for ( j = 0; !BER_BVISNULL( &ml->sml_values[ j ] ); ) {
                                        struct ldapmapping      *mapping;
 
-                                       ldap_back_mapping( &mi->mi_targets[ candidate ].mt_rwmap.rwm_oc,
+                                       ldap_back_mapping( &mi->mi_targets[ candidate ]->mt_rwmap.rwm_oc,
                                                        &ml->sml_values[ j ], &mapping, BACKLDAP_MAP );
 
                                        if ( mapping == NULL ) {
-                                               if ( mi->mi_targets[ candidate ].mt_rwmap.rwm_oc.drop_missing ) {
+                                               if ( mi->mi_targets[ candidate ]->mt_rwmap.rwm_oc.drop_missing ) {
                                                        continue;
                                                }
                                                mods[ i ].mod_bvalues[ j ] = &ml->sml_values[ j ];
@@ -188,8 +188,8 @@ retry:;
                struct timeval  tv, *tvp = NULL;
                LDAPMessage     *res = NULL;
 
-               if ( mi->mi_targets[ candidate ].mt_timeout[ LDAP_BACK_OP_MODIFY ] != 0 ) {
-                       tv.tv_sec = mi->mi_targets[ candidate ].mt_timeout[ LDAP_BACK_OP_MODIFY ];
+               if ( mi->mi_targets[ candidate ]->mt_timeout[ LDAP_BACK_OP_MODIFY ] != 0 ) {
+                       tv.tv_sec = mi->mi_targets[ candidate ]->mt_timeout[ LDAP_BACK_OP_MODIFY ];
                        tv.tv_usec = 0;
                        tvp = &tv;
                }
index a0f54f7b0883fc04f65fee940a58e5884791a2bb..2c7d603b2bb4717afdfff4acad681f92de5c81a5 100644 (file)
@@ -76,7 +76,7 @@ meta_back_modrdn( Operation *op, SlapReply *rs )
                 */
 
                /* needs LDAPv3 */
-               switch ( mi->mi_targets[ candidate ].mt_version ) {
+               switch ( mi->mi_targets[ candidate ]->mt_version ) {
                case LDAP_VERSION3:
                        break;
 
@@ -97,7 +97,7 @@ meta_back_modrdn( Operation *op, SlapReply *rs )
                /*
                 * Rewrite the new superior, if defined and required
                 */
-               dc.target = &mi->mi_targets[ candidate ];
+               dc.target = mi->mi_targets[ candidate ];
                dc.ctx = "newSuperiorDN";
                if ( ldap_back_dn_massage( &dc, op->orr_newSup, &mnewSuperior ) ) {
                        rs->sr_err = LDAP_OTHER;
@@ -109,7 +109,7 @@ meta_back_modrdn( Operation *op, SlapReply *rs )
        /*
         * Rewrite the modrdn dn, if required
         */
-       dc.target = &mi->mi_targets[ candidate ];
+       dc.target = mi->mi_targets[ candidate ];
        dc.ctx = "modrDN";
        if ( ldap_back_dn_massage( &dc, &op->o_req_dn, &mdn ) ) {
                rs->sr_err = LDAP_OTHER;
@@ -134,8 +134,8 @@ retry:;
                LDAPMessage     *res = NULL;
                int             rc;
 
-               if ( mi->mi_targets[ candidate ].mt_timeout[ LDAP_BACK_OP_MODRDN ] != 0 ) {
-                       tv.tv_sec = mi->mi_targets[ candidate ].mt_timeout[ LDAP_BACK_OP_MODRDN ];
+               if ( mi->mi_targets[ candidate ]->mt_timeout[ LDAP_BACK_OP_MODRDN ] != 0 ) {
+                       tv.tv_sec = mi->mi_targets[ candidate ]->mt_timeout[ LDAP_BACK_OP_MODRDN ];
                        tv.tv_usec = 0;
                        tvp = &tv;
                }
index 34ac69dc73899023ee59d0c5519608fa5e513b53..45c16240bd47d1f2894e23951e3d9d5af3f2002d 100644 (file)
 #include "ldap_log.h"
 #include "../../../libraries/libldap/ldap-int.h"
 
+/* IGNORE means that target does not (no longer) participate
+ * in the search;
+ * NOTREADY means the search on that target has not been initialized yet
+ */
+#define        META_MSGID_IGNORE       (-1)
+#define        META_MSGID_NEED_BIND    (-2)
+
 static int
 meta_send_entry(
        Operation       *op,
@@ -46,47 +53,222 @@ meta_send_entry(
 typedef enum meta_search_candidate_t {
        META_SEARCH_ERR = -1,
        META_SEARCH_NOT_CANDIDATE,
-       META_SEARCH_CANDIDATE
+       META_SEARCH_CANDIDATE,
+       META_SEARCH_BINDING,
+       META_SEARCH_NEED_BIND
 } meta_search_candidate_t;
 
+/*
+ * meta_search_dobind_init()
+ *
+ * initiates bind for a candidate target of a search.
+ */
+static meta_search_candidate_t
+meta_search_dobind_init(
+       Operation               *op,
+       SlapReply               *rs,
+       metaconn_t              **mcp,
+       int                     candidate,
+       SlapReply               *candidates )
+{
+       metaconn_t              *mc = *mcp;
+       metainfo_t              *mi = ( metainfo_t * )op->o_bd->be_private;
+       metatarget_t            *mt = mi->mi_targets[ candidate ];
+       metasingleconn_t        *msc = &mc->mc_conns[ candidate ];
+
+       char                    *binddn = "";
+       struct berval           cred = BER_BVC( "" );
+
+       int                     rc;
+       int                     nretries = 1;
+
+       meta_search_candidate_t retcode;
+
+       Debug( LDAP_DEBUG_TRACE, "%s >>> meta_search_dobind_init[%d]\n", op->o_log_prefix, candidate, 0 );
+
+       /*
+        * all the targets are already bound as pseudoroot
+        */
+       if ( mc->mc_authz_target == META_BOUND_ALL ) {
+               return META_SEARCH_CANDIDATE;
+       }
+
+       ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex );
+       if ( LDAP_BACK_CONN_ISBOUND( msc ) || LDAP_BACK_CONN_ISANON( msc ) ) {
+               ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
+               return META_SEARCH_CANDIDATE;
+       }
+
+       if ( LDAP_BACK_CONN_BINDING( msc ) ) {
+               ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
+               candidates[ candidate ].sr_msgid = META_MSGID_NEED_BIND;
+               return META_SEARCH_NEED_BIND;
+       }
+
+       LDAP_BACK_CONN_BINDING_SET( msc );
+       ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
+
+       if ( be_isroot( op ) && !BER_BVISNULL( &mt->mt_pseudorootdn ) ) {
+               binddn = mt->mt_pseudorootdn.bv_val;
+               cred = mt->mt_pseudorootpw;
+       }
+
+       /*
+        * Otherwise an anonymous bind is performed
+        * (note: if the target was already bound, the anonymous
+        * bind clears the previous bind).
+        */
+       if ( !BER_BVISNULL( &msc->msc_bound_ndn ) ) {
+               ber_memfree( msc->msc_bound_ndn.bv_val );
+               BER_BVZERO( &msc->msc_bound_ndn );
+       }
+               
+       if ( LDAP_BACK_SAVECRED( mi ) && !BER_BVISNULL( &msc->msc_cred ) ) {
+               /* destroy sensitive data */
+               memset( msc->msc_cred.bv_val, 0, msc->msc_cred.bv_len );
+               ber_memfree( msc->msc_cred.bv_val );
+               BER_BVZERO( &msc->msc_cred );
+       }
+
+retry:;
+       assert( msc->msc_ld != NULL );
+
+       rc = ldap_sasl_bind( msc->msc_ld, binddn, LDAP_SASL_SIMPLE, &cred,
+                       NULL, NULL, &candidates[ candidate ].sr_msgid );
+       switch ( rc ) {
+       case LDAP_SUCCESS:
+               return META_SEARCH_BINDING;
+
+       case LDAP_SERVER_DOWN:
+               if ( nretries && meta_back_retry( op, rs, mcp, candidate, LDAP_BACK_DONTSEND ) ) {
+                       nretries = 0;
+                       goto retry;
+               }
+
+               if ( *mcp == NULL ) {
+                       retcode = META_SEARCH_ERR;
+                       rs->sr_err = LDAP_UNAVAILABLE;
+                       break;
+               }
+               /* fall thru */
+
+       default:
+               rs->sr_err = rc;
+               rc = slap_map_api2result( rs );
+
+               ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex );
+               LDAP_BACK_CONN_BINDING_CLEAR( msc );
+               if ( META_BACK_ONERR_STOP( mi ) ) {
+                       LDAP_BACK_CONN_TAINTED_SET( mc );
+                       meta_back_release_conn( op, mc );
+                       *mcp = NULL;
+
+                       retcode = META_SEARCH_ERR;
+
+               } else {
+                       candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;
+                       retcode = META_SEARCH_NOT_CANDIDATE;
+               }
+               ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
+               break;
+       }
+
+       return retcode;
+}
+
+static meta_search_candidate_t
+meta_search_dobind_result(
+       Operation               *op,
+       SlapReply               *rs,
+       metaconn_t              **mcp,
+       int                     candidate,
+       SlapReply               *candidates,
+       LDAPMessage             *res )
+{
+       metainfo_t              *mi = ( metainfo_t * )op->o_bd->be_private;
+       metaconn_t              *mc = *mcp;
+       metasingleconn_t        *msc = &mc->mc_conns[ candidate ];
+
+       meta_search_candidate_t retcode = META_SEARCH_NOT_CANDIDATE;
+       int                     rc;
+
+       assert( msc->msc_ld != NULL );
+
+       rc = ldap_parse_result( msc->msc_ld, res,
+               &candidates[ candidate ].sr_err,
+               NULL, NULL, NULL, NULL, 1 );
+       if ( rc == LDAP_SUCCESS ) {
+               rc = slap_map_api2result( &candidates[ candidate ] );
+       }
+
+       ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex );
+       LDAP_BACK_CONN_BINDING_CLEAR( msc );
+       if ( rc != LDAP_SUCCESS ) {
+               if ( META_BACK_ONERR_STOP( mi ) ) {
+                       LDAP_BACK_CONN_TAINTED_SET( mc );
+                       meta_back_release_conn( op, mc );
+                       *mcp = NULL;
+                       retcode = META_SEARCH_ERR;
+               }
+
+       } else {
+               if ( be_isroot( op ) ) {
+                       LDAP_BACK_CONN_ISBOUND_SET( msc );
+               } else {
+                       LDAP_BACK_CONN_ISANON_SET( msc );
+               }
+               retcode = META_SEARCH_CANDIDATE;
+       }
+       ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
+
+       return retcode;
+}
+
 static meta_search_candidate_t
 meta_back_search_start(
        Operation               *op,
        SlapReply               *rs,
        dncookie                *dc,
-       metasingleconn_t        *msc,
+       metaconn_t              **mcp,
        int                     candidate,
-       SlapReply               *candidates
-)
+       SlapReply               *candidates )
 {
-       metainfo_t      *mi = ( metainfo_t * )op->o_bd->be_private;
-       struct berval   realbase = op->o_req_dn;
-       int             realscope = op->ors_scope;
-       ber_len_t       suffixlen = 0;
-       struct berval   mbase = BER_BVNULL; 
-       struct berval   mfilter = BER_BVNULL;
-       char            **mapped_attrs = NULL;
-       int             rc;
+       metainfo_t              *mi = ( metainfo_t * )op->o_bd->be_private;
+       metatarget_t            *mt = mi->mi_targets[ candidate ];
+       metaconn_t              *mc = *mcp;
+       metasingleconn_t        *msc = &mc->mc_conns[ candidate ];
+       struct berval           realbase = op->o_req_dn;
+       int                     realscope = op->ors_scope;
+       ber_len_t               suffixlen = 0;
+       struct berval           mbase = BER_BVNULL; 
+       struct berval           mfilter = BER_BVNULL;
+       char                    **mapped_attrs = NULL;
+       int                     rc;
        meta_search_candidate_t retcode;
-       struct timeval  tv, *tvp = NULL;
+       struct timeval          tv, *tvp = NULL;
+       int                     nretries = 1;
+
+       Debug( LDAP_DEBUG_TRACE, "%s >>> meta_back_search_start[%d]\n", op->o_log_prefix, candidate, 0 );
 
        /* should we check return values? */
        if ( op->ors_deref != -1 ) {
-               ldap_set_option( msc->msc_ld, LDAP_OPT_DEREF,
+               assert( msc->msc_ld != NULL );
+               (void)ldap_set_option( msc->msc_ld, LDAP_OPT_DEREF,
                                ( void * )&op->ors_deref );
        }
 
        if ( op->ors_tlimit != SLAP_NO_LIMIT ) {
                tv.tv_sec = op->ors_tlimit > 0 ? op->ors_tlimit : 1;
+               tv.tv_usec = 0;
                tvp = &tv;
        }
 
-       dc->target = &mi->mi_targets[ candidate ];
+       dc->target = mt;
 
        /*
         * modifies the base according to the scope, if required
         */
-       suffixlen = mi->mi_targets[ candidate ].mt_nsuffix.bv_len;
+       suffixlen = mt->mt_nsuffix.bv_len;
        if ( suffixlen > op->o_req_ndn.bv_len ) {
                switch ( op->ors_scope ) {
                case LDAP_SCOPE_SUBTREE:
@@ -98,11 +280,9 @@ meta_back_search_start(
                         * the requested searchBase already passed
                         * thru the candidate analyzer...
                         */
-                       if ( dnIsSuffix( &mi->mi_targets[ candidate ].mt_nsuffix,
-                                       &op->o_req_ndn ) )
-                       {
-                               realbase = mi->mi_targets[ candidate ].mt_nsuffix;
-                               if ( mi->mi_targets[ candidate ].mt_scope == LDAP_SCOPE_SUBORDINATE ) {
+                       if ( dnIsSuffix( &mt->mt_nsuffix, &op->o_req_ndn ) ) {
+                               realbase = mt->mt_nsuffix;
+                               if ( mt->mt_scope == LDAP_SCOPE_SUBORDINATE ) {
                                        realscope = LDAP_SCOPE_SUBORDINATE;
                                }
 
@@ -117,19 +297,19 @@ meta_back_search_start(
                case LDAP_SCOPE_SUBORDINATE:
                case LDAP_SCOPE_ONELEVEL:
                {
-                       struct berval   rdn = mi->mi_targets[ candidate ].mt_nsuffix;
+                       struct berval   rdn = mt->mt_nsuffix;
                        rdn.bv_len -= op->o_req_ndn.bv_len + STRLENOF( "," );
                        if ( dnIsOneLevelRDN( &rdn )
-                                       && dnIsSuffix( &mi->mi_targets[ candidate ].mt_nsuffix, &op->o_req_ndn ) )
+                                       && dnIsSuffix( &mt->mt_nsuffix, &op->o_req_ndn ) )
                        {
                                /*
                                 * if there is exactly one level,
                                 * make the target suffix the new
                                 * base, and make scope "base"
                                 */
-                               realbase = mi->mi_targets[ candidate ].mt_nsuffix;
+                               realbase = mt->mt_nsuffix;
                                if ( op->ors_scope == LDAP_SCOPE_SUBORDINATE ) {
-                                       if ( mi->mi_targets[ candidate ].mt_scope == LDAP_SCOPE_SUBORDINATE ) {
+                                       if ( mt->mt_scope == LDAP_SCOPE_SUBORDINATE ) {
                                                realscope = LDAP_SCOPE_SUBORDINATE;
                                        } else {
                                                realscope = LDAP_SCOPE_SUBTREE;
@@ -149,6 +329,15 @@ meta_back_search_start(
                }
        }
 
+       /* initiate dobind */
+       retcode = meta_search_dobind_init( op, rs, mcp, candidate, candidates );
+
+       Debug( LDAP_DEBUG_TRACE, "%s <<< meta_search_dobind_init[%d]=%d\n", op->o_log_prefix, candidate, retcode );
+
+       if ( retcode != META_SEARCH_CANDIDATE ) {
+               return retcode;
+       }
+
        /*
         * Rewrite the search base, if required
         */
@@ -192,7 +381,7 @@ meta_back_search_start(
        /*
         * Maps required attributes
         */
-       rc = ldap_back_map_attrs( &mi->mi_targets[ candidate ].mt_rwmap.rwm_at,
+       rc = ldap_back_map_attrs( &mt->mt_rwmap.rwm_at,
                        op->ors_attrs, BACKLDAP_MAP, &mapped_attrs );
        if ( rc != LDAP_SUCCESS ) {
                /*
@@ -205,16 +394,32 @@ meta_back_search_start(
        /*
         * Starts the search
         */
+retry:;
+       assert( msc->msc_ld != NULL );
        rc = ldap_search_ext( msc->msc_ld,
                        mbase.bv_val, realscope, mfilter.bv_val,
                        mapped_attrs, op->ors_attrsonly,
                        op->o_ctrls, NULL, tvp, op->ors_slimit,
                        &candidates[ candidate ].sr_msgid ); 
-       if ( rc == LDAP_SUCCESS ) {
+       switch ( rc ) {
+       case LDAP_SUCCESS:
                retcode = META_SEARCH_CANDIDATE;
+               break;
+       
+       case LDAP_SERVER_DOWN:
+               if ( nretries && meta_back_retry( op, rs, mcp, candidate, LDAP_BACK_DONTSEND ) ) {
+                       nretries = 0;
+                       goto retry;
+               }
 
-       } else {
-               candidates[ candidate ].sr_msgid = -1;
+               if ( *mcp == NULL ) {
+                       retcode = META_SEARCH_ERR;
+                       break;
+               }
+               /* fall thru */
+
+       default:
+               candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;
                retcode = META_SEARCH_NOT_CANDIDATE;
        }
 
@@ -257,7 +462,7 @@ meta_back_search( Operation *op, SlapReply *rs )
         * to map attrs and maybe rewrite value
         */
        mc = meta_back_getconn( op, rs, NULL, LDAP_BACK_SENDERR );
-       if ( !mc || !meta_back_dobind( op, rs, mc, LDAP_BACK_SENDERR ) ) {
+       if ( !mc ) {
                return rs->sr_err;
        }
 
@@ -268,31 +473,42 @@ meta_back_search( Operation *op, SlapReply *rs )
         * Inits searches
         */
        for ( i = 0; i < mi->mi_ntargets; i++ ) {
-               metasingleconn_t        *msc = &mc->mc_conns[ i ];
+               candidates[ i ].sr_msgid = META_MSGID_IGNORE;
+
+               if ( candidates[ i ].sr_tag != META_CANDIDATE ) {
+                       continue;
+               }
 
-               candidates[ i ].sr_msgid = -1;
                candidates[ i ].sr_matched = NULL;
                candidates[ i ].sr_text = NULL;
                candidates[ i ].sr_ref = NULL;
                candidates[ i ].sr_ctrls = NULL;
+       }
 
+       for ( i = 0; i < mi->mi_ntargets; i++ ) {
                if ( candidates[ i ].sr_tag != META_CANDIDATE
                        || candidates[ i ].sr_err != LDAP_SUCCESS )
                {
                        continue;
                }
 
-               switch ( meta_back_search_start( op, rs, &dc, msc, i, candidates ) )
+               switch ( meta_back_search_start( op, rs, &dc, &mc, i, candidates ) )
                {
                case META_SEARCH_NOT_CANDIDATE:
                        break;
 
                case META_SEARCH_CANDIDATE:
+               case META_SEARCH_BINDING:
+               case META_SEARCH_NEED_BIND:
                        candidates[ i ].sr_type = REP_INTERMEDIATE;
                        ++ncandidates;
                        break;
 
                case META_SEARCH_ERR:
+                       savepriv = op->o_private;
+                       op->o_private = (void *)i;
+                       send_ldap_result( op, rs );
+                       op->o_private = savepriv;
                        rc = -1;
                        goto finish;
                }
@@ -368,10 +584,85 @@ meta_back_search( Operation *op, SlapReply *rs )
        for ( rc = 0; ncandidates > 0; ) {
                int     gotit = 0, doabandon = 0;
 
+               /* check time limit */
+               if ( op->ors_tlimit != SLAP_NO_LIMIT
+                               && slap_get_time() > stoptime )
+               {
+                       doabandon = 1;
+                       rc = rs->sr_err = LDAP_TIMELIMIT_EXCEEDED;
+                       savepriv = op->o_private;
+                       op->o_private = (void *)i;
+                       send_ldap_result( op, rs );
+                       op->o_private = savepriv;
+                       goto finish;
+               }
+
                for ( i = 0; i < mi->mi_ntargets; i++ ) {
                        metasingleconn_t        *msc = &mc->mc_conns[ i ];
 
-                       if ( candidates[ i ].sr_msgid == -1 ) {
+                       if ( candidates[ i ].sr_msgid == META_MSGID_IGNORE ) {
+                               continue;
+                       }
+
+                       if ( candidates[ i ].sr_msgid == META_MSGID_NEED_BIND ) {
+                               /* initiate dobind */
+                               switch ( meta_search_dobind_init( op, rs, &mc, i, candidates ) )
+                               {
+                               case META_SEARCH_BINDING:
+                               case META_SEARCH_NEED_BIND:
+                                       break;
+
+                               case META_SEARCH_NOT_CANDIDATE:
+                                       /*
+                                        * When no candidates are left,
+                                        * the outer cycle finishes
+                                        */
+                                       candidates[ i ].sr_msgid = META_MSGID_IGNORE;
+                                       --ncandidates;
+                                       break;
+
+                               case META_SEARCH_ERR:
+                                       if ( META_BACK_ONERR_STOP( mi ) ) {
+                                               savepriv = op->o_private;
+                                               op->o_private = (void *)i;
+                                               send_ldap_result( op, rs );
+                                               op->o_private = savepriv;
+                                               goto finish;
+                                       }
+                                       break;
+
+                               case META_SEARCH_CANDIDATE:
+                                       switch ( meta_back_search_start( op, rs, &dc, &mc, i, candidates ) )
+                                       {
+                                       case META_SEARCH_CANDIDATE:
+                                               goto get_result;
+
+                                               /* means that failed but onerr == continue */
+                                       case META_SEARCH_NOT_CANDIDATE:
+                                       case META_SEARCH_ERR:
+                                               candidates[ i ].sr_msgid = META_MSGID_IGNORE;
+                                               --ncandidates;
+
+                                               if ( META_BACK_ONERR_STOP( mi ) ) {
+                                                       savepriv = op->o_private;
+                                                       op->o_private = (void *)i;
+                                                       send_ldap_result( op, rs );
+                                                       op->o_private = savepriv;
+                                                       goto finish;
+                                               }
+                                               break;
+
+                                       default:
+                                               /* impossible */
+                                               assert( 0 );
+                                               break;
+                                       }
+
+                               default:
+                                       /* impossible */
+                                       assert( 0 );
+                                       break;
+                               }
                                continue;
                        }
 
@@ -395,19 +686,6 @@ get_result:;
                                /* FIXME: res should not need to be freed */
                                assert( res == NULL );
 
-                               /* check time limit */
-                               if ( op->ors_tlimit != SLAP_NO_LIMIT
-                                               && slap_get_time() > stoptime )
-                               {
-                                       doabandon = 1;
-                                       rc = rs->sr_err = LDAP_TIMELIMIT_EXCEEDED;
-                                       savepriv = op->o_private;
-                                       op->o_private = (void *)i;
-                                       send_ldap_result( op, rs );
-                                       op->o_private = savepriv;
-                                       goto finish;
-                               }
-
                                continue;
 
                        } else if ( rc == -1 ) {
@@ -417,12 +695,27 @@ really_bad:;
                                        candidates[ i ].sr_type = REP_RESULT;
 
                                        if ( meta_back_retry( op, rs, &mc, i, LDAP_BACK_DONTSEND ) ) {
-                                               switch ( meta_back_search_start( op, rs, &dc, msc, i, candidates ) )
+                                               switch ( meta_back_search_start( op, rs, &dc, &mc, i, candidates ) )
                                                {
                                                case META_SEARCH_CANDIDATE:
                                                        goto get_result;
 
+                                                       /* means that failed but onerr == continue */
                                                case META_SEARCH_NOT_CANDIDATE:
+                                                       candidates[ i ].sr_msgid = META_MSGID_IGNORE;
+                                                       --ncandidates;
+
+                                                       if ( META_BACK_ONERR_STOP( mi ) ) {
+                                                               savepriv = op->o_private;
+                                                               op->o_private = (void *)i;
+                                                               send_ldap_result( op, rs );
+                                                               op->o_private = savepriv;
+                                                               goto finish;
+                                                       }
+                                                       break;
+
+                                               case META_SEARCH_BINDING:
+                                               case META_SEARCH_NEED_BIND:
                                                        assert( 0 );
 
                                                default:
@@ -431,18 +724,20 @@ really_bad:;
                                                }
                                        }
 
-                                       savepriv = op->o_private;
-                                       op->o_private = (void *)i;
-                                       send_ldap_result( op, rs );
-                                       op->o_private = savepriv;
-                                       goto finish;
+                                       if ( META_BACK_ONERR_STOP( mi ) ) {
+                                               savepriv = op->o_private;
+                                               op->o_private = (void *)i;
+                                               send_ldap_result( op, rs );
+                                               op->o_private = savepriv;
+                                               goto finish;
+                                       }
                                }
 
                                /*
                                 * When no candidates are left,
                                 * the outer cycle finishes
                                 */
-                               candidates[ i ].sr_msgid = -1;
+                               candidates[ i ].sr_msgid = META_MSGID_IGNORE;
                                --ncandidates;
                                rs->sr_err = candidates[ i ].sr_err = LDAP_OTHER;
                                rs->sr_text = "remote server unavailable";
@@ -613,7 +908,7 @@ really_bad:;
                                        candidates[ i ].sr_matched = NULL;
 
                                        dc.ctx = "matchedDN";
-                                       dc.target = &mi->mi_targets[ i ];
+                                       dc.target = mi->mi_targets[ i ];
                                        if ( !ldap_back_dn_massage( &dc, &match, &mmatch ) ) {
                                                if ( mmatch.bv_val == match.bv_val ) {
                                                        candidates[ i ].sr_matched = ch_strdup( mmatch.bv_val );
@@ -733,9 +1028,41 @@ really_bad:;
                                 * When no candidates are left,
                                 * the outer cycle finishes
                                 */
-                               candidates[ i ].sr_msgid = -1;
+                               candidates[ i ].sr_msgid = META_MSGID_IGNORE;
                                --ncandidates;
 
+                       } else if ( rc == LDAP_RES_BIND ) {
+                               meta_search_candidate_t retcode;
+
+                               retcode = meta_search_dobind_result( op, rs, &mc, i, candidates, res );
+                               if ( retcode == META_SEARCH_CANDIDATE ) {
+                                       retcode = meta_back_search_start( op, rs, &dc, &mc, i, candidates );
+                               }
+
+                               switch ( retcode ) {
+                               case META_SEARCH_CANDIDATE:
+                                       goto get_result;
+
+                                       /* means that failed but onerr == continue */
+                               case META_SEARCH_NOT_CANDIDATE:
+                               case META_SEARCH_ERR:
+                                       candidates[ i ].sr_msgid = META_MSGID_IGNORE;
+                                       --ncandidates;
+
+                                       if ( META_BACK_ONERR_STOP( mi ) ) {
+                                               savepriv = op->o_private;
+                                               op->o_private = (void *)i;
+                                               send_ldap_result( op, rs );
+                                               op->o_private = savepriv;
+                                               goto finish;
+                                       }
+                                       break;
+
+                               default:
+                                       assert( 0 );
+                                       break;
+                               }
+
                        } else {
                                assert( 0 );
                                goto really_bad;
@@ -747,11 +1074,12 @@ really_bad:;
                        for ( i = 0; i < mi->mi_ntargets; i++ ) {
                                metasingleconn_t        *msc = &mc->mc_conns[ i ];
 
-                               if ( candidates[ i ].sr_msgid != -1 ) {
+                               if ( candidates[ i ].sr_msgid != META_MSGID_IGNORE )
+                               {
                                        ldap_abandon_ext( msc->msc_ld,
                                                candidates[ i ].sr_msgid,
                                                NULL, NULL );
-                                       candidates[ i ].sr_msgid = -1;
+                                       candidates[ i ].sr_msgid = META_MSGID_IGNORE;
                                }
                        }
 
@@ -764,7 +1092,10 @@ really_bad:;
                /* if no entry was found during this loop,
                 * set a minimal timeout */
                if ( gotit == 0 ) {
-                       LDAP_BACK_TV_SET( &tv );
+                       /* make the entire wait last
+                        * LDAP_BACK_RESULT_UTIMEOUT at worst */
+                       tv.tv_sec = 0;
+                       tv.tv_usec = LDAP_BACK_RESULT_UTIMEOUT/initial_candidates;
                         ldap_pvt_thread_yield();
                }
        }
@@ -773,7 +1104,11 @@ really_bad:;
                /*
                 * FIXME: need a better strategy to handle errors
                 */
-               rc = meta_back_op_result( mc, op, rs, META_TARGET_NONE );
+               if ( mc ) {
+                       rc = meta_back_op_result( mc, op, rs, META_TARGET_NONE );
+               } else {
+                       rc = rs->sr_err;
+               }
                goto finish;
        }
 
@@ -801,7 +1136,7 @@ really_bad:;
                                 * ignore the matchedDN */
                                if ( sres == LDAP_SUCCESS
                                        && candidates[ i ].sr_err == LDAP_NO_SUCH_OBJECT
-                                       && op->o_req_ndn.bv_len > mi->mi_targets[ i ].mt_nsuffix.bv_len )
+                                       && op->o_req_ndn.bv_len > mi->mi_targets[ i ]->mt_nsuffix.bv_len )
                                {
                                        free( (char *)candidates[ i ].sr_matched );
                                        candidates[ i ].sr_matched = NULL;
@@ -898,6 +1233,14 @@ finish:;
                        continue;
                }
 
+               if ( mc && candidates[ i ].sr_msgid >= 0 ) {
+                       ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex );
+                       if ( LDAP_BACK_CONN_BINDING( &mc->mc_conns[ i ] ) ) {
+                               LDAP_BACK_CONN_BINDING_CLEAR( &mc->mc_conns[ i ] );
+                       }
+                       ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
+               }
+
                if ( candidates[ i ].sr_matched ) {
                        free( (char *)candidates[ i ].sr_matched );
                        candidates[ i ].sr_matched = NULL;
@@ -952,7 +1295,7 @@ meta_send_entry(
        /*
         * Rewrite the dn of the result, if needed
         */
-       dc.target = &mi->mi_targets[ target ];
+       dc.target = mi->mi_targets[ target ];
        dc.conn = op->o_conn;
        dc.rs = rs;
        dc.ctx = "searchResult";
@@ -996,7 +1339,7 @@ meta_send_entry(
                slap_syntax_validate_func       *validate;
                slap_syntax_transform_func      *pretty;
 
-               ldap_back_map( &mi->mi_targets[ target ].mt_rwmap.rwm_at, 
+               ldap_back_map( &mi->mi_targets[ target ]->mt_rwmap.rwm_at, 
                                &a, &mapped, BACKLDAP_REMAP );
                if ( BER_BVISNULL( &mapped ) || mapped.bv_val[0] == '\0' ) {
                        ( void )ber_scanf( &ber, "x" /* [W] */ );
@@ -1071,7 +1414,7 @@ meta_send_entry(
                        struct berval   *bv;
 
                        for ( bv = attr->a_vals; !BER_BVISNULL( bv ); bv++ ) {
-                               ldap_back_map( &mi->mi_targets[ target ].mt_rwmap.rwm_oc,
+                               ldap_back_map( &mi->mi_targets[ target ]->mt_rwmap.rwm_oc,
                                                bv, &mapped, BACKLDAP_REMAP );
                                if ( BER_BVISNULL( &mapped ) || mapped.bv_val[0] == '\0') {
                                        free( bv->bv_val );
index 0b301a242c5b6994a35869193793fdfaffa2d43c..7433c2613bc36d16cfdc59f833cc097301c9fb66 100644 (file)
@@ -67,7 +67,7 @@ meta_back_conn_destroy(
         * Cleanup rewrite session
         */
        for ( i = 0; i < mi->mi_ntargets; ++i ) {
-               rewrite_session_delete( mi->mi_targets[ i ].mt_rwmap.rwm_rw, conn );
+               rewrite_session_delete( mi->mi_targets[ i ]->mt_rwmap.rwm_rw, conn );
        }
 
        return 0;
index 629248ec79698cca959f9ace7d5fde6b838f51b1..02644819b9e459dde629a846d8ebdd32b14981f9 100644 (file)
@@ -370,7 +370,7 @@ monitor_subsys_database_init(
                        int             t;
 
                        for ( t = 0; t < mi->mi_ntargets; t++ ) {
-                               char            **urls = ldap_str2charray( mi->mi_targets[ t ].mt_uri, " " );
+                               char            **urls = ldap_str2charray( mi->mi_targets[ t ]->mt_uri, " " );
 
                                if ( urls != NULL ) {
                                        int             u;
index d5096f5f52b41fabdb1d01c2fb855549aa816d3a..64e71ee6102f5ab12427fb678b12e1928ad218ce 100644 (file)
@@ -38,7 +38,7 @@ null_back_bind( Operation *op, SlapReply *rs )
 {
        struct null_info *ni = (struct null_info *) op->o_bd->be_private;
 
-       if ( ni->ni_bind_allowed ) {
+       if ( ni->ni_bind_allowed || be_isroot_pw( op ) ) {
                /* front end will send result on success (0) */
                return LDAP_SUCCESS;
        }
index 3ecdcdfaa21748997520e4fc9a595d4034f779fe..6f47ce96aaec579b56bfaafa222a7ef9aea59923 100644 (file)
@@ -319,6 +319,7 @@ backsql_oc_get_attr_mapping( void *v_oc, void *v_bas )
                const char      *text = NULL;
                struct berval   bv;
                struct berbuf   bb = BB_NULL;
+               AttributeDescription *ad = NULL;
 
                Debug( LDAP_DEBUG_TRACE, 
                        "attributeType:\n"
@@ -336,10 +337,7 @@ backsql_oc_get_attr_mapping( void *v_oc, void *v_bas )
                /* TimesTen */
                Debug( LDAP_DEBUG_TRACE, "\tsel_expr_u=\"%s\"\n",
                                at_row.cols[ 8 ], 0, 0 );
-               at_map = (backsql_at_map_rec *)ch_calloc( 1,
-                               sizeof( backsql_at_map_rec ) );
-               rc = slap_str2ad( at_row.cols[ 0 ], 
-                               &at_map->bam_ad, &text );
+               rc = slap_str2ad( at_row.cols[ 0 ], &ad, &text );
                if ( rc != LDAP_SUCCESS ) {
                        Debug( LDAP_DEBUG_TRACE, "backsql_oc_get_attr_mapping(): "
                                "attribute \"%s\" for objectClass \"%s\" "
@@ -349,6 +347,9 @@ backsql_oc_get_attr_mapping( void *v_oc, void *v_bas )
                        bas->bas_rc = LDAP_CONSTRAINT_VIOLATION;
                        return BACKSQL_AVL_STOP;
                }
+               at_map = (backsql_at_map_rec *)ch_calloc( 1,
+                               sizeof( backsql_at_map_rec ) );
+               at_map->bam_ad = ad;
 
                ber_str2bv( at_row.cols[ 1 ], 0, 1, &at_map->bam_sel_expr );
                if ( at_row.value_len[ 8 ] < 0 ) {
index e630621b88bd7b401288ca0b6a00c00fca1b34a4..bda1982bcdbb47de64a5eddd6716730a45eca556 100644 (file)
@@ -162,12 +162,26 @@ backsql_BindRowAsStrings_x( SQLHSTMT sth, BACKSQL_ROW_NTS *row, void *ctx )
 
                row->col_names = (BerVarray)ber_memcalloc_x( row->ncols + 1, 
                                sizeof( struct berval ), ctx );
+               if ( !row->col_names ) goto nomem3;
                row->cols = (char **)ber_memcalloc_x( row->ncols + 1, 
                                sizeof( char * ), ctx );
+               if ( !row->cols ) goto nomem2;
                row->col_prec = (UDWORD *)ber_memcalloc_x( row->ncols,
                                sizeof( UDWORD ), ctx );
+               if ( !row->col_prec ) goto nomem1;
                row->value_len = (SQLINTEGER *)ber_memcalloc_x( row->ncols,
                                sizeof( SQLINTEGER ), ctx );
+               if ( !row->value_len ) {
+                       ber_memfree_x( row->col_prec, ctx );
+                       row->col_prec = NULL;
+nomem1:                ber_memfree_x( row->cols, ctx );
+                       row->cols = NULL;
+nomem2:                ber_memfree_x( row->col_names, ctx );
+                       row->col_names = NULL;
+nomem3:                Debug( LDAP_DEBUG_ANY, "backsql_BindRowAsStrings: "
+                               "out of memory\n", 0, 0, 0 );
+                       return LDAP_NO_MEMORY;
+               }
                for ( i = 1; i <= row->ncols; i++ ) {
                        rc = SQLDescribeCol( sth, (SQLSMALLINT)i, &colname[ 0 ],
                                        (SQLUINTEGER)( sizeof( colname ) - 1 ),
index f054e506779869b28d4dff99642f0e24174e7102..978f94649c77ca0df27b387b06f25d63adc0e2fc 100644 (file)
@@ -687,7 +687,10 @@ be_slurp_update( Operation *op )
 int
 be_shadow_update( Operation *op )
 {
-       return ( SLAP_SYNC_SHADOW( op->o_bd ) ||
+       /* This assumes that all internal ops (connid == -1) on a syncrepl
+        * database are syncrepl operations.
+        */
+       return (( SLAP_SYNC_SHADOW( op->o_bd ) && op->o_connid == -1 ) ||
                ( SLAP_SHADOW( op->o_bd ) && be_isupdate_dn( op->o_bd, &op->o_ndn ) ) );
 }
 
index f9b3cdce071fa54963baefb7e15ffeb667bfa161..202c63cd9d882ec212ec6b39bd2c1b56a4f50c79 100644 (file)
@@ -294,7 +294,7 @@ glue_op_search ( Operation *op, SlapReply *rs )
        BackendDB *b1 = NULL, *btmp;
        BackendInfo *bi0 = op->o_bd->bd_info;
        int i;
-       long stoptime = 0;
+       long stoptime = 0, starttime;
        glue_state gs = {NULL, NULL, NULL, 0, 0, 0, 0};
        slap_callback cb = { NULL, glue_op_response, NULL, NULL };
        int scope0, tlimit0;
@@ -304,6 +304,7 @@ glue_op_search ( Operation *op, SlapReply *rs )
 
        cb.sc_next = op->o_callback;
 
+       starttime = op->o_time;
        stoptime = slap_get_time () + op->ors_tlimit;
 
        op->o_bd = glue_back_select (b0, &op->o_req_ndn);
@@ -347,7 +348,8 @@ glue_op_search ( Operation *op, SlapReply *rs )
                        if (!dnIsSuffix(&btmp->be_nsuffix[0], &b1->be_nsuffix[0]))
                                continue;
                        if (tlimit0 != SLAP_NO_LIMIT) {
-                               op->ors_tlimit = stoptime - slap_get_time ();
+                               op->o_time = slap_get_time();
+                               op->ors_tlimit = stoptime - op->o_time;
                                if (op->ors_tlimit <= 0) {
                                        rs->sr_err = gs.err = LDAP_TIMELIMIT_EXCEEDED;
                                        break;
@@ -419,6 +421,7 @@ glue_op_search ( Operation *op, SlapReply *rs )
 end_of_loop:;
                op->ors_scope = scope0;
                op->ors_tlimit = tlimit0;
+               op->o_time = starttime;
                op->o_req_dn = dn;
                op->o_req_ndn = ndn;
 
index 8cf659b1ca6d62e4d80bbd5925571b1a5cec16c0..2f4528645074d32f1169648bda14ca298587098f 100644 (file)
@@ -40,6 +40,8 @@
 static struct berval config_rdn = BER_BVC("cn=config");
 static struct berval schema_rdn = BER_BVC("cn=schema");
 
+extern int slap_DN_strict;     /* dn.c */
+
 #ifdef SLAPD_MODULES
 typedef struct modpath_s {
        struct modpath_s *mp_next;
@@ -86,7 +88,7 @@ static ConfigFile *cfn;
 static Avlnode *CfOcTree;
 
 static int config_add_internal( CfBackInfo *cfb, Entry *e, ConfigArgs *ca,
-       SlapReply *rs, int *renumber );
+       SlapReply *rs, int *renumber, Operation *op );
 
 static ConfigDriver config_fname;
 static ConfigDriver config_cfdir;
@@ -213,6 +215,11 @@ static OidRec OidMacros[] = {
  * OLcfgOv{Oc|At}:7                    -> distproc
  * OLcfgOv{Oc|At}:8                    -> dynlist
  * OLcfgOv{Oc|At}:9                    -> dds
+ * OLcfgOv{Oc|At}:10           -> unique
+ * OLcfgOv{Oc|At}:11           -> refint
+ * OLcfgOv{Oc|At}:12           -> ppolicy
+ * OLcfgOv{Oc|At}:13           -> constraint
+ * OLcfgOv{Oc|At}:14           -> translucent
  */
 
 /* alphabetical ordering */
@@ -335,6 +342,7 @@ static ConfigTable config_back_cf_table[] = {
                        "SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL },
        { "limits", "limits", 2, 0, 0, ARG_DB|ARG_MAGIC|CFG_LIMITS,
                &config_generic, "( OLcfgDbAt:0.5 NAME 'olcLimits' "
+                       "EQUALITY caseIgnoreMatch "
                        "SYNTAX OMsDirectoryString X-ORDERED 'VALUES' )", NULL, NULL },
        { "localSSF", "ssf", 2, 2, 0, ARG_INT,
                &local_ssf, "( OLcfgGlAt:26 NAME 'olcLocalSSF' "
@@ -344,6 +352,7 @@ static ConfigTable config_back_cf_table[] = {
                        "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
        { "loglevel", "level", 2, 0, 0, ARG_MAGIC,
                &config_loglevel, "( OLcfgGlAt:28 NAME 'olcLogLevel' "
+                       "EQUALITY caseIgnoreMatch "
                        "SYNTAX OMsDirectoryString )", NULL, NULL },
        { "maxDerefDepth", "depth", 2, 2, 0, ARG_DB|ARG_INT|ARG_MAGIC|CFG_DEPTH,
                &config_generic, "( OLcfgDbAt:0.6 NAME 'olcMaxDerefDepth' "
@@ -358,6 +367,7 @@ static ConfigTable config_back_cf_table[] = {
                ARG_IGNORED, NULL,
 #endif
                "( OLcfgGlAt:30 NAME 'olcModuleLoad' "
+                       "EQUALITY caseIgnoreMatch "
                        "SYNTAX OMsDirectoryString X-ORDERED 'VALUES' )", NULL, NULL },
        { "modulepath", "path", 2, 2, 0,
 #ifdef SLAPD_MODULES
@@ -375,6 +385,7 @@ static ConfigTable config_back_cf_table[] = {
                        NULL, NULL },
        { "objectidentifier", NULL,     0, 0, 0, ARG_MAGIC|CFG_OID,
                &config_generic, "( OLcfgGlAt:33 NAME 'olcObjectIdentifier' "
+                       "EQUALITY caseIgnoreMatch "
                        "SYNTAX OMsDirectoryString X-ORDERED 'VALUES' )", NULL, NULL },
        { "overlay", "overlay", 2, 2, 0, ARG_MAGIC,
                &config_overlay, "( OLcfgGlAt:34 NAME 'olcOverlay' "
@@ -384,6 +395,7 @@ static ConfigTable config_back_cf_table[] = {
                        "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
        { "password-hash", "hash", 2, 2, 0, ARG_MAGIC,
                &config_passwd_hash, "( OLcfgGlAt:36 NAME 'olcPasswordHash' "
+                       "EQUALITY caseIgnoreMatch "
                        "SYNTAX OMsDirectoryString )", NULL, NULL },
        { "pidfile", "file", 2, 2, 0, ARG_STRING,
                &slapd_pid_file, "( OLcfgGlAt:37 NAME 'olcPidFile' "
@@ -395,6 +407,7 @@ static ConfigTable config_back_cf_table[] = {
                ARG_IGNORED, NULL,
 #endif
                "( OLcfgGlAt:38 NAME 'olcPlugin' "
+                       "EQUALITY caseIgnoreMatch "
                        "SYNTAX OMsDirectoryString )", NULL, NULL },
        { "pluginlog", "filename", 2, 2, 0,
 #ifdef LDAP_SLAPI
@@ -412,6 +425,7 @@ static ConfigTable config_back_cf_table[] = {
                        "SUP labeledURI SINGLE-VALUE )", NULL, NULL },
        { "replica", "host or uri", 2, 0, 0, ARG_DB|ARG_MAGIC,
                &config_replica, "( OLcfgDbAt:0.7 NAME 'olcReplica' "
+                       "EQUALITY caseIgnoreMatch "
                        "SUP labeledURI X-ORDERED 'VALUES' )", NULL, NULL },
        { "replica-argsfile", NULL, 0, 0, 0, ARG_MAY_DB|ARG_MAGIC|ARG_STRING|CFG_REPLICA_ARGSFILE,
                &config_generic, "( OLcfgGlAt:43 NAME 'olcReplicaArgsFile' "
@@ -427,9 +441,11 @@ static ConfigTable config_back_cf_table[] = {
                        "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
        { "require", "features", 2, 0, 7, ARG_MAY_DB|ARG_MAGIC,
                &config_requires, "( OLcfgGlAt:47 NAME 'olcRequires' "
+                       "EQUALITY caseIgnoreMatch "
                        "SYNTAX OMsDirectoryString )", NULL, NULL },
        { "restrict", "op_list", 2, 0, 0, ARG_MAY_DB|ARG_MAGIC,
                &config_restrict, "( OLcfgGlAt:48 NAME 'olcRestrict' "
+                       "EQUALITY caseIgnoreMatch "
                        "SYNTAX OMsDirectoryString )", NULL, NULL },
        { "reverse-lookup", "on|off", 2, 2, 0,
 #ifdef SLAPD_RLOOKUPS
@@ -444,6 +460,7 @@ static ConfigTable config_back_cf_table[] = {
                        "SYNTAX OMsDN SINGLE-VALUE )", NULL, NULL },
        { "rootDSE", "file", 2, 2, 0, ARG_MAGIC|CFG_ROOTDSE,
                &config_generic, "( OLcfgGlAt:51 NAME 'olcRootDSE' "
+                       "EQUALITY caseIgnoreMatch "
                        "SYNTAX OMsDirectoryString )", NULL, NULL },
        { "rootpw", "password", 2, 2, 0, ARG_BERVAL|ARG_DB|ARG_MAGIC,
                &config_rootpw, "( OLcfgDbAt:0.9 NAME 'olcRootPW' "
@@ -483,6 +500,7 @@ static ConfigTable config_back_cf_table[] = {
                        "SYNTAX OMsDN SINGLE-VALUE )", NULL, NULL },
        { "security", "factors", 2, 0, 0, ARG_MAY_DB|ARG_MAGIC,
                &config_security, "( OLcfgGlAt:59 NAME 'olcSecurity' "
+                       "EQUALITY caseIgnoreMatch "
                        "SYNTAX OMsDirectoryString )", NULL, NULL },
        { "sizelimit", "limit", 2, 0, 0, ARG_MAY_DB|ARG_MAGIC,
                &config_sizelimit, "( OLcfgGlAt:60 NAME 'olcSizeLimit' "
@@ -503,9 +521,10 @@ static ConfigTable config_back_cf_table[] = {
                        "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
        { "subordinate", "[advertise]", 1, 2, 0, ARG_DB|ARG_MAGIC,
                &config_subordinate, "( OLcfgDbAt:0.15 NAME 'olcSubordinate' "
-                       "SYNTAX OMsDirectoryString )", NULL, NULL },
+                       "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
        { "suffix",     "suffix", 2, 2, 0, ARG_DB|ARG_DN|ARG_QUOTE|ARG_MAGIC,
                &config_suffix, "( OLcfgDbAt:0.10 NAME 'olcSuffix' "
+                       "EQUALITY distinguishedNameMatch "
                        "SYNTAX OMsDN )", NULL, NULL },
        { "syncrepl", NULL, 0, 0, 0, ARG_DB|ARG_MAGIC,
                &syncrepl_config, "( OLcfgDbAt:0.11 NAME 'olcSyncrepl' "
@@ -603,6 +622,7 @@ static ConfigTable config_back_cf_table[] = {
                        "SYNTAX OMsDN SINGLE-VALUE )", NULL, NULL },
        { "updateref", "url", 2, 2, 0, ARG_DB|ARG_MAGIC,
                &config_updateref, "( OLcfgDbAt:0.13 NAME 'olcUpdateRef' "
+                       "EQUALITY caseIgnoreMatch "
                        "SUP labeledURI )", NULL, NULL },
        { NULL, NULL, 0, 0, 0, ARG_IGNORED,
                NULL, NULL, NULL, NULL }
@@ -1238,7 +1258,16 @@ config_generic(ConfigArgs *c) {
                        break;
 
                case CFG_ACL:
-                       if ( parse_acl(c->be, c->fname, c->lineno, c->argc, c->argv, c->valx ) ) {
+                       /* Don't append to the global ACL if we're on a specific DB */
+                       i = c->valx;
+                       if ( c->be != frontendDB && frontendDB->be_acl && c->valx == -1 ) {
+                               AccessControl *a;
+                               i = 0;
+                               for ( a=c->be->be_acl; a && a != frontendDB->be_acl;
+                                       a = a->acl_next )
+                                       i++;
+                       }
+                       if ( parse_acl(c->be, c->fname, c->lineno, c->argc, c->argv, i ) ) {
                                return 1;
                        }
                        break;
@@ -2602,6 +2631,10 @@ config_replica(ConfigArgs *c) {
                                /* dealt with separately; don't let it get to bindconf */
                                ;
 
+                       } else if(!strncasecmp(c->argv[i], "host=", STRLENOF("host="))) {
+                               /* dealt with separately; don't let it get to bindconf */
+                               ;
+
                        } else if(!strncasecmp(c->argv[i], "suffix=", STRLENOF( "suffix="))) {
                                switch(add_replica_suffix(c->be, nr, c->argv[i] + STRLENOF("suffix="))) {
                                        case 1:
@@ -2924,7 +2957,7 @@ config_ldif_resp( Operation *op, SlapReply *rs )
                setup_cookie *sc = op->o_callback->sc_private;
 
                sc->cfb->cb_got_ldif = 1;
-               rs->sr_err = config_add_internal( sc->cfb, rs->sr_entry, sc->ca, NULL, NULL );
+               rs->sr_err = config_add_internal( sc->cfb, rs->sr_entry, sc->ca, NULL, NULL, NULL );
                if ( rs->sr_err != LDAP_SUCCESS ) {
                        Debug( LDAP_DEBUG_ANY, "config error processing %s: %s\n",
                                rs->sr_entry->e_name.bv_val, sc->ca->msg, 0 );
@@ -2997,6 +3030,7 @@ config_setup_ldif( BackendDB *be, const char *dir, int readit ) {
 
        if ( readit ) {
                void *thrctx = ldap_pvt_thread_pool_context();
+               int prev_DN_strict;
 
                op = (Operation *) &opbuf;
                connection_fake_init( &conn, op, thrctx );
@@ -3027,8 +3061,16 @@ config_setup_ldif( BackendDB *be, const char *dir, int readit ) {
                cb.sc_private = &sc;
 
                op->o_bd = &cfb->cb_db;
+               
+               /* Allow unknown attrs in DNs */
+               prev_DN_strict = slap_DN_strict;
+               slap_DN_strict = 0;
+
                rc = op->o_bd->be_search( op, &rs );
 
+               /* Restore normal DN validation */
+               slap_DN_strict = prev_DN_strict;
+
                ldap_pvt_thread_pool_context_reset( thrctx );
        }
 
@@ -3082,6 +3124,7 @@ read_config(const char *fname, const char *dir) {
                return 1;
 
        cfb = be->be_private;
+       be->be_dfltaccess = ACL_NONE;
 
        /* If no .conf, or a dir was specified, setup the dir */
        if ( !fname || dir ) {
@@ -3107,10 +3150,18 @@ read_config(const char *fname, const char *dir) {
                        if ( rc != LDAP_NO_SUCH_OBJECT )
                                return 1;
                        /* ITS#4194: But if dir was specified and no fname,
-                        * then we were supposed to read the dir.
+                        * then we were supposed to read the dir. Unless we're
+                        * trying to slapadd the dir...
                         */
-                       if ( dir && !fname )
-                               return 1;
+                       if ( dir && !fname ) {
+                               if ( slapMode & (SLAP_SERVER_MODE|SLAP_TOOL_READMAIN|SLAP_TOOL_READONLY))
+                                       return 1;
+                               /* Assume it's slapadd with a config dir, let it continue */
+                               rc = 0;
+                               cfb->cb_got_ldif = 1;
+                               cfb->cb_use_ldif = 1;
+                               goto done;
+                       }
                }
 
                /* If we read the config from back-ldif, nothing to do here */
@@ -3130,25 +3181,6 @@ read_config(const char *fname, const char *dir) {
        if ( rc == 0 )
                ber_str2bv( cfname, 0, 1, &cfb->cb_config->c_file );
 
-       /* If we got this far and failed, it may be a serious problem. In server
-        * mode, we should never come to this. However, it may be alright if we're
-        * using slapadd to create the conf dir.
-        */
-       while ( rc ) {
-               if ( slapMode & (SLAP_SERVER_MODE|SLAP_TOOL_READMAIN|SLAP_TOOL_READONLY))
-                       break;
-               /* If a config file was explicitly given, fail */
-               if ( fname )
-                       break;
-               
-               /* Seems to be slapadd with a config dir, let it continue */
-               if ( cfb->cb_use_ldif ) {
-                       rc = 0;
-                       cfb->cb_got_ldif = 1;
-               }
-               break;
-       }
-
 done:
        if ( rc == 0 && BER_BVISNULL( &frontendDB->be_schemadn ) ) {
                ber_str2bv( SLAPD_SCHEMA_DN, STRLENOF( SLAPD_SCHEMA_DN ), 1,
@@ -3557,7 +3589,8 @@ cfAddOverlay( CfEntryInfo *p, Entry *e, struct config_args_s *ca )
 
 /* Parse an LDAP entry into config directives */
 static int
-config_add_internal( CfBackInfo *cfb, Entry *e, ConfigArgs *ca, SlapReply *rs, int *renum )
+config_add_internal( CfBackInfo *cfb, Entry *e, ConfigArgs *ca, SlapReply *rs,
+       int *renum, Operation *op )
 {
        CfEntryInfo *ce, *last;
        ConfigOCs **colst;
@@ -3583,6 +3616,15 @@ config_add_internal( CfBackInfo *cfb, Entry *e, ConfigArgs *ca, SlapReply *rs, i
                return LDAP_NO_SUCH_OBJECT;
        }
 
+       if ( op ) {
+               /* No parent, must be root. This will never happen... */
+               if ( !last && !be_isroot( op ) && !be_shadow_update( op ))
+                       return LDAP_NO_SUCH_OBJECT;
+               if ( last && !access_allowed( op, last->ce_entry,
+                       slap_schema.si_ad_children, NULL, ACL_WADD, NULL ))
+                       return LDAP_INSUFFICIENT_ACCESS;
+       }
+
        oc_at = attr_find( e->e_attrs, slap_schema.si_ad_objectClass );
        if ( !oc_at ) return LDAP_OBJECT_CLASS_VIOLATION;
 
@@ -3764,7 +3806,8 @@ config_back_add( Operation *op, SlapReply *rs )
        int renumber;
        ConfigArgs ca;
 
-       if ( !be_isroot( op ) ) {
+       if ( !access_allowed( op, op->ora_e, slap_schema.si_ad_entry,
+               NULL, ACL_WADD, NULL )) {
                rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
                goto out;
        }
@@ -3782,7 +3825,7 @@ config_back_add( Operation *op, SlapReply *rs )
         */
        /* NOTE: by now we do not accept adds that require renumbering */
        renumber = -1;
-       rs->sr_err = config_add_internal( cfb, op->ora_e, &ca, rs, &renumber );
+       rs->sr_err = config_add_internal( cfb, op->ora_e, &ca, rs, &renumber, op );
        if ( rs->sr_err != LDAP_SUCCESS ) {
                rs->sr_text = ca.msg;
                goto out2;
@@ -4101,11 +4144,6 @@ config_back_modify( Operation *op, SlapReply *rs )
        char *ptr;
        AttributeDescription *rad = NULL;
 
-       if ( !be_isroot( op ) ) {
-               rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
-               goto out;
-       }
-
        cfb = (CfBackInfo *)op->o_bd->be_private;
 
        ce = config_find_base( cfb->cb_root, &op->o_req_ndn, &last );
@@ -4116,6 +4154,11 @@ config_back_modify( Operation *op, SlapReply *rs )
                goto out;
        }
 
+       if ( !acl_check_modlist( op, ce->ce_entry, op->orm_modlist )) {
+               rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
+               goto out;
+       }
+
        /* Get type of RDN */
        rdn = ce->ce_entry->e_nname;
        ptr = strchr( rdn.bv_val, '=' );
@@ -4176,11 +4219,6 @@ config_back_modrdn( Operation *op, SlapReply *rs )
        CfBackInfo *cfb;
        CfEntryInfo *ce, *last;
 
-       if ( !be_isroot( op ) ) {
-               rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
-               goto out;
-       }
-
        cfb = (CfBackInfo *)op->o_bd->be_private;
 
        ce = config_find_base( cfb->cb_root, &op->o_req_ndn, &last );
@@ -4190,6 +4228,22 @@ config_back_modrdn( Operation *op, SlapReply *rs )
                rs->sr_err = LDAP_NO_SUCH_OBJECT;
                goto out;
        }
+       if ( !access_allowed( op, ce->ce_entry, slap_schema.si_ad_entry,
+               NULL, ACL_WRITE, NULL )) {
+               rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
+               goto out;
+       }
+       { Entry *parent;
+               if ( ce->ce_parent )
+                       parent = ce->ce_parent->ce_entry;
+               else
+                       parent = (Entry *)&slap_entry_root;
+               if ( !access_allowed( op, parent, slap_schema.si_ad_children,
+                       NULL, ACL_WRITE, NULL )) {
+                       rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
+                       goto out;
+               }
+       }
 
        /* We don't allow moving objects to new parents.
         * Generally we only allow reordering a set of ordered entries.
@@ -4214,11 +4268,7 @@ config_back_search( Operation *op, SlapReply *rs )
 {
        CfBackInfo *cfb;
        CfEntryInfo *ce, *last;
-
-       if ( !be_isroot( op ) ) {
-               rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
-               goto out;
-       }
+       slap_mask_t mask;
 
        cfb = (CfBackInfo *)op->o_bd->be_private;
 
@@ -4229,6 +4279,16 @@ config_back_search( Operation *op, SlapReply *rs )
                rs->sr_err = LDAP_NO_SUCH_OBJECT;
                goto out;
        }
+       if ( !access_allowed_mask( op, ce->ce_entry, slap_schema.si_ad_entry, NULL,
+               ACL_SEARCH, NULL, &mask ))
+       {
+               if ( !ACL_GRANT( mask, ACL_DISCLOSE )) {
+                       rs->sr_err = LDAP_NO_SUCH_OBJECT;
+               } else {
+                       rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
+               }
+               goto out;
+       }
        switch ( op->ors_scope ) {
        case LDAP_SCOPE_BASE:
        case LDAP_SCOPE_SUBTREE:
@@ -4469,6 +4529,10 @@ config_build_modules( ConfigArgs *c, CfEntryInfo *ceparent,
 }
 #endif
 
+static const char *defacl[] = {
+       NULL, "to", "*", "by", "*", "none", NULL
+};
+
 static int
 config_back_db_open( BackendDB *be )
 {
@@ -4487,6 +4551,14 @@ config_back_db_open( BackendDB *be )
        void *thrctx = NULL;
 
        Debug( LDAP_DEBUG_TRACE, "config_back_db_open\n", 0, 0, 0);
+
+       /* If we have no explicitly configured ACLs, don't just use
+        * the global ACLs. Explicitly deny access to everything.
+        */
+       if ( frontendDB->be_acl && be->be_acl == frontendDB->be_acl ) {
+               parse_acl(be, "config_back_db_open", 0, 6, (char **)defacl, 0 );
+       }
+
        /* If we read the config from back-ldif, nothing to do here */
        if ( cfb->cb_got_ldif )
                return 0;
@@ -4845,7 +4917,7 @@ config_tool_entry_put( BackendDB *be, Entry *e, struct berval *text )
        ConfigArgs ca;
 
        if ( bi && bi->bi_tool_entry_put &&
-               config_add_internal( cfb, e, &ca, NULL, NULL ) == 0 )
+               config_add_internal( cfb, e, &ca, NULL, NULL, NULL ) == 0 )
                return bi->bi_tool_entry_put( &cfb->cb_db, e, text );
        else
                return NOID;
@@ -4928,7 +5000,7 @@ config_back_initialize( BackendInfo *bi )
 
        bi->bi_chk_referrals = 0;
 
-       bi->bi_access_allowed = slap_access_always_allowed;
+       bi->bi_access_allowed = slap_access_allowed;
 
        bi->bi_connection_init = 0;
        bi->bi_connection_destroy = 0;
index 34ebb1d25cd4df9f5d2a1b2f604439814aeca354..d6e09186f2fb36dc5ed06256057682ff70338d47 100644 (file)
@@ -120,17 +120,20 @@ ConfigTable *config_find_keyword(ConfigTable *Conf, ConfigArgs *c) {
 }
 
 int config_check_vals(ConfigTable *Conf, ConfigArgs *c, int check_only ) {
-       int rc, arg_user, arg_type, iarg;
+       int rc, arg_user, arg_type, arg_syn, iarg;
        long larg;
        ber_len_t barg;
        
-       arg_type = Conf->arg_type;
-       if(arg_type == ARG_IGNORED) {
+       if(Conf->arg_type == ARG_IGNORED) {
                Debug(LDAP_DEBUG_CONFIG, "%s: keyword <%s> ignored\n",
                        c->log, Conf->name, 0);
                return(0);
        }
-       if((arg_type & ARG_DN) && c->argc == 1) {
+       arg_type = Conf->arg_type & ARGS_TYPES;
+       arg_user = Conf->arg_type & ARGS_USERLAND;
+       arg_syn = Conf->arg_type & ARGS_SYNTAX;
+
+       if((arg_type == ARG_DN) && c->argc == 1) {
                c->argc = 2;
                c->argv[1] = "";
        }
@@ -155,46 +158,66 @@ int config_check_vals(ConfigTable *Conf, ConfigArgs *c, int check_only ) {
                return(ARG_BAD_CONF);
 #endif /* LDAP_DEVEL */
        }
-       if((arg_type & ARG_DB) && !c->be) {
+       if((arg_syn & ARG_DB) && !c->be) {
                snprintf( c->msg, sizeof( c->msg ), "<%s> only allowed within database declaration",
                        c->argv[0] );
                Debug(LDAP_DEBUG_CONFIG, "%s: keyword %s\n",
                        c->log, c->msg, 0);
                return(ARG_BAD_CONF);
        }
-       if((arg_type & ARG_PRE_BI) && c->bi) {
+       if((arg_syn & ARG_PRE_BI) && c->bi) {
                snprintf( c->msg, sizeof( c->msg ), "<%s> must occur before any backend %sdeclaration",
-                       c->argv[0], (arg_type & ARG_PRE_DB) ? "or database " : "" );
+                       c->argv[0], (arg_syn & ARG_PRE_DB) ? "or database " : "" );
                Debug(LDAP_DEBUG_CONFIG, "%s: keyword %s\n",
                        c->log, c->msg, 0 );
                return(ARG_BAD_CONF);
        }
-       if((arg_type & ARG_PRE_DB) && c->be && c->be != frontendDB) {
+       if((arg_syn & ARG_PRE_DB) && c->be && c->be != frontendDB) {
                snprintf( c->msg, sizeof( c->msg ), "<%s> must occur before any database declaration",
                        c->argv[0] );
                Debug(LDAP_DEBUG_CONFIG, "%s: keyword %s\n",
                        c->log, c->msg, 0);
                return(ARG_BAD_CONF);
        }
-       if((arg_type & ARG_PAREN) && *c->argv[1] != '(' /*')'*/) {
+       if((arg_syn & ARG_PAREN) && *c->argv[1] != '(' /*')'*/) {
                snprintf( c->msg, sizeof( c->msg ), "<%s> old format not supported", c->argv[0] );
                Debug(LDAP_DEBUG_CONFIG, "%s: %s\n",
                        c->log, c->msg, 0);
                return(ARG_BAD_CONF);
        }
-       if((arg_type & ARGS_POINTER) && !Conf->arg_item && !(arg_type & ARG_OFFSET)) {
+       if(arg_type && !Conf->arg_item && !(arg_syn & ARG_OFFSET)) {
                snprintf( c->msg, sizeof( c->msg ), "<%s> invalid config_table, arg_item is NULL",
                        c->argv[0] );
                Debug(LDAP_DEBUG_CONFIG, "%s: %s\n",
                        c->log, c->msg, 0);
                return(ARG_BAD_CONF);
        }
-       c->type = arg_user = (arg_type & ARGS_USERLAND);
+       c->type = arg_user;
        memset(&c->values, 0, sizeof(c->values));
-       if(arg_type & ARGS_NUMERIC) {
+       if(arg_type == ARG_STRING) {
+               if ( !check_only )
+                       c->value_string = ch_strdup(c->argv[1]);
+       } else if(arg_type == ARG_BERVAL) {
+               if ( !check_only )
+                       ber_str2bv( c->argv[1], 0, 1, &c->value_bv );
+       } else if(arg_type == ARG_DN) {
+               struct berval bv;
+               ber_str2bv( c->argv[1], 0, 0, &bv );
+               rc = dnPrettyNormal( NULL, &bv, &c->value_dn, &c->value_ndn, NULL );
+               if ( rc != LDAP_SUCCESS ) {
+                       snprintf( c->msg, sizeof( c->msg ), "<%s> invalid DN %d (%s)",
+                               c->argv[0], rc, ldap_err2string( rc ));
+                       Debug(LDAP_DEBUG_CONFIG, "%s: %s\n" , c->log, c->msg, 0);
+                       return(ARG_BAD_CONF);
+               }
+               if ( check_only ) {
+                       ch_free( c->value_ndn.bv_val );
+                       ch_free( c->value_dn.bv_val );
+               }
+       } else {        /* all numeric */
                int j;
                iarg = 0; larg = 0; barg = 0;
-               switch(arg_type & ARGS_NUMERIC) {
+               switch(arg_type) {
                        case ARG_INT:
                                if ( lutil_atoix( &iarg, c->argv[1], 0 ) != 0 ) {
                                        snprintf( c->msg, sizeof( c->msg ),
@@ -258,32 +281,12 @@ int config_check_vals(ConfigTable *Conf, ConfigArgs *c, int check_only ) {
                                c->log, c->msg, 0 );
                        return(ARG_BAD_CONF);
                }
-               switch(arg_type & ARGS_NUMERIC) {
+               switch(arg_type) {
                        case ARG_ON_OFF:
                        case ARG_INT:           c->value_int = iarg;            break;
                        case ARG_LONG:          c->value_long = larg;           break;
                        case ARG_BER_LEN_T:     c->value_ber_t = barg;          break;
                }
-       } else if(arg_type & ARG_STRING) {
-               if ( !check_only )
-                       c->value_string = ch_strdup(c->argv[1]);
-       } else if(arg_type & ARG_BERVAL) {
-               if ( !check_only )
-                       ber_str2bv( c->argv[1], 0, 1, &c->value_bv );
-       } else if(arg_type & ARG_DN) {
-               struct berval bv;
-               ber_str2bv( c->argv[1], 0, 0, &bv );
-               rc = dnPrettyNormal( NULL, &bv, &c->value_dn, &c->value_ndn, NULL );
-               if ( rc != LDAP_SUCCESS ) {
-                       snprintf( c->msg, sizeof( c->msg ), "<%s> invalid DN %d (%s)",
-                               c->argv[0], rc, ldap_err2string( rc ));
-                       Debug(LDAP_DEBUG_CONFIG, "%s: %s\n" , c->log, c->msg, 0);
-                       return(ARG_BAD_CONF);
-               }
-               if ( check_only ) {
-                       ch_free( c->value_ndn.bv_val );
-                       ch_free( c->value_dn.bv_val );
-               }
        }
        return 0;
 }
@@ -324,11 +327,11 @@ int config_set_vals(ConfigTable *Conf, ConfigArgs *c) {
                        return(ARG_BAD_CONF);
                }
                ptr = (void *)((char *)ptr + (long)Conf->arg_item);
-       } else if (arg_type & ARGS_POINTER) {
+       } else if (arg_type & ARGS_TYPES) {
                ptr = Conf->arg_item;
        }
-       if(arg_type & ARGS_POINTER)
-               switch(arg_type & ARGS_POINTER) {
+       if(arg_type & ARGS_TYPES)
+               switch(arg_type & ARGS_TYPES) {
                        case ARG_ON_OFF:
                        case ARG_INT:           *(int*)ptr = c->value_int;                      break;
                        case ARG_LONG:          *(long*)ptr = c->value_long;                    break;
@@ -414,7 +417,7 @@ config_get_vals(ConfigTable *cf, ConfigArgs *c)
                        ptr = cf->arg_item;
                }
                
-               switch(cf->arg_type & ARGS_POINTER) {
+               switch(cf->arg_type & ARGS_TYPES) {
                case ARG_ON_OFF:
                case ARG_INT:   c->value_int = *(int *)ptr; break;
                case ARG_LONG:  c->value_long = *(long *)ptr; break;
@@ -427,9 +430,9 @@ config_get_vals(ConfigTable *cf, ConfigArgs *c)
                        ber_dupbv( &c->value_bv, (struct berval *)ptr ); break;
                }
        }
-       if ( cf->arg_type & ARGS_POINTER) {
+       if ( cf->arg_type & ARGS_TYPES) {
                bv.bv_val = c->log;
-               switch(cf->arg_type & ARGS_POINTER) {
+               switch(cf->arg_type & ARGS_TYPES) {
                case ARG_INT: bv.bv_len = snprintf(bv.bv_val, sizeof( c->log ), "%d", c->value_int); break;
                case ARG_LONG: bv.bv_len = snprintf(bv.bv_val, sizeof( c->log ), "%ld", c->value_long); break;
                case ARG_BER_LEN_T: bv.bv_len = snprintf(bv.bv_val, sizeof( c->log ), "%ld", c->value_ber_t); break;
@@ -453,7 +456,7 @@ config_get_vals(ConfigTable *cf, ConfigArgs *c)
                if (bv.bv_val == c->log && bv.bv_len >= sizeof( c->log ) ) {
                        return 1;
                }
-               if (( cf->arg_type & ARGS_POINTER ) == ARG_STRING )
+               if (( cf->arg_type & ARGS_TYPES ) == ARG_STRING )
                        ber_bvarray_add(&c->rvalue_vals, &bv);
                else
                        value_add_one(&c->rvalue_vals, &bv);
@@ -1011,12 +1014,14 @@ enum_to_verb(slap_verbmasks *v, slap_mask_t m, struct berval *bv) {
        return -1;
 }
 
+#ifdef HAVE_TLS
 static slap_verbmasks tlskey[] = {
        { BER_BVC("no"),        SB_TLS_OFF },
        { BER_BVC("yes"),       SB_TLS_ON },
        { BER_BVC("critical"),  SB_TLS_CRITICAL },
        { BER_BVNULL, 0 }
 };
+#endif
 
 static slap_verbmasks methkey[] = {
        { BER_BVC("none"),      LDAP_AUTH_NONE },
@@ -1029,7 +1034,6 @@ static slap_verbmasks methkey[] = {
 
 static slap_cf_aux_table bindkey[] = {
        { BER_BVC("uri="), offsetof(slap_bindconf, sb_uri), 'b', 1, NULL },
-       { BER_BVC("starttls="), offsetof(slap_bindconf, sb_tls), 'd', 0, tlskey },
        { BER_BVC("bindmethod="), offsetof(slap_bindconf, sb_method), 'd', 0, methkey },
        { BER_BVC("binddn="), offsetof(slap_bindconf, sb_binddn), 'b', 1, NULL },
        { BER_BVC("credentials="), offsetof(slap_bindconf, sb_cred), 'b', 1, NULL },
@@ -1039,6 +1043,10 @@ static slap_cf_aux_table bindkey[] = {
        { BER_BVC("authcID="), offsetof(slap_bindconf, sb_authcId), 'b', 0, NULL },
        { BER_BVC("authzID="), offsetof(slap_bindconf, sb_authzId), 'b', 1, NULL },
 #ifdef HAVE_TLS
+       { BER_BVC("starttls="), offsetof(slap_bindconf, sb_tls), 'd', 0, tlskey },
+
+#define aux_TLS (bindkey+10)   /* beginning of TLS keywords */
+
        { BER_BVC("tls_cert="), offsetof(slap_bindconf, sb_tls_cert), 's', 1, NULL },
        { BER_BVC("tls_key="), offsetof(slap_bindconf, sb_tls_key), 's', 1, NULL },
        { BER_BVC("tls_cacert="), offsetof(slap_bindconf, sb_tls_cacert), 's', 1, NULL },
@@ -1055,7 +1063,7 @@ static slap_cf_aux_table bindkey[] = {
 int
 slap_cf_aux_table_parse( const char *word, void *dst, slap_cf_aux_table *tab0, LDAP_CONST char *tabmsg )
 {
-       int rc = 0;
+       int rc = SLAP_CONF_UNKNOWN;
        slap_cf_aux_table *tab;
 
        for (tab = tab0; !BER_BVISNULL(&tab->key); tab++ ) {
@@ -1072,11 +1080,13 @@ slap_cf_aux_table_parse( const char *word, void *dst, slap_cf_aux_table *tab0, L
                        case 's':
                                cptr = (char **)((char *)dst + tab->off);
                                *cptr = ch_strdup( val );
+                               rc = 0;
                                break;
 
                        case 'b':
                                bptr = (struct berval *)((char *)dst + tab->off);
                                ber_str2bv( val, 0, 1, bptr );
+                               rc = 0;
                                break;
 
                        case 'd':
@@ -1216,6 +1226,13 @@ slap_cf_aux_table_unparse( void *src, struct berval *bv, slap_cf_aux_table *tab0
 int
 bindconf_parse( const char *word, slap_bindconf *bc )
 {
+#ifdef HAVE_TLS
+       /* Detect TLS config changes explicitly */
+       if ( slap_cf_aux_table_parse( word, bc, aux_TLS, "tls config" ) == 0 ) {
+               bc->sb_tls_do_init = 1;
+               return 0;
+       }
+#endif
        return slap_cf_aux_table_parse( word, bc, bindkey, "bind config" );
 }
 
@@ -1315,6 +1332,8 @@ int bindconf_tls_set( slap_bindconf *bc, LDAP *ld )
        int i, rc, newctx = 0, res = 0;
        char *ptr = (char *)bc, **word;
 
+       bc->sb_tls_do_init = 0;
+
        for (i=0; bindtlsopts[i].opt; i++) {
                word = (char **)(ptr + bindtlsopts[i].offset);
                if ( *word ) {
@@ -1354,6 +1373,11 @@ int bindconf_tls_set( slap_bindconf *bc, LDAP *ld )
 #endif
        if ( newctx ) {
                int opt = 0;
+
+               if ( bc->sb_tls_ctx ) {
+                       SSL_CTX_free( bc->sb_tls_ctx );
+                       bc->sb_tls_ctx = NULL;
+               }
                rc = ldap_set_option( ld, LDAP_OPT_X_TLS_NEWCTX, &opt );
                if ( rc )
                        res = rc;
index 0a57d4fdbf48a013193b9a8a2b3bc1b3ef239482..aaf4855eb0b9f5fbed213ce8d9ae855cd904eac0 100644 (file)
@@ -43,19 +43,19 @@ typedef enum {
 } ConfigType;
 
 #define ARGS_USERLAND  0x00000fff
-#define ARGS_TYPES     0x000ff000
-#define ARGS_POINTER   0x0003f000
-#define ARGS_NUMERIC   0x0000f000
+
+/* types are enumerated, not a bitmask */
+#define ARGS_TYPES     0x0000f000
 #define ARG_INT                0x00001000
 #define ARG_LONG       0x00002000
-#define ARG_BER_LEN_T  0x00004000
-#define ARG_ON_OFF     0x00008000
-#define ARG_STRING     0x00010000
-#define ARG_BERVAL     0x00020000
-#define ARG_DN         0x00040000
-#define ARG_IGNORED    0x00080000
+#define ARG_BER_LEN_T  0x00003000
+#define ARG_ON_OFF     0x00004000
+#define ARG_STRING     0x00005000
+#define ARG_BERVAL     0x00006000
+#define ARG_DN         0x00007000
 
-#define ARGS_SYNTAX    0xfff00000
+#define ARGS_SYNTAX    0xffff0000
+#define ARG_IGNORED    0x00080000
 #define ARG_PRE_BI     0x00100000
 #define ARG_PRE_DB     0x00200000
 #define ARG_DB         0x00400000      /* Only applies to DB */
index 46c28dfc1e358f0e71928b5f577f952614cfd2ab..4cf698c15b3767c8b135aca7487d392c0eedcc36 100644 (file)
 #include "slapi/slapi.h"
 #endif
 
-#ifdef SLAP_MULTI_CONN_ARRAY
-/* for Multiple Connection Arrary (MCA) Support */
-static ldap_pvt_thread_mutex_t* connections_mutex;
-static Connection **connections = NULL;
-
-/* set to the number of processors (round up to a power of 2) */
-#      define NUM_CONNECTION_ARRAY 4
-
-/* partition the array in a modulo manner */
-#      define MCA_conn_array_id(fd)            ((int)(fd)%NUM_CONNECTION_ARRAY)
-#      define MCA_conn_array_element_id(fd)    ((int)(fd)/NUM_CONNECTION_ARRAY)
-#      define MCA_ARRAY_SIZE                   ((int)(MCA_conn_array_element_id(dtblsize) + (MCA_conn_array_id(dtblsize) ? 1 : 0)))
-#      define MCA_conn_check(fd)               (dtblsize > 0 && (fd) >= 0 && (fd) < (MCA_ARRAY_SIZE*NUM_CONNECTION_ARRAY))
-#      define MCA_GET_CONNECTION(fd) (&(connections[MCA_conn_array_id(fd)]) \
-               [MCA_conn_array_element_id(fd)])
-#      define MCA_GET_CONN_MUTEX(fd) (&connections_mutex[MCA_conn_array_id(fd)])
-
-#else
 /* protected by connections_mutex */
 static ldap_pvt_thread_mutex_t connections_mutex;
 static Connection *connections = NULL;
 
-#      define MCA_conn_check(fd)               (dtblsize > 0 && (fd) < dtblsize)
-#      define MCA_GET_CONNECTION(fd) (&connections[s])
-#      define MCA_GET_CONN_MUTEX(fd) (&connections_mutex)
-#endif
-
 static ldap_pvt_thread_mutex_t conn_nextid_mutex;
 static unsigned long conn_nextid = 0;
 
@@ -79,6 +56,7 @@ static const char conn_lost_str[] = "connection lost";
 #define SLAP_C_UNINITIALIZED   0x00    /* MUST BE ZERO (0) */
 #define SLAP_C_UNUSED                  0x01
 #define SLAP_C_USED                            0x02
+#define        SLAP_C_PENDING                  0x03
 
 /* connection state (protected by c_mutex ) */
 #define SLAP_C_INVALID                 0x00    /* MUST BE ZERO (0) */
@@ -134,69 +112,6 @@ static ldap_pvt_thread_start_t connection_operation;
  * Initialize connection management infrastructure.
  */
 int connections_init(void)
-#ifdef SLAP_MULTI_CONN_ARRAY
-{
-       int             i, j;
-       Connection*     conn;
-
-       assert( connections == NULL );
-
-       if( connections != NULL) {
-               Debug( LDAP_DEBUG_ANY, "connections_init: already initialized.\n",
-                       0, 0, 0 );
-               return -1;
-       }
-
-       connections_mutex = (ldap_pvt_thread_mutex_t*) ch_calloc(
-               NUM_CONNECTION_ARRAY, sizeof(ldap_pvt_thread_mutex_t) );
-       if( connections_mutex == NULL ) {
-               Debug( LDAP_DEBUG_ANY, "connections_init: "
-                       "allocation of connection mutexes failed\n", 0, 0, 0 );
-               return -1;
-       }
-
-       connections = (Connection**) ch_calloc(
-               NUM_CONNECTION_ARRAY, sizeof(Connection*));
-       if( connections == NULL ) {
-               Debug( LDAP_DEBUG_ANY, "connections_init: "
-                       "allocation of connection[%d] failed\n", 0, 0, 0 );
-               return -1;
-       }
-
-       for ( i = 0; i < NUM_CONNECTION_ARRAY; i++ ) {
-               ldap_pvt_thread_mutex_init( connections_mutex+i );
-               connections[i] = (Connection*) ch_calloc(
-                       MCA_ARRAY_SIZE, sizeof(Connection) );
-               if( connections[i] == NULL ) {
-                       Debug( LDAP_DEBUG_ANY, "connections_init: "
-                               "allocation (%d*%ld) of connection array[%d] failed\n",
-                               dtblsize, (long) sizeof(Connection), i );
-                       return -1;
-               }
-       }
-
-       /* should check return of every call */
-       ldap_pvt_thread_mutex_init( &conn_nextid_mutex );
-
-       assert( connections[0]->c_struct_state == SLAP_C_UNINITIALIZED );
-       assert( connections[NUM_CONNECTION_ARRAY-1]->c_struct_state ==
-               SLAP_C_UNINITIALIZED );
-
-       for ( i = 0; i < NUM_CONNECTION_ARRAY; i++ ) {
-               conn = connections[i];
-               for ( j = 0; j < MCA_ARRAY_SIZE; j++ ) {
-                       conn[j].c_conn_idx = j;
-               }
-       }
-
-       /*
-        * per entry initialization of the Connection array initialization
-        * will be done by connection_init()
-        */ 
-
-       return 0;
-}
-#else
 {
        int i;
 
@@ -233,58 +148,12 @@ int connections_init(void)
 
        return 0;
 }
-#endif
 
 /*
  * Destroy connection management infrastructure.
  */
 
 int connections_destroy(void)
-#ifdef SLAP_MULTI_CONN_ARRAY
-{
-       int i;
-       ber_socket_t j;
-
-       if( connections == NULL) {
-               Debug( LDAP_DEBUG_ANY, "connections_destroy: nothing to destroy.\n",
-                       0, 0, 0 );
-               return -1;
-       }
-
-    for ( i = 0; i < NUM_CONNECTION_ARRAY; i++ ) {
-               Connection* conn = connections[i];
-               for ( j = 0; j < MCA_ARRAY_SIZE; j++ ) {
-                       if( conn[j].c_struct_state != SLAP_C_UNINITIALIZED ) {
-                               ber_sockbuf_free( conn[j].c_sb );
-                               ldap_pvt_thread_mutex_destroy( &conn[j].c_mutex );
-                               ldap_pvt_thread_mutex_destroy( &conn[j].c_write_mutex );
-                               ldap_pvt_thread_cond_destroy( &conn[j].c_write_cv );
-#ifdef LDAP_SLAPI
-                               /* FIX ME!! */
-                               if ( slapi_plugins_used ) {
-                                       slapi_int_free_object_extensions( SLAPI_X_EXT_CONNECTION,
-                                               &connections[i] );
-                               }
-#endif
-                       }
-               }
-       }
-
-       for ( i = 0; i < NUM_CONNECTION_ARRAY; i++ ) {
-               free( connections[i] );
-               connections[i] = NULL;
-               ldap_pvt_thread_mutex_destroy( &connections_mutex[i] );
-       }
-
-       free( connections );
-       free( connections_mutex );
-
-       ldap_pvt_thread_mutex_destroy( &conn_nextid_mutex );
-
-       return 0;
-
-}
-#else
 {
        ber_socket_t i;
 
@@ -318,50 +187,14 @@ int connections_destroy(void)
        ldap_pvt_thread_mutex_destroy( &conn_nextid_mutex );
        return 0;
 }
-#endif
 
 /*
  * shutdown all connections
  */
 int connections_shutdown(void)
-#ifdef SLAP_MULTI_CONN_ARRAY
-{
-       int i;
-       ber_socket_t j;
-
-       for ( i = 0; i < NUM_CONNECTION_ARRAY; i++ ) {
-               Connection* conn = connections[i];
-               ldap_pvt_thread_mutex_lock( &connections_mutex[i] );
-               for ( j = 0; j < MCA_ARRAY_SIZE; j++ ) {
-                       if( conn[j].c_struct_state != SLAP_C_USED ) {
-                               continue;
-                       }
-                       /* give persistent clients a chance to cleanup */
-                       if( conn[j].c_conn_state == SLAP_C_CLIENT ) {
-                               ldap_pvt_thread_pool_submit( &connection_pool,
-                               conn[j].c_clientfunc, conn[j].c_clientarg );
-                               continue;
-                       }
-
-                       ldap_pvt_thread_mutex_lock( &conn[j].c_mutex );
-                       /* connections_mutex and c_mutex are locked */
-                       connection_closing( &conn[j], "connection shutdown" );
-                       connection_close( &conn[j] );
-                       ldap_pvt_thread_mutex_unlock( &conn[j].c_mutex );
-               }
-
-               ldap_pvt_thread_mutex_unlock( &connections_mutex[i] );
-       }
-
-       return 0;
-
-}
-#else
 {
        ber_socket_t i;
 
-       ldap_pvt_thread_mutex_lock( &connections_mutex );
-
        for ( i = 0; i < dtblsize; i++ ) {
                if( connections[i].c_struct_state != SLAP_C_USED ) {
                        continue;
@@ -375,18 +208,15 @@ int connections_shutdown(void)
 
                ldap_pvt_thread_mutex_lock( &connections[i].c_mutex );
 
-               /* connections_mutex and c_mutex are locked */
+               /* c_mutex is locked */
                connection_closing( &connections[i], "slapd shutdown" );
                connection_close( &connections[i] );
 
                ldap_pvt_thread_mutex_unlock( &connections[i].c_mutex );
        }
 
-       ldap_pvt_thread_mutex_unlock( &connections_mutex );
-
        return 0;
 }
-#endif
 
 /*
  * Timeout idle connections.
@@ -421,8 +251,6 @@ int connections_timeout_idle(time_t now)
 
 static Connection* connection_get( ber_socket_t s )
 {
-       /* connections_mutex should be locked by caller */
-
        Connection *c;
 
        Debug( LDAP_DEBUG_ARGS,
@@ -434,15 +262,19 @@ static Connection* connection_get( ber_socket_t s )
        if(s == AC_SOCKET_INVALID) return NULL;
 
 #ifndef HAVE_WINSOCK
-       assert( MCA_conn_check( s ) );
-       c = MCA_GET_CONNECTION(s);
+       assert( s < dtblsize );
+       c = &connections[s];
 
 #else
        c = NULL;
        {
                ber_socket_t i, sd;
 
+               ldap_pvt_thread_mutex_lock( &connections_mutex );
                for(i=0; i<dtblsize; i++) {
+                       if( connections[i].c_struct_state == SLAP_C_PENDING )
+                               continue;
+
                        if( connections[i].c_struct_state == SLAP_C_UNINITIALIZED ) {
                                assert( connections[i].c_conn_state == SLAP_C_INVALID );
                                assert( connections[i].c_sb == 0 );
@@ -467,6 +299,7 @@ static Connection* connection_get( ber_socket_t s )
                                break;
                        }
                }
+               ldap_pvt_thread_mutex_unlock( &connections_mutex );
        }
 #endif
 
@@ -529,6 +362,7 @@ long connection_init(
 {
        unsigned long id;
        Connection *c;
+       int doinit = 0;
 
        assert( connections != NULL );
 
@@ -549,24 +383,29 @@ long connection_init(
        assert( s >= 0 );
 #ifndef HAVE_WINSOCK
        assert( s < dtblsize );
-#endif
-
-       ldap_pvt_thread_mutex_lock( MCA_GET_CONN_MUTEX(s) );
-
-#ifndef HAVE_WINSOCK
-       assert( MCA_conn_check( s ) );
-       c = MCA_GET_CONNECTION(s);
+       c = &connections[s];
+       if( c->c_struct_state == SLAP_C_UNINITIALIZED ) {
+               doinit = 1;
+       } else {
+               assert( c->c_struct_state == SLAP_C_UNUSED );
+       }
 #else
        {
                ber_socket_t i;
                c = NULL;
 
+               ldap_pvt_thread_mutex_lock( &connections_mutex );
                for( i=0; i < dtblsize; i++) {
                        ber_socket_t    sd;
 
+                       if ( connections[i].c_struct_state == SLAP_C_PENDING )
+                               continue;
+
                        if( connections[i].c_struct_state == SLAP_C_UNINITIALIZED ) {
                                assert( connections[i].c_sb == 0 );
                                c = &connections[i];
+                               c->c_struct_state = SLAP_C_PENDING;
+                               doinit = 1;
                                break;
                        }
 
@@ -579,6 +418,7 @@ long connection_init(
                        if( connections[i].c_struct_state == SLAP_C_UNUSED ) {
                                assert( sd == AC_SOCKET_INVALID );
                                c = &connections[i];
+                               c->c_struct_state = SLAP_C_PENDING;
                                break;
                        }
 
@@ -588,20 +428,18 @@ long connection_init(
                        assert( connections[i].c_conn_state != SLAP_C_INVALID );
                        assert( sd != AC_SOCKET_INVALID );
                }
+               ldap_pvt_thread_mutex_unlock( &connections_mutex );
 
                if( c == NULL ) {
                        Debug( LDAP_DEBUG_ANY,
                                "connection_init(%d): connection table full "
                                "(%d/%d)\n", s, i, dtblsize);
-                       ldap_pvt_thread_mutex_unlock( &connections_mutex );
                        return -1;
                }
        }
 #endif
 
-       assert( c != NULL );
-
-       if( c->c_struct_state == SLAP_C_UNINITIALIZED ) {
+       if( doinit ) {
                c->c_send_ldap_result = slap_send_ldap_result;
                c->c_send_search_entry = slap_send_search_entry;
                c->c_send_search_reference = slap_send_search_reference;
@@ -651,13 +489,10 @@ long connection_init(
                        slapi_int_create_object_extensions( SLAPI_X_EXT_CONNECTION, c );
                }
 #endif
-
-               c->c_struct_state = SLAP_C_UNUSED;
        }
 
        ldap_pvt_thread_mutex_lock( &c->c_mutex );
 
-       assert( c->c_struct_state == SLAP_C_UNUSED );
        assert( BER_BVISNULL( &c->c_authmech ) );
        assert( BER_BVISNULL( &c->c_dn ) );
        assert( BER_BVISNULL( &c->c_ndn ) );
@@ -688,7 +523,6 @@ long connection_init(
                c->c_close_reason = "?";                        /* should never be needed */
                ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_SET_FD, &s );
                ldap_pvt_thread_mutex_unlock( &c->c_mutex );
-               ldap_pvt_thread_mutex_unlock( MCA_GET_CONN_MUTEX(s) );
 
                return 0;
        }
@@ -777,7 +611,6 @@ long connection_init(
 
        slapd_add_internal( s, 1 );
        ldap_pvt_thread_mutex_unlock( &c->c_mutex );
-       ldap_pvt_thread_mutex_unlock( MCA_GET_CONN_MUTEX(s) );
 
        backend_connection_init(c);
 
@@ -820,10 +653,10 @@ void connection2anonymous( Connection *c )
 static void
 connection_destroy( Connection *c )
 {
-       /* note: connections_mutex should be locked by caller */
        ber_socket_t    sd;
        unsigned long   connid;
        const char              *close_reason;
+       Sockbuf                 *sb;
 
        assert( connections != NULL );
        assert( c != NULL );
@@ -842,6 +675,10 @@ connection_destroy( Connection *c )
        connid = c->c_connid;
        close_reason = c->c_close_reason;
 
+       ldap_pvt_thread_mutex_lock( &connections_mutex );
+       c->c_struct_state = SLAP_C_PENDING;
+       ldap_pvt_thread_mutex_unlock( &connections_mutex );
+
        backend_connection_destroy(c);
 
        c->c_protocol = 0;
@@ -874,37 +711,43 @@ connection_destroy( Connection *c )
                c->c_currentber = NULL;
        }
 
-       ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_GET_FD, &sd );
-       slapd_sd_lock();
-       ber_sockbuf_free( c->c_sb );
-       if ( sd != AC_SOCKET_INVALID ) {
-               slapd_remove( sd, 1, 0, 1 );
 
-               Statslog( LDAP_DEBUG_STATS, (close_reason
-                                                                        ? "conn=%lu fd=%ld closed (%s)\n"
-                                                                        : "conn=%lu fd=%ld closed\n"),
-                       connid, (long) sd, close_reason, 0, 0 );
-       } else {
-               slapd_sd_unlock();
+#ifdef LDAP_SLAPI
+       /* call destructors, then constructors; avoids unnecessary allocation */
+       if ( slapi_plugins_used ) {
+               slapi_int_clear_object_extensions( SLAPI_X_EXT_CONNECTION, c );
        }
+#endif
 
-       c->c_sb = ber_sockbuf_alloc( );
+       c->c_conn_state = SLAP_C_INVALID;
+       c->c_struct_state = SLAP_C_UNUSED;
+       c->c_close_reason = "?";                        /* should never be needed */
 
+       sb = c->c_sb;
+       c->c_sb = ber_sockbuf_alloc( );
        {
                ber_len_t max = sockbuf_max_incoming;
                ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_SET_MAX_INCOMING, &max );
        }
 
-       c->c_conn_state = SLAP_C_INVALID;
-       c->c_struct_state = SLAP_C_UNUSED;
-       c->c_close_reason = "?";                        /* should never be needed */
+       ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, &sd );
+       slapd_sd_lock();
 
-#ifdef LDAP_SLAPI
-       /* call destructors, then constructors; avoids unnecessary allocation */
-       if ( slapi_plugins_used ) {
-               slapi_int_clear_object_extensions( SLAPI_X_EXT_CONNECTION, c );
+       ber_sockbuf_free( sb );
+
+       /* c must be fully reset by this point; when we call slapd_remove
+        * it may get immediately reused by a new connection.
+        */
+       if ( sd != AC_SOCKET_INVALID ) {
+               slapd_remove( sd, 1, 0, 1 );
+
+               Statslog( LDAP_DEBUG_STATS, (close_reason
+                                                                        ? "conn=%lu fd=%ld closed (%s)\n"
+                                                                        : "conn=%lu fd=%ld closed\n"),
+                       connid, (long) sd, close_reason, 0, 0 );
+       } else {
+               slapd_sd_unlock();
        }
-#endif
 }
 
 int connection_state_closing( Connection *c )
@@ -985,7 +828,7 @@ void connection_closing( Connection *c, const char *why )
                c->c_close_reason = why;
 
                /* don't listen on this port anymore */
-               slapd_clr_read( sd, 1 );
+               slapd_clr_read( sd, 0 );
 
                /* abandon active operations */
                connection_abandon( c );
@@ -994,9 +837,6 @@ void connection_closing( Connection *c, const char *why )
                slapd_clr_write( sd, 1 );
                if ( c->c_writewaiter ) {
                        ldap_pvt_thread_cond_signal( &c->c_write_cv );
-                       ldap_pvt_thread_mutex_unlock( &c->c_mutex );
-                       ldap_pvt_thread_yield();
-                       ldap_pvt_thread_mutex_lock( &c->c_mutex );
                }
 
        } else if( why == NULL && c->c_close_reason == conn_lost_str ) {
@@ -1014,7 +854,7 @@ static void connection_close( Connection *c )
        assert( c->c_struct_state == SLAP_C_USED );
        assert( c->c_conn_state == SLAP_C_CLOSING );
 
-       /* note: connections_mutex and c_mutex should be locked by caller */
+       /* note: c_mutex should be locked by caller */
 
        ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_GET_FD, &sd );
        if( !LDAP_STAILQ_EMPTY(&c->c_ops) ) {
@@ -1045,71 +885,21 @@ unsigned long connections_nextid(void)
 
 Connection* connection_first( ber_socket_t *index )
 {
-#ifdef SLAP_MULTI_CONN_ARRAY
-       int conn_array_id;
-#endif
-
        assert( connections != NULL );
        assert( index != NULL );
 
-#ifdef SLAP_MULTI_CONN_ARRAY
-       for ( conn_array_id = 0;
-               conn_array_id < NUM_CONNECTION_ARRAY;
-               conn_array_id++ )
-       {
-               ldap_pvt_thread_mutex_lock( &connections_mutex[ conn_array_id ] );
-       }
-#else
        ldap_pvt_thread_mutex_lock( &connections_mutex );
-#endif
-
-       *index = 0;
-
-       return connection_next(NULL, index);
-}
-
-Connection* connection_next( Connection *c, ber_socket_t *index )
-#ifdef SLAP_MULTI_CONN_ARRAY
-{
-       Connection* conn;
-
-       assert( connections != NULL );
-       assert( index != NULL );
-       assert( *index >= 0 && *index <= dtblsize );
-
-       if( c != NULL ) ldap_pvt_thread_mutex_unlock( &c->c_mutex );
-
-       c = NULL;
-
-       for(; *index < dtblsize; (*index)++) {
-               assert( MCA_conn_check( *index ) );
-               conn = MCA_GET_CONNECTION(*index);
-               if( conn->c_struct_state == SLAP_C_UNINITIALIZED ) {
-                       assert( conn->c_conn_state == SLAP_C_INVALID );
-#ifndef HAVE_WINSOCK
-                       continue;
-#else
+       for( *index = 0; *index < dtblsize; (*index)++) {
+               if( connections[*index].c_struct_state != SLAP_C_UNINITIALIZED ) {
                        break;
-#endif
                }
-
-               if( conn->c_struct_state == SLAP_C_USED ) {
-                       assert( conn->c_conn_state != SLAP_C_INVALID );
-                       c = conn;
-                       (*index)++;
-                       break;
-               }
-
-               assert( conn->c_struct_state == SLAP_C_UNUSED );
-               assert( conn->c_conn_state == SLAP_C_INVALID );
        }
+       ldap_pvt_thread_mutex_unlock( &connections_mutex );
 
-       if( c != NULL ) ldap_pvt_thread_mutex_lock( &c->c_mutex );
-
-       return c;
-
+       return connection_next(NULL, index);
 }
-#else
+
+Connection* connection_next( Connection *c, ber_socket_t *index )
 {
        assert( connections != NULL );
        assert( index != NULL );
@@ -1119,14 +909,11 @@ Connection* connection_next( Connection *c, ber_socket_t *index )
 
        c = NULL;
 
+       ldap_pvt_thread_mutex_lock( &connections_mutex );
        for(; *index < dtblsize; (*index)++) {
                if( connections[*index].c_struct_state == SLAP_C_UNINITIALIZED ) {
                        assert( connections[*index].c_conn_state == SLAP_C_INVALID );
-#ifndef HAVE_WINSOCK
-                       continue;
-#else
                        break;
-#endif
                }
 
                if( connections[*index].c_struct_state == SLAP_C_USED ) {
@@ -1140,30 +927,15 @@ Connection* connection_next( Connection *c, ber_socket_t *index )
        }
 
        if( c != NULL ) ldap_pvt_thread_mutex_lock( &c->c_mutex );
+       ldap_pvt_thread_mutex_unlock( &connections_mutex );
        return c;
 }
-#endif
 
 void connection_done( Connection *c )
 {
-#ifdef SLAP_MULTI_CONN_ARRAY
-       int conn_array_id;
-#endif
-
        assert( connections != NULL );
 
        if( c != NULL ) ldap_pvt_thread_mutex_unlock( &c->c_mutex );
-
-#ifdef SLAP_MULTI_CONN_ARRAY
-       for ( conn_array_id = 0;
-               conn_array_id < NUM_CONNECTION_ARRAY;
-               conn_array_id++ )
-       {
-               ldap_pvt_thread_mutex_unlock( &connections_mutex[ conn_array_id ] );
-       }
-#else
-       ldap_pvt_thread_mutex_unlock( &connections_mutex );
-#endif
 }
 
 /*
@@ -1233,6 +1005,7 @@ connection_operation( void *ctx, void *arg_v )
        ldap_pvt_thread_mutex_unlock( &slap_counters.sc_ops_mutex );
 
        op->o_threadctx = ctx;
+       op->o_tid = ldap_pvt_thread_pool_tid( ctx );
 
        switch ( tag ) {
        case LDAP_REQ_BIND:
@@ -1524,8 +1297,6 @@ int connection_read(ber_socket_t s)
 
        assert( connections != NULL );
 
-       ldap_pvt_thread_mutex_lock( MCA_GET_CONN_MUTEX(s) );
-
        /* get (locked) connection */
        c = connection_get( s );
 
@@ -1534,7 +1305,6 @@ int connection_read(ber_socket_t s)
                        "connection_read(%ld): no connection!\n",
                        (long) s, 0, 0 );
 
-               ldap_pvt_thread_mutex_unlock( MCA_GET_CONN_MUTEX(s) );
                return -1;
        }
 
@@ -1544,12 +1314,7 @@ int connection_read(ber_socket_t s)
                Debug( LDAP_DEBUG_TRACE,
                        "connection_read(%d): closing, ignoring input for id=%lu\n",
                        s, c->c_connid, 0 );
-
-#ifdef SLAP_LIGHTWEIGHT_DISPATCHER
-               slapd_set_read( s, 1 );
-#endif
                connection_return( c );
-               ldap_pvt_thread_mutex_unlock( MCA_GET_CONN_MUTEX(s) );
                return 0;
        }
 
@@ -1564,7 +1329,6 @@ int connection_read(ber_socket_t s)
                        c->c_clientfunc, c->c_clientarg );
 #endif
                connection_return( c );
-               ldap_pvt_thread_mutex_unlock( MCA_GET_CONN_MUTEX(s) );
                return 0;
        }
 
@@ -1582,31 +1346,10 @@ int connection_read(ber_socket_t s)
                                s, rc, c->c_connid );
 
                        c->c_needs_tls_accept = 0;
-                       /* connections_mutex and c_mutex are locked */
+                       /* c_mutex is locked */
                        connection_closing( c, "TLS negotiation failure" );
-
-#if 0
-                       {
-                               struct timeval tv;
-                               fd_set rfd;
-                               /* Drain input before close, to allow SSL error codes
-                                * to propagate to client. */
-                               FD_ZERO(&rfd);
-                               FD_SET(s, &rfd);
-                               for (rc=1; rc>0;) {
-                                       tv.tv_sec = 1;
-                                       tv.tv_usec = 0;
-                                       rc = select(s+1, &rfd, NULL, NULL, &tv);
-                                       if (rc == 1) {
-                                               ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_DRAIN, NULL);
-                                       }
-                               }
-                       }
-#endif
-
                        connection_close( c );
                        connection_return( c );
-                       ldap_pvt_thread_mutex_unlock( MCA_GET_CONN_MUTEX(s) );
                        return 0;
 
                } else if ( rc == 0 ) {
@@ -1637,15 +1380,13 @@ int connection_read(ber_socket_t s)
                }
 
                /* if success and data is ready, fall thru to data input loop */
-               if( rc != 0 ||
-                       !ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_DATA_READY, NULL ) )
+               if( !ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_DATA_READY, NULL ) )
                {
 #ifdef SLAP_LIGHTWEIGHT_DISPATCHER
                        slapd_set_read( s, 1 );
 #endif
 
                        connection_return( c );
-                       ldap_pvt_thread_mutex_unlock( MCA_GET_CONN_MUTEX(s) );
                        return 0;
                }
        }
@@ -1660,7 +1401,6 @@ int connection_read(ber_socket_t s)
 #endif
 
                        connection_return( c );
-                       ldap_pvt_thread_mutex_unlock( MCA_GET_CONN_MUTEX(s) );
                        return 0;
                }
 
@@ -1673,11 +1413,10 @@ int connection_read(ber_socket_t s)
                                "error=%d id=%lu, closing\n",
                                s, rc, c->c_connid );
 
-                       /* connections_mutex and c_mutex are locked */
+                       /* c_mutex is locked */
                        connection_closing( c, "SASL layer install failure" );
                        connection_close( c );
                        connection_return( c );
-                       ldap_pvt_thread_mutex_unlock( MCA_GET_CONN_MUTEX(s) );
                        return 0;
                }
        }
@@ -1703,15 +1442,14 @@ int connection_read(ber_socket_t s)
 #endif
 
        if( rc < 0 ) {
-               Debug( LDAP_DEBUG_TRACE,
+               Debug( LDAP_DEBUG_CONNS,
                        "connection_read(%d): input error=%d id=%lu, closing.\n",
                        s, rc, c->c_connid );
 
-               /* connections_mutex and c_mutex are locked */
+               /* c_mutex is locked */
                connection_closing( c, conn_lost_str );
                connection_close( c );
                connection_return( c );
-               ldap_pvt_thread_mutex_unlock( MCA_GET_CONN_MUTEX(s) );
                return 0;
        }
 
@@ -1732,7 +1470,6 @@ int connection_read(ber_socket_t s)
 #endif
 
        connection_return( c );
-       ldap_pvt_thread_mutex_unlock( MCA_GET_CONN_MUTEX(s) );
 
        return 0;
 }
@@ -1969,39 +1706,13 @@ connection_resched( Connection *conn )
        Operation *op;
 
        if( conn->c_conn_state == SLAP_C_CLOSING ) {
-               int rc;
                ber_socket_t    sd;
                ber_sockbuf_ctrl( conn->c_sb, LBER_SB_OPT_GET_FD, &sd );
 
-               /* use trylock to avoid possible deadlock */
-               rc = ldap_pvt_thread_mutex_trylock( MCA_GET_CONN_MUTEX( sd ) );
-
-               if( rc ) {
-                       Debug( LDAP_DEBUG_TRACE,
-                               "connection_resched: reaquiring locks conn=%lu sd=%d\n",
-                               conn->c_connid, sd, 0 );
-                       /*
-                        * reaquire locks in the right order...
-                        * this may allow another thread to close this connection,
-                        * so recheck state below.
-                        */
-                       ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
-                       ldap_pvt_thread_mutex_lock( MCA_GET_CONN_MUTEX ( sd ) );
-                       ldap_pvt_thread_mutex_lock( &conn->c_mutex );
-               }
-
-               if( conn->c_conn_state != SLAP_C_CLOSING ) {
-                       Debug( LDAP_DEBUG_TRACE, "connection_resched: "
-                               "closed by other thread conn=%lu sd=%d\n",
-                               conn->c_connid, sd, 0 );
-               } else {
-                       Debug( LDAP_DEBUG_TRACE, "connection_resched: "
-                               "attempting closing conn=%lu sd=%d\n",
-                               conn->c_connid, sd, 0 );
-                       connection_close( conn );
-               }
-
-               ldap_pvt_thread_mutex_unlock( MCA_GET_CONN_MUTEX( sd ) );
+               Debug( LDAP_DEBUG_TRACE, "connection_resched: "
+                       "attempting closing conn=%lu sd=%d\n",
+                       conn->c_connid, sd, 0 );
+               connection_close( conn );
                return 0;
        }
 
@@ -2181,14 +1892,11 @@ int connection_write(ber_socket_t s)
 
        slapd_clr_write( s, 0 );
 
-       ldap_pvt_thread_mutex_lock( MCA_GET_CONN_MUTEX( s ) );
-
        c = connection_get( s );
        if( c == NULL ) {
                Debug( LDAP_DEBUG_ANY,
                        "connection_write(%ld): no connection!\n",
                        (long)s, 0, 0 );
-               ldap_pvt_thread_mutex_unlock( MCA_GET_CONN_MUTEX( s ) );
                return -1;
        }
 
@@ -2228,7 +1936,6 @@ int connection_write(ber_socket_t s)
        }
 
        connection_return( c );
-       ldap_pvt_thread_mutex_unlock( MCA_GET_CONN_MUTEX(s) );
        return 0;
 }
 
@@ -2253,6 +1960,7 @@ connection_fake_init(
        op->o_tmpmemctx = slap_sl_mem_create(SLAP_SLAB_SIZE, SLAP_SLAB_STACK, ctx);
        op->o_tmpmfuncs = &slap_sl_mfuncs;
        op->o_threadctx = ctx;
+       op->o_tid = ldap_pvt_thread_pool_tid( ctx );
 
        op->o_conn = conn;
        op->o_connid = op->o_conn->c_connid;
index 26e2461515939dc580e2309ae1f4929c81475776..6c610008843c31b338fc641248afa79b879c20a7 100644 (file)
@@ -1161,6 +1161,7 @@ static int parseAssert (
        
        rs->sr_err = get_filter( op, ber, (Filter **)&(op->o_assertion),
                &rs->sr_text);
+       (void) ber_free( ber, 1 );
        if( rs->sr_err != LDAP_SUCCESS ) {
                if( rs->sr_err == SLAPD_DISCONNECT ) {
                        rs->sr_err = LDAP_PROTOCOL_ERROR;
@@ -1223,26 +1224,28 @@ static int parsePreRead (
                return LDAP_OTHER;
        }
 
+       rs->sr_err = LDAP_SUCCESS;
+
        siz = sizeof( AttributeName );
        off = offsetof( AttributeName, an_name );
        if ( ber_scanf( ber, "{M}", &an, &siz, off ) == LBER_ERROR ) {
                rs->sr_text = "preread control: decoding error";
-               return LDAP_PROTOCOL_ERROR;
+               rs->sr_err = LDAP_PROTOCOL_ERROR;
+               goto done;
        }
 
        for( i=0; i<siz; i++ ) {
-               int             rc = LDAP_SUCCESS;
                const char      *dummy = NULL;
 
                an[i].an_desc = NULL;
                an[i].an_oc = NULL;
                an[i].an_oc_exclude = 0;
-               rc = slap_bv2ad( &an[i].an_name, &an[i].an_desc, &dummy );
-               if ( rc != LDAP_SUCCESS && ctrl->ldctl_iscritical ) {
+               rs->sr_err = slap_bv2ad( &an[i].an_name, &an[i].an_desc, &dummy );
+               if ( rs->sr_err != LDAP_SUCCESS && ctrl->ldctl_iscritical ) {
                        rs->sr_text = dummy
                                ? dummy
                                : "postread control: unknown attributeType";
-                       return rc;
+                       goto done;
                }
        }
 
@@ -1252,8 +1255,9 @@ static int parsePreRead (
 
        op->o_preread_attrs = an;
 
-       rs->sr_err = LDAP_SUCCESS;
-       return LDAP_SUCCESS;
+done:
+       (void) ber_free( ber, 1 );
+       return rs->sr_err;
 }
 
 static int parsePostRead (
@@ -1288,26 +1292,27 @@ static int parsePostRead (
                return LDAP_OTHER;
        }
 
+       rs->sr_err = LDAP_SUCCESS;
        siz = sizeof( AttributeName );
        off = offsetof( AttributeName, an_name );
        if ( ber_scanf( ber, "{M}", &an, &siz, off ) == LBER_ERROR ) {
                rs->sr_text = "postread control: decoding error";
-               return LDAP_PROTOCOL_ERROR;
+               rs->sr_err = LDAP_PROTOCOL_ERROR;
+               goto done;
        }
 
        for( i=0; i<siz; i++ ) {
-               int             rc = LDAP_SUCCESS;
                const char      *dummy = NULL;
 
                an[i].an_desc = NULL;
                an[i].an_oc = NULL;
                an[i].an_oc_exclude = 0;
-               rc = slap_bv2ad( &an[i].an_name, &an[i].an_desc, &dummy );
-               if ( rc != LDAP_SUCCESS && ctrl->ldctl_iscritical ) {
+               rs->sr_err = slap_bv2ad( &an[i].an_name, &an[i].an_desc, &dummy );
+               if ( rs->sr_err != LDAP_SUCCESS && ctrl->ldctl_iscritical ) {
                        rs->sr_text = dummy
                                ? dummy
                                : "postread control: unknown attributeType";
-                       return rc;
+                       goto done;
                }
        }
 
@@ -1317,8 +1322,9 @@ static int parsePostRead (
 
        op->o_postread_attrs = an;
 
-       rs->sr_err = LDAP_SUCCESS;
-       return LDAP_SUCCESS;
+done:
+       (void) ber_free( ber, 1 );
+       return rs->sr_err;
 }
 
 static int parseValuesReturnFilter (
@@ -1348,6 +1354,8 @@ static int parseValuesReturnFilter (
        rs->sr_err = get_vrFilter( op, ber,
                (ValuesReturnFilter **)&(op->o_vrFilter), &rs->sr_text);
 
+       (void) ber_free( ber, 1 );
+
        if( rs->sr_err != LDAP_SUCCESS ) {
                if( rs->sr_err == SLAPD_DISCONNECT ) {
                        rs->sr_err = LDAP_PROTOCOL_ERROR;
@@ -1494,13 +1502,14 @@ static int parseSearchOptions (
                return LDAP_OTHER;
        }
 
-       if ( (tag = ber_scanf( ber, "{i}", &search_flags )) == LBER_ERROR ) {
+       tag = ber_scanf( ber, "{i}", &search_flags );
+       (void) ber_free( ber, 1 );
+
+       if ( tag == LBER_ERROR ) {
                rs->sr_text = "searchOptions control decoding error";
                return LDAP_PROTOCOL_ERROR;
        }
 
-       (void) ber_free( ber, 1 );
-
        if ( search_flags & LDAP_SEARCH_FLAG_DOMAIN_SCOPE ) {
                if ( op->o_domain_scope != SLAP_CONTROL_NONE ) {
                        rs->sr_text = "searchOptions control specified multiple times "
index 4f6875ff78ef79ebd5db8ba05065a56aa4ca3367..03559d6288a9742454d5ef0068c8ea5b350f3b56 100644 (file)
@@ -339,9 +339,13 @@ static struct slap_daemon {
 static char** slapd_srvurls = NULL;
 static SLPHandle slapd_hslp = 0;
 int slapd_register_slp = 0;
+char *slapd_slp_attrs = NULL;
+
+static SLPError slapd_slp_cookie;
 
 void slapd_slp_init( const char* urls ) {
        int i;
+       SLPError err;
 
        slapd_srvurls = ldap_str2charray( urls, " " );
 
@@ -376,7 +380,12 @@ void slapd_slp_init( const char* urls ) {
        }
 
        /* open the SLP handle */
-       SLPOpen( "en", 0, &slapd_hslp );
+       err = SLPOpen( "en", 0, &slapd_hslp );
+
+       if (err != SLP_OK) {
+               Debug( LDAP_DEBUG_CONNS, "daemon: SLPOpen() failed with %ld\n",
+                       (long)err, 0, 0 );
+       }
 }
 
 void slapd_slp_deinit() {
@@ -394,11 +403,13 @@ void slapd_slp_regreport(
        SLPError errcode,
        void* cookie )
 {
-       /* empty report */
+       /* return the error code in the cookie */
+       *(SLPError*)cookie = errcode; 
 }
 
 void slapd_slp_reg() {
        int i;
+       SLPError err;
 
        if( slapd_srvurls == NULL ) return;
 
@@ -408,28 +419,41 @@ void slapd_slp_reg() {
                    strncmp( slapd_srvurls[i], LDAPS_SRVTYPE_PREFIX,
                                sizeof( LDAPS_SRVTYPE_PREFIX ) - 1 ) == 0 )
                {
-                       SLPReg( slapd_hslp,
+                       err = SLPReg( slapd_hslp,
                                slapd_srvurls[i],
                                SLP_LIFETIME_MAXIMUM,
                                "ldap",
-                               "",
-                               1,
+                                       (slapd_slp_attrs) ? slapd_slp_attrs : "",
+                                       SLP_TRUE,
                                slapd_slp_regreport,
-                               NULL );
+                                       &slapd_slp_cookie );
+
+                       if (err != SLP_OK || slapd_slp_cookie != SLP_OK) {
+                               Debug( LDAP_DEBUG_CONNS,
+                                       "daemon: SLPReg(%s) failed with %ld, cookie = %ld\n",
+                                       slapd_srvurls[i], (long)err, (long)slapd_slp_cookie );
+                       }       
                }
        }
 }
 
 void slapd_slp_dereg() {
        int i;
+       SLPError err;
 
        if( slapd_srvurls == NULL ) return;
 
        for( i=0; slapd_srvurls[i] != NULL; i++ ) {
-               SLPDereg( slapd_hslp,
+               err = SLPDereg( slapd_hslp,
                        slapd_srvurls[i],
                        slapd_slp_regreport,
-                       NULL );
+                               &slapd_slp_cookie );
+               
+               if (err != SLP_OK || slapd_slp_cookie != SLP_OK) {
+                       Debug( LDAP_DEBUG_CONNS,
+                               "daemon: SLPDereg(%s) failed with %ld, cookie = %ld\n",
+                               slapd_srvurls[i], (long)err, (long)slapd_slp_cookie );
+               }
        }
 }
 #endif /* HAVE_SLP */
@@ -807,7 +831,8 @@ static int slap_get_listener_addresses(
                        sap[i]->sa_family = AF_INET;
                        ((struct sockaddr_in *)sap[i])->sin_port = htons(port);
                        AC_MEMCPY( &((struct sockaddr_in *)sap[i])->sin_addr,
-                               he ? he->h_addr_list[i] : &in, sizeof(struct in_addr) );
+                               he ? (struct in_addr *)he->h_addr_list[i] : &in,
+                               sizeof(struct in_addr) );
                }
                sap[i] = NULL;
 #endif
@@ -1705,7 +1730,7 @@ slapd_daemon_task(
                struct timeval          tv;
                struct timeval          *tvp;
 
-               struct timeval          *cat;
+               struct timeval          cat;
                time_t                          tdelta = 1;
                struct re_s*            rtask;
                now = slap_get_time();
@@ -1786,7 +1811,7 @@ slapd_daemon_task(
 
                ldap_pvt_thread_mutex_lock( &slapd_rq.rq_mutex );
                rtask = ldap_pvt_runqueue_next_sched( &slapd_rq, &cat );
-               while ( cat && cat->tv_sec && cat->tv_sec <= now ) {
+               while ( rtask && cat.tv_sec && cat.tv_sec <= now ) {
                        if ( ldap_pvt_runqueue_isrunning( &slapd_rq, rtask )) {
                                ldap_pvt_runqueue_resched( &slapd_rq, rtask, 0 );
                        } else {
@@ -1794,15 +1819,15 @@ slapd_daemon_task(
                                ldap_pvt_runqueue_resched( &slapd_rq, rtask, 0 );
                                ldap_pvt_thread_mutex_unlock( &slapd_rq.rq_mutex );
                                ldap_pvt_thread_pool_submit( &connection_pool,
-                                                                                       rtask->routine, (void *) rtask );
+                                       rtask->routine, (void *) rtask );
                                ldap_pvt_thread_mutex_lock( &slapd_rq.rq_mutex );
                        }
                        rtask = ldap_pvt_runqueue_next_sched( &slapd_rq, &cat );
                }
                ldap_pvt_thread_mutex_unlock( &slapd_rq.rq_mutex );
 
-               if ( cat && cat->tv_sec ) {
-                       time_t diff = difftime( cat->tv_sec, now );
+               if ( rtask && cat.tv_sec ) {
+                       time_t diff = difftime( cat.tv_sec, now );
                        if ( diff == 0 ) diff = tdelta;
                        if ( tvp == NULL || diff < tv.tv_sec ) {
                                tv.tv_sec = diff;
@@ -2069,7 +2094,7 @@ slapd_daemon_task(
 #endif
 
                for (i=0; i<ns; i++) {
-                       int rc = 1, fd, waswrite = 0;
+                       int rc = 1, fd;
 
                        if ( SLAP_EVENT_IS_LISTENER(i) ) {
 #ifdef SLAP_LIGHTWEIGHT_DISPATCHER
@@ -2099,7 +2124,7 @@ slapd_daemon_task(
                                                "daemon: write active on %d\n",
                                                fd, 0, 0 );
 
-                                       waswrite = 1;
+                                       SLAP_EVENT_CLR_WRITE( i );
 
                                        /*
                                         * NOTE: it is possible that the connection was closed
@@ -2111,12 +2136,13 @@ slapd_daemon_task(
                                                continue;
                                        }
                                }
-                               /* If event is a read or an error */
-                               if( SLAP_EVENT_IS_READ( i ) || !waswrite ) {
+                               /* If event is a read */
+                               if( SLAP_EVENT_IS_READ( i )) {
                                        Debug( LDAP_DEBUG_CONNS,
                                                "daemon: read active on %d\n",
                                                fd, 0, 0 );
 
+                                       SLAP_EVENT_CLR_READ( i );
 #ifdef SLAP_LIGHTWEIGHT_DISPATCHER
                                        connection_read_activate( fd );
 #else
@@ -2128,6 +2154,9 @@ slapd_daemon_task(
                                         */
                                        connection_read( fd );
 #endif
+                               } else {
+                                       Debug( LDAP_DEBUG_CONNS,
+                                               "daemon: hangup on %d\n", fd, 0, 0 );
                                }
                        }
                }
index 83d042d9b4d338e117d22e22ecbe3dce413e6519..be7b0aea0fa6d5c72cb7d1448a75125c0da4389c 100644 (file)
@@ -53,6 +53,8 @@
 
 #define        AVA_PRIVATE( ava ) ( ( AttributeDescription * )(ava)->la_private )
 
+int slap_DN_strict = SLAP_AD_NOINSERT;
+
 static int
 LDAPRDN_validate( LDAPRDN rdn )
 {
@@ -75,7 +77,7 @@ LDAPRDN_validate( LDAPRDN rdn )
                        if ( rc != LDAP_SUCCESS ) {
                                rc = slap_bv2undef_ad( &ava->la_attr,
                                        &ad, &text,
-                                       SLAP_AD_PROXIED|SLAP_AD_NOINSERT );
+                                       SLAP_AD_PROXIED|slap_DN_strict );
                                if ( rc != LDAP_SUCCESS ) {
                                        return LDAP_INVALID_SYNTAX;
                                }
@@ -139,7 +141,7 @@ LDAPDN_validate( LDAPDN dn )
                                if ( rc != LDAP_SUCCESS ) {
                                        rc = slap_bv2undef_ad( &ava->la_attr,
                                                &ad, &text,
-                                               SLAP_AD_PROXIED|SLAP_AD_NOINSERT );
+                                               SLAP_AD_PROXIED|slap_DN_strict );
                                        if ( rc != LDAP_SUCCESS ) {
                                                return LDAP_INVALID_SYNTAX;
                                        }
@@ -356,7 +358,7 @@ LDAPRDN_rewrite( LDAPRDN rdn, unsigned flags, void *ctx )
                        if ( rc != LDAP_SUCCESS ) {
                                rc = slap_bv2undef_ad( &ava->la_attr,
                                        &ad, &text,
-                                       SLAP_AD_PROXIED|SLAP_AD_NOINSERT );
+                                       SLAP_AD_PROXIED|slap_DN_strict );
                                if ( rc != LDAP_SUCCESS ) {
                                        return LDAP_INVALID_SYNTAX;
                                }
@@ -488,7 +490,7 @@ LDAPDN_rewrite( LDAPDN dn, unsigned flags, void *ctx )
                                if ( rc != LDAP_SUCCESS ) {
                                        rc = slap_bv2undef_ad( &ava->la_attr,
                                                &ad, &text,
-                                               SLAP_AD_PROXIED|SLAP_AD_NOINSERT );
+                                               SLAP_AD_PROXIED|slap_DN_strict );
                                        if ( rc != LDAP_SUCCESS ) {
                                                return LDAP_INVALID_SYNTAX;
                                        }
index ac710dfcbca31415b00715a83bc3be3cf2ac0a0d..4476d6a40e8317b5267100ed95ed27254764877a 100644 (file)
@@ -122,8 +122,6 @@ slap_init( int mode, const char *name )
 
        switch ( slapMode & SLAP_MODE ) {
        case SLAP_SERVER_MODE:
-               ldap_pvt_thread_pool_init( &connection_pool,
-                               connection_pool_max, 0);
 
                /* FALLTHRU */
        case SLAP_TOOL_MODE:
@@ -134,6 +132,8 @@ slap_init( int mode, const char *name )
 
                slap_name = name;
 
+               ldap_pvt_thread_pool_init( &connection_pool,
+                               connection_pool_max, 0);
                ldap_pvt_thread_mutex_init( &entry2str_mutex );
                ldap_pvt_thread_mutex_init( &replog_mutex );
 
index cc1ed8705468df15f5d7fc9f0cdd8c4ed3095684..7d9b9cf20e76bc1f7319cfdaa262973f8787c4c1 100644 (file)
@@ -114,6 +114,9 @@ slap_parse_sync_cookie(
                return -1;
        }
 
+       if ( rid_ptr[ STRLENOF( "rid=" ) ] == '-' ) {
+               return -1;
+       }
        cookie->rid = strtoul( &rid_ptr[ STRLENOF( "rid=" ) ], &next, 10 );
        if ( next == &rid_ptr[ STRLENOF( "rid=" ) ] || ( next[ 0 ] != ',' && next[ 0 ] != '\0' ) ) {
                return -1;
index 76f30adf45729f19e83df3deaafcd10881dc1dc2..70f2ebe12dac1bf103cbd1c553fb73df2604672f 100644 (file)
@@ -115,8 +115,9 @@ slapd_opt_slp( const char *val, void *arg )
 {
 #ifdef HAVE_SLP
        /* NULL is default */
-       if ( val == NULL || strcasecmp( val, "on" ) == 0 ) {
+       if ( val == NULL || *val == '(' || strcasecmp( val, "on" ) == 0 ) {
                slapd_register_slp = 1;
+               slapd_slp_attrs = (val != NULL && *val == '(') ? val : NULL;
 
        } else if ( strcasecmp( val, "off" ) == 0 ) {
                slapd_register_slp = 0;
@@ -155,10 +156,11 @@ struct option_helper {
        void            *oh_arg;
        const char      *oh_usage;
 } option_helpers[] = {
-       { BER_BVC("slp"),       slapd_opt_slp,  NULL, "slp[={on|off}] enable/disable SLP" },
+       { BER_BVC("slp"),       slapd_opt_slp,  NULL, "slp[={on|off|(attrs)}] enable/disable SLP using (attrs)" },
        { BER_BVNULL, 0, NULL, NULL }
 };
 
+#if defined(LDAP_DEBUG) && defined(LDAP_SYSLOG)
 #ifdef LOG_LOCAL4
 static int
 parse_syslog_user( const char *arg, int *syslogUser )
@@ -221,6 +223,7 @@ parse_syslog_level( const char *arg, int *levelp )
 
        return 0;
 }
+#endif /* LDAP_DEBUG && LDAP_SYSLOG */
 
 int
 parse_debug_unknowns( char **unknowns, int *levelp )
@@ -446,12 +449,12 @@ int main( int argc, char **argv )
 #ifdef HAVE_CHROOT
                                "r:"
 #endif
-#ifdef LDAP_SYSLOG
+#if defined(LDAP_DEBUG) && defined(LDAP_SYSLOG)
                                "S:"
-#endif
 #ifdef LOG_LOCAL4
                                "l:"
 #endif
+#endif
 #if defined(HAVE_SETUID) && defined(HAVE_SETGID)
                                "u:g:"
 #endif
@@ -569,7 +572,6 @@ int main( int argc, char **argv )
                                goto destroy;
                        }
                        break;
-#endif /* LDAP_DEBUG && LDAP_SYSLOG */
 
 #ifdef LOG_LOCAL4
                case 'l':       /* set syslog local user */
@@ -578,6 +580,7 @@ int main( int argc, char **argv )
                        }
                        break;
 #endif
+#endif /* LDAP_DEBUG && LDAP_SYSLOG */
 
 #ifdef HAVE_CHROOT
                case 'r':
index 67af446af468823c101dc74decba8897755e50e7..7d0cca84b567fe613618115d067ee2ea55bf786f 100644 (file)
@@ -16,6 +16,7 @@
 SRCS = overlays.c \
        accesslog.c \
        auditlog.c \
+       constraint.c \
        dds.c \
        denyop.c \
        dyngroup.c \
@@ -65,6 +66,9 @@ accesslog.la : accesslog.lo
 auditlog.la : auditlog.lo
        $(LTLINK_MOD) -module -o $@ auditlog.lo version.lo $(LINK_LIBS)
 
+constraint.la : constraint.lo
+       $(LTLINK_MOD) -module -o $@ constraint.lo version.lo $(LINK_LIBS)
+
 dds.la : dds.lo
        $(LTLINK_MOD) -module -o $@ dds.lo version.lo $(LINK_LIBS)
 
index bd61096dbbb9f8e01c5e267438b588eca0bc0c43..27cd9c9adc30753857a71470fe89fec1b4e00e0d 100644 (file)
 #define LOG_OP_ALL             (LOG_OP_READS|LOG_OP_WRITES|LOG_OP_SESSION| \
        LOG_OP_EXTENDED|LOG_OP_UNKNOWN)
 
+typedef struct log_attr {
+       struct log_attr *next;
+       AttributeDescription *attr;
+} log_attr;
+
 typedef struct log_info {
        BackendDB *li_db;
        slap_mask_t li_ops;
        int li_age;
        int li_cycle;
        struct re_s *li_task;
+       Filter *li_oldf;
+       Entry *li_old;
+       log_attr *li_oldattrs;
        int li_success;
-       ldap_pvt_thread_mutex_t li_op_mutex;
+       ldap_pvt_thread_rmutex_t li_op_rmutex;
        ldap_pvt_thread_mutex_t li_log_mutex;
 } log_info;
 
@@ -68,7 +76,9 @@ enum {
        LOG_DB = 1,
        LOG_OPS,
        LOG_PURGE,
-       LOG_SUCCESS
+       LOG_SUCCESS,
+       LOG_OLD,
+       LOG_OLDATTR
 };
 
 static ConfigTable log_cfats[] = {
@@ -90,6 +100,14 @@ static ConfigTable log_cfats[] = {
                log_cf_gen, "( OLcfgOvAt:4.4 NAME 'olcAccessLogSuccess' "
                        "DESC 'Log successful ops only' "
                        "SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL },
+       { "logold", "filter", 2, 2, 0, ARG_MAGIC|LOG_OLD,
+               log_cf_gen, "( OLcfgOvAt:4.5 NAME 'olcAccessLogOld' "
+                       "DESC 'Log old values when modifying entries matching the filter' "
+                       "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
+       { "logoldattr", "attrs", 2, 0, 0, ARG_MAGIC|LOG_OLDATTR,
+               log_cf_gen, "( OLcfgOvAt:4.6 NAME 'olcAccessLogOldAttr' "
+                       "DESC 'Log old values of these attributes even if unmodified' "
+                       "SYNTAX OMsDirectoryString )", NULL, NULL },
        { NULL }
 };
 
@@ -99,7 +117,8 @@ static ConfigOCs log_cfocs[] = {
                "DESC 'Access log configuration' "
                "SUP olcOverlayConfig "
                "MUST olcAccessLogDB "
-               "MAY ( olcAccessLogOps $ olcAccessLogPurge $ olcAccessLogSuccess ) )",
+               "MAY ( olcAccessLogOps $ olcAccessLogPurge $ olcAccessLogSuccess $ "
+                       "olcAccessLogOld $ olcAccessLogOldAttr ) )",
                        Cft_Overlay, log_cfats },
        { NULL }
 };
@@ -361,7 +380,7 @@ static struct {
                "DESC 'ModRDN operation' "
                "SUP auditWriteObject STRUCTURAL "
                "MUST ( reqNewRDN $ reqDeleteOldRDN ) "
-               "MAY reqNewSuperior )", &log_ocs[LOG_EN_MODRDN] },
+               "MAY ( reqNewSuperior $ reqOld ) )", &log_ocs[LOG_EN_MODRDN] },
        { "( " LOG_SCHEMA_OC ".11 NAME 'auditSearch' "
                "DESC 'Search operation' "
                "SUP auditReadObject STRUCTURAL "
@@ -396,29 +415,29 @@ log_age_parse(char *agestr)
                        return -1;
                t1 *= 24;
                gotdays = 1;
-       } else if ( *endptr != ':' ) {
-       /* No valid delimiter found, fail */
-               return -1;
+               agestr = endptr + 1;
+       } else {
+               if ( agestr[2] != ':' ) {
+                       /* No valid delimiter found, fail */
+                       return -1;
+               }
+               t1 *= 60;
+               agestr += 3;
        }
 
-       agestr += 3;
        t2 = atoi( agestr );
-
-       /* if there's a delimiter, it can only be a colon */
-       if ( agestr[2] && agestr[2] != ':' )
-               return -1;
-
-       /* If we're at the end of the string, and we started with days,
-        * fail because we expected to find minutes too.
-        */
-       if ( gotdays && !agestr[2] )
-               return -1;
-
-       t1 *= 60;
        t1 += t2;
 
-       if ( !agestr[2] )
-               return t1 * 60;
+       if ( agestr[2] ) {
+               /* if there's a delimiter, it can only be a colon */
+               if ( agestr[2] != ':' )
+                       return -1;
+       } else {
+               /* If we're at the end of the string, and we started with days,
+                * fail because we expected to find minutes too.
+                */
+               return gotdays ? -1 : t1 * 60;
+       }
 
        agestr += 3;
        t2 = atoi( agestr );
@@ -429,12 +448,15 @@ log_age_parse(char *agestr)
        t1 *= 60;
        t1 += t2;
 
-       t1 *= 60;
        if ( agestr[2] ) {
                agestr += 3;
                if ( agestr[2] )
                        return -1;
+               t1 *= 60;
                t1 += atoi( agestr );
+       } else if ( gotdays ) {
+               /* only got days+hh:mm */
+               t1 *= 60;
        }
        return t1;
 }
@@ -449,7 +471,7 @@ log_age_unparse( int age, struct berval *agebv )
        age /= 60;
        mm = age % 60;
        age /= 60;
-       hh = age % 60;
+       hh = age % 24;
        age /= 24;
        dd = age;
 
@@ -605,6 +627,24 @@ log_cf_gen(ConfigArgs *c)
                        else
                                rc = 1;
                        break;
+               case LOG_OLD:
+                       if ( li->li_oldf ) {
+                               filter2bv( li->li_oldf, &agebv );
+                               value_add_one( &c->rvalue_vals, &agebv );
+                       }
+                       else
+                               rc = 1;
+                       break;
+               case LOG_OLDATTR:
+                       if ( li->li_oldattrs ) {
+                               log_attr *la;
+
+                               for ( la = li->li_oldattrs; la; la=la->next )
+                                       value_add_one( &c->rvalue_vals, &la->attr->ad_cname );
+                       }
+                       else
+                               rc = 1;
+                       break;
                }
                break;
        case LDAP_MOD_DELETE:
@@ -635,6 +675,32 @@ log_cf_gen(ConfigArgs *c)
                case LOG_SUCCESS:
                        li->li_success = 0;
                        break;
+               case LOG_OLD:
+                       if ( li->li_oldf ) {
+                               filter_free( li->li_oldf );
+                               li->li_oldf = NULL;
+                       }
+                       break;
+               case LOG_OLDATTR:
+                       if ( c->valx < 0 ) {
+                               log_attr *la, *ln;
+
+                               for ( la = li->li_oldattrs; la; la = ln ) {
+                                       ln = la->next;
+                                       ch_free( la );
+                               }
+                       } else {
+                               log_attr *la, **lp;
+                               int i;
+
+                               for ( lp = &li->li_oldattrs, i=0; i < c->valx; i++ ) {
+                                       la = *lp;
+                                       lp = &la->next;
+                               }
+                               *lp = la->next;
+                               ch_free( la );
+                       }
+                       break;
                }
                break;
        default:
@@ -680,6 +746,33 @@ log_cf_gen(ConfigArgs *c)
                case LOG_SUCCESS:
                        li->li_success = c->value_int;
                        break;
+               case LOG_OLD:
+                       li->li_oldf = str2filter( c->argv[1] );
+                       if ( !li->li_oldf ) {
+                               sprintf( c->msg, "bad filter!" );
+                               rc = 1;
+                       }
+                       break;
+               case LOG_OLDATTR: {
+                       int i;
+                       AttributeDescription *ad;
+                       const char *text;
+
+                       for ( i=1; i< c->argc; i++ ) {
+                               ad = NULL;
+                               if ( slap_str2ad( c->argv[i], &ad, &text ) == LDAP_SUCCESS ) {
+                                       log_attr *la = ch_malloc( sizeof( log_attr ));
+                                       la->attr = ad;
+                                       la->next = li->li_oldattrs;
+                                       li->li_oldattrs = la;
+                               } else {
+                                       sprintf( c->msg, "%s: %s", c->argv[i], text );
+                                       rc = ARG_BAD_CONF;
+                                       break;
+                               }
+                       }
+                       }
+                       break;
                }
                break;
        }
@@ -782,6 +875,24 @@ static struct berval derefs[] = {
 
 static struct berval simple = BER_BVC("SIMPLE");
 
+static void accesslog_val2val(AttributeDescription *ad, struct berval *val,
+       char c_op, struct berval *dst) {
+       char *ptr;
+
+       dst->bv_len = ad->ad_cname.bv_len + val->bv_len + 2;
+       if ( c_op ) dst->bv_len++;
+
+       dst->bv_val = ch_malloc( dst->bv_len+1 );
+
+       ptr = lutil_strcopy( dst->bv_val, ad->ad_cname.bv_val );
+       *ptr++ = ':';
+       if ( c_op )
+               *ptr++ = c_op;
+       *ptr++ = ' ';
+       AC_MEMCPY( ptr, val->bv_val, val->bv_len );
+       dst->bv_val[dst->bv_len] = '\0';
+}
+
 static int accesslog_response(Operation *op, SlapReply *rs) {
        slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
        log_info *li = on->on_bi.bi_private;
@@ -791,7 +902,7 @@ static int accesslog_response(Operation *op, SlapReply *rs) {
        int i;
        int logop;
        slap_verbmasks *lo;
-       Entry *e;
+       Entry *e = NULL, *old = NULL;
        char timebuf[LDAP_LUTIL_GENTIME_BUFSIZE+8];
        struct berval bv;
        char *ptr;
@@ -821,7 +932,9 @@ static int accesslog_response(Operation *op, SlapReply *rs) {
 
        if ( lo->mask & LOG_OP_WRITES ) {
                ldap_pvt_thread_mutex_lock( &li->li_log_mutex );
-               ldap_pvt_thread_mutex_unlock( &li->li_op_mutex );
+               old = li->li_old;
+               li->li_old = NULL;
+               ldap_pvt_thread_rmutex_unlock( &li->li_op_rmutex, op->o_tid );
        }
 
        if ( li->li_success && rs->sr_err != LDAP_SUCCESS )
@@ -844,9 +957,22 @@ static int accesslog_response(Operation *op, SlapReply *rs) {
 
        switch( logop ) {
        case LOG_EN_ADD:
+       case LOG_EN_DELETE: {
+               char c_op;
+               Entry *e2;
+
+               if ( logop == LOG_EN_ADD ) {
+                       e2 = op->ora_e;
+                       c_op = '+';
+               } else {
+                       if ( !old )
+                               break;
+                       e2 = old;
+                       c_op = 0;
+               }
                /* count all the vals */
                i = 0;
-               for ( a=op->ora_e->e_attrs; a; a=a->a_next ) {
+               for ( a=e2->e_attrs; a; a=a->a_next ) {
                        if ( a->a_vals ) {
                                for (b=a->a_vals; !BER_BVISNULL( b ); b++) {
                                        i++;
@@ -855,32 +981,21 @@ static int accesslog_response(Operation *op, SlapReply *rs) {
                }
                vals = ch_malloc( (i+1) * sizeof( struct berval ));
                i = 0;
-               for ( a=op->ora_e->e_attrs; a; a=a->a_next ) {
+               for ( a=e2->e_attrs; a; a=a->a_next ) {
                        if ( a->a_vals ) {
                                for (b=a->a_vals; !BER_BVISNULL( b ); b++,i++) {
-                                       vals[i].bv_len = a->a_desc->ad_cname.bv_len + b->bv_len +3;
-                                       vals[i].bv_val = ch_malloc( vals[i].bv_len+1 );
-                                       ptr = lutil_strcopy( vals[i].bv_val,
-                                               a->a_desc->ad_cname.bv_val );
-                                       *ptr++ = ':';
-                                       *ptr++ = '+';
-                                       *ptr++ = ' ';
-                                       AC_MEMCPY( ptr, b->bv_val, b->bv_len );
-                                       vals[i].bv_val[vals[i].bv_len] = '\0';
+                                       accesslog_val2val( a->a_desc, b, c_op, &vals[i] );
                                }
                        }
                }
                vals[i].bv_val = NULL;
                vals[i].bv_len = 0;
-               a = attr_alloc( ad_reqMod );
+               a = attr_alloc( logop == LOG_EN_ADD ? ad_reqMod : ad_reqOld );
                a->a_vals = vals;
                a->a_nvals = vals;
                last_attr->a_next = a;
                break;
-
-       case LOG_EN_DELETE:
-               /* needs nothing else */
-               break;
+       }
 
        case LOG_EN_MODIFY:
                /* count all the mods */
@@ -896,15 +1011,31 @@ static int accesslog_response(Operation *op, SlapReply *rs) {
                }
                vals = ch_malloc( (i+1) * sizeof( struct berval ));
                i = 0;
+
+               /* init flags on old entry */
+               if ( old ) {
+                       for ( a=old->e_attrs; a; a=a->a_next ) {
+                               log_attr *la;
+                               a->a_flags = 0;
+
+                               /* look for attrs that are always logged */
+                               for ( la=li->li_oldattrs; la; la=la->next )
+                                       if ( a->a_desc == la->attr )
+                                               a->a_flags = 1;
+                       }
+               }
+
                for ( m=op->orm_modlist; m; m=m->sml_next ) {
+                       /* Mark this attribute as modified */
+                       if ( old ) {
+                               a = attr_find( old->e_attrs, m->sml_desc );
+                               if ( a )
+                                       a->a_flags = 1;
+                       }
                        if ( m->sml_values ) {
                                for (b=m->sml_values; !BER_BVISNULL( b ); b++,i++) {
                                        char c_op;
-                                       vals[i].bv_len = m->sml_desc->ad_cname.bv_len + b->bv_len +3;
-                                       vals[i].bv_val = ch_malloc( vals[i].bv_len+1 );
-                                       ptr = lutil_strcopy( vals[i].bv_val,
-                                               m->sml_desc->ad_cname.bv_val );
-                                       *ptr++ = ':';
+
                                        switch( m->sml_op ) {
                                        case LDAP_MOD_ADD: c_op = '+'; break;
                                        case LDAP_MOD_DELETE:   c_op = '-'; break;
@@ -917,10 +1048,7 @@ static int accesslog_response(Operation *op, SlapReply *rs) {
                                         */
                                        default: c_op = '?'; break;
                                        }
-                                       *ptr++ = c_op;
-                                       *ptr++ = ' ';
-                                       AC_MEMCPY( ptr, b->bv_val, b->bv_len );
-                                       vals[i].bv_val[vals[i].bv_len] = '\0';
+                                       accesslog_val2val( m->sml_desc, b, c_op, &vals[i] );
                                }
                        } else if ( m->sml_op == LDAP_MOD_DELETE ) {
                                vals[i].bv_len = m->sml_desc->ad_cname.bv_len + 2;
@@ -939,9 +1067,71 @@ static int accesslog_response(Operation *op, SlapReply *rs) {
                a->a_vals = vals;
                a->a_nvals = vals;
                last_attr->a_next = a;
+
+               if ( old ) {
+                       last_attr = a;
+                       /* count all the vals */
+                       i = 0;
+                       for ( a=old->e_attrs; a; a=a->a_next ) {
+                               if ( a->a_vals && a->a_flags ) {
+                                       for (b=a->a_vals; !BER_BVISNULL( b ); b++) {
+                                       i++;
+                                       }
+                               }
+                       }
+                       vals = ch_malloc( (i+1) * sizeof( struct berval ));
+                       i = 0;
+                       for ( a=old->e_attrs; a; a=a->a_next ) {
+                               if ( a->a_vals && a->a_flags ) {
+                                       for (b=a->a_vals; !BER_BVISNULL( b ); b++,i++) {
+                                               accesslog_val2val( a->a_desc, b, 0, &vals[i] );
+                                       }
+                               }
+                       }
+                       vals[i].bv_val = NULL;
+                       vals[i].bv_len = 0;
+                       a = attr_alloc( ad_reqOld );
+                       a->a_vals = vals;
+                       a->a_nvals = vals;
+                       last_attr->a_next = a;
+               }
                break;
 
        case LOG_EN_MODRDN:
+               if ( old ) {
+                       /* count all the vals */
+                       i = 0;
+                       for ( a=old->e_attrs; a; a=a->a_next ) {
+                               log_attr *la;
+
+                               /* look for attrs that are always logged */
+                               for ( la=li->li_oldattrs; la; la=la->next ) {
+                                       if ( a->a_desc == la->attr ) {
+                                               for (b=a->a_vals; !BER_BVISNULL( b ); b++) {
+                                                       i++;
+                                               }
+                                       }
+                               }
+                       }
+                       vals = ch_malloc( (i+1) * sizeof( struct berval ));
+                       i = 0;
+                       for ( a=old->e_attrs; a; a=a->a_next ) {
+                               log_attr *la;
+                               for ( la=li->li_oldattrs; la; la=la->next ) {
+                                       if ( a->a_desc == la->attr ) {
+                                               for (b=a->a_vals; !BER_BVISNULL( b ); b++,i++) {
+                                                       accesslog_val2val( a->a_desc, b, 0, &vals[i] );
+                                               }
+                                       }
+                               }
+                       }
+                       vals[i].bv_val = NULL;
+                       vals[i].bv_len = 0;
+                       a = attr_alloc( ad_reqOld );
+                       a->a_vals = vals;
+                       a->a_nvals = vals;
+                       last_attr->a_next = a;
+               }
                attr_merge_one( e, ad_reqNewRDN, &op->orr_newrdn, &op->orr_nnewrdn );
                attr_merge_one( e, ad_reqDeleteOldRDN, op->orr_deleteoldrdn ?
                        (struct berval *)&slap_true_bv : (struct berval *)&slap_false_bv,
@@ -1040,10 +1230,12 @@ static int accesslog_response(Operation *op, SlapReply *rs) {
        }
 
        op2.o_bd->be_add( &op2, &rs2 );
-       entry_free( e );
 
 done:
-       ldap_pvt_thread_mutex_unlock( &li->li_log_mutex );
+       if ( lo->mask & LOG_OP_WRITES )
+               ldap_pvt_thread_mutex_unlock( &li->li_log_mutex );
+       if ( e ) entry_free( e );
+       if ( old ) entry_free( old );
        return SLAP_CB_CONTINUE;
 }
 
@@ -1095,10 +1287,22 @@ accesslog_op_mod( Operation *op, SlapReply *rs )
        log_info *li = on->on_bi.bi_private;
 
        if ( li->li_ops & LOG_OP_WRITES ) {
-               /* FIXME: this needs to be a recursive mutex to allow
-                * overlays like refint to keep working.
-                */
-               ldap_pvt_thread_mutex_lock( &li->li_op_mutex );
+               ldap_pvt_thread_rmutex_lock( &li->li_op_rmutex, op->o_tid );
+               if ( li->li_oldf && ( op->o_tag == LDAP_REQ_DELETE ||
+                       op->o_tag == LDAP_REQ_MODIFY ||
+                       ( op->o_tag == LDAP_REQ_MODRDN && li->li_oldattrs ))) {
+                       int rc;
+                       Entry *e;
+
+                       op->o_bd->bd_info = on->on_info->oi_orig;
+                       rc = be_entry_get_rw( op, &op->o_req_ndn, NULL, NULL, 0, &e );
+                       if ( e ) {
+                               if ( test_filter( op, e, li->li_oldf ) == LDAP_COMPARE_TRUE )
+                                       li->li_old = entry_dup( e );
+                               be_entry_release_rw( op, e, 0 );
+                       }
+                       op->o_bd->bd_info = (BackendInfo *)on;
+               }
        }
        return SLAP_CB_CONTINUE;
 }
@@ -1188,7 +1392,7 @@ accesslog_db_init(
        log_info *li = ch_calloc(1, sizeof(log_info));
 
        on->on_bi.bi_private = li;
-       ldap_pvt_thread_mutex_init( &li->li_op_mutex );
+       ldap_pvt_thread_rmutex_init( &li->li_op_rmutex );
        ldap_pvt_thread_mutex_init( &li->li_log_mutex );
        return 0;
 }
@@ -1202,7 +1406,7 @@ accesslog_db_destroy(
        log_info *li = on->on_bi.bi_private;
 
        ldap_pvt_thread_mutex_destroy( &li->li_log_mutex );
-       ldap_pvt_thread_mutex_destroy( &li->li_op_mutex );
+       ldap_pvt_thread_rmutex_destroy( &li->li_op_rmutex );
        free( li );
        return LDAP_SUCCESS;
 }
index cc67c2b950b55dd2afedddc64cda5eaac52ec5ac..f603c1429eec0c65c71d3606307a8456ed15a8b4 100644 (file)
@@ -51,8 +51,8 @@ static int auditlog_response(Operation *op, SlapReply *rs) {
        FILE *f;
        Attribute *a;
        Modifications *m;
-       struct berval *b;
-       char *what, *suffix, *who = NULL;
+       struct berval *b, *who = NULL;
+       char *what, *suffix;
        long stamp = slap_get_time();
        int i;
 
@@ -71,7 +71,7 @@ static int auditlog_response(Operation *op, SlapReply *rs) {
                        what = "add";
                        for(a = op->ora_e->e_attrs; a; a = a->a_next)
                                if( a->a_desc == slap_schema.si_ad_modifiersName ) {
-                                       who = a->a_vals[0].bv_val;
+                                       who = &a->a_vals[0];
                                        break;
                                }
                        break;
@@ -81,7 +81,7 @@ static int auditlog_response(Operation *op, SlapReply *rs) {
                                if( m->sml_desc == slap_schema.si_ad_modifiersName &&
                                        ( m->sml_op == LDAP_MOD_ADD ||
                                        m->sml_op == LDAP_MOD_REPLACE )) {
-                                       who = m->sml_values[0].bv_val;
+                                       who = &m->sml_values[0];
                                        break;
                                }
                        break;
@@ -96,7 +96,7 @@ static int auditlog_response(Operation *op, SlapReply *rs) {
 ** note: this means requestor's dn when modifiersName is null
 */
        if ( !who )
-               who = op->o_dn.bv_val;
+               who = &op->o_dn;
 
        ldap_pvt_thread_mutex_lock(&ad->ad_mutex);
        if((f = fopen(ad->ad_logfile, "a")) == NULL) {
@@ -104,8 +104,14 @@ static int auditlog_response(Operation *op, SlapReply *rs) {
                return SLAP_CB_CONTINUE;
        }
 
-       fprintf(f, "# %s %ld %s%s%s\ndn: %s\nchangetype: %s\n",
-               what, stamp, suffix, who ? " " : "", who ? who : "",
+       fprintf(f, "# %s %ld %s%s%s\n",
+               what, stamp, suffix, who ? " " : "", who ? who->bv_val : "");
+
+       if ( !who || !dn_match( who, &op->o_conn->c_dn ))
+               fprintf(f, "# realdn: %s\n", op->o_conn->c_dn.bv_val ? op->o_conn->c_dn.bv_val :
+                       "<empty>" );
+
+       fprintf(f, "dn: %s\nchangetype: %s\n",
                op->o_req_dn.bv_val, what);
 
        switch(op->o_tag) {
diff --git a/servers/slapd/overlays/constraint.c b/servers/slapd/overlays/constraint.c
new file mode 100644 (file)
index 0000000..18a3078
--- /dev/null
@@ -0,0 +1,287 @@
+/* constraint.c - Overlay to constrain attributes to certain values */
+/* 
+ *
+ * Copyright 2003-2004 Hewlett-Packard Company
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted only as authorized by the OpenLDAP
+ * Public License.
+ *
+ * A copy of this license is available in the file LICENSE in the
+ * top-level directory of the distribution or, alternatively, at
+ * <http://www.OpenLDAP.org/license.html>.
+ */
+/*
+ * Author: Neil Dunbar <neil.dunbar@hp.com>
+ */
+#include "portable.h"
+
+#ifdef SLAPD_OVER_CONSTRAINT
+
+#include <stdio.h>
+
+#include <ac/string.h>
+#include <ac/socket.h>
+#include <ac/regex.h>
+
+#include "slap.h"
+
+/*
+ * This overlay limits the values which can be placed into an
+ * attribute, over and above the limits placed by the schema.
+ *
+ * It traps only LDAP adds and modify commands (and only seeks to
+ * control the add and modify value mods of a modify)
+ */
+
+/*
+ * Linked list of attribute constraints which we should enforce.
+ * This is probably a sub optimal structure - some form of sorted
+ * array would be better if the number of attributes contrained is
+ * likely to be much bigger than 4 or 5. We stick with a list for
+ * the moment.
+ */
+typedef struct constraint {
+    struct constraint *ap_next;
+    AttributeDescription *ap;
+    regex_t *re;
+} constraint;
+
+static int
+constraint_violation( constraint *c, struct berval *bv )
+{
+    if ((!c) || (!bv)) return 0;
+    
+    if ((c->re) &&
+        (regexec(c->re, bv->bv_val, 0, NULL, 0) == REG_NOMATCH))
+        
+        return 1; /* regular expression violation */
+    
+    return 0;
+}
+
+static char *
+print_message( const char *fmt, AttributeDescription *a )
+{
+    char *ret;
+    int sz;
+    
+    sz = strlen(fmt) + a->ad_cname.bv_len + 1;
+    ret = ch_malloc(sz);
+    snprintf( ret, sz, fmt, a->ad_cname.bv_val );
+    return ret;
+}
+
+static int
+constraint_add( Operation *op, SlapReply *rs )
+{
+    slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
+    Attribute *a;
+    constraint *c = on->on_bi.bi_private, *cp;
+    BerVarray b = NULL;
+    int i;
+    const char *rsv = "add breaks regular expression constraint on %s";
+    char *msg;
+    
+    if ((a = op->ora_e->e_attrs) == NULL) {
+        op->o_bd->bd_info = (BackendInfo *)(on->on_info);
+        send_ldap_error(op, rs, LDAP_INVALID_SYNTAX,
+                        "constraint_add() got null op.ora_e.e_attrs");
+        return(rs->sr_err);
+    }
+
+    for(; a; a = a->a_next ) {
+            /* we don't constrain operational attributes */
+    
+        if (is_at_operational(a->a_desc->ad_type)) continue;
+        
+        for(cp = c; cp; cp = cp->ap_next) {
+            if (cp->ap != a->a_desc) continue;
+            if ((b = a->a_vals) == NULL) continue;
+                
+            for(i=0; b[i].bv_val; i++) {
+                int cv = constraint_violation( cp, &b[i]);
+                    
+                if (cv) {
+                        /* regex violation */
+                    op->o_bd->bd_info = (BackendInfo *)(on->on_info);
+                    msg = print_message( rsv, a->a_desc );
+                    send_ldap_error(op, rs, LDAP_CONSTRAINT_VIOLATION, msg );
+                    ch_free(msg);
+                    return (rs->sr_err);
+                }
+            }
+        }
+    }
+       /* Default is to just fall through to the normal processing */
+    return SLAP_CB_CONTINUE;
+}
+
+static int
+constraint_modify( Operation *op, SlapReply *rs )
+{
+    slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
+    constraint *c = on->on_bi.bi_private, *cp;
+    Modifications *m;
+    BerVarray b = NULL;
+    int i;
+    const char *rsv = "modify breaks regular expression constraint on %s";
+    char *msg;
+    
+    if ((m = op->orm_modlist) == NULL) {
+        op->o_bd->bd_info = (BackendInfo *)(on->on_info);
+        send_ldap_error(op, rs, LDAP_INVALID_SYNTAX,
+                        "constraint_modify() got null orm_modlist");
+        return(rs->sr_err);
+    }
+
+    for(;m; m = m->sml_next) {
+        if (is_at_operational( m->sml_desc->ad_type )) continue;
+        if ((( m->sml_op & LDAP_MOD_OP ) != LDAP_MOD_ADD) &&
+            (( m->sml_op & LDAP_MOD_OP ) != LDAP_MOD_REPLACE))
+            continue;
+            /* we only care about ADD and REPLACE modifications */
+        if ((( b = m->sml_values ) == NULL ) || (b[0].bv_val == NULL))
+            continue;
+
+        for(cp = c; cp; cp = cp->ap_next) {
+            if (cp->ap != m->sml_desc) continue;
+            
+            for(i=0; b[i].bv_val; i++) {
+                int cv = constraint_violation( cp, &b[i]);
+                
+                if (cv) {
+                        /* regex violation */
+                    op->o_bd->bd_info = (BackendInfo *)(on->on_info);
+                    msg = print_message( rsv, m->sml_desc );
+                    send_ldap_error(op, rs, LDAP_CONSTRAINT_VIOLATION, msg );
+                    ch_free(msg);
+                    return (rs->sr_err);
+                }
+            }
+        }
+    }
+    
+    return SLAP_CB_CONTINUE;
+}
+
+static int constraint_config(
+    BackendDB  *be,
+    const char *fname,
+    int                lineno,
+    int                argc,
+    char       **argv
+    )
+{
+    slap_overinst *on = (slap_overinst *) be->bd_info;
+    constraint ap = { NULL, NULL, NULL  }, *a2 = NULL;
+    regmatch_t rm[2];
+    
+    if ( strcasecmp( argv[0], "constraint_attribute" ) == 0 ) {
+        const char *text;
+                
+        if ( argc != 4 ) {
+            Debug( LDAP_DEBUG_ANY, "%s: line %d: "
+                   "wrong number of parameters in"
+                   "\"constraint_attribute <attribute> <constraint> <constraint_value>\" line.\n",
+                   fname, lineno, 0 );
+            return( 1 );
+        }
+        if ( slap_str2ad( argv[1], &ap.ap, &text ) ) {
+            Debug( LDAP_DEBUG_ANY, "%s: line %d: "
+                   "attribute description unknown \"constraint_attribute\" line: %s.\n",
+                   fname, lineno, text );
+            return( 1 );
+        }
+
+        if ( strcasecmp( argv[2], "regex" ) == 0) {
+            int err;
+            
+            ap.re = ch_malloc( sizeof(regex_t) );
+            if ((err = regcomp( ap.re, argv[3], REG_EXTENDED )) != 0) {
+                const char *fmt = "%s: line %d: Illegal regular expression \"%s\": Error %s\n";
+                char errmsg[1024], *msg;
+                int i, l, msgsize;
+                
+                msgsize = regerror( err, ap.re, errmsg, sizeof(errmsg) );
+                msgsize += strlen(fmt) + strlen(argv[3]) + strlen(fname);
+                for(l=lineno; l>0; l/=10, msgsize++);
+                msgsize++;
+
+                msg = ch_malloc( msgsize + 1 );
+                snprintf( msg, msgsize, fmt, fname, lineno, argv[3], errmsg );
+                ch_free(ap.re);
+                Debug( LDAP_DEBUG_ANY, msg, 0, 0, 0);
+                ch_free(msg);
+                ap.re = NULL;
+                return(1);
+            }
+        } else
+            Debug( LDAP_DEBUG_ANY, "%s: line %d: "
+                   "Unknown constraint type: %s",
+                   fname, lineno, argv[2] );
+        
+
+        a2 = ch_malloc( sizeof(constraint) );
+        a2->ap_next = on->on_bi.bi_private;
+        a2->ap = ap.ap;
+        a2->re = ap.re;
+        on->on_bi.bi_private = a2;
+    } else {
+        return SLAP_CONF_UNKNOWN;
+    }
+    
+    return 0;
+}
+
+static int
+constraint_close(
+    BackendDB *be
+    )
+{
+    slap_overinst *on = (slap_overinst *) be->bd_info;
+    constraint *ap, *a2;
+
+    for ( ap = on->on_bi.bi_private; ap; ap = a2 ) {
+        a2 = ap->ap_next;
+        if (ap->re) {
+            regfree( ap->re );
+            ch_free( ap->re );
+        }
+        
+        ch_free( ap );
+    }
+
+    return 0;
+}
+
+static slap_overinst constraint_ovl;
+
+/* This overlay is set up for dynamic loading via moduleload. For static
+ * configuration, you'll need to arrange for the slap_overinst to be
+ * initialized and registered by some other function inside slapd.
+ */
+
+#if SLAPD_OVER_CONSTRAINT == SLAPD_MOD_DYNAMIC
+static
+#endif
+int
+constraint_initialize( void ) {
+    constraint_ovl.on_bi.bi_type = "constraint";
+    constraint_ovl.on_bi.bi_db_config = constraint_config;
+    constraint_ovl.on_bi.bi_db_close = constraint_close;
+    constraint_ovl.on_bi.bi_op_add = constraint_add;
+    constraint_ovl.on_bi.bi_op_modify = constraint_modify;
+
+    return overlay_register( &constraint_ovl );
+}
+
+#if SLAPD_OVER_CONSTRAINT == SLAPD_MOD_DYNAMIC
+int init_module(int argc, char *argv[]) {
+    return constraint_initialize();
+}
+#endif
+
+#endif /* defined(SLAPD_OVER_CONSTRAINT) */
+
index 163e4daa8552eb3e22b14ce2abfed20d046d5fb4..a679e16f6e53e96e4f06272ad95b5a783119ed03 100644 (file)
@@ -475,9 +475,7 @@ cleanup:;
                        op->o_tmpfree( o.ors_filterstr.bv_val, op->o_tmpmemctx );
                        lud->lud_filter = NULL;
                }
-               if ( lud ) {
-                       ldap_free_urldesc( lud );
-               }
+               ldap_free_urldesc( lud );
        }
 
        rs->sr_entry = e;
index bed5b4b366b60e4509401e6e5a5790b9370d1301..95ff1fd7c84d914cae5a6c6c7a79fde2dc4e81b1 100644 (file)
@@ -55,7 +55,7 @@ typedef struct pp_info {
  * used by all instances
  */
 typedef struct pw_conn {
-       int restricted;         /* TRUE if connection is restricted */
+       struct berval dn;       /* DN of restricted user */
 } pw_conn;
 
 static pw_conn *pwcons;
@@ -259,11 +259,12 @@ account_locked( Operation *op, Entry *e,
        return 0;
 }
 
-#define PPOLICY_WARNING 0xa0L
-#define PPOLICY_ERROR 0xa1L
+/* IMPLICIT TAGS, all context-specific */
+#define PPOLICY_WARNING 0xa0L  /* constructed + 0 */
+#define PPOLICY_ERROR 0x81L            /* primitive + 1 */
  
-#define PPOLICY_EXPIRE 0xa0L
-#define PPOLICY_GRACE  0xa1L
+#define PPOLICY_EXPIRE 0x80L   /* primitive + 0 */
+#define PPOLICY_GRACE  0x81L   /* primitive + 1 */
 
 static LDAPControl *
 create_passcontrol( int exptime, int grace, LDAPPasswordPolicyError err )
@@ -813,7 +814,8 @@ ppolicy_bind_resp( Operation *op, SlapReply *rs )
                         * that we are disallowed from doing anything
                         * other than change password.
                         */
-                       pwcons[op->o_conn->c_conn_idx].restricted = 1;
+                       ber_dupbv( &pwcons[op->o_conn->c_conn_idx].dn,
+                               &op->o_conn->c_ndn );
 
                        ppb->pErr = PP_changeAfterReset;
 
@@ -971,7 +973,10 @@ ppolicy_bind( Operation *op, SlapReply *rs )
        slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
 
        /* Reset lockout status on all Bind requests */
-       pwcons[op->o_conn->c_conn_idx].restricted = 0;
+       if ( !BER_BVISEMPTY( &pwcons[op->o_conn->c_conn_idx].dn )) {
+               ch_free( pwcons[op->o_conn->c_conn_idx].dn.bv_val );
+               BER_BVZERO( &pwcons[op->o_conn->c_conn_idx].dn );
+       }
 
        /* Root bypasses policy */
        if ( !be_isroot_dn( op->o_bd, &op->o_req_ndn )) {
@@ -1025,11 +1030,14 @@ ppolicy_bind( Operation *op, SlapReply *rs )
        return SLAP_CB_CONTINUE;
 }
 
-/* Reset the restricted flag for the next session on this connection */
+/* Reset the restricted info for the next session on this connection */
 static int
 ppolicy_connection_destroy( BackendDB *bd, Connection *conn )
 {
-       pwcons[conn->c_conn_idx].restricted = 0;
+       if ( !BER_BVISEMPTY( &pwcons[conn->c_conn_idx].dn )) {
+               ch_free( pwcons[conn->c_conn_idx].dn.bv_val );
+               BER_BVZERO( &pwcons[conn->c_conn_idx].dn );
+       }
        return SLAP_CB_CONTINUE;
 }
 
@@ -1047,7 +1055,18 @@ ppolicy_restrict(
                send_ctrl = 1;
        }
 
-       if ( op->o_conn && pwcons[op->o_conn->c_conn_idx].restricted ) {
+       if ( op->o_conn && !BER_BVISEMPTY( &pwcons[op->o_conn->c_conn_idx].dn )) {
+               /* if the current authcDN doesn't match the one we recorded,
+                * then an intervening Bind has succeeded and the restriction
+                * no longer applies. (ITS#4516)
+                */
+               if ( !dn_match( &op->o_conn->c_ndn,
+                               &pwcons[op->o_conn->c_conn_idx].dn )) {
+                       ch_free( pwcons[op->o_conn->c_conn_idx].dn.bv_val );
+                       BER_BVZERO( &pwcons[op->o_conn->c_conn_idx].dn );
+                       return SLAP_CB_CONTINUE;
+               }
+
                Debug( LDAP_DEBUG_TRACE,
                        "connection restricted to password changing only\n", 0, 0, 0);
                if ( send_ctrl ) {
@@ -1353,13 +1372,19 @@ ppolicy_modify( Operation *op, SlapReply *rs )
                }
        }
        
-       if (pwcons[op->o_conn->c_conn_idx].restricted && !mod_pw_only) {
-               Debug( LDAP_DEBUG_TRACE,
-                       "connection restricted to password changing only\n", 0, 0, 0 );
-               rs->sr_err = LDAP_INSUFFICIENT_ACCESS; 
-               rs->sr_text = "Operations are restricted to bind/unbind/abandon/StartTLS/modify password";
-               pErr = PP_changeAfterReset;
-               goto return_results;
+       if (!BER_BVISEMPTY( &pwcons[op->o_conn->c_conn_idx].dn ) && !mod_pw_only ) {
+               if ( dn_match( &op->o_conn->c_ndn,
+                               &pwcons[op->o_conn->c_conn_idx].dn )) {
+                       Debug( LDAP_DEBUG_TRACE,
+                               "connection restricted to password changing only\n", 0, 0, 0 );
+                       rs->sr_err = LDAP_INSUFFICIENT_ACCESS; 
+                       rs->sr_text = "Operations are restricted to bind/unbind/abandon/StartTLS/modify password";
+                       pErr = PP_changeAfterReset;
+                       goto return_results;
+               } else {
+                       ch_free( pwcons[op->o_conn->c_conn_idx].dn.bv_val );
+                       BER_BVZERO( &pwcons[op->o_conn->c_conn_idx].dn );
+               }
        }
 
        /*
index fc197234e16d35855f563bdb2a696da8bd1c8f53..96fc8cd2ba6661b271b4938b5adbbf57ecba4426 100644 (file)
@@ -38,6 +38,7 @@
 #include <ac/socket.h>
 
 #include "slap.h"
+#include "config.h"
 
 static slap_overinst refint;
 
@@ -66,9 +67,163 @@ typedef struct refint_data_s {
        BerValue nnothing;                      /* normalized nothingness */
 } refint_data;
 
+enum {
+       REFINT_ATTRS = 1,
+       REFINT_NOTHING
+};
+
+static ConfigDriver refint_cf_gen;
+
+static ConfigTable refintcfg[] = {
+       { "refint_attributes", "attribute...", 2, 0, 0,
+         ARG_MAGIC|REFINT_ATTRS, refint_cf_gen,
+         "( OLcfgOvAt:11.1 NAME 'olcRefintAttribute' "
+         "DESC 'Attributes for referential integrity' "
+         "SYNTAX OMsDirectoryString )", NULL, NULL },
+       { "refint_nothing", "string", 2, 2, 0,
+         ARG_DN|ARG_MAGIC|REFINT_NOTHING, refint_cf_gen,
+         "( OLcfgOvAt:11.2 NAME 'olcRefintNothing' "
+         "DESC 'Replacement DN to supply when needed' "
+         "SYNTAX OMsDN SINGLE-VALUE )", NULL, NULL },
+       { NULL, NULL, 0, 0, 0, ARG_IGNORED }
+};
+
+static ConfigOCs refintocs[] = {
+       { "( OLcfgOvOc:11.1 "
+         "NAME 'olcRefintConfig' "
+         "DESC 'Referential integrity configuration' "
+         "SUP olcOverlayConfig "
+         "MAY ( olcRefintAttribute $ olcRefintNothing ) )",
+         Cft_Overlay, refintcfg },
+       { NULL, 0, NULL }
+};
+
+static int
+refint_cf_gen(ConfigArgs *c)
+{
+       slap_overinst *on = (slap_overinst *)c->bi;
+       refint_data *dd = (refint_data *)on->on_bi.bi_private;
+       refint_attrs *ip, *pip, **pipp = NULL;
+       AttributeDescription *ad;
+       const char *text;
+       int rc = ARG_BAD_CONF;
+       int i;
+
+       switch ( c->op ) {
+       case SLAP_CONFIG_EMIT:
+               switch ( c->type ) {
+               case REFINT_ATTRS:
+                       ip = dd->attrs;
+                       while ( ip ) {
+                               value_add_one( &c->rvalue_vals,
+                                              &ip->attr->ad_cname );
+                               ip = ip->next;
+                       }
+                       rc = 0;
+                       break;
+               case REFINT_NOTHING:
+                       if ( !BER_BVISEMPTY( &dd->nothing )) {
+                               rc = value_add_one( &c->rvalue_vals,
+                                                   &dd->nothing );
+                               if ( rc ) return rc;
+                               rc = value_add_one( &c->rvalue_nvals,
+                                                   &dd->nnothing );
+                               return rc;
+                       }
+                       rc = 0;
+                       break;
+               default:
+                       abort ();
+               }
+               break;
+       case LDAP_MOD_DELETE:
+               switch ( c->type ) {
+               case REFINT_ATTRS:
+                       pipp = &dd->attrs;
+                       if ( c->valx < 0 ) {
+                               ip = *pipp;
+                               *pipp = NULL;
+                               while ( ip ) {
+                                       pip = ip;
+                                       ip = ip->next;
+                                       ch_free ( pip );
+                               }
+                       } else {
+                               /* delete from linked list */
+                               for ( i=0; i < c->valx; ++i ) {
+                                       pipp = &(*pipp)->next;
+                               }
+                               ip = *pipp;
+                               *pipp = (*pipp)->next;
+
+                               /* AttributeDescriptions are global so
+                                * shouldn't be freed here... */
+                               ch_free ( ip );
+                       }
+                       rc = 0;
+                       break;
+               case REFINT_NOTHING:
+                       if ( dd->nothing.bv_val )
+                               ber_memfree ( dd->nothing.bv_val );
+                       if ( dd->nnothing.bv_val )
+                               ber_memfree ( dd->nnothing.bv_val );
+                       dd->nothing.bv_len = 0;
+                       dd->nnothing.bv_len = 0;
+                       rc = 0;
+                       break;
+               default:
+                       abort ();
+               }
+               break;
+       case SLAP_CONFIG_ADD:
+               /* fallthrough to LDAP_MOD_ADD */
+       case LDAP_MOD_ADD:
+               switch ( c->type ) {
+               case REFINT_ATTRS:
+                       rc = 0;
+                       for ( i=1; i < c->argc; ++i ) {
+                               ad = NULL;
+                               if ( slap_str2ad ( c->argv[i], &ad, &text )
+                                    == LDAP_SUCCESS) {
+                                       ip = ch_malloc (
+                                               sizeof ( refint_attrs ) );
+                                       ip->attr = ad;
+                                       ip->next = dd->attrs;
+                                       dd->attrs = ip;
+                               } else {
+                                       Debug ( LDAP_DEBUG_CONFIG,
+                                               "refint add: <%s>: %s\n",
+                                               c->argv[i], text, NULL );
+                                       strncpy ( c->msg,
+                                                 text,
+                                                 SLAP_TEXT_BUFLEN-1 );
+                                       c->msg[SLAP_TEXT_BUFLEN-1] = '\0';
+                                       rc = ARG_BAD_CONF;
+                               }
+                       }
+                       break;
+               case REFINT_NOTHING:
+                       if ( dd->nothing.bv_val )
+                               ber_memfree ( dd->nothing.bv_val );
+                       if ( dd->nnothing.bv_val )
+                               ber_memfree ( dd->nnothing.bv_val );
+                       dd->nothing = c->value_dn;
+                       dd->nnothing = c->value_ndn;
+                       rc = 0;
+                       break;
+               default:
+                       abort ();
+               }
+               break;
+       default:
+               abort ();
+       }
+
+       return rc;
+}
+
 /*
 ** allocate new refint_data;
-** initialize, copy basedn;
 ** store in on_bi.bi_private;
 **
 */
@@ -79,105 +234,29 @@ refint_db_init(
 )
 {
        slap_overinst *on = (slap_overinst *)be->bd_info;
-       refint_data *id = ch_malloc(sizeof(refint_data));
+       refint_data *id = ch_calloc(1,sizeof(refint_data));
 
        id->message = "_init";
-       id->attrs = NULL;
-       id->newdn.bv_val = NULL;
-       id->nothing.bv_val = NULL;
-       id->nnothing.bv_val = NULL;
-       ber_dupbv( &id->dn, &be->be_nsuffix[0] );
        on->on_bi.bi_private = id;
        return(0);
 }
 
-
-/*
-** if command = attributes:
-**     foreach argument:
-**             convert to attribute;
-**             add to configured attribute list;
-** elseif command = basedn:
-**     set our basedn to argument;
-**
-*/
-
 static int
-refint_config(
-       BackendDB       *be,
-       const char      *fname,
-       int             lineno,
-       int             argc,
-       char            **argv
+refint_db_destroy(
+       BackendDB       *be
 )
 {
-       slap_overinst *on       = (slap_overinst *) be->bd_info;
-       refint_data *id = on->on_bi.bi_private;
-       refint_attrs *ip;
-       const char *text;
-       AttributeDescription *ad;
-       BerValue dn;
-       int i;
+       slap_overinst *on = (slap_overinst *)be->bd_info;
 
-       if(!strcasecmp(*argv, "refint_attributes")) {
-               for(i = 1; i < argc; i++) {
-                       for(ip = id->attrs; ip; ip = ip->next)
-                           if(!strcmp(argv[i], ip->attr->ad_cname.bv_val)) {
-                               Debug(LDAP_DEBUG_ANY,
-                                       "%s: line %d: duplicate attribute <s>, ignored\n",
-                                       fname, lineno, argv[i]);
-                               continue;
-                       }
-                       ad = NULL;
-                       if(slap_str2ad(argv[i], &ad, &text) != LDAP_SUCCESS) {
-                               Debug(LDAP_DEBUG_ANY,
-                                       "%s: line %d: bad attribute <%s>, ignored\n",
-                                       fname, lineno, text);
-                               continue;               /* XXX */
-                       } else if(ad->ad_next) {
-                               Debug(LDAP_DEBUG_ANY,
-                                       "%s: line %d: multiple attributes match <%s>, ignored\n",
-                                       fname, lineno, argv[i]);
-                               continue;
-                       }
-                       ip = ch_malloc(sizeof(refint_attrs));
-                       ip->attr = ad;
-                       ip->next = id->attrs;
-                       id->attrs = ip;
-                       Debug(LDAP_DEBUG_ANY, "%s: line %d: new attribute <%s>\n",
-                               fname, lineno, argv[i]);
-               }
-       } else if(!strcasecmp(*argv, "refint_base")) {
-               /* XXX only one basedn (yet) - need validate argument! */
-               if(id->dn.bv_val) ch_free(id->dn.bv_val);
-               ber_str2bv( argv[1], 0, 0, &dn );
-               Debug(LDAP_DEBUG_ANY, "%s: line %d: new baseDN <%s>\n",
-                       fname, lineno, argv[1]);
-               if(dnNormalize(0, NULL, NULL, &dn, &id->dn, NULL)) {
-                       Debug(LDAP_DEBUG_ANY, "%s: line %d: bad baseDN!\n", fname, lineno, 0);
-                       return(1);
-               }
-       } else if(!strcasecmp(*argv, "refint_nothing")) {
-               if(id->nothing.bv_val) ch_free(id->nothing.bv_val);
-               if(id->nnothing.bv_val) ch_free(id->nnothing.bv_val);
-               ber_str2bv( argv[1], 0, 1, &id->nothing );
-               if(dnNormalize(0, NULL, NULL, &id->nothing, &id->nnothing, NULL)) {
-                       Debug(LDAP_DEBUG_ANY, "%s: line %d: bad nothingDN!\n", fname, lineno, 0);
-                       return(1);
-               }
-               Debug(LDAP_DEBUG_ANY, "%s: line %d: new nothingDN<%s>\n",
-                       fname, lineno, argv[1]);
-       } else {
-               return(SLAP_CONF_UNKNOWN);
+       if ( on->on_bi.bi_private ) {
+               ch_free( on->on_bi.bi_private );
+               on->on_bi.bi_private = NULL;
        }
-
-       id->message = "_config";
        return(0);
 }
 
-
 /*
-** nothing really happens here;
+** initialize, copy basedn if not already set
 **
 */
 
@@ -189,6 +268,12 @@ refint_open(
        slap_overinst *on       = (slap_overinst *)be->bd_info;
        refint_data *id = on->on_bi.bi_private;
        id->message             = "_open";
+
+       if ( BER_BVISNULL( &id->dn )) {
+               if ( BER_BVISNULL( &be->be_nsuffix[0] ))
+                       return -1;
+               ber_dupbv( &id->dn, &be->be_nsuffix[0] );
+       }
        return(0);
 }
 
@@ -222,9 +307,7 @@ refint_close(
        ch_free(id->nothing.bv_val);
        ch_free(id->nnothing.bv_val);
 
-       on->on_bi.bi_private = NULL;    /* XXX */
-
-       ch_free(id);
+       memset( id, 0, sizeof(*id));
 
        return(0);
 }
@@ -666,15 +749,20 @@ done:
 */
 
 int refint_initialize() {
+       int rc;
 
        /* statically declared just after the #includes at top */
        refint.on_bi.bi_type = "refint";
        refint.on_bi.bi_db_init = refint_db_init;
-       refint.on_bi.bi_db_config = refint_config;
+       refint.on_bi.bi_db_destroy = refint_db_destroy;
        refint.on_bi.bi_db_open = refint_open;
        refint.on_bi.bi_db_close = refint_close;
        refint.on_response = refint_response;
 
+       refint.on_bi.bi_cf_ocs = refintocs;
+       rc = config_register_schema ( refintcfg, refintocs );
+       if ( rc ) return rc;
+
        return(overlay_register(&refint));
 }
 
index 44a1b709c0d4999fa8c8731c45440f52039c0dd3..add5a75235424f3a1ae2099f76f7a9846f7b8446 100644 (file)
@@ -531,7 +531,7 @@ retcode_entry_response( Operation *op, SlapReply *rs, BackendInfo *bi, Entry *e
 
        /* sleep time */
        a = attr_find( e->e_attrs, ad_errSleepTime );
-       if ( a != NULL ) {
+       if ( a != NULL && a->a_nvals[ 0 ].bv_val[ 0 ] != '-' ) {
                int     sleepTime;
 
                sleepTime = strtoul( a->a_nvals[ 0 ].bv_val, &next, 0 );
index 95cc42225d6d739402b72b297ac03e1f61fc5635..2e07c98104628baf49a59f04c70f7aebb79f7943 100644 (file)
@@ -761,12 +761,97 @@ error_return:;
 
 }
 
+static int
+rwm_exop_passwd( Operation *op, SlapReply *rs )
+{
+       slap_overinst           *on = (slap_overinst *) op->o_bd->bd_info;
+       int                     rc;
+
+       struct berval   id = BER_BVNULL,
+                       pwold = BER_BVNULL,
+                       pwnew = BER_BVNULL;
+
+       if ( !BER_BVISNULL( &op->o_req_ndn ) ) {
+               return LDAP_SUCCESS;
+       }
+
+       if ( !SLAP_ISGLOBALOVERLAY( op->o_bd ) ) {
+               rs->sr_err = LDAP_OTHER;
+               return rs->sr_err;
+       }
+
+       rs->sr_err = slap_passwd_parse( op->ore_reqdata, &id,
+               &pwold, &pwnew, &rs->sr_text );
+       if ( rs->sr_err != LDAP_SUCCESS ) {
+               return rs->sr_err;
+       }
+
+       if ( !BER_BVISNULL( &id ) ) {
+               rs->sr_err = dnPrettyNormal( NULL, &id, &op->o_req_dn,
+                               &op->o_req_ndn, op->o_tmpmemctx );
+               if ( rs->sr_err != LDAP_SUCCESS ) {
+                       rs->sr_text = "Invalid DN";
+                       return rs->sr_err;
+               }
+
+       } else {
+               ber_dupbv_x( &op->o_req_dn, &op->o_dn, op->o_tmpmemctx );
+               ber_dupbv_x( &op->o_req_ndn, &op->o_ndn, op->o_tmpmemctx );
+       }
+
+#ifdef ENABLE_REWRITE
+       rc = rwm_op_dn_massage( op, rs, "extendedDN" );
+#else /* ! ENABLE_REWRITE */
+       rc = 1;
+       rc = rwm_op_dn_massage( op, rs, &rc );
+#endif /* ! ENABLE_REWRITE */
+       if ( rc != LDAP_SUCCESS ) {
+               op->o_bd->bd_info = (BackendInfo *)on->on_info;
+               send_ldap_error( op, rs, rc, "extendedDN massage error" );
+               return -1;
+       }
+
+       /* TODO: re-encode the request */
+
+       return SLAP_CB_CONTINUE;
+}
+
+static struct exop {
+       struct berval   oid;
+       BI_op_extended  *extended;
+} exop_table[] = {
+       { BER_BVC(LDAP_EXOP_MODIFY_PASSWD),     rwm_exop_passwd },
+       { BER_BVNULL, NULL }
+};
+
 static int
 rwm_extended( Operation *op, SlapReply *rs )
 {
        slap_overinst           *on = (slap_overinst *) op->o_bd->bd_info;
        int                     rc;
 
+       int     i;
+
+       for ( i = 0; exop_table[i].extended != NULL; i++ ) {
+               if ( bvmatch( &exop_table[i].oid, &op->oq_extended.rs_reqoid ) )
+               {
+                       rc = exop_table[i].extended( op, rs );
+                       switch ( rc ) {
+                       case LDAP_SUCCESS:
+                               break;
+
+                       case SLAP_CB_CONTINUE:
+                       case SLAPD_ABANDON:
+                               return rc;
+
+                       default:
+                               send_ldap_result( op, rs );
+                               return rc;
+                       }
+                       break;
+               }
+       }
+
 #ifdef ENABLE_REWRITE
        rc = rwm_op_dn_massage( op, rs, "extendedDN" );
 #else /* ! ENABLE_REWRITE */
index 2278ad34ebd284b1e4cce696d0aea16b80313fd9..3fe92a3e2be5bebf771c1117b007895ea60f53e6 100644 (file)
@@ -1320,12 +1320,14 @@ playlog_cb( Operation *op, SlapReply *rs )
 /* enter with sl->sl_mutex locked, release before returning */
 static void
 syncprov_playlog( Operation *op, SlapReply *rs, sessionlog *sl,
-       struct berval *oldcsn, struct berval *ctxcsn )
+       sync_control *srs, struct berval *ctxcsn )
 {
        slap_overinst           *on = (slap_overinst *)op->o_bd->bd_info;
        slog_entry *se;
        int i, j, ndel, num, nmods, mmods;
+       char cbuf[LDAP_LUTIL_CSNSTR_BUFSIZE];
        BerVarray uuids;
+       struct berval delcsn;
 
        if ( !sl->sl_num ) {
                ldap_pvt_thread_mutex_unlock( &sl->sl_mutex );
@@ -1338,19 +1340,23 @@ syncprov_playlog( Operation *op, SlapReply *rs, sessionlog *sl,
 
        uuids = op->o_tmpalloc( (num+1) * sizeof( struct berval ) +
                num * UUID_LEN, op->o_tmpmemctx );
-
        uuids[0].bv_val = (char *)(uuids + num + 1);
 
+       delcsn.bv_len = 0;
+       delcsn.bv_val = cbuf;
+
        /* Make a copy of the relevant UUIDs. Put the Deletes up front
         * and everything else at the end. Do this first so we can
         * unlock the list mutex.
         */
        for ( se=sl->sl_head; se; se=se->se_next ) {
-               if ( ber_bvcmp( &se->se_csn, oldcsn ) < 0 ) continue;
+               if ( ber_bvcmp( &se->se_csn, &srs->sr_state.ctxcsn ) <= 0 ) continue;
                if ( ber_bvcmp( &se->se_csn, ctxcsn ) > 0 ) break;
                if ( se->se_tag == LDAP_REQ_DELETE ) {
                        j = i;
                        i++;
+                       AC_MEMCPY( cbuf, se->se_csn.bv_val, se->se_csn.bv_len );
+                       delcsn.bv_len = se->se_csn.bv_len;
                } else {
                        nmods++;
                        j = num - nmods;
@@ -1442,9 +1448,14 @@ syncprov_playlog( Operation *op, SlapReply *rs, sessionlog *sl,
                fop.o_bd->bd_info = (BackendInfo *)on;
        }
        if ( ndel ) {
+               struct berval cookie;
+
+               slap_compose_sync_cookie( op, &cookie, &delcsn, srs->sr_state.rid );
                uuids[ndel].bv_val = NULL;
-               syncprov_sendinfo( op, rs, LDAP_TAG_SYNC_ID_SET, NULL, 0, uuids, 1 );
+               syncprov_sendinfo( op, rs, LDAP_TAG_SYNC_ID_SET, &cookie, 0, uuids, 1 );
+               op->o_tmpfree( cookie.bv_val, op->o_tmpmemctx );
        }
+       op->o_tmpfree( uuids, op->o_tmpmemctx );
 }
 
 static int
@@ -1811,13 +1822,23 @@ syncprov_search_response( Operation *op, SlapReply *rs )
                }
                if ( a ) {
                        /* Make sure entry is less than the snapshot'd contextCSN */
-                       if ( ber_bvcmp( &a->a_nvals[0], &ss->ss_ctxcsn ) > 0 )
+                       if ( ber_bvcmp( &a->a_nvals[0], &ss->ss_ctxcsn ) > 0 ) {
+                               Debug( LDAP_DEBUG_SYNC, "Entry %s CSN %s greater than snapshot %s\n",
+                                       rs->sr_entry->e_name.bv_val,
+                                       a->a_nvals[0].bv_val,
+                                       ss->ss_ctxcsn.bv_val );
                                return LDAP_SUCCESS;
+                       }
 
                        /* Don't send the ctx entry twice */
                        if ( !BER_BVISNULL( &srs->sr_state.ctxcsn ) &&
-                               bvmatch( &a->a_nvals[0], &srs->sr_state.ctxcsn ) )
+                               bvmatch( &a->a_nvals[0], &srs->sr_state.ctxcsn ) ) {
+                               Debug( LDAP_DEBUG_SYNC, "Entry %s CSN %s matches ctx %s\n",
+                                       rs->sr_entry->e_name.bv_val,
+                                       a->a_nvals[0].bv_val,
+                                       srs->sr_state.ctxcsn.bv_val );
                                return LDAP_SUCCESS;
+                       }
                }
                rs->sr_ctrls = op->o_tmpalloc( sizeof(LDAPControl *)*2,
                        op->o_tmpmemctx );
@@ -1963,7 +1984,7 @@ syncprov_op_search( Operation *op, SlapReply *rs )
                        if ( ber_bvcmp( &srs->sr_state.ctxcsn, &sl->sl_mincsn ) >= 0 ) {
                                do_present = 0;
                                /* mutex is unlocked in playlog */
-                               syncprov_playlog( op, rs, sl, &srs->sr_state.ctxcsn, &ctxcsn );
+                               syncprov_playlog( op, rs, sl, srs, &ctxcsn );
                        } else {
                                ldap_pvt_thread_mutex_unlock( &sl->sl_mutex );
                        }
index c87907462c32fc356d8f69c5833ff7db4446e2b6..401f1840849d8d13f1493512daa02e93a7e92fe6 100644 (file)
@@ -29,6 +29,7 @@
 #include <ac/socket.h>
 
 #include "slap.h"
+#include "config.h"
 
 static slap_overinst unique;
 
@@ -50,6 +51,196 @@ typedef struct unique_counter_s {
        int count;
 } unique_counter;
 
+enum {
+       UNIQUE_BASE = 1,
+       UNIQUE_IGNORE,
+       UNIQUE_ATTR,
+       UNIQUE_STRICT
+};
+
+static ConfigDriver unique_cf_gen;
+
+static ConfigTable uniquecfg[] = {
+       { "unique_base", "basedn", 2, 2, 0, ARG_DN|ARG_MAGIC|UNIQUE_BASE,
+         unique_cf_gen, "( OLcfgOvAt:10.1 NAME 'olcUniqueBase' "
+         "DESC 'Subtree for uniqueness searches' "
+         "SYNTAX OMsDN SINGLE-VALUE )", NULL, NULL },
+       { "unique_ignore", "attribute...", 2, 0, 0, ARG_MAGIC|UNIQUE_IGNORE,
+         unique_cf_gen, "( OLcfgOvAt:10.2 NAME 'olcUniqueIgnore' "
+         "DESC 'Attributes for which uniqueness shall not be enforced' "
+         "SYNTAX OMsDirectoryString )", NULL, NULL },
+       { "unique_attributes", "attribute...", 2, 0, 0, ARG_MAGIC|UNIQUE_ATTR,
+         unique_cf_gen, "( OLcfgOvAt:10.3 NAME 'olcUniqueAttribute' "
+         "DESC 'Attributes for which uniqueness shall be enforced' "
+         "SYNTAX OMsDirectoryString )", NULL, NULL },
+       { "unique_strict", "on|off", 1, 2, 0,
+         ARG_ON_OFF|ARG_OFFSET|UNIQUE_STRICT,
+         (void *)offsetof(unique_data, strict),
+         "( OLcfgOvAt:10.4 NAME 'olcUniqueStrict' "
+         "DESC 'Enforce uniqueness of null values' "
+         "SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL },
+       { NULL, NULL, 0, 0, 0, ARG_IGNORED }
+};
+
+static ConfigOCs uniqueocs[] = {
+       { "( OLcfgOvOc:10.1 "
+         "NAME 'olcUniqueConfig' "
+         "DESC 'Attribute value uniqueness configuration' "
+         "SUP olcOverlayConfig "
+         "MAY ( olcUniqueBase $ olcUniqueIgnore $ "
+         "olcUniqueAttribute $ olcUniqueStrict ) )",
+         Cft_Overlay, uniquecfg },
+       { NULL, 0, NULL }
+};
+
+static int
+unique_cf_gen( ConfigArgs *c )
+{
+       slap_overinst *on = (slap_overinst *)c->bi;
+       unique_data *ud = (unique_data *)on->on_bi.bi_private;
+       BackendDB *be = (BackendDB *)c->be;
+       unique_attrs *up, *pup, **pupp = NULL;
+       AttributeDescription *ad;
+       const char *text;
+       int rc = ARG_BAD_CONF;
+       int i;
+
+       switch ( c->op ) {
+       case SLAP_CONFIG_EMIT:
+               switch ( c->type ) {
+               case UNIQUE_BASE:
+                       if ( !BER_BVISEMPTY( &ud->dn )) {
+                               rc = value_add_one( &c->rvalue_vals, &ud->dn );
+                               if ( rc ) return rc;
+                               rc = value_add_one( &c->rvalue_nvals, &ud->dn );
+                               return rc;
+                       }
+                       break;
+               case UNIQUE_IGNORE:
+                       /* fallthrough to UNIQUE_ATTR */
+               case UNIQUE_ATTR:
+                       if ( c->type == UNIQUE_IGNORE ) up = ud->ignore;
+                       else up = ud->attrs;
+                       while ( up ) {
+                               value_add_one( &c->rvalue_vals,
+                                              &up->attr->ad_cname );
+                               up = up->next;
+                       }
+                       rc = 0;
+                       break;
+               case UNIQUE_STRICT:
+                       /* handled via ARG_OFFSET */
+                       /* fallthrough to default */
+               default:
+                       abort ();
+               }
+               break;
+       case LDAP_MOD_DELETE:
+               switch ( c->type ) {
+               case UNIQUE_BASE:
+                       /* default to the base of our configured database */
+                       if ( ud->dn.bv_val ) ber_memfree ( ud->dn.bv_val );
+                       ber_dupbv( &ud->dn, &be->be_nsuffix[0] );
+                       rc = 0;
+                       break;
+               case UNIQUE_IGNORE:
+                       /* fallthrough to UNIQUE_ATTR */
+               case UNIQUE_ATTR:
+                       if ( c->type == UNIQUE_IGNORE ) pupp = &ud->ignore;
+                       else pupp = &ud->attrs;
+
+                       if ( c->valx < 0 ) {
+                               up = *pupp;
+                               *pupp = NULL;
+                               while ( up ) {
+                                       pup = up;
+                                       up = up->next;
+                                       ch_free ( pup );
+                               }
+
+                       } else {
+
+                               /* delete from linked list */
+                               for ( i=0; i < c->valx; ++i ) {
+                                       pupp = &(*pupp)->next;
+                               }
+                               up = *pupp;
+                               *pupp = (*pupp)->next;
+
+                               /* AttributeDescriptions are global so
+                                * shouldn't be freed here... */
+                               ch_free ( up );
+                       }
+                       rc = 0;
+                       break;
+               case UNIQUE_STRICT:
+                       /* handled via ARG_OFFSET */
+                       /* fallthrough to default */
+               default:
+                       abort ();
+               }
+               break;
+       case SLAP_CONFIG_ADD:
+               /* fallthrough to LDAP_MOD_ADD */
+       case LDAP_MOD_ADD:
+               switch ( c->type ) {
+               case UNIQUE_BASE:
+                       if ( !dnIsSuffix ( &c->value_ndn,
+                                          &be->be_nsuffix[0] ) ) {
+                               sprintf ( c->msg, "dn is not a suffix of backend base" );
+                               Debug ( LDAP_DEBUG_CONFIG, "unique add: %s\n",
+                                       c->msg, NULL, NULL );
+                               rc = ARG_BAD_CONF;
+                       }
+                       if ( ud->dn.bv_val ) ber_memfree ( ud->dn.bv_val );
+                       ud->dn = c->value_ndn;
+                       rc = 0;
+                       break;
+               case UNIQUE_IGNORE:
+                       /* fallthrough to UNIQUE_ATTR */
+               case UNIQUE_ATTR:
+                       rc = 0;
+                       for ( i=1; i < c->argc; ++i ) {
+                               ad = NULL;
+                               if ( slap_str2ad ( c->argv[i], &ad, &text )
+                                    == LDAP_SUCCESS) {
+
+                                       up = ch_malloc (
+                                               sizeof ( unique_attrs ) );
+                                       up->attr = ad;
+                                       if ( c->type == UNIQUE_IGNORE ) {
+                                               up->next = ud->ignore;
+                                               ud->ignore = up;
+                                       } else {
+                                               up->next = ud->attrs;
+                                               ud->attrs = up;
+                                       }
+                               } else {
+                                       Debug ( LDAP_DEBUG_CONFIG,
+                                               "unique add: <%s>: %s\n",
+                                               c->argv[i], text, NULL );
+                                       strncpy ( c->msg,
+                                                 text,
+                                                 SLAP_TEXT_BUFLEN-1 );
+                                       c->msg[SLAP_TEXT_BUFLEN-1] = '\0';
+                                       rc = ARG_BAD_CONF;
+                               }
+                       }
+                       break;
+               case UNIQUE_STRICT:
+                       /* handled via ARG_OFFSET */
+                       /* fallthrough to default */
+               default:
+                       abort ();
+               }
+               break;
+       default:
+               abort ();
+       }
+
+       return rc;
+}
+
 /*
 ** allocate new unique_data;
 ** initialize, copy basedn;
@@ -62,103 +253,28 @@ static int unique_db_init(
 )
 {
        slap_overinst *on = (slap_overinst *)be->bd_info;
-       unique_data *ud   = ch_malloc(sizeof(unique_data));
+       unique_data *ud   = ch_calloc(1,sizeof(unique_data));
 
        /* Debug(LDAP_DEBUG_TRACE, "==> unique_init\n", 0, 0, 0); */
 
        ud->message     = "_init";
-       ud->attrs       = NULL;
-       ud->ignore      = NULL;
-       ud->strict      = 0;
-
-       /* default to the base of our configured database */
-       ber_dupbv(&ud->dn, &be->be_nsuffix[0]);
        on->on_bi.bi_private = ud;
-
        return 0;
 }
 
-
-/*
-** if command = attributes:
-**     foreach argument:
-**             convert to attribute;
-**             add to configured attribute list;
-** elseif command = base:
-**     set our basedn to argument;
-** else complain about invalid directive;
-**
-*/
-
-static int unique_config(
-       BackendDB       *be,
-       const char      *fname,
-       int             lineno,
-       int             argc,
-       char            **argv
+static int unique_db_destroy(
+       BackendDB       *be
 )
 {
-       slap_overinst *on = (slap_overinst *) be->bd_info;
-       unique_data *ud   = on->on_bi.bi_private;
-       unique_attrs *up;
-       const char *text;
-       AttributeDescription *ad;
-       int i;
+       slap_overinst *on = (slap_overinst *)be->bd_info;
 
-       ud->message = "_config";
-       Debug(LDAP_DEBUG_TRACE, "==> unique_config\n", 0, 0, 0);
-
-       if(!strcasecmp(*argv, "unique_attributes") ||
-          !strcasecmp(*argv, "unique_ignore")) {
-               for(i = 1; i < argc; i++) {
-                       for(up = ud->attrs; up; up = up->next)
-                           if(!strcmp(argv[i], up->attr->ad_cname.bv_val)) {
-                               Debug(LDAP_DEBUG_ANY,
-                                       "%s: line %d: duplicate attribute <%s>, ignored\n",
-                                       fname, lineno, argv[i]);
-                               continue;
-                       }
-                       ad = NULL;
-                       if(slap_str2ad(argv[i], &ad, &text) != LDAP_SUCCESS) {
-                               Debug(LDAP_DEBUG_ANY,
-                                       "%s: line %d: bad attribute <%s>, ignored\n",
-                                       fname, lineno, text);
-                               continue;               /* XXX */
-                       } else if(ad->ad_next) {
-                               Debug(LDAP_DEBUG_ANY,
-                                       "%s: line %d: multiple attributes match <%s>, ignored\n",
-                                       fname, lineno, argv[i]);
-                               continue;
-                       }
-                       up = ch_malloc(sizeof(unique_attrs));
-                       up->attr = ad;
-                       if(!strcasecmp(*argv, "unique_ignore")) {
-                               up->next = ud->ignore;
-                               ud->ignore = up;
-                       } else {
-                               up->next = ud->attrs;
-                               ud->attrs = up;
-                       }
-                       Debug(LDAP_DEBUG_CONFIG, "%s: line %d: new attribute <%s>\n",
-                               fname, lineno, argv[i]);
-               }
-       } else if(!strcasecmp(*argv, "unique_strict")) {
-               ud->strict = 1;
-       } else if(!strcasecmp(*argv, "unique_base")) {
-               struct berval bv;
-               ber_str2bv( argv[1], 0, 0, &bv );
-               ch_free(ud->dn.bv_val);
-               dnNormalize(0, NULL, NULL, &bv, &ud->dn, NULL);
-               Debug(LDAP_DEBUG_CONFIG, "%s: line %d: new base dn <%s>\n",
-                       fname, lineno, argv[1]);
-       } else {
-               return(SLAP_CONF_UNKNOWN);
+       if ( on->on_bi.bi_private ) {
+               ch_free( on->on_bi.bi_private );
+               on->on_bi.bi_private = NULL;
        }
-
-       return(0);
+       return 0;
 }
 
-
 /*
 ** mostly, just print the init message;
 **
@@ -175,6 +291,13 @@ unique_open(
 
        Debug(LDAP_DEBUG_TRACE, "unique_open: overlay initialized\n", 0, 0, 0);
 
+       if ( BER_BVISNULL( &ud->dn )) {
+               if ( BER_BVISNULL( &be->be_nsuffix[0] ))
+                       return -1;
+
+               /* default to the base of our configured database */
+               ber_dupbv(&ud->dn, &be->be_nsuffix[0]);
+       }
        return(0);
 }
 
@@ -183,9 +306,6 @@ unique_open(
 ** foreach configured attribute:
 **     free it;
 ** free our basedn;
-** (do not) free ud->message;
-** reset on_bi.bi_private;
-** free our config data;
 **
 */
 
@@ -213,9 +333,7 @@ unique_close(
 
        ch_free(ud->dn.bv_val);
 
-       on->on_bi.bi_private = NULL;    /* XXX */
-
-       ch_free(ud);
+       memset( ud, 0, sizeof(*ud));
 
        return(0);
 }
@@ -588,11 +706,12 @@ static int unique_modrdn(
 */
 
 int unique_initialize() {
+       int rc;
 
        /* statically declared just after the #includes at top */
        unique.on_bi.bi_type = "unique";
        unique.on_bi.bi_db_init = unique_db_init;
-       unique.on_bi.bi_db_config = unique_config;
+       unique.on_bi.bi_db_destroy = unique_db_destroy;
        unique.on_bi.bi_db_open = unique_open;
        unique.on_bi.bi_db_close = unique_close;
        unique.on_bi.bi_op_add = unique_add;
@@ -600,6 +719,10 @@ int unique_initialize() {
        unique.on_bi.bi_op_modrdn = unique_modrdn;
        unique.on_bi.bi_op_delete = NULL;
 
+       unique.on_bi.bi_cf_ocs = uniqueocs;
+       rc = config_register_schema( uniquecfg, uniqueocs );
+       if ( rc ) return rc;
+
        return(overlay_register(&unique));
 }
 
index 90d666dd8f2994ca29bdc36e459d62edeff2fd87..ddd3b27ef2b151e6335d6b1b82a77a023f81bcde 100644 (file)
@@ -520,8 +520,7 @@ void
 slap_passwd_generate( struct berval *pass )
 {
        Debug( LDAP_DEBUG_TRACE, "slap_passwd_generate\n", 0, 0, 0 );
-       pass->bv_val = NULL;
-       pass->bv_len = 0;
+       BER_BVZERO( pass );
 
        /*
         * generate passwords of only 8 characters as some getpass(3)
index 3697dad902fabe5554ff441b9523dcdc5abc7936..5a8bb9c5d605d6d7f086a0ee800a747e5e7dfabb 100644 (file)
@@ -727,6 +727,7 @@ LDAP_SLAPD_F (int) slapd_clr_read LDAP_P((ber_socket_t s, int wake));
 LDAP_SLAPD_V (volatile sig_atomic_t) slapd_abrupt_shutdown;
 LDAP_SLAPD_V (volatile sig_atomic_t) slapd_shutdown;
 LDAP_SLAPD_V (int) slapd_register_slp;
+LDAP_SLAPD_V (char *) slapd_slp_attrs;
 LDAP_SLAPD_V (slap_ssf_t) local_ssf;
 LDAP_SLAPD_V (struct runqueue_s) slapd_rq;
 
index 064854c721911b4b3d08af7e58fff6270097780f..966651ef2ab59f22f42de3f7a703f22d728f9323 100644 (file)
@@ -140,7 +140,7 @@ int validate_global_referral( const char *url )
        int rc;
        LDAPURLDesc *lurl;
 
-       rc = ldap_url_parse_ext( url, &lurl );
+       rc = ldap_url_parse_ext( url, &lurl, LDAP_PVT_URL_PARSE_NONE );
 
        switch( rc ) {
        case LDAP_URL_SUCCESS:
@@ -219,7 +219,7 @@ BerVarray referral_rewrite(
                char            *dn;
                int             rc;
                
-               rc = ldap_url_parse_ext( iv->bv_val, &url );
+               rc = ldap_url_parse_ext( iv->bv_val, &url, LDAP_PVT_URL_PARSE_NONE );
                if ( rc == LDAP_URL_ERR_BADSCHEME ) {
                        ber_dupbv( jv++, iv );
                        continue;
index e412c6169eecf7a9f70113ac3bb33232c846c056..bb27c760f3638cbc3cd7872e5db45e9fea6d416d 100644 (file)
@@ -36,7 +36,6 @@
 #include <ac/unistd.h>
 
 #include "slap.h"
-#include "lutil.h"
 
 const struct berval slap_dummy_bv = BER_BVNULL;
 
@@ -1467,9 +1466,43 @@ str2result(
                }
 
                if ( strncasecmp( s, "code", STRLENOF( "code" ) ) == 0 ) {
-                       if ( c != NULL && lutil_atoi( code, c ) != 0 ) {
-                               goto bailout;
+                       char    *next = NULL;
+                       long    retcode;
+
+                       if ( c == NULL ) {
+                               Debug( LDAP_DEBUG_ANY, "str2result (%s) missing value\n",
+                                   s, 0, 0 );
+                               rc = -1;
+                               continue;
                        }
+
+                       while ( isspace( (unsigned char) c[ 0 ] ) ) c++;
+                       if ( c[ 0 ] == '\0' ) {
+                               Debug( LDAP_DEBUG_ANY, "str2result (%s) missing or empty value\n",
+                                   s, 0, 0 );
+                               rc = -1;
+                               continue;
+                       }
+
+                       retcode = strtol( c, &next, 10 );
+                       if ( next == NULL || next == c ) {
+                               Debug( LDAP_DEBUG_ANY, "str2result (%s) unable to parse value\n",
+                                   s, 0, 0 );
+                               rc = -1;
+                               continue;
+                       }
+
+                       while ( isspace( (unsigned char) next[ 0 ] ) ) next++;
+                       if ( next[ 0 ] != '\0' ) {
+                               Debug( LDAP_DEBUG_ANY, "str2result (%s) extra cruft after value\n",
+                                   s, 0, 0 );
+                               rc = -1;
+                               continue;
+                       }
+
+                       /* FIXME: what if it's larger that max int? */
+                       *code = (int)retcode;
+
                } else if ( strncasecmp( s, "matched", STRLENOF( "matched" ) ) == 0 ) {
                        if ( c != NULL ) {
                                *matched = c;
@@ -1479,7 +1512,6 @@ str2result(
                                *info = c;
                        }
                } else {
-bailout:;
                        Debug( LDAP_DEBUG_ANY, "str2result (%s) unknown\n",
                            s, 0, 0 );
 
index 356cbc78a68182b7c59ac41ae7c6bc2bcf4ca2fd..9be7f5399b90334ee92b748060d27f65ecbd1110 100644 (file)
@@ -235,15 +235,17 @@ root_dse_info(
        /* FIXME: is this really needed? */
        BER_BVSTR( &val, "top" );
        if( attr_merge_one( e, ad_objectClass, &val, NULL ) ) {
+fail:
+               entry_free( e );
                return LDAP_OTHER;
        }
 
        BER_BVSTR( &val, "OpenLDAProotDSE" );
        if( attr_merge_one( e, ad_objectClass, &val, NULL ) ) {
-               return LDAP_OTHER;
+               goto fail;
        }
        if( attr_merge_one( e, ad_structuralObjectClass, &val, NULL ) ) {
-               return LDAP_OTHER;
+               goto fail;
        }
 
        LDAP_STAILQ_FOREACH( be, &backendDB, be_next ) {
@@ -257,7 +259,7 @@ root_dse_info(
                                        &be->be_suffix[0],
                                        &be->be_nsuffix[0] ) )
                        {
-                               return LDAP_OTHER;
+                               goto fail;
                        }
                        continue;
                }
@@ -266,7 +268,7 @@ root_dse_info(
                                        &be->be_suffix[0],
                                        & be->be_nsuffix[0] ) )
                        {
-                               return LDAP_OTHER;
+                               goto fail;
                        }
                        continue;
                }
@@ -278,7 +280,7 @@ root_dse_info(
                                        &be->be_suffix[j],
                                        &be->be_nsuffix[0] ) )
                        {
-                               return LDAP_OTHER;
+                               goto fail;
                        }
                }
        }
@@ -287,19 +289,19 @@ root_dse_info(
 
        /* supportedControl */
        if ( controls_root_dse_info( e ) != 0 ) {
-               return LDAP_OTHER;
+               goto fail;
        }
 
        /* supportedExtension */
        if ( exop_root_dse_info( e ) != 0 ) {
-               return LDAP_OTHER;
+               goto fail;
        }
 
 #ifdef LDAP_SLAPI
        /* netscape supportedExtension */
        for ( i = 0; (bv = slapi_int_get_supported_extop(i)) != NULL; i++ ) {
                if( attr_merge_one( e, ad_supportedExtension, bv, NULL ) ) {
-                       return LDAP_OTHER;
+                       goto fail;
                }
        }
 #endif /* LDAP_SLAPI */
@@ -310,7 +312,7 @@ root_dse_info(
        }
 
        if( attr_merge( e, ad_supportedFeatures, supportedFeatures, NULL ) ) {
-               return LDAP_OTHER;
+               goto fail;
        }
 
        /* supportedLDAPVersion */
@@ -325,7 +327,7 @@ root_dse_info(
                val.bv_val = buf;
                val.bv_len = strlen( val.bv_val );
                if( attr_merge_one( e, ad_supportedLDAPVersion, &val, NULL ) ) {
-                       return LDAP_OTHER;
+                       goto fail;
                }
        }
 
@@ -337,7 +339,8 @@ root_dse_info(
                        val.bv_val = supportedSASLMechanisms[i];
                        val.bv_len = strlen( val.bv_val );
                        if( attr_merge_one( e, ad_supportedSASLMechanisms, &val, NULL ) ) {
-                               return LDAP_OTHER;
+                               ldap_charray_free( supportedSASLMechanisms );
+                               goto fail;
                        }
                }
                ldap_charray_free( supportedSASLMechanisms );
@@ -345,7 +348,7 @@ root_dse_info(
 
        if ( default_referral != NULL ) {
                if( attr_merge( e, ad_ref, default_referral, NULL /* FIXME */ ) ) {
-                       return LDAP_OTHER;
+                       goto fail;
                }
        }
 
@@ -355,7 +358,7 @@ root_dse_info(
                        if( attr_merge( e, a->a_desc, a->a_vals,
                                (a->a_nvals == a->a_vals) ? NULL : a->a_nvals ) )
                        {
-                               return LDAP_OTHER;
+                               goto fail;
                        }
                }
        }
index 9b8a07f825719f7405f31bc1714949f185c492e2..dec004141559283d05ee695bce7fb38c17f21a5f 100644 (file)
@@ -1570,24 +1570,25 @@ static int slap_authz_regexp( struct berval *in, struct berval *out,
 }
 
 /* This callback actually does some work...*/
-static int sasl_sc_sasl2dn( Operation *o, SlapReply *rs )
+static int sasl_sc_sasl2dn( Operation *op, SlapReply *rs )
 {
-       struct berval *ndn = o->o_callback->sc_private;
+       struct berval *ndn = op->o_callback->sc_private;
 
-       if (rs->sr_type != REP_SEARCH) return 0;
+       if ( rs->sr_type != REP_SEARCH ) return LDAP_SUCCESS;
 
        /* We only want to be called once */
        if ( !BER_BVISNULL( ndn ) ) {
-               o->o_tmpfree(ndn->bv_val, o->o_tmpmemctx);
+               op->o_tmpfree( ndn->bv_val, op->o_tmpmemctx );
                BER_BVZERO( ndn );
 
                Debug( LDAP_DEBUG_TRACE,
-                       "slap_sc_sasl2dn: search DN returned more than 1 entry\n", 0, 0, 0 );
-               return -1;
+                       "%s: slap_sc_sasl2dn: search DN returned more than 1 entry\n",
+                       op->o_log_prefix, 0, 0 );
+               return LDAP_OTHER;
        }
 
-       ber_dupbv_x(ndn, &rs->sr_entry->e_nname, o->o_tmpmemctx);
-       return 0;
+       ber_dupbv_x( ndn, &rs->sr_entry->e_nname, op->o_tmpmemctx );
+       return LDAP_SUCCESS;
 }
 
 
index c150e339da2d2bf6616c56b43a4471986ec9b390..c600c6d84999135d65c3c50a2528b8ebdb8bf9f3 100644 (file)
@@ -1522,6 +1522,7 @@ typedef struct slap_bindconf {
 #ifdef HAVE_OPENSSL_CRL
        char *sb_tls_crlcheck;
 #endif
+       int sb_tls_do_init;
 #endif
 } slap_bindconf;
 
index f0a0a0580a8e50cbbc738093a5a67d6d2654f3bb..c7b6c274cf5b170ebea4027cb5fa47e71b8063a1 100644 (file)
@@ -313,12 +313,26 @@ slapacl( int argc, char **argv )
 
                accessstr = strchr( attr, '/' );
                if ( accessstr != NULL ) {
+                       int     invalid = 0;
+
                        accessstr[0] = '\0';
                        accessstr++;
                        access = str2access( accessstr );
-                       if ( access == ACL_INVALID_ACCESS ) {
+                       switch ( access ) {
+                       case ACL_INVALID_ACCESS:
                                fprintf( stderr, "unknown access \"%s\" for attribute \"%s\"\n",
                                                accessstr, attr );
+                               invalid = 1;
+                               break;
+
+                       case ACL_NONE:
+                               fprintf( stderr, "\"none\" not allowed for attribute \"%s\"\n",
+                                               attr );
+                               invalid = 1;
+                               break;
+                       }
+
+                       if ( invalid ) {
                                if ( continuemode ) {
                                        continue;
                                }
index 424a3d77989fb39e37b165a5abfb0c2c74b60320..0fb616118fd5fc6adc2a2932e7fa28e2aeae7e48 100644 (file)
@@ -230,7 +230,7 @@ slapi_over_result( Operation *op, SlapReply *rs, int type )
 {
        Slapi_PBlock            *pb = SLAPI_OPERATION_PBLOCK( op );
 
-       assert( rs->sr_type == REP_RESULT );
+       assert( rs->sr_type == REP_RESULT || rs->sr_type == REP_SASL || rs->sr_type == REP_EXTENDED );
 
        slapi_over_call_plugins( pb, type );
 
@@ -499,6 +499,8 @@ slapi_over_response( Operation *op, SlapReply *rs )
        if ( pb->pb_intop == 0 ) {
                switch ( rs->sr_type ) {
                case REP_RESULT:
+               case REP_SASL:
+               case REP_EXTENDED:
                        rc = slapi_over_result( op, rs, SLAPI_PLUGIN_PRE_RESULT_FN );
                        break;
                case REP_SEARCH:
@@ -528,6 +530,8 @@ slapi_over_cleanup( Operation *op, SlapReply *rs )
        if ( pb->pb_intop == 0 ) {
                switch ( rs->sr_type ) {
                case REP_RESULT:
+               case REP_SASL:
+               case REP_EXTENDED:
                        rc = slapi_over_result( op, rs, SLAPI_PLUGIN_POST_RESULT_FN );
                        break;
                case REP_SEARCH:
index 1bfdb768f1dda2ecc3108d2447c4e136141ba677..ea77df719d0a4ae3fadb6ab742c779382a4ec6c8 100644 (file)
@@ -32,6 +32,7 @@
 #include <ac/unistd.h>
 
 #include <ldap.h>
+#include <lber_pvt.h>
 #include <lutil.h>
 #include <lutil_sha1.h>
 
@@ -44,9 +45,11 @@ usage(const char *s)
 {
        fprintf(stderr,
                "Usage: %s [options]\n"
+               "  -c format\tcrypt(3) salt format\n"
+               "  -g\t\tgenerate random password\n"
                "  -h hash\tpassword scheme\n"
+               "  -n\t\tomit trailing newline\n"
                "  -s secret\tnew password\n"
-               "  -c format\tcrypt(3) salt format\n"
                "  -u\t\tgenerate RFC2307 values (default)\n"
                "  -v\t\tincrease verbosity\n"
                "  -T file\tread file for new password\n"
@@ -59,10 +62,11 @@ int
 slappasswd( int argc, char *argv[] )
 {
 #ifdef LUTIL_SHA1_BYTES
-       char    *scheme = "{SSHA}";
+       char    *default_scheme = "{SSHA}";
 #else
-       char    *scheme = "{SMD5}";
+       char    *default_scheme = "{SMD5}";
 #endif
+       char    *scheme = default_scheme;
 
        char    *newpw = NULL;
        char    *pwfile = NULL;
@@ -70,11 +74,12 @@ slappasswd( int argc, char *argv[] )
        const char *progname = "slappasswd";
 
        int             i;
-       struct berval passwd;
+       char            *newline = "\n";
+       struct berval passwd = BER_BVNULL;
        struct berval hash;
 
        while( (i = getopt( argc, argv,
-               "c:d:h:s:T:vu" )) != EOF )
+               "c:d:gh:ns:T:vu" )) != EOF )
        {
                switch (i) {
                case 'c':       /* crypt salt format */
@@ -82,21 +87,64 @@ slappasswd( int argc, char *argv[] )
                        lutil_salt_format( optarg );
                        break;
 
+               case 'g':       /* new password (generate) */
+                       if ( pwfile != NULL ) {
+                               fprintf( stderr, "Option -g incompatible with -T\n" );
+                               return EXIT_FAILURE;
+
+                       } else if ( newpw != NULL ) {
+                               fprintf( stderr, "New password already provided\n" );
+                               return EXIT_FAILURE;
+
+                       } else if ( lutil_passwd_generate( &passwd, 8 )) {
+                               fprintf( stderr, "Password generation failed\n" );
+                               return EXIT_FAILURE;
+                       }
+                       break;
+
                case 'h':       /* scheme */
-                       scheme = strdup( optarg );
+                       if ( scheme != default_scheme ) {
+                               fprintf( stderr, "Scheme already provided\n" );
+                               return EXIT_FAILURE;
+
+                       } else {
+                               scheme = strdup( optarg );
+                       }
+                       break;
+
+               case 'n':
+                       newline = "";
                        break;
 
                case 's':       /* new password (secret) */
-                       {
+                       if ( pwfile != NULL ) {
+                               fprintf( stderr, "Option -s incompatible with -T\n" );
+                               return EXIT_FAILURE;
+
+                       } else if ( newpw != NULL ) {
+                               fprintf( stderr, "New password already provided\n" );
+                               return EXIT_FAILURE;
+
+                       } else {
                                char* p;
                                newpw = strdup( optarg );
 
                                for( p = optarg; *p != '\0'; p++ ) {
                                        *p = '\0';
                                }
-                       } break;
+                       }
+                       break;
 
                case 'T':       /* password file */
+                       if ( pwfile != NULL ) {
+                               fprintf( stderr, "Password file already provided\n" );
+                               return EXIT_FAILURE;
+
+                       } else if ( newpw != NULL ) {
+                               fprintf( stderr, "Option -T incompatible with -s/-g\n" );
+                               return EXIT_FAILURE;
+
+                       }
                        pwfile = optarg;
                        break;
 
@@ -120,7 +168,7 @@ slappasswd( int argc, char *argv[] )
                if( lutil_get_filed_password( pwfile, &passwd )) {
                        return EXIT_FAILURE;
                }
-       } else {
+       } else if ( BER_BVISEMPTY( &passwd )) {
                if( newpw == NULL ) {
                        /* prompt for new password */
                        char *cknewpw;
@@ -135,6 +183,9 @@ slappasswd( int argc, char *argv[] )
 
                passwd.bv_val = newpw;
                passwd.bv_len = strlen(passwd.bv_val);
+       } else {
+               hash = passwd;
+               goto print_pw;
        }
 
        lutil_passwd_hash( &passwd, scheme, &hash, &text );
@@ -151,6 +202,7 @@ slappasswd( int argc, char *argv[] )
                return EXIT_FAILURE;
        }
 
-       printf( "%s\n" , hash.bv_val );
+print_pw:;
+       printf( "%s%s" , hash.bv_val, newline );
        return EXIT_SUCCESS;
 }
index b8f9a743297d40dd486c54815d7fedf4e1f6102c..de322be98fad93ff755c7fba5b7dc78b8fb07b1f 100644 (file)
@@ -83,9 +83,6 @@ typedef struct syncinfo_s {
        int                                     si_syncdata;
        int                                     si_logstate;
        int                                     si_conn_setup;
-#ifdef HAVE_TLS
-       int                                     si_check_tls;
-#endif
        Avlnode                         *si_presentlist;
        LDAP                            *si_ld;
        LDAP_LIST_HEAD(np, nonpresent_entry) si_nonpresentlist;
@@ -94,7 +91,7 @@ typedef struct syncinfo_s {
 
 static int syncuuid_cmp( const void *, const void * );
 static void avl_ber_bvfree( void * );
-static void syncrepl_del_nonpresent( Operation *, syncinfo_t *, BerVarray );
+static void syncrepl_del_nonpresent( Operation *, syncinfo_t *, BerVarray, struct berval * );
 static int syncrepl_message_to_op(
                                        syncinfo_t *, Operation *, LDAPMessage * );
 static int syncrepl_message_to_entry(
@@ -440,8 +437,7 @@ do_syncrep1(
                (const void *)&op->o_protocol );
 
 #ifdef HAVE_TLS
-       if ( si->si_check_tls ) {
-               si->si_check_tls = 0;
+       if ( si->si_bindconf.sb_tls_do_init ) {
                rc = bindconf_tls_set( &si->si_bindconf, si->si_ld );
        } else if ( si->si_bindconf.sb_tls_ctx ) {
                rc = ldap_set_option( si->si_ld, LDAP_OPT_X_TLS_CTX,
@@ -828,7 +824,7 @@ do_syncrep2(
                                        if ( refreshDeletes == 0 && match < 0 &&
                                                err == LDAP_SUCCESS )
                                        {
-                                               syncrepl_del_nonpresent( op, si, NULL );
+                                               syncrepl_del_nonpresent( op, si, NULL, NULL );
                                        } else {
                                                avl_free( si->si_presentlist, avl_ber_bvfree );
                                                si->si_presentlist = NULL;
@@ -920,7 +916,8 @@ do_syncrep2(
                                                ber_scanf( ber, "[W]", &syncUUIDs );
                                                ber_scanf( ber, /*"{"*/ "}" );
                                                if ( refreshDeletes ) {
-                                                       syncrepl_del_nonpresent( op, si, syncUUIDs );
+                                                       syncrepl_del_nonpresent( op, si, syncUUIDs,
+                                                               &syncCookie.ctxcsn );
                                                        ber_bvarray_free_x( syncUUIDs, op->o_tmpmemctx );
                                                } else {
                                                        for ( i = 0; !BER_BVISNULL( &syncUUIDs[i] ); i++ ) {
@@ -963,7 +960,7 @@ do_syncrep2(
 
                                        if ( si->si_refreshPresent == 1 ) {
                                                if ( match < 0 ) {
-                                                       syncrepl_del_nonpresent( op, si, NULL );
+                                                       syncrepl_del_nonpresent( op, si, NULL, NULL );
                                                }
                                        } 
 
@@ -1691,8 +1688,13 @@ syncrepl_entry(
        f.f_choice = LDAP_FILTER_EQUALITY;
        f.f_ava = &ava;
        ava.aa_desc = slap_schema.si_ad_entryUUID;
-       (void)slap_uuidstr_from_normalized( &syncUUID_strrep, syncUUID, op->o_tmpmemctx );
        ava.aa_value = *syncUUID;
+
+       (void)slap_uuidstr_from_normalized( &syncUUID_strrep, syncUUID, op->o_tmpmemctx );
+       if ( syncuuid_bv ) {
+               Debug( LDAP_DEBUG_SYNC, "syncrepl_entry: inserted UUID %s\n",
+                       syncUUID_strrep.bv_val, 0, 0 );
+       }
        op->ors_filter = &f;
 
        op->ors_filterstr.bv_len = STRLENOF( "(entryUUID=)" ) + syncUUID_strrep.bv_len;
@@ -2021,7 +2023,8 @@ static void
 syncrepl_del_nonpresent(
        Operation *op,
        syncinfo_t *si,
-       BerVarray uuids )
+       BerVarray uuids,
+       struct berval *cookiecsn )
 {
        Backend* be = op->o_bd;
        slap_callback   cb = { NULL };
@@ -2033,6 +2036,7 @@ syncrepl_del_nonpresent(
        AttributeName   an[2];
 
        struct berval pdn = BER_BVNULL;
+       struct berval csn;
 
        op->o_req_dn = si->si_base;
        op->o_req_ndn = si->si_base;
@@ -2099,7 +2103,12 @@ syncrepl_del_nonpresent(
 
        if ( !LDAP_LIST_EMPTY( &si->si_nonpresentlist ) ) {
 
-               slap_queue_csn( op, &si->si_syncCookie.ctxcsn );
+               if ( cookiecsn && !BER_BVISNULL( cookiecsn ))
+                       csn = *cookiecsn;
+               else
+                       csn = si->si_syncCookie.ctxcsn;
+
+               slap_queue_csn( op, &csn );
 
                np_list = LDAP_LIST_FIRST( &si->si_nonpresentlist );
                while ( np_list != NULL ) {
@@ -2497,10 +2506,14 @@ nonpresent_callback(
                if ( !(si->si_refreshDelete & NP_DELETE_ONE )) {
                        a = attr_find( rs->sr_entry->e_attrs, slap_schema.si_ad_entryUUID );
 
-                       if ( a == NULL ) return 0;
+                       if ( a )
+                               present_uuid = avl_find( si->si_presentlist, &a->a_nvals[0],
+                                       syncuuid_cmp );
+
+                       Debug( LDAP_DEBUG_SYNC, "nonpresent_callback: UUID %s, dn %s, %sfound\n",
+                               a ? a->a_vals[0].bv_val : "<missing>", rs->sr_entry->e_name.bv_val, present_uuid ? "" : "not " );
 
-                       present_uuid = avl_find( si->si_presentlist, &a->a_nvals[0],
-                               syncuuid_cmp );
+                       if ( a == NULL ) return 0;
                }
 
                if ( present_uuid == NULL ) {
@@ -2748,10 +2761,11 @@ syncinfo_free( syncinfo_t *sie )
 
 /* mandatory */
 #define GOT_ID                 0x0001
-#define GOT_PROVIDER           0x0002
+#define GOT_PROVIDER   0x0002
+#define        GOT_BASE                0x0004
 
 /* check */
-#define GOT_ALL                        (GOT_ID|GOT_PROVIDER)
+#define GOT_ALL                        (GOT_ID|GOT_PROVIDER|GOT_BASE)
 
 static struct {
        struct berval key;
@@ -2857,6 +2871,7 @@ parse_syncrepl_line(
                                Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
                                return -1;
                        }
+                       gots |= GOT_BASE;
                } else if ( !strncasecmp( c->argv[ i ], LOGBASESTR "=",
                                        STRLENOF( LOGBASESTR "=" ) ) )
                {
@@ -2983,8 +2998,11 @@ parse_syncrepl_line(
                        } else if ( strchr( val, ':' ) != NULL ) {
                                char *next, *ptr = val;
                                unsigned dd, hh, mm, ss;
+
+                               /* NOTE: the test for ptr[ 0 ] == '-'
+                                * should go before the call to strtoul() */
                                dd = strtoul( ptr, &next, 10 );
-                               if ( next == ptr || next[0] != ':' ) {
+                               if ( ptr[ 0 ] == '-' || next == ptr || next[0] != ':' ) {
                                        snprintf( c->msg, sizeof( c->msg ),
                                                "Error: parse_syncrepl_line: "
                                                "invalid interval \"%s\", unable to parse days", val );
@@ -2993,7 +3011,7 @@ parse_syncrepl_line(
                                }
                                ptr = next + 1;
                                hh = strtoul( ptr, &next, 10 );
-                               if ( next == ptr || next[0] != ':' || hh > 24 ) {
+                               if ( ptr[ 0 ] == '-' || next == ptr || next[0] != ':' || hh > 24 ) {
                                        snprintf( c->msg, sizeof( c->msg ),
                                                "Error: parse_syncrepl_line: "
                                                "invalid interval \"%s\", unable to parse hours", val );
@@ -3002,7 +3020,7 @@ parse_syncrepl_line(
                                }
                                ptr = next + 1;
                                mm = strtoul( ptr, &next, 10 );
-                               if ( next == ptr || next[0] != ':' || mm > 60 ) {
+                               if ( ptr[ 0 ] == '-' || next == ptr || next[0] != ':' || mm > 60 ) {
                                        snprintf( c->msg, sizeof( c->msg ),
                                                "Error: parse_syncrepl_line: "
                                                "invalid interval \"%s\", unable to parse minutes", val );
@@ -3011,7 +3029,7 @@ parse_syncrepl_line(
                                }
                                ptr = next + 1;
                                ss = strtoul( ptr, &next, 10 );
-                               if ( next == ptr || next[0] != '\0' || ss > 60 ) {
+                               if ( ptr[ 0 ] == '-' || next == ptr || next[0] != '\0' || ss > 60 ) {
                                        snprintf( c->msg, sizeof( c->msg ),
                                                "Error: parse_syncrepl_line: "
                                                "invalid interval \"%s\", unable to parse seconds", val );
@@ -3170,7 +3188,10 @@ parse_syncrepl_line(
 
        if ( gots != GOT_ALL ) {
                snprintf( c->msg, sizeof( c->msg ),
-                       "Error: Malformed \"syncrepl\" line in slapd config file" );
+                       "Error: Malformed \"syncrepl\" line in slapd config file, missing%s%s%s",
+                       gots & GOT_ID ? "" : " "IDSTR,
+                       gots & GOT_PROVIDER ? "" : " "PROVIDERSTR,
+                       gots & GOT_BASE ? "" : " "SEARCHBASESTR );
                Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
                return -1;
        }
@@ -3221,10 +3242,6 @@ add_syncrepl(
        si->si_slimit = 0;
        si->si_conn_setup = 0;
 
-#ifdef HAVE_TLS
-       si->si_check_tls = 1;
-#endif
-
        si->si_presentlist = NULL;
        LDAP_LIST_INIT( &si->si_nonpresentlist );
        ldap_pvt_thread_mutex_init( &si->si_mutex );
index 26d7d2b5620fd7a724f2f3a73a230a9eb1128e71..c05a0a317f8f78a6e01c956806f3c21c1f3c6d60 100644 (file)
@@ -41,7 +41,7 @@ authz-regexp  "^uid=([^,]+),.*" "uid=$1,ou=People,dc=example,dc=com"
 # cn=monitor, cn=schema, and cn=config
 #
 
-access to attr=userpassword
+access to attrs=userpassword
        by self =wx
        by anonymous =x
 
index 3037624c0b00fd869b5b6979e2ef017211e8e4eb..a44d7aabb11b3a49f1a6ef39a52d090a45ea0999 100644 (file)
@@ -40,7 +40,7 @@ authz-regexp  "^uid=([^,]+),.*" "uid=$1,ou=Groups,dc=example,dc=com"
 # cn=monitor, cn=schema, and cn=config
 #
 
-access to attr=userpassword
+access to attrs=userpassword
        by self =wx
        by anonymous =x
 
index 0798eeddb877f1a8c2c03e3d4fb4be21b30c1471..92c8488e0d6c3a7bc9bd8b517b1c55f906f2aade 100644 (file)
@@ -40,7 +40,7 @@ authz-regexp  "^uid=([^,]+),.*" "uid=$1,ou=People,dc=example,dc=com"
 # cn=monitor, cn=schema, and cn=config
 #
 
-access to attr=userpassword
+access to attrs=userpassword
        by dn.exact="uid=proxy,ou=People,dc=example,dc=com" read
        by self =wx
        by anonymous =x
index 6a31bc4dd952de665e944a380b1e0d76cbf45200..a87d5803be41189a69862a0eabecd045bba167ac 100644 (file)
@@ -45,7 +45,7 @@ overlay               ppolicy
 ppolicy_default        "cn=Standard Policy,ou=Policies,dc=example,dc=com"
 ppolicy_use_lockout
 
-access to attr=userpassword
+access to attrs=userpassword
        by self write
        by * auth
 
index 05fd80a99e57c9b3bab629d8e27cd9a3276eb138..d56bdcb42112788376d2fe25479c2ff6d7cf2611 100644 (file)
@@ -49,7 +49,7 @@ rootpw                secret
 # cn=monitor, cn=schema, and cn=config
 #
 
-access to attr=userpassword
+access to attrs=userpassword
        by anonymous auth
        by self write
 
index 2d6c7d8e54b2af0e65e4b832540c31ea893db5f4..b017b1af40f84fa7497a2503258c0581990936ba 100644 (file)
@@ -55,6 +55,7 @@ directory     @TESTDIR@/db.1.a
 #database      @BACKEND@
 #suffix                "dc=example,dc=com"
 #directory     @TESTDIR@/db.1.b
-#index         objectClass eq
+##bdb#index            objectClass eq
+##hdb#index            objectClass eq
 
 #monitor#database      monitor
index 166a30d92b74a0476209a86a6937bb3203ab0215..0d6b8c0dc068abad4fe8fd0eb25d0c43ef5c44ce 100644 (file)
@@ -52,6 +52,6 @@ valsort-attr            ou ou=users,o=valsort weighted
 valsort-attr            employeeType ou=users,o=valsort weighted alpha-ascend
 
 database config
-rootpw secret
+rootpw @CONFIGPW@
 
 #monitor#database      monitor
index 4be27d507964aedf5d3fba05988d22386df9fe63..89ae3b41029b5b3db9900a341045e71bc6449912 100644 (file)
@@ -40,10 +40,10 @@ authz-regexp        "^uid=([^,]+),.*" "ldap:///dc=example,dc=com??sub?uid=$1"
 # cn=monitor, cn=schema, and cn=config
 #
 
-access to attr=authzFrom,authzTo
+access to attrs=authzFrom,authzTo
        by * auth
 
-access to attr=userpassword
+access to attrs=userpassword
        by anonymous auth
        by self write
 
index 8cd45d1220e1fd509eb1b3b76c5faf5ccf49bd4f..912cc1531c85cb33937916c63f8f4b359c6ade4d 100644 (file)
@@ -37,7 +37,9 @@ suffix                "dc=example,dc=com"
 directory      @TESTDIR@/db.2.a
 rootdn         "cn=Manager,dc=example,dc=com"
 rootpw         secret
-index          objectClass     eq
-index          cn,sn,uid       pres,eq,sub
+#bdb#index             objectClass     eq
+#bdb#index             cn,sn,uid       pres,eq,sub
+#hdb#index             objectClass     eq
+#hdb#index             cn,sn,uid       pres,eq,sub
 
 #monitor#database      monitor
index 58ff55d7d2fe8e97f5ae2939084bdd9897b870a8..7118fb6b0fb251d8e93a9f5a2d5c87ae7fd368aa 100644 (file)
@@ -34,6 +34,7 @@
 
 #include <ldap.h>
 #include <lutil.h>
+#include <lber_pvt.h>
 
 #include "slapd-common.h"
 
@@ -44,8 +45,8 @@ do_bind( char *uri, char *dn, struct berval *pass, int maxloop,
        int force, int chaserefs, int noinit, LDAP **ldp );
 
 static int
-do_base( char *uri, struct berval *base, struct berval *pass, int maxloop,
-       int force, int chaserefs, int noinit, int delay );
+do_base( char *uri, struct berval *base, struct berval *pass, char *pwattr,
+       int maxloop, int force, int chaserefs, int noinit, int delay );
 
 /* This program can be invoked two ways: if -D is used to specify a Bind DN,
  * that DN will be used repeatedly for all of the Binds. If instead -b is used
@@ -58,10 +59,9 @@ static void
 usage( char *name )
 {
        fprintf( stderr, "usage: %s "
-               "[-h <host>] "
-               "-p port "
-               "(-D <dn>|-b <baseDN> [-f <searchfilter>]) "
-               "-w <passwd> "
+               "[-H uri | -h <host> [-p port]] "
+               "[-D <dn> [-w <passwd>]] "
+               "[-b <baseDN> [-f <searchfilter>] [-a pwattr]] "
                "[-l <loops>] "
                "[-L <outerloops>] "
                "[-F] "
@@ -83,6 +83,7 @@ main( int argc, char **argv )
        char            *dn = NULL;
        struct berval   base = { 0, NULL };
        struct berval   pass = { 0, NULL };
+       char            *pwattr = NULL;
        int             port = -1;
        int             loops = LOOPS;
        int             outerloops = 1;
@@ -93,8 +94,12 @@ main( int argc, char **argv )
 
        tester_init( "slapd-bind" );
 
-       while ( (i = getopt( argc, argv, "b:H:h:p:D:w:l:L:f:FIt:" )) != EOF ) {
+       while ( (i = getopt( argc, argv, "a:b:H:h:p:D:w:l:L:f:FIt:" )) != EOF ) {
                switch( i ) {
+               case 'a':
+                       pwattr = optarg;
+                       break;
+
                case 'b':               /* base DN of a tree of user DNs */
                        ber_str2bv( optarg, 0, 0, &base );
                        break;
@@ -104,11 +109,11 @@ main( int argc, char **argv )
                        break;
 
                case 'H':               /* the server uri */
-                       uri = strdup( optarg );
+                       uri = optarg;
                        break;
 
                case 'h':               /* the servers host */
-                       host = strdup( optarg );
+                       host = optarg;
                        break;
 
                case 'p':               /* the servers port */
@@ -118,12 +123,11 @@ main( int argc, char **argv )
                        break;
 
                case 'D':
-                       dn = strdup( optarg );
+                       dn = optarg;
                        break;
 
                case 'w':
-                       pass.bv_val = strdup( optarg );
-                       pass.bv_len = strlen( optarg );
+                       ber_str2bv( optarg, 0, 0, &pass );
                        break;
 
                case 'l':               /* the number of loops */
@@ -172,7 +176,7 @@ main( int argc, char **argv )
 
        for ( i = 0; i < outerloops; i++ ) {
                if ( base.bv_val != NULL ) {
-                       do_base( uri, &base, &pass, loops,
+                       do_base( uri, &base, &pass, pwattr, loops,
                                force, chaserefs, noinit, delay );
                } else {
                        do_bind( uri, dn, &pass, loops,
@@ -244,7 +248,7 @@ do_bind( char *uri, char *dn, struct berval *pass, int maxloop,
                fprintf( stderr, " PID=%ld - Bind done (%d).\n", (long) pid, rc );
        }
 
-       if ( ldp ) {
+       if ( ldp && noinit ) {
                *ldp = ld;
 
        } else if ( ld != NULL ) {
@@ -256,8 +260,8 @@ do_bind( char *uri, char *dn, struct berval *pass, int maxloop,
 
 
 static int
-do_base( char *uri, struct berval *base, struct berval *pass, int maxloop,
-       int force, int chaserefs, int noinit, int delay )
+do_base( char *uri, struct berval *base, struct berval *pass, char *pwattr,
+       int maxloop, int force, int chaserefs, int noinit, int delay )
 {
        LDAP    *ld = NULL;
        int     i = 0;
@@ -265,9 +269,10 @@ do_base( char *uri, struct berval *base, struct berval *pass, int maxloop,
        int     rc = LDAP_SUCCESS;
        ber_int_t msgid;
        LDAPMessage *res, *msg;
-       struct berval *rdns = NULL;
+       char **dns = NULL;
+       struct berval *creds = NULL;
        char *attrs[] = { LDAP_NO_ATTRS, NULL };
-       int nrdns = 0;
+       int ndns = 0;
 #ifdef _WIN32
        DWORD beg, end;
 #else
@@ -275,6 +280,7 @@ do_base( char *uri, struct berval *base, struct berval *pass, int maxloop,
 #endif
        int version = LDAP_VERSION3;
        struct berval pw = { 0, NULL };
+       char *nullstr = "";
 
        srand(pid);
 
@@ -294,32 +300,75 @@ do_base( char *uri, struct berval *base, struct berval *pass, int maxloop,
                exit( EXIT_FAILURE );
        }
 
-       rc = ldap_search_ext( ld, base->bv_val, LDAP_SCOPE_ONE,
+       fprintf( stderr, "PID=%ld - Bind(%d): base=\"%s\", filter=\"%s\" attr=\"%s\".\n",
+                       (long) pid, maxloop, base->bv_val, filter, pwattr );
+
+       if ( pwattr != NULL ) {
+               attrs[ 0 ] = pwattr;
+       }
+       rc = ldap_search_ext( ld, base->bv_val, LDAP_SCOPE_SUBTREE,
                        filter, attrs, 0, NULL, NULL, 0, 0, &msgid );
        if ( rc != LDAP_SUCCESS ) {
                tester_ldap_error( ld, "ldap_search_ext", NULL );
                exit( EXIT_FAILURE );
        }
 
-       while (( rc=ldap_result( ld, LDAP_RES_ANY, LDAP_MSG_ONE, NULL, &res )) >0){
+       while ( ( rc = ldap_result( ld, LDAP_RES_ANY, LDAP_MSG_ONE, NULL, &res ) ) > 0 )
+       {
                BerElement *ber;
                struct berval bv;
-               char *ptr;
                int done = 0;
 
-               for (msg = ldap_first_message( ld, res ); msg;
-                       msg = ldap_next_message( ld, msg )) {
-                       switch ( ldap_msgtype( msg )) {
+               for ( msg = ldap_first_message( ld, res ); msg;
+                       msg = ldap_next_message( ld, msg ) )
+               {
+                       switch ( ldap_msgtype( msg ) ) {
                        case LDAP_RES_SEARCH_ENTRY:
                                rc = ldap_get_dn_ber( ld, msg, &ber, &bv );
-                               ptr = strchr( bv.bv_val, ',');
-                               assert( ptr != NULL );
-                               bv.bv_len = ptr - bv.bv_val + 1;
-                               rdns = realloc( rdns, (nrdns+1)*sizeof(struct berval));
-                               ber_dupbv( &rdns[nrdns], &bv );
-                               nrdns++;
+                               dns = realloc( dns, (ndns + 1)*sizeof(char *) );
+                               dns[ndns] = ber_strdup( bv.bv_val );
+                               if ( pwattr != NULL ) {
+                                       struct berval   **values = ldap_get_values_len( ld, msg, pwattr );
+
+                                       creds = realloc( creds, (ndns + 1)*sizeof(struct berval) );
+                                       if ( values == NULL ) {
+novals:;
+                                               if ( pass != NULL ) {
+                                                       ber_dupbv( &creds[ndns], pass );
+
+                                               } else {
+                                                       creds[ndns].bv_len = 0;
+                                                       creds[ndns].bv_val = nullstr;
+                                               }
+
+                                       } else {
+                                               static struct berval    cleartext = BER_BVC( "{CLEARTEXT} " );
+                                               struct berval           value = *values[ 0 ];
+
+                                               if ( value.bv_val[ 0 ] == '{' ) {
+                                                       char *end = ber_bvchr( &value, '}' );
+
+                                                       if ( end ) {
+                                                               if ( ber_bvcmp( &value, &cleartext ) == 0 ) {
+                                                                       value.bv_val += cleartext.bv_len;
+                                                                       value.bv_len -= cleartext.bv_len;
+
+                                                               } else {
+                                                                       ldap_value_free_len( values );
+                                                                       goto novals;
+                                                               }
+                                                       }
+
+                                               }
+
+                                               ber_dupbv( &creds[ndns], &value );
+                                               ldap_value_free_len( values );
+                                       }
+                               }
+                               ndns++;
                                ber_free( ber, 0 );
                                break;
+
                        case LDAP_RES_SEARCH_RESULT:
                                done = 1;
                                break;
@@ -337,30 +386,26 @@ do_base( char *uri, struct berval *base, struct berval *pass, int maxloop,
        gettimeofday( &beg, NULL );
 #endif
 
-       if ( nrdns == 0 ) {
+       if ( ndns == 0 ) {
                tester_error( "No RDNs" );
                return 1;
        }
 
+       fprintf( stderr, "PID=%ld - got %d values.\n", (long) pid, ndns );
+
        /* Ok, got list of RDNs, now start binding to each */
        for ( i = 0; i < maxloop; i++ ) {
-               char dn[BUFSIZ], *ptr;
                int j, k;
+               struct berval *cred = pass;
 
-               for ( j = 0, k = 0; k < nrdns; k++) {
-                       j = rand() % nrdns;
-                       if ( base->bv_len + rdns[j].bv_len < sizeof( dn ) ) {
-                               break;
-                       }
+               for ( j = 0, k = 0; k < ndns; k++) {
+                       j = rand() % ndns;
                }
 
-               if ( k == nrdns ) {
-                       
+               if ( creds && !BER_BVISEMPTY( &creds[j] ) ) {
+                       cred = &creds[j];
                }
-               
-               ptr = lutil_strcopy(dn, rdns[j].bv_val);
-               strcpy(ptr, base->bv_val);
-               if ( do_bind( uri, dn, pass, 1, force, chaserefs, noinit, &ld )
+               if ( do_bind( uri, dns[j], cred, 1, force, chaserefs, noinit, &ld )
                        && !force )
                {
                        break;
@@ -395,11 +440,20 @@ do_base( char *uri, struct berval *base, struct berval *pass, int maxloop,
                (long) end.tv_sec, (long) end.tv_usec );
 #endif
 
-       if ( rdns ) {
-               for ( i = 0; i < nrdns; i++ ) {
-                       free( rdns[i].bv_val );
+       if ( dns ) {
+               for ( i = 0; i < ndns; i++ ) {
+                       free( dns[i] );
+               }
+               free( dns );
+       }
+
+       if ( creds ) {
+               for ( i = 0; i < ndns; i++ ) {
+                       if ( creds[i].bv_val != nullstr ) {
+                               free( creds[i].bv_val );
+                       }
                }
-               free( rdns );
+               free( creds );
        }
 
        return 0;
index 6000f965120281c8409c0ffe27e0928071f57e4e..13cbc00d50858681dd94574bb48ed6904e67270a 100644 (file)
@@ -162,6 +162,7 @@ main( int argc, char **argv )
        char            *bfile = NULL;
        char            *breqs[MAXREQS];
        char            *bcreds[MAXREQS];
+       char            *battrs[MAXREQS];
        int             bnum = 0;
        char            *bargs[MAXARGS];
        int             banum;
@@ -309,7 +310,7 @@ main( int argc, char **argv )
 
        /* look for bind requests */
        if ( bfile ) {
-               bnum = get_search_filters( bfile, bcreds, NULL, breqs );
+               bnum = get_search_filters( bfile, bcreds, battrs, breqs );
        }
 
        /* setup friendly option */
@@ -642,6 +643,13 @@ main( int argc, char **argv )
 
                        bargs[banum - 4] = breqs[jj];
                        bargs[banum - 2] = bcreds[jj];
+                       if ( battrs[jj] != NULL ) {
+                               bargs[banum - 1] = "-a";
+                               bargs[banum] = battrs[jj];
+
+                       } else {
+                               sargs[sanum - 1] = NULL;
+                       }
                        fork_child( bcmd, bargs );
                }
        }
index 7bef25a2a58305ba24b092cf063e056a5f98ebb6..c16ea0bb6800c483f0f0c31c155c45a07ab62496 100755 (executable)
@@ -69,6 +69,7 @@ sed -e "s/@BACKEND@/${BACKEND}/"                      \
        -e "s;@PORT4@;${PORT4};"                        \
        -e "s;@PORT5@;${PORT5};"                        \
        -e "s;@PORT6@;${PORT6};"                        \
+       -e "s/@CONFIGPW@/${CONFIGPW}/"          \
        -e "s/@SASL_MECH@/${SASL_MECH}/"                \
        -e "s/@CACHETTL@/${CACHETTL}/"                  \
        -e "s/@ENTRY_LIMIT@/${CACHE_ENTRY_LIMIT}/"      \
index a77439c2b7cc4d4361095aaca76656dbe8b0851f..f4da57e0e5876b0a37511fbccdfd92e29fb8b50f 100755 (executable)
@@ -13,6 +13,8 @@
 ## top-level directory of the distribution or, alternatively, at
 ## <http://www.OpenLDAP.org/license.html>.
 
+umask 077
+
 MONITORDB=${AC_monitor-no}
 BACKLDAP=${AC_ldap-ldapno}
 BACKMETA=${AC_meta-metano}
@@ -132,6 +134,9 @@ CONFFILTER=$SRCDIR/scripts/conf.sh
 SLAPADD="../servers/slapd/slapd -Ta -d 0 $LDAP_VERBOSE"
 SLAPCAT="../servers/slapd/slapd -Tc -d 0 $LDAP_VERBOSE"
 SLAPINDEX="../servers/slapd/slapd -Ti -d 0 $LDAP_VERBOSE"
+SLAPPASSWD="../servers/slapd/slapd -Tpasswd"
+
+CONFIGPWF=$TESTDIR/configpw
 
 unset DIFF_OPTIONS
 # NOTE: -u/-c is not that portable...
index 57e6c93660c2110e62e01bee5d54c73b62436c29..60c90d796585571b57c33ade96832029fb71b22a 100755 (executable)
@@ -107,7 +107,7 @@ $CMP $SEARCHFLT $LDIFFLT > $CMPOUT
 if test $? != 0 ; then
        echo "comparison failed - modrdn operations did not complete correctly"
        test $KILLSERVERS != no && kill -HUP $KILLPIDS
-       exit 1
+       exit -1
 fi
 
 
@@ -134,7 +134,7 @@ $CMP $SEARCHFLT $LDIFFLT > $CMPOUT
 if test $? != 0 ; then
        echo "comparison failed - modrdn operations did not complete correctly"
        test $KILLSERVERS != no && kill -HUP $KILLPIDS
-       exit 1
+       exit -1
 fi
 
 # Ensure that you cannot find the entry for which the rdn was deleted as
@@ -153,7 +153,7 @@ $CMP $SEARCHOUT - < /dev/null > $CMPOUT
 if test $? != 0 ; then
        echo "failure: ldapsearch found attribute that was to be removed!"
        test $KILLSERVERS != no && kill -HUP $KILLPIDS
-       exit 1
+       exit -1
 fi
 
 echo "Using ldapsearch to retrieve all the entries..."
@@ -178,7 +178,7 @@ $CMP $SEARCHFLT $LDIFFLT > $CMPOUT
 if test $? != 0 ; then
        echo "comparison failed - modrdn operations did not complete correctly"
        test $KILLSERVERS != no && kill -HUP $KILLPIDS
-       exit 1
+       exit -1
 fi
 
 # Test that you can use modrdn with an attribute value which was previously
@@ -218,7 +218,7 @@ $CMP $SEARCHFLT $LDIFFLT > $CMPOUT
 if test $? != 0 ; then
        echo "comparison failed - modrdn operations did not complete correctly"
        test $KILLSERVERS != no && kill -HUP $KILLPIDS
-       exit 1
+       exit -1
 fi
 
 echo "Testing modrdn with newSuperior as child of target "
@@ -227,11 +227,21 @@ $LDAPMODRDN -D "$MANAGERDN" -h $LOCALHOST -p $PORT1 -w $PASSWD > \
        'cn=James A Jones 1, ou=Alumni Association, ou=People, dc=example, dc=com' 'cn=James A Jones 1'
 
 RC=$?
-if test $RC -eq 0 ; then
+case $RC in
+0)
        echo "ldapmodrdn succeeded, should have failed!"
        test $KILLSERVERS != no && kill -HUP $KILLPIDS
-       exit 1
-fi
+       exit -1
+       ;;
+32)
+       echo "ldapmodrdn failed (noSuchObject)"
+       ;;
+*)
+       echo "ldapmodrdn failed ($RC)!"
+       test $KILLSERVERS != no && kill -HUP $KILLPIDS
+       exit $RC
+       ;;
+esac
 
 test $KILLSERVERS != no && kill -HUP $KILLPIDS
 
index 2a94cb65aa3a47df06734bc01bc74261f592227a..f28062bc9c251150b632dab5ff283261b48b3c21 100755 (executable)
@@ -123,6 +123,15 @@ if test $RC != 0 ; then
        exit $RC
 fi
 
+# ITS#4491, if debug messages are unavailable, we can't verify the tests.
+grep "query template" $LOG2 > /dev/null
+RC=$?
+if test $RC != 0 ; then
+       echo "Debug messages unavailable, test aborted..."
+       test $KILLSERVERS != no && kill -HUP $KILLPIDS && wait
+       exit 0
+fi
+
 echo "Query 2: filter:(|(cn=*Jon*)(sn=Jon*)) attrs:cn sn title uid"  
 echo "# Query 2: filter:(|(cn=*Jon*)(sn=Jon*)) attrs:cn sn title uid" >> $SLAVEOUT
 $LDAPSEARCH -x -S "" -b "$BASEDN" -h $LOCALHOST -p $PORT2 \
index 1676ff4539b3ec09fc58dbf41478bceaacc38bbb..613a9ee7e4568267f320ea1cfdfd736c5b28b690 100755 (executable)
@@ -20,6 +20,11 @@ fi
 echo "running defines.sh"
 . $SRCDIR/scripts/defines.sh
 
+if test $SYNCPROV = syncprovno; then 
+       echo "Syncrepl provider overlay not available, test skipped"
+       exit 0
+fi 
+
 mkdir -p $TESTDIR $DBDIR1A $DBDIR1B $DBDIR1C $DBDIR2A $DBDIR2B
 
 echo "Running slapadd to build glued slapd databases..."
index 6e72d0b9a891f2c7485fa48a866f05a92d706e26..1e633e0c0859ad2042f35312ffacb15f6b75fd26 100755 (executable)
@@ -23,6 +23,14 @@ fi
 
 mkdir -p $TESTDIR $DBDIR1
 
+$SLAPPASSWD -g -n > $CONFIGPWF
+RC=$?
+if test $RC != 0 ; then
+       echo "slappasswd failed ($RC)!"
+       exit $RC
+fi
+read CONFIGPW < $CONFIGPWF
+
 echo "Running slapadd to build slapd database..."
 . $CONFFILTER $BACKEND $MONITORDB < $VALSORTCONF > $CONF1
 $SLAPADD -f $CONF1 -l $LDIFVALSORT
@@ -85,11 +93,9 @@ if test $? != 0 ; then
        exit 1
 fi
 
-echo ">>>>> Test succeeded"
-
 echo "Reconfiguring slapd to test valsort descending"
 
-$LDAPMODIFY -x -D cn=config -h $LOCALHOST -p $PORT1 -w $PASSWD > \
+$LDAPMODIFY -x -D cn=config -h $LOCALHOST -p $PORT1 -y $CONFIGPWF > \
        $TESTOUT 2>&1 << EOMODS
 version: 1
 dn: olcOverlay={0}valsort,olcDatabase={1}$BACKEND,cn=config
@@ -133,8 +139,6 @@ if test $? != 0 ; then
        exit 1
 fi
 
-echo ">>>>> Test succeeded"
-
 echo "Adding a valsort record with weighted ou..."
 
 $LDAPADD -D "$VALSORTDN" -h $LOCALHOST -p $PORT1 -w $PASSWD \
@@ -217,8 +221,8 @@ fi
 
 test $KILLSERVERS != no && kill -HUP $KILLPIDS
 
-echo ">>>>> Test succeeded"
-
 test $KILLSERVERS != no && wait
 
+echo ">>>>> Test succeeded"
+
 exit 0