]> git.sur5r.net Git - openldap/commitdiff
Sync with HEAD for OL 2.4.5
authorQuanah Gibson-Mount <quanah@openldap.org>
Sat, 1 Sep 2007 01:13:44 +0000 (01:13 +0000)
committerQuanah Gibson-Mount <quanah@openldap.org>
Sat, 1 Sep 2007 01:13:44 +0000 (01:13 +0000)
464 files changed:
COPYRIGHT
README
build/config.guess
build/config.sub
build/ltmain.sh
build/openldap.m4
build/top.mk
clients/tools/common.c
clients/tools/ldapcompare.c
clients/tools/ldapdelete.c
clients/tools/ldapexop.c
clients/tools/ldapmodify.c
clients/tools/ldapmodrdn.c
clients/tools/ldappasswd.c
clients/tools/ldapwhoami.c
configure
configure.in
contrib/ldapc++/src/ac/time.h
contrib/ldaptcl/configure
contrib/ldaptcl/configure.in
contrib/ldaptcl/neoXldap.c
contrib/slapd-modules/addpartial/COPYRIGHT [new file with mode: 0644]
contrib/slapd-modules/addpartial/LICENSE [new file with mode: 0644]
contrib/slapd-modules/addpartial/Makefile [new file with mode: 0644]
contrib/slapd-modules/addpartial/README [new file with mode: 0644]
contrib/slapd-modules/addpartial/addpartial-overlay.c [new file with mode: 0644]
contrib/slapd-modules/allop/allop.c
contrib/slapd-modules/passwd/radius.c
contrib/slapd-modules/smbk5pwd/smbk5pwd.c
doc/devel/toolargs
doc/drafts/draft-haripriya-dynamicgroup-xx.txt [new file with mode: 0644]
doc/drafts/draft-wahl-ldap-session-xx.txt [new file with mode: 0644]
doc/drafts/draft-zeilenga-ldap-dontusecopy-xx.txt
doc/drafts/draft-zeilenga-ldap-managedit-xx.txt [deleted file]
doc/drafts/draft-zeilenga-ldap-noop-xx.txt
doc/drafts/draft-zeilenga-ldap-relax.txt [new file with mode: 0644]
doc/man/man1/ldapcompare.1
doc/man/man1/ldapmodrdn.1
doc/man/man1/ldapsearch.1
doc/man/man3/Deprecated
doc/man/man3/lber-decode.3
doc/man/man3/lber-encode.3
doc/man/man3/lber-memory.3
doc/man/man3/lber-sockbuf.3
doc/man/man3/lber-types.3
doc/man/man3/ldap.3
doc/man/man3/ldap_bind.3
doc/man/man3/ldap_controls.3
doc/man/man3/ldap_controls.3.links
doc/man/man3/ldap_first_message.3
doc/man/man3/ldap_first_reference.3
doc/man/man3/ldap_get_option.3
doc/man/man3/ldap_parse_sort_control.3
doc/man/man3/ldap_parse_vlv_control.3
doc/man/man3/ldap_rename.3
doc/man/man3/ldap_result.3
doc/man/man3/ldap_schema.3
doc/man/man3/ldap_search.3
doc/man/man3/ldap_sort.3
doc/man/man3/ldap_sync.3
doc/man/man3/ldap_url.3
doc/man/man5/ldap.conf.5
doc/man/man5/ldif.5
doc/man/man5/slapd-bdb.5
doc/man/man5/slapd-config.5
doc/man/man5/slapd-ldap.5
doc/man/man5/slapd-ldbm.5
doc/man/man5/slapd-meta.5
doc/man/man5/slapd-monitor.5
doc/man/man5/slapd-null.5
doc/man/man5/slapd-relay.5
doc/man/man5/slapd-sql.5
doc/man/man5/slapd.access.5
doc/man/man5/slapd.backends.5
doc/man/man5/slapd.conf.5
doc/man/man5/slapd.overlays.5
doc/man/man5/slapd.plugin.5
doc/man/man5/slapd.replog.5 [deleted file]
doc/man/man5/slapo-accesslog.5
doc/man/man5/slapo-auditlog.5
doc/man/man5/slapo-chain.5
doc/man/man5/slapo-constraint.5 [new file with mode: 0644]
doc/man/man5/slapo-dds.5
doc/man/man5/slapo-dyngroup.5 [new file with mode: 0644]
doc/man/man5/slapo-dynlist.5
doc/man/man5/slapo-memberof.5 [new file with mode: 0644]
doc/man/man5/slapo-pcache.5
doc/man/man5/slapo-ppolicy.5
doc/man/man5/slapo-refint.5
doc/man/man5/slapo-retcode.5
doc/man/man5/slapo-rwm.5
doc/man/man5/slapo-syncprov.5
doc/man/man5/slapo-translucent.5
doc/man/man5/slapo-unique.5
doc/man/man5/slapo-valsort.5
doc/man/man8/slapadd.8
doc/man/man8/slapauth.8
doc/man/man8/slapcat.8
doc/man/man8/slapd.8
doc/man/man8/slapdn.8
doc/man/man8/slaptest.8
doc/man/man8/slurpd.8 [deleted file]
doc/rfc/INDEX
doc/rfc/rfc5020.txt [new file with mode: 0644]
include/Makefile.in
include/ac/alloca.h
include/ac/crypt.h
include/ac/dirent.h
include/ac/errno.h
include/ac/socket.h
include/ac/termios.h
include/ac/time.h
include/ac/unistd.h
include/ac/wait.h
include/lber.h
include/ldap.h
include/ldap_config.hin
include/ldap_pvt.h
include/ldap_pvt_thread.h
include/lutil.h
include/portable.hin
include/slapi-plugin.h
libraries/liblber/bprint.c
libraries/liblber/decode.c
libraries/liblber/encode.c
libraries/liblber/io.c
libraries/liblber/lber-int.h
libraries/liblber/memory.c
libraries/liblber/sockbuf.c
libraries/libldap/Makefile.in
libraries/libldap/abandon.c
libraries/libldap/addentry.c
libraries/libldap/controls.c
libraries/libldap/dds.c
libraries/libldap/extended.c
libraries/libldap/getdn.c
libraries/libldap/init.c
libraries/libldap/ldap-int.h
libraries/libldap/ldap.conf
libraries/libldap/ldap_sync.c
libraries/libldap/os-ip.c
libraries/libldap/os-local.c
libraries/libldap/pagectrl.c
libraries/libldap/ppolicy.c
libraries/libldap/request.c
libraries/libldap/result.c
libraries/libldap/search.c
libraries/libldap/sortctrl.c
libraries/libldap/stctrl.c [new file with mode: 0644]
libraries/libldap/test.c
libraries/libldap/tls.c
libraries/libldap/url.c
libraries/libldap/urltest.c
libraries/libldap/vlvctrl.c
libraries/libldap_r/Makefile.in
libraries/libldap_r/thr_debug.c
libraries/libldap_r/thr_posix.c
libraries/libldap_r/tpool.c
libraries/liblutil/detach.c
libraries/liblutil/getpass.c
libraries/liblutil/getpeereid.c
libraries/liblutil/ldif.c
libraries/liblutil/lockf.c
libraries/liblutil/passfile.c
libraries/liblutil/sasl.c
libraries/liblutil/sockpair.c
libraries/liblutil/uuid.c
servers/Makefile.in
servers/slapd/Makefile.in
servers/slapd/abandon.c
servers/slapd/aci.c
servers/slapd/acl.c
servers/slapd/ad.c
servers/slapd/add.c
servers/slapd/alock.c
servers/slapd/at.c
servers/slapd/attr.c
servers/slapd/back-bdb/add.c
servers/slapd/back-bdb/back-bdb.h
servers/slapd/back-bdb/bind.c
servers/slapd/back-bdb/cache.c
servers/slapd/back-bdb/compare.c
servers/slapd/back-bdb/config.c
servers/slapd/back-bdb/dbcache.c
servers/slapd/back-bdb/delete.c
servers/slapd/back-bdb/dn2entry.c
servers/slapd/back-bdb/dn2id.c
servers/slapd/back-bdb/filterindex.c
servers/slapd/back-bdb/id2entry.c
servers/slapd/back-bdb/idl.c
servers/slapd/back-bdb/index.c
servers/slapd/back-bdb/init.c
servers/slapd/back-bdb/key.c
servers/slapd/back-bdb/modify.c
servers/slapd/back-bdb/modrdn.c
servers/slapd/back-bdb/monitor.c
servers/slapd/back-bdb/proto-bdb.h
servers/slapd/back-bdb/referral.c
servers/slapd/back-bdb/search.c
servers/slapd/back-bdb/tools.c
servers/slapd/back-dnssrv/bind.c
servers/slapd/back-dnssrv/init.c
servers/slapd/back-ldap/add.c
servers/slapd/back-ldap/back-ldap.h
servers/slapd/back-ldap/bind.c
servers/slapd/back-ldap/chain.c
servers/slapd/back-ldap/compare.c
servers/slapd/back-ldap/config.c
servers/slapd/back-ldap/delete.c
servers/slapd/back-ldap/distproc.c
servers/slapd/back-ldap/extended.c
servers/slapd/back-ldap/init.c
servers/slapd/back-ldap/modify.c
servers/slapd/back-ldap/modrdn.c
servers/slapd/back-ldap/proto-ldap.h
servers/slapd/back-ldap/search.c
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/compare.c
servers/slapd/back-meta/config.c
servers/slapd/back-meta/delete.c
servers/slapd/back-meta/init.c
servers/slapd/back-meta/map.c
servers/slapd/back-meta/modify.c
servers/slapd/back-meta/modrdn.c
servers/slapd/back-meta/search.c
servers/slapd/back-monitor/back-monitor.h
servers/slapd/back-monitor/bind.c
servers/slapd/back-monitor/compare.c
servers/slapd/back-monitor/database.c
servers/slapd/back-monitor/init.c
servers/slapd/back-monitor/log.c
servers/slapd/back-monitor/modify.c
servers/slapd/back-monitor/operation.c
servers/slapd/back-monitor/proto-back-monitor.h
servers/slapd/back-monitor/time.c
servers/slapd/back-null/null.c
servers/slapd/back-perl/SampleLDAP.pm
servers/slapd/back-perl/bind.c
servers/slapd/back-perl/close.c
servers/slapd/back-perl/init.c
servers/slapd/back-relay/Makefile.in
servers/slapd/back-relay/config.c [deleted file]
servers/slapd/back-relay/init.c
servers/slapd/back-relay/op.c
servers/slapd/back-relay/proto-back-relay.h
servers/slapd/back-shell/bind.c
servers/slapd/back-shell/init.c
servers/slapd/back-shell/modify.c
servers/slapd/back-shell/shell.h
servers/slapd/back-sql/add.c
servers/slapd/back-sql/back-sql.h
servers/slapd/back-sql/bind.c
servers/slapd/back-sql/compare.c
servers/slapd/back-sql/config.c
servers/slapd/back-sql/delete.c
servers/slapd/back-sql/entry-id.c
servers/slapd/back-sql/init.c
servers/slapd/back-sql/modify.c
servers/slapd/back-sql/modrdn.c
servers/slapd/back-sql/operational.c
servers/slapd/back-sql/proto-sql.h
servers/slapd/back-sql/rdbms_depend/mysql/testdb_create.sql
servers/slapd/back-sql/rdbms_depend/mysql/testdb_data.sql
servers/slapd/back-sql/rdbms_depend/mysql/testdb_metadata.sql
servers/slapd/back-sql/rdbms_depend/pgsql/testdb_create.sql
servers/slapd/back-sql/rdbms_depend/pgsql/testdb_data.sql
servers/slapd/back-sql/rdbms_depend/pgsql/testdb_metadata.sql
servers/slapd/back-sql/schema-map.c
servers/slapd/back-sql/search.c
servers/slapd/back-sql/sql-wrap.c
servers/slapd/backend.c
servers/slapd/backglue.c
servers/slapd/backover.c
servers/slapd/bconfig.c
servers/slapd/bind.c
servers/slapd/cancel.c
servers/slapd/compare.c
servers/slapd/config.c
servers/slapd/config.h
servers/slapd/connection.c
servers/slapd/controls.c
servers/slapd/cr.c
servers/slapd/daemon.c
servers/slapd/delete.c
servers/slapd/dn.c
servers/slapd/entry.c
servers/slapd/extended.c
servers/slapd/filter.c
servers/slapd/filterentry.c
servers/slapd/init.c
servers/slapd/ldapsync.c
servers/slapd/limits.c
servers/slapd/main.c
servers/slapd/modify.c
servers/slapd/modrdn.c
servers/slapd/module.c
servers/slapd/mr.c
servers/slapd/oc.c
servers/slapd/oidm.c
servers/slapd/operation.c
servers/slapd/overlays/Makefile.in
servers/slapd/overlays/accesslog.c
servers/slapd/overlays/auditlog.c
servers/slapd/overlays/collect.c
servers/slapd/overlays/constraint.c
servers/slapd/overlays/dds.c
servers/slapd/overlays/dyngroup.c
servers/slapd/overlays/dynlist.c
servers/slapd/overlays/memberof.c [new file with mode: 0644]
servers/slapd/overlays/pcache.c
servers/slapd/overlays/ppolicy.c
servers/slapd/overlays/refint.c
servers/slapd/overlays/retcode.c
servers/slapd/overlays/rwm.c
servers/slapd/overlays/rwm.h
servers/slapd/overlays/rwmconf.c
servers/slapd/overlays/rwmdn.c
servers/slapd/overlays/rwmmap.c
servers/slapd/overlays/seqmod.c
servers/slapd/overlays/syncprov.c
servers/slapd/overlays/translucent.c
servers/slapd/overlays/unique.c
servers/slapd/overlays/valsort.c
servers/slapd/passwd.c
servers/slapd/proto-slap.h
servers/slapd/repl.c [deleted file]
servers/slapd/result.c
servers/slapd/sasl.c
servers/slapd/saslauthz.c
servers/slapd/schema/core.schema
servers/slapd/schema/dyngroup.schema
servers/slapd/schema_check.c
servers/slapd/schema_init.c
servers/slapd/schema_prep.c
servers/slapd/schemaparse.c
servers/slapd/search.c
servers/slapd/sets.h
servers/slapd/sl_malloc.c
servers/slapd/slap.h
servers/slapd/slapacl.c
servers/slapd/slapadd.c
servers/slapd/slapauth.c
servers/slapd/slapcommon.c
servers/slapd/slapcommon.h
servers/slapd/slapi/slapi.h
servers/slapd/slapi/slapi_ops.c
servers/slapd/slapi/slapi_overlay.c
servers/slapd/slapi/slapi_pblock.c
servers/slapd/slapi/slapi_utils.c
servers/slapd/slaptest.c
servers/slapd/syncrepl.c
servers/slapd/syntax.c
servers/slapd/unbind.c
servers/slapd/value.c
servers/slurpd/DESIGN [deleted file]
servers/slurpd/Makefile.in [deleted file]
servers/slurpd/NOTES [deleted file]
servers/slurpd/admin.c [deleted file]
servers/slurpd/args.c [deleted file]
servers/slurpd/ch_malloc.c [deleted file]
servers/slurpd/config.c [deleted file]
servers/slurpd/fm.c [deleted file]
servers/slurpd/globals.c [deleted file]
servers/slurpd/globals.h [deleted file]
servers/slurpd/ldap_op.c [deleted file]
servers/slurpd/lock.c [deleted file]
servers/slurpd/main.c [deleted file]
servers/slurpd/nt_svc.c [deleted file]
servers/slurpd/proto-slurp.h [deleted file]
servers/slurpd/re.c [deleted file]
servers/slurpd/reject.c [deleted file]
servers/slurpd/replica.c [deleted file]
servers/slurpd/replog.c [deleted file]
servers/slurpd/ri.c [deleted file]
servers/slurpd/rq.c [deleted file]
servers/slurpd/sanity.c [deleted file]
servers/slurpd/slurp.h [deleted file]
servers/slurpd/st.c [deleted file]
tests/Makefile.in
tests/README
tests/data/dynlist.out
tests/data/slapd-aci.conf
tests/data/slapd-acl.conf
tests/data/slapd-cache-master.conf
tests/data/slapd-chain1.conf
tests/data/slapd-chain2.conf
tests/data/slapd-component.conf
tests/data/slapd-config-undo.conf
tests/data/slapd-dds.conf
tests/data/slapd-deltasync-master.conf
tests/data/slapd-deltasync-slave.conf
tests/data/slapd-dn.conf
tests/data/slapd-dynamic.ldif
tests/data/slapd-dynlist.conf
tests/data/slapd-emptydn.conf
tests/data/slapd-glue-syncrepl1.conf
tests/data/slapd-glue-syncrepl2.conf
tests/data/slapd-glue.conf
tests/data/slapd-idassert.conf
tests/data/slapd-ldapglue.conf
tests/data/slapd-ldapgluegroups.conf
tests/data/slapd-ldapgluepeople.conf
tests/data/slapd-limits.conf
tests/data/slapd-master.conf
tests/data/slapd-meta2.conf
tests/data/slapd-ppolicy.conf
tests/data/slapd-proxycache.conf
tests/data/slapd-pw.conf
tests/data/slapd-ref-slave.conf
tests/data/slapd-referrals.conf
tests/data/slapd-refint.conf
tests/data/slapd-relay.conf
tests/data/slapd-repl-master.conf [deleted file]
tests/data/slapd-repl-slave-remote.conf
tests/data/slapd-repl-slave.conf [deleted file]
tests/data/slapd-retcode.conf
tests/data/slapd-schema.conf
tests/data/slapd-syncrepl-master.conf
tests/data/slapd-syncrepl-multiproxy.conf
tests/data/slapd-syncrepl-slave-persist1.conf
tests/data/slapd-syncrepl-slave-persist2.conf
tests/data/slapd-syncrepl-slave-persist3.conf
tests/data/slapd-syncrepl-slave-refresh1.conf
tests/data/slapd-syncrepl-slave-refresh2.conf
tests/data/slapd-translucent-local.conf
tests/data/slapd-translucent-remote.conf
tests/data/slapd-unique.conf
tests/data/slapd-valsort.conf
tests/data/slapd-whoami.conf
tests/data/slapd.conf
tests/data/sql-read.out
tests/data/sql-write.out
tests/data/test.schema
tests/progs/slapd-addel.c
tests/progs/slapd-bind.c
tests/progs/slapd-common.c
tests/progs/slapd-modify.c
tests/progs/slapd-modrdn.c
tests/progs/slapd-read.c
tests/progs/slapd-search.c
tests/progs/slapd-tester.c
tests/run.in
tests/scripts/all
tests/scripts/defines.sh
tests/scripts/its-all
tests/scripts/sql-all
tests/scripts/sql-test000-read
tests/scripts/test007-replication [deleted file]
tests/scripts/test017-syncreplication-refresh
tests/scripts/test018-syncreplication-persist
tests/scripts/test021-certificate
tests/scripts/test023-refint
tests/scripts/test024-unique
tests/scripts/test034-translucent
tests/scripts/test042-valsort
tests/scripts/test043-delta-syncrepl
tests/scripts/test044-dynlist
tests/scripts/test045-syncreplication-proxied
tests/scripts/test049-sync-config
tests/scripts/test050-syncrepl-multimaster
tests/scripts/test051-config-undo

index db69cf2d0e7f9cb8ca584cdf1b04f8273ca7bf3e..fbfe5d4ed4a02ddbfdb93df9179dd77fed6bf276 100644 (file)
--- a/COPYRIGHT
+++ b/COPYRIGHT
@@ -36,9 +36,11 @@ Public License.
 
 ---
 
-Portions Copyright 1999-2005 Howard Y.H. Chu.
-Portions Copyright 1999-2005 Symas Corporation.
+Portions Copyright 1999-2007 Howard Y.H. Chu.
+Portions Copyright 1999-2007 Symas Corporation.
 Portions Copyright 1998-2003 Hallvard B. Furuseth.
+Portions Copyright 2007 Gavin Henry
+Portions Copyright 2007 Suretec Systems
 All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
diff --git a/README b/README
index 612ad6c6370c6b1f4a8c708ddfa555bfa82c54a0..9a03a72ab1542b9d2a96c363c844fa19cdcb2e26 100644 (file)
--- a/README
+++ b/README
@@ -21,10 +21,6 @@ REQUIRED SOFTWARE
     SLAPD:
         BDB and HDB backends require Sleepycat Berkeley DB 4.2 or later
 
-    SLURPD:
-        LTHREAD compatible thread package
-            [POSIX threads, Mach Cthreads, select others]
-
     CLIENTS/CONTRIB ware:
         Depends on package.  See per package README.
 
index a55c277e8405824330338e6582e6ed38e154ca77..f936d180ab7954b8846e9574ba7156a9cb66578a 100755 (executable)
@@ -29,7 +29,7 @@ timestamp='2003-07-02-OpenLDAP'
 # configuration script generated by Autoconf, and is distributable
 # under the same distributions terms as OpenLDAP itself.
 
-## Copyright 1998-2007 The OpenLDAP Foundation.
+## Portions Copyright 1998-2007 The OpenLDAP Foundation.
 ## All rights reserved.
 ##
 ## Redistribution and use in source and binary forms, with or without
index 0678b9d1554aa9e378e4a318add1c3fa34132473..77792ff06d15c2cee91f70b36a122cbf31d5e072 100755 (executable)
@@ -34,7 +34,7 @@ timestamp='2003-07-04-OpenLDAP'
 # configuration script generated by Autoconf, and is distributable
 # under the same distributions terms as OpenLDAP itself.
 
-## Copyright 1998-2007 The OpenLDAP Foundation.
+## Portions Copyright 1998-2007 The OpenLDAP Foundation.
 ## All rights reserved.
 ##
 ## Redistribution and use in source and binary forms, with or without
index be364aa8c8209ffb3ed3b96caa8aef21ec382f9a..21b86bbb4aba27e55a12d2ba4a87a1c2e672111c 100755 (executable)
@@ -26,9 +26,9 @@
 
 # This file is distributed with OpenLDAP Software, which contains a
 # configuration script generated by Autoconf, and is distributable
-# under the same distributions terms as OpenLDAP inself.
+# under the same distributions terms as OpenLDAP itself.
 
-## Copyright 1998-2007 The OpenLDAP Foundation.
+## Portions Copyright 1998-2007 The OpenLDAP Foundation.
 ## All rights reserved.
 ##
 ## Redistribution and use in source and binary forms, with or without
index 5fa82a24e771b23958033f9509c0dcfc7ce90d4a..9f627b534c441219e48ca5d001873a3af632579e 100644 (file)
@@ -91,6 +91,7 @@ EOF
                        done
                        rm -f conftest*
                ])
+               test "$ol_cv_mkdep" = no && OL_MKDEP=":"
        else
                cc_cv_mkdep=yes
                OL_MKDEP_FLAGS="${MKDEP_FLAGS}"
@@ -627,9 +628,9 @@ main()
        }
 
 #if (DB_VERSION_MAJOR > 3) || (DB_VERSION_MINOR >= 1)
-       rc = env->open( env, NULL, flags, 0 );
+       rc = (env->open)( env, NULL, flags, 0 );
 #else
-       rc = env->open( env, NULL, NULL, flags, 0 );
+       rc = (env->open)( env, NULL, NULL, flags, 0 );
 #endif
 
        if ( rc == 0 ) {
@@ -736,152 +737,6 @@ fi
 ])
 dnl
 dnl ====================================================================
-dnl Check if GDBM library exists
-dnl Check for gdbm_open in standard libraries or -lgdbm
-dnl
-dnl defines ol_cv_lib_gdbm to 'yes' or '-lgdbm' or 'no'
-dnl            'yes' implies gdbm_open is in $LIBS
-dnl
-dnl uses:
-dnl            AC_CHECK_FUNC(gdbm_open)
-dnl            AC_CHECK_LIB(gdbm,gdbm_open)
-dnl
-AC_DEFUN([OL_LIB_GDBM],
-[AC_CACHE_CHECK(for GDBM library, [ol_cv_lib_gdbm],
-[      ol_LIBS="$LIBS"
-       AC_CHECK_FUNC(gdbm_open,[ol_cv_lib_gdbm=yes], [
-               AC_CHECK_LIB(gdbm,gdbm_open,[ol_cv_lib_gdbm=-lgdbm],[ol_cv_lib_gdbm=no])
-       ])
-       LIBS="$ol_LIBS"
-])
-])dnl
-dnl
-dnl --------------------------------------------------------------------
-dnl Check if GDBM exists
-dnl
-dnl defines ol_cv_gdbm to 'yes' or 'no'
-dnl 
-dnl uses:
-dnl            OL_LIB_GDBM
-dnl            AC_CHECK_HEADERS(gdbm.h)
-dnl
-AC_DEFUN([OL_GDBM],
-[AC_REQUIRE([OL_LIB_GDBM])
- AC_CHECK_HEADERS(gdbm.h)
- AC_CACHE_CHECK(for db, [ol_cv_gdbm], [
-       if test $ol_cv_lib_gdbm = no || test $ac_cv_header_gdbm_h = no ; then
-               ol_cv_gdbm=no
-       else
-               ol_cv_gdbm=yes
-       fi
-])
- if test $ol_cv_gdbm = yes ; then
-       AC_DEFINE(HAVE_GDBM,1, [define if GNU DBM is available])
- fi
-])dnl
-dnl
-dnl ====================================================================
-dnl Check if MDBM library exists
-dnl Check for mdbm_open in standard libraries or -lmdbm
-dnl
-dnl defines ol_cv_lib_mdbm to 'yes' or '-lmdbm' or 'no'
-dnl            'yes' implies mdbm_open is in $LIBS
-dnl
-dnl uses:
-dnl            AC_CHECK_FUNC(mdbm_set_chain)
-dnl            AC_CHECK_LIB(mdbm,mdbm_set_chain)
-dnl
-AC_DEFUN([OL_LIB_MDBM],
-[AC_CACHE_CHECK(for MDBM library, [ol_cv_lib_mdbm],
-[      ol_LIBS="$LIBS"
-       AC_CHECK_FUNC(mdbm_set_chain,[ol_cv_lib_mdbm=yes], [
-               AC_CHECK_LIB(mdbm,mdbm_set_chain,[ol_cv_lib_mdbm=-lmdbm],[ol_cv_lib_mdbm=no])
-       ])
-       LIBS="$ol_LIBS"
-])
-])dnl
-dnl
-dnl --------------------------------------------------------------------
-dnl Check if MDBM exists
-dnl
-dnl defines ol_cv_mdbm to 'yes' or 'no'
-dnl 
-dnl uses:
-dnl            OL_LIB_MDBM
-dnl            AC_CHECK_HEADERS(mdbm.h)
-dnl
-AC_DEFUN([OL_MDBM],
-[AC_REQUIRE([OL_LIB_MDBM])
- AC_CHECK_HEADERS(mdbm.h)
- AC_CACHE_CHECK(for db, [ol_cv_mdbm], [
-       if test $ol_cv_lib_mdbm = no || test $ac_cv_header_mdbm_h = no ; then
-               ol_cv_mdbm=no
-       else
-               ol_cv_mdbm=yes
-       fi
-])
- if test $ol_cv_mdbm = yes ; then
-       AC_DEFINE(HAVE_MDBM,1, [define if MDBM is available])
- fi
-])dnl
-dnl
-dnl ====================================================================
-dnl Check if NDBM library exists
-dnl Check for dbm_open in standard libraries or -lndbm or -ldbm
-dnl
-dnl defines ol_cv_lib_ndbm to 'yes' or '-lndbm' or -ldbm or 'no'
-dnl            'yes' implies ndbm_open is in $LIBS
-dnl
-dnl uses:
-dnl            AC_CHECK_FUNC(dbm_open)
-dnl            AC_CHECK_LIB(ndbm,dbm_open)
-dnl            AC_CHECK_LIB(dbm,dbm_open)
-dnl
-dnl restrictions:
-dnl            should also check SVR4 case: dbm_open() in -lucb but that
-dnl            would requiring dealing with -L/usr/ucblib
-dnl
-AC_DEFUN([OL_LIB_NDBM],
-[AC_CACHE_CHECK(for NDBM library, [ol_cv_lib_ndbm],
-[      ol_LIBS="$LIBS"
-       AC_CHECK_FUNC(dbm_open,[ol_cv_lib_ndbm=yes], [
-               AC_CHECK_LIB(ndbm,dbm_open,[ol_cv_lib_ndbm=-lndbm], [
-                       AC_CHECK_LIB(dbm,dbm_open,[ol_cv_lib_ndbm=-ldbm],
-                               [ol_cv_lib_ndbm=no])dnl
-               ])
-       ])
-       LIBS="$ol_LIBS"
-])
-])dnl
-dnl
-dnl --------------------------------------------------------------------
-dnl Check if NDBM exists
-dnl
-dnl defines ol_cv_ndbm to 'yes' or 'no'
-dnl 
-dnl uses:
-dnl            OL_LIB_NDBM
-dnl            AC_CHECK_HEADERS(ndbm.h)
-dnl
-dnl restrictions:
-dnl            Doesn't handle SVR4 case (see above)
-dnl
-AC_DEFUN([OL_NDBM],
-[AC_REQUIRE([OL_LIB_NDBM])
- AC_CHECK_HEADERS(ndbm.h)
- AC_CACHE_CHECK(for db, [ol_cv_ndbm], [
-       if test $ol_cv_lib_ndbm = no || test $ac_cv_header_ndbm_h = no ; then
-               ol_cv_ndbm=no
-       else
-               ol_cv_ndbm=yes
-       fi
-])
- if test $ol_cv_ndbm = yes ; then
-       AC_DEFINE(HAVE_NDBM,1, [define if NDBM is available])
- fi
-])dnl
-dnl
-dnl ====================================================================
 dnl Check POSIX Thread version 
 dnl
 dnl defines ol_cv_pthread_version to 4, 5, 6, 7, 8, 10, depending on the
index d63fd33776a20a1d96714ad3dcc978a59c51950e..3b81f63d9d93775cc9b211a45b0c41207ab9d039 100644 (file)
@@ -170,10 +170,8 @@ LDAP_LIBLUTIL_A = $(LDAP_LIBDIR)/liblutil/liblutil.a
 
 LDAP_L = $(LDAP_LIBLUTIL_A) \
        $(LDAP_LIBLDAP_LA) $(LDAP_LIBLBER_LA)
-SLURPD_L = $(LDAP_LIBLUTIL_A) \
-       $(LDAP_LIBLDAP_R_LA) $(LDAP_LIBLBER_LA)
 SLAPD_L = $(LDAP_LIBLUNICODE_A) $(LDAP_LIBREWRITE_A) \
-       $(SLURPD_L)
+       $(LDAP_LIBLUTIL_A) $(LDAP_LIBLDAP_R_LA) $(LDAP_LIBLBER_LA)
 
 WRAP_LIBS = @WRAP_LIBS@
 # AutoConfig generated 
@@ -202,7 +200,6 @@ SLAPD_SQL_INCLUDES = @SLAPD_SQL_INCLUDES@
 SLAPD_SQL_LIBS = @SLAPD_SQL_LIBS@
 
 SLAPD_LIBS = @SLAPD_LIBS@ @SLAPD_PERL_LDFLAGS@ @SLAPD_SQL_LDFLAGS@ @SLAPD_SQL_LIBS@ @SLAPD_SLP_LIBS@ @SLAPD_GMP_LIBS@ $(ICU_LIBS)
-SLURPD_LIBS = @SLURPD_LIBS@
 
 # Our Defaults
 CC = $(AC_CC)
index fbacf5ad2991a30285f4cfc3dc931006b6e3db3c..bffbf121d029ecd80b11e6ca4c0d12d69eb9537c 100644 (file)
@@ -33,6 +33,7 @@
 #include <ac/unistd.h>
 #include <ac/errno.h>
 #include <ac/time.h>
+#include <ac/socket.h>
 
 #ifdef HAVE_CYRUS_SASL
 #ifdef HAVE_SASL_SASL_H
@@ -113,6 +114,13 @@ int                chaining = 0;
 static int     chainingResolve = -1;
 static int     chainingContinuation = -1;
 #endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
+#ifdef LDAP_CONTROL_X_SESSION_TRACKING
+static int     sessionTracking = 0;
+struct berval  stValue;
+#endif /* LDAP_CONTROL_X_SESSION_TRACKING */
+
+LDAPControl    *unknown_ctrls = NULL;
+int            unknown_ctrls_num = 0;
 
 /* options */
 struct timeval nettimeout = { -1 , 0 };
@@ -144,6 +152,53 @@ static struct tool_ctrls_t {
 static int     gotintr;
 static int     abcan;
 
+
+#ifdef LDAP_CONTROL_X_SESSION_TRACKING
+static int
+st_value( LDAP *ld, struct berval *value )
+{
+       char            *ip = NULL, *name = NULL;
+       struct berval   id = { 0 };
+       char            namebuf[ MAXHOSTNAMELEN ];
+
+       if ( gethostname( namebuf, sizeof( namebuf ) ) == 0 ) {
+               struct hostent  *h;
+               struct in_addr  addr;
+
+               name = namebuf;
+
+               h = gethostbyname( name );
+               if ( h != NULL ) {
+                       AC_MEMCPY( &addr, h->h_addr, sizeof( addr ) );
+                       ip = inet_ntoa( addr );
+               }
+       }
+
+#ifdef HAVE_CYRUS_SASL
+       if ( sasl_authz_id != NULL ) {
+               ber_str2bv( sasl_authz_id, 0, 0, &id );
+
+       } else if ( sasl_authc_id != NULL ) {
+               ber_str2bv( sasl_authc_id, 0, 0, &id );
+
+       } else 
+#endif /* HAVE_CYRUS_SASL */
+       if ( binddn != NULL ) {
+               ber_str2bv( binddn, 0, 0, &id );
+       }
+
+       if ( ldap_create_session_tracking_value( ld,
+               ip, name, LDAP_CONTROL_X_SESSION_TRACKING_USERNAME,
+               &id, &stValue ) )
+       {
+               fprintf( stderr, _("Session tracking control encoding error!\n") );
+               return -1;
+       }
+
+       return 0;
+}
+#endif /* LDAP_CONTROL_X_SESSION_TRACKING */
+
 RETSIGTYPE
 do_sig( int sig )
 {
@@ -175,7 +230,6 @@ tool_common_usage( void )
 {
        static const char *const descriptions[] = {
 N_("  -c         continuous operation mode (do not stop on errors)\n"),
-N_("  -C         chase referrals (anonymously)\n"),
 N_("  -d level   set LDAP debugging level to `level'\n"),
 N_("  -D binddn  bind DN\n"),
 N_("  -e [!]<ext>[=<extparam>] general extensions (! indicates criticality)\n")
@@ -199,15 +253,16 @@ N_("             ppolicy\n")
 #endif
 N_("             [!]postread[=<attrs>]  (a comma-separated attribute list)\n")
 N_("             [!]preread[=<attrs>]   (a comma-separated attribute list)\n")
-#ifdef LDAP_DEVEL
 N_("             [!]relax\n")
-#endif
+#ifdef LDAP_CONTROL_X_SESSION_TRACKING
+N_("             [!]sessiontracking\n")
+#endif /* LDAP_CONTROL_X_SESSION_TRACKING */
 N_("             abandon, cancel, ignore (SIGINT sends abandon/cancel,\n"
    "             or ignores response; if critical, doesn't wait for SIGINT.\n"
    "             not really controls)\n")
 N_("  -f file    read operations from `file'\n"),
 N_("  -h host    LDAP server\n"),
-N_("  -H URI     LDAP Uniform Resource Indentifier(s)\n"),
+N_("  -H URI     LDAP Uniform Resource Identifier(s)\n"),
 N_("  -I         use SASL Interactive mode\n"),
 N_("  -M         enable Manage DSA IT control (-MM to make critical)\n"),
 N_("  -n         show what would be done but don't actually do it\n"),
@@ -215,7 +270,7 @@ N_("  -O props   SASL security properties\n"),
 N_("  -o <opt>[=<optparam] general options\n"),
 N_("             nettimeout=<timeout> (in seconds, or \"none\" or \"max\")\n"),
 N_("  -p port    port on LDAP server\n"),
-N_("  -P version procotol version (default: 3)\n"),
+N_("  -P version protocol version (default: 3)\n"),
 N_("  -Q         use SASL Quiet mode\n"),
 N_("  -R realm   SASL realm\n"),
 N_("  -U authcid SASL authentication identity\n"),
@@ -299,7 +354,7 @@ tool_args( int argc, char **argv )
                        }
                        binddn = ber_strdup( optarg );
                        break;
-               case 'e': /* general extensions (controls and such) */
+               case 'e':       /* general extensions (controls and such) */
                        /* should be extended to support comma separated list of
                         *      [!]key[=value] parameters, e.g.  -e !foo,bar=567
                         */
@@ -520,6 +575,55 @@ tool_args( int argc, char **argv )
                                        gotintr = abcan;
                                }
 
+#ifdef LDAP_CONTROL_X_SESSION_TRACKING
+                       } else if ( strcasecmp( control, "sessiontracking" ) == 0 ) {
+                               if ( sessionTracking ) {
+                                       fprintf( stderr, "%s: session tracking can be only specified once\n", prog );
+                                       exit( EXIT_FAILURE );
+                               }
+                               sessionTracking = 1;
+#endif /* LDAP_CONTROL_X_SESSION_TRACKING */
+
+                       } else if ( tool_is_oid( control ) ) {
+                               LDAPControl     *tmpctrls, ctrl;
+
+                               tmpctrls = (LDAPControl *)realloc( unknown_ctrls,
+                                       (unknown_ctrls_num + 1)*sizeof( LDAPControl ) );
+                               if ( tmpctrls == NULL ) {
+                                       fprintf( stderr, "%s: no memory?\n", prog );
+                                       exit( EXIT_FAILURE );
+                               }
+                               unknown_ctrls = tmpctrls;
+                               ctrl.ldctl_oid = control;
+                               ctrl.ldctl_value.bv_val = NULL;
+                               ctrl.ldctl_value.bv_len = 0;
+                               ctrl.ldctl_iscritical = crit;
+
+                               if ( cvalue != NULL ) {
+                                       struct berval   bv;
+                                       size_t          len = strlen( cvalue );
+                                       int             retcode;
+
+                                       bv.bv_len = LUTIL_BASE64_DECODE_LEN( len );
+                                       bv.bv_val = ber_memalloc( bv.bv_len + 1 );
+
+                                       retcode = lutil_b64_pton( cvalue,
+                                               (unsigned char *)bv.bv_val,
+                                               bv.bv_len );
+
+                                       if ( retcode == -1 || retcode > bv.bv_len ) {
+                                               fprintf( stderr, "Unable to parse value of general control %s\n",
+                                                       control );
+                                               usage();
+                                       }
+
+                                       bv.bv_len = retcode;
+                                       ctrl.ldctl_value = bv;
+                               }
+
+                               unknown_ctrls[ unknown_ctrls_num ] = ctrl;
+                               unknown_ctrls_num++;
+
                        } else {
                                fprintf( stderr, "Invalid general control name: %s\n",
                                        control );
@@ -893,6 +997,9 @@ tool_args( int argc, char **argv )
 #ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
                        chaining ||
 #endif
+#ifdef LDAP_CONTROL_X_SESSION_TRACKING
+                       sessionTracking ||
+#endif /* LDAP_CONTROL_X_SESSION_TRACKING */
                        noop || ppolicy || preread || postread )
                {
                        fprintf( stderr, "%s: -e/-M incompatible with LDAPv2\n", prog );
@@ -957,6 +1064,137 @@ tool_conn_setup( int dont, void (*private_setup)( LDAP * ) )
                        url.lud_scope = LDAP_SCOPE_DEFAULT;
 
                        ldapuri = ldap_url_desc2str( &url );
+
+               } else if ( ldapuri != NULL ) {
+                       LDAPURLDesc     *ludlist, **ludp;
+                       char            **urls = NULL;
+                       int             nurls = 0;
+
+                       rc = ldap_url_parselist( &ludlist, ldapuri );
+                       if ( rc != LDAP_URL_SUCCESS ) {
+                               fprintf( stderr,
+                                       "Could not parse LDAP URI(s)=%s (%d)\n",
+                                       ldapuri, rc );
+                               exit( EXIT_FAILURE );
+                       }
+
+                       for ( ludp = &ludlist; *ludp != NULL; ) {
+                               LDAPURLDesc     *lud = *ludp;
+                               char            **tmp;
+
+                               if ( lud->lud_dn != NULL && lud->lud_dn[ 0 ] != '\0' &&
+                                       ( lud->lud_host == NULL || lud->lud_host[0] == '\0' ) )
+                               {
+                                       /* if no host but a DN is provided,
+                                        * use DNS SRV to gather the host list
+                                        * and turn it into a list of URIs
+                                        * using the scheme provided */
+                                       char    *domain = NULL,
+                                               *hostlist = NULL,
+                                               **hosts = NULL;
+                                       int     i,
+                                               len_proto = strlen( lud->lud_scheme );
+
+                                       if ( ldap_dn2domain( lud->lud_dn, &domain )
+                                               || domain == NULL )
+                                       {
+                                               fprintf( stderr,
+                                                       "DNS SRV: Could not turn "
+                                                       "DN=\"%s\" into a domain\n",
+                                                       lud->lud_dn );
+                                               goto dnssrv_free;
+                                       }
+                                       
+                                       rc = ldap_domain2hostlist( domain, &hostlist );
+                                       if ( rc ) {
+                                               fprintf( stderr,
+                                                       "DNS SRV: Could not turn "
+                                                       "domain=%s into a hostlist\n",
+                                                       domain );
+                                               goto dnssrv_free;
+                                       }
+
+                                       hosts = ldap_str2charray( hostlist, " " );
+                                       if ( hosts == NULL ) {
+                                               fprintf( stderr,
+                                                       "DNS SRV: Could not parse "
+                                                       "hostlist=\"%s\"\n",
+                                                       hostlist );
+                                               goto dnssrv_free;
+                                       }
+
+                                       for ( i = 0; hosts[ i ] != NULL; i++ )
+                                               /* count'em */ ;
+
+                                       tmp = (char **)realloc( urls, sizeof( char * ) * ( nurls + i + 1 ) );
+                                       if ( tmp == NULL ) {
+                                               fprintf( stderr,
+                                                       "DNS SRV: out of memory?\n" );
+                                               goto dnssrv_free;
+                                       }
+                                       urls = tmp;
+                                       urls[ nurls ] = NULL;
+
+                                       for ( i = 0; hosts[ i ] != NULL; i++ ) {
+                                               size_t  len = len_proto
+                                                       + STRLENOF( "://" )
+                                                       + strlen( hosts[ i ] )
+                                                       + 1;
+
+                                               urls[ nurls + i + 1 ] = NULL;
+                                               urls[ nurls + i ] = (char *)malloc( sizeof( char ) * len );
+                                               if ( urls[ nurls + i ] == NULL ) {
+                                                       fprintf( stderr,
+                                                               "DNS SRV: out of memory?\n" );
+                                                       goto dnssrv_free;
+                                               }
+
+                                               snprintf( urls[ nurls + i ], len, "%s://%s",
+                                                       lud->lud_scheme, hosts[ i ] );
+                                       }
+                                       nurls += i;
+
+dnssrv_free:;
+                                       ber_memvfree( (void **)hosts );
+                                       ber_memfree( hostlist );
+                                       ber_memfree( domain );
+
+                               } else {
+                                       tmp = (char **)realloc( urls, sizeof( char * ) * ( nurls + 2 ) );
+                                       if ( tmp == NULL ) {
+                                               fprintf( stderr,
+                                                       "DNS SRV: out of memory?\n" );
+                                               break;
+                                       }
+                                       urls = tmp;
+                                       urls[ nurls + 1 ] = NULL;
+
+                                       urls[ nurls ] = ldap_url_desc2str( lud );
+                                       if ( urls[ nurls ] == NULL ) {
+                                               fprintf( stderr,
+                                                       "DNS SRV: out of memory?\n" );
+                                               break;
+                                       }
+                                       nurls++;
+                               }
+
+                               *ludp = lud->lud_next;
+
+                               lud->lud_next = NULL;
+                               ldap_free_urldesc( lud );
+                       }
+
+                       if ( ludlist != NULL ) {
+                               ldap_free_urllist( ludlist );
+                               exit( EXIT_FAILURE );
+
+                       } else if ( urls == NULL ) {
+                               exit( EXIT_FAILURE );
+                       }
+
+                       ldap_memfree( ldapuri );
+                       ldapuri = ldap_charray2str( urls, " " );
+                       ber_memvfree( (void **)urls );
                }
 
                if ( verbose ) {
@@ -1019,21 +1257,41 @@ void
 tool_bind( LDAP *ld )
 {
        LDAPControl     **sctrlsp = NULL;
-       LDAPControl     *sctrls[2];
+       LDAPControl     *sctrls[3];
+       LDAPControl     sctrl[3];
        int             nsctrls = 0;
 
 #ifdef LDAP_CONTROL_PASSWORDPOLICYREQUEST
-       LDAPControl c;
        if ( ppolicy ) {
+               LDAPControl c;
                c.ldctl_oid = LDAP_CONTROL_PASSWORDPOLICYREQUEST;
                c.ldctl_value.bv_val = NULL;
                c.ldctl_value.bv_len = 0;
                c.ldctl_iscritical = 0;
-               sctrls[nsctrls] = &c;
+               sctrl[nsctrls] = c;
+               sctrls[nsctrls] = &sctrl[nsctrls];
                sctrls[++nsctrls] = NULL;
        }
 #endif
 
+#ifdef LDAP_CONTROL_X_SESSION_TRACKING
+       if ( sessionTracking ) {
+               LDAPControl c;
+
+               if (stValue.bv_val == NULL && st_value( ld, &stValue ) ) {
+                       exit( EXIT_FAILURE );
+               }
+
+               c.ldctl_oid = LDAP_CONTROL_X_SESSION_TRACKING;
+               c.ldctl_iscritical = 0;
+               ber_dupbv( &c.ldctl_value, &stValue );
+
+               sctrl[nsctrls] = c;
+               sctrls[nsctrls] = &sctrl[nsctrls];
+               sctrls[++nsctrls] = NULL;
+       }
+#endif /* LDAP_CONTROL_X_SESSION_TRACKING */
+
        if ( nsctrls ) {
                sctrlsp = sctrls;
        }
@@ -1108,7 +1366,7 @@ tool_bind( LDAP *ld )
                rc = ldap_parse_result( ld, result, &err, &matched, &info, &refs,
                        &ctrls, 1 );
                if ( rc != LDAP_SUCCESS ) {
-                       tool_perror( "ldap_bind parse result", rc, NULL, NULL, NULL, NULL );
+                       tool_perror( "ldap_bind parse result", rc, NULL, matched, info, refs );
                        exit( LDAP_LOCAL_ERROR );
                }
 
@@ -1118,8 +1376,8 @@ tool_bind( LDAP *ld )
                        int expire, grace, len = 0;
                        LDAPPasswordPolicyError pErr = -1;
                        
-                       ctrl = ldap_find_control( LDAP_CONTROL_PASSWORDPOLICYRESPONSE,
-                               ctrls );
+                       ctrl = ldap_control_find( LDAP_CONTROL_PASSWORDPOLICYRESPONSE,
+                               ctrls, NULL );
 
                        if ( ctrl && ldap_parse_passwordpolicy_control( ld, ctrl,
                                &expire, &grace, &pErr ) == LDAP_SUCCESS )
@@ -1182,7 +1440,7 @@ void
 tool_server_controls( LDAP *ld, LDAPControl *extra_c, int count )
 {
        int i = 0, j, crit = 0, err;
-       LDAPControl c[10], **ctrls;
+       LDAPControl c[16], **ctrls;
 
        if ( ! ( assertctl
                || authzid
@@ -1192,17 +1450,24 @@ tool_server_controls( LDAP *ld, LDAPControl *extra_c, int count )
                || manageDIT
                || manageDSAit
                || noop
+#ifdef LDAP_CONTROL_PASSWORDPOLICYREQUEST
+               || ppolicy
+#endif
                || preread
                || postread
 #ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
                || chaining
 #endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
-               || count ) )
+#ifdef LDAP_CONTROL_X_SESSION_TRACKING
+               || sessionTracking
+#endif /* LDAP_CONTROL_X_SESSION_TRACKING */
+               || count
+               || unknown_ctrls_num ) )
        {
                return;
        }
 
-       ctrls = (LDAPControl**) malloc(sizeof(c) + (count+1)*sizeof(LDAPControl*));
+       ctrls = (LDAPControl**) malloc(sizeof(c) + (count + unknown_ctrls_num + 1)*sizeof(LDAPControl*));
        if ( ctrls == NULL ) {
                fprintf( stderr, "No memory\n" );
                exit( EXIT_FAILURE );
@@ -1294,6 +1559,16 @@ tool_server_controls( LDAP *ld, LDAPControl *extra_c, int count )
                i++;
        }
 
+#ifdef LDAP_CONTROL_PASSWORDPOLICYREQUEST
+       if ( ppolicy ) {
+               c[i].ldctl_oid = LDAP_CONTROL_PASSWORDPOLICYREQUEST;
+               BER_BVZERO( &c[i].ldctl_value );
+               c[i].ldctl_iscritical = 0;
+               ctrls[i] = &c[i];
+               i++;
+       }
+#endif
+
        if ( preread ) {
                char berbuf[LBER_ELEMENT_SIZEOF];
                BerElement *ber = (BerElement *)berbuf;
@@ -1400,9 +1675,27 @@ tool_server_controls( LDAP *ld, LDAPControl *extra_c, int count )
        }
 #endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
 
+#ifdef LDAP_CONTROL_X_SESSION_TRACKING
+       if ( sessionTracking ) {
+               if ( stValue.bv_val == NULL && st_value( ld, &stValue ) ) {
+                       exit( EXIT_FAILURE );
+               }
+
+               c[i].ldctl_oid = LDAP_CONTROL_X_SESSION_TRACKING;
+               c[i].ldctl_iscritical = 0;
+               ber_dupbv( &c[i].ldctl_value, &stValue );
+
+               ctrls[i] = &c[i];
+               i++;
+       }
+#endif /* LDAP_CONTROL_X_SESSION_TRACKING */
+
        while ( count-- ) {
                ctrls[i++] = extra_c++;
        }
+       for ( count = 0; count < unknown_ctrls_num; count++ ) {
+               ctrls[i++] = &unknown_ctrls[count];
+       }
        ctrls[i] = NULL;
 
        err = ldap_set_option( ld, LDAP_OPT_SERVER_CONTROLS, ctrls );
@@ -1594,7 +1887,8 @@ print_ppolicy( LDAP *ld, LDAPControl *ctrl )
 
                if ( pperr != PP_noError ) {
                        ptr += snprintf( ptr, sizeof( buf ) - ( ptr - buf ),
-                               "%serror=%s", ptr == buf ? "" : " ",
+                               "%serror=%d (%s)", ptr == buf ? "" : " ",
+                               pperr,
                                ldap_passwordpolicy_err2txt( pperr ) );
                }
 
@@ -1620,6 +1914,13 @@ void tool_print_ctrls(
                char *str;
                int j;
 
+               /* FIXME: there might be cases where a control has NULL OID;
+                * this makes little sense, especially when returned by the
+                * server, but libldap happily allows it */
+               if ( ctrls[i]->ldctl_oid == NULL ) {
+                       continue;
+               }
+
                len = ldif ? 2 : 0;
                len += strlen( ctrls[i]->ldctl_oid );
 
@@ -1628,7 +1929,7 @@ void tool_print_ctrls(
                        ? sizeof("true") : sizeof("false");
 
                /* convert to base64 */
-               if ( ctrls[i]->ldctl_value.bv_len ) {
+               if ( !BER_BVISNULL( &ctrls[i]->ldctl_value ) ) {
                        b64.bv_len = LUTIL_BASE64_ENCODE_LEN(
                                ctrls[i]->ldctl_value.bv_len ) + 1;
                        b64.bv_val = ber_memalloc( b64.bv_len + 1 );
index 47753525e17166b6a19f4892ec6405a541ffcf3d..18f9179476238c6fc881fc03ffc45679dd90afef 100644 (file)
@@ -288,6 +288,7 @@ static int docompare(
        char            *matcheddn;
        char            *text;
        char            **refs;
+       LDAPControl **ctrls = NULL;
 
        if ( dont ) {
                return LDAP_SUCCESS;
@@ -320,7 +321,7 @@ static int docompare(
                }
        }
 
-       rc = ldap_parse_result( ld, res, &code, &matcheddn, &text, &refs, NULL, 1 );
+       rc = ldap_parse_result( ld, res, &code, &matcheddn, &text, &refs, &ctrls, 1 );
 
        if( rc != LDAP_SUCCESS ) {
                fprintf( stderr, "%s: ldap_parse_result: %s (%d)\n",
@@ -350,10 +351,6 @@ static int docompare(
                }
        }
 
-       ber_memfree( text );
-       ber_memfree( matcheddn );
-       ber_memvfree( (void **) refs );
-
        /* if we were told to be quiet, use the return value. */
        if ( !quiet ) {
                if ( code == LDAP_COMPARE_TRUE ) {
@@ -365,6 +362,15 @@ static int docompare(
                }
        }
 
+       if ( ctrls ) {
+               tool_print_ctrls( ld, ctrls );
+               ldap_controls_free( ctrls );
+       }
+
+       ber_memfree( text );
+       ber_memfree( matcheddn );
+       ber_memvfree( (void **) refs );
+
        return( code );
 }
 
index 8133a2d3a05d31b809b7326e3737d463f647e5b0..635db793fad8b91e83315fac08520ba59fe03f83 100644 (file)
@@ -210,6 +210,7 @@ static int dodelete(
        int id;
        int     rc, code;
        char *matcheddn = NULL, *text = NULL, **refs = NULL;
+       LDAPControl **ctrls = NULL;
        LDAPMessage *res;
 
        if ( verbose ) {
@@ -254,7 +255,7 @@ static int dodelete(
                }
        }
 
-       rc = ldap_parse_result( ld, res, &code, &matcheddn, &text, &refs, NULL, 1 );
+       rc = ldap_parse_result( ld, res, &code, &matcheddn, &text, &refs, &ctrls, 1 );
 
        if( rc != LDAP_SUCCESS ) {
                fprintf( stderr, "%s: ldap_parse_result: %s (%d)\n",
@@ -286,6 +287,11 @@ static int dodelete(
                }
        }
 
+       if (ctrls) {
+               tool_print_ctrls( ld, ctrls );
+               ldap_controls_free( ctrls );
+    }
+
        ber_memfree( text );
        ber_memfree( matcheddn );
        ber_memvfree( (void **) refs );
index 59632de3c2693a773e6132ef848e49a36f4f2712..6de7ec2bd02a4f78eb91553005a9eb9ae56b4790 100644 (file)
@@ -66,11 +66,11 @@ int
 main( int argc, char *argv[] )
 {
        int             rc;
-       char            *user = NULL;
 
        LDAP            *ld = NULL;
 
        char            *matcheddn = NULL, *text = NULL, **refs = NULL;
+       LDAPControl **ctrls = NULL;
        int             id, code;
        LDAPMessage     *res;
 
@@ -104,18 +104,6 @@ main( int argc, char *argv[] )
        argc -= optind;
 
        if ( strcasecmp( argv[ 0 ], "whoami" ) == 0 ) {
-               switch ( argc ) {
-               case 2:
-                       user = argv[ 1 ];
-
-               case 1:
-                       break;
-
-               default:
-                       fprintf( stderr, "need [user]\n\n" );
-                       usage();
-               }
-
                tool_server_controls( ld, NULL, 0 );
 
                rc = ldap_whoami( ld, NULL, NULL, &id ); 
@@ -253,7 +241,7 @@ main( int argc, char *argv[] )
        }
 
        rc = ldap_parse_result( ld, res,
-               &code, &matcheddn, &text, &refs, NULL, 0 );
+               &code, &matcheddn, &text, &refs, &ctrls, 0 );
        if ( rc == LDAP_SUCCESS ) {
                rc = code;
        }
@@ -358,6 +346,11 @@ main( int argc, char *argv[] )
                }
        }
 
+    if (ctrls) {
+               tool_print_ctrls( ld, ctrls );
+               ldap_controls_free( ctrls );
+       }
+
        ber_memfree( text );
        ber_memfree( matcheddn );
        ber_memvfree( (void **) refs );
index ee59c0f7dc8f83d0a203245f952f024cb591ff00..dac9efcd822288fa9f090577953dca61e04036e3 100644 (file)
@@ -92,7 +92,6 @@ static struct berval BV_MODOPADD = BER_BVC("add");
 static struct berval BV_MODOPREPLACE = BER_BVC("replace");
 static struct berval BV_MODOPDELETE = BER_BVC("delete");
 static struct berval BV_MODOPINCREMENT = BER_BVC("increment");
-static struct berval BV_MODSEP = BER_BVC("-");
 static struct berval BV_NEWRDN = BER_BVC("newrdn");
 static struct berval BV_DELETEOLDRDN = BER_BVC("deleteoldrdn");
 static struct berval BV_NEWSUP = BER_BVC("newsuperior");
@@ -372,9 +371,9 @@ main( int argc, char **argv )
                        fprintf( rejfp, "\n%s\n", rejbuf );
                }
 
-               if (rejfp) free( rejbuf );
+               if (rejfp) ber_memfree( rejbuf );
        }
-       free( rbuf );
+       ber_memfree( rbuf );
 
 #ifdef LDAP_X_TXN
        if( retval == 0 && txn ) {
@@ -1296,7 +1295,7 @@ static int process_response(
        if ( matched ) ldap_memfree( matched );
        if ( text ) ber_memvfree( (void **)refs );
 
-       if ( ctrls != NULL ) {
+       if ( ctrls ) {
                tool_print_ctrls( ld, ctrls );
                ldap_controls_free( ctrls );
        }
index 9b03471f4776c429d3fbb0a56a5ec99b53dce358..477b74e365d1478a12f9d55fb61a704255c3d8ee 100644 (file)
@@ -241,6 +241,7 @@ static int domodrdn(
 {
        int rc, code, id;
        char *matcheddn=NULL, *text=NULL, **refs=NULL;
+       LDAPControl **ctrls = NULL;
        LDAPMessage *res;
 
     if ( verbose ) {
@@ -284,7 +285,7 @@ static int domodrdn(
                }
        }
 
-       rc = ldap_parse_result( ld, res, &code, &matcheddn, &text, &refs, NULL, 1 );
+       rc = ldap_parse_result( ld, res, &code, &matcheddn, &text, &refs, &ctrls, 1 );
 
        if( rc != LDAP_SUCCESS ) {
                fprintf( stderr, "%s: ldap_parse_result: %s (%d)\n",
@@ -314,6 +315,11 @@ static int domodrdn(
                }
        }
 
+       if (ctrls) {
+               tool_print_ctrls( ld, ctrls );
+               ldap_controls_free( ctrls );
+    }
+
        ber_memfree( text );
        ber_memfree( matcheddn );
        ber_memvfree( (void **) refs );
index 7645e55e0a8c97238db0a9ef802ecc79a5c0dba2..5d676e399ed6dc703f963825069f5223c21535b6 100644 (file)
@@ -177,6 +177,7 @@ main( int argc, char *argv[] )
        char *matcheddn = NULL, *text = NULL, **refs = NULL;
        char    *retoid = NULL;
        struct berval *retdata = NULL;
+       LDAPControl **ctrls = NULL;
 
     tool_init( TOOL_PASSWD );
        prog = lutil_progname( "ldappasswd", argc, argv );
@@ -310,6 +311,8 @@ main( int argc, char *argv[] )
                goto done;
        }
 
+       tool_server_controls( ld, NULL, 0);
+
        rc = ldap_extended_operation( ld,
                LDAP_EXOP_MODIFY_PASSWD, bv.bv_val ? &bv : NULL, 
                NULL, NULL, &id );
@@ -344,7 +347,7 @@ main( int argc, char *argv[] )
        }
 
        rc = ldap_parse_result( ld, res,
-               &code, &matcheddn, &text, &refs, NULL, 0 );
+               &code, &matcheddn, &text, &refs, &ctrls, 0 );
        if( rc != LDAP_SUCCESS ) {
                tool_perror( "ldap_parse_result", rc, NULL, NULL, NULL, NULL );
                rc = EXIT_FAILURE;
@@ -381,12 +384,15 @@ main( int argc, char *argv[] )
 
                ber_free( ber, 1 );
 
-       } else if ( newpw.bv_val == NULL ) {
+       } else if ( code == LDAP_SUCCESS && newpw.bv_val == NULL ) {
                tool_perror( "ldap_parse_extended_result", LDAP_DECODING_ERROR,
                        " new password expected", NULL, NULL, NULL );
        }
 
-       if( verbose || code != LDAP_SUCCESS || matcheddn || text || refs ) {
+skip:
+       if( verbose || code != LDAP_SUCCESS ||
+               matcheddn || text || refs || ctrls )
+       {
                printf( _("Result: %s (%d)\n"), ldap_err2string( code ), code );
 
                if( text && *text ) {
@@ -403,6 +409,11 @@ main( int argc, char *argv[] )
                                printf(_("Referral: %s\n"), refs[i] );
                        }
                }
+
+               if( ctrls ) {
+                       tool_print_ctrls( ld, ctrls );
+                       ldap_controls_free( ctrls );
+               }
        }
 
        ber_memfree( text );
@@ -411,9 +422,6 @@ main( int argc, char *argv[] )
        ber_memfree( retoid );
        ber_bvfree( retdata );
 
-       rc = ldap_search_s( ld, binddn, LDAP_SCOPE_BASE, "(objectclass=*)",
-               NULL, 0, &res );
-
        rc = ( code == LDAP_SUCCESS ) ? EXIT_SUCCESS : EXIT_FAILURE;
 
 done:
index 7d20097848df333638cd56b0770283e70c7f37b9..08ca1414de924bf63bc1e5e25272a48c58b81f95 100644 (file)
@@ -109,15 +109,13 @@ int
 main( int argc, char *argv[] )
 {
        int             rc;
-       char            *user = NULL;
-
        LDAP            *ld = NULL;
-
        char            *matcheddn = NULL, *text = NULL, **refs = NULL;
        char            *retoid = NULL;
        struct berval   *retdata = NULL;
        int             id, code = 0;
        LDAPMessage     *res;
+       LDAPControl     **ctrls = NULL;
 
        tool_init( TOOL_WHOAMI );
        prog = lutil_progname( "ldapwhoami", argc, argv );
@@ -127,12 +125,8 @@ main( int argc, char *argv[] )
 
        tool_args( argc, argv );
 
-       if( argc - optind > 1 ) {
+       if( argc - optind > 0 ) {
                usage();
-       } else if ( argc - optind == 1 ) {
-               user = strdup( argv[optind] );
-       } else {
-               user = NULL;
        }
 
        if ( pw_file || want_bindpw ) {
@@ -159,7 +153,7 @@ main( int argc, char *argv[] )
        rc = ldap_whoami( ld, NULL, NULL, &id ); 
 
        if( rc != LDAP_SUCCESS ) {
-               tool_perror( "ldap_extended_operation", rc, NULL, NULL, NULL, NULL );
+               tool_perror( "ldap_whoami", rc, NULL, NULL, NULL, NULL );
                rc = EXIT_FAILURE;
                goto skip;
        }
@@ -186,7 +180,7 @@ main( int argc, char *argv[] )
        }
 
        rc = ldap_parse_result( ld, res,
-               &code, &matcheddn, &text, &refs, NULL, 0 );
+               &code, &matcheddn, &text, &refs, &ctrls, 0 );
 
        if ( rc == LDAP_SUCCESS ) {
                rc = code;
@@ -214,7 +208,10 @@ main( int argc, char *argv[] )
                }
        }
 
-       if( verbose || ( code != LDAP_SUCCESS ) || matcheddn || text || refs ) {
+skip:
+       if ( verbose || ( code != LDAP_SUCCESS ) ||
+               matcheddn || text || refs || ctrls )
+       {
                printf( _("Result: %s (%d)\n"), ldap_err2string( code ), code );
 
                if( text && *text ) {
@@ -231,6 +228,11 @@ main( int argc, char *argv[] )
                                printf(_("Referral: %s\n"), refs[i] );
                        }
                }
+
+               if (ctrls) {
+                       tool_print_ctrls( ld, ctrls );
+                       ldap_controls_free( ctrls );
+               }
        }
 
        ber_memfree( text );
@@ -239,7 +241,6 @@ main( int argc, char *argv[] )
        ber_memfree( retoid );
        ber_bvfree( retdata );
 
-skip:
        /* disconnect from server */
        tool_unbind( ld );
        tool_destroy();
index 204042d757591f6c670e52c0f7c852951d7400c0..ee0e248313cc117af6630c17da9ec2c312cc953f 100755 (executable)
--- a/configure
+++ b/configure
@@ -1,5 +1,5 @@
 #! /bin/sh
-# From configure.in OpenLDAP: pkg/ldap/configure.in,v 1.631.2.4 2006/10/19 20:06:32 kurt Exp .
+# From configure.in OpenLDAP: pkg/ldap/configure.in,v 1.658 2007/07/02 13:15:31 hallvard 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_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_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 LDAP_LIBS SLAPD_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.
@@ -1051,6 +1051,7 @@ SLAPD Overlay Options:
     --enable-dds         Dynamic Directory Services overlay no|yes|mod [no]
     --enable-dyngroup    Dynamic Group overlay no|yes|mod [no]
     --enable-dynlist     Dynamic List overlay no|yes|mod [no]
+    --enable-memberof    Reverse Group Membership overlay no|yes|mod [no]
     --enable-ppolicy     Password Policy overlay no|yes|mod [no]
     --enable-proxycache          Proxy Cache overlay no|yes|mod [no]
     --enable-refint      Referential Integrity overlay no|yes|mod [no]
@@ -1062,9 +1063,6 @@ SLAPD Overlay Options:
     --enable-unique       Attribute Uniqueness overlay no|yes|mod [no]
     --enable-valsort      Value Sorting overlay no|yes|mod [no]
 
-SLURPD (Replication Daemon) Options:
-  --enable-slurpd        enable building slurpd [auto]
-
 Library Generation & Linking Options
   --enable-static[=PKGS]
                           build static libraries [default=yes]
@@ -1083,7 +1081,7 @@ Optional Packages:
   --with-cyrus-sasl      with Cyrus SASL support [auto]
   --with-fetch           with fetch(3) URL support [auto]
   --with-threads         with threads [auto]
-  --with-tls             with TLS/SSL support [auto]
+  --with-tls             with TLS/SSL support auto|openssl|gnutls [auto]
   --with-yielding-select  with implicitly yielding select [auto]
   --with-mp               with multiple precision statistics auto|longlong|long|bignum|gmp [auto]
   --with-odbc             with specific ODBC support iodbc|unixodbc|auto [auto]
@@ -1595,8 +1593,11 @@ fi
 
 SHTOOL="$ac_cv_shtool"
 
-TB="`$SHTOOL echo -e '%B' 2>/dev/null`"
-TN="`$SHTOOL echo -e '%b' 2>/dev/null`"
+TB="" TN=""
+if test -t 1; then
+       TB="`$SHTOOL echo -e '%B' 2>/dev/null`"
+       TN="`$SHTOOL echo -e '%b' 2>/dev/null`"
+fi
 
 OPENLDAP_CVS=""
 if test -d $ac_aux_dir/CVS; then
@@ -2384,7 +2385,7 @@ if test "${with_tls+set}" = set; then
   withval="$with_tls"
 
        ol_arg=invalid
-       for ol_val in auto openssl yes no  ; do
+       for ol_val in auto openssl gnutls yes no  ; do
                if test "$withval" = "$ol_val" ; then
                        ol_arg="$ol_val"
                fi
@@ -3099,6 +3100,7 @@ Overlays="accesslog \
        dds \
        dyngroup \
        dynlist \
+       memberof \
        ppolicy \
        proxycache \
        refint \
@@ -3281,6 +3283,30 @@ else
 fi;
 # end --enable-dynlist
 
+# OpenLDAP --enable-memberof
+
+       # Check whether --enable-memberof or --disable-memberof was given.
+if test "${enable_memberof+set}" = set; then
+  enableval="$enable_memberof"
+
+       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-memberof" >&5
+echo "$as_me: error: bad value $enableval for --enable-memberof" >&2;}
+   { (exit 1); exit 1; }; }
+       fi
+       ol_enable_memberof="$ol_arg"
+
+else
+       ol_enable_memberof=${ol_enable_overlays:-no}
+fi;
+# end --enable-memberof
+
 # OpenLDAP --enable-ppolicy
 
        # Check whether --enable-ppolicy or --disable-ppolicy was given.
@@ -3522,35 +3548,6 @@ fi;
 # end --enable-valsort
 
 
-# Check whether --enable-xxslurpdoptions or --disable-xxslurpdoptions was given.
-if test "${enable_xxslurpdoptions+set}" = set; then
-  enableval="$enable_xxslurpdoptions"
-
-fi;
-# OpenLDAP --enable-slurpd
-
-       # Check whether --enable-slurpd or --disable-slurpd was given.
-if test "${enable_slurpd+set}" = set; then
-  enableval="$enable_slurpd"
-
-       ol_arg=invalid
-       for ol_val in auto yes no ; 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-slurpd" >&5
-echo "$as_me: error: bad value $enableval for --enable-slurpd" >&2;}
-   { (exit 1); exit 1; }; }
-       fi
-       ol_enable_slurpd="$ol_arg"
-
-else
-       ol_enable_slurpd=auto
-fi;
-# end --enable-slurpd
-
 # Check whether --enable-xxliboptions or --disable-xxliboptions was given.
 if test "${enable_xxliboptions+set}" = set; then
   enableval="$enable_xxliboptions"
@@ -3643,11 +3640,6 @@ echo "$as_me: WARNING: slapd disabled, ignoring --enable-dynacl argument" >&2;}
        if test $ol_enable_aci != no ; then
                { echo "$as_me:$LINENO: WARNING: slapd disabled, ignoring --enable-aci argument" >&5
 echo "$as_me: WARNING: slapd disabled, ignoring --enable-aci argument" >&2;}
-       fi
-       if test $ol_enable_slurpd = yes ; then
-               { { echo "$as_me:$LINENO: error: slurpd requires slapd" >&5
-echo "$as_me: error: slurpd requires slapd" >&2;}
-   { (exit 1); exit 1; }; }
        fi
        if test $ol_enable_rewrite = yes ; then
                { echo "$as_me:$LINENO: WARNING: slapd disabled, ignoring --enable-rewrite argument" >&5
@@ -3677,8 +3669,6 @@ echo "$as_me: WARNING: slapd disabled, ignoring --enable-$i argument" >&2;}
        ol_enable_aci=no
        ol_enable_wrappers=no
 
-       ol_enable_slurpd=no
-
        ol_enable_rewrite=no
 
 elif test $ol_enable_modules != yes &&
@@ -3712,14 +3702,6 @@ echo "$as_me: error: --enable-meta requires --enable-ldap" >&2;}
    { (exit 1); exit 1; }; }
 fi
 
-if test $ol_enable_slurpd = yes ; then
-               if test $ol_with_threads = no ; then
-               { { echo "$as_me:$LINENO: error: slurpd requires threads" >&5
-echo "$as_me: error: slurpd requires threads" >&2;}
-   { (exit 1); exit 1; }; }
-       fi
-fi
-
 if test $ol_enable_lmpasswd = yes ; then
        if test $ol_with_tls = no ; then
                { { echo "$as_me:$LINENO: error: LAN Manager passwords require OpenSSL" >&5
@@ -3746,10 +3728,8 @@ LTHREAD_LIBS=
 LUTIL_LIBS=
 
 SLAPD_LIBS=
-SLURPD_LIBS=
 
 BUILD_SLAPD=no
-BUILD_SLURPD=no
 
 BUILD_THREAD=no
 
@@ -5613,7 +5593,7 @@ ia64-*-hpux*)
   ;;
 *-*-irix6*)
   # Find out which ABI we are using.
-  echo '#line 5616 "configure"' > conftest.$ac_ext
+  echo '#line 5596 "configure"' > conftest.$ac_ext
   if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
@@ -7593,11 +7573,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:7596: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:7576: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:7600: \$? = $ac_status" >&5
+   echo "$as_me:7580: \$? = $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.
@@ -7855,11 +7835,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:7858: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:7838: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:7862: \$? = $ac_status" >&5
+   echo "$as_me:7842: \$? = $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.
@@ -7917,11 +7897,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:7920: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:7900: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>out/conftest.err)
    ac_status=$?
    cat out/conftest.err >&5
-   echo "$as_me:7924: \$? = $ac_status" >&5
+   echo "$as_me:7904: \$? = $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
@@ -10165,7 +10145,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<EOF
-#line 10168 "configure"
+#line 10148 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -10263,7 +10243,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<EOF
-#line 10266 "configure"
+#line 10246 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -12749,6 +12729,7 @@ EOF
 fi
 echo "$as_me:$LINENO: result: $ol_cv_mkdep" >&5
 echo "${ECHO_T}$ol_cv_mkdep" >&6
+               test "$ol_cv_mkdep" = no && OL_MKDEP=":"
        else
                cc_cv_mkdep=yes
                OL_MKDEP_FLAGS="${MKDEP_FLAGS}"
@@ -13837,6 +13818,9 @@ fi
 
 
 
+
+
+
 
 
 
@@ -13871,9 +13855,11 @@ for ac_header in \
        sysexits.h              \
        sys/file.h              \
        sys/filio.h             \
+       sys/fstyp.h             \
        sys/errno.h             \
        sys/ioctl.h             \
        sys/param.h             \
+       sys/privgrp.h   \
        sys/resource.h  \
        sys/select.h    \
        sys/socket.h    \
@@ -13882,6 +13868,7 @@ for ac_header in \
        sys/time.h              \
        sys/types.h             \
        sys/uio.h               \
+       sys/vmount.h    \
        syslog.h                \
        termios.h               \
        unistd.h                \
@@ -17245,26 +17232,322 @@ _ACEOF
 fi
 
 if test $have_uuid = no ; then
-       echo "$as_me:$LINENO: checking to see if -lrpcrt4 is needed for win32 UUID support" >&5
-echo $ECHO_N "checking to see if -lrpcrt4 is needed for win32 UUID support... $ECHO_C" >&6
-       save_LIBS="$LIBS"
-       LIBS="$LIBS -lrpcrt4"
-       cat >conftest.$ac_ext <<_ACEOF
+
+for ac_header in uuid/uuid.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+else
+  # Is the header compilable?
+echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
 /* confdefs.h.  */
 _ACEOF
 cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_header_compiler=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
 
-               int __stdcall UuidCreate(void *);
-               int __stdcall UuidToStringA(void *,void **);
+ac_header_compiler=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6
 
+# Is the header present?
+echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <$ac_header>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  ac_header_preproc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  ac_header_preproc=no
+fi
+rm -f conftest.err conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+  yes:no: )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header:     check for missing prerequisite headers?" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+    (
+      cat <<\_ASBOX
+## --------------------------------------------- ##
+## Report this to <http://www.openldap.org/its/> ##
+## --------------------------------------------- ##
+_ASBOX
+    ) |
+      sed "s/^/$as_me: WARNING:     /" >&2
+    ;;
+esac
+echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  eval "$as_ac_Header=\$ac_header_preproc"
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+       if test $ac_cv_header_uuid_uuid_h = yes ; then
+               save_LIBS="$LIBS"
+               echo "$as_me:$LINENO: checking for library containing uuid_generate" >&5
+echo $ECHO_N "checking for library containing uuid_generate... $ECHO_C" >&6
+if test "${ac_cv_search_uuid_generate+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_func_search_save_LIBS=$LIBS
+ac_cv_search_uuid_generate=no
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char uuid_generate ();
 int
 main ()
 {
+uuid_generate ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_search_uuid_generate="none required"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
 
-               UuidCreate(0);
-               UuidToStringA(0,0);
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+if test "$ac_cv_search_uuid_generate" = no; then
+  for ac_lib in uuid; do
+    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
+    cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char uuid_generate ();
+int
+main ()
+{
+uuid_generate ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_search_uuid_generate="-l$ac_lib"
+break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+  done
+fi
+LIBS=$ac_func_search_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_search_uuid_generate" >&5
+echo "${ECHO_T}$ac_cv_search_uuid_generate" >&6
+if test "$ac_cv_search_uuid_generate" != no; then
+  test "$ac_cv_search_uuid_generate" = "none required" || LIBS="$ac_cv_search_uuid_generate $LIBS"
+  have_uuid=yes
+else
+  :
+fi
+
+               LIBS="$save_LIBS"
+
+               if test have_uuid = yes ; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_UUID_GENERATE 1
+_ACEOF
+
+
+                       test "$ac_cv_search_uuid_generate" = "none required" || \
+                               SLAPD_LIBS="$SLAPD_LIBS $ac_cv_search_uuid_generate"
+               fi
+       fi
+fi
+
+if test $have_uuid = no ; then
+       echo "$as_me:$LINENO: checking to see if -lrpcrt4 is needed for win32 UUID support" >&5
+echo $ECHO_N "checking to see if -lrpcrt4 is needed for win32 UUID support... $ECHO_C" >&6
+       save_LIBS="$LIBS"
+       LIBS="$LIBS -lrpcrt4"
+       cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+               int __stdcall UuidCreate(void *);
+               int __stdcall UuidToStringA(void *,void **);
+
+int
+main ()
+{
+
+               UuidCreate(0);
+               UuidToStringA(0,0);
 
   ;
   return 0;
@@ -18525,6 +18808,247 @@ _ACEOF
        fi
 fi
 
+if test $ol_link_tls = no ; then
+       if test $ol_with_tls = gnutls || test $ol_with_tls = auto ; then
+
+for ac_header in gnutls/gnutls.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+else
+  # Is the header compilable?
+echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_header_compiler=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_header_compiler=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6
+
+# Is the header present?
+echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <$ac_header>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  ac_header_preproc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  ac_header_preproc=no
+fi
+rm -f conftest.err conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+  yes:no: )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header:     check for missing prerequisite headers?" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+    (
+      cat <<\_ASBOX
+## --------------------------------------------- ##
+## Report this to <http://www.openldap.org/its/> ##
+## --------------------------------------------- ##
+_ASBOX
+    ) |
+      sed "s/^/$as_me: WARNING:     /" >&2
+    ;;
+esac
+echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  eval "$as_ac_Header=\$ac_header_preproc"
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+               if test $ac_cv_header_gnutls_gnutls_h = yes ; then
+                       echo "$as_me:$LINENO: checking for gnutls_init in -lgnutls" >&5
+echo $ECHO_N "checking for gnutls_init in -lgnutls... $ECHO_C" >&6
+if test "${ac_cv_lib_gnutls_gnutls_init+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lgnutls  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char gnutls_init ();
+int
+main ()
+{
+gnutls_init ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_lib_gnutls_gnutls_init=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_gnutls_gnutls_init=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_gnutls_gnutls_init" >&5
+echo "${ECHO_T}$ac_cv_lib_gnutls_gnutls_init" >&6
+if test $ac_cv_lib_gnutls_gnutls_init = yes; then
+  have_gnutls=yes
+else
+  have_gnutls=no
+fi
+
+
+                       if test $have_gnutls = yes ; then
+                               ol_with_tls=gnutls
+                               ol_link_tls=yes
+
+                               TLS_LIBS="-lgnutls"
+
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_GNUTLS 1
+_ACEOF
+
+                       fi
+               fi
+       fi
+fi
+
 WITH_TLS=no
 if test $ol_link_tls = yes ; then
 
@@ -23879,7 +24403,7 @@ int main(argc, argv)
 #endif
 
        /* make sure task runs first */
-#if HAVE_THR_YIELD
+#ifdef HAVE_THR_YIELD
        thr_yield();
 #elif defined( HAVE_SCHED_YIELD )
        sched_yield();
@@ -30649,9 +31173,9 @@ main()
        }
 
 #if (DB_VERSION_MAJOR > 3) || (DB_VERSION_MINOR >= 1)
-       rc = env->open( env, NULL, flags, 0 );
+       rc = (env->open)( env, NULL, flags, 0 );
 #else
-       rc = env->open( env, NULL, NULL, flags, 0 );
+       rc = (env->open)( env, NULL, NULL, flags, 0 );
 #endif
 
        if ( rc == 0 ) {
@@ -33518,6 +34042,7 @@ _ACEOF
 fi
 
 
+
 echo "$as_me:$LINENO: checking for socklen_t" >&5
 echo $ECHO_N "checking for socklen_t... $ECHO_C" >&6
 if test "${ac_cv_type_socklen_t+set}" = set; then
@@ -33534,7 +34059,6 @@ $ac_includes_default
 #include <sys/socket.h>
 #endif
 
-
 int
 main ()
 {
@@ -33579,12 +34103,84 @@ rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
 fi
 echo "$as_me:$LINENO: result: $ac_cv_type_socklen_t" >&5
 echo "${ECHO_T}$ac_cv_type_socklen_t" >&6
-if test $ac_cv_type_socklen_t = yes; then
-  :
+
+
+echo "$as_me:$LINENO: checking the type of arg 3 to accept()" >&5
+echo $ECHO_N "checking the type of arg 3 to accept()... $ECHO_C" >&6
+if test "${ol_cv_type_ber_socklen_t+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+       set socklen_t int unsigned "unsigned long" long size_t
+       test "$ac_cv_type_socklen_t" = yes || shift
+       ol_cv_type_ber_socklen_t=$1 guessing="guessing "
+       for lentype in "$@" ; do for addrtype in "struct sockaddr" void ; do
+               cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+extern int accept(int s, $addrtype *ap, $lentype *lp);
+
+int
+main ()
+{
+
+accept(0, (struct sockaddr *) 0, ($lentype *) 0);
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ol_cv_type_ber_socklen_t=$lentype guessing= ; break 2
 else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+       done ; done
+fi
+
+echo "$as_me:$LINENO: result: $guessing$ol_cv_type_ber_socklen_t *" >&5
+echo "${ECHO_T}$guessing$ol_cv_type_ber_socklen_t *" >&6
 
 cat >>confdefs.h <<_ACEOF
-#define socklen_t int
+#define ber_socklen_t $ol_cv_type_ber_socklen_t
+_ACEOF
+
+
+if test "$ac_cv_type_socklen_t" != yes; then
+
+cat >>confdefs.h <<_ACEOF
+#define socklen_t $ol_cv_type_ber_socklen_t
 _ACEOF
 
 fi
@@ -38855,7 +39451,126 @@ int
 main ()
 {
 static struct msghdr ac_aggr;
-if (sizeof ac_aggr.msg_accrightslen)
+if (sizeof ac_aggr.msg_accrightslen)
+return 0;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_member_struct_msghdr_msg_accrightslen=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_member_struct_msghdr_msg_accrightslen=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_member_struct_msghdr_msg_accrightslen" >&5
+echo "${ECHO_T}$ac_cv_member_struct_msghdr_msg_accrightslen" >&6
+if test $ac_cv_member_struct_msghdr_msg_accrightslen = yes; then
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTSLEN 1
+_ACEOF
+
+
+fi
+
+               if test "$ac_cv_member_struct_msghdr_msg_accrightslen" != yes; then
+                       echo "$as_me:$LINENO: checking for struct msghdr.msg_control" >&5
+echo $ECHO_N "checking for struct msghdr.msg_control... $ECHO_C" >&6
+if test "${ac_cv_member_struct_msghdr_msg_control+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+
+int
+main ()
+{
+static struct msghdr ac_aggr;
+if (ac_aggr.msg_control)
+return 0;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_member_struct_msghdr_msg_control=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+
+int
+main ()
+{
+static struct msghdr ac_aggr;
+if (sizeof ac_aggr.msg_control)
 return 0;
   ;
   return 0;
@@ -38883,32 +39598,32 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
-  ac_cv_member_struct_msghdr_msg_accrightslen=yes
+  ac_cv_member_struct_msghdr_msg_control=yes
 else
   echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-ac_cv_member_struct_msghdr_msg_accrightslen=no
+ac_cv_member_struct_msghdr_msg_control=no
 fi
 rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
 fi
 rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
 fi
-echo "$as_me:$LINENO: result: $ac_cv_member_struct_msghdr_msg_accrightslen" >&5
-echo "${ECHO_T}$ac_cv_member_struct_msghdr_msg_accrightslen" >&6
-if test $ac_cv_member_struct_msghdr_msg_accrightslen = yes; then
+echo "$as_me:$LINENO: result: $ac_cv_member_struct_msghdr_msg_control" >&5
+echo "${ECHO_T}$ac_cv_member_struct_msghdr_msg_control" >&6
+if test $ac_cv_member_struct_msghdr_msg_control = yes; then
 
 cat >>confdefs.h <<_ACEOF
-#define HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTSLEN 1
+#define HAVE_STRUCT_MSGHDR_MSG_CONTROL 1
 _ACEOF
 
 
 fi
 
-               if test "$ac_cv_member_struct_msghdr_msg_accrightslen" != yes; then
-                       echo "$as_me:$LINENO: checking for struct msghdr.msg_control" >&5
-echo $ECHO_N "checking for struct msghdr.msg_control... $ECHO_C" >&6
-if test "${ac_cv_member_struct_msghdr_msg_control+set}" = set; then
+               fi
+               echo "$as_me:$LINENO: checking for struct stat.st_fstype" >&5
+echo $ECHO_N "checking for struct stat.st_fstype... $ECHO_C" >&6
+if test "${ac_cv_member_struct_stat_st_fstype+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
@@ -38918,15 +39633,11 @@ cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
 $ac_includes_default
-#ifdef HAVE_SYS_SOCKET_H
-#include <sys/socket.h>
-#endif
-
 int
 main ()
 {
-static struct msghdr ac_aggr;
-if (ac_aggr.msg_control)
+static struct stat ac_aggr;
+if (ac_aggr.st_fstype)
 return 0;
   ;
   return 0;
@@ -38954,7 +39665,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
-  ac_cv_member_struct_msghdr_msg_control=yes
+  ac_cv_member_struct_stat_st_fstype=yes
 else
   echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
@@ -38966,15 +39677,76 @@ cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
 $ac_includes_default
-#ifdef HAVE_SYS_SOCKET_H
-#include <sys/socket.h>
-#endif
+int
+main ()
+{
+static struct stat ac_aggr;
+if (sizeof ac_aggr.st_fstype)
+return 0;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_member_struct_stat_st_fstype=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
 
+ac_cv_member_struct_stat_st_fstype=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_member_struct_stat_st_fstype" >&5
+echo "${ECHO_T}$ac_cv_member_struct_stat_st_fstype" >&6
+if test $ac_cv_member_struct_stat_st_fstype = yes; then
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_STRUCT_STAT_ST_FSTYPE 1
+_ACEOF
+
+
+fi
+echo "$as_me:$LINENO: checking for struct stat.st_vfstype" >&5
+echo $ECHO_N "checking for struct stat.st_vfstype... $ECHO_C" >&6
+if test "${ac_cv_member_struct_stat_st_vfstype+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
 int
 main ()
 {
-static struct msghdr ac_aggr;
-if (sizeof ac_aggr.msg_control)
+static struct stat ac_aggr;
+if (ac_aggr.st_vfstype)
 return 0;
   ;
   return 0;
@@ -39002,28 +39774,114 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
-  ac_cv_member_struct_msghdr_msg_control=yes
+  ac_cv_member_struct_stat_st_vfstype=yes
 else
   echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-ac_cv_member_struct_msghdr_msg_control=no
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+static struct stat ac_aggr;
+if (sizeof ac_aggr.st_vfstype)
+return 0;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_member_struct_stat_st_vfstype=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_member_struct_stat_st_vfstype=no
 fi
 rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
 fi
 rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
 fi
-echo "$as_me:$LINENO: result: $ac_cv_member_struct_msghdr_msg_control" >&5
-echo "${ECHO_T}$ac_cv_member_struct_msghdr_msg_control" >&6
-if test $ac_cv_member_struct_msghdr_msg_control = yes; then
+echo "$as_me:$LINENO: result: $ac_cv_member_struct_stat_st_vfstype" >&5
+echo "${ECHO_T}$ac_cv_member_struct_stat_st_vfstype" >&6
+if test $ac_cv_member_struct_stat_st_vfstype = yes; then
 
 cat >>confdefs.h <<_ACEOF
-#define HAVE_STRUCT_MSGHDR_MSG_CONTROL 1
+#define HAVE_STRUCT_STAT_ST_VFSTYPE 1
 _ACEOF
 
 
 fi
 
+               if test "$ac_cv_member_struct_stat_st_fstype" = yes; then
+                       cat >conftest.$ac_ext <<_ACEOF
+struct stat st; char *ptr=st.st_fstype;
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_STRUCT_STAT_ST_FSTYPE_CHAR 1
+_ACEOF
+
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_STRUCT_STAT_ST_FSTYPE_INT 1
+_ACEOF
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
                fi
        fi
        LIBSRCS="$LIBSRCS getpeereid.c"
@@ -39728,6 +40586,22 @@ _ACEOF
 
 fi
 
+if test "$ol_enable_memberof" != no ; then
+       BUILD_MEMBEROF=$ol_enable_memberof
+       if test "$ol_enable_memberof" = mod ; then
+               MFLAG=SLAPD_MOD_DYNAMIC
+               SLAPD_DYNAMIC_OVERLAYS="$SLAPD_DYNAMIC_OVERLAYS memberof.la"
+       else
+               MFLAG=SLAPD_MOD_STATIC
+               SLAPD_STATIC_OVERLAYS="$SLAPD_STATIC_OVERLAYS memberof.o"
+       fi
+
+cat >>confdefs.h <<_ACEOF
+#define SLAPD_OVER_MEMBEROF $MFLAG
+_ACEOF
+
+fi
+
 if test "$ol_enable_ppolicy" != no ; then
        BUILD_PPOLICY=$ol_enable_ppolicy
        if test "$ol_enable_ppolicy" = mod ; then
@@ -39889,12 +40763,6 @@ _ACEOF
 
 fi
 
-if test "$ol_enable_slurpd" != no &&
-   test "$ol_link_threads" != no &&
-   test $BUILD_SLAPD = yes ; then
-       BUILD_SLURPD=yes
-fi
-
 if test "$ol_enable_rewrite" != no ; then
 
 cat >>confdefs.h <<\_ACEOF
@@ -40002,8 +40870,6 @@ fi
 
 
 
-
-
 
 
 
@@ -40014,7 +40880,7 @@ if test "${with_xxinstall+set}" = set; then
 fi;
 
 
-                                                                                                                                                                                                                                                                                                                                                                                                      ac_config_files="$ac_config_files Makefile:build/top.mk:Makefile.in:build/dir.mk doc/Makefile:build/top.mk:doc/Makefile.in:build/dir.mk doc/man/Makefile:build/top.mk:doc/man/Makefile.in:build/dir.mk doc/man/man1/Makefile:build/top.mk:doc/man/man1/Makefile.in:build/man.mk doc/man/man3/Makefile:build/top.mk:doc/man/man3/Makefile.in:build/man.mk doc/man/man5/Makefile:build/top.mk:doc/man/man5/Makefile.in:build/man.mk doc/man/man8/Makefile:build/top.mk:doc/man/man8/Makefile.in:build/man.mk clients/Makefile:build/top.mk:clients/Makefile.in:build/dir.mk clients/tools/Makefile:build/top.mk:clients/tools/Makefile.in:build/rules.mk include/Makefile:build/top.mk:include/Makefile.in libraries/Makefile:build/top.mk:libraries/Makefile.in:build/dir.mk libraries/liblber/Makefile:build/top.mk:libraries/liblber/Makefile.in:build/lib.mk:build/lib-shared.mk libraries/libldap/Makefile:build/top.mk:libraries/libldap/Makefile.in:build/lib.mk:build/lib-shared.mk libraries/libldap_r/Makefile:build/top.mk:libraries/libldap_r/Makefile.in:build/lib.mk:build/lib-shared.mk libraries/liblunicode/Makefile:build/top.mk:libraries/liblunicode/Makefile.in:build/lib.mk:build/lib-static.mk libraries/liblutil/Makefile:build/top.mk:libraries/liblutil/Makefile.in:build/lib.mk:build/lib-static.mk libraries/librewrite/Makefile:build/top.mk:libraries/librewrite/Makefile.in:build/lib.mk:build/lib-static.mk servers/Makefile:build/top.mk:servers/Makefile.in:build/dir.mk servers/slapd/Makefile:build/top.mk:servers/slapd/Makefile.in:build/srv.mk servers/slapd/back-bdb/Makefile:build/top.mk:servers/slapd/back-bdb/Makefile.in:build/mod.mk servers/slapd/back-dnssrv/Makefile:build/top.mk:servers/slapd/back-dnssrv/Makefile.in:build/mod.mk servers/slapd/back-hdb/Makefile:build/top.mk:servers/slapd/back-hdb/Makefile.in:build/mod.mk servers/slapd/back-ldap/Makefile:build/top.mk:servers/slapd/back-ldap/Makefile.in:build/mod.mk servers/slapd/back-ldif/Makefile:build/top.mk:servers/slapd/back-ldif/Makefile.in:build/mod.mk servers/slapd/back-meta/Makefile:build/top.mk:servers/slapd/back-meta/Makefile.in:build/mod.mk servers/slapd/back-monitor/Makefile:build/top.mk:servers/slapd/back-monitor/Makefile.in:build/mod.mk servers/slapd/back-null/Makefile:build/top.mk:servers/slapd/back-null/Makefile.in:build/mod.mk servers/slapd/back-passwd/Makefile:build/top.mk:servers/slapd/back-passwd/Makefile.in:build/mod.mk servers/slapd/back-perl/Makefile:build/top.mk:servers/slapd/back-perl/Makefile.in:build/mod.mk servers/slapd/back-relay/Makefile:build/top.mk:servers/slapd/back-relay/Makefile.in:build/mod.mk servers/slapd/back-shell/Makefile:build/top.mk:servers/slapd/back-shell/Makefile.in:build/mod.mk servers/slapd/back-sql/Makefile:build/top.mk:servers/slapd/back-sql/Makefile.in:build/mod.mk servers/slapd/shell-backends/Makefile:build/top.mk:servers/slapd/shell-backends/Makefile.in:build/srv.mk servers/slapd/slapi/Makefile:build/top.mk:servers/slapd/slapi/Makefile.in:build/lib.mk:build/lib-shared.mk servers/slapd/overlays/Makefile:build/top.mk:servers/slapd/overlays/Makefile.in:build/lib.mk servers/slurpd/Makefile:build/top.mk:servers/slurpd/Makefile.in:build/srv.mk tests/Makefile:build/top.mk:tests/Makefile.in:build/dir.mk tests/run tests/progs/Makefile:build/top.mk:tests/progs/Makefile.in:build/rules.mk"
+                                                                                                                                                                                                                                                                                                                                                                                            ac_config_files="$ac_config_files Makefile:build/top.mk:Makefile.in:build/dir.mk doc/Makefile:build/top.mk:doc/Makefile.in:build/dir.mk doc/man/Makefile:build/top.mk:doc/man/Makefile.in:build/dir.mk doc/man/man1/Makefile:build/top.mk:doc/man/man1/Makefile.in:build/man.mk doc/man/man3/Makefile:build/top.mk:doc/man/man3/Makefile.in:build/man.mk doc/man/man5/Makefile:build/top.mk:doc/man/man5/Makefile.in:build/man.mk doc/man/man8/Makefile:build/top.mk:doc/man/man8/Makefile.in:build/man.mk clients/Makefile:build/top.mk:clients/Makefile.in:build/dir.mk clients/tools/Makefile:build/top.mk:clients/tools/Makefile.in:build/rules.mk include/Makefile:build/top.mk:include/Makefile.in libraries/Makefile:build/top.mk:libraries/Makefile.in:build/dir.mk libraries/liblber/Makefile:build/top.mk:libraries/liblber/Makefile.in:build/lib.mk:build/lib-shared.mk libraries/libldap/Makefile:build/top.mk:libraries/libldap/Makefile.in:build/lib.mk:build/lib-shared.mk libraries/libldap_r/Makefile:build/top.mk:libraries/libldap_r/Makefile.in:build/lib.mk:build/lib-shared.mk libraries/liblunicode/Makefile:build/top.mk:libraries/liblunicode/Makefile.in:build/lib.mk:build/lib-static.mk libraries/liblutil/Makefile:build/top.mk:libraries/liblutil/Makefile.in:build/lib.mk:build/lib-static.mk libraries/librewrite/Makefile:build/top.mk:libraries/librewrite/Makefile.in:build/lib.mk:build/lib-static.mk servers/Makefile:build/top.mk:servers/Makefile.in:build/dir.mk servers/slapd/Makefile:build/top.mk:servers/slapd/Makefile.in:build/srv.mk servers/slapd/back-bdb/Makefile:build/top.mk:servers/slapd/back-bdb/Makefile.in:build/mod.mk servers/slapd/back-dnssrv/Makefile:build/top.mk:servers/slapd/back-dnssrv/Makefile.in:build/mod.mk servers/slapd/back-hdb/Makefile:build/top.mk:servers/slapd/back-hdb/Makefile.in:build/mod.mk servers/slapd/back-ldap/Makefile:build/top.mk:servers/slapd/back-ldap/Makefile.in:build/mod.mk servers/slapd/back-ldif/Makefile:build/top.mk:servers/slapd/back-ldif/Makefile.in:build/mod.mk servers/slapd/back-meta/Makefile:build/top.mk:servers/slapd/back-meta/Makefile.in:build/mod.mk servers/slapd/back-monitor/Makefile:build/top.mk:servers/slapd/back-monitor/Makefile.in:build/mod.mk servers/slapd/back-null/Makefile:build/top.mk:servers/slapd/back-null/Makefile.in:build/mod.mk servers/slapd/back-passwd/Makefile:build/top.mk:servers/slapd/back-passwd/Makefile.in:build/mod.mk servers/slapd/back-perl/Makefile:build/top.mk:servers/slapd/back-perl/Makefile.in:build/mod.mk servers/slapd/back-relay/Makefile:build/top.mk:servers/slapd/back-relay/Makefile.in:build/mod.mk servers/slapd/back-shell/Makefile:build/top.mk:servers/slapd/back-shell/Makefile.in:build/mod.mk servers/slapd/back-sql/Makefile:build/top.mk:servers/slapd/back-sql/Makefile.in:build/mod.mk servers/slapd/shell-backends/Makefile:build/top.mk:servers/slapd/shell-backends/Makefile.in:build/srv.mk servers/slapd/slapi/Makefile:build/top.mk:servers/slapd/slapi/Makefile.in:build/lib.mk:build/lib-shared.mk servers/slapd/overlays/Makefile:build/top.mk:servers/slapd/overlays/Makefile.in:build/lib.mk tests/Makefile:build/top.mk:tests/Makefile.in:build/dir.mk tests/run tests/progs/Makefile:build/top.mk:tests/progs/Makefile.in:build/rules.mk"
 
 
           ac_config_commands="$ac_config_commands default"
@@ -40561,7 +41427,6 @@ do
   "servers/slapd/shell-backends/Makefile" ) CONFIG_FILES="$CONFIG_FILES servers/slapd/shell-backends/Makefile:build/top.mk:servers/slapd/shell-backends/Makefile.in:build/srv.mk" ;;
   "servers/slapd/slapi/Makefile" ) CONFIG_FILES="$CONFIG_FILES servers/slapd/slapi/Makefile:build/top.mk:servers/slapd/slapi/Makefile.in:build/lib.mk:build/lib-shared.mk" ;;
   "servers/slapd/overlays/Makefile" ) CONFIG_FILES="$CONFIG_FILES servers/slapd/overlays/Makefile:build/top.mk:servers/slapd/overlays/Makefile.in:build/lib.mk" ;;
-  "servers/slurpd/Makefile" ) CONFIG_FILES="$CONFIG_FILES servers/slurpd/Makefile:build/top.mk:servers/slurpd/Makefile.in:build/srv.mk" ;;
   "tests/Makefile" ) CONFIG_FILES="$CONFIG_FILES tests/Makefile:build/top.mk:tests/Makefile.in:build/dir.mk" ;;
   "tests/run" ) CONFIG_FILES="$CONFIG_FILES tests/run" ;;
   "tests/progs/Makefile" ) CONFIG_FILES="$CONFIG_FILES tests/progs/Makefile:build/top.mk:tests/progs/Makefile.in:build/rules.mk" ;;
@@ -40771,10 +41636,8 @@ s,@BUILD_SYNCPROV@,$BUILD_SYNCPROV,;t t
 s,@BUILD_TRANSLUCENT@,$BUILD_TRANSLUCENT,;t t
 s,@BUILD_UNIQUE@,$BUILD_UNIQUE,;t t
 s,@BUILD_VALSORT@,$BUILD_VALSORT,;t t
-s,@BUILD_SLURPD@,$BUILD_SLURPD,;t t
 s,@LDAP_LIBS@,$LDAP_LIBS,;t t
 s,@SLAPD_LIBS@,$SLAPD_LIBS,;t t
-s,@SLURPD_LIBS@,$SLURPD_LIBS,;t t
 s,@BDB_LIBS@,$BDB_LIBS,;t t
 s,@LTHREAD_LIBS@,$LTHREAD_LIBS,;t t
 s,@LUTIL_LIBS@,$LUTIL_LIBS,;t t
 /* end of generated file */
 ENDX
 
-echo Please run \"make depend\" to build dependencies
+if test "${ol_cv_mkdep}" = no; then
+       echo '(Do not "make depend"; we do not know how to build dependencies)'
+else
+       echo 'Please run "make depend" to build dependencies'
+fi
  ;;
   esac
 done
index b013b04f732973e7b045dfdee79b3e1e7159f2a2..cad9a70bbbd33a127e80a15d70bf8b075854168f 100644 (file)
@@ -50,8 +50,11 @@ fi
 SHTOOL="$ac_cv_shtool"
 dnl AC_SUBST(SHTOOL)dnl
 
-TB="`$SHTOOL echo -e '%B' 2>/dev/null`"
-TN="`$SHTOOL echo -e '%b' 2>/dev/null`"
+TB="" TN=""
+if test -t 1; then
+       TB="`$SHTOOL echo -e '%B' 2>/dev/null`"
+       TN="`$SHTOOL echo -e '%b' 2>/dev/null`"
+fi
 
 OPENLDAP_CVS=""
 if test -d $ac_aux_dir/CVS; then
@@ -241,8 +244,8 @@ OL_ARG_WITH(fetch,[  --with-fetch             with fetch(3) URL support],
        auto, [auto yes no] )
 OL_ARG_WITH(threads,[  --with-threads    with threads],
        auto, [auto nt posix mach pth lwp yes no manual] )
-OL_ARG_WITH(tls,[  --with-tls            with TLS/SSL support],
-       auto, [auto openssl yes no] )
+OL_ARG_WITH(tls,[  --with-tls            with TLS/SSL support auto|openssl|gnutls],
+       auto, [auto openssl gnutls yes no] )
 OL_ARG_WITH(yielding_select,
        [  --with-yielding-select  with implicitly yielding select],
        auto, [auto yes no manual] )
@@ -328,6 +331,7 @@ Overlays="accesslog \
        dds \
        dyngroup \
        dynlist \
+       memberof \
        ppolicy \
        proxycache \
        refint \
@@ -356,6 +360,8 @@ OL_ARG_ENABLE(dyngroup,[    --enable-dyngroup         Dynamic Group overlay],
        no, [no yes mod], ol_enable_overlays)
 OL_ARG_ENABLE(dynlist,[    --enable-dynlist      Dynamic List overlay],
        no, [no yes mod], ol_enable_overlays)
+OL_ARG_ENABLE(memberof,[    --enable-memberof    Reverse Group Membership overlay],
+       no, [no yes mod], ol_enable_overlays)
 OL_ARG_ENABLE(ppolicy,[    --enable-ppolicy      Password Policy overlay],
        no, [no yes mod], ol_enable_overlays)
 OL_ARG_ENABLE(proxycache,[    --enable-proxycache        Proxy Cache overlay],
@@ -377,12 +383,6 @@ OL_ARG_ENABLE(unique,[    --enable-unique       Attribute Uniqueness overlay],
 OL_ARG_ENABLE(valsort,[    --enable-valsort      Value Sorting overlay],
        no, [no yes mod], ol_enable_overlays)
 
-dnl ----------------------------------------------------------------
-dnl SLURPD OPTIONS
-AC_ARG_ENABLE(xxslurpdoptions,[
-SLURPD (Replication Daemon) Options:])
-OL_ARG_ENABLE(slurpd,[  --enable-slurpd          enable building slurpd], auto)dnl
-
 dnl ----------------------------------------------------------------
 AC_ARG_ENABLE(xxliboptions,[
 Library Generation & Linking Options])
@@ -422,9 +422,6 @@ if test $ol_enable_slapd = no ; then
        if test $ol_enable_aci != no ; then
                AC_MSG_WARN([slapd disabled, ignoring --enable-aci argument])
        fi
-       if test $ol_enable_slurpd = yes ; then
-               AC_MSG_ERROR([slurpd requires slapd])
-       fi
        if test $ol_enable_rewrite = yes ; then
                AC_MSG_WARN([slapd disabled, ignoring --enable-rewrite argument])
        fi
@@ -451,8 +448,6 @@ if test $ol_enable_slapd = no ; then
        ol_enable_aci=no
        ol_enable_wrappers=no
 
-       ol_enable_slurpd=no
-
        ol_enable_rewrite=no
 
 elif test $ol_enable_modules != yes &&
@@ -482,13 +477,6 @@ if test $ol_enable_meta/$ol_enable_ldap = yes/no ; then
        AC_MSG_ERROR([--enable-meta requires --enable-ldap])
 fi
 
-if test $ol_enable_slurpd = yes ; then
-       dnl SLURPD was specifically enabled
-       if test $ol_with_threads = no ; then
-               AC_MSG_ERROR([slurpd requires threads])
-       fi
-fi
-
 if test $ol_enable_lmpasswd = yes ; then
        if test $ol_with_tls = no ; then
                AC_MSG_ERROR([LAN Manager passwords require OpenSSL])
@@ -512,10 +500,8 @@ LTHREAD_LIBS=
 LUTIL_LIBS=
 
 SLAPD_LIBS=
-SLURPD_LIBS=
 
 BUILD_SLAPD=no
-BUILD_SLURPD=no
 
 BUILD_THREAD=no
 
@@ -813,9 +799,11 @@ AC_CHECK_HEADERS(  \
        sysexits.h              \
        sys/file.h              \
        sys/filio.h             \
+       sys/fstyp.h             \
        sys/errno.h             \
        sys/ioctl.h             \
        sys/param.h             \
+       sys/privgrp.h   \
        sys/resource.h  \
        sys/select.h    \
        sys/socket.h    \
@@ -824,6 +812,7 @@ AC_CHECK_HEADERS(   \
        sys/time.h              \
        sys/types.h             \
        sys/uio.h               \
+       sys/vmount.h    \
        syslog.h                \
        termios.h               \
        unistd.h                \
@@ -988,7 +977,7 @@ have_uuid=no
 AC_CHECK_HEADERS(sys/uuid.h)
 if test $ac_cv_header_sys_uuid_h = yes ; then
        save_LIBS="$LIBS"
-       AC_SEARCH_LIBS(uuid_to_str, uuid, [have_uuid=yes], :)
+       AC_SEARCH_LIBS([uuid_to_str], [uuid], [have_uuid=yes], :)
        LIBS="$save_LIBS"
 
        if test have_uuid = yes ; then
@@ -1000,6 +989,24 @@ if test $ac_cv_header_sys_uuid_h = yes ; then
        fi
 fi
 
+dnl Look for uuid_generate
+if test $have_uuid = no ; then
+       AC_CHECK_HEADERS(uuid/uuid.h)
+       if test $ac_cv_header_uuid_uuid_h = yes ; then
+               save_LIBS="$LIBS"
+               AC_SEARCH_LIBS([uuid_generate], [uuid], [have_uuid=yes], :)
+               LIBS="$save_LIBS"
+
+               if test have_uuid = yes ; then
+                       AC_DEFINE(HAVE_UUID_GENERATE,1,
+                               [define if you have uuid_generate()])
+
+                       test "$ac_cv_search_uuid_generate" = "none required" || \
+                               SLAPD_LIBS="$SLAPD_LIBS $ac_cv_search_uuid_generate"
+               fi
+       fi
+fi
+
 dnl For windows, check for the need of RPCRT for UUID function support
 if test $have_uuid = no ; then
        AC_MSG_CHECKING(to see if -lrpcrt4 is needed for win32 UUID support)
@@ -1146,6 +1153,27 @@ if test $ol_with_tls = openssl || test $ol_with_tls = auto ; then
        fi
 fi
 
+if test $ol_link_tls = no ; then
+       if test $ol_with_tls = gnutls || test $ol_with_tls = auto ; then
+               AC_CHECK_HEADERS(gnutls/gnutls.h)
+
+               if test $ac_cv_header_gnutls_gnutls_h = yes ; then
+                       AC_CHECK_LIB(gnutls, gnutls_init,
+                               [have_gnutls=yes], [have_gnutls=no])
+
+                       if test $have_gnutls = yes ; then
+                               ol_with_tls=gnutls
+                               ol_link_tls=yes
+
+                               TLS_LIBS="-lgnutls"
+
+                               AC_DEFINE(HAVE_GNUTLS, 1, 
+                                       [define if you have GNUtls])
+                       fi
+               fi
+       fi
+fi
+
 WITH_TLS=no
 if test $ol_link_tls = yes ; then
        AC_DEFINE(HAVE_TLS, 1, [define if you have TLS])
@@ -1471,7 +1499,7 @@ int main(argc, argv)
 #endif
 
        /* make sure task runs first */
-#if HAVE_THR_YIELD
+#ifdef HAVE_THR_YIELD
        thr_yield();
 #elif defined( HAVE_SCHED_YIELD )
        sched_yield();
@@ -2108,14 +2136,43 @@ AC_CHECK_TYPE(size_t, unsigned)
 AC_CHECK_TYPES([long long])
 AC_CHECK_TYPES([ptrdiff_t])
 
-AC_CHECK_TYPE([socklen_t],,
-       [AC_DEFINE_UNQUOTED([socklen_t], [int],
-               [Define to `int' if <sys/socket.h> does not define.])],
-       [$ac_includes_default
+
+AC_CHECK_TYPE([socklen_t],,, [$ac_includes_default
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif])
+
+dnl socklen_t-like type in accept(), default socklen_t or int:
+dnl - The OS might define socklen_t without using it.  POSIX moved from
+dnl   int to size_t to socklen_t, hoping to stay at a 32-bit type, and
+dnl   HP-UX now has selectors for what to use.
+dnl - On Solaris 2.8 the prototype has void *len, but the default is OK.
+AC_MSG_CHECKING([the type of arg 3 to accept()])
+AC_CACHE_VAL(ol_cv_type_ber_socklen_t, [
+       set socklen_t int unsigned "unsigned long" long size_t
+       test "$ac_cv_type_socklen_t" = yes || shift
+       ol_cv_type_ber_socklen_t=$1 guessing="guessing "
+       for lentype in "$@" ; do for addrtype in "struct sockaddr" void ; do
+               AC_COMPILE_IFELSE([AC_LANG_PROGRAM([$ac_includes_default
 #ifdef HAVE_SYS_SOCKET_H
 #include <sys/socket.h>
 #endif
-       ])
+extern int accept(int s, $addrtype *ap, $lentype *lp);
+], [
+accept(0, (struct sockaddr *) 0, ($lentype *) 0);
+])], [ol_cv_type_ber_socklen_t=$lentype guessing= ; break 2])
+       done ; done])
+AC_MSG_RESULT([$guessing$ol_cv_type_ber_socklen_t *])
+AC_DEFINE_UNQUOTED(ber_socklen_t, $ol_cv_type_ber_socklen_t,
+       [Define to the type of arg 3 for `accept'.])
+
+dnl Modules should use ber_socklen_t, not socklen_t.  Define socklen_t
+dnl for the time being anyway, for backwards compatibility.
+if test "$ac_cv_type_socklen_t" != yes; then
+       AC_DEFINE_UNQUOTED([socklen_t], [$ol_cv_type_ber_socklen_t],
+               [Define like ber_socklen_t if <sys/socket.h> does not define.])
+fi
+
 
 AC_TYPE_SIGNAL
 
@@ -2320,6 +2377,12 @@ if test "$ac_cv_func_getpeereid" != yes; then
 #include <sys/socket.h>
 #endif])
                fi
+               AC_CHECK_MEMBERS([struct stat.st_fstype, struct stat.st_vfstype])
+               if test "$ac_cv_member_struct_stat_st_fstype" = yes; then
+                       AC_COMPILE_IFELSE([struct stat st; char *ptr=st.st_fstype;],
+                               AC_DEFINE([HAVE_STRUCT_STAT_ST_FSTYPE_CHAR],1,[define to 1 if st_fstype is char *]),
+                               AC_DEFINE([HAVE_STRUCT_STAT_ST_FSTYPE_INT],1,[define to 1 if st_fstype is int]))
+               fi
        fi
        LIBSRCS="$LIBSRCS getpeereid.c"
 fi
@@ -2656,6 +2719,18 @@ if test "$ol_enable_dynlist" != no ; then
        AC_DEFINE_UNQUOTED(SLAPD_OVER_DYNLIST,$MFLAG,[define for Dynamic List overlay])
 fi
 
+if test "$ol_enable_memberof" != no ; then
+       BUILD_MEMBEROF=$ol_enable_memberof
+       if test "$ol_enable_memberof" = mod ; then
+               MFLAG=SLAPD_MOD_DYNAMIC
+               SLAPD_DYNAMIC_OVERLAYS="$SLAPD_DYNAMIC_OVERLAYS memberof.la"
+       else
+               MFLAG=SLAPD_MOD_STATIC
+               SLAPD_STATIC_OVERLAYS="$SLAPD_STATIC_OVERLAYS memberof.o"
+       fi
+       AC_DEFINE_UNQUOTED(SLAPD_OVER_MEMBEROF,$MFLAG,[define for Reverse Group Membership overlay])
+fi
+
 if test "$ol_enable_ppolicy" != no ; then
        BUILD_PPOLICY=$ol_enable_ppolicy
        if test "$ol_enable_ppolicy" = mod ; then
@@ -2777,12 +2852,6 @@ if test "$ol_enable_valsort" != no ; then
        AC_DEFINE_UNQUOTED(SLAPD_OVER_VALSORT,$MFLAG,[define for Value Sorting overlay])
 fi
 
-if test "$ol_enable_slurpd" != no &&
-   test "$ol_link_threads" != no &&
-   test $BUILD_SLAPD = yes ; then
-       BUILD_SLURPD=yes
-fi
-
 if test "$ol_enable_rewrite" != no ; then
        AC_DEFINE(ENABLE_REWRITE,1,[define to enable rewriting in back-ldap and back-meta])
        BUILD_REWRITE=yes
@@ -2853,11 +2922,9 @@ dnl overlays
   AC_SUBST(BUILD_TRANSLUCENT)
   AC_SUBST(BUILD_UNIQUE)
   AC_SUBST(BUILD_VALSORT)
-AC_SUBST(BUILD_SLURPD)
 
 AC_SUBST(LDAP_LIBS)
 AC_SUBST(SLAPD_LIBS)
-AC_SUBST(SLURPD_LIBS)
 AC_SUBST(BDB_LIBS)
 AC_SUBST(LTHREAD_LIBS)
 AC_SUBST(LUTIL_LIBS)
@@ -2938,7 +3005,6 @@ AC_CONFIG_FILES([Makefile:build/top.mk:Makefile.in:build/dir.mk]
 [servers/slapd/shell-backends/Makefile:build/top.mk:servers/slapd/shell-backends/Makefile.in:build/srv.mk]
 [servers/slapd/slapi/Makefile:build/top.mk:servers/slapd/slapi/Makefile.in:build/lib.mk:build/lib-shared.mk]
 [servers/slapd/overlays/Makefile:build/top.mk:servers/slapd/overlays/Makefile.in:build/lib.mk]
-[servers/slurpd/Makefile:build/top.mk:servers/slurpd/Makefile.in:build/srv.mk]
 [tests/Makefile:build/top.mk:tests/Makefile.in:build/dir.mk]
 [tests/run]
 [tests/progs/Makefile:build/top.mk:tests/progs/Makefile.in:build/rules.mk])
@@ -3051,7 +3117,11 @@ fi
 /* end of generated file */
 ENDX
 
-echo Please run \"make depend\" to build dependencies
+if test "${ol_cv_mkdep}" = no; then
+       echo '(Do not "make depend"; we do not know how to build dependencies)'
+else
+       echo 'Please run "make depend" to build dependencies'
+fi
 ]],[[
 STATIC_BACKENDS="$SLAPD_STATIC_BACKENDS"
 STATIC_OVERLAYS="$SLAPD_STATIC_OVERLAYS"
index 332d96d0531fbf488741669c6392e34968a18555..94db3bb1b241348e2ffe9528404aec1d3897b322 100644 (file)
 #ifndef _AC_TIME_H
 #define _AC_TIME_H
 
-#if TIME_WITH_SYS_TIME
+#ifdef TIME_WITH_SYS_TIME
 # include <sys/time.h>
 # include <time.h>
-#elif HAVE_SYS_TIME_H
+#elif defined HAVE_SYS_TIME_H
 # include <sys/time.h>
 # ifdef HAVE_SYS_TIMEB_H
 #  include <sys/timeb.h>
index 2137d294fbe96bf9e6d63933acd6ab6ade608574..731d3aba12c77d8c069c5698ad0ad45bf7e8663b 100755 (executable)
@@ -931,7 +931,8 @@ fi
 
 case "$with_tk" in
     yes)
-       if test -f $exec_prefix/lib/tkConfig.sh -a $exec_prefix/lib/tkxConfig.sh
+       if test -f $exec_prefix/lib/tkConfig.sh &&
+          test -f $exec_prefix/lib/tkxConfig.sh
        then
            :
        else
index 71ac2a67b132ff3c3b188768fc5a66f006fec566..9a0364c3a7d574b8d24554e67a5daa518c68d975 100644 (file)
@@ -52,7 +52,8 @@ AC_ARG_WITH(tk, [  --with-tk=DIR          use Tk 8.0 binaries from DIR],
 
 case "$with_tk" in
     yes)
-       if test -f $exec_prefix/lib/tkConfig.sh -a $exec_prefix/lib/tkxConfig.sh
+       if test -f $exec_prefix/lib/tkConfig.sh &&
+          test -f $exec_prefix/lib/tkxConfig.sh
        then
            :
        else
index a9f1a8f2b9a271f650057a5bd9bea97c268b7b86..b1ce03e705ce055ca475e165ed6d6128a7b55909 100644 (file)
@@ -1408,7 +1408,7 @@ NeoX_LdapObjCmd (clientData, interp, objc, objv)
        }
        ldap = ldap_init (ldapHost, ldapPort);
 
-#if LDAP_OPT_PROTOCOL_VERSION
+#ifdef LDAP_OPT_PROTOCOL_VERSION
        if (version != -1)
            ldap_set_option(ldap, LDAP_OPT_PROTOCOL_VERSION, &version);
 #endif
@@ -1426,7 +1426,7 @@ NeoX_LdapObjCmd (clientData, interp, objc, objv)
        return TCL_ERROR;
     }
 
-#if UMICH_LDAP
+#ifdef UMICH_LDAP
     ldap->ld_deref = LDAP_DEREF_NEVER;  /* Turn off alias dereferencing */
 #endif
 
diff --git a/contrib/slapd-modules/addpartial/COPYRIGHT b/contrib/slapd-modules/addpartial/COPYRIGHT
new file mode 100644 (file)
index 0000000..fda001e
--- /dev/null
@@ -0,0 +1,10 @@
+Copyright (C) Virginia Tech, David Hawes.
+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.
diff --git a/contrib/slapd-modules/addpartial/LICENSE b/contrib/slapd-modules/addpartial/LICENSE
new file mode 100644 (file)
index 0000000..83a87ef
--- /dev/null
@@ -0,0 +1,47 @@
+The OpenLDAP Public License
+  Version 2.8, 17 August 2003
+
+  Redistribution and use of this software and associated documentation
+  ("Software"), with or without modification, are permitted provided
+  that the following conditions are met:
+
+  1. Redistributions in source form must retain copyright statements
+     and notices,
+
+  2. Redistributions in binary form must reproduce applicable copyright
+     statements and notices, this list of conditions, and the following
+     disclaimer in the documentation and/or other materials provided
+     with the distribution, and
+
+  3. Redistributions must contain a verbatim copy of this document.
+
+The OpenLDAP Foundation may revise this license from time to time.
+Each revision is distinguished by a version number.  You may use
+this Software under terms of this license revision or under the
+terms of any subsequent revision of the license.
+
+THIS SOFTWARE IS PROVIDED BY THE OPENLDAP FOUNDATION AND ITS
+CONTRIBUTORS ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT
+SHALL THE OPENLDAP FOUNDATION, ITS CONTRIBUTORS, OR THE AUTHOR(S)
+OR OWNER(S) OF THE SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+
+The names of the authors and copyright holders must not be used in
+advertising or otherwise to promote the sale, use or other dealing
+in this Software without specific, written prior permission.  Title
+to copyright in this Software shall at all times remain with copyright
+holders.
+
+OpenLDAP is a registered trademark of the OpenLDAP Foundation.
+
+Copyright 1999-2003 The OpenLDAP Foundation, Redwood City,
+California, USA.  All Rights Reserved.  Permission to copy and
+distribute verbatim copies of this document is granted.
diff --git a/contrib/slapd-modules/addpartial/Makefile b/contrib/slapd-modules/addpartial/Makefile
new file mode 100644 (file)
index 0000000..60a1b59
--- /dev/null
@@ -0,0 +1,12 @@
+OPENLDAP_SRC=/usr/local/src/openldap-2.3.32
+CPPFLAGS+=-I${OPENLDAP_SRC}/include -I${OPENLDAP_SRC}/servers/slapd
+LDFLAGS+=-L/usr/local/openldap-2.3.32/lib
+CC=gcc
+
+all: addpartial-overlay.so
+
+addpartial-overlay.so: addpartial-overlay.c
+       $(CC) -shared $(CPPFLAGS) $(LDFLAGS) -Wall -o $@ $?
+
+clean:
+       rm addpartial-overlay.so
diff --git a/contrib/slapd-modules/addpartial/README b/contrib/slapd-modules/addpartial/README
new file mode 100644 (file)
index 0000000..dca8b14
--- /dev/null
@@ -0,0 +1,61 @@
+addpartial Overlay README
+
+DESCRIPTION
+    This package contains an OpenLDAP overlay called "addpartial" that 
+    intercepts add requests, determines if the entry exists, determines what 
+    attributes, if any, have changed, and modifies those attributes.  If the
+    entry does not exist, the add request falls through and proceeds normally.
+    If the entry exists but no changes have been detected, the client receives
+    LDAP_SUCCESS (I suppose it is debatable what to do in this case, but this is
+    the most clean for my use.  The LDAP_SUCCESS lets me know that the entry I
+    sent slapd == the entry already in my slapd DB.  Perhaps this behavior
+    should be configurable in the future).
+
+    When a change is found, the addpartial overlay will replace all values for
+    the attribute (if an attribute does not exist in the new entry but exists
+    in the entry in the slapd DB, a replace will be done with an empty list of
+    values).
+
+    Once a modify takes place, the addpartial overlay will write changes to the
+    replog (using the slap_replog_cb).  If you are using syncrepl for
+    replication, the syncprov overlay will properly process the change, provided
+    that addpartial is the first overlay to run.  Please see the CAVEATS for
+    more specifics about this.
+
+    The addpartial overlay makes it easy to replicate full entries to a slapd 
+    instance without worrying about the differences between entries or even if
+    the entry exists.  Using ldapadd to add entries, the addpartial overlay can
+    compare about 500 records per second.  The intent of the addpartial overlay
+    is to make it easy to replicate records from a source that is not an LDAP
+    instance, such as a database.  The overlay is also useful in places where it
+    is easier to create full entries rather than comparing an entry with an
+    entry that must be retrieved (with ldapsearch or similar) from an existing
+    slapd DB to find changes. 
+
+    The addpartial overlay has been used in production since August 2004 and has
+    processed millions of records without incident.
+
+BUILDING
+    A Makefile is included, please set your OPENLDAP_SRC directory properly.
+
+INSTALLATION
+    After compiling the addpartial overlay, add the following to your 
+    slapd.conf:
+
+    ### slapd.conf
+    ...
+    moduleload /path/to/addpartial-overlay.so
+    ...
+    # after database directive...
+    # this overlay should be the last overlay in the config file to ensure that
+    # it properly intercepts the add request
+    overlay addpartial
+    ...
+    ### end slapd.conf
+
+CAVEATS
+    - In order to ensure that addpartial does what it needs to do, it should be
+      the last overlay configured so it will run before the other overlays.
+      This is especially important if you are using syncrepl, as the modify that
+      addpartial does will muck with the locking that takes place in the
+      syncprov overlay.
diff --git a/contrib/slapd-modules/addpartial/addpartial-overlay.c b/contrib/slapd-modules/addpartial/addpartial-overlay.c
new file mode 100644 (file)
index 0000000..9210040
--- /dev/null
@@ -0,0 +1,434 @@
+/**
+ * $Id: addpartial-overlay.c 5376 2007-01-26 20:03:13Z dhawes $
+ *
+ * Copyright (C) 2004 Virginia Tech, David Hawes.
+ * 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.
+ *
+ * SEE LICENSE FOR MORE INFORMATION
+ *
+ * Author:  David H. Hawes, Jr.
+ * Email:   dhawes@vt.edu
+ * Version: $Revision: 5376 $
+ * Updated: $Date: 2007-01-26 15:03:13 -0500 (Fri, 26 Jan 2007) $
+ * 
+ * addpartial-overlay
+ *
+ * This is an OpenLDAP overlay that intercepts ADD requests, determines if a
+ * change has actually taken place for that record, and then performs a modify
+ * request for those values that have changed (modified, added, deleted).  If
+ * the record has not changed in any way, it is ignored.  If the record does not
+ * exist, the record falls through to the normal add mechanism.  This overlay is
+ * useful for replicating from sources that are not LDAPs where it is easier to
+ * build entire records than to determine the changes (i.e. a database). 
+ */
+
+#include "portable.h" 
+#include <stdio.h>
+#include <ac/string.h>
+#include <ac/socket.h>
+#include "slap.h"
+#include <unistd.h>
+#include <lutil.h>
+
+static int addpartial_search_cb( Operation *op, SlapReply *rs);
+static int collect_error_msg_cb( Operation *op, SlapReply *rs);
+
+static slap_overinst addpartial;
+
+/**
+ *  The meat of the overlay.  Search for the record, determine changes, take
+ *  action or fall through.
+ */
+static int addpartial_add( Operation *op, SlapReply *rs)
+{
+    Operation nop = *op;
+    SlapReply nrs = { REP_RESULT };
+    Filter *filter = NULL;
+    Entry *toAdd = NULL;
+    struct berval fstr = BER_BVNULL;
+    slap_callback cb = { NULL, addpartial_search_cb, NULL, NULL };
+    slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
+    int rc;
+
+    toAdd = op->oq_add.rs_e;
+
+    Debug(LDAP_DEBUG_TRACE, "%s: toAdd->e_nname.bv_val: %s\n",
+          addpartial.on_bi.bi_type, toAdd->e_nname.bv_val,0);
+
+    /* if the user doesn't have access, fall through to the normal ADD */
+    if(!access_allowed(op, toAdd, slap_schema.si_ad_entry,
+                       NULL, ACL_WRITE, NULL))
+    {
+        return SLAP_CB_CONTINUE;
+    }
+    
+    rs->sr_text = NULL;
+
+    nop.o_callback = &cb;
+    op->o_bd->bd_info = (BackendInfo *) on->on_info;
+    nop.o_tag = LDAP_REQ_SEARCH;
+    nop.o_ctrls = NULL;
+    
+    filter = str2filter("(objectclass=*)");
+    filter2bv(filter, &fstr);
+
+    nop.ors_scope = LDAP_SCOPE_BASE;
+    nop.ors_deref = LDAP_DEREF_NEVER;
+    nop.ors_slimit = -1;//SLAP_NO_LIMIT;
+    nop.ors_tlimit = -1;//SLAP_NO_LIMIT;
+    nop.ors_attrsonly = 0;
+    nop.ors_attrs = slap_anlist_no_attrs;
+    nop.ors_filter = filter;
+    nop.ors_filterstr = fstr;
+
+    memset(&nrs, 0, sizeof(nrs));
+    nrs.sr_type = REP_RESULT;
+    nrs.sr_err = LDAP_SUCCESS;
+    nrs.sr_entry = NULL;
+    nrs.sr_flags |= REP_ENTRY_MUSTBEFREED;
+    nrs.sr_text = NULL;
+
+    Debug(LDAP_DEBUG_TRACE, "%s: performing search\n", addpartial.on_bi.bi_type,
+          0,0);
+
+    if(nop.o_bd->be_search)
+    {
+        rc = nop.o_bd->be_search(&nop, &nrs);
+        Debug(LDAP_DEBUG_TRACE, "%s: search performed\n",
+              addpartial.on_bi.bi_type,0,0);
+    }
+    else
+    {
+        Debug(LDAP_DEBUG_TRACE, "%s: backend missing search function\n",
+              addpartial.on_bi.bi_type,0,0);
+    }
+
+    if(filter)
+        filter_free(filter);
+    if(fstr.bv_val)
+        ch_free(fstr.bv_val);
+
+    if(rc != LDAP_SUCCESS)
+        return SLAP_CB_CONTINUE;
+    else
+    { 
+        Entry *found = NULL;
+        Debug(LDAP_DEBUG_TRACE, "%s: found the dn\n", addpartial.on_bi.bi_type,
+              0,0);
+        found = (Entry *) cb.sc_private;
+
+        if(found)
+        {
+            Attribute *attr = NULL;
+            Attribute *at = NULL;
+            int ret;
+            Modifications *mods = NULL;
+            Modifications **modtail = &mods;
+            Modifications *mod = NULL;
+
+            Debug(LDAP_DEBUG_TRACE, "%s: have an entry!\n",
+                  addpartial.on_bi.bi_type,0,0);
+
+           /* determine if the changes are in the found entry */ 
+            for(attr = toAdd->e_attrs; attr; attr = attr->a_next)
+            {
+                if(attr->a_desc->ad_type->sat_atype.at_usage != 0) continue;
+
+                at = attr_find(found->e_attrs, attr->a_desc);
+                if(!at)
+                {
+                    Debug(LDAP_DEBUG_TRACE, "%s: Attribute %s not found!\n",
+                          addpartial.on_bi.bi_type,
+                          attr->a_desc->ad_cname.bv_val,0);
+                    mod = (Modifications *) ch_malloc(sizeof(
+                                                            Modifications));
+                    mod->sml_flags = 0;
+                    mod->sml_op = LDAP_MOD_REPLACE | LDAP_MOD_BVALUES;
+                    mod->sml_op &= LDAP_MOD_OP;
+                    mod->sml_next = NULL;
+                    mod->sml_desc = attr->a_desc;
+                    mod->sml_type.bv_val = attr->a_desc->ad_cname.bv_val;
+                    mod->sml_type.bv_len = strlen(mod->sml_type.bv_val);
+                    mod->sml_values = attr->a_vals;
+                    mod->sml_nvalues = attr->a_nvals;
+                    *modtail = mod;
+                    modtail = &mod->sml_next;
+                }
+                else
+                {
+                    MatchingRule *mr = attr->a_desc->ad_type->sat_equality;
+                    struct berval *bv;
+                    const char *text;
+                    int acount , bcount;
+                    Debug(LDAP_DEBUG_TRACE, "%s: Attribute %s found\n",
+                          addpartial.on_bi.bi_type,
+                          attr->a_desc->ad_cname.bv_val,0);
+
+                    for(bv = attr->a_vals, acount = 0; bv->bv_val != NULL; 
+                        bv++, acount++)
+                    {
+                        /* count num values for attr */
+                    }
+                    for(bv = at->a_vals, bcount = 0; bv->bv_val != NULL; 
+                        bv++, bcount++)
+                    {
+                        /* count num values for attr */
+                    }
+                    if(acount != bcount)
+                    {
+                        Debug(LDAP_DEBUG_TRACE, "%s: acount != bcount, %s\n",
+                              addpartial.on_bi.bi_type,
+                              "replace all",0);
+                        mod = (Modifications *) ch_malloc(sizeof(
+                                                                Modifications));
+                        mod->sml_flags = 0;
+                        mod->sml_op = LDAP_MOD_REPLACE | LDAP_MOD_BVALUES;
+                        mod->sml_op &= LDAP_MOD_OP;
+                        mod->sml_next = NULL;
+                        mod->sml_desc = attr->a_desc;
+                        mod->sml_type.bv_val = attr->a_desc->ad_cname.bv_val;
+                        mod->sml_type.bv_len = strlen(mod->sml_type.bv_val);
+                        mod->sml_values = attr->a_vals;
+                        mod->sml_nvalues = attr->a_nvals;
+                        *modtail = mod;
+                        modtail = &mod->sml_next;
+                        continue;
+                    }
+                    
+                    for(bv = attr->a_vals; bv->bv_val != NULL; bv++)
+                    {
+                        struct berval *v;
+                        ret = -1;
+                        
+                        for(v = at->a_vals; v->bv_val != NULL; v++)
+                        {
+                            int r;
+                            if(mr && ((r = value_match(&ret, attr->a_desc, mr,
+                                           SLAP_MR_VALUE_OF_ASSERTION_SYNTAX,
+                                           bv, v, &text)) == 0))
+                            {
+                                if(ret == 0)
+                                    break;
+                            }
+                            else
+                            {
+                                Debug(LDAP_DEBUG_TRACE,
+                                      "%s: \tvalue DNE, r: %d \n",
+                                      addpartial.on_bi.bi_type,
+                                      r,0);
+                                ret = strcmp(bv->bv_val, v->bv_val);
+                                if(ret == 0)
+                                    break;
+                            }
+                        }
+
+                        if(ret == 0)
+                        {
+                            Debug(LDAP_DEBUG_TRACE,
+                                  "%s: \tvalue %s exists, ret: %d\n",
+                                  addpartial.on_bi.bi_type, bv->bv_val, ret);
+                        }
+                        else
+                        {
+                            Debug(LDAP_DEBUG_TRACE,
+                                  "%s: \tvalue %s DNE, ret: %d\n",
+                                  addpartial.on_bi.bi_type, bv->bv_val, ret);
+                            mod = (Modifications *) ch_malloc(sizeof(
+                                                                Modifications));
+                            mod->sml_flags = 0;
+                            mod->sml_op = LDAP_MOD_REPLACE | LDAP_MOD_BVALUES;
+                            mod->sml_op &= LDAP_MOD_OP;
+                            mod->sml_next = NULL;
+                            mod->sml_desc = attr->a_desc;
+                            mod->sml_type.bv_val = 
+                                                  attr->a_desc->ad_cname.bv_val;
+                            mod->sml_type.bv_len = strlen(mod->sml_type.bv_val);
+                            mod->sml_values = attr->a_vals;
+                            mod->sml_nvalues = attr->a_nvals;
+                            *modtail = mod;
+                            modtail = &mod->sml_next;
+                            break;
+                        }
+                    }
+                }
+            }
+
+            /* determine if any attributes were deleted */
+            for(attr = found->e_attrs; attr; attr = attr->a_next)
+            {
+                if(attr->a_desc->ad_type->sat_atype.at_usage != 0) continue;
+
+                at = NULL;
+                at = attr_find(toAdd->e_attrs, attr->a_desc);
+                if(!at)
+                {
+                    Debug(LDAP_DEBUG_TRACE,
+                          "%s: Attribute %s not found in new entry!!!\n",
+                          addpartial.on_bi.bi_type,
+                          attr->a_desc->ad_cname.bv_val, 0);
+                    mod = (Modifications *) ch_malloc(sizeof(
+                                                        Modifications));
+                    mod->sml_flags = 0;
+                    mod->sml_op = LDAP_MOD_REPLACE;
+                    mod->sml_next = NULL;
+                    mod->sml_desc = attr->a_desc;
+                    mod->sml_type.bv_val = 
+                                          attr->a_desc->ad_cname.bv_val;
+                    mod->sml_type.bv_len = strlen(mod->sml_type.bv_val);
+                    mod->sml_values = NULL;
+                    mod->sml_nvalues = NULL;
+                    *modtail = mod;
+                    modtail = &mod->sml_next;
+                }
+                else
+                {
+                    Debug(LDAP_DEBUG_TRACE,
+                          "%s: Attribute %s found in new entry\n",
+                          addpartial.on_bi.bi_type,
+                          at->a_desc->ad_cname.bv_val, 0);
+                }
+            }
+
+            if(mods)
+            {
+                Debug(LDAP_DEBUG_TRACE, "%s: mods to do...\n",
+                      addpartial.on_bi.bi_type, 0, 0);
+                if(nop.o_bd->be_modify)
+                {
+                    Modifications *m = NULL;
+                    int modcount;
+                    slap_callback cb2 = { NULL, slap_replog_cb, NULL, NULL };
+                    slap_callback nullcb = { NULL, collect_error_msg_cb, 
+                                             NULL, NULL };
+                    char textbuf[SLAP_TEXT_BUFLEN];
+                    size_t textlen = sizeof textbuf;
+
+                    memset(&nrs, 0, sizeof(nrs));
+                    nrs.sr_type = REP_RESULT;
+                    nrs.sr_err = LDAP_SUCCESS;
+                    nrs.sr_entry = NULL;
+                    nrs.sr_text = NULL;
+
+                    nop.o_tag = LDAP_REQ_MODIFY;
+                    nop.orm_modlist = mods;
+                    cb2.sc_next = &nullcb;
+                    nop.o_callback = &cb2;
+                    nop.o_bd->bd_info = (BackendInfo *) on->on_info;
+
+                    for(m = mods, modcount = 0; m; m = m->sml_next, 
+                        modcount++)
+                    {
+                        /* count number of mods */
+                    }
+
+                    Debug(LDAP_DEBUG_TRACE, "%s: number of mods: %d\n",
+                          addpartial.on_bi.bi_type, modcount, 0);
+
+                    rc = (nop.o_bd->be_modify)(&nop, &nrs);
+
+                    if(rc == LDAP_SUCCESS)
+                    {
+                        Debug(LDAP_DEBUG_TRACE,
+                              "%s: modify successful\n",
+                              addpartial.on_bi.bi_type, 0, 0);
+                    }
+                    else
+                    {
+                        Debug(LDAP_DEBUG_TRACE, "%s: modify unsuccessful: %d\n",
+                              addpartial.on_bi.bi_type, rc, 0);
+                        rs->sr_err = rc;
+                        if(nrs.sr_text)
+                        {
+                            rs->sr_text = nullcb.sc_private;
+                        }
+                    }
+
+                    Debug(LDAP_DEBUG_TRACE, "%s: freeing mods...\n",
+                          addpartial.on_bi.bi_type, 0, 0);
+
+                    if(mods != NULL)
+                    {
+                        Modifications *toDel;
+
+                        for(toDel = mods; toDel; toDel = mods)
+                        {
+                            mods = mods->sml_next;
+                            ch_free(toDel);
+                        }
+                    }
+                }
+            }
+            else
+            {
+                Debug(LDAP_DEBUG_TRACE, "%s: no mods to process\n",
+                      addpartial.on_bi.bi_type, 0, 0);
+            }
+
+            if(found != NULL) ;
+                entry_free(found);
+        }
+        else
+        {
+            Debug(LDAP_DEBUG_TRACE, "%s: no entry!\n",
+                  addpartial.on_bi.bi_type, 0, 0);
+        }
+
+        op->o_callback = NULL;
+        send_ldap_result( op, rs );
+        ch_free((void *)rs->sr_text);
+        rs->sr_text = NULL;
+
+        return LDAP_SUCCESS;
+    }
+}
+
+static int addpartial_search_cb( Operation *op, SlapReply *rs)
+{
+    Entry *entry = NULL;
+
+    if(rs->sr_type != REP_SEARCH) return 0;
+        
+    Debug(LDAP_DEBUG_TRACE, "%s: addpartial_search_cb\n",
+          addpartial.on_bi.bi_type, 0, 0);
+
+    if(rs->sr_entry)
+    {
+        Debug(LDAP_DEBUG_TRACE, "%s: dn found: %s\n",
+              addpartial.on_bi.bi_type, rs->sr_entry->e_nname.bv_val, 0);
+        entry = rs->sr_entry;
+        op->o_callback->sc_private = (void *) entry_dup(entry);
+    }
+
+    return 0;
+}
+
+static int collect_error_msg_cb( Operation *op, SlapReply *rs)
+{
+    if(rs->sr_text)
+    {
+        op->o_callback->sc_private = (void *) ch_strdup(rs->sr_text);
+    }
+
+    return LDAP_SUCCESS;
+}
+
+int addpartial_init() 
+{
+    addpartial.on_bi.bi_type = "addpartial";
+    addpartial.on_bi.bi_op_add = addpartial_add;
+
+    return (overlay_register(&addpartial));
+}
+
+int init_module(int argc, char *argv[]) 
+{
+        return addpartial_init();
+}
index 6ddf4a473e062f47d54c65fce5717e9c00f28e64..e5cbf416bebd3239e660fb80e5c87ab89801849b 100644 (file)
@@ -39,6 +39,7 @@ allop-URI     <ldapURI>
 #include <ac/string.h>
 
 #include "slap.h"
+#include "config.h"
 
 #define        SLAP_OVER_VERSION_REQUIRE(major,minor,patch) \
        ( \
@@ -140,7 +141,7 @@ allop_db_config(
 }
 
 static int
-allop_db_destroy( BackendDB *be )
+allop_db_destroy( BackendDB *be, ConfigReply *cr )
 {
        slap_overinst   *on = (slap_overinst *)be->bd_info;
        allop_t         *ao = (allop_t *)on->on_bi.bi_private;
index f4bbb284bb9c925a94a6576157f9c75699ebbf78..0e9bb36d1e356ce154814b256765b79aa5f6de3e 100644 (file)
  * <http://www.OpenLDAP.org/license.html>.
  */
 
+#include "portable.h"
+
 #include <stdio.h>
 
 #include <lber.h>
 #include <lber_pvt.h>  /* BER_BVC definition */
 #include "lutil.h"
+#include <ldap_pvt_thread.h>
 #include <ac/string.h>
 #include <ac/unistd.h>
 
@@ -25,6 +28,7 @@
 static LUTIL_PASSWD_CHK_FUNC chk_radius;
 static const struct berval scheme = BER_BVC("{RADIUS}");
 static char *config_filename;
+static ldap_pvt_thread_mutex_t libradius_mutex;
 
 static int
 chk_radius(
@@ -58,8 +62,11 @@ chk_radius(
                return LUTIL_PASSWD_ERR;        /* passwd must behave like a string */
        }
 
+       ldap_pvt_thread_mutex_lock( &libradius_mutex );
+
        h = rad_auth_open();
        if ( h == NULL ) {
+               ldap_pvt_thread_mutex_unlock( &libradius_mutex );
                return LUTIL_PASSWD_ERR;
        }
 
@@ -79,16 +86,37 @@ chk_radius(
                goto done;
        }
 
-       if ( rad_send_request( h ) == RAD_ACCESS_ACCEPT ) {
+       switch ( rad_send_request( h ) ) {
+       case RAD_ACCESS_ACCEPT:
                rc = LUTIL_PASSWD_OK;
+               break;
+
+       case RAD_ACCESS_REJECT:
+               rc = LUTIL_PASSWD_ERR;
+               break;
+
+       case RAD_ACCESS_CHALLENGE:
+               rc = LUTIL_PASSWD_ERR;
+               break;
+
+       case -1:
+               /* no valid response is received */
+               break;
        }
 
 done:;
        rad_close( h );
 
+       ldap_pvt_thread_mutex_unlock( &libradius_mutex );
        return rc;
 }
 
+int
+term_module()
+{
+       return ldap_pvt_thread_mutex_destroy( &libradius_mutex );
+}
+
 int
 init_module( int argc, char *argv[] )
 {
@@ -109,5 +137,7 @@ init_module( int argc, char *argv[] )
                }
        }
 
+       ldap_pvt_thread_mutex_init( &libradius_mutex );
+
        return lutil_passwd_add( (struct berval *)&scheme, chk_radius, NULL );
 }
index 6b674583ebd3735d63c193da354331f756c1cedb..dabf6e782a376f47957b8de045e3d483075fe5d4 100644 (file)
@@ -943,7 +943,7 @@ smbk5pwd_modules_init( smbk5pwd_t *pi )
 }
 
 static int
-smbk5pwd_db_init(BackendDB *be)
+smbk5pwd_db_init(BackendDB *be, ConfigReply *cr)
 {
        slap_overinst   *on = (slap_overinst *)be->bd_info;
        smbk5pwd_t      *pi;
@@ -958,7 +958,7 @@ smbk5pwd_db_init(BackendDB *be)
 }
 
 static int
-smbk5pwd_db_open(BackendDB *be)
+smbk5pwd_db_open(BackendDB *be, ConfigReply *cr)
 {
        slap_overinst   *on = (slap_overinst *)be->bd_info;
        smbk5pwd_t      *pi = (smbk5pwd_t *)on->on_bi.bi_private;
@@ -978,7 +978,7 @@ smbk5pwd_db_open(BackendDB *be)
 }
 
 static int
-smbk5pwd_db_destroy(BackendDB *be)
+smbk5pwd_db_destroy(BackendDB *be, ConfigReply *cr)
 {
        slap_overinst   *on = (slap_overinst *)be->bd_info;
        smbk5pwd_t      *pi = (smbk5pwd_t *)on->on_bi.bi_private;
index 24c1482c88ddad4ab9c513fbfd849e9449edb7bf..555ce64772c13eadbed820f8f75e7c4e1884372c 100644 (file)
@@ -24,4 +24,4 @@ slaptest             F                       d f              uv
        -v verbose
 
 ---
-$Header$
+$OpenLDAP$
diff --git a/doc/drafts/draft-haripriya-dynamicgroup-xx.txt b/doc/drafts/draft-haripriya-dynamicgroup-xx.txt
new file mode 100644 (file)
index 0000000..a68af29
--- /dev/null
@@ -0,0 +1,1400 @@
+
+
+
+Network Working Group                                       S. Haripriya
+Internet-Draft                                         Jaimon. Jose, Ed.
+Updates: 02 (if approved)                               Jim. Sermersheim
+Intended status: Standards Track                            Novell, Inc.
+Expires: July 9, 2007                                    January 5, 2007
+
+
+                    LDAP: Dynamic Groups for LDAPv3
+                    draft-haripriya-dynamicgroup-02
+
+Status of this Memo
+
+   By submitting this Internet-Draft, each author represents that any
+   applicable patent or other IPR claims of which he or she is aware
+   have been or will be disclosed, and any of which he or she becomes
+   aware will be disclosed, in accordance with Section 6 of BCP 79.
+
+   Internet-Drafts are working documents of the Internet Engineering
+   Task Force (IETF), its areas, and its working groups.  Note that
+   other groups may also distribute working documents as Internet-
+   Drafts.
+
+   Internet-Drafts are draft documents valid for a maximum of six months
+   and may be updated, replaced, or obsoleted by other documents at any
+   time.  It is inappropriate to use Internet-Drafts as reference
+   material or to cite them other than as "work in progress."
+
+   The list of current Internet-Drafts can be accessed at
+   http://www.ietf.org/ietf/1id-abstracts.txt.
+
+   The list of Internet-Draft Shadow Directories can be accessed at
+   http://www.ietf.org/shadow.html.
+
+   This Internet-Draft will expire on July 9, 2007.
+
+Copyright Notice
+
+   Copyright (C) The Internet Society (2007).
+
+
+
+
+
+
+
+
+
+
+
+
+
+Haripriya, et al.         Expires July 9, 2007                  [Page 1]
+\f
+Internet-Draft       LDAP: Dynamic Groups for LDAPv3        January 2007
+
+
+Abstract
+
+   This document describes the requirements, semantics, schema elements,
+   and operations needed for a dynamic group feature in LDAP.  A dynamic
+   group is defined here as a group object with a membership list of
+   distinguished names that is dynamically generated using LDAP search
+   criteria.  The dynamic membership list may then be interrogated by
+   LDAP search and compare operations, and may also be used to find the
+   groups that an object is a member of.  This feature eliminates a huge
+   amount of the administrative effort required today for maintaining
+   group memberships and role-based operations in large enterprises.
+
+
+Table of Contents
+
+   1.  Conventions used in this document  . . . . . . . . . . . . . .  4
+   2.  Introduction . . . . . . . . . . . . . . . . . . . . . . . . .  5
+   3.  Requirements of a dynamic group feature  . . . . . . . . . . .  6
+   4.  Schema and Semantic Definitions for Dynamic Groups . . . . . .  7
+     4.1.  Object Classes . . . . . . . . . . . . . . . . . . . . . .  7
+       4.1.1.  dynamicGroup . . . . . . . . . . . . . . . . . . . . .  7
+       4.1.2.  dynamicGroupOfUniqueNames  . . . . . . . . . . . . . .  7
+       4.1.3.  dynamicGroupAux  . . . . . . . . . . . . . . . . . . .  7
+       4.1.4.  dynamicGroupOfUniqueNamesAux . . . . . . . . . . . . .  7
+     4.2.  Attributes . . . . . . . . . . . . . . . . . . . . . . . .  8
+       4.2.1.  memberQueryURL . . . . . . . . . . . . . . . . . . . .  8
+       4.2.2.  excludedMember . . . . . . . . . . . . . . . . . . . . 11
+     4.3.  member . . . . . . . . . . . . . . . . . . . . . . . . . . 11
+     4.4.  uniqueMember . . . . . . . . . . . . . . . . . . . . . . . 11
+     4.5.  dgIdentity . . . . . . . . . . . . . . . . . . . . . . . . 11
+       4.5.1.  dgIdentity - Security implications . . . . . . . . . . 12
+   5.  Advertisement of support for dynamic groups  . . . . . . . . . 13
+   6.  Dynamic Group Operations . . . . . . . . . . . . . . . . . . . 14
+     6.1.  Existing Operations  . . . . . . . . . . . . . . . . . . . 14
+       6.1.1.  Access to resources in the directory . . . . . . . . . 14
+       6.1.2.  Reading a dynamic group object . . . . . . . . . . . . 14
+       6.1.3.  'Is Member Of' functionality . . . . . . . . . . . . . 15
+     6.2.  New Extensions . . . . . . . . . . . . . . . . . . . . . . 16
+       6.2.1.  Managing the static members of a dynamic group . . . . 16
+   7.  Performance Considerations . . . . . . . . . . . . . . . . . . 17
+     7.1.  Caching of Dynamic Members . . . . . . . . . . . . . . . . 17
+   8.  Security Considerations  . . . . . . . . . . . . . . . . . . . 18
+   9.  IANA Considerations  . . . . . . . . . . . . . . . . . . . . . 19
+   10. Conclusions  . . . . . . . . . . . . . . . . . . . . . . . . . 20
+   11. Normative References . . . . . . . . . . . . . . . . . . . . . 21
+   Appendix A.  Example Values for memberQueryURL . . . . . . . . . . 22
+   Appendix B.  Acknowledgments . . . . . . . . . . . . . . . . . . . 23
+   Authors' Addresses . . . . . . . . . . . . . . . . . . . . . . . . 24
+
+
+
+Haripriya, et al.         Expires July 9, 2007                  [Page 2]
+\f
+Internet-Draft       LDAP: Dynamic Groups for LDAPv3        January 2007
+
+
+   Intellectual Property and Copyright Statements . . . . . . . . . . 25
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Haripriya, et al.         Expires July 9, 2007                  [Page 3]
+\f
+Internet-Draft       LDAP: Dynamic Groups for LDAPv3        January 2007
+
+
+1.  Conventions used in this document
+
+   The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
+   "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
+   document are to be interpreted as described in [1].
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Haripriya, et al.         Expires July 9, 2007                  [Page 4]
+\f
+Internet-Draft       LDAP: Dynamic Groups for LDAPv3        January 2007
+
+
+2.  Introduction
+
+   The LDAP schema described in [4] defines two object classes:
+   'groupOfNames', and 'groupOfUniqueNames', that hold a static list of
+   distinguished names in their 'member' or 'uniqueMember' attributes
+   respectively, and are typically used to describe a group of objects
+   for various functions.  These grouping functions range from simple
+   group membership applications such as email distribution lists to
+   describing common authorization for a set of users The administration
+   and updating of these membership lists must be done by specifically
+   modifying the DN values in the member or uniqueMember attributes.
+   Thus, each time a change in membership happens, a process must exist
+   which adds or removes the particular entry's DN from the member
+   attribute.  For example, consider an organization, where the access
+   to its facilities is controlled by membership in a directory group.
+   Assume that all employees in a department have been added to the
+   group that provides access to the required department facility.  If
+   an employee moves from one department to another, the administrator
+   must remove the employee from one group and add him to another.
+   Similarly consider an organization that wants to provide access to
+   its facility, to both interns and employees on weekdays, but only to
+   employees on weekends.  It would be effort-consuming to achieve this
+   with static groups.
+
+   "Dynamic groups" are like normal groups, but they let one specify
+   criteria to be used for evaluating membership to a group; the
+   membership of the group is determined dynamically by the directory
+   servers involved.  This lets the group administrator define the
+   membership in terms of attributes, and let the DSAs worry about who
+   are the actual members.  This solution is more scalable and reduces
+   administrative costs.  This can also supplement static groups in LDAP
+   to provide flexibility to the user.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Haripriya, et al.         Expires July 9, 2007                  [Page 5]
+\f
+Internet-Draft       LDAP: Dynamic Groups for LDAPv3        January 2007
+
+
+3.  Requirements of a dynamic group feature
+
+   The following requirements SHOULD be met by a proposal for the
+   dynamic groups feature:
+
+   1.  Creation and administration of dynamic groups should be done
+       using normal LDAP operations.
+
+   2.  Applications must be able to use dynamic groups in the same way
+       that they are able to use static groups for listing members and
+       for membership evaluation.
+
+   3.  Interrogation of a dynamic group's membership should be done
+       using normal LDAP operations, and should be consistent.  This
+       means that all authorization identities with the same permission
+       to the membership attribute of a dynamic group (such as 'read')
+       should be presented with the same membership list.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Haripriya, et al.         Expires July 9, 2007                  [Page 6]
+\f
+Internet-Draft       LDAP: Dynamic Groups for LDAPv3        January 2007
+
+
+4.  Schema and Semantic Definitions for Dynamic Groups
+
+   The dynamic group classes are defined by the following schema
+
+4.1.  Object Classes
+
+   The following object classes MUST be supported, and their semantics
+   understood by the server, for it to support the dynamic groups
+   feature.
+
+4.1.1.  dynamicGroup
+
+   ( <OID.TBD> NAME 'dynamicGroup' SUP groupOfNames STRUCTURAL MAY
+   (memberQueryURL $ excludedMember $ dgIdentity ))
+
+   This structural object class is used to create a dynamic group
+   object.  It is derived from groupOfNames, which is defined in [4].
+
+4.1.2.  dynamicGroupOfUniqueNames
+
+   ( <OID.TBD> NAME 'dynamicGroupOfUniqueNames' SUP groupOfUniqueNames
+   STRUCTURAL MAY (memberQueryURL $ excludedMember $ dgIdentity ))
+
+   This structural object class is used to create a dynamic group object
+   whose membership list is held in a uniqueMember attribute.  It is
+   derived from groupOfUniqueNames, which is defined in [4].
+
+4.1.3.  dynamicGroupAux
+
+   ( <OID.TBD> NAME 'dynamicGroupAux' SUP groupOfNames AUXILIARY MAY
+   (memberQueryURL $ excludedMember $ dgIdentity ))
+
+   This auxiliary object class is used to convert an existing object to
+   a dynamic group or to create an object of another object class but
+   with dynamic group capabilities.  This is derived from groupOfNames
+   which is defined in [4].
+
+4.1.4.  dynamicGroupOfUniqueNamesAux
+
+  ( <OID.TBD> NAME 'dynamicGroupOfUniqueNamesAux' SUP groupOfUniqueNames
+  AUXILIARY MAY (memberQueryURL $ excludedMember $ dgIdentity ))
+
+   This auxiliary object class is used to convert an existing object to
+   a dynamic group of unique names or to create an object of another
+   object class but with dynamic group capabilities.  This is derived
+   from groupOfUniqueNames which is defined in [4].
+
+
+
+
+
+Haripriya, et al.         Expires July 9, 2007                  [Page 7]
+\f
+Internet-Draft       LDAP: Dynamic Groups for LDAPv3        January 2007
+
+
+4.2.  Attributes
+
+   The following attribute names MUST be supported by the server.
+
+4.2.1.  memberQueryURL
+
+   This attribute describes the membership of the list using an LDAPURL
+   [3].
+
+ (<OID.TBD> NAME 'memberQueryURL' SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
+
+   The value of memberQueryURL is encoded as an LDAPURL [3]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Haripriya, et al.         Expires July 9, 2007                  [Page 8]
+\f
+Internet-Draft       LDAP: Dynamic Groups for LDAPv3        January 2007
+
+
+   The BNF from [3] is listed here for reference.
+ldapurl = scheme COLON SLASH SLASH [host [COLON port]] [SLASH dn
+                     [QUESTION [attributes] [QUESTION [scope] [QUESTION [filter] [QUESTION
+                     extensions]]]]]
+                                ; <host> and <port> are defined
+                                ;   in Sections 3.2.2 and 3.2.3
+                                ;   of [RFC3986].
+                                ; <filter> is from Section 3 of
+                                ;   [RFC4515], subject to the
+                                ;   provisions of the
+                                ;   "Percent-Encoding" section
+                                ;   below.
+scheme      = "ldap"
+dn          = distinguishedName ; From Section 3 of [RFC4514],
+                                ; subject to the provisions of
+                                ; the "Percent-Encoding"
+                                ; section below.
+attributes  = attrdesc *(COMMA attrdesc)
+attrdesc    = selector *(COMMA selector)
+selector    = attributeSelector ; From Section 4.5.1 of
+                                ; [RFC4511], subject to the
+                                ; provisions of the
+                                ; "Percent-Encoding" section
+                                ; below.
+scope       = "base" / "one" / "sub"
+extensions  = extension *(COMMA extension)
+extension   = [EXCLAMATION] extype [EQUALS exvalue]
+extype      = oid               ; From section 1.4 of [RFC4512].
+exvalue     = LDAPString        ; From section 4.1.2 of
+                                ; [RFC4511], subject to the
+                                ; provisions of the
+                                ; "Percent-Encoding" section
+                                ; below.
+EXCLAMATION = %x21              ; exclamation mark ("!")
+SLASH       = %x2F              ; forward slash ("/")
+COLON       = %x3A              ; colon (":")
+QUESTION    = %x3F              ; question mark ("?")
+
+
+   For the purpose of evaluating dynamic members, the directory server
+   uses only the dn, scope, filter and extensions fields.  All remaining
+   fields are ignored if specified.  If other fields are specified, the
+   server SHALL ignore them and MAY omit them when presenting the value
+   to a client.  The dn is used to specify the base dn from which to
+   start the search for dynamic members.  The scope specifies the scope
+   with respect to the dn in which to search for dynamic members.  The
+   filter specifies the criteria with which to select objects for
+   dynamic membership.
+
+
+
+Haripriya, et al.         Expires July 9, 2007                  [Page 9]
+\f
+Internet-Draft       LDAP: Dynamic Groups for LDAPv3        January 2007
+
+
+4.2.1.1.  The x-chain extension
+
+   A new extension is defined for use of the memberQueryURL in dynamic
+   groups, named 'x-chain'. x-chain does not take a value.  When x-chain
+   is present, the server must follow any search continuation references
+   to other servers while searching for dynamic members.  When x-chain
+   is absent, the dynamic members computed will be only those that are
+   present on the server from which the search is made.  A directory
+   server supporting the memberQueryURL MAY support the x-chain
+   extension, thus the x-chain extension could be critical or non-
+   critical as specified by the '!' prefix to the extension type.
+
+4.2.1.2.  Semantics of multiple values for memberQueryURL
+
+   The memberQueryURL MAY have multiple values, and in that case, the
+   members of the dynamic group will be the union of the members
+   computed using each individual URL value.  This is useful in
+   specifying a group membership that is made up from subtrees rooted at
+   different base DNs, and possibly using different filters.
+
+4.2.1.3.  Condition of membership
+
+   An object O is a member of a dynamic group G if and only if
+
+   (( O is a value of the 'member' or 'uniqueMember' attribute of G)
+
+   OR
+
+   (( O is selected by the membership criteria specified in the
+   'memberQueryURL' attribute values of G)
+
+   AND
+
+   ( O is not listed in the 'excludedMember' attribute of G) ))
+
+   If a member M of a dynamic group G happens to be a dynamic or a
+   static group, the static or dynamic members of M SHALL NOT be
+   considered as members of G. M is a member of G though.
+
+   The last condition is imposed because
+
+   o  Recursively evaluating members of members may degrade the
+      performance of the server drastically.
+
+   o  Looping may occur particularly in situations where the search
+      chains across multiple-servers.
+
+
+
+
+
+Haripriya, et al.         Expires July 9, 2007                 [Page 10]
+\f
+Internet-Draft       LDAP: Dynamic Groups for LDAPv3        January 2007
+
+
+   o  Dynamic membership assertions (compare operation) cannot be
+      optimized if recursive memberships are allowed.  Without
+      recursion, comparisons can be made light-weight.
+
+4.2.2.  excludedMember
+
+   ( <OID.TBD> NAME 'excludedMember' SUP distinguishedName )
+
+   This attribute is used to exclude entries from being a dynamic member
+   of a dynamic group.  Thus an entry is a dynamic member of a dynamic
+   group if and only if it is selected by the member criteria specified
+   by the 'memberQueryURL' attribute or explicitly added to the member
+   or uniqueMember attribute, and it is not listed in the
+   'excludedMember' attribute.
+
+4.3.  member
+
+   ( 2.5.4.31 NAME 'member' SUP distinguishedName )
+
+   Defined in [4], this attribute is overloaded when used in the context
+   of a dynamic group.  It is used to explicitly specify static members
+   of a dynamic group.  If the same entry is listed in both the 'member'
+   and 'excludedMember' attributes, the 'member' overrides the
+   'excludedMember', and the entry is considered to be a member of the
+   group.  This attribute is also used to interrogate both the static
+   and dynamic member values of a dynamic group object.  Subclasses of
+   this attribute are NOT considered in this manner.
+
+4.4.  uniqueMember
+
+   ( 2.5.4.32 NAME 'uniqueMember' SUP distinguishedName )
+
+   Defined in [4], this attribute is overloaded when used in the context
+   of a dynamic group.  It is used to specify the static members of a
+   dynamic group.  If the same entry is listed in both the
+   'uniqueMember' and 'excludedMember' attributes, the 'uniqueMember'
+   overrides the 'excludedMember', and the entry is considered to be a
+   member of the group.  This attribute is also used to interrogate both
+   the static and dynamic member values of a dynamic group object.
+   Subclasses of this attribute are NOT considered in this manner.
+
+4.5.  dgIdentity
+
+   ( <OID.TBD> NAME 'identity' SUP distinguishedName SINGLE-VALUE )
+
+   In order to provide consistent results when processing the search
+   criteria, the server must use a single authorization identity.  If
+   the authorization of the bound identity is used, the membership list
+
+
+
+Haripriya, et al.         Expires July 9, 2007                 [Page 11]
+\f
+Internet-Draft       LDAP: Dynamic Groups for LDAPv3        January 2007
+
+
+   will vary, from identity to identity due to differing access
+   controls.  This may either be done by the server authenticating as
+   the dgIdentity prior to performing a search or compare operation, or
+   may be done by simply assuming the authorization of the dgIdentity
+   when performing those operations.  As server implementations vary, so
+   may the mechanisms to achieve consistent results through the use of
+   the dgIdentity.  In the case that the server authenticates as the
+   dgIdentity, it may be required by the server that this identity have
+   proper authentication credentials, and it may be required that this
+   identity reside in the DIB of the local server.
+
+   In the absence of an identity value, or in case the identity value
+   cannot be used, the server will process the memberQueryURL as the
+   anonymous identity.  This attribute MAY be supported, and represents
+   the identity the server will use for processing the memberQueryURL.
+
+4.5.1.  dgIdentity - Security implications
+
+   Because this attribute indirectly but effectively grants anyone with
+   read or compare access to the member or uniqueMember attribute
+   sufficient permission to gain a DN result set from the
+   memberQueryURL, server implementations SHOULD NOT allow this
+   attribute to be populated with the DN of any object that is not
+   administered by the identity making the change to this attribute.
+   For purposes of this document, to "administer an object" indicates
+   that the administrative identity has the ability to fully update the
+   access control mechanism in place the object in question.  As of this
+   writing, there is no way to describe further what it means to be
+   fully able to administer the access control mechanism for an object,
+   so this definition is left as implementation-specific.
+
+   This requirement will allow an entity that has privileges to
+   administer a particular subtree (meaning that entity can add, delete,
+   and update objects in that subtree), to place in the dgIdentity DNs
+   of only those objects it administers.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Haripriya, et al.         Expires July 9, 2007                 [Page 12]
+\f
+Internet-Draft       LDAP: Dynamic Groups for LDAPv3        January 2007
+
+
+5.  Advertisement of support for dynamic groups
+
+   If the dynamic groups schema is not present on an LDAP server, it
+   MUST be assumed that the dynamic groups feature is not supported.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Haripriya, et al.         Expires July 9, 2007                 [Page 13]
+\f
+Internet-Draft       LDAP: Dynamic Groups for LDAPv3        January 2007
+
+
+6.  Dynamic Group Operations
+
+6.1.  Existing Operations
+
+   The following operations SHOULD expose the dynamic groups
+   functionality.  These operations do not require any change in the
+   LDAP protocol to be exchanged between the client and server.
+
+6.1.1.  Access to resources in the directory
+
+   If access control items are set on a target resource object in the
+   directory, with the subject being a dynamic group object, then all
+   the members of the group object, including the dynamic members, will
+   get the same permissions on the target entry.  This would be the most
+   useful application of dynamic groups as seen by an administrator
+   because it lets the server control access to resources based on
+   dynamic membership to a trustee (subject of ACI) of the resource.
+   The way to specify a dynamic ACL is currently implementation
+   specific, as there is no common ACL definition for LDAP, and hence
+   will be dealt with in a separate document or later (TO BE DONE).
+
+6.1.2.  Reading a dynamic group object
+
+   When the member attributes of a dynamic group object is listed by the
+   client using an LDAP search operation, the member values returned
+   SHOULD contain both the static and dynamic members of the group
+   object.  This functionality will not require a change to the
+   protocol, and the clients need not be aware of dynamic groups to
+   exploit this functionality.  This feature is useful for clients that
+   determine access privileges to a resource by themselves, by reading
+   the members of a group object.  It will also be useful to
+   administrators who want to see the result of the query URL that they
+   set on the dynamic group entry.  Note that this overloads the
+   semantics of the 'member' and 'uniqueMember' attributes.  This could
+   lead to some surprises for the client .
+
+   for example: Clients that read the member attribute of a dynamic
+   group object and then attempt to remove values (which were dynamic)
+   could get an error specifying such a value was not there.
+
+   Example:
+
+   Let cn=dg1,o=myorg be a dynamic group object with the following
+   attributes stored in the directory.
+
+
+
+
+
+
+
+Haripriya, et al.         Expires July 9, 2007                 [Page 14]
+\f
+Internet-Draft       LDAP: Dynamic Groups for LDAPv3        January 2007
+
+
+      member: cn=admin,o=myorg
+
+      excludedMember: cn=guest,ou=finance,o=myorg
+
+      excludedMember: cn=robin,ou=finance,o=myorg
+
+      memberQueryURL:
+      ldap:///ou=finance,o=myorg??sub?(objectclass=organizationalPerson)
+
+   If there are 5 organizationalPerson objects under ou=finance,o=myorg
+   with common names bob, alice, john, robin, and guest, then the output
+   of a base-scope LDAP search at cn=dg1,o=myorg, with the attribute
+   list containing 'member' will be as follows:
+
+      dn: cn=dg1,o=myorg
+
+      member: cn=admin,o=myorg
+
+      member: cn=bob,ou=finance,o=myorg
+
+      member: cn=alice,ou=finance,o=myorg
+
+      member: cn=john,ou=finance,o=myorg
+
+6.1.3.  'Is Member Of' functionality
+
+   The LDAP compare operation allows one to discover whether a given DN
+   is in the membership list of a dynamic group.  Again, the server
+   SHOULD produce consistent results among different authorization
+   identities when processing this request, as long as those identities
+   have the same access to the member or uniqueMember attribute.  Using
+   the data from the example in Section 6.1.2, a compare on
+   cn=dg1,o=myorg, for the AVA member=cn=bob,ou=finance,o=myorg would
+   result in a response of compareTrue (assuming the bound identity was
+   authorized to compare the member attribute of cn=dg1,o=myorg).
+
+   Likewise, a search operation that contains an equalityMatch or
+   presence filter, naming the member or uniqueMember attribute as the
+   attribute (such as (member= cn=bob,ou=finance,o=myorg), or
+   (member=*)), will cause the server to evaluate this filter against
+   the rules given in Section 4.2.1.3 in the event that the search is
+   performed on a dynamic group object.  As of this writing, no other
+   matching rules exist for the distinguished name syntax, thus no
+   requirements beyond equalityMatch are given here.
+
+
+
+
+
+
+
+Haripriya, et al.         Expires July 9, 2007                 [Page 15]
+\f
+Internet-Draft       LDAP: Dynamic Groups for LDAPv3        January 2007
+
+
+6.2.  New Extensions
+
+   The following new extensions are added for dynamic group support.
+
+6.2.1.  Managing the static members of a dynamic group
+
+   Because a dynamic group overloads the semantics of the member and
+   uniqueMember attributes, a mechanism is needed to retrieve the static
+   values found in these attributes for management purposes.  To serve
+   this need, a new attribute option is defined here called 'x-static'.
+   Attribute options are discussed in Section 2.5 of [2].  This option
+   SHALL only be specified with the 'member' or 'uniqueMember'
+   attribute.  When the LDAP server does not understand the semantics of
+   this option on a given attribute, the option SHOULD be ignored.  This
+   attribute option is only used to affect the transmitted values, and
+   does not impose sub-typing semantics on the attribute.
+
+   This option MAY be specified by a client during a search request in
+   the list of attributes to be returned, i.e. member;x-static.  In this
+   case, the server SHALL only return those members of the dynamic group
+   that are statically listed as values of the member or uniqueMember
+   attribute.  The evaluation process listed in Section 9 SHALL NOT be
+   used to populate the values to be returned.
+
+   This option MAY be specified is either an equalityMatch or presence
+   search filter.  In this case, the server evaluates only the values
+   statically listed in the member or uniqueMember attribute, and does
+   not apply the evaluation process listed in Section 9.
+
+   This option MAY be specified in update operations such as add and
+   modify, but SHOULD be ignored, as its presence is semantically the
+   same as its non-presence.
+
+   Note to user: Performing a search to read a dynamic group, with a
+   filter item such as (member=*), and specifying member;x-static, may
+   result in a search result entry that has no member attribute.  This
+   may seem counter-intuitive.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Haripriya, et al.         Expires July 9, 2007                 [Page 16]
+\f
+Internet-Draft       LDAP: Dynamic Groups for LDAPv3        January 2007
+
+
+7.  Performance Considerations
+
+   When the x-chain extension is present on the memberQueryURL, the
+   server MUST follow any search continuation references to other
+   servers while searching for dynamic members.  This may be expensive
+   and slow in a true distributed environment.  The dynamicGroup
+   implementation can consider a distributed caching feature to improve
+   the performance.  An outline of such a distributed caching is given
+   below.
+
+7.1.  Caching of Dynamic Members
+
+   Since the dynamic members of a group are computed every time the
+   group is accessed, the performance could be affected.  An
+   implementation of dynamic groups can get around this problem by
+   caching the computed members of a dynamic group locally and using the
+   cached data subsequently.  One way to do this is to create pseudo-
+   objects for each dynamic group on every server that holds an object
+   that is a dynamic member of the group.  With this, the computation of
+   the dynamic members of a group reduces to the task of reading the
+   pseudo-objects from each server.  These pseudo-objects need to be
+   linked from the original dynamic group to speed up the member
+   computation.  Also, since these are cached objects, appropriate
+   timeouts need to be associated with the cache after which the cache
+   should be invalidated or refreshed
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Haripriya, et al.         Expires July 9, 2007                 [Page 17]
+\f
+Internet-Draft       LDAP: Dynamic Groups for LDAPv3        January 2007
+
+
+8.  Security Considerations
+
+   This document discusses the use of one object as the identity
+   (Section 4.5) with which to read information for another object.  If
+   the creation of the dgIdentity attribute is uncontrolled, an intruder
+   could potentially create a dynamic group with the identity of, say,
+   the administrator, to be able to read the directory as the
+   administrator, and see information which would be otherwise
+   unavailable to him.  Thus, a person adding an object as identity of a
+   dynamic group should have appropriate permissions on the object being
+   added as identity.
+
+   This document also discusses using dynamic memberships to provide
+   access for resources in a directory.  As the dynamic members are not
+   created by the administrator, there could be surprises for the
+   administrator in the form of certain objects getting access to
+   certain resources through dynamic membership, which the administrator
+   never intended.  So the administrator should be wary of such
+   problems.  The administrator could view the memberships and make sure
+   that anybody who is not supposed to be a member of a group is added
+   to the excludedMember list.
+
+   Denial of service attacks can be launched on an LDAP server, by
+   repeatedly searching for a dynamic group with a large membership list
+   and listing the member attribute.  A more effective form of denial of
+   service attack could be launched by making searches of the form
+   (member="somedn") at the top of tree and closing the client
+   connection as soon as the search starts.  Some administrative limits
+   be imposed to avoid such situations.
+
+   The dynamic groups feature could be potentially misused by a user to
+   circumvent any administrative size-limit restriction placed on the
+   server.  In order to search an LDAP server and obtain the names of
+   all the objects on the server irrespective of admin size-limit
+   restriction on the server, the LDAP user could create a dynamic group
+   with a memberQueryURL which matches all objects in the tree, and list
+   just that one object.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Haripriya, et al.         Expires July 9, 2007                 [Page 18]
+\f
+Internet-Draft       LDAP: Dynamic Groups for LDAPv3        January 2007
+
+
+9.  IANA Considerations
+
+   There are no IANA considerations.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Haripriya, et al.         Expires July 9, 2007                 [Page 19]
+\f
+Internet-Draft       LDAP: Dynamic Groups for LDAPv3        January 2007
+
+
+10.  Conclusions
+
+   This document discusses the syntax, semantics and usage of dynamic
+   groups in LDAPv3.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Haripriya, et al.         Expires July 9, 2007                 [Page 20]
+\f
+Internet-Draft       LDAP: Dynamic Groups for LDAPv3        January 2007
+
+
+11.  Normative References
+
+   [1]  Bradner, S., "Key words for use in RFCs to Indicate Requirement
+        Levels", BCP 14, RFC 2119, March 1997.
+
+   [2]  Zeilenga, K., "Lightweight Directory Access Protocol (LDAP):
+        Directory Information Models", RFC 4512, June 2006.
+
+   [3]  Smith, M. and T. Howes, "Lightweight Directory Access Protocol
+        (LDAP): Uniform Resource Locator", RFC 4516, June 2006.
+
+   [4]  Sciberras, A., "Lightweight Directory Access Protocol (LDAP):
+        Schema for User Applications", RFC 4519, June 2006.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Haripriya, et al.         Expires July 9, 2007                 [Page 21]
+\f
+Internet-Draft       LDAP: Dynamic Groups for LDAPv3        January 2007
+
+
+Appendix A.  Example Values for memberQueryURL
+
+   1.  This memberQueryURL value specifies the membership criteria for a
+       dynamic group entry as "all inetorgperson entries that also have
+       their title attribute set to 'manager', and are in the DIT-wide
+       subtree under ou=hr,o=myorg ".
+
+          memberQueryURL: ldap:///
+          ou=hr,o=myorg??sub?(&
+          (objectclass=inetorgperson)(title=manager))? x-chain
+
+   2.  This value lets the user specify the membership criteria for a
+       dynamic group entry as "all entries on the local server, that
+       either have unix accounts or belong to the unix department, and
+       are under the engineering container ".
+
+          memberQueryURL: ldap:///ou=eng,o=myorg??sub?
+          (|(objectclass=posixaccount)(department=unix))
+
+   3.  These values let the user specify the membership criteria as "all
+       inetorgperson entries on the local server, in either the
+       ou=eng,o=myorg or ou=support,o=myorg" subtrees.
+
+          memberQueryURL:
+          ldap:///ou=eng,o=myorg??sub?(objectclass=inetorgperson)
+
+          memberQueryURL:
+          ldap:///ou=support,o=myorg??sub?(objectclass=inetorgperson)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Haripriya, et al.         Expires July 9, 2007                 [Page 22]
+\f
+Internet-Draft       LDAP: Dynamic Groups for LDAPv3        January 2007
+
+
+Appendix B.  Acknowledgments
+
+   Funding for the RFC Editor function is currently provided by the
+   Internet Society.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Haripriya, et al.         Expires July 9, 2007                 [Page 23]
+\f
+Internet-Draft       LDAP: Dynamic Groups for LDAPv3        January 2007
+
+
+Authors' Addresses
+
+   Haripriya S
+   Novell, Inc.
+   49/1 & 49/3 Garvebhavi Palya,
+   7th Mile, Hosur Road
+   Bangalore, Karnataka  560068
+   India
+
+   Email: sharipriya@novell.com
+
+
+   Jaimon Jose (editor)
+   Novell, Inc.
+   49/1 & 49/3 Garvebhavi Palya,
+   7th Mile, Hosur Road
+   Bangalore, Karnataka  560068
+   India
+
+   Email: jjaimon@novell.com
+
+
+   Jim Sermersheim
+   Novell, Inc.
+   1800 South Novell Place
+   Provo, Utah  84606
+   US
+
+   Email: jimse@novell.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Haripriya, et al.         Expires July 9, 2007                 [Page 24]
+\f
+Internet-Draft       LDAP: Dynamic Groups for LDAPv3        January 2007
+
+
+Full Copyright Statement
+
+   Copyright (C) The Internet Society (2007).
+
+   This document is subject to the rights, licenses and restrictions
+   contained in BCP 78, and except as set forth therein, the authors
+   retain all their rights.
+
+   This document and the information contained herein are provided on an
+   "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS
+   OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND THE INTERNET
+   ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED,
+   INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE
+   INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED
+   WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+
+Intellectual Property
+
+   The IETF takes no position regarding the validity or scope of any
+   Intellectual Property Rights or other rights that might be claimed to
+   pertain to the implementation or use of the technology described in
+   this document or the extent to which any license under such rights
+   might or might not be available; nor does it represent that it has
+   made any independent effort to identify any such rights.  Information
+   on the procedures with respect to rights in RFC documents can be
+   found in BCP 78 and BCP 79.
+
+   Copies of IPR disclosures made to the IETF Secretariat and any
+   assurances of licenses to be made available, or the result of an
+   attempt made to obtain a general license or permission for the use of
+   such proprietary rights by implementers or users of this
+   specification can be obtained from the IETF on-line IPR repository at
+   http://www.ietf.org/ipr.
+
+   The IETF invites any interested party to bring to its attention any
+   copyrights, patents or patent applications, or other proprietary
+   rights that may cover technology that may be required to implement
+   this standard.  Please address the information to the IETF at
+   ietf-ipr@ietf.org.
+
+
+Acknowledgment
+
+   Funding for the RFC Editor function is provided by the IETF
+   Administrative Support Activity (IASA).
+
+
+
+
+
+Haripriya, et al.         Expires July 9, 2007                 [Page 25]
+\f
diff --git a/doc/drafts/draft-wahl-ldap-session-xx.txt b/doc/drafts/draft-wahl-ldap-session-xx.txt
new file mode 100644 (file)
index 0000000..ba1c732
--- /dev/null
@@ -0,0 +1,1120 @@
+
+
+
+Network Working Group                                            M. Wahl
+Internet-Draft                                     Informed Control Inc.
+Intended status: Standards Track                             May 9, 2007
+Expires: November 10, 2007
+
+
+                     LDAP Session Tracking Control
+                       draft-wahl-ldap-session-03
+
+Status of this Memo
+
+   By submitting this Internet-Draft, each author represents that any
+   applicable patent or other IPR claims of which he or she is aware
+   have been or will be disclosed, and any of which he or she becomes
+   aware will be disclosed, in accordance with Section 6 of BCP 79.
+
+   Internet-Drafts are working documents of the Internet Engineering
+   Task Force (IETF), its areas, and its working groups.  Note that
+   other groups may also distribute working documents as Internet-
+   Drafts.
+
+   Internet-Drafts are draft documents valid for a maximum of six months
+   and may be updated, replaced, or obsoleted by other documents at any
+   time.  It is inappropriate to use Internet-Drafts as reference
+   material or to cite them other than as "work in progress."
+
+   The list of current Internet-Drafts can be accessed at
+   http://www.ietf.org/ietf/1id-abstracts.txt.
+
+   The list of Internet-Draft Shadow Directories can be accessed at
+   http://www.ietf.org/shadow.html.
+
+   This Internet-Draft will expire on November 10, 2007.
+
+Copyright Notice
+
+   Copyright (C) The IETF Trust (2007).
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Wahl                    Expires November 10, 2007               [Page 1]
+\f
+Internet-Draft        LDAP Session Tracking Control             May 2007
+
+
+Abstract
+
+   Many network devices, application servers, and middleware components
+   of a enterprise software infrastructure generate some form of session
+   tracking identifiers, which are useful when analyzing activity and
+   accounting logs to group activity relating to a particular session.
+   This document discusses how Lightweight Directory Access Protocol
+   version 3 (LDAP) clients can include session tracking identifiers
+   with their LDAP requests.  This information is provided through
+   controls in the requests the clients send to LDAP servers.  The LDAP
+   server receiving these controls can include the session tracking
+   identifiers in the log messages it writes, enabling LDAP requests in
+   the LDAP server's logs to be correlated with activity in logs of
+   other components in the infrastructure.  The control also enables
+   session tracking information to be generated by LDAP servers and
+   returned to clients and other servers.  Three formats of session
+   tracking identifiers are defined in this document.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Wahl                    Expires November 10, 2007               [Page 2]
+\f
+Internet-Draft        LDAP Session Tracking Control             May 2007
+
+
+1.  Introduction
+
+   The majority of directory server implementations produce access logs
+   detailing each request they receive.  These logs can be read using
+   log parsing tools or specialized log viewer applications.  Typically
+   it will be possible, for each request logged by a directory server,
+   to determine the bind DN (or possibly another form of authentication
+   identity) of the client which sent the request to the server, and
+   many servers also log the IP address of the client that sent the
+   request.
+
+   In the original OSI architecture, it was envisaged that users might
+   interact with a directory service through specialized applications,
+   known as Directory User Agents, which were the clients of the
+   Directory Access Protocol.  Similarly, in early Internet directory
+   deployments, a majority of LDAP clients were desktop applications,
+   that used the LDAP protocol to search an enterprise directory for
+   address book/contact information.
+
+   Today, the majority of LDAP clients are embedded within middleware
+   and server applications.  Legacy address book protocols might be
+   gatewayed into LDAP, or a server might consult an LDAP server in
+   order to check a user's password or obtain their preferences.  While
+   the LDAP requests might result from a user's activity somewhere on
+   the network, it is rare for the user to be 'driving' the LDAP client,
+   and in most cases the user performing the activity is unaware that
+   LDAP requests are being generated on their behalf.
+
+   However, this information is important to directory system
+   administrators and auditors.  They may wish to determine who is
+   making use of the directory service, or track the source of unusual
+   requests.
+
+   When a directory server administrator reviews a log file produced by
+   a directory server that has been accessed only by clients that are
+   themselves middleware, where the end user does not interact with the
+   middleware directly, only through other kinds of servers (e.g.
+   application servers or remote access servers), it will be difficult
+   to correlate between the directory server's log and the logs of the
+   servers which made use of this directory to determine why the LDAP
+   requests were made and who were responsible for causing them.
+
+   Reasons for this include:
+
+   o  Directory servers are capable of performing many hundreds of
+      requests per second or more, and even with time synchronization
+      between the systems on which the directory server and middleware
+      are deployed, times of requests might not be logged accurately
+
+
+
+Wahl                    Expires November 10, 2007               [Page 3]
+\f
+Internet-Draft        LDAP Session Tracking Control             May 2007
+
+
+      enough to be able to correlate based on time: the server's logs
+      might be only to 1-second resolution.
+
+   o  A single function on a middleware server, such as "authenticate a
+      user", may result in multiple LDAP requests being generated in
+      order to perform that request.
+
+   o  Many high performance middleware servers implement connection
+      pooling, managing a set of persistent connections to each
+      directory server and multiplexing operations across the
+      connections.  Each connection will have the same source IP address
+      and bind DN.  If a particular activity causes multiple LDAP
+      requests to be generated, each LDAP request might be sent on a
+      different connection.  Also, as LDAP is an asynchronous protocol,
+      middleware servers may have more than one request in progress on
+      each connection, asynchronously sending requests to the directory
+      server on each connection and processing the responses in whatever
+      order they are received.
+
+   This document defines a new control for use in LDAPv3 [1] operation
+   requests.  This control contains session tracking information that
+   can be used to correlate log information present in the directory
+   server's log with the logs of other middleware servers.
+
+   The words "MUST", "SHOULD" and "MAY" are used as defined in RFC 2119
+   [2].
+
+1.1.  Motivation for session tracking
+
+   A typical enterprise deployment with an application indirectly
+   relying upon the directory might resemble:
+
+
+       +------+     +--------+       +----------+      +--------+
+       | User |     | Appli- |       | Auth./   | LDAP |  LDAP  |
+       |      +-----+ cation +-------+ Identity +------+ Server |
+       |      |     | Server |       | Provider |      |        |
+       |  A   |     |   B    |       |    C     |      |   D    |
+       +------+     +--------+       +----------+      +--------+
+
+
+   In this diagram, a user (A) makes some request of an application
+   server (B).  The application server might rely on an integrated or
+   external authentication provider in order to check the user's
+   authentication credentials, or might use an identity provider to
+   obtain profile information about the user.  This request might be
+   made through an API or a protocol other than LDAP, e.g.  RADIUS,
+   Kerberos, SMB, etc.  The authentication/identity provider (C) would
+
+
+
+Wahl                    Expires November 10, 2007               [Page 4]
+\f
+Internet-Draft        LDAP Session Tracking Control             May 2007
+
+
+   generate one or more LDAP requests and send them to an LDAP server
+   (D).
+
+   The LDAP server has the following information already available to it
+   through the LDAP protocol: the IP address and authentication
+   credentials of the authentication/identity provider (C).  If the
+   provider has included the Proxy Authorization Control [11], then the
+   LDAP server might also receive the Distinguished Name or
+   authorization identity of either the user (A) or the application
+   server (B), depending on how the authentication/identity provider (C)
+   uses the directory.  In order to obtain this distinguished name
+   however, the authentication/identity provider (C) might need to
+   perform one or more LDAP search or bind requests.  If there is no
+   entry in the directory corresponding to the identity of the user (A)
+   or the application server (B), then there is no way in the base LDAP
+   specification or the Proxy Authorization Control for the
+   authentication/identity provider (C) to describe the user (A) or the
+   application server (B) to the LDAP server (D).
+
+   If either the application server (B) or the authentication/identity
+   provider (C) have generated a session identifier for tracking the
+   interactions of the user (A) for a particular session, then it is
+   useful to include this information with the requests made to the
+   directory server, so that this session identifier will show up in the
+   directory server's logs.  That is the purpose of the control defined
+   in the next section.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Wahl                    Expires November 10, 2007               [Page 5]
+\f
+Internet-Draft        LDAP Session Tracking Control             May 2007
+
+
+2.  Control definition
+
+   There is currently no standard way of describing a session: there are
+   many different formats for a session identifier, and each application
+   that tracks sessions typically has its own semantics for what a
+   session means.  Thus, a control is defined using an extensible model,
+   in order to incorporate many different application's concepts and
+   formats of a session tracking identifier.
+
+   The value of the session identifier control encapsulates the
+   following four pieces of information: sessionSourceIp,
+   sessionSourceName, formatOID and sessionTrackingIdentifier.
+
+   The sessionSourceIp field is a US-ASCII string encoding of an IPv4 or
+   IPv6 [3] address of the component of the system which has generated a
+   session tracking identifier.  The purpose of this field is to enable
+   the directory server administrator, even if they do not have a log
+   parser that understands a particular session tracking identifier
+   format, to at least be able to identify the server that manages the
+   session.  Note that there is no guarantee of IP-level connectivity
+   between the directory server and the system which generated the
+   tracking identifier, and if Network Address Translation is being
+   used, the IP address in this field might be from a private use
+   address range.
+
+   The sessionSourceName field is a UTF-8 [4] encoded ISO 10646 [5] text
+   string.  This field describes the component of the system which has
+   generated a session tracking identifier.  The format of this field is
+   determined by the formatOID (discussed below); examples of contents
+   of a sessionSourceName field might be a hostname, a distinguished
+   name, or a web service address.  This contents of this field is not
+   intended to identify an end user; instead it identifies the server
+   using a name other than the server's IP address.
+
+   The formatOID is a US-ASCII encoded dotted decimal representation of
+   an OBJECT IDENTIFIER.  The OBJECT IDENTIFIER indicates the scheme
+   that is used to generate the sessionSourceName and
+   sessionTrackingIdentifier fields.  As there is currently no standard
+   scheme for session information, it is expected that there will be
+   many different formats carried within this control.  The OBJECT
+   IDENTIFIERs for three formats are presented in this document.
+
+   The sessionTrackingIdentifier field is a UTF-8 encoded ISO 10646
+   string.  The session identifier SHOULD be limited to whitespace and
+   printable characters; non-printing and control characters SHOULD NOT
+   be used, and byte sequences that are not legal UTF-8 MUST NOT be
+   used.  The syntax of the session identifier and its semantics (e.g.,
+   how values are compared for equality) are governed by the formatOID.
+
+
+
+Wahl                    Expires November 10, 2007               [Page 6]
+\f
+Internet-Draft        LDAP Session Tracking Control             May 2007
+
+
+   For example, the session identifier might be a simple string encoding
+   of a decimal counter, a username, a timestamp, a fragment of XML, or
+   it might be something else, depending on the format.
+
+2.1.  Formal definition
+
+   This document defines a single LDAP control.
+
+   The controlType is 1.3.6.1.4.1.21008.108.63.1, the criticality MUST
+   be either FALSE or absent, and the controlValue MUST be present.  The
+   controlValue OCTET STRING is always present and contains the bytes of
+   the BER [6] encoding of a value of the ASN.1 data type
+   SessionIdentifierControlValue, defined as follows:
+
+      LDAP-Session-Identifier-Control
+      DEFINITIONS IMPLICIT TAGS ::=
+      BEGIN
+
+      LDAPString ::= OCTET STRING -- UTF-8 encoded
+      LDAPOID ::= OCTET STRING -- Constrained to numericoid
+
+      SessionIdentifierControlValue ::= SEQUENCE {
+           sessionSourceIp                 LDAPString,
+           sessionSourceName               LDAPString,
+           formatOID                       LDAPOID,
+           sessionTrackingIdentifier       LDAPString
+      }
+
+      END
+
+   The sessionSourceIp element SHOULD NOT be longer than 42 characters
+   (the length necessary for a string representation of an IPv6
+   address), and MUST NOT be longer than 128 characters.  Each character
+   will be encoded into a single byte.  If the IP address of the system
+   which generated the session tracking identifier is not known, the
+   sessionSourceIp element SHOULD be of zero length.
+
+   The sessionSourceName element SHOULD NOT be longer than 1024
+   characters, and MUST NOT be longer than 65536 bytes.  Note that in
+   the UTF-8 encoding a character MAY be encoded into more than one
+   byte.  If no other addressing information about that system is known
+   or relevant to the format, the sessionSourceName element SHOULD be of
+   zero length.
+
+   The formatOID element MUST contain only the US-ASCII encodings of the
+   ISO 10646 characters FULL STOP and DIGIT ZERO through DIGIT NINE
+   (0x2E, 0x30-0x39).  The formatOID element MUST NOT be of zero length,
+   and SHOULD NOT be longer than 1024 characters.
+
+
+
+Wahl                    Expires November 10, 2007               [Page 7]
+\f
+Internet-Draft        LDAP Session Tracking Control             May 2007
+
+
+   The sessionTrackingIdentifier field MAY be of zero length (although
+   this might not be useful).  There is no upper bound on the
+   sessionTrackingIdentifier, but it is suggested that values SHOULD NOT
+   be longer than 65536 characters without prior agreement with the
+   directory server administrator.  Note that in the UTF-8 encoding a
+   character MAY be encoded into more than one byte.
+
+2.2.  Use in LDAP
+
+   The control MAY be included in any LDAP operation.  The control has
+   order-dependent semantics.
+
+   A client might place the control on a message with a bindRequest,
+   searchRequest, modifyRequest, addRequest, delRequest, modDNRequest,
+   compareRequest or extendedReq.  A client MAY include multiple
+   controls of this type in a single request.  This enables the client
+   to incorporate multiple distinct session tracking identifiers with
+   different formats.
+
+   When a network service is proxying or chaining LDAP, in which the
+   service receives an incoming LDAP request from a client and from this
+   generates one or more requests to other LDAP servers, the service
+   SHOULD include any controls of this type that it received from
+   clients in requests it generates, without modification.  A service
+   MAY silently remove a control if that control would violate security
+   policy.  If the service has its own session state identifier, it
+   SHOULD include the session identifier control it generates in the
+   Controls SEQUENCE after any session identifier controls received by
+   clients.  (If there are multiple proxies involved, each will add
+   their own session state to the end of the controls list).
+
+   A server might place the control on message with a bindResponse,
+   searchResDone, modifyResponse, addResponse, delResponse,
+   modDNResponse, compareResponse, extendedResp or intermediateResponse.
+   The server can include the control in the response regardless of
+   whether the client included a control in the request or not.  (The
+   control in a response is unsolicited, and a client which does not
+   recognize the control or a session tracking format can safely ignore
+   the control, as discussed in the following section).  A server MAY
+   include multiple controls of this type in a response.
+
+2.3.  Extensibility considerations
+
+   The following section of this document defines 3 possible formats,
+   and it is expected that applications MAY define their own formats to
+   represent session tracking identifiers already implemented.
+
+   An application developer or server developer who wishes to transfer
+
+
+
+Wahl                    Expires November 10, 2007               [Page 8]
+\f
+Internet-Draft        LDAP Session Tracking Control             May 2007
+
+
+   their implementation's format for session tracking identifier within
+   an LDAP control MUST choose a new, unique, OBJECT IDENTIFIER to
+   represent this format.
+
+   The format determines the semantics of the sessionSourceName string,
+   and the sessionTrackingIdentifier string.
+
+   In general, when an LDAP server that has session tracking logging
+   enabled receives one or more of these controls with a request, the
+   server SHOULD include all fields of all of the controls with the
+   logging information for the request.
+
+   A LDAP server that supports third-party or extensible log parsing
+   tools SHOULD NOT reject or ignore a control if the formatOID value is
+   not recognized, as it is expected that applications may include
+   session tracking identifiers and want to make this information
+   available to log parsers for correlation purposes, even if the
+   directory server does not need to make any use of this information.
+
+   However, if the LDAP server does not recognize the control, the
+   control is not properly formatted, or the LDAP client is not
+   authorized to use this control, the LDAP server SHOULD ignore the
+   control and process the request as if the control had not been
+   included.
+
+   When an LDAP client receives a response that includes this control,
+   the behavior depends on the client implementation.  Clients SHOULD
+   silently ignore controls with formats they do not recognize, and
+   process the response as if the control had not been included.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Wahl                    Expires November 10, 2007               [Page 9]
+\f
+Internet-Draft        LDAP Session Tracking Control             May 2007
+
+
+3.  Session tracking format definitions
+
+   This section defines three session tracking formats that can be used
+   within the session tracking control: two for RADIUS accounting, and
+   one based on usernames.  Other formats can be defined in other
+   documents.
+
+3.1.  Formats for use with RADIUS accounting
+
+   This section defines two possible session tracking formats, that can
+   be used in LDAP clients that are part of or used by RADIUS servers
+   [7].
+
+   With formatOID set to 1.3.6.1.4.1.21008.108.63.1.1 within the control
+   value, the sessionTrackingIdentifier SHOULD contain the value of the
+   Acct-Session-Id RADIUS attribute (type 44), as defined in RFC 2866
+   [8].  (RFC 2866 section 5.5 states that the Acct-Session-Id SHOULD
+   contain UTF-8 encoded ISO 10646 characters.)
+
+   With formatOID set to 1.3.6.1.4.1.21008.108.63.1.2 within the control
+   value, the sessionTrackingIdentifier SHOULD contain the value of the
+   Acct-Multi-Session-Id RADIUS attribute (type 50), as defined in RFC
+   2866 [8].  (RFC 2866 section 5.11 states that the
+   Acct-Multi-Session-Id SHOULD contain UTF-8 encoded ISO 10646
+   characters.)
+
+   In both of these two formats, the value of the sessionSourceIp field
+   SHOULD contain either a string encoding value of the IPv4 address
+   from the NAS-IP-Address RADIUS attribute (type 4), or a string
+   encoding of the IPv6 address from the value of the NAS-IPv6-Address
+   RADIUS attribute (type 95) as defined in RFC 3162 [9].  The value of
+   the sessionSourceName field SHOULD contain a string encoding the
+   value of the NAS-Identifier RADIUS attribute (type 32), if present,
+   or be of zero length if the NAS-Identifier RADIUS attribute was not
+   provided or was not in a recognized format.
+
+3.2.  Format for username accounting
+
+   This section defines another possible session tracking format that
+   can be used in LDAP clients that are part of applications which
+   identify users with simple string usernames.
+
+   With formatOID set to 1.3.6.1.4.1.21008.108.63.1.3 within the control
+   value, the sessionTrackingIdentifier SHOULD contain a username that
+   has already been authenticated by the application that is generating
+   the session.  This format SHOULD NOT be used for purported names,
+   where the application has not verified that the username is valid.
+
+
+
+
+Wahl                    Expires November 10, 2007              [Page 10]
+\f
+Internet-Draft        LDAP Session Tracking Control             May 2007
+
+
+   The sessionSourceName field SHOULD contain the hostname where that
+   application is running, or be of zero length if the hostname is not
+   known.
+
+   The username SHOULD be a SASL authorization identity string, as
+   described in section 3.4.1 of RFC 4422 [10].  It is expected that
+   these usernames are not globally unique, but are only unique within
+   the context of a particular application or particular enterprise.  A
+   username need not be a distinguished name, and an implementation
+   receiving a control in this format MUST NOT assume that the contents
+   of the sessionTrackingIdentifier can be parsed as a distinguished
+   name.
+
+   A control with this format differs from the Proxied Authorization
+   Control as defined in RFC 4370 [11], as the presence of this session
+   identifier control on a request SHOULD NOT influence the directory
+   server's access control decision of whether or how to perform that
+   request.
+
+   Note that this format does not provide any information to
+   differentiate between multiple sessions or periods of interaction by
+   the same user.  It is primarily intended for deployments which merely
+   need to be able to tie each directory operation to they identity of
+   the user whose activities caused the operation request to be
+   generated, even if the user might not even be represented in the
+   directory where the operations are being performed.
+
+3.2.1.  Example
+
+   For example, if an application server "app.example.com" with IPv4
+   address "192.0.2.1" had authenticated an user with name "bloggs", and
+   then sent a search request to the LDAP directory in order to obtain
+   some public information on service configuration intending to provide
+   it to that user, the application might include a session identifier
+   control.  The SessionIdentifierControlValue would have the following
+   ASN.1 value prior to encoding:
+
+
+      {  -- SEQUENCE
+         "192.0.2.1",                    -- sessionSourceIp
+         "app.example.com",              -- sessionSourceName
+         "1.3.6.1.4.1.21008.108.63.1.3", -- formatOID
+         "bloggs"                        -- sessionTrackingIdentifier
+      }
+
+
+
+
+
+
+
+Wahl                    Expires November 10, 2007              [Page 11]
+\f
+Internet-Draft        LDAP Session Tracking Control             May 2007
+
+
+   The session identifier control would be sent with controlType
+   1.3.6.1.4.1.21008.108.63.1, criticality FALSE, and the controlValue
+   the BER encoding of the SessionIdentifierControlValue.  The control
+   included with the LDAP request would resemble:
+
+
+      {  -- SEQUENCE
+         "1.3.6.1.4.1.21008.108.63.1", -- controlType
+         FALSE,                        -- criticality
+         '304204093139322e302e322e31040f6170702e6578616d706c652e636f6d
+          041c312e332e362e312e342e312e32313030382e3130382e36332e312e33
+          0406626c6f676773'H           -- controlValue
+      }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Wahl                    Expires November 10, 2007              [Page 12]
+\f
+Internet-Draft        LDAP Session Tracking Control             May 2007
+
+
+4.  Security Considerations
+
+   The session identifier controls used in this document are not
+   intended as a security control or proxy authentication mechanism, and
+   SHOULD NOT be used within a directory server to influence the
+   operation processing behavior.
+
+   Malicious clients might attempt to provide false or misleading
+   information in directory server logs through the use of this control.
+   LDAP servers SHOULD implement access checks which limit whether
+   session identifier information provided by a client is logged.  LDAP
+   servers which implement this control SHOULD permit the administrator
+   of the directory server to configure that this control is ignored
+   unless the request containing the control was received from a client
+   that been authenticated.  LDAP servers which implement this control
+   SHOULD permit the administrator of the directory server to configure
+   that this control is ignored unless the client is authorized to use
+   this or related controls, such as the Proxied Authorization Control
+   [11].  Session identifier information from clients which do not meet
+   the server's access check requirement SHOULD be silently discarded.
+
+   In some formats, session tracking identifiers may contain personal-
+   identifiable information, such as usernames or client IP addresses.
+   Unless data link, network or transport level encryption is being
+   used, this information might be visible to attackers monitoring the
+   network segments across which this information is being transmitted.
+   Implementations of LDAP clients which include this control in
+   requests sent to directory servers SHOULD support the use of
+   underlying security services that establish connection
+   confidentiality before the control is sent, such as a SASL mechanism
+   that negotiates a security layer, or the Start TLS operation.
+
+   Correlation of activities across multiple servers can enable
+   administrators and monitoring tools to construct a more accurate
+   picture of user behavior.  In particular, this tracking control could
+   be used to determine the set of applications and services with which
+   a particular user has had interactions.  Thus, this control would not
+   be appropriate to deployments intending to anonymize directory
+   requests.  Session formats containing personal identifiable
+   information SHOULD NOT be used between systems in different
+   organizations where there is no existing agreement between those
+   organizations on privacy protection.
+
+   A value of the session tracking control might contain internal IP
+   addresses, hostnames and other identifiers that reveal the structure
+   of an enterprise network.  A network service that generates its own
+   sessions SHOULD NOT send a session tracking control to a directory
+   server that is under different administration or in a different
+
+
+
+Wahl                    Expires November 10, 2007              [Page 13]
+\f
+Internet-Draft        LDAP Session Tracking Control             May 2007
+
+
+   security enclave from itself.  A network service that is an LDAP
+   client and also either receives requests over another protocol that
+   contains session tracking identifiers or is proxying incoming LDAP
+   requests SHOULD NOT forward received session tracking identifiers to
+   a directory server that is under different administration or in a
+   different security enclave from itself.  A packet inspecting firewall
+   that permits outgoing LDAP requests from an enterprise network SHOULD
+   silently remove any session tracking controls from requests that are
+   being sent to directory servers outside of the enterprise network for
+   which there is not a preexisting policy configured to allow the
+   session tracking control to be sent to that directory server.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Wahl                    Expires November 10, 2007              [Page 14]
+\f
+Internet-Draft        LDAP Session Tracking Control             May 2007
+
+
+5.  IANA Considerations
+
+   This control will be registered as follows:
+
+      Subject: Request for LDAP Protocol Mechanism Registration
+
+      Object Identifier: 1.3.6.1.4.1.21008.108.63.1
+
+      Description: Session Tracking Identifier
+
+      Person & email address to contact for further information:
+      Mark Wahl <Mark.Wahl@informed-control.com>
+
+      Usage: Control
+
+      Specification: (I-D) RFC XXXX
+
+      Author/Change Controller: Mark Wahl
+
+
+   The OBJECT IDENTIFIER for particular session identifier formats
+   defined for other applications need not be registered with IANA.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Wahl                    Expires November 10, 2007              [Page 15]
+\f
+Internet-Draft        LDAP Session Tracking Control             May 2007
+
+
+6.  Acknowledgments
+
+   This control was inspired by conversations with Greg Lavender.  Neil
+   Wilson provided useful feedback on this document.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Wahl                    Expires November 10, 2007              [Page 16]
+\f
+Internet-Draft        LDAP Session Tracking Control             May 2007
+
+
+7.  References
+
+7.1.  Normative References
+
+   [1]   Zeilenga, K., "Lightweight Directory Access Protocol (LDAP):
+         Technical Specification Road Map", RFC 4510, June 2006.
+
+   [2]   Bradner, S., "Key words for use in RFCs to Indicate Requirement
+         Levels", RFC 2119, BCP 14, March 1997.
+
+   [3]   Hinden, R., "IP Version 6 Addressing Architecture", RFC 1884,
+         January 1996.
+
+   [4]   Yergeau, F., "UTF-8, a transformation format of ISO 10646",
+         RFC 3629, November 2003.
+
+   [5]   "Universal Multiple-Octet Coded Character Set (UCS) -
+         Architecture and Basic Multilingual Plane, ISO/IEC 10646-1:
+         1993".
+
+   [6]   "ITU-T Rec. X.690 (07/2002) | ISO/IEC 8825-1:2002, "Information
+         technology - ASN.1 encoding rules: Specification of Basic
+         Encoding Rules (BER), Canonical Encoding Rules (CER) and
+         Distinguished Encoding Rules (DER)", 2002.".
+
+   [7]   Rigney, C., "Remote Authentication Dial In User Service
+         (RADIUS)", RFC 2865, June 2000.
+
+   [8]   Rigney, C., "RADIUS Accounting", RFC 2866, June 2000.
+
+   [9]   Aboba, B., "RADIUS and IPv6", RFC 3162, August 2001.
+
+   [10]  Melnikov, A., "Simple Authentication and Security Layer
+         (SASL)", RFC 4422, June 2006.
+
+7.2.  Informative References
+
+   [11]  Weltman, R., "Lightweight Directory Access Protocol (LDAP)
+         Proxied Authorization Control", RFC 4370, February 2006.
+
+
+
+
+
+
+
+
+
+
+
+
+Wahl                    Expires November 10, 2007              [Page 17]
+\f
+Internet-Draft        LDAP Session Tracking Control             May 2007
+
+
+Appendix A.  Copyright
+
+   Copyright (C) The IETF Trust (2007).  This document is subject to the
+   rights, licenses and restrictions contained in BCP 78, and except as
+   set forth therein, the authors retain all their rights.  This
+   document and the information contained herein are provided on an "AS
+   IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS OR
+   IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND THE INTERNET
+   ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED,
+   INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE
+   INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED
+   WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Wahl                    Expires November 10, 2007              [Page 18]
+\f
+Internet-Draft        LDAP Session Tracking Control             May 2007
+
+
+Author's Address
+
+   Mark Wahl
+   Informed Control Inc.
+   PO Box 90626
+   Austin, TX  78709
+   US
+
+   Email: mark.wahl@informed-control.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Wahl                    Expires November 10, 2007              [Page 19]
+\f
+Internet-Draft        LDAP Session Tracking Control             May 2007
+
+
+Full Copyright Statement
+
+   Copyright (C) The IETF Trust (2007).
+
+   This document is subject to the rights, licenses and restrictions
+   contained in BCP 78, and except as set forth therein, the authors
+   retain all their rights.
+
+   This document and the information contained herein are provided on an
+   "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS
+   OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY, THE IETF TRUST AND
+   THE INTERNET ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF
+   THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED
+   WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+
+Intellectual Property
+
+   The IETF takes no position regarding the validity or scope of any
+   Intellectual Property Rights or other rights that might be claimed to
+   pertain to the implementation or use of the technology described in
+   this document or the extent to which any license under such rights
+   might or might not be available; nor does it represent that it has
+   made any independent effort to identify any such rights.  Information
+   on the procedures with respect to rights in RFC documents can be
+   found in BCP 78 and BCP 79.
+
+   Copies of IPR disclosures made to the IETF Secretariat and any
+   assurances of licenses to be made available, or the result of an
+   attempt made to obtain a general license or permission for the use of
+   such proprietary rights by implementers or users of this
+   specification can be obtained from the IETF on-line IPR repository at
+   http://www.ietf.org/ipr.
+
+   The IETF invites any interested party to bring to its attention any
+   copyrights, patents or patent applications, or other proprietary
+   rights that may cover technology that may be required to implement
+   this standard.  Please address the information to the IETF at
+   ietf-ipr@ietf.org.
+
+
+Acknowledgment
+
+   Funding for the RFC Editor function is provided by the IETF
+   Administrative Support Activity (IASA).
+
+
+
+
+
+Wahl                    Expires November 10, 2007              [Page 20]
+\f
index 84065c8dfc50a0d530c125ada5300207c5955beb..3341290cdd6f9cb8727fafa03bd7946bce13c4c8 100644 (file)
@@ -5,13 +5,13 @@
 
 
 INTERNET-DRAFT                                   Kurt D. Zeilenga
-Intended Category: Standard Track                OpenLDAP Foundation
-Expires in six months                            5 March 2006
+Intended Category: Standard Track                Isode Limited
+Expires in six months                            14 February 2007
 
 
 
                      The LDAP Don't Use Copy Control
-                 <draft-zeilenga-ldap-dontusecopy-02.txt>
+                 <draft-zeilenga-ldap-dontusecopy-04.txt>
 
 
 Status of this Memo
@@ -21,7 +21,7 @@ Status of this Memo
   document.  Distribution of this memo is unlimited.  Technical
   discussion of this document will take place on the IETF LDAP
   Extensions mailing list <ldapext@ietf.org>.  Please send editorial
-  comments directly to the author <Kurt@OpenLDAP.org>.
+  comments directly to the author <Kurt.Zeilenga@Isode.COM>.
 
   By submitting this Internet-Draft, each author represents that any
   applicable patent or other IPR claims of which he or she is aware have
@@ -38,13 +38,13 @@ Status of this Memo
   or to cite them other than as "work in progress."
 
   The list of current Internet-Drafts can be accessed at
-  http://www.ietf.org/1id-abstracts.html
+  http://www.ietf.org/1id-abstracts.html.
 
   The list of Internet-Draft Shadow Directories can be accessed at
-  http://www.ietf.org/shadow.html
+  http://www.ietf.org/shadow.html.
 
 
-  Copyright (C) The Internet Society (2006).  All Rights Reserved.
+  Copyright (C) The IETF Trust (2007).  All Rights Reserved.
 
   Please see the Full Copyright section near the end of this document
   for more information.
@@ -57,7 +57,7 @@ Status of this Memo
 
 Zeilenga               LDAP Don't Use Copy Control              [Page 1]
 \f
-INTERNET-DRAFT     draft-zeilenga-ldap-dontusecopy-02       5 March 2006
+INTERNET-DRAFT     draft-zeilenga-ldap-dontusecopy-04   14 February 2007
 
 
 Abstract
@@ -71,7 +71,7 @@ Abstract
 1.  Background and Intended Usage
 
   This document defines the Lightweight Directory Access Protocol (LDAP)
-  [Roadmap] Don't Use Copy control extension.  The control may be
+  [RFC4510] Don't Use Copy control extension.  The control may be
   attached to request messages to indicate that copied (replicated or
   cached) information [X.500] should not be used in providing service.
   This control is based upon the X.511 [X.511] dontUseCopy service
@@ -94,14 +94,14 @@ Abstract
 
 3.  The Don't Use Copy Control
 
-  The Don't Use Copy control is an LDAP Control [Protocol] whose
+  The Don't Use Copy control is an LDAP Control [RFC4511] whose
   controlType is IANA-ASSIGNED-OID and controlValue is absent.  The
   criticality MUST be TRUE.  There is no corresponding response control.
 
   The control is appropriate for both LDAP interrogation operations,
-  including Compare and Search operations [Protocol].  It is
+  including Compare and Search operations [RFC4511].  It is
   inappropriate for all other operations, including Abandon, Bind,
-  Delete, Modify, ModifyDN, StartTLS, and Unbind operations [Protocol].
+  Delete, Modify, ModifyDN, StartTLS, and Unbind operations [RFC4511].
 
   When the control is attached to an LDAP request, the requested
   operation MUST NOT be performed on copied information.  That is, the
@@ -113,7 +113,7 @@ Abstract
 
 Zeilenga               LDAP Don't Use Copy Control              [Page 2]
 \f
-INTERNET-DRAFT     draft-zeilenga-ldap-dontusecopy-02       5 March 2006
+INTERNET-DRAFT     draft-zeilenga-ldap-dontusecopy-04   14 February 2007
 
 
   is not available (either locally or through chaining), the server MUST
@@ -121,6 +121,12 @@ INTERNET-DRAFT     draft-zeilenga-ldap-dontusecopy-02       5 March 2006
   be better able to service the request or return an appropriate result
   code (e.g., unwillingToPerform).
 
+  Servers implementing this technical specification SHOULD publish the
+  object identifier IANA-ASSIGNED-OID as a value of the
+  'supportedControl' attribute [RFC4512] in their root DSE.  A server
+  MAY choose to advertise this extension only when the client is
+  authorized to use it.
+
 
 4.  Security Considerations
 
@@ -131,9 +137,9 @@ INTERNET-DRAFT     draft-zeilenga-ldap-dontusecopy-02       5 March 2006
   consider whether use of copied information, in particular security and
   policy information, may result insecure behavior.
 
-  Security considerations for the base operations [Protocol] extended by
+  Security considerations for the base operations [RFC4511] extended by
   this control, as well as general LDAP security considerations
-  [Roadmap], generally apply to implementation and use of this
+  [RFC4510], generally apply to implementation and use of this
   extension.
 
 
@@ -142,12 +148,12 @@ INTERNET-DRAFT     draft-zeilenga-ldap-dontusecopy-02       5 March 2006
 5.1.  Object Identifier
 
   It is requested that IANA assign upon Standards Action an LDAP Object
-  Identifier [BCP64bis] to identify the LDAP Don't Use Copy Control
+  Identifier [RFC4520] to identify the LDAP Don't Use Copy Control
   defined in this document.
 
       Subject: Request for LDAP Object Identifier Registration
       Person & email address to contact for further information:
-          Kurt Zeilenga <kurt@OpenLDAP.org>
+          Kurt Zeilenga <Kurt.Zeilenga@Isode.COM>
       Specification: RFC XXXX
       Author/Change Controller: IESG
       Comments:
@@ -155,23 +161,23 @@ INTERNET-DRAFT     draft-zeilenga-ldap-dontusecopy-02       5 March 2006
 
 5.2  LDAP Protocol Mechanism
 
-  Registration of this protocol mechanism [BCP64bis] is requested.
+  Registration of this protocol mechanism [RFC4520] is requested.
 
       Subject: Request for LDAP Protocol Mechanism Registration
-      Object Identifier: IANA-ASSIGNED-OID
-      Description: Don't Use Copy Control
-      Person & email address to contact for further information:
-          Kurt Zeilenga <kurt@openldap.org>
-      Usage: Control
-      Specification: RFC XXXX
 
 
 
 Zeilenga               LDAP Don't Use Copy Control              [Page 3]
 \f
-INTERNET-DRAFT     draft-zeilenga-ldap-dontusecopy-02       5 March 2006
+INTERNET-DRAFT     draft-zeilenga-ldap-dontusecopy-04   14 February 2007
 
 
+      Object Identifier: IANA-ASSIGNED-OID
+      Description: Don't Use Copy Control
+      Person & email address to contact for further information:
+          Kurt Zeilenga <Kurt.Zeilenga@Isode.COM>
+      Usage: Control
+      Specification: RFC XXXX
       Author/Change Controller: IESG
       Comments: none
 
@@ -180,9 +186,9 @@ INTERNET-DRAFT     draft-zeilenga-ldap-dontusecopy-02       5 March 2006
 6.  Author's Address
 
   Kurt D. Zeilenga
-  OpenLDAP Foundation
+  Isode Limited
 
-  Email: Kurt@OpenLDAP.org
+  Email: Kurt.Zeilenga@Isode.COM
 
 
 7. References
@@ -197,12 +203,14 @@ INTERNET-DRAFT     draft-zeilenga-ldap-dontusecopy-02       5 March 2006
   [RFC2119]     Bradner, S., "Key words for use in RFCs to Indicate
                 Requirement Levels", BCP 14 (also RFC 2119), March 1997.
 
-  [Roadmap]     Zeilenga, K. (editor), "LDAP: Technical Specification
-                Road Map", draft-ietf-ldapbis-roadmap-xx.txt, a work in
-                progress.
+  [RFC4510]     Zeilenga, K. (editor), "LDAP: Technical Specification
+                Road Map", RFC 4510, June 2006.
+
+  [RFC4511]     Sermersheim, J. (editor), "LDAP: The Protocol", RFC
+                4511, June 2006.
 
-  [Protocol]    Sermersheim, J. (editor), "LDAP: The Protocol",
-                draft-ietf-ldapbis-protocol-xx.txt, a work in progress.
+  [RFC4512]     Zeilenga, K. (editor), "LDAP: Directory Information
+                Models", RFC 4512, June 2006.
 
 
 7.2. Informative References
@@ -212,23 +220,26 @@ INTERNET-DRAFT     draft-zeilenga-ldap-dontusecopy-02       5 March 2006
                 -- Overview of concepts, models and services,"
                 X.500(1993) (also ISO/IEC 9594-1:1994).
 
+
+
+
+Zeilenga               LDAP Don't Use Copy Control              [Page 4]
+\f
+INTERNET-DRAFT     draft-zeilenga-ldap-dontusecopy-04   14 February 2007
+
+
   [X.511]       International Telecommunication Union -
                 Telecommunication Standardization Sector, "The
                 Directory: Abstract Service Definition", X.511(1993)
                 (also ISO/IEC 9594-3:1993).
 
-  [BCP64bis]    Zeilenga, K., "IANA Considerations for LDAP",
-                draft-ietf-ldapbis-bcp64-xx.txt, a work in progress.
-
-
+  [RFC4520]     Zeilenga, K., "Internet Assigned Numbers Authority
+                (IANA) Considerations for the Lightweight Directory
+                Access Protocol (LDAP)", RFC 4520, BCP 64, June 2006.
 
 
-Zeilenga               LDAP Don't Use Copy Control              [Page 4]
-\f
-INTERNET-DRAFT     draft-zeilenga-ldap-dontusecopy-02       5 March 2006
 
-
-Intellectual Property Rights
+Intellectual Property
 
   The IETF takes no position regarding the validity or scope of any
   Intellectual Property Rights or other rights that might be claimed to
@@ -256,7 +267,7 @@ Intellectual Property Rights
 
 Full Copyright
 
-  Copyright (C) The Internet Society (2006).
+  Copyright (C) The IETF Trust (2007).
 
   This document is subject to the rights, licenses and restrictions
   contained in BCP 78, and except as set forth therein, the authors
@@ -264,10 +275,18 @@ Full Copyright
 
   This document and the information contained herein are provided on an
   "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS
-  OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND THE INTERNET
-  ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED,
-  INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE
-  INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED
+  OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY, THE IETF TRUST AND
+
+
+
+Zeilenga               LDAP Don't Use Copy Control              [Page 5]
+\f
+INTERNET-DRAFT     draft-zeilenga-ldap-dontusecopy-04   14 February 2007
+
+
+  THE INTERNET ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS
+  OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF
+  THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED
   WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
 
 
@@ -279,5 +298,42 @@ Full Copyright
 
 
 
-Zeilenga               LDAP Don't Use Copy Control              [Page 5]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Zeilenga               LDAP Don't Use Copy Control              [Page 6]
 \f
diff --git a/doc/drafts/draft-zeilenga-ldap-managedit-xx.txt b/doc/drafts/draft-zeilenga-ldap-managedit-xx.txt
deleted file mode 100644 (file)
index f73f2a3..0000000
+++ /dev/null
@@ -1,675 +0,0 @@
-
-
-
-
-
-
-INTERNET-DRAFT                                   Kurt D. Zeilenga
-Intended Category: Experimental                  OpenLDAP Foundation
-Expires in six months                            27 February 2006
-
-
-
-            The LDAP Manage Directory Information Tree Control
-                  <draft-zeilenga-ldap-managedit-00.txt>
-
-
-Status of this Memo
-
-  This document is intended to be, after appropriate review and
-  revision, submitted to the RFC Editor for publication as an
-  Experimental document.   Distribution of this memo is unlimited.
-  Technical discussion of this document will take place on the IETF LDAP
-  Extensions mailing list <ldapext@ietf.org>.  Please send editorial
-  comments directly to the author <Kurt@OpenLDAP.org>.
-
-  By submitting this Internet-Draft, each author represents that any
-  applicable patent or other IPR claims of which he or she is aware have
-  been or will be disclosed, and any of which he or she becomes aware
-  will be disclosed, in accordance with Section 6 of BCP 79.
-
-  Internet-Drafts are working documents of the Internet Engineering Task
-  Force (IETF), its areas, and its working groups. Note that other
-  groups may also distribute working documents as Internet-Drafts.
-
-  Internet-Drafts are draft documents valid for a maximum of six months
-  and may be updated, replaced, or obsoleted by other documents at any
-  time. It is inappropriate to use Internet-Drafts as reference material
-  or to cite them other than as "work in progress."
-
-  The list of current Internet-Drafts can be accessed at
-  http://www.ietf.org/1id-abstracts.html
-
-  The list of Internet-Draft Shadow Directories can be accessed at
-  http://www.ietf.org/shadow.html
-
-
-  Copyright (C) The Internet Society (2006).  All Rights Reserved.
-
-  Please see the Full Copyright section near the end of this document
-  for more information.
-
-
-
-
-
-
-
-Zeilenga                 LDAP Manage DIT Control                [Page 1]
-\f
-INTERNET-DRAFT      draft-zeilenga-ldap-managedit-00    27 February 2006
-
-
-Abstract
-
-  This document defines the Lightweight Directory Access Protocol (LDAP)
-  Manage Directory Information Tree (DIT) Control which allows a
-  directory user agent (a client) to request the directory service
-  temporarily relax enforcement of constraints of the X.500 models.
-
-
-1.  Background and Intended Use
-
-  Directory servers accessible via Lightweight Directory Access Protocol
-  (LDAP) [Roadmap] are expected to act in accordance with the X.500
-  series of ITU-T Recommendations.  In particular, servers are expected
-  to ensure the X.500 data and service models are not violated.
-
-  An LDAP server is expected to prevent modification of the structural
-  object class of an object [Models].  That is, the X.500 models do not
-  allow a 'person' object to be transformed into an
-  'organizationalPerson' object through modification of the object.
-  Instead, the 'person' object must be deleted and then a new
-  'organizationalPerson' object created in its place.  This approach,
-  aside from being inconvient, is problematic for a number reasons.
-  First, as LDAP does not have a standardized method for performing the
-  two operations in a single transaction, the intermediate directory
-  state (after the delete, before the add) is visible to other clients,
-  which may lead to undesirable client behavior.  Second, attributes
-  such as entryUUID [entryUUID] will reflect the object was replaced,
-  not transformed.
-
-  An LDAP server is expected to prevent clients from modifying values of
-  NO-USER-MODIFICATION attributes [Models].  For instance, an entry is
-  not allowed to assign or modify the value of the entryUUID attribute.
-  However, where an administrator is restoring a previously existing
-  object, for instance when repartitioning data between directory
-  servers or when migrating from one vendor server product to another,
-  it may be desirable to allow the client to assign or modify the value
-  of the entryUUID attribute.
-
-  This document specifies the Manage Directory Information Tree (DIT)
-  control.  The Manage DIT control may be attached to LDAP requests to
-  update the DIT to request DIT restrictions be temporarily relaxed
-  during the performance of the requested DIT update.  The server is
-  however to ensure the resulting directory state is valid.
-
-  Use of this control is expected that use of this extension will be
-  restricted by administrative and/or access controls.  It is intended
-  to be used by directory administrators.
-
-
-
-
-Zeilenga                 LDAP Manage DIT Control                [Page 2]
-\f
-INTERNET-DRAFT      draft-zeilenga-ldap-managedit-00    27 February 2006
-
-
-  This extension is considered experimental as it is not yet clear
-  whether it adequately addresses directory administrators' needs for
-  flexible mechanisms for managing directory objects.  It is hoped that
-  after suitable amount of time, either this extension or a suitable
-  replacement will be standardization.
-
-
-1.1. Terminology
-
-  Protocol elements are described using ASN.1 [X.680] with implicit
-  tags.  The term "BER-encoded" means the element is to be encoded using
-  the Basic Encoding Rules [X.690] under the restrictions detailed in
-  Section 5.2 of [Protocol].
-
-  The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
-  "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
-  document are to be interpreted as described in BCP 14 [RFC2119].
-
-  DSA stands for Directory System Agent, a server.  DSE stands for DSA-
-  specific Entry.
-
-
-2.  The Manage DIT Control
-
-  The Manage DIT control is an LDAP Control [Protocol] whose controlType
-  is IANA-ASSIGNED-OID, controlValue is empty, and the criticality of
-  TRUE.
-
-  There is no corresponding response control.
-
-  The control is appropriate for all LDAP update requests, including
-  add, delete, modify, and modifyDN (rename) [Protocol].
-
-  The presence of the Manage DIT control in an LDAP update request
-  indicates the server temporarily relax X.500 model contraints during
-  performance of the directory update.
-
-  The server may restrict use of this control and/or limit the extent of
-  the relaxation provided based upon local policy or factors.
-
-  The server is obligated to ensure the resulting directory state is
-  consistent with the X.500 models.  For instance, the server ensure
-  that values of attributes conform to the value syntax.
-
-  It is noted that while this extension may be used to add or modify
-  objects in a manner which violate the controlling subschema, the
-  presence of objects in the DIT is not inconsistent with the X.500
-  models.  For instance, an object created prior to establshment of a
-
-
-
-Zeilenga                 LDAP Manage DIT Control                [Page 3]
-\f
-INTERNET-DRAFT      draft-zeilenga-ldap-managedit-00    27 February 2006
-
-
-  DIT content rule may contain an attribute now precluded by the current
-  controlling DIT Content Rule.
-
-  Servers implementing this technical specification SHOULD publish the
-  object identifier IANA-ASSIGNED-OID as a value of the
-  'supportedControl' attribute [Models] in their root DSE.  A server MAY
-  choose to advertise this extension only when the client is authorized
-  to use it.
-
-
-3.  Use Cases
-
-3.1. Object metamorphism
-
-  In absence of this control, an attempt to modify an object's
-  'objectClass' in a manner which cause a change in the structural
-  object class of the object would normally lead to an
-  objectClassModsProhibited error [Protocol].  The presence of the
-  Manage DIT control in the modify request requests the change be
-  allowed.  If the server is willing and able to allow the change in the
-  structural object class of the object.
-
-  For instance, to change an 'organization' object into an
-  'organizationalUnit' object, a client could issue the following LDAP
-  request:
-
-      dn: o=Unit,dc=example,dc=net
-      control: IANA-ASSIGNED-OID
-      changetype: modify
-      delete: objectClass
-      objectClass: organization
-      -
-      add: objectClass
-      objectClass: organizationalUnit
-      -
-
-  In this case, the server is expected to either effect the requested
-  change in the structural object class, including updating of the value
-  of the structural object class, or fail the operation.
-
-
-3.2. Inactive Attribute Types
-
-  In absence of the Manage DIT control, an attempt to add or modify
-  values to an attribute whose type has been marked inactive in the
-  controlling subschema (its attribute type description contains the
-  OBSOLETE field) [Models] normally results in a failure.
-
-
-
-
-Zeilenga                 LDAP Manage DIT Control                [Page 4]
-\f
-INTERNET-DRAFT      draft-zeilenga-ldap-managedit-00    27 February 2006
-
-
-  In the presence of the Manage DIT control, the server performs the
-  update operation as if the attribute's type is marked active in the
-  controlling subschema (its attribute type description does not contain
-  the OBSOLETE field).
-
-
-3.3. DIT Content Rules
-
-  In absence of the Manage DIT control, an attempt to include the name
-  (or OID) of an auxiliary class to an object's 'objectClass' which is
-  not allowed by the controlling DIT Content Rule would be disallowed
-  [Models].   Additionally, an attempt to add values of an attribute not
-  allowed (or explicitly precluded) by the DIT Content Rule would fail.
-
-  In presence of the Manage DIT control, the server performs the update
-  operation as if the controlling DIT Content Rule allowed any and all
-  known auxiliary classses to be present and allowed any and all known
-  attributes to be present (and precluded no attributes).
-
-
-3.4. DIT Structure Rules and Name Forms
-
-  In absence of the Manage DIT control, the service enforces DIT
-  structure rules and name form requirements of the controlling
-  subschema [Models].
-
-  In the presence of the Manage DIT control, the server performs the
-  update operation ignoring all DIT structure rules and name forms in
-  the controlling subschema.
-
-
-3.5. Modification of Nonconformant Objects
-
-  It is also noted that in absense of this control, modification of an
-  object which presently violates the controlling subschema will fail
-  unless the modification would result in the object conforming to the
-  controlling subschema.  That is, modifications of an non-conformant
-  object should result in a conformant object.
-
-  In the presence of this control, modifications of a non-conformant
-  object need not result in a conformant object.
-
-
-3.6. NO-USER-MODIFICATION attribute modification
-
-  In absence of this control, an attempt to modify values of a
-  NO-USER-MODIFICATION attribute would normally lead to a
-  constraintViolation or other appropriate error [Protocol].  In the
-
-
-
-Zeilenga                 LDAP Manage DIT Control                [Page 5]
-\f
-INTERNET-DRAFT      draft-zeilenga-ldap-managedit-00    27 February 2006
-
-
-  presence of the Manage DIT control in the update request requests the
-  modification be allowed.
-
-  Relaxation of the NO-USER-MODIFICATION constraint is not appropriate
-  for some operational attribute types. For instance, as the value of
-  the 'structuralObjectClass' is derived by the values of the
-  'objectClass' attribute, the 'structuralObjectClass' attribute type's
-  NO-USER-MODIFICATION contraint MUST NOT be relaxed.  To effect a
-  change in the structuralObjectClass class, values of objectClass
-  should be changed as discussed in Section 3.1.  Other attributes for
-  which the NO-USER-MODIFICATION constraint should not be relaxed
-  include 'entryDN' [EntryDN], 'subschemaSubentry' [Models], and
-  'collectiveAttributeSubentries' [RFC3671].
-
-  The subsections of this section discuss modification of various
-  operational attributes where their NO-USER-MODIFICATION constraint may
-  be relaxed.  Future documents may specify where NO-USER-MODIFICATION
-  constraints on other operational attribute may be relaxed.  In absence
-  of a document detailing that the NO-USER-MODIFICATION constraint on a
-  particular operational attribute may be relaxed, implementors SHOULD
-  assume relaxation of the constraint is not appropriate for that
-  attribute.
-
-
-3.1.1. entryUUID
-
-  To provide a value for the 'entryUUID' attribute on entry creation,
-  the client should issue an LDAP Add request with a Manage DIT control
-  providing the desired value.  For instance:
-
-      dn: ou=Unit,dc=example,dc=net
-      control: IANA-ASSIGNED-OID
-      changetype: add
-      objectClass: organizationalUnit
-      ou: Unit
-      entryUUID: 597ae2f6-16a6-1027-98f4-d28b5365dc14
-
-  In this case, the server is either to add the entry using the
-  provided 'entryUUID' value or fail the request.
-
-  To provide a replacement value for the 'entryUUID' after entry
-  creation, the client should issue an LDAP Modify request with a
-  Manage DIT control including an approrpiate change.  For instance:
-
-      dn: ou=Unit,dc=example,dc=net
-      control: IANA-ASSIGNED-OID
-      changetype: modify
-      replace: entryUUID
-
-
-
-Zeilenga                 LDAP Manage DIT Control                [Page 6]
-\f
-INTERNET-DRAFT      draft-zeilenga-ldap-managedit-00    27 February 2006
-
-
-      entryUUID: 597ae2f6-16a6-1027-98f4-d28b5365dc14
-      -
-
-  In this case, the server is either to replace the 'entryUUID' value
-  as requested or fail the request.
-
-
-3.2.2. createTimestamp
-
-  To provide a value for the 'createTimestamp' attribute on entry
-  creation, the client should issue an LDAP Add request with a Manage
-  DIT control providing the desired 'createTimestamp' value.  For
-  instance:
-
-      dn: ou=Unit,dc=example,dc=net
-      control: IANA-ASSIGNED-OID
-      changetype: add
-      objectClass: organizationalUnit
-      ou: Unit
-      createTimestamp: 20060101000000Z
-
-  In this case, the server is either to add the entry using the
-  provided 'createTimestamp' value or fail the request.
-
-  To provide a replacement value for the 'createTimestamp' after
-  entry creation, the client should issue an LDAP Modify request with
-  a Manage DIT control including an approrpiate change.  For instance:
-
-      dn: ou=Unit,dc=example,dc=net
-      control: IANA-ASSIGNED-OID
-      changetype: modify
-      replace: createTimestamp
-      createTimestamp: 20060101000000Z
-      -
-
-  In this case, the server is either to replace the 'createTimestamp'
-  value as requested or fail the request.
-
-  The server should ensure the requested 'createTimestamp' value is
-  appropriate.  In particular, it should fail the request if the
-  requested 'createTimestamp' value is in the future or is greater
-  than the value of the 'modifyTimestamp' attribute.
-
-
-3.2.3. modifyTimestamp
-
-  To provide a value for the 'modifyTimestamp' attribute on entry
-  creation, the client should issue an LDAP Add request with a Manage
-
-
-
-Zeilenga                 LDAP Manage DIT Control                [Page 7]
-\f
-INTERNET-DRAFT      draft-zeilenga-ldap-managedit-00    27 February 2006
-
-
-  DIT control providing the desired 'modifyTimestamp' value.  For
-  instance:
-
-      dn: ou=Unit,dc=example,dc=net
-      control: IANA-ASSIGNED-OID
-      changetype: add
-      objectClass: organizationalUnit
-      ou: Unit
-      modifyTimestamp: 20060101000000Z
-
-  In this case, the server is either to add the entry using
-  the provided 'modifyTimestamp' value or fail the request.
-
-  To provide a replacement value for the 'modifyTimestamp' after
-  entry creation, the client should issue an LDAP Modify
-  request with a Manage DIT control including an approrpiate
-  change.  For instance:
-
-      dn: ou=Unit,dc=example,dc=net
-      control: IANA-ASSIGNED-OID
-      changetype: modify
-      replace: modifyTimestamp
-      modifyTimestamp: 20060101000000Z
-      -
-
-  In this case, the server is either to replace the 'modifyTimestamp'
-  value as requested or fail the request.
-
-  The server should ensure the requested 'modifyTimestamp' value is
-  appropriate.  In particular, it should fail the request if the
-  requested 'modifyTimestamp' value is in the future or is less than
-  the value of the 'createTimestamp' attribute.
-
-
-  3.2.3. creatorsName and modifiersName
-
-  To provide a value for the 'creatorsName' and/or 'modifiersName'
-  attribute on entry creation, the client should issue an LDAP Add
-  request with a Manage DIT control providing the desired values.
-  For instance:
-
-      dn: ou=Unit,dc=example,dc=net
-      control: IANA-ASSIGNED-OID
-      changetype: add
-      objectClass: organizationalUnit
-      ou: Unit
-      creatorsName: cn=Jane Doe,dc=example,net
-      modifiersName: cn=Jane Doe,dc=example,net
-
-
-
-Zeilenga                 LDAP Manage DIT Control                [Page 8]
-\f
-INTERNET-DRAFT      draft-zeilenga-ldap-managedit-00    27 February 2006
-
-
-  In this case, the server is either to add the entry using
-  the provided values or fail the request.
-
-  To provide a replacement values after entry creation for either of
-  the 'creatorsName' or 'modifiersName' attributes or both, the
-  client should issue an LDAP Modify request with a Manage DIT control
-  including the approrpiate changes.  For instance:
-
-      dn: ou=Unit,dc=example,dc=net
-      control: IANA-ASSIGNED-OID
-      changetype: modify
-      replace: creatorsName
-      creatorsName: cn=Jane Doe,dc=example,net
-      -
-      replace: modifiersName
-      modifiersName: cn=Jane Doe,dc=example,net
-      -
-
-  In this case, the server is either to replace the provided
-  values as requested or fail the request.
-
-
-4.  Security Considerations
-
-  Use of this extension should be subject to appropriate administrative
-  and access controls.  Use of this mechanism is intended to be
-  restricted to directory administrators.
-
-  Security considerations for the base operations [Protocol] extended
-  by this control, as well as general LDAP security considerations
-  [Roadmap], generally apply to implementation and use of this
-  extension.
-
-
-5.  IANA Considerations
-
-5.1.  Object Identifier
-
-  It is requested that IANA assign a LDAP Object Identifier [BCP64bis]
-  to identify the LDAP Assertion Control defined in this document.
-
-      Subject: Request for LDAP Object Identifier Registration
-      Person & email address to contact for further information:
-          Kurt Zeilenga <kurt@OpenLDAP.org>
-      Specification: RFC XXXX
-      Author/Change Controller: Kurt Zeilenga <kurt@openldap.org>
-      Comments: Identifies the LDAP Manage DIT Control
-
-
-
-
-Zeilenga                 LDAP Manage DIT Control                [Page 9]
-\f
-INTERNET-DRAFT      draft-zeilenga-ldap-managedit-00    27 February 2006
-
-
-5.2  LDAP Protocol Mechanism
-
-  Registration of this protocol mechanism [BCP64bis] is requested.
-
-      Subject: Request for LDAP Protocol Mechanism Registration
-      Object Identifier: IANA-ASSIGNED-OID
-      Description: Manage DIT Control
-      Person & email address to contact for further information:
-          Kurt Zeilenga <kurt@openldap.org>
-      Usage: Control
-      Specification: RFC XXXX
-      Author/Change Controller: Kurt Zeilenga <kurt@openldap.org>
-      Comments: none
-
-
-6.  Author's Address
-
-  Kurt D. Zeilenga
-  OpenLDAP Foundation
-
-  Email: Kurt@OpenLDAP.org
-
-
-7. References
-
-  [[Note to the RFC Editor: please replace the citation tags used in
-  referencing Internet-Drafts with tags of the form RFCnnnn where
-  possible.]]
-
-
-7.1. Normative References
-
-  [RFC2119]     Bradner, S., "Key words for use in RFCs to Indicate
-                Requirement Levels", BCP 14 (also RFC 2119), March 1997.
-
-  [Roadmap]     Zeilenga, K. (editor), "LDAP: Technical Specification
-                Road Map", draft-ietf-ldapbis-roadmap-xx.txt, a work in
-                progress.
-
-  [Models]      Zeilenga, K. (editor), "LDAP: Directory Information
-                Models", draft-ietf-ldapbis-models-xx.txt, a work in
-                progress.
-
-
-
-7.2. Informative References
-
-  [BCP64bis]    Zeilenga, K., "IANA Considerations for LDAP",
-
-
-
-Zeilenga                 LDAP Manage DIT Control               [Page 10]
-\f
-INTERNET-DRAFT      draft-zeilenga-ldap-managedit-00    27 February 2006
-
-
-                draft-ietf-ldapbis-bcp64-xx.txt, a work in progress.
-
-  [EntryUUID]   Zeilenga, K., "The LDAP EntryUUID Operational
-                Attribute", draft-zeilenga-ldap-uuid-xx.txt, a work in
-                progress.
-
-  [RFC2849]     Good, G., "The LDAP Data Interchange Format (LDIF) -
-                Technical Specification", RFC 2849, June 2000.
-
-
-
-Intellectual Property Rights
-
-  The IETF takes no position regarding the validity or scope of any
-  Intellectual Property Rights or other rights that might be claimed to
-  pertain to the implementation or use of the technology described in
-  this document or the extent to which any license under such rights
-  might or might not be available; nor does it represent that it has
-  made any independent effort to identify any such rights.  Information
-  on the procedures with respect to rights in RFC documents can be found
-  in BCP 78 and BCP 79.
-
-  Copies of IPR disclosures made to the IETF Secretariat and any
-  assurances of licenses to be made available, or the result of an
-  attempt made to obtain a general license or permission for the use of
-  such proprietary rights by implementers or users of this specification
-  can be obtained from the IETF on-line IPR repository at
-  http://www.ietf.org/ipr.
-
-  The IETF invites any interested party to bring to its attention any
-  copyrights, patents or patent applications, or other proprietary
-  rights that may cover technology that may be required to implement
-  this standard.  Please address the information to the IETF at
-  ietf-ipr@ietf.org.
-
-
-
-Full Copyright
-
-  Copyright (C) The Internet Society (2006).
-
-  This document is subject to the rights, licenses and restrictions
-  contained in BCP 78, and except as set forth therein, the authors
-  retain all their rights.
-
-  This document and the information contained herein are provided on an
-  "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS
-  OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND THE INTERNET
-
-
-
-Zeilenga                 LDAP Manage DIT Control               [Page 11]
-\f
-INTERNET-DRAFT      draft-zeilenga-ldap-managedit-00    27 February 2006
-
-
-  ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED,
-  INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE
-  INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED
-  WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Zeilenga                 LDAP Manage DIT Control               [Page 12]
-\f
index 100a845bb65b647dc050283d5416ce6cc08f6360..9411c386a191f9deada2d056789307455e8ced2d 100644 (file)
@@ -5,13 +5,13 @@
 
 
 INTERNET-DRAFT                                      Kurt D. Zeilenga
-Intended Category: Standard Track                OpenLDAP Foundation
-Expires in six months                                   5 March 2006
+Intended Category: Standard Track                      Isode Limited
+Expires in six months                               14 February 2007
 
 
 
                           The LDAP No-Op Control
-                    <draft-zeilenga-ldap-noop-08.txt>
+                    <draft-zeilenga-ldap-noop-10.txt>
 
 
 Status of this Memo
@@ -21,7 +21,7 @@ Status of this Memo
   document.  Distribution of this memo is unlimited.  Technical
   discussion of this document will take place on the IETF LDAP
   Extensions mailing list <ldapext@ietf.org>.  Please send editorial
-  comments directly to the author <Kurt@OpenLDAP.org>.
+  comments directly to the author <Kurt.Zeilenga@Isode.COM>.
 
   By submitting this Internet-Draft, each author represents that any
   applicable patent or other IPR claims of which he or she is aware have
@@ -38,13 +38,13 @@ Status of this Memo
   or to cite them other than as "work in progress."
 
   The list of current Internet-Drafts can be accessed at
-  http://www.ietf.org/1id-abstracts.html
+  http://www.ietf.org/1id-abstracts.html.
 
   The list of Internet-Draft Shadow Directories can be accessed at
-  http://www.ietf.org/shadow.html
+  http://www.ietf.org/shadow.html.
 
 
-  Copyright (C) The Internet Society (2006).  All Rights Reserved.
+  Copyright (C) The IETF Trust (2007).  All Rights Reserved.
 
   Please see the Full Copyright section near the end of this document
   for more information.
@@ -57,7 +57,7 @@ Status of this Memo
 
 Zeilenga                   LDAP No-Op Control                   [Page 1]
 \f
-INTERNET-DRAFT         draft-zeilenga-ldap-noop-08          5 March 2006
+INTERNET-DRAFT         draft-zeilenga-ldap-noop-10      14 February 2007
 
 
 Abstract
@@ -71,7 +71,7 @@ Abstract
 1.  Overview
 
   It is often desirable to be able to determine if a directory operation
-  [Protocol] would successful complete or not without having the normal
+  [RFC4511] would successful complete or not without having the normal
   effect of the operation take place.  For example, an administrative
   client might want to verify that new user could update their entry
   (and not other entries) without the directory actually being updated.
@@ -79,7 +79,7 @@ Abstract
   auditing tools.
 
   This document defines the Lightweight Directory Access Protocol (LDAP)
-  [Roadmap] No-Op control extension.  The presence of the No-Op control
+  [RFC4510] No-Op control extension.  The presence of the No-Op control
   in an operation request message disables its normal effect upon the
   directory which operation would otherwise have.  Instead of updating
   the directory and returning the normal indication of success, the
@@ -87,7 +87,7 @@ Abstract
   noOperation resultCode (introduced below).
 
   For example, when the No-Op control is present in a LDAP modify
-  operation [Protocol], the server is do all processing necessary to
+  operation [RFC4511], the server is do all processing necessary to
   perform the operation without actually updating the directory.  If it
   detects an error during this processing, it returns a non-success
   (other than noOperation) resultCode as it normally would.  Otherwise,
@@ -113,18 +113,18 @@ Abstract
 
 Zeilenga                   LDAP No-Op Control                   [Page 2]
 \f
-INTERNET-DRAFT         draft-zeilenga-ldap-noop-08          5 March 2006
+INTERNET-DRAFT         draft-zeilenga-ldap-noop-10      14 February 2007
 
 
 2.  No-Op Control
 
-  The No-Op control is an LDAP Control [Protocol] whose controlType is
+  The No-Op control is an LDAP Control [RFC4511] whose controlType is
   IANA-ASSIGNED-OID and controlValue is absent.  Clients MUST provide a
   criticality value of TRUE to prevent unintended modification of the
   directory.
 
   The control is appropriate for request messages of LDAP Add, Delete,
-  Modify and ModifyDN operations [Protocol].  The control is also
+  Modify and ModifyDN operations [RFC4511].  The control is also
   appropriate for requests of extended operations which update the
   directory (or other data stores), such as Password Modify Extended
   Operation [RFC3062].  There is no corresponding response control.
@@ -145,7 +145,7 @@ INTERNET-DRAFT         draft-zeilenga-ldap-noop-08          5 March 2006
 
   Servers SHOULD indicate their support for this control by providing
   IANA-ASSIGNED-OID as a value of the 'supportedControl' attribute type
-  [Models] in their root DSE entry.  A server MAY choose to advertise
+  [RFC4512] in their root DSE entry.  A server MAY choose to advertise
   this extension only when the client is authorized to use this
   operation.
 
@@ -159,8 +159,8 @@ INTERNET-DRAFT         draft-zeilenga-ldap-noop-08          5 March 2006
   tools.
 
   Implementors of this LDAP extension should be familiar with security
-  considerations applicable to the LDAP operations [Protocol] extended
-  by this control, as well as general LDAP security considerations
+  considerations applicable to the LDAP operations [RFC4511] extended by
+  this control, as well as general LDAP security considerations
   [Roadmap].
 
 
@@ -169,19 +169,19 @@ INTERNET-DRAFT         draft-zeilenga-ldap-noop-08          5 March 2006
 
 Zeilenga                   LDAP No-Op Control                   [Page 3]
 \f
-INTERNET-DRAFT         draft-zeilenga-ldap-noop-08          5 March 2006
+INTERNET-DRAFT         draft-zeilenga-ldap-noop-10      14 February 2007
 
 
 4.  IANA Considerations
 
 4.1.  Object Identifier
 
-  It is requested that IANA assign an LDAP Object Identifier [BCP64bis]
+  It is requested that IANA assign an LDAP Object Identifier [RFC4520]
   to identify the LDAP No-Op Control defined in this document.
 
       Subject: Request for LDAP Object Identifier Registration
       Person & email address to contact for further information:
-          Kurt Zeilenga <kurt@OpenLDAP.org>
+          Kurt Zeilenga <Kurt.Zeilenga@Isode.COM>
       Specification: RFC XXXX
       Author/Change Controller: IESG
       Comments:
@@ -190,13 +190,13 @@ INTERNET-DRAFT         draft-zeilenga-ldap-noop-08          5 March 2006
 
 4.2  LDAP Protocol Mechanism
 
-  Registration of this protocol mechanism is requested [RFC3383].
+  Registration of this protocol mechanism is requested [RFC4520].
 
   Subject: Request for LDAP Protocol Mechanism Registration
   Object Identifier: IANA-ASSIGNED-OID
   Description: No-Op Control
   Person & email address to contact for further information:
-      Kurt Zeilenga <kurt@openldap.org>
+      Kurt Zeilenga <Kurt.Zeilenga@Isode.COM>
   Usage: Control
   Specification: RFC XXXX
   Author/Change Controller: IESG
@@ -209,7 +209,7 @@ INTERNET-DRAFT         draft-zeilenga-ldap-noop-08          5 March 2006
 
       Subject: LDAP Result Code Registration
       Person & email address to contact for further information:
-          Kurt Zeilenga <kurt@OpenLDAP.org>
+          Kurt Zeilenga <Kurt.Zeilenga@Isode.COM>
       Result Code Name: noOperation
       Specification: RFC XXXX
       Author/Change Controller: IESG
@@ -219,16 +219,16 @@ INTERNET-DRAFT         draft-zeilenga-ldap-noop-08          5 March 2006
 5.  Author's Address
 
   Kurt D. Zeilenga
-  OpenLDAP Foundation
+  Isode Limited
 
 
 
 Zeilenga                   LDAP No-Op Control                   [Page 4]
 \f
-INTERNET-DRAFT         draft-zeilenga-ldap-noop-08          5 March 2006
+INTERNET-DRAFT         draft-zeilenga-ldap-noop-10      14 February 2007
 
 
-  Email: Kurt@OpenLDAP.org
+  Email: Kurt.Zeilenga@Isode.COM
 
 
 6. References
@@ -243,16 +243,14 @@ INTERNET-DRAFT         draft-zeilenga-ldap-noop-08          5 March 2006
   [RFC2119]     Bradner, S., "Key words for use in RFCs to Indicate
                 Requirement Levels", BCP 14 (also RFC 2119), March 1997.
 
-  [Protocol]    Sermersheim, J. (editor), "LDAP: The Protocol",
-                draft-ietf-ldapbis-protocol-xx.txt, a work in progress.
+  [RFC4510]     Zeilenga, K. (editor), "LDAP: Technical Specification
+                Road Map", RFC 4510, June 2006.
 
-  [Roadmap]     Zeilenga, K. (editor), "LDAP: Technical Specification
-                Road Map", draft-ietf-ldapbis-roadmap-xx.txt, a work in
-                progress.
+  [RFC4511]     Sermersheim, J. (editor), "LDAP: The Protocol", RFC
+                4511, June 2006.
 
-  [Models]      Zeilenga, K. (editor), "LDAP: Directory Information
-                Models", draft-ietf-ldapbis-models-xx.txt, a work in
-                progress.
+  [RFC4512]     Zeilenga, K. (editor), "LDAP: Directory Information
+                Models", RFC 4512, June 2006.
 
 
 6.2. Informative References
@@ -268,23 +266,24 @@ INTERNET-DRAFT         draft-zeilenga-ldap-noop-08          5 March 2006
   [RFC3062]     Zeilenga, K., "LDAP Password Modify Extended Operation",
                 RFC 3062, February 2000.
 
-  [BCP64bis]    Zeilenga, K., "IANA Considerations for LDAP",
-                draft-ietf-ldapbis-bcp64-xx.txt, a work in progress.
+  [RFC4520]     Zeilenga, K., "Internet Assigned Numbers Authority
+                (IANA) Considerations for the Lightweight Directory
+                Access Protocol (LDAP)", RFC 4520, BCP 64, June 2006.
 
 
 
-Intellectual Property Rights
+Intellectual Property
 
   The IETF takes no position regarding the validity or scope of any
+  Intellectual Property Rights or other rights that might be claimed to
 
 
 
 Zeilenga                   LDAP No-Op Control                   [Page 5]
 \f
-INTERNET-DRAFT         draft-zeilenga-ldap-noop-08          5 March 2006
+INTERNET-DRAFT         draft-zeilenga-ldap-noop-10      14 February 2007
 
 
-  Intellectual Property Rights or other rights that might be claimed to
   pertain to the implementation or use of the technology described in
   this document or the extent to which any license under such rights
   might or might not be available; nor does it represent that it has
@@ -309,7 +308,7 @@ INTERNET-DRAFT         draft-zeilenga-ldap-noop-08          5 March 2006
 
 Full Copyright
 
-  Copyright (C) The Internet Society (2006).
+  Copyright (C) The IETF Trust (2007).
 
   This document is subject to the rights, licenses and restrictions
   contained in BCP 78, and except as set forth therein, the authors
@@ -317,10 +316,10 @@ Full Copyright
 
   This document and the information contained herein are provided on an
   "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS
-  OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND THE INTERNET
-  ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED,
-  INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE
-  INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED
+  OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY, THE IETF TRUST AND
+  THE INTERNET ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS
+  OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF
+  THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED
   WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
 
 
@@ -335,5 +334,6 @@ Full Copyright
 
 
 
+
 Zeilenga                   LDAP No-Op Control                   [Page 6]
 \f
diff --git a/doc/drafts/draft-zeilenga-ldap-relax.txt b/doc/drafts/draft-zeilenga-ldap-relax.txt
new file mode 100644 (file)
index 0000000..c656f9e
--- /dev/null
@@ -0,0 +1,675 @@
+
+
+
+
+
+
+INTERNET-DRAFT                                   Kurt D. Zeilenga
+Intended Category: Experimental                  Isode Limited
+Expires in six months                            14 February 2007
+
+
+
+                       The LDAP Relax Rules Control
+                    <draft-zeilenga-ldap-relax-01.txt>
+
+
+Status of this Memo
+
+  This document is intended to be, after appropriate review and
+  revision, submitted to the RFC Editor for publication as an
+  Experimental document.   Distribution of this memo is unlimited.
+  Technical discussion of this document will take place on the IETF LDAP
+  Extensions mailing list <ldapext@ietf.org>.  Please send editorial
+  comments directly to the author <Kurt.Zeilenga@Isode.COM>.
+
+  This document replaces draft-zeilenga-ldap-managedit-xx.txt.
+
+  By submitting this Internet-Draft, each author represents that any
+  applicable patent or other IPR claims of which he or she is aware have
+  been or will be disclosed, and any of which he or she becomes aware
+  will be disclosed, in accordance with Section 6 of BCP 79.
+
+  Internet-Drafts are working documents of the Internet Engineering Task
+  Force (IETF), its areas, and its working groups. Note that other
+  groups may also distribute working documents as Internet-Drafts.
+
+  Internet-Drafts are draft documents valid for a maximum of six months
+  and may be updated, replaced, or obsoleted by other documents at any
+  time. It is inappropriate to use Internet-Drafts as reference material
+  or to cite them other than as "work in progress."
+
+  The list of current Internet-Drafts can be accessed at
+  http://www.ietf.org/1id-abstracts.html.
+
+  The list of Internet-Draft Shadow Directories can be accessed at
+  http://www.ietf.org/shadow.html.
+
+
+  Copyright (C) The IETF Trust (2007).  All Rights Reserved.
+
+  Please see the Full Copyright section near the end of this document
+  for more information.
+
+
+
+
+
+Zeilenga                LDAP Relax Rules Control                [Page 1]
+\f
+INTERNET-DRAFT        draft-zeilenga-ldap-relax-01      14 February 2007
+
+
+Abstract
+
+  This document defines the Lightweight Directory Access Protocol (LDAP)
+  Relax Rules Control which allows a directory user agent (a client) to
+  request the directory service temporarily relax enforcement of various
+  data and service model rules.
+
+
+1.  Background and Intended Use
+
+  Directory servers accessible via Lightweight Directory Access Protocol
+  (LDAP) [RFC4510] are expected to act in accordance with the X.500
+  [X.500] series of ITU-T Recommendations.  In particular, servers are
+  expected to ensure the X.500 data and service models are not violated.
+
+  An LDAP server is expected to prevent modification of the structural
+  object class of an object [RFC4512].  That is, the X.500 models do not
+  allow a 'person' object to be transformed into an
+  'organizationalPerson' object through modification of the object.
+  Instead, the 'person' object must be deleted and then a new
+  'organizationalPerson' object created in its place.  This approach,
+  aside from being inconvient, is problematic for a number reasons.
+  First, as LDAP does not have a standardized method for performing the
+  two operations in a single transaction, the intermediate directory
+  state (after the delete, before the add) is visible to other clients,
+  which may lead to undesirable client behavior.  Second, attributes
+  such as 'entryUUID' [RFC4530] will reflect the object was replaced,
+  not transformed.
+
+  An LDAP server is expected to prevent clients from modifying values of
+  NO-USER-MODIFICATION attributes [RFC4512].  For instance, an entry is
+  not allowed to assign or modify the value of the 'entryUUID'
+  attribute.  However, where an administrator is restoring a previously
+  existing object, for instance when repartitioning data between
+  directory servers or when migrating from one vendor server product to
+  another, it may be desirable to allow the client to assign or modify
+  the value of the 'entryUUID' attribute.
+
+  This document defines the LDAP Relax Rules control.  This control may
+  be attached to LDAP requests to update the Directory Information Tree
+  (DIT) to request various data and service rules be temporarily relaxed
+  during the performance of the requested DIT update.  The server is
+  however to ensure the resulting directory state is valid.
+
+  Use of this control is expected that use of this extension will be
+  restricted by administrative and/or access controls.  It is intended
+  to be used primarily by directory administrators.
+
+
+
+
+Zeilenga                LDAP Relax Rules Control                [Page 2]
+\f
+INTERNET-DRAFT        draft-zeilenga-ldap-relax-01      14 February 2007
+
+
+  This extension is considered experimental as it is not yet clear
+  whether it adequately addresses directory administrators' needs for
+  flexible mechanisms for managing directory objects.  It is hoped that
+  after suitable amount of time, either this extension or a suitable
+  replacement will be standardization.
+
+
+1.1. Terminology
+
+  Protocol elements are described using ASN.1 [X.680] with implicit
+  tags.  The term "BER-encoded" means the element is to be encoded using
+  the Basic Encoding Rules [X.690] under the restrictions detailed in
+  Section 5.1 of [RFC4511].
+
+  The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
+  "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
+  document are to be interpreted as described in BCP 14 [RFC2119].
+
+  DSA stands for Directory System Agent, a server.  DSE stands for
+  DSA-specific Entry.
+
+
+2.  The Relax Rules Control
+
+  The Relax Rules control is an LDAP Control [RFC4511] whose controlType
+  is IANA-ASSIGNED-OID, controlValue is empty, and the criticality of
+  TRUE.
+
+  There is no corresponding response control.
+
+  The control is appropriate for all LDAP update requests, including
+  add, delete, modify, and modifyDN (rename) [RFC4511].
+
+  The presence of the Rules Rules control in an LDAP update request
+  indicates the server temporarily relax X.500 model contraints during
+  performance of the directory update.
+
+  The server may restrict use of this control and/or limit the extent of
+  the relaxation provided based upon local policy or factors.
+
+  The server is obligated to ensure the resulting directory state is
+  consistent with the X.500 models.  For instance, the server ensure
+  that values of attributes conform to the value syntax.
+
+  It is noted that while this extension may be used to add or modify
+  objects in a manner which violate the controlling subschema, the
+  presence of objects in the DIT is not inconsistent with the X.500
+  models.  For instance, an object created prior to establshment of a
+
+
+
+Zeilenga                LDAP Relax Rules Control                [Page 3]
+\f
+INTERNET-DRAFT        draft-zeilenga-ldap-relax-01      14 February 2007
+
+
+  DIT content rule may contain an attribute now precluded by the current
+  controlling DIT Content Rule.
+
+  Servers implementing this technical specification SHOULD publish the
+  object identifier IANA-ASSIGNED-OID as a value of the
+  'supportedControl' attribute [RFC4512] in their root DSE.  A server
+  MAY choose to advertise this extension only when the client is
+  authorized to use it.
+
+
+3.  Use Cases
+
+3.1. Object metamorphism
+
+  In absence of this control, an attempt to modify an object's
+  'objectClass' in a manner which cause a change in the structural
+  object class of the object would normally lead to an
+  objectClassModsProhibited error [RFC4511].  The presence of the Relax
+  Rules control in the modify request requests the change be allowed.
+  If the server is willing and able to allow the change in the
+  structural object class of the object.
+
+  For instance, to change an 'organization' object into an
+  'organizationalUnit' object, a client could issue the following LDAP
+  request:
+
+      dn: o=Unit,dc=example,dc=net
+      control: IANA-ASSIGNED-OID
+      changetype: modify
+      delete: objectClass
+      objectClass: organization
+      -
+      add: objectClass
+      objectClass: organizationalUnit
+      -
+
+  In this case, the server is expected to either effect the requested
+  change in the structural object class, including updating of the value
+  of the structural object class, or fail the operation.
+
+
+3.2. Inactive Attribute Types
+
+  In absence of the Relax Rules control, an attempt to add or modify
+  values to an attribute whose type has been marked inactive in the
+  controlling subschema (its attribute type description contains the
+  OBSOLETE field) [RFC4512] normally results in a failure.
+
+
+
+
+Zeilenga                LDAP Relax Rules Control                [Page 4]
+\f
+INTERNET-DRAFT        draft-zeilenga-ldap-relax-01      14 February 2007
+
+
+  In the presence of the Relax Rules control, the server performs the
+  update operation as if the attribute's type is marked active in the
+  controlling subschema (its attribute type description does not contain
+  the OBSOLETE field).
+
+
+3.3. DIT Content Rules
+
+  In absence of the Relax Rules control, an attempt to include the name
+  (or OID) of an auxiliary class to an object's 'objectClass' which is
+  not allowed by the controlling DIT Content Rule would be disallowed
+  [RFC4512].   Additionally, an attempt to add values of an attribute
+  not allowed (or explicitly precluded) by the DIT Content Rule would
+  fail.
+
+  In presence of the Relax Rules control, the server performs the update
+  operation as if the controlling DIT Content Rule allowed any and all
+  known auxiliary classses to be present and allowed any and all known
+  attributes to be present (and precluded no attributes).
+
+
+3.4. DIT Structure Rules and Name Forms
+
+  In absence of the Relax Rules control, the service enforces DIT
+  structure rules and name form requirements of the controlling
+  subschema [RFC4512].
+
+  In the presence of the Relax Rules control, the server performs the
+  update operation ignoring all DIT structure rules and name forms in
+  the controlling subschema.
+
+
+3.5. Modification of Nonconformant Objects
+
+  It is also noted that in absense of this control, modification of an
+  object which presently violates the controlling subschema will fail
+  unless the modification would result in the object conforming to the
+  controlling subschema.  That is, modifications of an non-conformant
+  object should result in a conformant object.
+
+  In the presence of this control, modifications of a non-conformant
+  object need not result in a conformant object.
+
+
+3.6. NO-USER-MODIFICATION attribute modification
+
+  In absence of this control, an attempt to modify values of a
+  NO-USER-MODIFICATION attribute [RFC4512] would normally lead to a
+
+
+
+Zeilenga                LDAP Relax Rules Control                [Page 5]
+\f
+INTERNET-DRAFT        draft-zeilenga-ldap-relax-01      14 February 2007
+
+
+  constraintViolation or other appropriate error [RFC4511].  In the
+  presence of the Relax Rules control in the update request requests the
+  modification be allowed.
+
+  Relaxation of the NO-USER-MODIFICATION constraint is not appropriate
+  for some operational attribute types. For instance, as the value of
+  the 'structuralObjectClass' is derived by the values of the
+  'objectClass' attribute, the 'structuralObjectClass' attribute type's
+  NO-USER-MODIFICATION contraint MUST NOT be relaxed.  To effect a
+  change in the structuralObjectClass class, values of objectClass
+  should be changed as discussed in Section 3.1.  Other attributes for
+  which the NO-USER-MODIFICATION constraint should not be relaxed
+  include 'subschemaSubentry' [RFC4512] and
+  'collectiveAttributeSubentries' [RFC3671].
+
+  The subsections of this section discuss modification of various
+  operational attributes where their NO-USER-MODIFICATION constraint may
+  be relaxed.  Future documents may specify where NO-USER-MODIFICATION
+  constraints on other operational attribute may be relaxed.  In absence
+  of a document detailing that the NO-USER-MODIFICATION constraint on a
+  particular operational attribute may be relaxed, implementors SHOULD
+  assume relaxation of the constraint is not appropriate for that
+  attribute.
+
+
+3.1.1. 'entryUUID' attribute
+
+  To provide a value for the 'entryUUID' [RFC4530] attribute on entry
+  creation, the client should issue an LDAP Add request with a Relax
+  Rules control providing the desired value.  For instance:
+
+      dn: ou=Unit,dc=example,dc=net
+      control: IANA-ASSIGNED-OID
+      changetype: add
+      objectClass: organizationalUnit
+      ou: Unit
+      entryUUID: 597ae2f6-16a6-1027-98f4-d28b5365dc14
+
+  In this case, the server is either to add the entry using the
+  provided 'entryUUID' value or fail the request.
+
+  To provide a replacement value for the 'entryUUID' after entry
+  creation, the client should issue an LDAP Modify request with a
+  Relax Rules control including an approrpiate change.  For instance:
+
+      dn: ou=Unit,dc=example,dc=net
+      control: IANA-ASSIGNED-OID
+      changetype: modify
+
+
+
+Zeilenga                LDAP Relax Rules Control                [Page 6]
+\f
+INTERNET-DRAFT        draft-zeilenga-ldap-relax-01      14 February 2007
+
+
+      replace: entryUUID
+      entryUUID: 597ae2f6-16a6-1027-98f4-d28b5365dc14
+      -
+
+  In this case, the server is either to replace the 'entryUUID' value
+  as requested or fail the request.
+
+
+3.2.2. createTimestamp
+
+  To provide a value for the 'createTimestamp' [RFC4512] attribute
+  on entry creation, the client should issue an LDAP Add request with
+  a Relax Rules control providing the desired 'createTimestamp'
+  value.  For instance:
+
+      dn: ou=Unit,dc=example,dc=net
+      control: IANA-ASSIGNED-OID
+      changetype: add
+      objectClass: organizationalUnit
+      ou: Unit
+      createTimestamp: 20060101000000Z
+
+  In this case, the server is either to add the entry using the
+  provided 'createTimestamp' value or fail the request.
+
+  To provide a replacement value for the 'createTimestamp' after
+  entry creation, the client should issue an LDAP Modify request with
+  a Relax Rules control including an approrpiate change.  For instance:
+
+      dn: ou=Unit,dc=example,dc=net
+      control: IANA-ASSIGNED-OID
+      changetype: modify
+      replace: createTimestamp
+      createTimestamp: 20060101000000Z
+      -
+
+  In this case, the server is either to replace the 'createTimestamp'
+  value as requested or fail the request.
+
+  The server should ensure the requested 'createTimestamp' value is
+  appropriate.  In particular, it should fail the request if the
+  requested 'createTimestamp' value is in the future or is greater
+  than the value of the 'modifyTimestamp' attribute.
+
+
+3.2.3. modifyTimestamp
+
+  To provide a value for the 'modifyTimestamp' [RFC4512] attribute
+
+
+
+Zeilenga                LDAP Relax Rules Control                [Page 7]
+\f
+INTERNET-DRAFT        draft-zeilenga-ldap-relax-01      14 February 2007
+
+
+  on entry creation, the client should issue an LDAP Add request with
+  a Relax Rules control providing the desired 'modifyTimestamp'
+  value.  For instance:
+
+      dn: ou=Unit,dc=example,dc=net
+      control: IANA-ASSIGNED-OID
+      changetype: add
+      objectClass: organizationalUnit
+      ou: Unit
+      modifyTimestamp: 20060101000000Z
+
+  In this case, the server is either to add the entry using
+  the provided 'modifyTimestamp' value or fail the request.
+
+  To provide a replacement value for the 'modifyTimestamp' after
+  entry creation, the client should issue an LDAP Modify
+  request with a Relax Rules control including an approrpiate
+  change.  For instance:
+
+      dn: ou=Unit,dc=example,dc=net
+      control: IANA-ASSIGNED-OID
+      changetype: modify
+      replace: modifyTimestamp
+      modifyTimestamp: 20060101000000Z
+      -
+
+  In this case, the server is either to replace the 'modifyTimestamp'
+  value as requested or fail the request.
+
+  The server should ensure the requested 'modifyTimestamp' value is
+  appropriate.  In particular, it should fail the request if the
+  requested 'modifyTimestamp' value is in the future or is less than
+  the value of the 'createTimestamp' attribute.
+
+
+  3.2.3. creatorsName and modifiersName
+
+  To provide a value for the 'creatorsName' and/or 'modifiersName'
+  [RFC4512] attribute on entry creation, the client should issue an
+  LDAP Add request with a Relax Rules control providing the desired
+  values.  For instance:
+
+      dn: ou=Unit,dc=example,dc=net
+      control: IANA-ASSIGNED-OID
+      changetype: add
+      objectClass: organizationalUnit
+      ou: Unit
+      creatorsName: cn=Jane Doe,dc=example,net
+
+
+
+Zeilenga                LDAP Relax Rules Control                [Page 8]
+\f
+INTERNET-DRAFT        draft-zeilenga-ldap-relax-01      14 February 2007
+
+
+      modifiersName: cn=Jane Doe,dc=example,net
+
+  In this case, the server is either to add the entry using
+  the provided values or fail the request.
+
+  To provide a replacement values after entry creation for either of
+  the 'creatorsName' or 'modifiersName' attributes or both, the
+  client should issue an LDAP Modify request with a Relax Rules control
+  including the approrpiate changes.  For instance:
+
+      dn: ou=Unit,dc=example,dc=net
+      control: IANA-ASSIGNED-OID
+      changetype: modify
+      replace: creatorsName
+      creatorsName: cn=Jane Doe,dc=example,net
+      -
+      replace: modifiersName
+      modifiersName: cn=Jane Doe,dc=example,net
+      -
+
+  In this case, the server is either to replace the provided
+  values as requested or fail the request.
+
+
+4.  Security Considerations
+
+  Use of this extension should be subject to appropriate administrative
+  and access controls.  Use of this mechanism is intended to be
+  restricted to directory administrators.
+
+  Security considerations for the base operations [RFC4511] extended
+  by this control, as well as general LDAP security considerations
+  [RFC4510], generally apply to implementation and use of this
+  extension.
+
+
+5.  IANA Considerations
+
+5.1.  Object Identifier
+
+  It is requested that the IANA assign a LDAP Object Identifier
+  [RFC4520] to identify the LDAP Relax Rules Control defined in this
+  document.
+
+      Subject: Request for LDAP Object Identifier Registration
+      Person & email address to contact for further information:
+          Kurt Zeilenga <Kurt.Zeilenga@Isode.COM>
+      Specification: RFC XXXX
+
+
+
+Zeilenga                LDAP Relax Rules Control                [Page 9]
+\f
+INTERNET-DRAFT        draft-zeilenga-ldap-relax-01      14 February 2007
+
+
+      Author/Change Controller: Kurt Zeilenga <Kurt.Zeilenga@Isode.COM>
+      Comments: Identifies the LDAP Relax Rules Control
+
+5.2  LDAP Protocol Mechanism
+
+  Registration of this protocol mechanism [RFC4520] is requested.
+
+      Subject: Request for LDAP Protocol Mechanism Registration
+      Object Identifier: IANA-ASSIGNED-OID
+      Description: Relax Rules Control
+      Person & email address to contact for further information:
+          Kurt Zeilenga <Kurt.Zeilenga@Isode.COM>
+      Usage: Control
+      Specification: RFC XXXX
+      Author/Change Controller: Kurt Zeilenga <Kurt.Zeilenga@Isode.COM>
+      Comments: none
+
+
+6.  Author's Address
+
+  Kurt D. Zeilenga
+  Isode Limited
+
+  Email: Kurt.Zeilenga@Isode.COM
+
+
+7. References
+
+  [[Note to the RFC Editor: please replace the citation tags used in
+  referencing Internet-Drafts with tags of the form RFCnnnn where
+  possible.]]
+
+
+7.1. Normative References
+
+  [RFC2119]     Bradner, S., "Key words for use in RFCs to Indicate
+                Requirement Levels", BCP 14 (also RFC 2119), March 1997.
+
+  [RFC3671]     Zeilenga, K., "Collective Attributes in LDAP", RFC 3671,
+                December 2003.
+
+  [RFC4510]     Zeilenga, K. (editor), "LDAP: Technical Specification
+                Road Map", RFC 4510, June 2006.
+
+  [RFC4511]     Sermersheim, J. (editor), "LDAP: The Protocol", RFC
+                4511, June 2006.
+
+  [RFC4512]     Zeilenga, K. (editor), "LDAP: Directory Information
+
+
+
+Zeilenga                LDAP Relax Rules Control               [Page 10]
+\f
+INTERNET-DRAFT        draft-zeilenga-ldap-relax-01      14 February 2007
+
+
+                Models", RFC 4512, June 2006.
+
+  [RFC4530]     Zeilenga, K., "Lightweight Directory Access Protocol
+                (LDAP) entryUUID Operational Attribute", RFC 4530, June
+                2006.
+
+  [X.500]       International Telecommunication Union -
+                Telecommunication Standardization Sector, "The Directory
+                -- Overview of concepts, models and services,"
+                X.500(1993) (also ISO/IEC 9594-1:1994).
+
+
+7.2. Informative References
+
+  [RFC4520]     Zeilenga, K., "Internet Assigned Numbers Authority
+                (IANA) Considerations for the Lightweight Directory
+                Access Protocol (LDAP)", RFC 4520, BCP 64, June 2006.
+
+
+
+Intellectual Property
+
+  The IETF takes no position regarding the validity or scope of any
+  Intellectual Property Rights or other rights that might be claimed to
+  pertain to the implementation or use of the technology described in
+  this document or the extent to which any license under such rights
+  might or might not be available; nor does it represent that it has
+  made any independent effort to identify any such rights.  Information
+  on the procedures with respect to rights in RFC documents can be found
+  in BCP 78 and BCP 79.
+
+  Copies of IPR disclosures made to the IETF Secretariat and any
+  assurances of licenses to be made available, or the result of an
+  attempt made to obtain a general license or permission for the use of
+  such proprietary rights by implementers or users of this specification
+  can be obtained from the IETF on-line IPR repository at
+  http://www.ietf.org/ipr.
+
+  The IETF invites any interested party to bring to its attention any
+  copyrights, patents or patent applications, or other proprietary
+  rights that may cover technology that may be required to implement
+  this standard.  Please address the information to the IETF at
+  ietf-ipr@ietf.org.
+
+
+
+Full Copyright
+
+
+
+
+Zeilenga                LDAP Relax Rules Control               [Page 11]
+\f
+INTERNET-DRAFT        draft-zeilenga-ldap-relax-01      14 February 2007
+
+
+  Copyright (C) The IETF Trust (2007).
+
+  This document is subject to the rights, licenses and restrictions
+  contained in BCP 78, and except as set forth therein, the authors
+  retain all their rights.
+
+  This document and the information contained herein are provided on an
+  "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS
+  OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY, THE IETF TRUST AND
+  THE INTERNET ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS
+  OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF
+  THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED
+  WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Zeilenga                LDAP Relax Rules Control               [Page 12]
+\f
index ea5d7c20aeb6c06d25c1498a9c6c733df7cbbe9f..4adffa6ed886664b38679217a86ec26d1fcedc3b 100644 (file)
@@ -108,6 +108,18 @@ Use \fIpasswd\fP as the password for simple authentication.
 .BI \-y \ passwdfile
 Use complete contents of \fIpasswdfile\fP as the password for
 simple authentication.
+Note that \fIcomplete\fP means that any leading or trailing whitespaces,
+including newlines, will be considered part of the password and,
+unlike other software, they will not be stripped.
+As a consequence, passwords stored in files by commands like
+.BR echo (1)
+will not behave as expected, since
+.BR echo (1)
+by default appends a trailing newline to the echoed string.
+The recommended portable way to store a cleartext password in a file
+for use with this option is to use
+.BR slappasswd (8)
+with \fI{CLEARTEXT}\fP as hash and the option \fI\-n\fP.
 .TP
 .BI \-H \ ldapuri
 Specify URI(s) referring to the ldap server(s); only the protocol/host/port
index 5d58bd7032bfaa8a4f9bff9f8782c1492e46938d..b82ed1d7e78a8b8c074cc9197b055fed51ab1088 100644 (file)
@@ -9,6 +9,8 @@ ldapmodrdn \- LDAP rename entry tool
 [\c
 .BR \-r ]
 [\c
+.BI \-s \ newsup\fR]
+[\c
 .BR \-n ]
 [\c
 .BR \-v ]
@@ -74,6 +76,10 @@ option, or from the command-line pair \fIdn\fP and
 .B \-r
 Remove old RDN values from the entry.  Default is to keep old values.
 .TP
+.BI \-s \ newsup
+Specify a new superior entry. (I.e., move the target entry and make it a
+child of the new superior.)  This option is not supported in LDAPv2.
+.TP
 .B \-n
 Show what would be done, but don't actually change entries.  Useful for
 debugging in conjunction with -v.
index 1350f9074a6359caf007985806f01f2a33e29647..2e798111a466a82e7127a3742c52288cdcc54469 100644 (file)
@@ -173,7 +173,7 @@ must be compiled with LDAP_DEBUG defined for this option to have any effect.
 Read a series of lines from \fIfile\fP, performing one LDAP search for
 each line.  In this case, the \fIfilter\fP given on the command line
 is treated as a pattern where the first and only occurrence of \fB%s\fP
-is replaced with a line from \fIfile\fP.  Any other occurence of the
+is replaced with a line from \fIfile\fP.  Any other occurrence of the
 the \fB%\fP character in the pattern will be regarded as an error.
 Where it is desired that the search filter include a \fB%\fP character,
 the character should be encoded as \fB\\25\fP (see RFC 4515).
@@ -201,9 +201,14 @@ Use complete contents of \fIpasswdfile\fP as the password for
 simple authentication.
 .TP
 .BI \-H \ ldapuri
-Specify URI(s) referring to the ldap server(s); only the protocol/host/port
-fields are allowed; a list of URI, separated by whitespace or commas
-is expected.
+Specify URI(s) referring to the ldap server(s);
+a list of URI, separated by whitespace or commas is expected;
+only the protocol/host/port fields are allowed.
+As an exception, if no host/port is specified, but a DN is,
+the DN is used to look up the corresponding host(s) using the
+DNS SRV records, according to RFC 2782.  The DN must be a non-empty
+sequence of AVAs whose attribute type is "dc" (domain component),
+and must be escaped according to RFC 2396.
 .TP
 .BI \-h \ ldaphost
 Specify an alternate host on which the ldap server is running.
index 6d850c0368d0350230778e2a3357a954c88c18c6..3b7f6960abc62cdc299168de4820c0a8daa9126a 100644 (file)
@@ -1,7 +1,7 @@
 Deprecated interfaces generally remain in the library.  The macro
 LDAP_DEPRECATED can be defined to a non-zero value
 (e.g., -DLDAP_DEPRECATED=1) when compiling program designed to use
-deprecated interaces.  It is recommended that developers writing new
+deprecated interfaces.  It is recommended that developers writing new
 programs, or updating old programs, avoid use of deprecated interfaces.
 Over time, it is expected that documentation (and, eventually, support) for
 deprecated interfaces to be eliminated.
index f677f2df56ae39a8c02186fe619ae95c2a959ff4..e2644c561c226354cba1c113990c3a195557a72d 100644 (file)
@@ -3,11 +3,7 @@
 .\" Copyright 1998-2007 The OpenLDAP Foundation All Rights Reserved.
 .\" Copying restrictions apply.  See COPYRIGHT/LICENSE.
 .SH NAME
-ber_get_next, ber_skip_tag, ber_peek_tag, ber_scanf, ber_get_int,
-ber_get_enum, ber_get_stringb, ber_get_stringa, ber_get_stringal,
-ber_get_stringbv, ber_get_null, ber_get_boolean, ber_get_bitstring,
-ber_first_element, ber_next_element
-\- LBER simplified Basic Encoding Rules library routines for decoding
+ber_get_next, ber_skip_tag, ber_peek_tag, ber_scanf, ber_get_int, ber_get_enum, ber_get_stringb, ber_get_stringa, ber_get_stringal, ber_get_stringbv, ber_get_null, ber_get_boolean, ber_get_bitstring, ber_first_element, ber_next_element \- OpenLDAP LBER simplified Basic Encoding Rules library routines for decoding
 .SH LIBRARY
 OpenLDAP LBER (liblber, -llber)
 .SH SYNOPSIS
index 275d42cb09f067d62d0bc6d01550be3d7843adb9..6d9a48da054020b6e3a32aab813ba92e81be12cc 100644 (file)
@@ -3,7 +3,7 @@
 .\" Copyright 1998-2007 The OpenLDAP Foundation All Rights Reserved.
 .\" Copying restrictions apply.  See COPYRIGHT/LICENSE.
 .SH NAME
-ber_alloc_t, ber_flush, ber_flush2, ber_printf, ber_put_int, ber_put_enum, ber_put_ostring, ber_put_string, ber_put_null, ber_put_boolean, ber_put_bitstring, ber_start_seq, ber_start_set, ber_put_seq, ber_put_set \- LBER simplified Basic Encoding Rules library routines for encoding
+ber_alloc_t, ber_flush, ber_flush2, ber_printf, ber_put_int, ber_put_enum, ber_put_ostring, ber_put_string, ber_put_null, ber_put_boolean, ber_put_bitstring, ber_start_seq, ber_start_set, ber_put_seq, ber_put_set \- OpenLDAP LBER simplified Basic Encoding Rules library routines for encoding
 .SH LIBRARY
 OpenLDAP LBER (liblber, -llber)
 .SH SYNOPSIS
index 0a4e968d34cb74733946a29f659351207ef85942..dfede5a21a91e621f0f861c86ada421a59cb5273 100644 (file)
@@ -3,7 +3,7 @@
 .\" Copyright 1998-2007 The OpenLDAP Foundation All Rights Reserved.
 .\" Copying restrictions apply.  See COPYRIGHT/LICENSE.
 .SH NAME
-ber_memalloc, ber_memcalloc, ber_memrealloc, ber_memfree, ber_memvfree \- LBER memory allocators
+ber_memalloc, ber_memcalloc, ber_memrealloc, ber_memfree, ber_memvfree \- OpenLDAP LBER memory allocators
 .SH LIBRARY
 OpenLDAP LBER (liblber, -llber)
 .SH SYNOPSIS
index d2e2b5364d860805c8ee7950ee43f0748ec7042a..5ab9c1d8483f794624a71e860abbf3f286613516 100644 (file)
@@ -3,8 +3,7 @@
 .\" Copyright 1998-2007 The OpenLDAP Foundation All Rights Reserved.
 .\" Copying restrictions apply.  See COPYRIGHT/LICENSE.
 .SH NAME
-ber_sockbuf_alloc, ber_sockbuf_free, ber_sockbuf_ctrl, ber_sockbuf_add_io,
-ber_sockbuf_remove_io, Sockbuf_IO \- LBER I/O infrastructure
+ber_sockbuf_alloc, ber_sockbuf_free, ber_sockbuf_ctrl, ber_sockbuf_add_io, ber_sockbuf_remove_io, Sockbuf_IO \- OpenLDAP LBER I/O infrastructure
 .SH LIBRARY
 OpenLDAP LBER (liblber, -llber)
 .SH SYNOPSIS
index 3ca443c6caf6ddd39d41a789158e30b8511b6127..a58c4f3cfe241589909f4494a9fc5ac0ac868cad 100644 (file)
@@ -3,12 +3,7 @@
 .\" Copyright 1998-2007 The OpenLDAP Foundation All Rights Reserved.
 .\" Copying restrictions apply.  See COPYRIGHT/LICENSE.
 .SH NAME
-ber_int_t, ber_uint_t, ber_len_t, ber_slen_t, ber_tag_t,
-struct berval, BerValue, BerVarray, BerElement,
-ber_bvfree, ber_bvecfree, ber_bvecadd, ber_bvarray_free, ber_bvarray_add,
-ber_bvdup, ber_dupbv, ber_bvstr, ber_bvstrdup, ber_str2bv,
-ber_alloc_t, ber_init, ber_init2, ber_free
-\- LBER types and allocation functions
+ber_int_t, ber_uint_t, ber_len_t, ber_slen_t, ber_tag_t, struct berval, BerValue, BerVarray, BerElement, ber_bvfree, ber_bvecfree, ber_bvecadd, ber_bvarray_free, ber_bvarray_add, ber_bvdup, ber_dupbv, ber_bvstr, ber_bvstrdup, ber_str2bv, ber_alloc_t, ber_init, ber_init2, ber_free \- OpenLDAP LBER types and allocation functions
 .SH LIBRARY
 OpenLDAP LBER (liblber, -llber)
 .SH SYNOPSIS
@@ -95,7 +90,7 @@ points to
 .B bv_len
 octets.
 .B bv_val
-is not necessarily terminated by a NUL (zero) octet.
+is not necessarily terminated by a NULL (zero) octet.
 .BR ber_bvfree ()
 frees a BerValue, pointed to by \fIbv\fP, returned from this API.  If \fIbv\fP
 is NULL, the routine does nothing.
index 3dd34f753847c28d459398ca831c62e6504265f1..67d753937e41971a398466eda1546520ad451580 100644 (file)
@@ -3,7 +3,7 @@
 .\" Copyright 1998-2007 The OpenLDAP Foundation All Rights Reserved.
 .\" Copying restrictions apply.  See COPYRIGHT/LICENSE.
 .SH NAME
-ldap - OpenLDAP Lightweight Directory Access Protocol API
+ldap \- OpenLDAP Lightweight Directory Access Protocol API
 .SH LIBRARY
 OpenLDAP LDAP (libldap, -lldap)
 .SH SYNOPSIS
@@ -88,10 +88,14 @@ Search filters to be passed to the search routines are to be
 constructed by hand and should conform to RFC 4515 UTF\-8
 string representation.
 .LP
-LDAP URL are to be passed to routines are expected to conform
+LDAP URLs to be passed to routines are expected to conform
 to RFC 4516 format.  The
 .BR ldap_url (3)
 routines can be used to work with LDAP URLs.
+.LP
+LDAP controls to be passed to routines can be manipulated using the
+.BR ldap_controls (3)
+routines.
 .SH DISPLAYING RESULTS
 Results obtained from the search routines can be output by hand,
 by calling
@@ -184,6 +188,12 @@ list of LDAP errors and their meanings
 .SM ldap_err2string(3)
 convert LDAP error indication to a string
 .TP
+.SM ldap_extended_operation(3)
+asynchronously perform an arbitrary extended operation
+.TP
+.SM ldap_extended_operation_s(3)
+synchronously perform an arbitrary extended operation
+.TP
 .SM ldap_first_attribute(3)
 return first attribute name in an entry
 .TP
index 07c4129fbbc8f79d9c56f5cd1c348103f5c2468b..6b26f843118347a82a13bd433a566b65e3822154 100644 (file)
@@ -265,7 +265,7 @@ The
 .B ldap_unbind_ext()
 and
 .B ldap_unbind_ext_s()
-allows the operations to sepicify  controls.
+allows the operations to specify  controls.
 .SH ERRORS
 Asynchronous routines will return -1 in case of error, setting the
 \fIld_errno\fP parameter of the \fIld\fP structure.  Synchronous
index 7cb7d21ddd11093e9d3480778346bfde83e696c8..413ce0817ec4bd16a87f53ebf70b5443d98a9d93 100644 (file)
@@ -3,45 +3,80 @@
 .\" Copyright 1998-2007 The OpenLDAP Foundation All Rights Reserved.
 .\" Copying restrictions apply.  See COPYRIGHT/LICENSE.
 .SH NAME
-ldap_create_control, ldap_find_control, ldap_control_free, ldap_controls_free \- LDAP control manipulation routines
+ldap_control_create, ldap_control_find, ldap_control_dup,
+ldap_controls_dup, ldap_control_free, ldap_controls_free
+\- LDAP control manipulation routines
 .SH LIBRARY
 OpenLDAP LDAP (libldap, -lldap)
 .SH SYNOPSIS
 .B #include <ldap.h>
 .LP
-.BI "int ldap_create_control(LDAP_CONST char *" OID ", BerElement *" ber ", int " iscritical ", LDAPControl **" ctrlp ");"
+.BI "int ldap_control_create(const char *" oid ", int " iscritical ", struct berval *" value ", int " dupval ", LDAPControl **" ctrlp ");"
 .LP
-.BI "LDAPControl *ldap_find_control(LDAP_CONST char *" OID ", LDAPControl **" ctrls ");"
+.BI "LDAPControl *ldap_control_find( const char *" oid ", LDAPControl **" ctrls ", LDAPControl ***" nextctrlp ");"
+.LP
+.BI "LDAPControl *ldap_control_dup(LDAPControl *" ctrl ");"
+.LP
+.BI "LDAPControl **ldap_controls_dup(LDAPControl **" ctrls ");"
 .LP
 .BI "void ldap_control_free(LDAPControl *" ctrl ");"
 .LP
 .BI "void ldap_controls_free(LDAPControl **" ctrls ");"
 .SH DESCRIPTION
 These routines are used to manipulate structures used for LDAP controls.
-.BR ldap_create_control ()
+
+.BR ldap_control_create ()
 creates a control with the specified
 .I OID
 using the contents of the
-.I ber
-parameter for the control value, if any. The
+.I value
+parameter for the control value, if any.  The content of
+.I value 
+is duplicated if
+.I dupval
+is non-zero.  The
 .I iscritical
-parameter should be non-zero for a critical control. The created control
+parameter must be non-zero for a critical control. The created control
 is returned in the
 .I ctrlp
-parameter. The routine returns
+parameter.  The routine returns
 .B LDAP_SUCCESS
 on success or some other error code on failure.
-.BR ldap_find_control ()
-searches the
+The content of
+.IR value ,
+for supported control types, can be prepared using helpers provided
+by this implementation of libldap, usually in the form
+.BR "ldap_create_<control name>_control_value" ().
+Otherwise, it can be BER-encoded using the functionalities of liblber.
+
+.BR ldap_control_find ()
+searches the NULL-terminated
 .I ctrls
 array for a control whose OID matches the
-.I OID
-parameter. The routine returns a pointer to the control if found,
+.I oid
+parameter.  The routine returns a pointer to the control if found,
 NULL otherwise.
+If the parameter
+.I nextctrlp
+is not NULL, on return it will point to the next control
+in the array, and can be passed to the
+.BR ldap_control_find ()
+routine for subsequent calls, to find further occurrences of the same 
+control type.
+The use of this function is discouraged; the recommended way of handling
+controls in responses consists in going through the array of controls,
+dealing with each of them in the returned order, since it could matter.
+
+.BR ldap_control_dup ()
+duplicates an individual control structure, and
+.BR ldap_controls_dup ()
+duplicates a NULL-terminated array of controls.
+
 .BR ldap_control_free ()
 frees an individual control structure, and
 .BR ldap_controls_free ()
-frees an array of controls.
+frees a NULL-terminated array of controls.
+
 .SH SEE ALSO
 .BR ldap (3),
 .BR ldap_error (3)
index 03cd358cc800d73ec9fe0892bfeff3858b6686c5..6c5248f641a5bef03e38f0af51f5a158c9cd1e39 100644 (file)
@@ -1,4 +1,6 @@
-ldap_create_control.3
-ldap_find_control.3
+ldap_control_create.3
+ldap_control_find.3
+ldap_control_dup.3
+ldap_controls_dup.3
 ldap_control_free.3
 ldap_controls_free.3
index 66af6e7650898eb997e567ed9cfc3b27ff3a6ba5..0eeadd77b5a34d1312c344704fbfa7215be11c52 100644 (file)
@@ -3,8 +3,7 @@
 .\" Copyright 1998-2007 The OpenLDAP Foundation All Rights Reserved.
 .\" Copying restrictions apply.  See COPYRIGHT/LICENSE.
 .SH NAME
-ldap_first_message, ldap_next_message, ldap_count_messages \- Stepping
-through messages in a result chain
+ldap_first_message, ldap_next_message, ldap_count_messages \- Stepping through messages in a result chain
 .SH LIBRARY
 OpenLDAP LDAP (libldap, -lldap)
 .SH SYNOPSIS
index b5b2822a35b557227b5b90881193ad513e26d4d7..ddaa83696064caf2338cb4b069537ea1a4b6045e 100644 (file)
@@ -3,8 +3,7 @@
 .\" Copyright 1998-2007 The OpenLDAP Foundation All Rights Reserved.
 .\" Copying restrictions apply.  See COPYRIGHT/LICENSE.
 .SH NAME
-ldap_first_reference, ldap_next_reference, ldap_count_references \- Stepping
-through continuation references in a result chain
+ldap_first_reference, ldap_next_reference, ldap_count_references \- Stepping through continuation references in a result chain
 .SH LIBRARY
 OpenLDAP LDAP (libldap, -lldap)
 .SH SYNOPSIS
index b98906d7562158ede61a95f14b6359d72bdee5ee..ab795520e5ced78ba2d5ec920f289c5b52db4cb5 100644 (file)
@@ -80,7 +80,7 @@ and they cannot be NULL. Using a struct with seconds set to -1 results
 in an infinite timeout, which is the default.
 .TP
 .B LDAP_OPT_DEREF
-Sets/gets the value that defines when alias deferencing must occur.
+Sets/gets the value that defines when alias dereferencing must occur.
 .BR outvalue 
 and 
 .BR invalue
@@ -187,7 +187,7 @@ the library duplicates the controls passed via
 .B LDAP_OPT_HOST_NAME
 Sets/gets a space-separated list of hosts to be contacted by the library 
 when trying to establish a connection.
-This is now deprecated in favour of
+This is now deprecated in favor of
 .BR LDAP_OPT_URI .
 .BR outvalue
 must be a 
index 28813961ab256cf7e365b05130db8e2c4360bebf..f2e5acd43705eb48cdabbadb1e0ac551452f3f53 100644 (file)
@@ -3,8 +3,7 @@
 .\" Copyright 1998-2007 The OpenLDAP Foundation All Rights Reserved.
 .\" Copying restrictions apply.  See COPYRIGHT/LICENSE.
 .SH NAME
-ldap_parse_sort_control \- Decodes the information returned from a search operation
-that used a server-side sort control.
+ldap_parse_sort_control \- Decode the information returned from a search operation that used a server-side sort control
 .SH LIBRARY
 OpenLDAP LDAP (libldap, -lldap)
 .SH SYNOPSIS
index 522cc13c076ed7f2805f79ded27f214687178904..f0fa8d996906a03b15409e9e719f840fdbbb3a4e 100644 (file)
@@ -3,8 +3,7 @@
 .\" Copyright 1998-2007 The OpenLDAP Foundation All Rights Reserved.
 .\" Copying restrictions apply.  See COPYRIGHT/LICENSE.
 .SH NAME
-ldap_parse_vlv_control \- Decodes the information returned from a search operation that
-used a VLV (virtual list view) control.
+ldap_parse_vlv_control \- Decode the information returned from a search operation that used a VLV (virtual list view) control
 .SH LIBRARY
 OpenLDAP LDAP (libldap, -lldap)
 .SH SYNOPSIS
@@ -39,7 +38,7 @@ in this parameter. If this parameter is set to NULL, the context identifier is
 not returned. You should use this returned context in the next call to
 create a VLV control. When the berval structure is no longer needed, you should
 free the memory by calling the \fIber_bvfree function.e\fP
-\fIerrcodep\fP is an output paremeter, which points to the result code returned
+\fIerrcodep\fP is an output parameter, which points to the result code returned
 by the server. If this parameter is NULL, the result code is not returned.
 .LP 
 See
index 26d4264b9bf4e16670cbf5bd483fbcba8e211b3a..3cd48cc32c1fa804d25354abd1d0d8c405eb52a3 100644 (file)
@@ -49,7 +49,7 @@ structures that list the client controls to use with the search.
 .B ldap_rename
 works just like
 .B ldap_rename_s,
-but the operation is asynchornous. It returns the message id of the request
+but the operation is asynchronous. It returns the message id of the request
 it initiated. The result of this operation can be obtained by calling
 .BR ldap_result(3).
 .SH ERRORS
index e86aecffd1b5a80d3240c5758d2e23ca043bec94..cae3a8d26d39706559c000fd627b1475871ee64c 100644 (file)
@@ -27,8 +27,8 @@ The
 routine is used to wait for and return the result of
 an operation previously initiated by one of the LDAP asynchronous
 operation routines (e.g.,
-.BR ldap_search (3),
-.BR ldap_modify (3),
+.BR ldap_search_ext (3),
+.BR ldap_modify_ext (3),
 etc.).  Those routines all return -1 in case of error, and an
 invocation identifier upon successful initiation of the operation. The
 invocation identifier is picked by the library and is guaranteed to be
@@ -94,7 +94,7 @@ The possible result types returned are:
        LDAP_RES_MODDN (0x6d)
        LDAP_RES_COMPARE (0x6f)
        LDAP_RES_EXTENDED (0x78)
-       LDAP_RES_EXTENDED_PARTIAL (0x79)
+       LDAP_RES_INTERMEDIATE (0x79)
 .fi
 .LP
 The
@@ -103,7 +103,7 @@ routine is used to free the memory allocated for
 result(s) by
 .B ldap_result()
 or
-.BR ldap_search_s (3)
+.BR ldap_search_ext_s (3)
 and friends.
 It takes a pointer to the result or result chain to be freed and returns
 the type of the last message in the chain.
@@ -126,7 +126,6 @@ and
 return -1 on error.
 .SH SEE ALSO
 .BR ldap (3),
-.BR ldap_search (3),
 .BR ldap_first_message (3),
 .BR select (2)
 .SH ACKNOWLEDGEMENTS
index 63b040ba917922a8f1fd00b7b1e913ab58b29173..5b794be4019d0791fb1449ac20557aad0f1e12b0 100644 (file)
@@ -3,14 +3,7 @@
 .\" Copyright 2000-2007 The OpenLDAP Foundation All Rights Reserved.
 .\" Copying restrictions apply.  See COPYRIGHT/LICENSE.
 .SH NAME
-ldap_str2syntax, ldap_syntax2str, ldap_syntax2name, ldap_syntax_free,
-ldap_str2matchingrule, ldap_matchingrule2str, ldap_matchingrule2name,
-ldap_matchingrule_free,
-ldap_str2attributetype, ldap_attributetype2str,
-ldap_attributetype2name, ldap_attributetype_free,
-ldap_str2objectclass, ldap_objectclass2str, ldap_objectclass2name,
-ldap_objectclass_free,
-ldap_scherr2str \- Schema definition handling routines
+ldap_str2syntax, ldap_syntax2str, ldap_syntax2name, ldap_syntax_free, ldap_str2matchingrule, ldap_matchingrule2str, ldap_matchingrule2name, ldap_matchingrule_free, ldap_str2attributetype, ldap_attributetype2str, ldap_attributetype2name, ldap_attributetype_free, ldap_str2objectclass, ldap_objectclass2str, ldap_objectclass2name, ldap_objectclass_free, ldap_scherr2str \- Schema definition handling routines
 .SH LIBRARY
 OpenLDAP LDAP (libldap, -lldap)
 .SH SYNOPSIS
index f17b62f9e8e439f57f6f58310ad53d78b50368e2..83374caeaea4b0ec98dd7b9883a45fbc3d174adb 100644 (file)
@@ -83,7 +83,7 @@ The description "*" (LDAP_ALL_USER_ATTRIBUTES) may be used to request
 all user attributes to be returned.
 The description "+"(LDAP_ALL_OPERATIONAL_ATTRIBUTES) may be used to
 request all operational attributes to be returned.  Note that this
-requires the server to suppor the LDAP All Operational Attribute
+requires the server to support the LDAP All Operational Attribute
 extension.
 To request no attributes, the description "1.1" (LDAP_NO_ATTRS)
 should be listed by itself.
index 1f4cfa4bf71c4e12e7bd6e38f269eb23f17cdd67..10a92e16599f2ab53eb5b4a8d32ec41fdcc13274 100644 (file)
@@ -3,7 +3,7 @@
 .\" Copyright 1998-2007 The OpenLDAP Foundation All Rights Reserved.
 .\" Copying restrictions apply.  See COPYRIGHT/LICENSE.
 .SH NAME
-LDAP sorting routines (deprecated)
+ldap_sort_entries, ldap_sort_values, ldap_sort_strcasecmp \- LDAP sorting routines (deprecated)
 .SH LIBRARY
 OpenLDAP LDAP (libldap, -lldap)
 .SH DESCRIPTION
index 17b97536c4875c40139f75954bfb77d89f710ce6..9cb1436c02f700cb35d576cf125c555ca82e532c 100644 (file)
@@ -10,11 +10,11 @@ OpenLDAP LDAP (libldap, -lldap)
 .nf
 .B #include <ldap_sync.h>
 .LP
-.BI "int ldap_sync_init(ldap_sync_t *" ls ", int " mode ", int " cancel ");"
+.BI "int ldap_sync_init(ldap_sync_t *" ls ", int " mode ");"
 .LP
-.BI "int ldap_sync_init_refresh_only(ldap_sync_t *" ls ", int " cancel ");"
+.BI "int ldap_sync_init_refresh_only(ldap_sync_t *" ls ");"
 .LP
-.BI "int ldap_sync_init_refresh_and_persist(ldap_sync_t *" ls ", int " cancel ");"
+.BI "int ldap_sync_init_refresh_and_persist(ldap_sync_t *" ls  ");"
 .LP
 .BI "int ldap_sync_poll(ldap_sync_t *" ls ");"
 .LP
@@ -198,7 +198,8 @@ to indicate that the refresh phase of refreshAndPersist is over, and
 the client should start polling.
 Except for the
 .BR LDAP_SYNC_CAPI_PRESENTS_IDSET
-and LDAP_SYNC_CAPI_DELETES_IDSET
+and
+.BR LDAP_SYNC_CAPI_DELETES_IDSET
 cases,
 .BR syncUUIDs
 is NULL.
@@ -239,7 +240,7 @@ structure, and sets appropriate values for some members.
 After that, the caller is responsible for setting up the
 connection (member
 .BR ls_ld ),
-evetually setting up transport security (TLS),
+eventually setting up transport security (TLS),
 for binding and any other initialization.
 The caller must also fill all the documented search-related fields
 of the
index 7a1662bb3f5446d246d7bc01909aaac490feb69b..d1045245a4cc7c05ef217063849867ba603b1100 100644 (file)
@@ -3,9 +3,7 @@
 .\" Copyright 1998-2007 The OpenLDAP Foundation All Rights Reserved.
 .\" Copying restrictions apply.  See COPYRIGHT/LICENSE.
 .SH NAME
-ldap_is_ldap_url,
-ldap_url_parse,
-ldap_free_urldesc \- LDAP Uniform Resource Locator routines
+ldap_is_ldap_url, ldap_url_parse, ldap_free_urldesc \- LDAP Uniform Resource Locator routines
 .SH LIBRARY
 OpenLDAP LDAP (libldap, -lldap)
 .SH SYNOPSIS
index b5818696385fd74e2879fe678fef55fc5f0d8255..df5604be8162e659809d8e29c4348aec41bf1274 100644 (file)
@@ -278,6 +278,7 @@ certificates in separate individual files. The
 .B TLS_CACERT
 is always used before
 .B TLS_CACERTDIR.
+This parameter is ignored with GNUtls.
 .TP
 .B TLS_CERT <filename>
 Specifies the file that contains the client certificate.
@@ -300,6 +301,7 @@ e.g., HIGH:MEDIUM:+SSLv2.
 Specifies the file to obtain random bits from when /dev/[u]random is
 not available. Generally set to the name of the EGD/PRNGD socket.
 The environment variable RANDFILE can also be used to specify the filename.
+This parameter is ignored with GNUtls.
 .TP
 .B TLS_REQCERT <level>
 Specifies what checks to perform on server certificates in a TLS session,
@@ -332,7 +334,7 @@ Specifies if the Certificate Revocation List (CRL) of the CA should be
 used to verify if the server certificates have not been revoked. This
 requires
 .B TLS_CACERTDIR
-parameter to be set.
+parameter to be set. This parameter is ignored with GNUtls.
 .B <level>
 can be specified as one of the following keywords:
 .RS
@@ -346,6 +348,11 @@ Check the CRL of the peer certificate
 .B all
 Check the CRL for a whole certificate chain
 .RE
+.TP
+.B TLS_CRLFILE <filename>
+Specifies the file containing a Certificate Revocation List to be used
+to verify if the server certificates have not been revoked. This
+parameter is only supported with GNUtls.
 .SH "ENVIRONMENT VARIABLES"
 .TP
 LDAPNOINIT
index 0a892983c36a3ac3c5272d6dc8ad4530f9047b5a..dfc44f5afbfc025778d6b2a80ce63cb48759d681 100644 (file)
@@ -269,6 +269,8 @@ commands.
 .BR ldapadd (1),
 .BR ldapmodify (1),
 .BR slapadd (8),
+.BR slapcat (8),
+.BR slapd-ldif (5),
 .BR slapd.replog (5).
 .LP
 "LDAP Data Interchange Format," Good, G., RFC 2849.
index 4fda2c35db6339e7c0bf4eea869e73b6b1ced441..8f59a1565e7971e87165acc78e91f10ff061ce9e 100644 (file)
@@ -3,7 +3,7 @@
 .\" Copying restrictions apply.  See COPYRIGHT/LICENSE.
 .\" $OpenLDAP$
 .SH NAME
-\fBslapd-bdb\fP, \fBslapd-hdb\fP \- Berkeley DB backends to \fBslapd\fP
+slapd-bdb, slapd-hdb \- Berkeley DB backends to slapd
 .SH SYNOPSIS
 .B ETCDIR/slapd.conf
 .SH DESCRIPTION
@@ -12,7 +12,7 @@ The \fBbdb\fP backend to
 is the recommended primary backend for a normal 
 .B slapd 
 database.
-It uses the Sleepycat Berkeley DB (BDB) package to store data.
+It uses the Oracle Berkeley DB (BDB) package to store data.
 It makes extensive use of indexing and caching to speed data access.
 .LP
 \fBhdb\fP is a variant of the \fBbdb\fP backend that uses a 
@@ -107,6 +107,11 @@ results if the data comes from a transaction that is later aborted.
 In this case, the modified data is discarded and a subsequent search
 will return a different result.
 .TP
+.BI dncachesize \ <integer>
+Specify the maximum number of DNs in the in-memory DN cache. The
+default is twice the \fBcachesize\fP. Ideally this cache should be
+large enough to contain the DNs of every entry in the database.
+.TP
 .BI idlcachesize \ <integer>
 Specify the size of the in-memory index cache, in index slots. The
 default is zero. A larger value will speed up frequent searches of
@@ -225,3 +230,6 @@ Berkeley DB configuration file
 Berkeley DB documentation.
 .SH ACKNOWLEDGEMENTS
 .so ../Project
+Originally begun by Kurt Zeilenga. Caching mechanisms originally designed
+by Jong-Hyuk Choi. Completion and subsequent work, as well as
+back-hdb, by Howard Chu.
index 3a375546cb36b17f93aaa8cf3bd169aebd047fdc..146dc30131198b2565f43f34cf7a0af4f4a6ebe8 100644 (file)
@@ -3,7 +3,7 @@
 .\" Copying restrictions apply.  See COPYRIGHT/LICENSE.
 .\" $OpenLDAP$
 .SH NAME
-slapd-config \- configuration backend
+slapd-config \- configuration backend to slapd
 .SH SYNOPSIS
 ETCDIR/slapd.d
 .SH DESCRIPTION
@@ -488,6 +488,11 @@ see
 .B minssf
 option description.  The default is 71.
 .TP
+.B olcLogFile: <filename>
+Specify a file for recording debug log messages. By default these messages
+only go to stderr and are not recorded anywhere else. Specifying a logfile
+copies messages to both stderr and the logfile.
+.TP
 .B olcLogLevel: <integer> [...]
 Specify the level at which debugging statements and operation 
 statistics should be syslogged (currently logged to the
@@ -496,8 +501,7 @@ LOG_LOCAL4 facility).
 They must be considered subsystems rather than increasingly verbose 
 log levels.
 Some messages with higher priority are logged regardless 
-of the configured loglevel as soon as some logging is configured,
-otherwise anything is logged at all.
+of the configured loglevel as soon as any logging is configured.
 Log levels are additive, and available levels are:
 .RS
 .RS
@@ -668,40 +672,6 @@ Specify the referral to pass back when
 .BR slapd (8)
 cannot find a local database to handle a request.
 If multiple values are specified, each url is provided.
-.\" slurpd-related keywords are all deprecated
-.\".TP
-.\".B replica-argsfile
-.\"The ( absolute ) name of a file that will hold the 
-.\".B slurpd
-.\"server's command line options
-.\"if started without the debugging command line option.
-.\"If it appears after a
-.\".B replogfile
-.\"directive, the args file is specific to the 
-.\".BR slurpd (8)
-.\"instance that handles that replication log.
-.\".TP
-.\".B replica-pidfile
-.\"The ( absolute ) name of a file that will hold the 
-.\".B slurpd
-.\"server's process ID ( see
-.\".BR getpid (2)
-.\") if started without the debugging command line option.
-.\"If it appears after a
-.\".B replogfile
-.\"directive, the pid file is specific to the 
-.\".BR slurpd (8)
-.\"instance that handles that replication log.
-.\".TP
-.\".B replicationinterval
-.\"The number of seconds 
-.\".B slurpd 
-.\"waits before checking the replogfile for changes.
-.\"If it appears after a
-.\".B replogfile
-.\"directive, the replication interval is specific to the 
-.\".BR slurpd (8)
-.\"instance that handles that replication log.
 .TP
 .B olcReverseLookup: TRUE | FALSE
 Enable/disable client name unverified reverse lookup (default is 
@@ -712,6 +682,14 @@ if compiled with --enable-rlookups).
 Specify the name of an LDIF(5) file containing user defined attributes
 for the root DSE.  These attributes are returned in addition to the
 attributes normally produced by slapd.
+
+The root DSE is an entry with information about the server and its
+capabilities, in operational attributes.
+It has the empty DN, and can be read with e.g.:
+.ti +4
+ldapsearch -x -b "" -s base "+"
+.br
+See RFC 4512 section 5.1 for details.
 .TP
 .B olcSaslHost: <fqdn>
 Used to specify the fully qualified domain name used for SASL processing.
@@ -811,9 +789,17 @@ Permits configuring what ciphers will be accepted and the preference order.
 
 olcTLSCipherSuite: HIGH:MEDIUM:+SSLv2
 
-To check what ciphers a given spec selects, use:
+To check what ciphers a given spec selects in OpenSSL, use:
+
+.nf
+       openssl ciphers -v <cipher-suite-spec>
+.fi
 
-openssl ciphers -v <cipher-suite-spec>
+To obtain the list of ciphers in GNUtls use:
+
+.nf
+       gnutls-cli -l
+.fi
 .TP
 .B olcTLSCACertificateFile: <filename>
 Specifies the file that contains certificates for all of the Certificate
@@ -825,7 +811,8 @@ will recognize.
 Specifies the path of a directory that contains Certificate Authority
 certificates in separate individual files. Usually only one of this
 or the olcTLSCACertificateFile is defined. If both are specified, both
-locations will be used.
+locations will be used. This directive is not supported
+when using GNUtls.
 .TP
 .B olcTLSCertificateFile: <filename>
 Specifies the file that contains the
@@ -851,12 +838,14 @@ them will be processed.  Note that setting this option may also enable
 Anonymous Diffie-Hellman key exchanges in certain non-default cipher suites.
 You should append "!ADH" to your cipher suites if you have changed them
 from the default, otherwise no certificate exchanges or verification will
-be done.
+be done. When using GNUtls these parameters are always generated randomly
+so this directive is ignored.
 .TP
 .B olcTLSRandFile: <filename>
 Specifies the file to obtain random bits from when /dev/[u]random
 is not available.  Generally set to the name of the EGD/PRNGD socket.
 The environment variable RANDFILE can also be used to specify the filename.
+This directive is ignored with GNUtls.
 .TP
 .B olcTLSVerifyClient: <level>
 Specifies what checks to perform on client certificates in an
@@ -898,7 +887,7 @@ Specifies if the Certificate Revocation List (CRL) of the CA should be
 used to verify if the client certificates have not been revoked. This
 requires
 .B olcTLSCACertificatePath
-parameter to be set.
+parameter to be set. This parameter is ignored with GNUtls.
 .B <level>
 can be specified as one of the following keywords:
 .RS
@@ -912,6 +901,11 @@ Check the CRL of the peer certificate
 .B all
 Check the CRL for a whole certificate chain
 .RE
+.TP
+.B olcTLSCRLFile: <filename>
+Specifies a file containing a Certificate Revocation List to be used
+for verifying that certificates have not been revoked. This parameter
+is only valid when using GNUtls.
 .SH DYNAMIC MODULE OPTIONS
 If
 .B slapd
@@ -1216,6 +1210,13 @@ which they are defined.  They are supported by every
 type of backend. All of the Global Database Options may also be
 used here.
 .TP
+.B olcHidden: TRUE | FALSE
+Controls whether the database will be used to answer
+queries. A database that is hidden will never be
+selected to answer any queries, and any suffix configured
+on the database will be ignored in checks for conflicts
+with other databases. By default, olcHidden is FALSE.
+.TP
 .B olcLastMod: TRUE | FALSE
 Controls whether
 .B slapd
@@ -1451,90 +1452,15 @@ resolve an entry, used to avoid infinite alias loops. The default is 1.
 This option puts a replica database into "mirror" mode.  Update
 operations will be accepted from any user, not just the updatedn.  The
 database must already be configured as syncrepl consumer
-before this keyword may be set.  This mode must be used with extreme
-care, as it does not offer any consistency guarantees.  This feature
-is intended to be used with an external frontend that guarantees that
-writes are only directed to a single master, switching to an alternate
-server only if the original master goes down.
+before this keyword may be set.  This mode also requires a
+.B olcServerID
+(see above) to be configured.
 By default, this setting is FALSE.
 .TP
 .B olcPlugin: <plugin_type> <lib_path> <init_function> [<arguments>]
 Configure a SLAPI plugin. See the
 .BR slapd.plugin (5)
 manpage for more details.
-.\".HP
-.\".hy 0
-.\".B replica uri=ldap[s]://<hostname>[:port]|host=<hostname>[:port] 
-.\".B [starttls=yes|critical]
-.\".B [suffix=<suffix> [...]]
-.\".B bindmethod=simple|sasl [binddn=<simple DN>] [credentials=<simple password>]
-.\".B [saslmech=<SASL mech>] [secprops=<properties>] [realm=<realm>]
-.\".B [authcId=<authentication ID>] [authzId=<authorization ID>]
-.\".B [attrs[!]=<attr list>]
-.\".RS
-.\"Specify a replication site for this database.  Refer to the "OpenLDAP 
-.\"Administrator's Guide" for detailed information on setting up a replicated
-.\".B slapd
-.\"directory service. Zero or more
-.\".B suffix
-.\"instances can be used to select the subtrees that will be replicated
-.\"(defaults to all the database). 
-.\".B host
-.\"is deprecated in favor of the
-.\".B uri
-.\"option.
-.\".B uri
-.\"allows the replica LDAP server to be specified as an LDAP URI. 
-.\"A
-.\".B bindmethod
-.\"of
-.\".B simple
-.\"requires the options
-.\".B binddn 
-.\"and
-.\".B credentials  
-.\"and should only be used when adequate security services 
-.\"(e.g TLS or IPSEC) are in place. A
-.\".B bindmethod 
-.\"of
-.\".B sasl 
-.\"requires the option
-.\".B saslmech. 
-.\"Specific security properties (as with the
-.\".B sasl-secprops
-.\"keyword above) for a SASL bind can be set with the
-.\".B secprops
-.\"option. A non-default SASL realm can be set with the
-.\".B realm
-.\"option.
-.\"If the 
-.\".B mechanism
-.\"will use Kerberos, a kerberos instance should be given in 
-.\".B authcId.
-.\"An
-.\".B attr list
-.\"can be given after the 
-.\".B attrs
-.\"keyword to allow the selective replication of the listed attributes only;
-.\"if the optional 
-.\".B !
-.\"mark is used, the list is considered exclusive, i.e. the listed attributes
-.\"are not replicated.
-.\"If an objectClass is listed, all the related attributes
-.\"are (are not) replicated.
-.\".RE
-.\".TP
-.\".B replogfile <filename>
-.\"Specify the name of the replication log file to log changes to.  
-.\"The replication log is typically written by
-.\".BR slapd (8)
-.\"and read by
-.\".BR slurpd (8).
-.\"See
-.\".BR slapd.replog (5)
-.\"for more information.  The specified file should be located
-.\"in a directory with limited read/write/execute access as the replication
-.\"logs may contain sensitive information.
 .TP
 .B olcRootDN: <dn>
 Specify the distinguished name that is not subject to access control 
@@ -1807,9 +1733,8 @@ ignored.
 This option is only applicable in a slave
 database.
 It specifies the DN permitted to update (subject to access controls)
-the replica (typically, this is the DN
-.BR slurpd (8)
-binds to update the replica).  Generally, this DN
+the replica.  It is only needed in certain push-mode
+replication scenarios.  Generally, this DN
 .I should not
 be the same as the
 .B rootdn 
@@ -1954,8 +1879,7 @@ default slapd configuration directory
 .BR slapdn (8),
 .BR slapindex (8),
 .BR slappasswd (8),
-.BR slaptest (8),
-.BR slurpd (8).
+.BR slaptest (8).
 .LP
 "OpenLDAP Administrator's Guide" (http://www.OpenLDAP.org/doc/admin/)
 .SH ACKNOWLEDGEMENTS
index 847ea6d6570d4a2976eb8ef64fa0f44d4e1063b6..ee9fbffdd496971b732d4f797ffcedd442426fa3 100644 (file)
@@ -429,6 +429,13 @@ or when chasing a referral, if
 is set to
 .IR yes .
 
+.TP
+.B session\-tracking\-request {NO|yes}
+Adds session tracking control for all requests.
+The client's IP and hostname, and the identity associated to each request,
+if known, are sent to the remote server for informational purposes.
+This directive is incompatible with setting \fIprotocol\-version\fP to 2.
+
 .TP
 .B single\-conn {NO|yes}
 Discards current cached connection when the client rebinds.
index 336d0ae46a7b331a9048921e89a13b8de3503492..45856458da7a6694b328f716b158e42ae0fd93a3 100644 (file)
 .\" Copying restrictions apply.  See COPYRIGHT/LICENSE.
 .\" $OpenLDAP$
 .SH NAME
-slapd-ldbm \- LDBM backend to slapd
+slapd-ldbm \- Discontinued LDBM backend to slapd
 .SH SYNOPSIS
 ETCDIR/slapd.conf
 .SH DESCRIPTION
-The LDBM backend to
-.BR slapd (8)
-is an easy\-to\-configure but obsolete database backend.  It does not
-offer the data durability features of the BDB and HDB backends and
-hence is considered deprecated in favor of these robust backends.
-LDBM uses lightweight non\-transactional data interfaces, such as those
-provided by GDBM or Berkeley DB, to store data.  It makes extensive
-use of indexing and caching to speed data access.
-.SH CONFIGURATION
-These
-.B slapd.conf
-options apply to the LDBM backend database.
-That is, they must follow a "database ldbm" line and come before any
-subsequent "backend" or "database" lines.
-Other database options are described in the
-.BR slapd.conf (5)
-manual page.
-.TP
-.B cachesize <integer>
-Specify the size in entries of the in-memory cache maintained 
-by the LDBM backend database instance.
-The default is 1000 entries.
-.TP
-.B dbcachesize <integer>
-Specify the size in bytes of the in-memory cache associated with each
-open index file.
-If not supported by the underlying database method, this option is
-ignored without comment.
-The default is 100000 bytes.
-.TP
-.B dbnolocking
-Specify that no database locking should be performed.  
-Enabling this option may improve performance at the expense of data security.
-Do NOT run any slap tools while slapd is running.
-.TP
-.B dbnosync
-Specify that on-disk database contents should not be immediately
-synchronized with in memory changes.
-Enabling this option may improve performance at the expense of data
-security.
-.TP
-.B dbsync <frequency> <maxdelays> <delayinterval>
-Flush dirty database buffers to disk every
-.B <seconds>
-seconds.
-Implies
-.B dbnosync
-(ie. individual updates are no longer written to disk).
-It attempts to avoid syncs during periods of peak activity by waiting
-.B <delayinterval>
-seconds if the server is busy, repeating this delay up to
-.B <maxdelays>
-times before proceeding.  
-It is an attempt to provide higher write performance with some amount
-of data security.
-Note that it may still be possible to get an inconsistent database if
-the underlying engine fills its cache and writes out individual pages
-and slapd crashes or is killed before the next sync.
-.B <maxdelays>
-and
-.B <delayinterval>
-are optional and default to
-.B 12
-and
-.B 5
-respectively, giving a total elapsed delay of 60 seconds before a sync
-will occur.
-.B <maxdelays>
-may be zero, and
-.B <delayinterval>
-must be 1 or greater.
-.TP
-.B directory <directory>
-Specify the directory where the LDBM files containing this database and
-associated indexes live.
-A separate directory must be specified for each database.
-The default is
-.BR LOCALSTATEDIR/openldap-data .
-.TP
-.B
-index {<attrlist>|default} [pres,eq,approx,sub,<special>]
-Specify the indexes to maintain for the given attribute (or
-list of attributes).
-Some attributes only support a subset of indexes.
-If only an <attr> is given, the indices specified for \fBdefault\fR
-are maintained.
-Note that setting a default does not imply that all attributes will be
-indexed. Also, for best performance, an
-.B eq
-index should always be configured for the
-.B objectClass
-attribute.
+LDBM was the original database backend to
+.BR slapd (8),
+and was supported up to OpenLDAP 2.3.
+It has been superseded by the more robust BDB and HDB backends.
 
-A number of special index parameters may be specified.
-The index type
-.B sub
-can be decomposed into
-.BR subinitial ,
-.BR subany ,\ and
-.B subfinal
-indices.
-The special type
-.B notags
-(or
-.BR nolang )
-may be specified to disallow use of this index by subtypes with tagging
-options (such as language options).
-The special type
-.B nosubtypes
-may be specified to disallow use of this index by named subtypes.
-Note: changing index settings requires rebuilding indices, see
-.BR slapindex (8).
-.TP
-.B mode <integer>
-Specify the file protection mode that newly created database 
-index files should have.
-The default is 0600.
-.SH ACCESS CONTROL
-The 
-.B ldbm
-backend honors access control semantics as indicated in
-.BR slapd.access (5).
-.SH FILES
-.TP
-ETCDIR/slapd.conf
-default slapd configuration file
 .SH SEE ALSO
-.BR slapd.conf (5),
 .BR slapd (8),
-.BR slapadd (8),
-.BR slapcat (8),
-.BR slapindex (8).
+.BR slapd-bdb (5),
+.BR slapd.backends (5).
 .SH ACKNOWLEDGEMENTS
 .so ../Project
index 46e9fb5c142b8c035eda04e9e3151b72d60510fe..e2c5bbe0e259ed1ecf6e7f7bb6f6c3c75cdf6020 100644 (file)
@@ -8,7 +8,7 @@
 .\" and maybe manual pages for librewrite.
 .\"
 .SH NAME
-slapd-meta \- metadirectory backend
+slapd-meta \- metadirectory backend to slapd
 .SH SYNOPSIS
 ETCDIR/slapd.conf
 .SH DESCRIPTION
@@ -172,6 +172,15 @@ or when chasing a referral, if
 is set to
 .IR yes .
 
+.TP
+.B session\-tracking\-request {NO|yes}
+Adds session tracking control for all requests.
+The client's IP and hostname, and the identity associated to each request,
+if known, are sent to the remote server for informational purposes.
+This directive is incompatible with setting \fIprotocol\-version\fP to 2.
+If set before any target specification, it affects all targets, unless
+overridden by any per-target directive.
+
 .TP
 .B single\-conn {NO|yes}
 Discards current cached connection when the client rebinds.
@@ -532,7 +541,7 @@ The rule
 .LP
 .RS
 .nf
-access to dn="<dn>" attr=<attr>
+access to dn="<dn>" attrs=<attr>
        by dnattr=<dnattr> read
        by * none
 .fi
index b4894c34a187feb3905f4b8175199c371437bbb3..e5faa0dd669752b241dee1dbb462a56745bc8e3f 100644 (file)
@@ -3,8 +3,7 @@
 .\" Copying restrictions apply.  See COPYRIGHT/LICENSE.
 .\" $OpenLDAP$
 .SH NAME
-.B slapd-monitor 
-\- Monitor backend to slapd
+slapd-monitor \- Monitor backend to slapd
 .SH SYNOPSIS
 ETCDIR/slapd.conf
 .SH DESCRIPTION
index 90d0437509ec0cb68b332741d76fa57e401dac4d..8a28a51040732b7566a91efdbfc040e70778e796 100644 (file)
@@ -39,7 +39,7 @@ Other database options are described in the
 manual page.
 .TP
 .B bind <on/off>
-Allow binds as DNs in this backend's suffix.
+Allow binds as any DN in this backend's suffix, with any password.
 The default is "off".
 .SH EXAMPLE
 Here is a possible slapd.conf extract using the Null backend:
index 8aeead99c29e819cf2798fdfb3b11c15bd3010a8..b59d215c3094ab5821b2d09a0583b06b455e4093 100644 (file)
@@ -12,8 +12,8 @@ running in the same
 instance into a virtual naming context, with attributeType
 and objectClass manipulation, if required.
 It requires the
-.B rwm
-.BR overlay .
+.BR slapo-rwm (5)
+overlay.
 .LP
 This backend and the above mentioned overlay are experimental.
 .SH CONFIGURATION
@@ -26,27 +26,30 @@ Other database options are described in the
 .BR slapd.conf (5)
 manual page; only the
 .B suffix
-directive is required by the 
+directive is allowed by the 
 .I relay
 backend.
 .TP
-.B relay <real naming context> [massage]
+.B relay <real naming context>
 The naming context of the database that is presented 
 under a virtual naming context.
 The presence of this directive implies that one specific database,
 i.e. the one serving the
 .BR "real naming context" ,
 will be presented under a virtual naming context.
-This directive automatically instantiates the 
-.IR "rwm overlay" .
-If the optional
-.B massage
-keyword is present, the suffix massaging is automatically
-configured as well; otherwise, specific massaging instructions
-are required by means of the
-.I rewrite
-directives described in
-.BR slapo-rwm (5).
+
+.SH MASSAGING
+The
+.B relay
+database does not automatically rewrite the naming context
+of requests and responses.
+For this purpose, the
+.BR slapo-rwm (5)
+overlay must be explicitly instantiated, and configured
+as appropriate.
+Usually, the
+.B rwm-suffixmassage
+directive suffices if only naming context rewriting is required.
 
 .SH ACCESS RULES
 One important issue is that access rules are based on the identity
@@ -57,7 +60,7 @@ real naming context.
 Moreover, since
 .B back-relay
 bypasses the real database frontend operations by short-circuiting
-operations thru the internal backend API, the original database
+operations through the internal backend API, the original database
 access rules do not apply but in selected cases, i.e. when the
 backend itself applies access control.
 As a consequence, the instances of the relay database must provide
@@ -88,29 +91,26 @@ Another possibility is to map the same operation to different
 databases based on details of the virtual naming context,
 e.g. groups on one database and persons on another.
 .LP
-.SH Caveats
-The
-.B rwm overlay
-is experimental.
-.LP
 .SH EXAMPLES
 To implement a plain virtual naming context mapping
 that refers to a single database, use
 .LP
 .nf
-  database        relay
-  suffix          "dc=virtual,dc=naming,dc=context"
-  relay           "dc=real,dc=naming,dc=context" massage
+  database                relay
+  suffix                  "dc=virtual,dc=naming,dc=context"
+  relay                   "dc=real,dc=naming,dc=context"
+  overlay                 rwm
+  rwm-suffixmassage       "dc=real,dc=naming,dc=context"
 .fi
 .LP
 To implement a plain virtual naming context mapping
 that looks up the real naming context for each operation, use
 .LP
 .nf
-  database        relay
-  suffix          "dc=virtual,dc=naming,dc=context"
-  overlay         rwm
-  suffixmassage   "dc=real,dc=naming,dc=context"
+  database                relay
+  suffix                  "dc=virtual,dc=naming,dc=context"
+  overlay                 rwm
+  rwm-suffixmassage       "dc=real,dc=naming,dc=context"
 .fi
 .LP
 This is useful, for instance, to relay different databases that
@@ -122,39 +122,43 @@ the virtual to the real naming context, but not the results
 back from the real to the virtual naming context, use
 .LP
 .nf
-  database        relay
-  suffix          "dc=virtual,dc=naming,dc=context"
-  relay           "dc=real,dc=naming,dc=context"
-  rewriteEngine   on
-  rewriteContext  default
-  rewriteRule     "dc=virtual,dc=naming,dc=context"
-          "dc=real,dc=naming,dc=context" ":@"
-  rewriteContext  searchFilter
-  rewriteContext  searchEntryDN
-  rewriteContext  searchAttrDN
-  rewriteContext  matchedDN
+  database                relay
+  suffix                  "dc=virtual,dc=naming,dc=context"
+  relay                   "dc=real,dc=naming,dc=context"
+  overlay                 rwm
+  rwm-rewriteEngine       on
+  rwm-rewriteContext      default
+  rwm-rewriteRule         "dc=virtual,dc=naming,dc=context"
+                          "dc=real,dc=naming,dc=context" ":@"
+  rwm-rewriteContext      searchFilter
+  rwm-rewriteContext      searchEntryDN
+  rwm-rewriteContext      searchAttrDN
+  rwm-rewriteContext      matchedDN
 .fi
 .LP
-Note that the virtual database is bound to a single real database,
-so the 
-.B rwm overlay
-is automatically instantiated, but the rewrite rules 
-are written explicitly to map all the virtual to real 
-naming context data flow, but none of the real to virtual.
+Note that the 
+.BR slapo-rwm (5)
+overlay is instantiated, but the rewrite rules are written explicitly,
+rather than automatically as with the
+.B rwm-suffixmassage
+statement, to map all the virtual to real naming context data flow,
+but none of the real to virtual.
 .LP
 Access rules:
 .LP
 .nf
-  database        bdb
-  suffix          "dc=example,dc=com"
+  database                bdb
+  suffix                  "dc=example,dc=com"
   # skip...
   access to dn.subtree="dc=example,dc=com"
           by dn.exact="cn=Supervisor,dc=example,dc=com" write
           by * read
 
-  database        relay
-  suffix          "o=Example,c=US"
-  relay           "dc=example,dc=com" massage
+  database                relay
+  suffix                  "o=Example,c=US"
+  relay                   "dc=example,dc=com"
+  overlay                 rwm
+  rwm-suffixmassage       "dc=example,dc=com"
   # skip ...
   access to dn.subtree="o=Example,c=US"
           by dn.exact="cn=Supervisor,dc=example,dc=com" write
index 454f63f46d4b0e88a682ef5ade9aa462e41a35e5..59e91ca809c81fe0057b0c852168a2b11c2d6daa 100644 (file)
@@ -100,7 +100,7 @@ see \fBupper_func\fP, \fBupper_needs_cast\fP, \fBconcat_pattern\fP
 and \fBstrcast_func\fP in "HELPER CONFIGURATION" for details.
 
 .TP
-.B use_subtree_shortcut { NO | yes }
+.B use_subtree_shortcut { YES | no }
 Do not use the subtree condition when the searchBase is the database
 suffix, and the scope is subtree; rather collect all entries.
 
@@ -654,7 +654,7 @@ A directoryString value of the form "__First___Last_"
 (where underscores mean spaces, ASCII 0x20 char) corresponds
 to its prettified counterpart "First_Last"; this is not currently
 honored by back-sql if non-prettified data is written via RDBMS;
-when non-prettified data is written thru back-sql, the prettified 
+when non-prettified data is written through back-sql, the prettified 
 values are actually used instead.
 
 .LP
index 75450bd2426646a13b14b7d4c648e91a1b5a3e43..2129e58e83e6b15ce4f48949712ac9c6916e389f 100644 (file)
@@ -10,9 +10,7 @@ The
 .BR slapd.conf (5)
 file contains configuration information for the
 .BR slapd (8)
-daemon. This configuration file is also used by the
-.BR slurpd (8)
-replication daemon and by the SLAPD tools
+daemon. This configuration file is also used by the SLAPD tools
 .BR slapacl (8),
 .BR slapadd (8),
 .BR slapauth (8),
index c5801ad31feb28fb48b5a19cdb93dcfaa1fcce58..887c499c144ec7adc7e1dd5481a58c47e9e3fc14 100644 (file)
@@ -22,7 +22,7 @@ manual pages.
 .B bdb
 This is the recommended primary backend for a normal slapd database.
 It takes care to configure it properly.
-It uses the transactional database interface of the Sleepycat Berkeley
+It uses the transactional database interface of the Oracle Berkeley
 DB (BDB) package to store data.
 .TP
 .B config
index e6d75395b9c45105de374d885b5716bf64d9d294..e5c5a1cc2e4415454312e4e8cb977478b8533428 100644 (file)
@@ -11,9 +11,7 @@ The file
 .B ETCDIR/slapd.conf
 contains configuration information for the
 .BR slapd (8)
-daemon.  This configuration file is also used by the
-.BR slurpd (8)
-replication daemon and by the SLAPD tools
+daemon.  This configuration file is also used by the SLAPD tools
 .BR slapacl (8),
 .BR slapadd (8),
 .BR slapauth (8),
@@ -497,13 +495,6 @@ for the segments of a filter string that are processed for a subany index
 lookup. The default is 2. For example, with the default values, a search
 using this filter "cn=*abcdefgh*" would generate index lookups for
 "abcd", "cdef", and "efgh".
-
-.\"-- NEW_LOGGING option --
-.\".TP
-.\".B logfile <filename>
-.\"Specify a file for recording debug log messages. By default these messages
-.\"only go to stderr and are not recorded anywhere else. Specifying a logfile
-.\"copies messages to both stderr and the logfile.
 .TP
 .B localSSF <SSF>
 Specifies the Security Strength Factor (SSF) to be given local LDAP sessions,
@@ -513,6 +504,11 @@ see
 .B minssf
 option description.  The default is 71.
 .TP
+.B logfile <filename>
+Specify a file for recording debug log messages. By default these messages
+only go to stderr and are not recorded anywhere else. Specifying a logfile
+copies messages to both stderr and the logfile.
+.TP
 .B loglevel <integer> [...]
 Specify the level at which debugging statements and operation 
 statistics should be syslogged (currently logged to the
@@ -521,8 +517,7 @@ LOG_LOCAL4 facility).
 They must be considered subsystems rather than increasingly verbose 
 log levels.
 Some messages with higher priority are logged regardless 
-of the configured loglevel as soon as some logging is configured,
-otherwise anything is logged at all.
+of the configured loglevel as soon as any logging is configured.
 Log levels are additive, and available levels are:
 .RS
 .RS
@@ -562,7 +557,7 @@ access control list processing
 .TP
 .B 256
 .B (0x100 stats)
-stats log connections/operations/results
+connections, LDAP operations, results (recommended)
 .TP
 .B 512
 .B (0x200 stats2)
@@ -614,10 +609,14 @@ The keyword
 .BR none ,
 or the equivalent integer representation, causes those messages
 that are logged regardless of the configured loglevel to be logged.
-In fact, if no loglevel (or a 0 level) is defined, no logging occurs, 
+In fact, if loglevel is set to 0, no logging occurs, 
 so at least the 
 .B none
 level is required to have high priority messages logged.
+
+The loglevel defaults to \fBstats\fP.
+This level should usually also be included when using other loglevels, to
+help analyze the logs.
 .RE
 .TP
 .B moduleload <filename>
@@ -723,39 +722,6 @@ Specify the referral to pass back when
 cannot find a local database to handle a request.
 If specified multiple times, each url is provided.
 .TP
-.B replica-argsfile
-The ( absolute ) name of a file that will hold the 
-.B slurpd
-server's command line options
-if started without the debugging command line option.
-If it appears after a
-.B replogfile
-directive, the args file is specific to the 
-.BR slurpd (8)
-instance that handles that replication log.
-.TP
-.B replica-pidfile
-The ( absolute ) name of a file that will hold the 
-.B slurpd
-server's process ID ( see
-.BR getpid (2)
-) if started without the debugging command line option.
-If it appears after a
-.B replogfile
-directive, the pid file is specific to the 
-.BR slurpd (8)
-instance that handles that replication log.
-.TP
-.B replicationinterval
-The number of seconds 
-.B slurpd 
-waits before checking the replogfile for changes.
-If it appears after a
-.B replogfile
-directive, the replication interval is specific to the 
-.BR slurpd (8)
-instance that handles that replication log.
-.TP
 .B require <conditions>
 Specify a set of conditions (separated by white space) to
 require (default none).
@@ -788,6 +754,14 @@ if compiled with --enable-rlookups).
 Specify the name of an LDIF(5) file containing user defined attributes
 for the root DSE.  These attributes are returned in addition to the
 attributes normally produced by slapd.
+
+The root DSE is an entry with information about the server and its
+capabilities, in operational attributes.
+It has the empty DN, and can be read with e.g.:
+.ti +4
+ldapsearch -x -b "" -s base "+"
+.br
+See RFC 4512 section 5.1 for details.
 .TP
 .B sasl-host <fqdn>
 Used to specify the fully qualified domain name used for SASL processing.
@@ -880,7 +854,9 @@ factor is measure of security provided by the underlying transport,
 e.g. ldapi:// (and eventually IPSEC).  It is not normally used.
 .TP
 .B serverID <integer> [<URL>]
-Specify an integer ID from 0 to 4095 for this server. These IDs are
+Specify an integer ID from 0 to 4095 for this server (limited
+to 3 hexadecimal digits).
+These IDs are
 required when using multimaster replication and each master must have a
 unique ID. If the URL is provided, this directive may be specified
 multiple times, providing a complete list of participating servers
@@ -957,7 +933,16 @@ TLSCipherSuite HIGH:MEDIUM:+SSLv2
 
 To check what ciphers a given spec selects, use:
 
-openssl ciphers -v <cipher-suite-spec>
+.nf
+       openssl ciphers -v <cipher-suite-spec>
+.fi
+
+To obtain the list of ciphers in GNUtls use:
+
+.nf
+       gnutls-cli -l
+.fi
+
 .TP
 .B TLSCACertificateFile <filename>
 Specifies the file that contains certificates for all of the Certificate
@@ -968,7 +953,8 @@ will recognize.
 .B TLSCACertificatePath <path>
 Specifies the path of a directory that contains Certificate Authority
 certificates in separate individual files. Usually only one of this
-or the TLSCACertificateFile is used.
+or the TLSCACertificateFile is used. This directive is not supported
+when using GNUtls.
 .TP
 .B TLSCertificateFile <filename>
 Specifies the file that contains the
@@ -991,12 +977,14 @@ them will be processed.  Note that setting this option may also enable
 Anonymous Diffie-Hellman key exchanges in certain non-default cipher suites.
 You should append "!ADH" to your cipher suites if you have changed them
 from the default, otherwise no certificate exchanges or verification will
-be done.
+be done. When using GNUtls these parameters are always generated randomly so
+this directive is ignored.
 .TP
 .B TLSRandFile <filename>
 Specifies the file to obtain random bits from when /dev/[u]random
 is not available.  Generally set to the name of the EGD/PRNGD socket.
 The environment variable RANDFILE can also be used to specify the filename.
+This directive is ignored with GNUtls.
 .TP
 .B TLSVerifyClient <level>
 Specifies what checks to perform on client certificates in an
@@ -1038,7 +1026,7 @@ Specifies if the Certificate Revocation List (CRL) of the CA should be
 used to verify if the client certificates have not been revoked. This
 requires
 .B TLSCACertificatePath
-parameter to be set.
+parameter to be set. This directive is ignored with GNUtls.
 .B <level>
 can be specified as one of the following keywords:
 .RS
@@ -1052,6 +1040,11 @@ Check the CRL of the peer certificate
 .B all
 Check the CRL for a whole certificate chain
 .RE
+.TP
+.B TLSCRLFile <filename>
+Specifies a file containing a Certificate Revocation List to be used
+for verifying that certificates have not been revoked. This directive is
+only valid when using GNUtls.
 .SH GENERAL BACKEND OPTIONS
 Options in this section only apply to the configuration file section
 for the specified backend.  They are supported by every
@@ -1065,7 +1058,6 @@ should be one of
 .BR dnssrv ,
 .BR hdb ,
 .BR ldap ,
-.BR ldbm ,
 .BR ldif ,
 .BR meta ,
 .BR monitor ,
@@ -1095,7 +1087,6 @@ should be one of
 .BR dnssrv ,
 .BR hdb ,
 .BR ldap ,
-.BR ldbm ,
 .BR ldif ,
 .BR meta ,
 .BR monitor ,
@@ -1108,6 +1099,13 @@ or
 .BR sql ,
 depending on which backend will serve the database.
 .TP
+.B hidden on | off
+Controls whether the database will be used to answer
+queries. A database that is hidden will never be
+selected to answer any queries, and any suffix configured
+on the database will be ignored in checks for conflicts
+with other databases. By default, hidden is off.
+.TP
 .B lastmod on | off
 Controls whether
 .B slapd
@@ -1342,12 +1340,10 @@ resolve an entry, used to avoid infinite alias loops. The default is 1.
 .B mirrormode on | off
 This option puts a replica database into "mirror" mode.  Update
 operations will be accepted from any user, not just the updatedn.  The
-database must already be configured as a slurpd or syncrepl consumer
-before this keyword may be set.  This mode must be used with extreme
-care, as it does not offer any consistency guarantees.  This feature
-is intended to be used with an external frontend that guarantees that
-writes are only directed to a single master, switching to an alternate
-server only if the original master goes down.
+database must already be configured as a syncrepl consumer
+before this keyword may be set. This mode also requires a
+.B serverID
+(see above) to be configured.
 By default, mirrormode is off.
 .TP
 .B overlay <overlay-name>
@@ -1359,6 +1355,8 @@ of the order in which they were configured and the database itself
 will receive control last of all. See the
 .BR slapd.overlays (5)
 manual page for an overview of the available overlays.
+Note that all of the database's
+regular settings should be configured before any overlay settings.
 .TP
 .B readonly on | off
 This option puts the database into "read-only" mode.  Any attempts to 
@@ -1426,18 +1424,6 @@ If an objectClass is listed, all the related attributes
 are (are not) replicated.
 .RE
 .TP
-.B replogfile <filename>
-Specify the name of the replication log file to log changes to.  
-The replication log is typically written by
-.BR slapd (8)
-and read by
-.BR slurpd (8).
-See
-.BR slapd.replog (5)
-for more information.  The specified file should be located
-in a directory with limited read/write/execute access as the replication
-logs may contain sensitive information.
-.TP
 .B restrict <oplist>
 Specify a whitespace separated list of operations that are restricted.
 If defined inside a database specification, restrictions apply only
@@ -1600,7 +1586,8 @@ replication engine.
 identifies the current
 .B syncrepl
 directive within the replication consumer site.
-It is a non-negative integer having no more than three digits.
+It is a non-negative integer not greater than 4095 (limited
+to three hexadecimal digits).
 
 .B provider
 specifies the replication provider site containing the master content
@@ -1670,6 +1657,7 @@ and
 .B credentials
 and should only be used when adequate security services
 (e.g. TLS or IPSEC) are in place.
+.B REMEMBER: simple bind credentials must be in cleartext!
 A
 .B bindmethod
 of
@@ -1726,12 +1714,10 @@ ignored.
 .TP
 .B updatedn <dn>
 This option is only applicable in a slave
-database updated using
-.BR slurpd(8). 
+database.
 It specifies the DN permitted to update (subject to access controls)
-the replica (typically, this is the DN
-.BR slurpd (8)
-binds to update the replica).  Generally, this DN
+the replica.  It is only needed in certain push-mode
+replication scenarios.  Generally, this DN
 .I should not
 be the same as the
 .B rootdn 
@@ -1810,8 +1796,7 @@ default slapd configuration file
 .BR slapdn (8),
 .BR slapindex (8),
 .BR slappasswd (8),
-.BR slaptest (8),
-.BR slurpd (8).
+.BR slaptest (8).
 .LP
 "OpenLDAP Administrator's Guide" (http://www.OpenLDAP.org/doc/admin/)
 .SH ACKNOWLEDGEMENTS
index 251f61f234935b3c2d6aa1bbebb11c9fe5ad6b82..3e02d59d890ec2e33a4e0c2ac1b371366b0e3d45 100644 (file)
@@ -36,6 +36,17 @@ This overlay allows automatic referral chasing when a referral would
 have been returned, either when configured by the server or when 
 requested by the client.
 .TP
+.B constraint
+Constraint.
+This overlay enforces a regular expression constraint on all values
+of specified attributes. It is used to enforce a more rigorous
+syntax when the underlying attribute syntax is too general.
+.TP
+.B dds
+Dynamic Directory Services.
+This overlay supports dynamic objects, which have a limited life after
+which they expire and are automatically deleted.
+.TP
 .B dyngroup
 Dynamic Group.
 This is a demo overlay which extends the Compare operation to detect
@@ -98,6 +109,11 @@ Attribute Uniqueness.
 This overlay can be used with a backend database such as
 .BR slapd-bdb (5)
 to enforce the uniqueness of some or all attributes within a subtree.
+.TP
+.B valsort
+Value Sorting.
+This overlay can be used to enforce a specific order for the values
+of an attribute when it is returned in a search.
 .SH FILES
 .TP
 ETCDIR/slapd.conf
@@ -110,6 +126,9 @@ default slapd configuration directory
 .BR slapo\-accesslog (5),
 .BR slapo\-auditlog (5),
 .BR slapo\-chain (5),
+.BR slapo\-constraint (5),
+.BR slapo\-dds (5),
+.BR slapo\-dyngroup (5),
 .BR slapo\-dynlist (5),
 .BR slapo\-pcache (5),
 .BR slapo\-ppolicy (5),
@@ -119,6 +138,7 @@ default slapd configuration directory
 .BR slapo\-syncprov (5),
 .BR slapo\-translucent (5),
 .BR slapo\-unique (5).
+.BR slapo\-valsort (5).
 .BR slapd\-config (5),
 .BR slapd.conf (5),
 .BR slapd.backends (5),
index de9e4f3abc560a63a10f657b68d1f893c4c002ab..c25b69b6464b89aa41f9a50872047c9deeef34fe 100644 (file)
@@ -10,9 +10,7 @@ The
 .BR slapd.conf (5)
 file contains configuration information for the
 .BR slapd (8)
-daemon. This configuration file is also used by the
-.BR slurpd (8)
-replication daemon and by the SLAPD tools
+daemon. This configuration file is also used by the SLAPD tools
 .BR slapadd (8),
 .BR slapcat (8),
 and
diff --git a/doc/man/man5/slapd.replog.5 b/doc/man/man5/slapd.replog.5
deleted file mode 100644 (file)
index 87f1c73..0000000
+++ /dev/null
@@ -1,167 +0,0 @@
-.TH SLAPD.REPLOG 5 "RELEASEDATE" "OpenLDAP LDVERSION"
-.\" $OpenLDAP$
-.\" Copyright 1998-2007 The OpenLDAP Foundation All Rights Reserved.
-.\" Copying restrictions apply.  See COPYRIGHT/LICENSE.
-.SH NAME
-slapd.replog \- slapd replication log format
-.SH SYNOPSIS
-slapd.replog
-slapd.replog.lock
-.SH DESCRIPTION
-.LP
-The file slapd.replog is produced by the stand-alone LDAP daemon,
-.BR slapd (8),
-when changes are made to its local database that are to be
-propagated to one or more replica
-.IR slapd s.
-The file consists of
-zero or more records, each one corresponding to a change, addition,
-or deletion from the
-.I slapd
-database.  The file is meant to be read
-and processed by
-.BR slurpd (8),
-the stand-alone LDAP update replication daemon.  The records are
-separated by a blank line.  Each record has the following format.
-.LP
-The record begins with one or more lines indicating the replicas
-to which the change is to be propagated:
-.LP
-.nf
-       replica: <hostname[:portnumber]>
-.fi
-.LP
-Next, the time the change took place given, as the number of seconds since
-00:00:00 GMT, Jan. 1, 1970, with an optional decimal extension, in order
-to make times unique.  Note that slapd does not make times unique, but
-slurpd makes all times unique in its copies of the replog files.
-.LP
-.nf
-       time: <integer[.integer]>
-.fi
-.LP
-Next, the distinguished name of the entry being changed is given:
-.LP
-.nf
-       dn: <distinguishedname>
-.fi
-.LP
-Next, the type of change being made is given:
-.LP
-.nf
-       changetype: <[modify|add|delete|modrdn]>
-.fi
-.LP
-Finally, the change information itself is given, the format of which
-depends on what kind of change was specified above.  For a \fIchangetype\fP
-of \fImodify\fP, the format is one or more of the following:
-.LP
-.nf
-       add: <attributetype>
-       <attributetype>: <value1>
-       <attributetype>: <value2>
-       ...
-       -
-.fi
-.LP
-Or, for a replace modification:
-.LP
-.nf
-       replace: <attributetype>
-       <attributetype>: <value1>
-       <attributetype>: <value2>
-       ...
-       -
-.fi
-.LP
-Or, for a delete modification:
-.LP
-.nf
-       delete: <attributetype>
-       <attributetype>: <value1>
-       <attributetype>: <value2>
-       ...
-       -
-.fi
-.LP
-If no \fIattributetype\fP lines are given, the entire attribute is to be
-deleted.
-.LP
-For a \fIchangetype\fP of \fIadd\fP, the format is:
-.LP
-.nf
-       <attributetype1>: <value1>
-       <attributetype1>: <value2>
-       ...
-       <attributetypeN>: <value1>
-       <attributetypeN>: <value2>
-.fi
-.LP
-For a \fIchangetype\fP of \fImodrdn\fP, the format is:
-.LP
-.nf
-       newrdn: <newrdn>
-       deleteoldrdn: 0 | 1
-.fi
-.LP
-where a value of 1 for deleteoldrdn means to delete the values
-forming the old rdn from the entry, and a value of 0 means to
-leave the values as non-distinguished attributes in the entry.
-.LP
-For a \fIchangetype\fP of \fIdelete\fP, no additional information
-is needed in the record.
-.LP
-The format of the values is the LDAP Directory Interchange Format
-described in
-.BR ldif (5).
-.LP
-Access to the \fIslapd.replog\fP file is synchronized through the
-use of
-.BR flock (3)
-on the file \fIslapd.replog.lock\fP.  Any process
-reading or writing this file should obey this locking convention.
-.SH EXAMPLE
-The following sample \fIslapd.replog\fP file contains information
-on one of each type of change.
-.LP
-.nf
-       replica: truelies.rs.itd.umich.edu
-       replica: judgmentday.rs.itd.umich.edu
-       time: 797612941
-       dn: cn=Babs Jensen,dc=example,dc=com
-       changetype: add
-       objectclass: person
-       cn: babs
-       cn: babs jensen
-       sn: jensen
-        
-       replica: truelies.rs.itd.umich.edu
-       replica: judgmentday.rs.itd.umich.edu
-       time: 797612973
-       dn: cn=Babs Jensen,dc=example,dc=com
-       changetype: modify
-       add: description
-       description: the fabulous babs
-        
-       replica: truelies.rs.itd.umich.edu
-       replica: judgmentday.rs.itd.umich.edu
-       time: 797613020
-       dn: cn=Babs Jensen,dc=example,dc=com
-       changetype: modrdn
-       newrdn: cn=Barbara J Jensen
-       deleteoldrdn: 0
-.fi
-.SH FILES
-.TP
-slapd.replog
-slapd replication log file
-.TP
-slapd.replog.lock
-lockfile for slapd.replog
-.SH SEE ALSO
-.BR ldap (3),
-.BR ldif (5),
-.BR slapd (8),
-.BR slurpd (8)
-.SH ACKNOWLEDGEMENTS
-.so ../Project
index 3c51f0115d9a1c11e37a7367b45e383bcfa32f47..947b8fefdc41bfe2fe0147ccfc70af3a29c9b5d4 100644 (file)
@@ -3,7 +3,7 @@
 .\" Copying restrictions apply.  See COPYRIGHT/LICENSE.
 .\" $OpenLDAP$
 .SH NAME
-slapo-accesslog \- Access Logging overlay
+slapo-accesslog \- Access Logging overlay to slapd
 .SH SYNOPSIS
 ETCDIR/slapd.conf
 .SH DESCRIPTION
index 63cc0cfc65a165107274154b91e96b2bc9bd68fe..ec50acd09c405764bbeb0212f9978a7c06f4994d 100644 (file)
@@ -3,7 +3,7 @@
 .\" Copying restrictions apply.  See COPYRIGHT/LICENSE.
 .\" $OpenLDAP$
 .SH NAME
-slapo-auditlog \- Audit Logging overlay
+slapo-auditlog \- Audit Logging overlay to slapd
 .SH SYNOPSIS
 ETCDIR/slapd.conf
 .SH DESCRIPTION
index 3757516e0a29945ac3ca9f18773acb0342e6c2c8..177db91cb240e7c8902cec00bd367b1b3af46bd1 100644 (file)
@@ -3,7 +3,7 @@
 .\" Copying restrictions apply.  See the COPYRIGHT file.
 .\" $OpenLDAP$
 .SH NAME
-slapo-chain \- chain overlay
+slapo-chain \- chain overlay to slapd
 .SH SYNOPSIS
 ETCDIR/slapd.conf
 .SH DESCRIPTION
diff --git a/doc/man/man5/slapo-constraint.5 b/doc/man/man5/slapo-constraint.5
new file mode 100644 (file)
index 0000000..e5752fd
--- /dev/null
@@ -0,0 +1,57 @@
+.TH SLAPO-CONSTRAINT 5 "RELEASEDATE" "OpenLDAP LDVERSION"
+.\" Copyright 2005-2006 Hewlett-Packard Company
+.\" Copying restrictions apply.  See COPYRIGHT/LICENSE.
+.SH NAME
+slapo-constraint \- Attribute Constraint Overlay to slapd
+.SH SYNOPSIS
+ETCDIR/slapd.conf
+.SH DESCRIPTION
+The constraint overlay is used to enforce a regular expression
+constraint on all values of specified attributes. Attributes can
+have multiple constraints placed upon them, and all must be satisfied
+when modifying an attribute value under constraint.
+.LP
+This overlay is intended to be used to force syntactic regularity upon
+certain string represented data which have well known canonical forms,
+like telephone numbers, post codes, FQDNs, etc.
+.SH CONFIGURATION
+This
+.B slapd.conf
+option applies to the constraint overlay.
+It should appear after the
+.B overlay
+directive.
+.TP
+.B constraint_attribute <attribute_name> <type> <value>
+Specifies the constraint which should apply to the attribute named as
+the first parameter.
+At the moment only one type of constraint is supported -
+.B
+regex.
+The parameter following the
+.B
+regex
+type is a Unix style regular expression (See
+.B
+regex(7))
+
+Any attempt to add or modify an attribute named as part of the
+constraint overlay specification which does not fit the regular
+expression constraint listed will fail with a
+LDAP_CONSTRAINT_VIOLATION error.
+.SH EXAMPLES
+.B
+constraint_attribute mail regex ^[:alnum:]+@mydomain.com$
+
+A specification like the above would reject any
+.B
+mail
+attribute which did not look like
+.B
+<alpha-numeric string>@mydomain.com
+.SH FILES
+.TP
+ETCDIR/slapd.conf
+default slapd configuration file
+.SH SEE ALSO
+.BR slapd.conf (5).
index 77196ca92018e7115c6708c4c9bcee710324b391..6cba6cd9ed24c8ebee3f21237593fe7efb6ef7e1 100644 (file)
@@ -3,7 +3,7 @@
 .\" Copying restrictions apply.  See the COPYRIGHT file.
 .\" $OpenLDAP$
 .SH NAME
-slapo-dds \- dds overlay
+slapo-dds \- Dynamic Directory Services overlay to slapd
 .SH SYNOPSIS
 ETCDIR/slapd.conf
 .SH DESCRIPTION
@@ -15,12 +15,13 @@ implements dynamic objects as per RFC 2589.
 The name 
 .B dds
 stands for
-Dynamic Dyrectory Services.
+Dynamic Directory Services.
 It allows to define dynamic objects, characterized by the
 .B dynamicObject
 objectClass.
-Dynamic objects have a limited life, determined by a time-to-live (TTL)
-that can be refreshed by means of a specific 
+
+Dynamic objects have a limited lifetime, determined by a time-to-live
+(TTL) that can be refreshed by means of a specific
 .B refresh
 extended operation.
 This operation allows to set the Client Refresh Period (CRP),
@@ -28,16 +29,18 @@ namely the period between refreshes that is required to preserve the
 dynamic object from expiration.
 The expiration time is computed by adding the requested TTL to the 
 current time.
-When dynamic objects reach the end of their life without being
-further refreshed, they are automatically deleted; there is no guarantee
-of immediate deletion, but clients should not count over it.
-Dynamic objects can have subordinates, provided they also are dynamic
+When dynamic objects reach the end of their lifetime without being
+further refreshed, they are automatically deleted.
+There is no guarantee of immediate deletion, so clients should not count
+on it.
+
+Dynamic objects can have subordinates, provided these also are dynamic
 objects.
-RFC 2589 does not specify what should the behavior of a dynamic 
-directory service be when a dynamic object with (dynamic) subordinates
+RFC 2589 does not specify what the behavior of a dynamic directory
+service should be when a dynamic object with (dynamic) subordinates
 expires.
-In this implementation, the life of dynamic objects with subordinates
-is prolonged until all the dynamic subordinates expired.
+In this implementation, the lifetime of dynamic objects with subordinates
+is prolonged until all the dynamic subordinates expire.
 
 
 This 
@@ -61,7 +64,7 @@ and
 operations.
 Since its use may result in many internal entry lookups, adds
 and deletes, it should be best used in conjunction with backends
-that have resonably good write performances.
+that have reasonably good write performances.
 
 .LP 
 The config directives that are specific to the
@@ -73,19 +76,20 @@ database or to other stacked overlays.
 
 .TP
 .B dds\-max\-ttl <ttl>
-Specifies the max TTL value; this is the default TTL newly created
+Specifies the max TTL value.
+This is also the default TTL newly created
 dynamic objects receive, unless
 .B dds\-default\-ttl
 is set.
-When the client with a refresh exop requests a TTL higher than it,
-sizeLimitExceeded is returned.
+When the client with a refresh extended operation requests a TTL higher
+than it, sizeLimitExceeded is returned.
 This value must be between 86400 (1 day, the default) and 31557600
 (1 year plus 6 hours, as per RFC 2589).
 
 .TP
 .B dds\-min\-ttl <ttl>
 Specifies the min TTL value; clients requesting a lower TTL by means
-of the refresh exop actually obtain this value as CRP.
+of the refresh extended operation actually obtain this value as CRP.
 If set to 0 (the default), no lower limit is set.
 
 .TP
@@ -103,11 +107,12 @@ Specifies the interval between expiration checks; defaults to 1 hour.
 .B dds\-tolerance <ttl>
 Specifies an extra time that is added to the timer that actually wakes up
 the thread that will delete an expired dynamic object.
-So the nominal life of the entry is that specified in the
+So the nominal lifetime of the entry is that specified in the
 .B entryTtl
-attribute, but its life will actually be
-.BR " entryTtl + tolerance " .
-Note that there is no guarantee that the life of a dynamic object will be
+attribute, but its lifetime will actually be
+.BR "entryTtl + tolerance" .
+Note that there is no guarantee that the lifetime of a dynamic object
+will be
 .I exactly
 the requested TTL; due to implementation details, it may be longer, which 
 is allowed by RFC 2589.
@@ -117,8 +122,8 @@ By default, tolerance is 0.
 .B dds\-max\-dynamicObjects <num>
 Specifies the maximum number of dynamic objects that can simultaneously exist
 within a naming context.
-This allows to limit the amount of resources (mostly in terms of runqueue size)
-that are used by dynamic objects.
+This allows to limit the amount of resources (mostly in terms of
+run-queue size) that are used by dynamic objects.
 By default, no limit is set.
 
 .TP
@@ -146,8 +151,8 @@ is an operational, NO-USER-MODIFICATION attribute, no direct write access
 to it is possible.
 So the 
 .B dds
-overlay turns refresh exops into an internal modification to the value 
-of the
+overlay turns refresh extended operation into an internal modification to
+the value of the
 .B entryTtl
 attribute with the
 .B manageDIT
@@ -155,7 +160,7 @@ control set.
 
 RFC 2589 recommends that anonymous clients should not be allowed to refresh
 a dynamic object.
-This cn be implemented by appropriately crafting access control to obtain 
+This can be implemented by appropriately crafting access control to obtain 
 the desired effect.
 
 Example: restrict refresh to authenticated clients
@@ -218,7 +223,7 @@ dynamic objects replicate.  Only the master takes care of handling dynamic
 object expiration, while replicas simply see the dynamic object as a plain
 object.
 
-When using slurpd replication, one needs to explicitly exclude the 
+When replicating these objects, one needs to explicitly exclude the 
 .B dynamicObject
 class and the
 .B entryTtl
@@ -227,21 +232,10 @@ This implementation of RFC 2589 introduces a new operational attribute,
 .BR entryExpireTimestamp ,
 that contains the expiration timestamp.  This must be excluded from 
 replication as well.
-In
-.BR slapd.conf (5),
-add the following \fIexclusion list\fP to each
-.B replica 
-statement:
-
-.RS
-.nf
-replica ...
-       attrs!=@dynamicObject,entryTtl,entryExpireTimestamp
-.fi
-.RE
 
-When using syncrepl, the quick and dirty solution is to set 
+The quick and dirty solution is to set 
 .B schemacheck=off
+in the syncrepl configuration
 and, optionally, exclude the operational attributes from replication, using
 
 .RS
diff --git a/doc/man/man5/slapo-dyngroup.5 b/doc/man/man5/slapo-dyngroup.5
new file mode 100644 (file)
index 0000000..7728831
--- /dev/null
@@ -0,0 +1,48 @@
+.TH SLAPO-DYNGROUP 5 "RELEASEDATE" "OpenLDAP LDVERSION"
+.\" Copyright 2005-2007 The OpenLDAP Foundation All Rights Reserved.
+.\" Copying restrictions apply.  See COPYRIGHT/LICENSE.
+.\" $OpenLDAP$
+.SH NAME
+slapo-dyngroup \- Dynamic Group overlay to slapd
+.SH SYNOPSIS
+ETCDIR/slapd.conf
+.SH DESCRIPTION
+The Dynamic Group overlay allows clients to use LDAP Compare operations
+to test the membership of a dynamic group the same way they would check
+against a static group. Compare operations targeting a group's static
+member attribute will be intercepted and tested against the configured
+dynamic group's URL attribute.
+.LP
+Note that this intercept only happens if the actual
+Compare operation does not return a LDAP_COMPARE_TRUE result. So if a
+group has both static and dynamic members, the static member list will
+be checked first.
+.SH CONFIGURATION
+This
+.B slapd.conf
+option applies to the Dynamic Group overlay.
+It should appear after the
+.B overlay
+directive.
+.TP
+.B attrpair <memberAttr> <URLattr>
+Specify the attributes to be compared. A compare operation on the
+.I memberAttr
+will cause the
+.I URLattr
+to be evaluated for the result.
+.SH EXAMPLES
+.nf
+  database bdb
+  ...
+  overlay dyngroup
+  attrpair member memberURL
+.fi
+.SH FILES
+.TP
+ETCDIR/slapd.conf
+default slapd configuration file
+.SH SEE ALSO
+.BR slapd.conf (5).
+.SH AUTHOR
+Howard Chu
index 4a1be5723208847cd0010b60a12b848a2c4e7f76..7ae8d92686db1cba8313053efd309047d926e689 100644 (file)
@@ -3,7 +3,7 @@
 .\" Copying restrictions apply.  See the COPYRIGHT file.
 .\" $OpenLDAP$
 .SH NAME
-slapo-dynlist \- Dynamic List overlay
+slapo-dynlist \- Dynamic List overlay to slapd
 .SH SYNOPSIS
 ETCDIR/slapd.conf
 .SH DESCRIPTION
@@ -45,7 +45,7 @@ for details.
 .LP
 This
 .B slapd.conf
-configuration option is define for the dynlist overlay. It may have multiple 
+configuration option is defined for the dynlist overlay. It may have multiple 
 occurrences, and it must appear after the
 .B overlay
 directive.
@@ -58,7 +58,7 @@ data.
 
 The value
 .B <URL-ad>
-is the name of the attributeDescription that cointains the URI that is 
+is the name of the attributeDescription that contains the URI that is 
 expanded by the overlay; if none is present, no expansion occurs.
 If the intersection of the attributes requested by the search operation 
 (or the asserted attribute for compares) and the attributes listed 
@@ -89,6 +89,18 @@ In case the URI expansion is very resource-intensive and occurs frequently
 with well-defined patterns, one should consider adding a proxycache
 later on in the overlay stack.
 
+.SH AUTHORIZATION
+By default the expansions are performed using the identity of the current
+LDAP user. This identity may be overridden by setting the
+.B dgIdentity
+attribute to the DN of another LDAP user. In that case the dgIdentity
+will be used when expanding the URIs in the object. Setting the dgIdentity
+to a zero-length string will cause the expansions to be performed
+anonymously. Note that the dgIdentity attribute is defined in the
+.B dyngroup
+schema, and this schema must be loaded before the dgIdentity
+authorization feature may be used.
+
 .SH EXAMPLE
 This example collects all the email addresses of a database into a single
 entry; first of all, make sure that slapd.conf contains the directives:
@@ -135,6 +147,18 @@ attribute:
 .fi
 .LP
 
+A dynamic group with dgIdentity authorization could be created with an
+entry like
+.LP
+.nf
+    dn: cn=Dynamic Group,ou=Groups,dc=example,dc=com
+    objectClass: groupOfURLs
+    objectClass: dgIdentityAux
+    cn: Dynamic Group
+    memberURL: ldap:///ou=People,dc=example,dc=com??sub?(objectClass=person)
+    dgIdentity: cn=Group Proxy,ou=Services,dc=example,dc=com
+.fi
+
 .SH FILES
 .TP
 ETCDIR/slapd.conf
diff --git a/doc/man/man5/slapo-memberof.5 b/doc/man/man5/slapo-memberof.5
new file mode 100644 (file)
index 0000000..b9f6e06
--- /dev/null
@@ -0,0 +1,114 @@
+.TH SLAPO-MEMBEROF 5 "RELEASEDATE" "OpenLDAP LDVERSION"
+.\" Copyright 1998-2007 The OpenLDAP Foundation, All Rights Reserved.
+.\" Copying restrictions apply.  See the COPYRIGHT file.
+.\" $OpenLDAP$
+.SH NAME
+slapo-memberof \- Reverse Group Membership overlay to slapd
+.SH SYNOPSIS
+ETCDIR/slapd.conf
+.SH DESCRIPTION
+The
+.B memberof
+overlay to
+.BR slapd (8)
+allows automatic reverse group membership maintenance.
+Any time a group entry is modified, its members are modified as appropriate
+in order to keep a DN-valued "is member of" attribute updated with the DN
+of the group.
+
+.SH CONFIGURATION
+The config directives that are specific to the
+.B memberof
+overlay must be prefixed by
+.BR memberof\- ,
+to avoid potential conflicts with directives specific to the underlying 
+database or to other stacked overlays.
+
+.TP
+.B overlay memberof
+This directive adds the memberof overlay to the current database; see
+.BR slapd.conf (5)
+for details.
+
+.LP
+The following
+.B slapd.conf
+configuration options are defined for the memberofoverlay.
+
+.TP
+.B memberof-group-oc <group-oc>
+The value 
+.B <group-oc> 
+is the name of the objectClass that triggers the reverse group membership
+update.
+It defaults to \fIgroupOfNames\fP.
+
+.TP
+.B memberof-member-ad <member-ad>
+The value 
+.B <member-ad> 
+is the name of the attribute that contains the names of the members
+in the group objects; it must be DN-valued.
+It defaults to \fImember\fP.
+
+.TP
+.B memberof-memberof-ad <memberof-ad>
+The value 
+.B <memberof-ad> 
+is the name of the attribute that contains the names of the groups
+an entry is member of; it must be DN-valued.  Its contents are 
+automatically updated by the overlay.
+It defaults to \fImemberOf\fP.
+
+.TP
+.B memberof-dn <dn>
+The value 
+.B <dn> 
+contains the DN that is used as \fImodifiersName\fP for internal 
+modifications performed to update the reverse group membership.
+It defaults to the \fIrootdn\fP of the underlying database.
+
+.TP
+.B memberof-dangling {ignore, drop, error}
+This option determines the behavior of the overlay when, during 
+a modification, it encounters dangling references.
+The default is
+.BR ignore ,
+which may leave dangling references.
+Other options are
+.BR drop ,
+which discards those modifications that would result in dangling
+references, and
+.BR error ,
+which causes modifications that would result in dangling references
+to fail.
+
+.TP
+.B memberof-refint {true|FALSE}
+This option determines whether the overlay will try to preserve
+referential integrity or not.
+If set to
+.BR TRUE ,
+when an entry containing values of the "is member of" attribute is modified,
+the corresponding groups are modified as well.
+
+.LP
+The memberof overlay may be used with any backend that provides full 
+read-write functionality, but it is mainly intended for use 
+with local storage backends.
+
+.SH FILES
+.TP
+ETCDIR/slapd.conf
+default slapd configuration file
+.SH SEE ALSO
+.BR slapd.conf (5),
+.BR slapd (8).
+The
+.BR slapo-memberof (5)
+overlay supports dynamic configuration via
+.BR back-config .
+.SH ACKNOWLEDGEMENTS
+.P
+This module was written in 2005 by Pierangelo Masarati for SysNet s.n.c.
+
index f20270945e7d0365162256d745cc1c846022acbe..032f3250672e2eafc9e52498ceef022c374069b0 100644 (file)
@@ -4,7 +4,7 @@
 .\" Copyright 2001, Pierangelo Masarati, All rights reserved. <ando@sys-net.it>
 .\" $OpenLDAP$
 .SH NAME
-slapo-pcache \- proxycache overlay
+slapo-pcache \- proxycache overlay to slapd
 .SH SYNOPSIS
 ETCDIR/slapd.conf
 .SH DESCRIPTION
@@ -67,15 +67,39 @@ returned is less than <entry_limit>. Consistency check is performed every
 .RS
 proxycache \fBbdb 10000 1 50 100\fP
 .RE
+
 .TP
 .B proxycachequeries <queries>
 Specify the maximum number of queries to cache. The default is 10000.
 
+.TP
+.B proxysavequeries { TRUE | FALSE }
+Specify whether the cached queries should be saved across restarts
+of the caching proxy, to provide hot startup of the cache.  Only non-expired
+queries are reloaded.  The default is FALSE.
+
+.BR CAVEAT :
+of course, the configuration of the proxycache must not change
+across restarts; the pcache overlay does not perform any consistency
+checks in this sense.
+In detail, this option should be disabled unless the existing
+.B proxyattrset
+and
+.B proxytemplate
+directives are not changed neither in order nor in contents.
+If new sets and templates are added, or if other details of the pcache
+overlay configuration changed, this feature should not be affected.
+
 .TP
 .B proxyattrset <index> <attrs...>
 Used to associate a set of attributes <attrs..> with an <index>. Each attribute
 set is associated with an integer from 0 to <numattrsets>-1. These indices are
 used by the \fBproxytemplate\fP directive to define cacheable templates. 
+A set of attributes cannot be empty.  A set of attributes can contain the
+special attributes "*" (all user attributes), "+" (all operational attributes)
+or both; in the latter case, any other attribute is redundant and should
+be avoided for clarity.  A set of attributes can contain "1.1" as the only
+attribute; in this case, only the presence of the entries is cached.
 
 .TP
 .B proxytemplate <template_string> <attrset_index> <ttl> [<negttl>]
index 5a507e176bb272ce09a0cb454c4f8666f4e7357d..95335dcfad5639dab6e3e51131be873383609587 100644 (file)
@@ -3,7 +3,7 @@
 .\" Copying restrictions apply.  See COPYRIGHT/LICENSE.
 .TH SLAPO_PPOLICY 5 "RELEASEDATE" "OpenLDAP LDVERSION"
 .SH NAME
-slapo-ppolicy \- Password Policy overlay
+slapo-ppolicy \- Password Policy overlay to slapd
 .SH SYNOPSIS
 ETCDIR/slapd.conf
 .SH DESCRIPTION
@@ -565,7 +565,7 @@ This attribute contains the time that the user's account was locked.
 If the account has been locked, the password may no longer be used to
 authenticate the user to the directory.  If
 .B pwdAccountLockedTime   
-is set to zero (0), the user's account has been permanently locked
+is set to 000001010000Z, the user's account has been permanently locked
 and may only be unlocked by an administrator.
 .LP
 .RS 4
index 1881b8de90e6a652e0a6627f53fea53d3eb94b8d..5d4ae9382894fea6e17ed9ead571f4949931e7d3 100644 (file)
@@ -3,7 +3,7 @@
 .\" Copying restrictions apply.  See COPYRIGHT/LICENSE.
 .\" $OpenLDAP$
 .SH NAME
-slapo-refint \- Referential Integrity overlay
+slapo-refint \- Referential Integrity overlay to slapd
 .SH SYNOPSIS
 ETCDIR/slapd.conf
 .SH DESCRIPTION
index 313dd228ebc026ad921fb35eccc2a0650b9a8a40..9b1b4bb338d7cb760df01a0fe813765598736a51 100644 (file)
@@ -4,7 +4,7 @@
 .\" Copyright 2001, Pierangelo Masarati, All rights reserved. <ando@sys-net.it>
 .\" $OpenLDAP$
 .SH NAME
-slapo-retcode \- return code overlay
+slapo-retcode \- return code overlay to slapd
 .SH SYNOPSIS
 ETCDIR/slapd.conf
 .SH DESCRIPTION
index 9ab1c1b3b7f7a41c682d8a0fe0f7d79d84cbaf61..dddf0a7deb0f0be62775c82fe0be3678542307e6 100644 (file)
@@ -8,7 +8,7 @@
 .\" and maybe manual pages for librewrite.
 .\"
 .SH NAME
-slapo-rwm \- rewrite/remap overlay
+slapo-rwm \- rewrite/remap overlay to slapd
 .SH SYNOPSIS
 ETCDIR/slapd.conf
 .SH DESCRIPTION
@@ -71,6 +71,24 @@ defined as using the distinguishedName syntax.
 Also, note that there are DN-related syntaxes (i.e. compound types with
 a portion that is DN-valued), like nameAndOptionalUID,
 whose values are currently not rewritten.
+.LP
+If the foreign type of an attribute mapping is not defined on the local 
+server, it might be desirable to have the attribute values normalized after
+the mapping process. Not normalizing the values can lead to wrong results, 
+when the
+.B rwm
+overlay is used together with e.g. the
+.B pcache
+overlay. This normalization can be enabled by means of the 
+.B rwm-normalize-mapped-attrs
+directive.
+.TP
+.B rwm-normalize-mapped-attrs {yes|no}
+Set this to "yes", if the
+.B rwm
+overlay should try to normalize the values of attributes that are mapped from
+an attribute type that is unknown to the local server. The default value of
+this setting is "no".
 .SH SUFFIX MASSAGING
 A basic feature of the
 .B rwm
@@ -78,6 +96,20 @@ overlay is the capability to perform suffix massaging between a virtual
 and a real naming context by means of the 
 .B rwm-suffixmassage
 directive.
+This, in conjunction with proxy backends,
+.BR slapd-ldap (5)
+and
+.BR slapd-meta (5),
+or with the relay backend, 
+.BR slapd-relay (5),
+allows to create virtual views of databases.
+A distinguishing feature of this overlay is that, when instantiated
+before any database, it can modify the DN of requests
+.I before
+database selection.
+For this reason, rules that rewrite the empty DN ("") 
+or the subschemaSubentry DN (usually "cn=subschema"),
+would prevent clients from reading the root DSE or the DSA's schema.
 .TP
 .B rwm-suffixmassage "[<virtual naming context>]" "<real naming context>"
 Shortcut to implement naming context rewriting; the trailing part
index 1b3059c3eb05c7db66ef2f154efd2b706be90d54..c6bc84bac160ab4bb2de29b58c1f1af6b7d2fd74 100644 (file)
@@ -3,7 +3,7 @@
 .\" Copying restrictions apply.  See COPYRIGHT/LICENSE.
 .\" $OpenLDAP$
 .SH NAME
-slapo-syncprov \- Sync Provider overlay
+slapo-syncprov \- Sync Provider overlay to slapd
 .SH SYNOPSIS
 ETCDIR/slapd.conf
 .SH DESCRIPTION
@@ -21,9 +21,6 @@ memory on startup, and maintained in memory thereafter. Checkpoints may be
 configured to write the contextCSN into the underlying database to minimize
 recovery time after an unclean shutdown.
 
-Note that due to deadlock constraints in the LDBM database, this overlay
-will only work in RefreshOnly mode, and cannot perform checkpoints, on LDBM.
-
 On databases that support inequality indexing, it is helpful to set an
 eq index on the entryCSN attribute when using this overlay.
 .SH CONFIGURATION
index 3afec26d721b3ac1d35c7ebdde9976fabf6ad8cb..f33c14c98e8c787198fb6a21dfc37a93bbd01a29 100644 (file)
@@ -3,7 +3,7 @@
 .\" Copying restrictions apply.  See COPYRIGHT/LICENSE.
 .\" $OpenLDAP$
 .SH NAME
-slapo-translucent \- Translucent Proxy overlay
+slapo-translucent \- Translucent Proxy overlay to slapd
 .SH SYNOPSIS
 ETCDIR/slapd.conf
 .SH DESCRIPTION
index e25df849188eb7d4750eecd80d466b5772006fb6..b5de5e88447c8782d17f9547a22af97deedc09bb 100644 (file)
@@ -3,15 +3,15 @@
 .\" Copying restrictions apply.  See COPYRIGHT/LICENSE.
 .\" $OpenLDAP$
 .SH NAME
-slapo-unique \- Attribute Uniqueness overlay
+slapo-unique \- Attribute Uniqueness overlay to slapd
 .SH SYNOPSIS
 ETCDIR/slapd.conf
 .SH DESCRIPTION
 The Attribute Uniqueness overlay can be used with a backend database such as
 .BR slapd-bdb (5)
-to enforce the uniqueness of some or all attributes within a subtree. This
-subtree defaults to the base DN of the database for which the Uniqueness
-overlay is configured.
+to enforce the uniqueness of some or all attributes within a
+scope. This subtree defaults to all objects within the subtree of the
+database for which the Uniqueness overlay is configured.
 .LP
 Uniqueness is enforced by searching the subtree to ensure that the values of
 all attributes presented with an
@@ -19,7 +19,7 @@ all attributes presented with an
 .B modify
 or
 .B modrdn
-operation are unique within the subtree.
+operation are unique within the scope.
 For example, if uniqueness were enforced for the
 .B uid
 attribute, the subtree would be searched for any other records which also
@@ -35,18 +35,59 @@ They should appear after the
 .B overlay
 directive.
 .TP
-.B unique_base <basedn>
-Configure the subtree against which uniqueness searches will be invoked.
+.B unique_uri <[strict ][ignore ]URI[URI...]...>
+Configure the base, attributes, scope, and filter for uniqueness
+checking.  Multiple URIs may be specified within a domain, allowing complex selections of objects.  Multiple
+.B unique_uri
+statements or
+.B olcUniqueURI
+attributes will create independent domains, each with their own independent lists of URIs and ignore/strict settings.
+
+The LDAP URI syntax is a subset of
+.B RFC-4516,
+and takes the form:
+
+ldap:///[base dn]?[attributes...]?scope[?filter]
+
 The
-.B basedn
-defaults to the base DN of the database for which uniqueness is configured.
-.TP
-.B unique_ignore <attribute...>
-Configure one or more attributes for which uniqueness will not be enforced.
-If not configured, all non-operational (eg, system) attributes must be
+.B base dn
+defaults to that of the back-end database.  Specified base dns must be within the subtree of the back-end database.
+
+If no
+.B attributes
+are specified, the URI applies to all non-operational attributes.
+
+The
+.B scope
+component is effectively mandatory, because LDAP URIs default to
+.B base
+scope, which is not valid for uniqueness, because groups of one object
+are always unique.  Scopes of
+.B sub
+(for subtree) and
+.B one
+for one-level are valid.
+
+The
+.B filter
+component causes the domain to apply uniqueness constraints only to
+matching objects.  e.g.
+.B ldap:///?cn?sub?(sn=e*)
+would require unique
+.B cn
+attributes for all objects in the subtree of the back-end database whose
+.B sn
+starts with an e.
+
+It is possible to assert uniqueness upon all non-operational
+attributes except those listed by prepending the keyword
+.B ignore
+If not configured, all non-operational (e.g., system) attributes must be
 unique. Note that the
-.B unique_ignore
-list should generally contain the
+.B attributes
+list of an
+.B ignore
+URI should generally contain the
 .BR objectClass ,
 .BR dc ,
 .B ou
@@ -54,42 +95,55 @@ and
 .B o
 attributes, as these will generally not be unique, nor are they operational
 attributes.
+
+It is possible to set strict checking for the uniqueness domain by
+prepending the keyword
+.B strict.
+By default, uniqueness is not enforced
+for null values. Enabling
+.B strict
+mode extends the concept of uniqueness to include null values, such
+that only one attribute within a subtree will be allowed to have a
+null value.  Strictness applies to all URIs within a uniqueness
+domain, but some domains may be strict while others are not.
+.LP
+It is not possible to set both URIs and legacy slapo-unique configuration parameters simultaneously.  In general, the legacy configuration options control pieces of a single unfiltered subtree domain.
+.TP
+.B unique_base <basedn>
+This legacy configuration parameter should be converted to the
+.B base dn
+component of the above
+.B unique_uri
+style of parameter.
+.TP
+.B unique_ignore <attribute...>
+This legacy configuration parameter should be converted to a
+.B unique_uri
+parameter with
+.B ignore
+keyword as described above.
 .TP
 .B unique_attributes <attribute...>
-Specify one or more attributes for which uniqueness will be enforced.
-If not specified, all attributes which are not operational (eg, system
-attributes such as
-.B entryUUID )
-or specified via the
-.B unique_ignore
-directive above must be unique within the subtree.
+This legacy configuration parameter should be converted to a
+.B unique_uri
+parameter, as described above.
 .TP
 .B unique_strict
-By default, uniqueness is not enforced for null values. Enabling
-.B unique_strict
-mode extends the concept of uniqueness to include null values, such that
-only one attribute within a subtree will be allowed to have a null value.
+This legacy configuration parameter should be converted to a
+.B strict
+keyword prepended to a
+.B unique_uri
+parameter, as described above.
 .SH CAVEATS
 .LP
-The search key is generated with attributes that are non-operational, not
-on the
-.B unique_ignore
-list, and included in the
-.B unique_attributes
-list, in that order. This makes it possible to create interesting and
-unusable configurations. Usually only one of
-.B unique_ignore
-or
-.B unique_attributes
-should be configured; use
-.B unique_ignore
-if the majority of attributes should be unique, and use
-.B unique_attributes
-if only a small set of attributes should be unique.
+.B unique_uri
+cannot be used with the old-style of configuration, and vice versa.
+.B unique_uri
+can implement everything the older system can do, however.
 .LP
 Typical attributes for the
-.B unique_ignore
-directive are intentionally not hardcoded into the overlay to allow for
+.B ignore ldap:///...
+URIs are intentionally not hardcoded into the overlay to allow for
 maximum flexibility in meeting site-specific requirements.
 .SH FILES
 .TP
index 3b483bb9c4576eaa128bc2f094dbe95badee24d2..453b8c9afc9482a045dc304009b541442515fe23 100644 (file)
@@ -3,7 +3,7 @@
 .\" Copying restrictions apply.  See COPYRIGHT/LICENSE.
 .\" $OpenLDAP$
 .SH NAME
-slapo-valsort \- Value Sorting overlay
+slapo-valsort \- Value Sorting overlay to slapd
 .SH SYNOPSIS
 ETCDIR/slapd.conf
 .SH DESCRIPTION
index deaea256658c80d7803cba2012efdacf50f14bc8..7cecd3d527030834689c431c3714072a47041735 100644 (file)
@@ -8,15 +8,17 @@ slapadd \- Add entries to a SLAPD database
 .B SBINDIR/slapadd
 .B [\-b suffix]
 .B [\-c]
-.B [\-g]
 .B [\-d level]
 .B [\-f slapd.conf]
 .B [\-F confdir]
+.B [\-g]
 .B [\-j lineno]
 .B [\-l ldif-file]
 .B [\-n dbnum]
 .B [\-o name[=value]
 .B [\-q]
+.B [\-s]
+.B [\-S SID]
 .B [\-u]
 .B [\-v]
 .B [\-w]
@@ -118,6 +120,10 @@ databases containing special objects, such as fractional objects on a
 partial replica.  Loading normal objects which do not conform to
 schema may result in unexpected and ill behavior.
 .TP
+.B \-S " SID"
+Server ID to use in generated entryCSN.  Also used for contextCSN
+if `\-w' is set as well.  Defaults to 0.
+.TP
 .B \-u
 enable dry-run (don't write to backend) mode.
 .TP
index 84201845048db140f1fed010883345f5209d1ff1..14a4a033a57c8c27e872fa14d7d1a59f950def82 100644 (file)
@@ -2,7 +2,7 @@
 .\" Copyright 2004-2007 The OpenLDAP Foundation All Rights Reserved.
 .\" Copying restrictions apply.  See COPYRIGHT/LICENSE.
 .SH NAME
-slapauth \- Check a list of string-represented IDs for authc/authz.
+slapauth \- Check a list of string-represented IDs for LDAP authc/authz
 .SH SYNOPSIS
 .B SBINDIR/slapauth
 .B [\-d level]
index 498d148125df576f6eadb718a4278472180d0da7..f591a658faf82dad3afd6d5addb297c247b44808 100644 (file)
@@ -134,10 +134,18 @@ option is given.
 .B \-v
 Enable verbose mode.
 .SH LIMITATIONS
-In general, your
+For some backend types, your
 .BR slapd (8)
 should not be running (at least, not in read-write
-mode) when you do this to ensure consistency of the database.
+mode) when you do this to ensure consistency of the database. It is
+always safe to run 
+.B slapcat
+with the
+.BR slapd-bdb (5),
+.BR slapd-hdb (5),
+and
+.BR slapd-null (5)
+backends.
 .SH EXAMPLES
 To make a text backup of your SLAPD database and put it in a file called
 .BR ldif ,
index bb070483e19649f1ddd457e020f344be238ffda8..0fd19df9f84446c5282dadb746dc43a4fa24ce55 100644 (file)
@@ -46,15 +46,6 @@ flag is given, even with a zero argument,
 .B slapd
 will not fork and disassociate from the invoking tty.
 .LP
-.B Slapd
-can be configured to provide replicated service for a database with
-the help of
-.BR slurpd ,
-the standalone LDAP update replication daemon.
-See
-.BR slurpd (8)
-for details.
-.LP
 See the "OpenLDAP Administrator's Guide" for more details on
 .BR slapd .
 .SH OPTIONS
@@ -262,7 +253,7 @@ registers at SLP DAs with the three SLP attributes tree, server-type and server-
 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.
+tree in case multiple trees are available.
 .RE
 .SH EXAMPLES
 To start 
@@ -306,8 +297,7 @@ To test whether the configuration file is correct or not, type:
 .BR slapdn (8),
 .BR slapindex (8),
 .BR slappasswd (8),
-.BR slaptest (8),
-.BR slurpd (8)
+.BR slaptest (8).
 .LP
 "OpenLDAP Administrator's Guide" (http://www.OpenLDAP.org/doc/admin/)
 .SH BUGS
index 4455dc960b798f749e71522c5b4ba460d4ed29e7..e07fac12064a0375e168f4cd0f36df76c6fc1bc5 100644 (file)
@@ -2,7 +2,7 @@
 .\" Copyright 2004-2007 The OpenLDAP Foundation All Rights Reserved.
 .\" Copying restrictions apply.  See COPYRIGHT/LICENSE.
 .SH NAME
-slapdn \- Check a list of string-represented DNs based on schema syntax.
+slapdn \- Check a list of string-represented LDAP DNs based on schema syntax
 .SH SYNOPSIS
 .B SBINDIR/slapdn
 .B [\-d level]
index a9a66c62419039f2de2651e5d5d5ee5980825add..809669787fa1b2422373807ee7d1ca10575a71c8 100644 (file)
@@ -2,13 +2,14 @@
 .\" Copyright 2004-2007 The OpenLDAP Foundation All Rights Reserved.
 .\" Copying restrictions apply.  See COPYRIGHT/LICENSE.
 .SH NAME
-slaptest \- Check the suitability of the slapd.conf file.
+slaptest \- Check the suitability of the OpenLDAP slapd.conf file
 .SH SYNOPSIS
 .B SBINDIR/slaptest
 .B [\-d level]
 .B [\-f slapd.conf]
 .B [\-F confdir]
 .B [\-o name[=value]
+.B [\-Q]
 .B [\-u]
 .B [\-v]
 .LP
@@ -65,11 +66,15 @@ Possible generic options/values are:
 
 .fi
 .TP
-.B \-u
+.BI \-Q
+Be extremely quiet: only the exit code indicates success (0) or not 
+(any other value).
+.TP
+.BI \-u
 enable dryrun mode (i.e. don't fail if databases cannot be opened,
 but config is fine).
 .TP
-.B \-v
+.BI \-v
 enable verbose mode.
 .SH EXAMPLES
 To check a 
diff --git a/doc/man/man8/slurpd.8 b/doc/man/man8/slurpd.8
deleted file mode 100644 (file)
index 0f7a303..0000000
+++ /dev/null
@@ -1,160 +0,0 @@
-.TH SLURPD 8C "RELEASEDATE" "OpenLDAP LDVERSION"
-.\" $OpenLDAP$
-.\" Copyright 1998-2007 The OpenLDAP Foundation All Rights Reserved.
-.\" Copying restrictions apply.  See COPYRIGHT/LICENSE.
-.SH NAME
-slurpd \- Standalone LDAP Update Replication Daemon
-.SH SYNOPSIS
-.B LIBEXECDIR/slurpd [\-d debug\-level]
-.B [\-f slapd\-config\-file] [\-r slapd\-replog\-file]
-.B [\-t temp\-dir] [\-o]
-.B 
-.SH DESCRIPTION
-.LP
-.B Slurpd
-is used to propagate changes from one slapd database to another.  If
-slapd is configured to produce a replication log, 
-.B slurpd
-reads that
-replication log and sends the changes to the slave 
-.B slapd
-instances
-via the LDAP protocol.
-.B slurpd
-is typically invoked at boot time, usually out of
-.BR  /etc/rc.local .
-.LP
-Upon startup,
-.B slurpd
-normally forks and disassociates itself from the invoking tty,
-then reads the replication log (given either by the
-.I replogfile
-directive in the 
-.B slapd
-config file, or by the
-.RB \- r
-command-line option).
-If the replication log file does not exist or is empty,
-.B slurpd
-goes to sleep.  It periodically wakes up and checks to see if there
-are any changes to be propagated.
-.LP
-When
-.B slurpd
-notices that there are changes to propagate to slave 
-.B slapd
-instances, it locks the replication log, makes its own private copy,
-releases the lock, and forks one copy of itself for each replica
-.B slapd
-to be updated.  Each child process binds to the slave 
-.B slapd
-as the
-DN given by the
-.I binddn
-option to the
-.I replica
-directive in the
-.B slapd
-config file, and sends the changes.
-.LP
-See
-.BR slapd (8)
-for details on the standalone LDAP daemon.
-.LP
-Note that slurpd reads
-.B replication
-directive from
-.BR slapd.conf (5),
-but uses
-.BR ldap.conf (5)
-to obtain other configuration settings (such as TLS settings).
-.SH OPTIONS
-.TP
-.BI \-d " debug\-level"
-Turn on debugging as defined by
-.I debug\-level.
-If this option is specified, even with a zero argument,
-.B slurpd
-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.
-.TP
-.BI \-f " slapd\-config\-file"
-Specifies the slapd configuration file.  The default is
-.BR ETCDIR/slapd.conf .
-.TP
-.BI \-r " slapd\-replog\-file"
-Specifies the name of the 
-.B slapd
-replication logfile.  Normally, the name
-of the replication log file is read from the 
-.B slapd
-configuration file.  The file should be located in a directory
-with limited read/write/execute access.
-The
-.B \-r
-option allows you to override this.  In conjunction with the
-.B \-o
-option, you can process a replication log file in a "one\-shot" mode.  For
-example, if 
-.B slurpd
-has encountered errors in processing a replication log,
-you can run it in one\-shot mode and give the rejection file name as
-the argument to the \-r option, once you've resolved the problem which caused
-the replication to fail.
-.TP
-.B \-o
-Run in "one\-shot" mode.  Normally, 
-.B slurpd
-processes the replog file
-and then watches for more replication entries to be appended.  In
-one\-shot mode, 
-.B slurpd
-processes a replication log and exits.
-.TP
-.BI \-t " temp\-dir"
-.B slurpd
-copies the replication log to a working directory before processing it.
-The directory permissions should limit read/write/execute access as
-temporary files may contain sensitive information.
-This option allows you to specify the location of these temporary files. 
-The default is
-.BR LOCALSTATEDIR/openldap-slurp .
-.SH EXAMPLES
-To start 
-.I slurpd
-and have it fork and detach from the terminal and process
-the replication logs generated by
-.I slapd,
-just type:
-.LP
-.nf
-.ft tt
-       LIBEXECDIR/slurpd
-.ft
-.fi
-.LP
-To start 
-.I slurpd
-with an alternate 
-.I slapd
-configuration file, and turn
-on voluminous debugging which will be printed on standard error, type:
-.LP
-.nf
-.ft tt
-       LIBEXECDIR/slurpd -f ETCDIR/slapd.conf -d 255
-.ft
-.fi
-.LP
-.SH "SEE ALSO"
-.BR ldap (3),
-.BR ldap.conf (5),
-.BR slapd.conf (5),
-.BR slapd.replog (5),
-.BR slapd (8)
-.LP
-"OpenLDAP Administrator's Guide" (http://www.OpenLDAP.org/doc/admin/)
-.SH ACKNOWLEDGEMENTS
-.so ../Project
index 4420833bff5add2c4d218ddaaff18167df44757b..3908e3265d6d3d30b73ac408d7a4d20c6078f711 100644 (file)
@@ -64,6 +64,7 @@ rfc4530.txt LDAP: entryUUID (PS)
 rfc4531.txt LDAP Turn Operation (E)
 rfc4532.txt LDAP Who am I? Operation (PS)
 rfc4533.txt LDAP Content Sync Operation (E)
+rfc5020.txt LDAP 'entryDN' operational attribute (PS)
 
 Legend:
 STD    Standard
diff --git a/doc/rfc/rfc5020.txt b/doc/rfc/rfc5020.txt
new file mode 100644 (file)
index 0000000..e289f8b
--- /dev/null
@@ -0,0 +1,283 @@
+
+
+
+
+
+
+Network Working Group                                        K. Zeilenga
+Request for Comments: 5020                                 Isode Limited
+Category: Standards Track                                    August 2007
+
+
+       The Lightweight Directory Access Protocol (LDAP) entryDN
+                         Operational Attribute
+
+Status of This Memo
+
+   This document specifies an Internet standards track protocol for the
+   Internet community, and requests discussion and suggestions for
+   improvements.  Please refer to the current edition of the "Internet
+   Official Protocol Standards" (STD 1) for the standardization state
+   and status of this protocol.  Distribution of this memo is unlimited.
+
+Copyright Notice
+
+   Copyright (C) The IETF Trust (2007).
+
+Abstract
+
+   This document describes the Lightweight Directory Access Protocol
+   (LDAP) / X.500 'entryDN' operational attribute.  The attribute
+   provides a copy of the entry's distinguished name for use in
+   attribute value assertions.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Zeilenga                    Standards Track                     [Page 1]
+\f
+RFC 5020                      LDAP entryDN                   August 2007
+
+
+1.  Background and Intended Use
+
+   In X.500 Directory Services [X.501], such as those accessible using
+   the Lightweight Directory Access Protocol (LDAP) [RFC4510], an entry
+   is identified by its distinguished name (DN) [RFC4512].  However, as
+   an entry's DN is not an attribute of the entry, it is not possible to
+   perform attribute value assertions [RFC4511] against it.
+
+   This document describes the 'entryDN' operational attribute which
+   holds a copy of the entry's distinguished name.  This attribute may
+   be used in search filters.  For instance, searching the subtree
+   <dc=example,dc=com> with the filter:
+
+      (entryDN:componentFilterMatch:=or:{
+          item:{ component "3", rule rdnMatch, value "ou=A" },
+          item:{ component "3", rule rdnMatch, value "ou=B" } })
+
+   would return entries in the subtree <ou=A,dc=example,dc=com> and
+   entries in subtree <ou=B,dc=example,dc=com>, but would not return any
+   other entries in the subtree <dc=example,dc=com>.
+
+   In the above paragraph, DNs are presented using the string
+   representation defined in [RFC4514], and the example search filter is
+   presented using the string representation defined in [RFC4515] with
+   whitespace (line breaks and indentation) added to improve
+   readability.  The 'componentFilterMatch' and 'rdnMatch' rules are
+   specified in [RFC3687].
+
+   Schema definitions are provided using LDAP description formats
+   [RFC4512].  Definitions provided here are formatted (line wrapped)
+   for readability.
+
+2.  'entryDN' Operational Attribute
+
+   The 'entryDN' operational attribute provides a copy of the entry's
+   current DN.
+
+   The following is an LDAP attribute type description suitable for
+   publication in subschema subentries.
+
+      ( 1.3.6.1.1.20 NAME 'entryDN'
+          DESC 'DN of the entry'
+          EQUALITY distinguishedNameMatch
+          SYNTAX 1.3.6.1.4.1.1466.115.121.1.12
+          SINGLE-VALUE
+          NO-USER-MODIFICATION
+          USAGE directoryOperation )
+
+
+
+
+Zeilenga                    Standards Track                     [Page 2]
+\f
+RFC 5020                      LDAP entryDN                   August 2007
+
+
+   Note that the DN of the entry cannot be modified through this
+   attribute.
+
+3.  Security Considerations
+
+   As this attribute only provides an additional mechanism to access an
+   entry's DN, the introduction of this attribute is not believed to
+   introduce new security considerations.
+
+4.  IANA Considerations
+
+4.1.  Object Identifier Registration
+
+   IANA has registered (upon Standards Action) an LDAP Object Identifier
+   [RFC4520] for use in this document.
+
+      Subject: Request for LDAP OID Registration
+      Person & email address to contact for further information:
+          Kurt Zeilenga <Kurt.Zeilenga@Isode.COM>
+      Specification: RFC 5020
+      Author/Change Controller: IESG
+      Comments:
+          Identifies the 'entryDN' attribute type
+
+4.2.  'entryDN' Descriptor Registration
+
+   IANA has registered (upon Standards Action) the LDAP 'entryDN'
+   descriptor [RFC4520].
+
+      Subject: Request for LDAP Descriptor Registration
+      Descriptor (short name): entryDN
+      Object Identifier: 1.3.6.1.1.20
+      Person & email address to contact for further information:
+          Kurt Zeilenga <Kurt.Zeilenga@Isode.COM>
+      Usage: Attribute Type
+      Specification: RFC 5020
+      Author/Change Controller: IESG
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Zeilenga                    Standards Track                     [Page 3]
+\f
+RFC 5020                      LDAP entryDN                   August 2007
+
+
+5.  References
+
+5.1.  Normative References
+
+   [RFC4510]   Zeilenga, K., Ed., "Lightweight Directory Access Protocol
+               (LDAP): Technical Specification Road Map", RFC 4510, June
+               2006.
+
+   [RFC4512]   Zeilenga, K., Ed., "Lightweight Directory Access Protocol
+               (LDAP): Directory Information Models", RFC 4512, June
+               2006.
+
+   [X.501]     International Telecommunication Union - Telecommunication
+               Standardization Sector, "The Directory -- Models,"
+               X.501(1993) (also ISO/IEC 9594-2:1994).
+
+5.2.  Informative References
+
+   [RFC3687]   Legg, S., "Lightweight Directory Access Protocol (LDAP)
+               and X.500 Component Matching Rules", RFC 3687, February
+               2004.
+
+   [RFC4511]   Sermersheim, J., Ed., "Lightweight Directory Access
+               Protocol (LDAP): The Protocol", RFC 4511, June 2006.
+
+   [RFC4514]   Zeilenga, K., Ed., "Lightweight Directory Access Protocol
+               (LDAP): String Representation of Distinguished Names",
+               RFC 4514, June 2006.
+
+   [RFC4515]   Smith, M., Ed., and T. Howes, "Lightweight Directory
+               Access Protocol (LDAP): String Representation of Search
+               Filters", RFC 4515, June 2006.
+
+   [RFC4520]   Zeilenga, K., "Internet Assigned Numbers Authority (IANA)
+               Considerations for the Lightweight Directory Access
+               Protocol (LDAP)", BCP 64, RFC 4520, June 2006.
+
+Author's Address
+
+   Kurt D. Zeilenga
+   Isode Limited
+
+   EMail: Kurt.Zeilenga@Isode.COM
+
+
+
+
+
+
+
+
+Zeilenga                    Standards Track                     [Page 4]
+\f
+RFC 5020                      LDAP entryDN                   August 2007
+
+
+Full Copyright Statement
+
+   Copyright (C) The IETF Trust (2007).
+
+   This document is subject to the rights, licenses and restrictions
+   contained in BCP 78, and except as set forth therein, the authors
+   retain all their rights.
+
+   This document and the information contained herein are provided on an
+   "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS
+   OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY, THE IETF TRUST AND
+   THE INTERNET ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF
+   THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED
+   WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Intellectual Property
+
+   The IETF takes no position regarding the validity or scope of any
+   Intellectual Property Rights or other rights that might be claimed to
+   pertain to the implementation or use of the technology described in
+   this document or the extent to which any license under such rights
+   might or might not be available; nor does it represent that it has
+   made any independent effort to identify any such rights.  Information
+   on the procedures with respect to rights in RFC documents can be
+   found in BCP 78 and BCP 79.
+
+   Copies of IPR disclosures made to the IETF Secretariat and any
+   assurances of licenses to be made available, or the result of an
+   attempt made to obtain a general license or permission for the use of
+   such proprietary rights by implementers or users of this
+   specification can be obtained from the IETF on-line IPR repository at
+   http://www.ietf.org/ipr.
+
+   The IETF invites any interested party to bring to its attention any
+   copyrights, patents or patent applications, or other proprietary
+   rights that may cover technology that may be required to implement
+   this standard.  Please address the information to the IETF at
+   ietf-ipr@ietf.org.
+
+Acknowledgement
+
+   Funding for the RFC Editor function is currently provided by the
+   Internet Society.
+
+
+
+
+
+
+
+Zeilenga                    Standards Track                     [Page 5]
+\f
index cd25dca8ab2cca531cc176c94410a9ca29640769..794769baf2008603fd6db81593f154b1394b460a 100644 (file)
@@ -50,6 +50,8 @@ ldap_config.h: $(LDAP_CONFIG) Makefile
                $(SED) -e 's/\\\\/\\\\\\\\\\\\\\\\/g'`; \
            libexecdir=`cygpath -w $(libexecdir) | \
                $(SED) -e 's/\\\\/\\\\\\\\\\\\\\\\/g'`; \
+           moduledir=`cygpath -w $(moduledir) | \
+               $(SED) -e 's/\\\\/\\\\\\\\\\\\\\\\/g'`; \
            localstatedir=`cygpath -w $(localstatedir) | \
                $(SED) -e 's/\\\\/\\\\\\\\\\\\\\\\/g'`; \
        else \
@@ -58,6 +60,7 @@ ldap_config.h: $(LDAP_CONFIG) Makefile
            bindir=$(bindir); \
            sbindir=$(sbindir); \
            libexecdir=$(libexecdir); \
+           moduledir=$(moduledir); \
            localstatedir=$(localstatedir); \
            localedir=$(localedir); \
        fi; \
@@ -67,6 +70,7 @@ ldap_config.h: $(LDAP_CONFIG) Makefile
                        -e "s;%BINDIR%;$$bindir;" \
                        -e "s;%SBINDIR%;$$sbindir;" \
                        -e "s;%LIBEXECDIR%;$$libexecdir;" \
+                       -e "s;%MODULEDIR%;$$moduledir;" \
                        -e "s;%RUNDIR%;$$localstatedir;" \
                        -e "s;%LOCALEDIR%;$$localedir;" \
                         $(LDAP_CONFIG) >> $@; \
index 20884dd9bcecf366b21516ac50d1cf1d6e29486b..be352ccdd6150725cd26551a4fde3145e9a41ace 100644 (file)
@@ -26,7 +26,7 @@
 #ifdef __GNUC__
 # define alloca __builtin_alloca
 #else
-# if HAVE_ALLOCA_H
+# ifdef HAVE_ALLOCA_H
 #  include <alloca.h>
 # else
 #  ifdef _AIX
index 4596a06cbe83a06083c329dc7e55b635430c7caf..c5a16bd1fbef621958d1e103147ea24c20a3fae0 100644 (file)
@@ -20,7 +20,7 @@
 #include <ac/unistd.h>
 
 /* crypt() may be defined in a separate include file */
-#if HAVE_CRYPT_H
+#ifdef HAVE_CRYPT_H
 #      include <crypt.h>
 #else
        extern char *(crypt)();
index 169d29d5025137c7916bb9ba70ddd773112147ef..6b4de339b5904f4770987821a1d1c02477cecd75 100644 (file)
@@ -17,7 +17,7 @@
 #ifndef _AC_DIRENT_H
 #define _AC_DIRENT_H
 
-#if HAVE_DIRENT_H
+#ifdef HAVE_DIRENT_H
 # include <dirent.h>
 # define NAMLEN(dirent) strlen((dirent)->d_name)
 #elif defined(_MSC_VER)
@@ -37,13 +37,13 @@ typedef struct DIR {
 #else
 # define dirent direct
 # define NAMLEN(dirent) (dirent)->d_namlen
-# if HAVE_SYS_NDIR_H
+# ifdef HAVE_SYS_NDIR_H
 #  include <sys/ndir.h>
 # endif
-# if HAVE_SYS_DIR_H
+# ifdef HAVE_SYS_DIR_H
 #  include <sys/dir.h>
 # endif
-# if HAVE_NDIR_H
+# ifdef HAVE_NDIR_H
 #  include <ndir.h>
 # endif
 #endif
index 89ef242ef7e6a9dc845c9b9cf76c932d4c817680..601f2456ba8266839fde6f441fa586f76ec31a20 100644 (file)
@@ -27,7 +27,7 @@
        /* no sys_errlist */
 #      define          sys_nerr        0
 #      define          sys_errlist     ((char **)0)
-#elif DECL_SYS_ERRLIST
+#elif defined( DECL_SYS_ERRLIST )
        /* have sys_errlist but need declaration */
        LDAP_LIBC_V(int)      sys_nerr;
        LDAP_LIBC_V(char)    *sys_errlist[];
index 0496c4d62c92e079bf101ac64e00c7d6219e01ec..d5644b3dfa0f9656bfc53eeff4d8975d471b5dce 100644 (file)
@@ -127,7 +127,7 @@ LBER_F( char * ) ber_pvt_wsa_err2string LDAP_P((int));
 #              define tcp_write( s, buf, len ) netwrite( s, buf, len )
 #      endif /* NCSA */
 
-#elif HAVE_CLOSESOCKET
+#elif defined(HAVE_CLOSESOCKET)
 #      define tcp_close( s )           closesocket( s )
 
 #      ifdef __BEOS__
@@ -213,8 +213,24 @@ LDAP_F (int) ldap_pvt_inet_aton LDAP_P(( const char *, struct in_addr * ));
 #      endif
 #endif
 
-#ifndef HAVE_GETPEEREID
-LDAP_LUTIL_F( int ) getpeereid( int s, uid_t *, gid_t * );
+#if defined(LDAP_PF_LOCAL) && \
+       !defined(HAVE_GETPEEREID) && \
+       !defined(HAVE_GETPEERUCRED) && \
+       !defined(SO_PEERCRED) && !defined(LOCAL_PEERCRED) && \
+       defined(HAVE_SENDMSG) && (defined(HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTSLEN) || \
+       defined(HAVE_STRUCT_MSGHDR_MSG_CONTROL))
+#      define LDAP_PF_LOCAL_SENDMSG 1
+#endif
+
+#ifdef HAVE_GETPEEREID
+#define        LUTIL_GETPEEREID( s, uid, gid, bv )     getpeereid( s, uid, gid )
+#elif defined(LDAP_PF_LOCAL_SENDMSG)
+struct berval;
+LDAP_LUTIL_F( int ) lutil_getpeereid( int s, uid_t *, gid_t *, struct berval *bv );
+#define        LUTIL_GETPEEREID( s, uid, gid, bv )     lutil_getpeereid( s, uid, gid, bv )
+#else
+LDAP_LUTIL_F( int ) lutil_getpeereid( int s, uid_t *, gid_t * );
+#define        LUTIL_GETPEEREID( s, uid, gid, bv )     lutil_getpeereid( s, uid, gid )
 #endif
 
 /* DNS RFC defines max host name as 255. New systems seem to use 1024 */
index 51f4c34ef756f1dd764a99464dfc07f23c1aafb1..ff521a63e6d9b452c7d290cb3ecbbd83b30d24dc 100644 (file)
@@ -17,7 +17,7 @@
 #ifndef _AC_TERMIOS_H
 #define _AC_TERMIOS_H
 
-#ifdef HAVE_POSIX_TERMIOS
+#ifdef HAVE_TERMIOS_H
 #include <termios.h>
 
 #ifdef GCWINSZ_IN_SYS_IOCTL
index 6dd5b541dc6dd2a9ee951072ca712e1f88205046..cdf8cebb5abc72f3714e88d071b32ed4c0ccd655 100644 (file)
 #ifndef _AC_TIME_H
 #define _AC_TIME_H
 
-#if TIME_WITH_SYS_TIME
+#ifdef TIME_WITH_SYS_TIME
 # include <sys/time.h>
 # include <time.h>
-#elif HAVE_SYS_TIME_H
+#elif defined(HAVE_SYS_TIME_H)
 # include <sys/time.h>
 # ifdef HAVE_SYS_TIMEB_H
 #  include <sys/timeb.h>
index dd3c2788ae83cf1e8db423ebed6aff48d4b24868..c3accf62535bc1ba076563b75f7676c57b8b70c1 100644 (file)
 #ifndef _AC_UNISTD_H
 #define _AC_UNISTD_H
 
-#if HAVE_SYS_TYPES_H
+#ifdef HAVE_SYS_TYPES_H
 #      include <sys/types.h>
 #endif
 
-#if HAVE_UNISTD_H
+#ifdef HAVE_UNISTD_H
 #      include <unistd.h>
 #endif
 
-#if HAVE_PROCESS_H
+#ifdef HAVE_PROCESS_H
 #      include <process.h>
 #endif
 
@@ -45,7 +45,7 @@ LDAP_LUTIL_F(char*)(lutil_getpass) LDAP_P((const char *getpass));
 #endif
 
 /* getopt() defines may be in separate include file */
-#if HAVE_GETOPT_H
+#ifdef HAVE_GETOPT_H
 #      include <getopt.h>
 
 #elif !defined(HAVE_GETOPT)
index 705a2de41f3beaca610c5f7f5938f532cca2d733..555e859bb03f7eb75e3e10623dbeb9620cd22f8f 100644 (file)
@@ -19,7 +19,7 @@
 
 #include <sys/types.h>
 
-#if HAVE_SYS_WAIT_H
+#ifdef HAVE_SYS_WAIT_H
 # include <sys/wait.h>
 #endif
 
index 5fb2c8a9ee73e247d21d954ab27ab758ec039021..4b3a8d5ecd8ac22a03e39fa9748976d0512a7a25 100644 (file)
@@ -138,8 +138,12 @@ typedef struct lber_memory_fns {
 #define LBER_SB_OPT_NEEDS_WRITE                12
 #define LBER_SB_OPT_GET_MAX_INCOMING   13
 #define LBER_SB_OPT_SET_MAX_INCOMING   14
+
+/* Only meaningful ifdef LDAP_PF_LOCAL_SENDMSG */
+#define LBER_SB_OPT_UNGET_BUF  15
+
 /* Largest option used by the library */
-#define LBER_SB_OPT_OPT_MAX            14
+#define LBER_SB_OPT_OPT_MAX            15
 
 /* LBER IO operations stacking levels */
 #define LBER_SBIOD_LEVEL_PROVIDER      10
@@ -267,11 +271,14 @@ ber_get_stringb LDAP_P((
        char *buf,
        ber_len_t *len ));
 
+#define        LBER_BV_ALLOC   0x01    /* allocate/copy result, otherwise in-place */
+#define        LBER_BV_NOTERM  0x02    /* omit NUL-terminator if parsing in-place */
+
 LBER_F( ber_tag_t )
 ber_get_stringbv LDAP_P((
        BerElement *ber,
        struct berval *bv,
-       int alloc ));
+       int options ));
 
 LBER_F( ber_tag_t )
 ber_get_stringa LDAP_P((
@@ -316,9 +323,19 @@ ber_scanf LDAP_P((
        LDAP_CONST char *fmt,
        ... ));
 
+LBER_F( int )
+ber_decode_oid LDAP_P((
+       struct berval *in,
+       struct berval *out ));
+
 /*
  * in encode.c
  */
+LBER_F( int )
+ber_encode_oid LDAP_P((
+       struct berval *in,
+       struct berval *out ));
+
 typedef int (*BEREncodeCallback) LDAP_P((
        BerElement *ber,
        void *data ));
@@ -401,6 +418,11 @@ ber_printf LDAP_P((
  * in io.c:
  */
 
+LBER_F( ber_slen_t )
+ber_skip_data LDAP_P((
+       BerElement *ber,
+       ber_len_t len ));
+
 LBER_F( ber_slen_t )
 ber_read LDAP_P((
        BerElement *ber,
index 759b9ba01d62ecdcbe97228eb8dcff6c4b68ec39..2e55abd00701d548f13e2b64f31842fe20b18957 100644 (file)
@@ -141,6 +141,7 @@ LDAP_BEGIN_DECL
 #define LDAP_OPT_X_TLS_CONNECT_ARG     0x600d
 #define LDAP_OPT_X_TLS_DHFILE          0x600e
 #define LDAP_OPT_X_TLS_NEWCTX          0x600f
+#define LDAP_OPT_X_TLS_CRLFILE         0x6010  /* GNUtls only */
 
 #define LDAP_OPT_X_TLS_NEVER   0
 #define LDAP_OPT_X_TLS_HARD            1
@@ -288,11 +289,22 @@ typedef struct ldapcontrol {
 #define LDAP_CONTROL_X_SEARCH_OPTIONS          "1.2.840.113556.1.4.1340"
 #define LDAP_SEARCH_FLAG_DOMAIN_SCOPE 1 /* do not generate referrals */
 #define LDAP_SEARCH_FLAG_PHANTOM_ROOT 2 /* search all subordinate NCs */
+#define LDAP_CONTROL_X_TREE_DELETE             "1.2.840.113556.1.4.805"
 
 /* MS Active Directory controls - not implemented in slapd(8) */
-#define LDAP_CONTROL_X_TREE_DELETE             "1.2.840.113556.1.4.805"
 #define LDAP_CONTROL_X_EXTENDED_DN             "1.2.840.113556.1.4.529"
 
+#ifdef LDAP_DEVEL
+/* <draft-wahl-ldap-session> */
+#define LDAP_CONTROL_X_SESSION_TRACKING                "1.3.6.1.4.1.21008.108.63.1"
+#define LDAP_CONTROL_X_SESSION_TRACKING_RADIUS_ACCT_SESSION_ID \
+                                               LDAP_CONTROL_X_SESSION_TRACKING ".1"
+#define LDAP_CONTROL_X_SESSION_TRACKING_RADIUS_ACCT_MULTI_SESSION_ID \
+                                               LDAP_CONTROL_X_SESSION_TRACKING ".2"
+#define LDAP_CONTROL_X_SESSION_TRACKING_USERNAME \
+                                               LDAP_CONTROL_X_SESSION_TRACKING ".3"
+#endif /* LDAP_DEVEL */
+
 /* various expired works */
 /* LDAP Duplicated Entry Control Extension *//* not implemented in slapd(8) */
 #define LDAP_CONTROL_DUPENT_REQUEST            "2.16.840.1.113719.1.27.101.1"
@@ -929,17 +941,33 @@ ldap_set_urllist_proc LDAP_P((
 /*
  * in controls.c:
  */
+#if LDAP_DEPRECATED    
 LDAP_F( int )
-ldap_create_control LDAP_P((
+ldap_create_control LDAP_P((   /* deprecated, use ldap_control_create */
        LDAP_CONST char *requestOID,
        BerElement *ber,
        int iscritical,
        LDAPControl **ctrlp ));
 
 LDAP_F( LDAPControl * )
-ldap_find_control LDAP_P((
+ldap_find_control LDAP_P((     /* deprecated, use ldap_control_find */
        LDAP_CONST char *oid,
        LDAPControl **ctrls ));
+#endif
+
+LDAP_F( int )
+ldap_control_create LDAP_P((
+       LDAP_CONST char *requestOID,
+       int iscritical,
+       struct berval *value,
+       int dupval,
+       LDAPControl **ctrlp ));
+
+LDAP_F( LDAPControl * )
+ldap_control_find LDAP_P((
+       LDAP_CONST char *oid,
+       LDAPControl **ctrls,
+       LDAPControl ***nextctrlp ));
 
 LDAP_F( void )
 ldap_control_free LDAP_P((
@@ -949,6 +977,14 @@ LDAP_F( void )
 ldap_controls_free LDAP_P((
        LDAPControl **ctrls ));
 
+LDAP_F( LDAPControl ** )
+ldap_controls_dup LDAP_P((
+       LDAPControl *LDAP_CONST *controls ));
+
+LDAP_F( LDAPControl * )
+ldap_control_dup LDAP_P((
+       LDAP_CONST LDAPControl *c ));
+
 /*
  * in dnssrv.c:
  */
@@ -2273,5 +2309,39 @@ LDAP_F( int )
 ldap_sync_poll LDAP_P((
        ldap_sync_t     *ls ));
 
+#ifdef LDAP_CONTROL_X_SESSION_TRACKING
+
+/*
+ * in stctrl.c
+ */
+LDAP_F( int )
+ldap_create_session_tracking_value LDAP_P((
+       LDAP            *ld,
+       char            *sessionSourceIp,
+       char            *sessionSourceName,
+       char            *formatOID,
+       struct berval   *sessionTrackingIdentifier,
+       struct berval   *value ));
+
+LDAP_F( int )
+ldap_create_session_tracking LDAP_P((
+       LDAP            *ld,
+       char            *sessionSourceIp,
+       char            *sessionSourceName,
+       char            *formatOID,
+       struct berval   *sessionTrackingIdentifier,
+       LDAPControl     **ctrlp ));
+
+LDAP_F( int )
+ldap_parse_session_tracking_control LDAP_P((
+       LDAP *ld,
+       LDAPControl *ctrl,
+       struct berval *ip,
+       struct berval *name,
+       struct berval *oid,
+       struct berval *id ));
+
+#endif /* LDAP_CONTROL_X_SESSION_TRACKING */
+
 LDAP_END_DECL
 #endif /* _LDAP_H */
index 5d8132b7c4a0f7c8bd2611220a26a74e9fdc4995..fcd59493abc98ba3f5ecaffcb6156d2445df5780 100644 (file)
@@ -59,6 +59,9 @@
 #ifndef LDAP_LIBEXECDIR
 #define LDAP_LIBEXECDIR                "%LIBEXECDIR%"
 #endif
+#ifndef LDAP_MODULEDIR
+#define LDAP_MODULEDIR         "%MODULEDIR%"
+#endif
 #ifndef LDAP_RUNDIR
 #define LDAP_RUNDIR                    "%RUNDIR%"
 #endif
index bc9c90662c36afd6a98ffe3ad56c28df9bea9194..1506983757700e2b67e7f658cd6340376fa1f57d 100644 (file)
@@ -47,13 +47,20 @@ struct ldap_url_desc; /* avoid pulling in <ldap.h> */
 #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)
+#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,
        unsigned flags ));
 
+LDAP_F (int) ldap_url_parselist LDAP_P((       /* deprecated, use ldap_url_parselist_ext() */
+       struct ldap_url_desc **ludlist,
+       const char *url ));
+
 LDAP_F (int) ldap_url_parselist_ext LDAP_P((
        struct ldap_url_desc **ludlist,
        const char *url,
@@ -188,12 +195,10 @@ LDAP_F (void) ldap_pvt_hex_unescape LDAP_P(( char *s ));
 
 /* controls.c */
 struct ldapcontrol;
-LDAP_F (struct ldapcontrol *) ldap_control_dup LDAP_P((
-       const struct ldapcontrol *ctrl ));
-
-LDAP_F (struct ldapcontrol **) ldap_controls_dup LDAP_P((
-       struct ldapcontrol *const *ctrls ));
-
+LDAP_F (int)
+ldap_pvt_put_control LDAP_P((
+       const struct ldapcontrol *c,
+       BerElement *ber ));
 LDAP_F (int) ldap_pvt_get_controls LDAP_P((
        BerElement *be,
        struct ldapcontrol ***ctrlsp));
@@ -285,8 +290,7 @@ LDAP_F (int) ldap_pvt_tls_init_def_ctx LDAP_P(( int is_server ));
 LDAP_F (int) ldap_pvt_tls_accept LDAP_P(( Sockbuf *sb, void *ctx_arg ));
 LDAP_F (int) ldap_pvt_tls_inplace LDAP_P(( Sockbuf *sb ));
 LDAP_F (void *) ldap_pvt_tls_sb_ctx LDAP_P(( Sockbuf *sb ));
-
-LDAP_F (int) ldap_pvt_tls_init_default_ctx LDAP_P(( void ));
+LDAP_F (void) ldap_pvt_tls_ctx_free LDAP_P(( void * ));
 
 typedef int LDAPDN_rewrite_dummy LDAP_P (( void *dn, unsigned flags ));
 
@@ -312,7 +316,7 @@ LDAP_END_DECL
  * If none is available, unsigned long data is used.
  */
 
-#if USE_MP_BIGNUM
+#ifdef USE_MP_BIGNUM
 /*
  * Use OpenSSL's BIGNUM
  */
@@ -338,7 +342,7 @@ typedef     BIGNUM* ldap_pvt_mp_t;
 #define ldap_pvt_mp_clear(mp) \
        do { BN_free((mp)); (mp) = 0; } while (0)
 
-#elif USE_MP_GMP
+#elif defined(USE_MP_GMP)
 /*
  * Use GNU's multiple precision library
  */
@@ -367,13 +371,13 @@ typedef mpz_t             ldap_pvt_mp_t;
  * Use unsigned long long
  */
 
-#if USE_MP_LONG_LONG
+#ifdef USE_MP_LONG_LONG
 typedef        unsigned long long      ldap_pvt_mp_t;
 #define        LDAP_PVT_MP_INIT        (0LL)
-#elif USE_MP_LONG
+#elif defined(USE_MP_LONG)
 typedef        unsigned long           ldap_pvt_mp_t;
 #define        LDAP_PVT_MP_INIT        (0L)
-#elif HAVE_LONG_LONG
+#elif defined(HAVE_LONG_LONG)
 typedef        unsigned long long      ldap_pvt_mp_t;
 #define        LDAP_PVT_MP_INIT        (0LL)
 #else
index ddc0302a83cf12cfdf58afb91760e6d024df3699..4d6a9d4294e1015ea5a7266eeeb8bea15be160bb 100644 (file)
@@ -36,11 +36,6 @@ typedef ldap_int_thread_rdwr_t               ldap_pvt_thread_rdwr_t;
 typedef ldap_int_thread_rmutex_t       ldap_pvt_thread_rmutex_t;
 #endif /* !LDAP_PVT_THREAD_H_DONE */
 
-#if 0 && defined(LDAP_DEVEL)
-/* must also be defined in slapd.h */
-#define LDAP_PVT_THREAD_POOL_SEM_LOAD_CONTROL
-#endif
-
 #define ldap_pvt_thread_equal          ldap_int_thread_equal
 
 LDAP_F( int )
index 49ea7951938dbc163b0e516b1b3b9d6d7ae0fc5d..9e40663201d3133e00fff5c2e5e9c24d4883828d 100644 (file)
@@ -219,6 +219,13 @@ lutil_pair( ber_socket_t sd[2] );
 LDAP_LUTIL_F( size_t )
 lutil_uuidstr( char *buf, size_t len );
 
+LDAP_LUTIL_F( int )
+lutil_uuidstr_from_normalized(
+       char            *uuid,
+       size_t          uuidlen,
+       char            *buf,
+       size_t          buflen );
+
 /* csn.c */
 /* use this macro to allocate buffer for lutil_csnstr */
 #define LDAP_LUTIL_CSNSTR_BUFSIZE      64
index b31e486f17c2a2dd83f59e693d5da530f13f87bf..b4ef095a9fe9cc485434d760e3f25d0e0a4a3ae9 100644 (file)
 /* Define to 1 if you have the <gmp.h> header file. */
 #undef HAVE_GMP_H
 
+/* define if you have GNUtls */
+#undef HAVE_GNUTLS
+
+/* Define to 1 if you have the <gnutls/gnutls.h> header file. */
+#undef HAVE_GNUTLS_GNUTLS_H
+
 /* if you have GNU Pth */
 #undef HAVE_GNU_PTH
 
 /* Define to 1 if `st_blksize' is member of `struct stat'. */
 #undef HAVE_STRUCT_STAT_ST_BLKSIZE
 
+/* Define to 1 if `st_fstype' is member of `struct stat'. */
+#undef HAVE_STRUCT_STAT_ST_FSTYPE
+
+/* define to 1 if st_fstype is char * */
+#undef HAVE_STRUCT_STAT_ST_FSTYPE_CHAR
+
+/* define to 1 if st_fstype is int */
+#undef HAVE_STRUCT_STAT_ST_FSTYPE_INT
+
+/* Define to 1 if `st_vfstype' is member of `struct stat'. */
+#undef HAVE_STRUCT_STAT_ST_VFSTYPE
+
 /* Define to 1 if you have the <synch.h> header file. */
 #undef HAVE_SYNCH_H
 
 /* Define to 1 if you have the <sys/filio.h> header file. */
 #undef HAVE_SYS_FILIO_H
 
+/* Define to 1 if you have the <sys/fstyp.h> header file. */
+#undef HAVE_SYS_FSTYP_H
+
 /* Define to 1 if you have the <sys/ioctl.h> header file. */
 #undef HAVE_SYS_IOCTL_H
 
 /* Define to 1 if you have the <sys/poll.h> header file. */
 #undef HAVE_SYS_POLL_H
 
+/* Define to 1 if you have the <sys/privgrp.h> header file. */
+#undef HAVE_SYS_PRIVGRP_H
+
 /* Define to 1 if you have the <sys/resource.h> header file. */
 #undef HAVE_SYS_RESOURCE_H
 
 /* Define to 1 if you have the <sys/uuid.h> header file. */
 #undef HAVE_SYS_UUID_H
 
+/* Define to 1 if you have the <sys/vmount.h> header file. */
+#undef HAVE_SYS_VMOUNT_H
+
 /* Define to 1 if you have <sys/wait.h> that is POSIX.1 compatible. */
 #undef HAVE_SYS_WAIT_H
 
 /* Define to 1 if you have the <utime.h> header file. */
 #undef HAVE_UTIME_H
 
+/* define if you have uuid_generate() */
+#undef HAVE_UUID_GENERATE
+
 /* define if you have uuid_to_str() */
 #undef HAVE_UUID_TO_STR
 
+/* Define to 1 if you have the <uuid/uuid.h> header file. */
+#undef HAVE_UUID_UUID_H
+
 /* Define to 1 if you have the `vprintf' function. */
 #undef HAVE_VPRINTF
 
 /* define for Dynamic List overlay */
 #undef SLAPD_OVER_DYNLIST
 
+/* define for Reverse Group Membership overlay */
+#undef SLAPD_OVER_MEMBEROF
+
 /* define for Password Policy overlay */
 #undef SLAPD_OVER_PPOLICY
 
    first (like Motorola and SPARC, unlike Intel and VAX). */
 #undef WORDS_BIGENDIAN
 
+/* Define to the type of arg 3 for `accept'. */
+#undef ber_socklen_t
+
 /* Define to `char *' if <sys/types.h> does not define. */
 #undef caddr_t
 
 /* define to snprintf routine */
 #undef snprintf
 
-/* Define to `int' if <sys/socket.h> does not define. */
+/* Define like ber_socklen_t if <sys/socket.h> does not define. */
 #undef socklen_t
 
 /* Define to `signed int' if <sys/types.h> does not define. */
index b3589058f2b6a441e4ab567ad74f8b279e38aa6d..3076bc9c22ba9f1fa85410776bf574cba8435dcc 100644 (file)
@@ -31,9 +31,9 @@ typedef struct slapi_attr             Slapi_Attr;
 typedef struct slapi_value             Slapi_Value;
 typedef struct slapi_valueset          Slapi_ValueSet;
 typedef struct slapi_filter            Slapi_Filter;
-typedef struct slap_backend_db         Slapi_Backend;
-typedef struct slap_op                 Slapi_Operation;
-typedef struct slap_conn               Slapi_Connection;
+typedef struct BackendDB               Slapi_Backend;
+typedef struct Operation               Slapi_Operation;
+typedef struct Connection              Slapi_Connection;
 typedef struct slapi_dn                        Slapi_DN;
 typedef struct slapi_rdn               Slapi_RDN;
 typedef struct slapi_mod               Slapi_Mod;
index 9bfc34f01e5cd638624c9768809fd2677d75c87a..51a958f0aba5320e6fe6fcd346b6e67cab62a0e0 100644 (file)
@@ -265,10 +265,10 @@ ber_dump(
                len = ber_pvt_ber_write(ber);
        }
 
-       sprintf( buf, "ber_dump: buf=0x%08lx ptr=0x%08lx end=0x%08lx len=%ld\n",
-           (long) ber->ber_buf,
-               (long) ber->ber_ptr,
-               (long) ber->ber_end,
+       sprintf( buf, "ber_dump: buf=%p ptr=%p end=%p len=%ld\n",
+               ber->ber_buf,
+               ber->ber_ptr,
+               ber->ber_end,
                (long) len );
 
        (void) (*ber_pvt_log_print)( buf );
@@ -303,10 +303,10 @@ ber_sos_dump(
        (*ber_pvt_log_print)( "*** sos dump ***\n" );
 
        while ( sos != NULL ) {
-               sprintf( buf, "ber_sos_dump: clen %ld first 0x%lx ptr 0x%lx\n",
+               sprintf( buf, "ber_sos_dump: clen %ld first %p ptr %p\n",
                    (long) sos->sos_clen,
-                       (long) sos->sos_first,
-                       (long) sos->sos_ptr );
+                       sos->sos_first,
+                       sos->sos_ptr );
                (*ber_pvt_log_print)( buf );
 
                sprintf( buf, "              current len %ld contents:\n",
index 7e1343f9267e94dfc8e4a96c010bc6d3c6b34dbd..f2261e7bd50f4017747005dbf0127216d7a6a7b0 100644 (file)
@@ -45,6 +45,52 @@ static ber_len_t ber_getnint LDAP_P((
        ber_int_t *num,
        ber_len_t len ));
 
+/* out->bv_len should be the buffer size on input */
+int
+ber_decode_oid( BerValue *in, BerValue *out )
+{
+       const unsigned char *der;
+       unsigned long val;
+       unsigned val1;
+       ber_len_t i;
+       char *ptr;
+
+       assert( in != NULL );
+       assert( out != NULL );
+
+       /* need 4 chars/inbyte + \0 for input={7f 7f 7f...} */
+       if ( !out->bv_val || (out->bv_len+3)/4 <= in->bv_len )
+               return -1;
+
+       ptr = NULL;
+       der = (unsigned char *) in->bv_val;
+       val = 0;
+       for ( i=0; i < in->bv_len; i++ ) {
+               val |= der[i] & 0x7f;
+               if ( !( der[i] & 0x80 )) {
+                       if ( ptr == NULL ) {
+                               /* Initial "x.y": val=x*40+y, x<=2, y<40 if x=2 */
+                               ptr = out->bv_val;
+                               val1 = (val < 80 ? val/40 : 2);
+                               val -= val1*40;
+                               ptr += sprintf( ptr, "%u", val1 );
+                       }
+                       ptr += sprintf( ptr, ".%lu", val );
+                       val = 0;
+               } else if ( val - 1UL < LBER_OID_COMPONENT_MAX >> 7 ) {
+                       val <<= 7;
+               } else {
+                       /* val would overflow, or is 0 from invalid initial 0x80 octet */
+                       return -1;
+               }
+       }
+       if ( ptr == NULL || val != 0 )
+               return -1;
+
+       out->bv_len = ptr - out->bv_val;
+       return 0;
+}
+
 /* return the tag - LBER_DEFAULT returned means trouble */
 ber_tag_t
 ber_get_tag( BerElement *ber )
@@ -373,7 +419,7 @@ ber_get_stringbvl( bgbvr *b, ber_len_t *rlen )
        case BvOff:
                *b->res.ba = ber_memalloc_x( (n+1) * b->siz, b->ber->ber_memctx );
                if ( *b->res.ba == NULL ) return LBER_DEFAULT;
-               ((struct berval *)((long)(*b->res.ba) + n*b->siz +
+               ((struct berval *)((char *)(*b->res.ba) + n*b->siz +
                        b->off))->bv_val = NULL;
                break;
        }
@@ -406,7 +452,7 @@ ber_get_stringbvl( bgbvr *b, ber_len_t *rlen )
                        *bvp = bv;
                        break;
                case BvOff:
-                       *(BerVarray)((long)(*b->res.ba)+n*b->siz+b->off) = bv;
+                       *(BerVarray)((char *)(*b->res.ba)+n*b->siz+b->off) = bv;
                        break;
                }
        }
@@ -437,7 +483,7 @@ nomem:
 }
 
 ber_tag_t
-ber_get_stringbv( BerElement *ber, struct berval *bv, int alloc )
+ber_get_stringbv( BerElement *ber, struct berval *bv, int option )
 {
        ber_tag_t       tag;
 
@@ -455,7 +501,7 @@ ber_get_stringbv( BerElement *ber, struct berval *bv, int alloc )
                return LBER_DEFAULT;
        }
 
-       if ( alloc ) {
+       if ( option & LBER_BV_ALLOC ) {
                bv->bv_val = (char *) ber_memalloc_x( bv->bv_len + 1,
                        ber->ber_memctx );
                if ( bv->bv_val == NULL ) {
@@ -474,13 +520,14 @@ ber_get_stringbv( BerElement *ber, struct berval *bv, int alloc )
                ber->ber_ptr += bv->bv_len;
        }
        ber->ber_tag = *(unsigned char *)ber->ber_ptr;
-       bv->bv_val[bv->bv_len] = '\0';
+       if ( !( option & LBER_BV_NOTERM ))
+               bv->bv_val[bv->bv_len] = '\0';
 
        return tag;
 }
 
 ber_tag_t
-ber_get_stringbv_null( BerElement *ber, struct berval *bv, int alloc )
+ber_get_stringbv_null( BerElement *ber, struct berval *bv, int option )
 {
        ber_tag_t       tag;
 
@@ -504,7 +551,7 @@ ber_get_stringbv_null( BerElement *ber, struct berval *bv, int alloc )
                return tag;
        }
 
-       if ( alloc ) {
+       if ( option & LBER_BV_ALLOC ) {
                bv->bv_val = (char *) ber_memalloc_x( bv->bv_len + 1,
                        ber->ber_memctx );
                if ( bv->bv_val == NULL ) {
@@ -523,7 +570,8 @@ ber_get_stringbv_null( BerElement *ber, struct berval *bv, int alloc )
                ber->ber_ptr += bv->bv_len;
        }
        ber->ber_tag = *(unsigned char *)ber->ber_ptr;
-       bv->bv_val[bv->bv_len] = '\0';
+       if ( !( option & LBER_BV_NOTERM ))
+               bv->bv_val[bv->bv_len] = '\0';
 
        return tag;
 }
@@ -536,7 +584,7 @@ ber_get_stringa( BerElement *ber, char **buf )
 
        assert( buf != NULL );
 
-       tag = ber_get_stringbv( ber, &bv, 1 );
+       tag = ber_get_stringbv( ber, &bv, LBER_BV_ALLOC );
        *buf = bv.bv_val;
 
        return tag;
@@ -550,7 +598,7 @@ ber_get_stringa_null( BerElement *ber, char **buf )
 
        assert( buf != NULL );
 
-       tag = ber_get_stringbv_null( ber, &bv, 1 );
+       tag = ber_get_stringbv_null( ber, &bv, LBER_BV_ALLOC );
        *buf = bv.bv_val;
 
        return tag;
@@ -570,7 +618,7 @@ ber_get_stringal( BerElement *ber, struct berval **bv )
                return LBER_DEFAULT;
        }
 
-       tag = ber_get_stringbv( ber, *bv, 1 );
+       tag = ber_get_stringbv( ber, *bv, LBER_BV_ALLOC );
        if ( tag == LBER_DEFAULT ) {
                LBER_FREE( *bv );
                *bv = NULL;
@@ -811,7 +859,7 @@ ber_scanf ( BerElement *ber,
 
                case 'o':       /* octet string in a supplied berval */
                        bval = va_arg( ap, struct berval * );
-                       rc = ber_get_stringbv( ber, bval, 1 );
+                       rc = ber_get_stringbv( ber, bval, LBER_BV_ALLOC );
                        break;
 
                case 'O':       /* octet string - allocate & include length */
@@ -840,7 +888,7 @@ ber_scanf ( BerElement *ber,
                        bgbvr cookie = { ChArray };
                        cookie.ber = ber;
                        cookie.res.c = va_arg( ap, char *** );
-                       cookie.alloc = 1;
+                       cookie.alloc = LBER_BV_ALLOC;
                        rc = ber_get_stringbvl( &cookie, NULL );
                        break;
                }
@@ -850,7 +898,7 @@ ber_scanf ( BerElement *ber,
                        bgbvr cookie = { BvVec };
                        cookie.ber = ber;
                        cookie.res.bv = va_arg( ap, struct berval *** );
-                       cookie.alloc = 1;
+                       cookie.alloc = LBER_BV_ALLOC;
                        rc = ber_get_stringbvl( &cookie, NULL );
                        break;
                }
@@ -860,7 +908,7 @@ ber_scanf ( BerElement *ber,
                        bgbvr cookie = { BvArray };
                        cookie.ber = ber;
                        cookie.res.ba = va_arg( ap, struct berval ** );
-                       cookie.alloc = 1;
+                       cookie.alloc = LBER_BV_ALLOC;
                        rc = ber_get_stringbvl( &cookie, NULL );
                        break;
                }
index 4272a5d9cf2043719667b162d749d8ab0f432a92..9b20518ba363b34b0818ca414917a090fa5c5e97 100644 (file)
@@ -30,6 +30,7 @@
 
 #include "portable.h"
 
+#include <ctype.h>
 #include <stdio.h>
 
 #include <ac/stdlib.h>
@@ -177,6 +178,63 @@ ber_put_len( BerElement *ber, ber_len_t len, int nosos )
        return rc == i ?  i+1 : -1;
 }
 
+/* out->bv_len should be the buffer size on input */
+int
+ber_encode_oid( BerValue *in, BerValue *out )
+{
+       unsigned char *der;
+       unsigned long val1, val;
+       int i, j, len;
+       char *ptr, *end, *inend;
+
+       assert( in != NULL );
+       assert( out != NULL );
+
+       if ( !out->bv_val || out->bv_len < in->bv_len/2 )
+               return -1;
+
+       der = (unsigned char *) out->bv_val;
+       ptr = in->bv_val;
+       inend = ptr + in->bv_len;
+
+       /* OIDs start with <0-1>.<0-39> or 2.<any>, DER-encoded 40*val1+val2 */
+       if ( !isdigit( (unsigned char) *ptr )) return -1;
+       val1 = strtoul( ptr, &end, 10 );
+       if ( end == ptr || val1 > 2 ) return -1;
+       if ( *end++ != '.' || !isdigit( (unsigned char) *end )) return -1;
+       val = strtoul( end, &ptr, 10 );
+       if ( ptr == end ) return -1;
+       if ( val > (val1 < 2 ? 39 : LBER_OID_COMPONENT_MAX - 80) ) return -1;
+       val += val1 * 40;
+
+       for (;;) {
+               if ( ptr > inend ) return -1;
+
+               len = 0;
+               do {
+                       der[len++] = (val & 0xff) | 0x80;
+               } while ( (val >>= 7) != 0 );
+               der[0] &= 0x7f;
+               for ( i = 0, j = len; i < --j; i++ ) {
+                       unsigned char tmp = der[i];
+                       der[i] = der[j];
+                       der[j] = tmp;
+               }
+               der += len;
+               if ( ptr == inend )
+                       break;
+
+               if ( *ptr++ != '.' ) return -1;
+               if ( !isdigit( (unsigned char) *ptr )) return -1;
+               val = strtoul( ptr, &end, 10 );
+               if ( end == ptr || val > LBER_OID_COMPONENT_MAX ) return -1;
+               ptr = end;
+       }
+
+       out->bv_len = (char *)der - out->bv_val;
+       return 0;
+}
+
 static int
 ber_put_int_or_enum(
        BerElement *ber,
index 503735819f42a5c7737c3c69f561465b8bb8e2ae..4f4afa390f1f486a30764b3afa06b6fce7b012c6 100644 (file)
 #include "lber-int.h"
 #include "ldap_log.h"
 
+ber_slen_t
+ber_skip_data(
+       BerElement *ber,
+       ber_len_t len )
+{
+       ber_len_t       actuallen, nleft;
+
+       assert( ber != NULL );
+
+       assert( LBER_VALID( ber ) );
+
+       nleft = ber_pvt_ber_remaining( ber );
+       actuallen = nleft < len ? nleft : len;
+       ber->ber_ptr += actuallen;
+       ber->ber_tag = *(unsigned char *)ber->ber_ptr;
+
+       return( (ber_slen_t) actuallen );
+}
+
 ber_slen_t
 ber_read(
        BerElement *ber,
@@ -185,11 +204,8 @@ ber_free_buf( BerElement *ber )
 void
 ber_free( BerElement *ber, int freebuf )
 {
-#ifdef LDAP_MEMORY_DEBUG
-       assert( ber != NULL );
-#endif
-
        if( ber == NULL ) {
+               LDAP_MEMORY_DEBUG_ASSERT( ber != NULL );
                return;
        }
 
index 4e73a58ebbe0f6c24323cec965398d227f1007e9..e2657d2eb1d21695b04d8e99ec3f30bfcb2c9f8a 100644 (file)
@@ -47,6 +47,11 @@ LBER_V (BER_ERRNO_FN) ber_int_errno_fn;
 #ifdef LDAP_MEMORY_DEBUG
 LBER_V (long)  ber_int_meminuse;
 #endif
+#if defined(LDAP_MEMORY_DEBUG) && ((LDAP_MEMORY_DEBUG +0) & 2)
+# define LDAP_MEMORY_DEBUG_ASSERT assert
+#else
+# define LDAP_MEMORY_DEBUG_ASSERT(expr) ((void) 0)
+#endif
 
 struct lber_options {
        short lbo_valid;
@@ -99,9 +104,13 @@ struct sockbuf {
 #define        sb_options              sb_opts.lbo_options
 #define        sb_debug                sb_opts.lbo_debug
        ber_socket_t            sb_fd;
+       ber_len_t                       sb_max_incoming;
        unsigned int            sb_trans_needs_read:1;
        unsigned int            sb_trans_needs_write:1;
-       ber_len_t                       sb_max_incoming;
+#ifdef LDAP_PF_LOCAL_SENDMSG
+       char                            sb_ungetlen;
+       char                            sb_ungetbuf[8];
+#endif
 };
 
 #define SOCKBUF_VALID( sb )    ( (sb)->sb_valid == LBER_VALID_SOCKBUF )
@@ -116,6 +125,14 @@ struct seqorset {
 };
 
 
+/*
+ * decode.c, encode.c
+ */
+
+/* Simplest OID max-DER-component to implement in both decode and encode */
+#define LBER_OID_COMPONENT_MAX ((unsigned long)-1 - 128)
+
+
 /*
  * io.c
  */
index 0681869862b475253d4779aad4320a83c2741150..94ef772d97dbe169807c261b6840bcd9dcf23216 100644 (file)
 #include <stdio.h>
 #endif
 
-#if LDAP_MEMORY_DEBUG
+#ifdef LDAP_MEMORY_DEBUG
 /*
  * LDAP_MEMORY_DEBUG should only be enabled for the purposes of
  * debugging memory management within OpenLDAP libraries and slapd.
- * It should only be enabled by an experienced developer as it
- * causes the inclusion of numerous assert()'s, many of which may
- * be triggered by a prefectly valid program.
+ *
+ * It should only be enabled by an experienced developer as it causes
+ * the inclusion of numerous assert()'s, many of which may be triggered
+ * by a prefectly valid program.  If LDAP_MEMORY_DEBUG & 2 is true,
+ * that includes asserts known to break both slapd and current clients.
  *
  * The code behind this macro is subject to change as needed to
  * support this testing.
@@ -71,6 +73,7 @@ static const struct ber_mem_hdr ber_int_mem_hdr = { LBER_MEM_JUNK, 0, 0 };
  * put allocations/frees together.  It is then a simple matter to write a script
  * to find any allocations that don't have a buffer free function.
  */
+long ber_int_meminuse = 0;
 #ifdef LDAP_MEMORY_TRACE
 static ber_int_t sequence = 0;
 #endif
@@ -191,11 +194,8 @@ ber_memalloc_x( ber_len_t s, void *ctx )
 {
        void *new;
 
-#ifdef LDAP_MEMORY_DEBUG
-       assert( s != 0 );
-#endif
-
        if( s == 0 ) {
+               LDAP_MEMORY_DEBUG_ASSERT( s != 0 );
                return NULL;
        }
 
@@ -247,11 +247,8 @@ ber_memcalloc_x( ber_len_t n, ber_len_t s, void *ctx )
 {
        void *new;
 
-#ifdef LDAP_MEMORY_DEBUG
-       assert( n != 0 && s != 0);
-#endif
-
        if( n == 0 || s == 0 ) {
+               LDAP_MEMORY_DEBUG_ASSERT( n != 0 && s != 0);
                return NULL;
        }
 
index 353d526320f30b0aa45b3b859096f74af56617bf..176122ec2a4fdf8fba458061fb67d9b7fcf10a6f 100644 (file)
@@ -150,6 +150,20 @@ ber_sockbuf_ctrl( Sockbuf *sb, int opt, void *arg )
                        ret = 1;
                        break;
 
+               case LBER_SB_OPT_UNGET_BUF:
+#ifdef LDAP_PF_LOCAL_SENDMSG
+                       sb->sb_ungetlen = ((struct berval *)arg)->bv_len;
+                       if ( sb->sb_ungetlen <= sizeof( sb->sb_ungetbuf )) {
+                               AC_MEMCPY( sb->sb_ungetbuf, ((struct berval *)arg)->bv_val,
+                                       sb->sb_ungetlen );
+                               ret = 1;
+                       } else {
+                               sb->sb_ungetlen = 0;
+                               ret = -1;
+                       }
+#endif
+                       break;
+
                default:
                        ret = sb->sb_iod->sbiod_io->sbi_ctrl( sb->sb_iod, opt, arg );
                        break;
@@ -325,7 +339,7 @@ ber_pvt_sb_do_write( Sockbuf_IO_Desc *sbiod, Sockbuf_Buf *buf_out )
 int
 ber_pvt_socket_set_nonblock( ber_socket_t sd, int nb )
 {
-#if HAVE_FCNTL
+#ifdef HAVE_FCNTL
        int flags = fcntl( sd, F_GETFL);
        if( nb ) {
                flags |= O_NONBLOCK;
@@ -704,6 +718,24 @@ sb_fd_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
        assert( sbiod != NULL);
        assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
 
+#ifdef LDAP_PF_LOCAL_SENDMSG
+       if ( sbiod->sbiod_sb->sb_ungetlen ) {
+               ber_len_t blen = sbiod->sbiod_sb->sb_ungetlen;
+               if ( blen > len )
+                       blen = len;
+               AC_MEMCPY( buf, sbiod->sbiod_sb->sb_ungetbuf, blen );
+               buf = (char *) buf + blen;
+               len -= blen;
+               sbiod->sbiod_sb->sb_ungetlen -= blen;
+               if ( sbiod->sbiod_sb->sb_ungetlen ) {
+                       AC_MEMCPY( sbiod->sbiod_sb->sb_ungetbuf,
+                               sbiod->sbiod_sb->sb_ungetbuf+blen,
+                               sbiod->sbiod_sb->sb_ungetlen );
+               }
+               if ( len == 0 )
+                       return blen;
+       }
+#endif
        return read( sbiod->sbiod_sb->sb_fd, buf, len );
 }
 
@@ -873,7 +905,7 @@ static ber_slen_t
 sb_dgram_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
 {
        ber_slen_t rc;
-       socklen_t  addrlen;
+       ber_socklen_t addrlen;
        struct sockaddr *src;
    
        assert( sbiod != NULL );
@@ -882,7 +914,7 @@ sb_dgram_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
 
        addrlen = sizeof( struct sockaddr );
        src = buf;
-       buf += addrlen;
+       buf = (char *) buf + addrlen;
        len -= addrlen;
        rc = recvfrom( sbiod->sbiod_sb->sb_fd, buf, len, 0, src, &addrlen );
 
@@ -900,7 +932,7 @@ sb_dgram_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
        assert( buf != NULL );
 
        dst = buf;
-       buf += sizeof( struct sockaddr );
+       buf = (char *) buf + sizeof( struct sockaddr );
        len -= sizeof( struct sockaddr );
    
        rc = sendto( sbiod->sbiod_sb->sb_fd, buf, len, 0, dst,
index 8b62c45cc1c873cae80fd3d878379e9cd1c889dc..c031db07385b346e2e3f1f22114318efbc40dbcc 100644 (file)
@@ -26,7 +26,7 @@ SRCS  = bind.c open.c result.c error.c compare.c search.c \
        request.c os-ip.c url.c pagectrl.c sortctrl.c vlvctrl.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 ldap_sync.c
+       turn.c ppolicy.c dds.c txn.c ldap_sync.c stctrl.c
 
 OBJS   = bind.lo open.lo result.lo error.lo compare.lo search.lo \
        controls.lo messages.lo references.lo extended.lo cyrus.lo \
@@ -37,7 +37,7 @@ OBJS  = bind.lo open.lo result.lo error.lo compare.lo search.lo \
        request.lo os-ip.lo url.lo pagectrl.lo sortctrl.lo vlvctrl.lo \
        init.lo options.lo print.lo string.lo util-int.lo schema.lo \
        charray.lo tls.lo os-local.lo dnssrv.lo utf-8.lo utf-8-conv.lo \
-       turn.lo ppolicy.lo dds.lo txn.lo ldap_sync.lo
+       turn.lo ppolicy.lo dds.lo txn.lo ldap_sync.lo stctrl.lo
 
 LDAP_INCDIR= ../../include       
 LDAP_LIBDIR= ../../libraries
index 43e2f342c8826207f9c0e59405e8a9208d8360c1..d72483ecdaf8614b4d34c032055f5afabfb714b4 100644 (file)
@@ -224,8 +224,9 @@ start_again:;
                        i = ++(ld)->ld_msgid;
 #ifdef LDAP_CONNECTIONLESS
                        if ( LDAP_IS_UDP(ld) ) {
-                               err = ber_write( ber, ld->ld_options.ldo_peer,
-                                       sizeof(struct sockaddr), 0);
+                               struct sockaddr sa = {0};
+                               /* dummy, filled with ldo_peer in request.c */
+                               err = ber_write( ber, &sa, sizeof(sa), 0 );
                        }
                        if ( LDAP_IS_UDP(ld) && ld->ld_options.ldo_version ==
                                LDAP_VERSION2 )
index 229524cd2ee2f98c1bed6e469e29371e46ef7bea..db4568dc7f3257bc7585289d604f5399b99dfa7f 100644 (file)
@@ -64,6 +64,9 @@ ldap_add_result_entry( LDAPMessage **list, LDAPMessage *e )
        assert( e != NULL );
 
        e->lm_chain = *list;
-       e->lm_chain_tail = (*list)->lm_chain_tail;
+       if ( *list )
+               e->lm_chain_tail = (*list)->lm_chain_tail;
+       else
+               e->lm_chain_tail = e;
        *list = e;
 }
index faca9839ecbf4fb7c1258239200246e720f305c0..059dc5266f268d434d1369dda5f3fcbec5a05a71 100644 (file)
  *     }
  */
 
+int
+ldap_pvt_put_control(
+       const LDAPControl *c,
+       BerElement *ber )
+{
+       if ( ber_printf( ber, "{s" /*}*/, c->ldctl_oid ) == -1 ) {
+               return LDAP_ENCODING_ERROR;
+       }
+
+       if ( c->ldctl_iscritical /* only if true */
+               &&  ( ber_printf( ber, "b",
+                       (ber_int_t) c->ldctl_iscritical ) == -1 ) )
+       {
+               return LDAP_ENCODING_ERROR;
+       }
+
+       if ( !BER_BVISNULL( &c->ldctl_value ) /* only if we have a value */
+               &&  ( ber_printf( ber, "O", &c->ldctl_value ) == -1 ) )
+       {
+               return LDAP_ENCODING_ERROR;
+       }
+
+       if ( ber_printf( ber, /*{*/"N}" ) == -1 ) {
+               return LDAP_ENCODING_ERROR;
+       }
+
+       return LDAP_SUCCESS;
+}
+
+
 /*
  * ldap_int_put_controls
  */
@@ -97,32 +127,8 @@ ldap_int_put_controls(
        }
 
        for( c = ctrls ; *c != NULL; c++ ) {
-               if ( ber_printf( ber, "{s" /*}*/,
-                       (*c)->ldctl_oid ) == -1 )
-               {
-                       ld->ld_errno = LDAP_ENCODING_ERROR;
-                       return ld->ld_errno;
-               }
-
-               if( (*c)->ldctl_iscritical /* only if true */
-                       &&  ( ber_printf( ber, "b",
-                               (ber_int_t) (*c)->ldctl_iscritical ) == -1 ) )
-               {
-                       ld->ld_errno = LDAP_ENCODING_ERROR;
-                       return ld->ld_errno;
-               }
-
-               if( (*c)->ldctl_value.bv_val != NULL /* only if we have a value */
-                       &&  ( ber_printf( ber, "O",
-                               &((*c)->ldctl_value) ) == -1 ) )
-               {
-                       ld->ld_errno = LDAP_ENCODING_ERROR;
-                       return ld->ld_errno;
-               }
-
-
-               if( ber_printf( ber, /*{*/"N}" ) == -1 ) {
-                       ld->ld_errno = LDAP_ENCODING_ERROR;
+               ld->ld_errno = ldap_pvt_put_control( *c, ber );
+               if ( ld->ld_errno != LDAP_SUCCESS ) {
                        return ld->ld_errno;
                }
        }
@@ -231,7 +237,7 @@ int ldap_pvt_get_controls(
                if( tag == LBER_OCTETSTRING ) {
                        tag = ber_scanf( ber, "o", &tctrl->ldctl_value );
                } else {
-                       tctrl->ldctl_value.bv_val = NULL;
+                       BER_BVZERO( &tctrl->ldctl_value );
                }
 
                *ctrls = tctrls;
@@ -246,9 +252,7 @@ int ldap_pvt_get_controls(
 void
 ldap_control_free( LDAPControl *c )
 {
-#ifdef LDAP_MEMORY_DEBUG
-       assert( c != NULL );
-#endif
+       LDAP_MEMORY_DEBUG_ASSERT( c != NULL );
 
        if ( c != NULL ) {
                if( c->ldctl_oid != NULL) {
@@ -269,9 +273,7 @@ ldap_control_free( LDAPControl *c )
 void
 ldap_controls_free( LDAPControl **controls )
 {
-#ifdef LDAP_MEMORY_DEBUG
-       assert( controls != NULL );
-#endif
+       LDAP_MEMORY_DEBUG_ASSERT( controls != NULL );
 
        if ( controls != NULL ) {
                int i;
@@ -354,6 +356,7 @@ ldap_control_dup( const LDAPControl *c )
                }
 
        } else {
+               /* FIXME: how can a control have null OID? */
                new->ldctl_oid = NULL;
        }
 
@@ -385,7 +388,9 @@ ldap_control_dup( const LDAPControl *c )
        return new;
 }
 
-
+/*
+ * Find a LDAPControl - deprecated
+ */
 LDAPControl *
 ldap_find_control(
        LDAP_CONST char *oid,
@@ -405,21 +410,38 @@ ldap_find_control(
 }
 
 /*
-   ldap_create_control
-   
-   Internal function to create an LDAP control from the encoded BerElement.
-
-   requestOID  (IN) The OID to use in creating the control.
-   
-   ber         (IN) The encoded BerElement to use in creating the control.
-   
-   iscritical  (IN) 0 - Indicates the control is not critical to the operation.
-                                       non-zero - The control is critical to the operation.
-                                 
-   ctrlp      (OUT) Returns a pointer to the LDAPControl created.  This control
-                                       SHOULD be freed by calling ldap_control_free() when done.
----*/
+ * Find a LDAPControl
+ */
+LDAPControl *
+ldap_control_find(
+       LDAP_CONST char *oid,
+       LDAPControl **ctrls,
+       LDAPControl ***nextctrlp )
+{
+       if ( oid == NULL || ctrls == NULL || *ctrls == NULL ) {
+               return NULL;
+       }
+
+       for( ; *ctrls != NULL; ctrls++ ) {
+               if( strcmp( (*ctrls)->ldctl_oid, oid ) == 0 ) {
+                       if ( nextctrlp != NULL ) {
+                               *nextctrlp = ctrls + 1;
+                       }
+
+                       return *ctrls;
+               }
+       }
+
+       if ( nextctrlp != NULL ) {
+               *nextctrlp = NULL;
+       }
 
+       return NULL;
+}
+
+/*
+ * Create a LDAPControl, optionally from ber - deprecated
+ */
 int
 ldap_create_control(
        LDAP_CONST char *requestOID,
@@ -430,7 +452,6 @@ ldap_create_control(
        LDAPControl *ctrl;
 
        assert( requestOID != NULL );
-       assert( ber != NULL );
        assert( ctrlp != NULL );
 
        ctrl = (LDAPControl *) LDAP_MALLOC( sizeof(LDAPControl) );
@@ -438,7 +459,8 @@ ldap_create_control(
                return LDAP_NO_MEMORY;
        }
 
-       if ( ber_flatten2( ber, &ctrl->ldctl_value, 1 ) == -1 ) {
+       BER_BVZERO(&ctrl->ldctl_value);
+       if ( ber && ( ber_flatten2( ber, &ctrl->ldctl_value, 1 ) == -1 )) {
                LDAP_FREE( ctrl );
                return LDAP_NO_MEMORY;
        }
@@ -455,6 +477,54 @@ ldap_create_control(
        return LDAP_SUCCESS;
 }
 
+/*
+ * Create a LDAPControl, optionally from value
+ */
+int
+ldap_control_create(
+       LDAP_CONST char *requestOID,
+       int iscritical,
+       struct berval *value,
+       int dupval,
+       LDAPControl **ctrlp )
+{
+       LDAPControl *ctrl;
+
+       assert( requestOID != NULL );
+       assert( ctrlp != NULL );
+
+       ctrl = (LDAPControl *) LDAP_CALLOC( sizeof(LDAPControl), 1 );
+       if ( ctrl == NULL ) {
+               return LDAP_NO_MEMORY;
+       }
+
+       ctrl->ldctl_iscritical = iscritical;
+       if ( requestOID != NULL ) {
+               ctrl->ldctl_oid = LDAP_STRDUP( requestOID );
+               if ( ctrl->ldctl_oid == NULL ) {
+                       ldap_control_free( ctrl );
+                       return LDAP_NO_MEMORY;
+               }
+       }
+
+       if ( value && !BER_BVISNULL( value ) ) {
+               if ( dupval ) {
+                       ber_dupbv( &ctrl->ldctl_value, value );
+                       if ( BER_BVISNULL( &ctrl->ldctl_value ) ) {
+                               ldap_control_free( ctrl );
+                               return LDAP_NO_MEMORY;
+                       }
+
+               } else {
+                       ctrl->ldctl_value = *value;
+               }
+       }
+
+       *ctrlp = ctrl;
+
+       return LDAP_SUCCESS;
+}
+
 /*
  * check for critical client controls and bitch if present
  * if we ever support critical controls, we'll have to
index 88ec16f4bd13a15cd8592d83aee36ce2e3c2e16f..e3c986d89edbe69860b795a2a1ab8bfd46ada78c 100644 (file)
@@ -113,13 +113,14 @@ ldap_refresh(
        rc = ber_flatten2( ber, &bv, 0 );
 
        if ( rc < 0 ) {
-               ld->ld_errno = LDAP_ENCODING_ERROR;
-               return ld->ld_errno;
+               rc = ld->ld_errno = LDAP_ENCODING_ERROR;
+               goto done;
        }
 
        rc = ldap_extended_operation( ld, LDAP_EXOP_REFRESH, &bv,
                sctrls, cctrls, msgidp );
 
+done:;
         ber_free( ber, 1 );
 
        return rc;
index 644180de0ecf0662291c4363544fb5131e8f54f5..5a6efda9f13bb0348122842a591b783e4b1768f6 100644 (file)
@@ -315,6 +315,7 @@ ldap_parse_intermediate (
 
        if( retoidp != NULL ) *retoidp = NULL;
        if( retdatap != NULL ) *retdatap = NULL;
+       if( serverctrls != NULL ) *serverctrls = NULL;
 
        ber = ber_dup( res->lm_ber );
 
index 161beca9f0a8ee7b9ecb1896f7597e1144855447..d43287172576ff1174dffff2afaf20f26ebb5137 100644 (file)
@@ -2368,12 +2368,12 @@ strval2DCEstr( struct berval *val, char *str, unsigned flags, ber_len_t *len )
 
 /*
  * Length of the (supposedly) AD canonical string representation, 
- * accounting for escaped hex of UTF-8 chars
+ * accounting for chars that need to be escaped 
  */
 static int
 strval2ADstrlen( struct berval *val, unsigned flags, ber_len_t *len )
 {
-       ber_len_t       l;
+       ber_len_t       l, cl;
        char            *p;
 
        assert( val != NULL );
@@ -2384,37 +2384,31 @@ strval2ADstrlen( struct berval *val, unsigned flags, ber_len_t *len )
                return( 0 );
        }
 
-       if ( flags & LDAP_AVA_NONPRINTABLE ) {
-               /* 
-                * FIXME: Turn the value into a binary encoded BER?
-                */
-               return( -1 );
-               
-       } else {
-               for ( l = 0, p = val->bv_val; p[ 0 ]; p++ ) {
-                       if ( LDAP_DN_NEEDESCAPE_AD( p[ 0 ] ) ) {
-                               l += 2;
-
-                       } else {
-                               l++;
-                       }
+       for ( l = 0, p = val->bv_val; p[ 0 ]; p += cl ) {
+               cl = LDAP_UTF8_CHARLEN2( p, cl );
+               if ( cl == 0 ) {
+                       /* illegal utf-8 char */
+                       return -1;
+               } else if ( (cl == 1) && LDAP_DN_NEEDESCAPE_AD( p[ 0 ] ) ) {
+                       l += 2;
+               } else {
+                       l += cl;
                }
        }
 
        *len = l;
-       
+
        return( 0 );
 }
 
 /*
- * convert to (supposedly) AD string representation, 
- * escaping with hex the UTF-8 stuff;
+ * convert to (supposedly) AD string representation,
  * assume the destination has enough room for escaping
  */
 static int
 strval2ADstr( struct berval *val, char *str, unsigned flags, ber_len_t *len )
 {
-       ber_len_t       s, d;
+       ber_len_t       s, d, cl;
 
        assert( val != NULL );
        assert( str != NULL );
@@ -2425,24 +2419,20 @@ strval2ADstr( struct berval *val, char *str, unsigned flags, ber_len_t *len )
                return( 0 );
        }
 
-       if ( flags & LDAP_AVA_NONPRINTABLE ) {
-               /*
-                * FIXME: Turn the value into a binary encoded BER?
-                */
-               *len = 0;
-               return( -1 );
-               
-       } else {
-
-               /* 
-                * we assume the string has enough room for the hex encoding
-                * of the value
-                */
+       /* 
+        * we assume the string has enough room for the escaping
+        * of the value
+        */
 
-               for ( s = 0, d = 0; s < val->bv_len; ) {
-                       if ( LDAP_DN_NEEDESCAPE_AD( val->bv_val[ s ] ) ) {
-                               str[ d++ ] = '\\';
-                       }
+       for ( s = 0, d = 0; s < val->bv_len; ) {
+               cl = LDAP_UTF8_CHARLEN2( val->bv_val+s, cl );
+               if ( cl == 0 ) {
+                       /* illegal utf-8 char */
+                       return -1;
+               } else if ( (cl == 1) && LDAP_DN_NEEDESCAPE_AD(val->bv_val[ s ]) ) {
+                       str[ d++ ] = '\\';
+               }
+               for (; cl--;) {
                        str[ d++ ] = val->bv_val[ s++ ];
                }
        }
@@ -3309,202 +3299,3 @@ return_results:;
        return( rc );
 }
 
-#ifdef HAVE_TLS
-#include <openssl/x509.h>
-#include <openssl/err.h>
-
-/* Convert a structured DN from an X.509 certificate into an LDAPV3 DN.
- * x509_name must be an (X509_NAME *). If func is non-NULL, the
- * constructed DN will use numeric OIDs to identify attributeTypes,
- * and the func() will be invoked to rewrite the DN with the given
- * flags.
- *
- * Otherwise the DN will use shortNames as defined in the OpenSSL
- * library.
- *
- * It's preferable to let slapd do the OID to attributeType mapping,
- * because the OpenSSL tables are known to have many typos in versions
- * up to (at least) 0.9.6c. However, the LDAP client has no schema tables,
- * so we're forced to use OpenSSL's mapping there.
- *  -- Howard Chu 2002-04-18
- */
-
-int
-ldap_X509dn2bv( void *x509_name, struct berval *bv, LDAPDN_rewrite_func *func,
-       unsigned flags )
-{
-       LDAPDN  newDN;
-       LDAPRDN newRDN;
-       LDAPAVA *newAVA, *baseAVA;
-       X509_NAME_ENTRY *ne;
-       ASN1_OBJECT *obj;
-       ASN1_STRING *str;
-       char oids[8192], *oidptr = oids, *oidbuf = NULL;
-       void *ptrs[2048];
-       int i, j, k = 0, navas, nrdns, rc = LDAP_SUCCESS;
-       int set = -1;
-       size_t dnsize, oidrem = sizeof(oids), oidsize = 0;
-       int csize;
-
-       struct berval   Val;
-
-       assert( bv != NULL );
-       bv->bv_len = 0;
-       bv->bv_val = NULL;
-
-       /* Get the number of AVAs. This is not necessarily the same as
-        * the number of RDNs.
-        */
-       navas = X509_NAME_entry_count( x509_name );
-
-       /* Get the last element, to see how many RDNs there are */
-       ne = X509_NAME_get_entry( x509_name, navas - 1 );
-       nrdns = ne->set + 1;
-
-       /* Allocate the DN/RDN/AVA stuff as a single block */    
-       dnsize = sizeof(LDAPRDN) * (nrdns+1);
-       dnsize += sizeof(LDAPAVA *) * (navas+nrdns);
-       dnsize += sizeof(LDAPAVA) * navas;
-       if (dnsize > sizeof(ptrs)) {
-               newDN = (LDAPDN)LDAP_MALLOC( dnsize );
-               if ( newDN == NULL )
-                       return LDAP_NO_MEMORY;
-       } else {
-               newDN = (LDAPDN)(char *)ptrs;
-       }
-       
-       newDN[nrdns] = NULL;
-       newRDN = (LDAPRDN)(newDN + nrdns+1);
-       newAVA = (LDAPAVA *)(newRDN + navas + nrdns);
-       baseAVA = newAVA;
-
-       /* Retrieve RDNs in reverse order; LDAP is backwards from X.500. */
-       for ( i = nrdns - 1, j = 0; i >= 0; i-- ) {
-               ne = X509_NAME_get_entry( x509_name, i );
-               obj = X509_NAME_ENTRY_get_object( ne );
-               str = X509_NAME_ENTRY_get_data( ne );
-
-               /* If set changed, move to next RDN */
-               if ( set != ne->set ) {
-                       /* If this is not the first time, end the
-                        * previous RDN and advance.
-                        */
-                       if ( j > 0 ) {
-                               newRDN[k] = NULL;
-                               newRDN += k+1;
-                       }
-                       newDN[j++] = newRDN;
-
-                       k = 0;
-                       set = ne->set;
-               }
-               newAVA->la_private = NULL;
-               newAVA->la_flags = LDAP_AVA_STRING;
-
-               if ( !func ) {
-                       int n = OBJ_obj2nid( obj );
-
-                       if (n == NID_undef)
-                               goto get_oid;
-                       newAVA->la_attr.bv_val = (char *)OBJ_nid2sn( n );
-                       newAVA->la_attr.bv_len = strlen( newAVA->la_attr.bv_val );
-#ifdef HAVE_EBCDIC
-                       newAVA->la_attr.bv_val = LDAP_STRDUP( newAVA->la_attr.bv_val );
-                       __etoa( newAVA->la_attr.bv_val );
-                       newAVA->la_flags |= LDAP_AVA_FREE_ATTR;
-#endif
-               } else {
-get_oid:               newAVA->la_attr.bv_val = oidptr;
-                       newAVA->la_attr.bv_len = OBJ_obj2txt( oidptr, oidrem, obj, 1 );
-#ifdef HAVE_EBCDIC
-                       __etoa( newAVA->la_attr.bv_val );
-#endif
-                       oidptr += newAVA->la_attr.bv_len + 1;
-                       oidrem -= newAVA->la_attr.bv_len + 1;
-
-                       /* Running out of OID buffer space? */
-                       if (oidrem < 128) {
-                               if ( oidsize == 0 ) {
-                                       oidsize = sizeof(oids) * 2;
-                                       oidrem = oidsize;
-                                       oidbuf = LDAP_MALLOC( oidsize );
-                                       if ( oidbuf == NULL ) goto nomem;
-                                       oidptr = oidbuf;
-                               } else {
-                                       char *old = oidbuf;
-                                       oidbuf = LDAP_REALLOC( oidbuf, oidsize*2 );
-                                       if ( oidbuf == NULL ) goto nomem;
-                                       /* Buffer moved! Fix AVA pointers */
-                                       if ( old != oidbuf ) {
-                                               LDAPAVA *a;
-                                               long dif = oidbuf - old;
-
-                                               for (a=baseAVA; a<=newAVA; a++){
-                                                       if (a->la_attr.bv_val >= old &&
-                                                               a->la_attr.bv_val <= (old + oidsize))
-                                                               a->la_attr.bv_val += dif;
-                                               }
-                                       }
-                                       oidptr = oidbuf + oidsize - oidrem;
-                                       oidrem += oidsize;
-                                       oidsize *= 2;
-                               }
-                       }
-               }
-               Val.bv_val = (char *) str->data;
-               Val.bv_len = str->length;
-               switch( str->type ) {
-               case V_ASN1_UNIVERSALSTRING:
-                       /* This uses 32-bit ISO 10646-1 */
-                       csize = 4; goto to_utf8;
-               case V_ASN1_BMPSTRING:
-                       /* This uses 16-bit ISO 10646-1 */
-                       csize = 2; goto to_utf8;
-               case V_ASN1_T61STRING:
-                       /* This uses 8-bit, assume ISO 8859-1 */
-                       csize = 1;
-to_utf8:               rc = ldap_ucs_to_utf8s( &Val, csize, &newAVA->la_value );
-                       newAVA->la_flags |= LDAP_AVA_FREE_VALUE;
-                       if (rc != LDAP_SUCCESS) goto nomem;
-                       newAVA->la_flags = LDAP_AVA_NONPRINTABLE;
-                       break;
-               case V_ASN1_UTF8STRING:
-                       newAVA->la_flags = LDAP_AVA_NONPRINTABLE;
-                       /* This is already in UTF-8 encoding */
-               case V_ASN1_IA5STRING:
-               case V_ASN1_PRINTABLESTRING:
-                       /* These are always 7-bit strings */
-                       newAVA->la_value = Val;
-               default:
-                       ;
-               }
-               newRDN[k] = newAVA;
-               newAVA++;
-               k++;
-       }
-       newRDN[k] = NULL;
-
-       if ( func ) {
-               rc = func( newDN, flags, NULL );
-               if ( rc != LDAP_SUCCESS )
-                       goto nomem;
-       }
-
-       rc = ldap_dn2bv_x( newDN, bv, LDAP_DN_FORMAT_LDAPV3, NULL );
-
-nomem:
-       for (;baseAVA < newAVA; baseAVA++) {
-               if (baseAVA->la_flags & LDAP_AVA_FREE_ATTR)
-                       LDAP_FREE( baseAVA->la_attr.bv_val );
-               if (baseAVA->la_flags & LDAP_AVA_FREE_VALUE)
-                       LDAP_FREE( baseAVA->la_value.bv_val );
-       }
-
-       if ( oidsize != 0 )
-               LDAP_FREE( oidbuf );
-       if ( newDN != (LDAPDN)(char *) ptrs )
-               LDAP_FREE( newDN );
-       return rc;
-}
-#endif /* HAVE_TLS */
-
index 345eb823d3f7bf4827086a384f214ff99bcbca88..3f6e3d61e027f583704451a372a67d397f243997 100644 (file)
@@ -114,6 +114,9 @@ static const struct ol_attribute {
 #ifdef HAVE_OPENSSL_CRL
        {0, ATTR_TLS,   "TLS_CRLCHECK",         NULL,   LDAP_OPT_X_TLS_CRLCHECK},
 #endif
+#ifdef HAVE_GNUTLS
+       {0, ATTR_TLS,   "TLS_CRL",                      NULL,   LDAP_OPT_X_TLS_CRLFILE},
+#endif
         
 #endif
 
@@ -521,6 +524,7 @@ void ldap_int_initialize_global_options( struct ldapoptions *gopts, int *dbglvl
 #ifdef HAVE_TLS
        gopts->ldo_tls_connect_cb = NULL;
        gopts->ldo_tls_connect_arg = NULL;
+       gopts->ldo_tls_require_cert = LDAP_OPT_X_TLS_DEMAND;
 #endif
 
        gopts->ldo_valid = LDAP_INITIALIZED;
index 5f6f6d5d35519494c2e2538d250937ce36edd1b4..91e9bb8ae9efbecd4713a7bc75429be0d2ed00b9 100644 (file)
@@ -38,7 +38,7 @@
 #include <sasl.h>
 #endif
 
-#define SASL_MAX_BUFF_SIZE     65536
+#define SASL_MAX_BUFF_SIZE     (0xffffff)
 #define SASL_MIN_BUFF_SIZE     4096
 #endif
 
@@ -154,6 +154,9 @@ struct ldaptls {
        char            *lt_cacertfile;
        char            *lt_cacertdir;
        char            *lt_ciphersuite;
+#ifdef HAVE_GNUTLS
+       char            *lt_crlfile;
+#endif
 };
 #endif
 
@@ -196,6 +199,7 @@ struct ldapoptions {
 #define ldo_tls_cacertfile     ldo_tls_info.lt_cacertfile
 #define ldo_tls_cacertdir      ldo_tls_info.lt_cacertdir
 #define ldo_tls_ciphersuite    ldo_tls_info.lt_ciphersuite
+#define ldo_tls_crlfile        ldo_tls_info.lt_crlfile
        int                     ldo_tls_mode;
        int                     ldo_tls_require_cert;
 #ifdef HAVE_OPENSSL_CRL
@@ -595,10 +599,6 @@ LDAP_F (LDAPURLDesc *) ldap_url_dup LDAP_P((
 LDAP_F (LDAPURLDesc *) ldap_url_duplist LDAP_P((
        LDAPURLDesc *ludlist ));
 
-LDAP_F (int) ldap_url_parselist LDAP_P((
-       LDAPURLDesc **ludlist,
-       const char *url ));
-
 LDAP_F (int) ldap_url_parsehosts LDAP_P((
        LDAPURLDesc **ludlist,
        const char *hosts,
index 00ff0fa1a53702fc57d3a90137c3810452cd0408..a94cfaab6efc7353713409e42508da9d2823eb58 100644 (file)
@@ -5,7 +5,7 @@
 # See ldap.conf(5) for details
 # This file should be world readable but not world writable.
 
-#BASE  dc=example, dc=com
+#BASE  dc=example,dc=com
 #URI   ldap://ldap.example.com ldap://ldap-master.example.com:666
 
 #SIZELIMIT     12
index 8db70ada2801960d0d22142adfc2adf6b1835805..8eb8933e200c277e70b45101f602be80537bf30d 100644 (file)
 #include "ldap-int.h"
 
 #ifdef LDAP_SYNC_TRACE
-/*
- * used for debug purposes
- */
-static char *
-print_UUID( char *buf, size_t len, unsigned char *UUID )
-{
-       snprintf( buf, len,
-               "%02x%02x%02x%02x-%02x%02x-%02x%02x-"
-               "%02x%02x-%02x%02x%02x%02x%02x%02x",
-               UUID[0],
-               UUID[1],
-               UUID[2],
-               UUID[3],
-               UUID[4],
-               UUID[5],
-               UUID[6],
-               UUID[7],
-               UUID[8],
-               UUID[9],
-               UUID[10],
-               UUID[11],
-               UUID[12],
-               UUID[13],
-               UUID[14],
-               UUID[15] );
-       return buf;
-}
-
 static const char *
 ldap_sync_state2str( int state )
 {
@@ -600,8 +572,9 @@ ldap_sync_search_intermediate( ldap_sync_t *ls, LDAPMessage *res, int *refreshDo
                        for ( i = 0; syncUUIDs[ i ].bv_val != NULL; i++ ) {
                                char    buf[ BUFSIZ ];
                                fprintf( stderr, "\t\t%s\n", 
-                                       print_UUID( buf, sizeof( buf ),
-                                               (unsigned char *)syncUUIDs[ i ].bv_val ) );
+                                       lutil_uuidstr_from_normalized(
+                                               syncUUIDs[ i ].bv_val, syncUUIDs[ i ].bv_len,
+                                               buf, sizeof( buf ) ) );
                        }
                }
 #endif /* LDAP_SYNC_TRACE */
index 4b7de9e690f362c5b72c7c56b3a777f6d315e48a..7859aa75e3061f0c0abf481c4c21b833589fb682 100644 (file)
@@ -174,7 +174,7 @@ ldap_pvt_is_socket_ready(LDAP *ld, int s)
 #if defined( notyet ) /* && defined( SO_ERROR ) */
 {
        int so_errno;
-       socklen_t dummy = sizeof(so_errno);
+       ber_socklen_t dummy = sizeof(so_errno);
        if ( getsockopt( s, SOL_SOCKET, SO_ERROR, &so_errno, &dummy )
                == AC_SOCKET_ERROR )
        {
@@ -196,7 +196,7 @@ ldap_pvt_is_socket_ready(LDAP *ld, int s)
        struct sockaddr_in sin;
 #endif
        char ch;
-       socklen_t dummy = sizeof(sin);
+       ber_socklen_t dummy = sizeof(sin);
        if ( getpeername( s, (struct sockaddr *) &sin, &dummy )
                == AC_SOCKET_ERROR )
        {
@@ -316,7 +316,7 @@ ldap_int_poll(
                /* This means the connection failed */
                if ( FD_ISSET(s, &efds) ) {
                        int so_errno;
-                       int dummy = sizeof(so_errno);
+                       ber_socklen_t dummy = sizeof(so_errno);
                        if ( getsockopt( s, SOL_SOCKET, SO_ERROR,
                                (char *) &so_errno, &dummy ) == AC_SOCKET_ERROR || !so_errno )
                        {
@@ -350,7 +350,7 @@ ldap_int_poll(
 
 static int
 ldap_pvt_connect(LDAP *ld, ber_socket_t s,
-       struct sockaddr *sin, socklen_t addrlen,
+       struct sockaddr *sin, ber_socklen_t addrlen,
        int async)
 {
        int rc, err;
@@ -621,7 +621,7 @@ ldap_connect_to_host(LDAP *ld, Sockbuf *sb,
 char *
 ldap_host_connected_to( Sockbuf *sb, const char *host )
 {
-       socklen_t               len;
+       ber_socklen_t   len;
 #ifdef LDAP_PF_INET6
        struct sockaddr_storage sabuf;
 #else
index 4e3a19e5a29c20fa0fe19f1f73195f1996890230..fbec2273e13437e4933dad8af4b550496fc586fe 100644 (file)
@@ -120,7 +120,7 @@ ldap_pvt_is_socket_ready(LDAP *ld, int s)
 #if defined( notyet ) /* && defined( SO_ERROR ) */
 {
        int so_errno;
-       socklen_t dummy = sizeof(so_errno);
+       ber_socklen_t dummy = sizeof(so_errno);
        if ( getsockopt( s, SOL_SOCKET, SO_ERROR, &so_errno, &dummy )
                == AC_SOCKET_ERROR )
        {
@@ -138,7 +138,7 @@ ldap_pvt_is_socket_ready(LDAP *ld, int s)
        /* error slippery */
        struct sockaddr_un sa;
        char ch;
-       socklen_t dummy = sizeof(sa);
+       ber_socklen_t dummy = sizeof(sa);
        if ( getpeername( s, (struct sockaddr *) &sa, &dummy )
                == AC_SOCKET_ERROR )
        {
@@ -154,12 +154,7 @@ ldap_pvt_is_socket_ready(LDAP *ld, int s)
 }
 #undef TRACE
 
-#if !defined(HAVE_GETPEEREID) && \
-       !defined(HAVE_GETPEERUCRED) && \
-       !defined(SO_PEERCRED) && !defined(LOCAL_PEERCRED) && \
-       defined(HAVE_SENDMSG) && (defined(HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTSLEN) || \
-               defined(HAVE_STRUCT_MSGHDR_MSG_CONTROL))
-#define DO_SENDMSG
+#ifdef LDAP_PF_LOCAL_SENDMSG
 static const char abandonPDU[] = {LDAP_TAG_MESSAGE, 6,
        LDAP_TAG_MSGID, 1, 0, LDAP_REQ_ABANDON, 1, 0};
 #endif
@@ -185,13 +180,16 @@ ldap_pvt_connect(LDAP *ld, ber_socket_t s, struct sockaddr_un *sa, int async)
        {
                if ( ldap_pvt_ndelay_off(ld, s) == -1 ) return -1;
 
-#ifdef DO_SENDMSG
+#ifdef LDAP_PF_LOCAL_SENDMSG
        /* Send a dummy message with access rights. Remote side will
-        * obtain our uid/gid by fstat'ing this descriptor.
+        * obtain our uid/gid by fstat'ing this descriptor. The
+        * descriptor permissions must match exactly, and we also
+        * send the socket name, which must also match.
         */
 sendcred:
                {
                        int fds[2];
+                       ber_socklen_t salen = sizeof(*sa);
                        if (pipe(fds) == 0) {
                                /* Abandon, noop, has no reply */
                                struct iovec iov;
@@ -230,6 +228,9 @@ sendcred:
                                msg.msg_accrights = (char *)fds;
                                msg.msg_accrightslen = sizeof(int);
 # endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
+                               getpeername( s, sa, &salen );
+                               fchmod( fds[0], S_ISUID|S_IRWXU );
+                               write( fds[1], sa, salen );
                                sendmsg( s, &msg, 0 );
                                close(fds[0]);
                                close(fds[1]);
@@ -266,7 +267,7 @@ sendcred:
                if( fd.revents & POLL_WRITE ) {
                        if ( ldap_pvt_is_socket_ready(ld, s) == -1 ) return -1;
                        if ( ldap_pvt_ndelay_off(ld, s) == -1 ) return -1;
-#ifdef DO_SENDMSG
+#ifdef LDAP_PF_LOCAL_SENDMSG
                        goto sendcred;
 #else
                        return ( 0 );
@@ -297,7 +298,7 @@ sendcred:
                if ( FD_ISSET(s, &wfds) ) {
                        if ( ldap_pvt_is_socket_ready(ld, s) == -1 ) return -1;
                        if ( ldap_pvt_ndelay_off(ld, s) == -1 ) return -1;
-#ifdef DO_SENDMSG
+#ifdef LDAP_PF_LOCAL_SENDMSG
                        goto sendcred;
 #else
                        return ( 0 );
index df4978705d8401bc22770a8dd8a55bb5b2c029fd..93222406b18421edb8e389b609a5f460b5f585fc 100644 (file)
@@ -139,7 +139,6 @@ ldap_create_page_control(
        LDAPControl     **ctrlp )
 {
        struct berval   value;
-       BerElement      *ber;
 
        if ( ctrlp == NULL ) {
                ld->ld_errno = LDAP_PARAM_ERROR;
@@ -149,19 +148,11 @@ ldap_create_page_control(
        ld->ld_errno = ldap_create_page_control_value( ld,
                pagesize, cookie, &value );
        if ( ld->ld_errno == LDAP_SUCCESS ) {
-               if ((ber = ldap_alloc_ber_with_options(ld)) == NULL) {
-                       ld->ld_errno = LDAP_NO_MEMORY;
-                       return LDAP_NO_MEMORY;
-               }
-
-               ld->ld_errno = ldap_create_control( LDAP_CONTROL_PAGEDRESULTS,
-                       ber, iscritical, ctrlp );
-               if ( ld->ld_errno == LDAP_SUCCESS ) {
-                       (*ctrlp)->ldctl_value = value;
-               } else {
+               ld->ld_errno = ldap_control_create( LDAP_CONTROL_PAGEDRESULTS,
+                       iscritical, &value, 0, ctrlp );
+               if ( ld->ld_errno != LDAP_SUCCESS ) {
                        LDAP_FREE( value.bv_val );
                }
-               ber_free(ber, 1);
        }
 
        return ld->ld_errno;
@@ -256,7 +247,7 @@ ldap_parse_page_control(
                return ld->ld_errno;
        }
 
-       c = ldap_find_control( LDAP_CONTROL_PAGEDRESULTS, ctrls );
+       c = ldap_control_find( LDAP_CONTROL_PAGEDRESULTS, ctrls, NULL );
        if ( c == NULL ) {
                /* No page control was found. */
                ld->ld_errno = LDAP_CONTROL_NOT_FOUND;
index 16193f64008c5c830f4582712108859a85d3f147..ad7153406f08394179774116b0d71b698a38badc 100644 (file)
@@ -61,22 +61,14 @@ int
 ldap_create_passwordpolicy_control( LDAP *ld,
                                     LDAPControl **ctrlp )
 {
-       BerElement *ber;
-
        assert( ld != NULL );
        assert( LDAP_VALID( ld ) );
        assert( ctrlp != NULL );
 
-       if ((ber = ldap_alloc_ber_with_options(ld)) == NULL) {
-               ld->ld_errno = LDAP_NO_MEMORY;
-               return(LDAP_NO_MEMORY);
-       }
-
-       ld->ld_errno = ldap_create_control( LDAP_CONTROL_PASSWORDPOLICYREQUEST,
-               ber, 0, ctrlp);
+       ld->ld_errno = ldap_control_create( LDAP_CONTROL_PASSWORDPOLICYREQUEST,
+               0, NULL, 0, ctrlp );
 
-       ber_free(ber, 1);
-       return(ld->ld_errno);
+       return ld->ld_errno;
 }
 
 
@@ -88,8 +80,9 @@ ldap_create_passwordpolicy_control( LDAP *ld,
    ld           (IN)   An LDAP session handle.
    
    ctrl         (IN)   The address of an
-                                          LDAPControl structure, typically obtained 
-                                          by a call to ldap_find_control().
+                                          LDAPControl structure, either obtained 
+                                          by running thorugh the list of response controls or
+                                          by a call to ldap_control_find().
 
    exptimep     (OUT)  This result parameter is filled in with the number of seconds before
                                            the password will expire, if expiration is imminent
index ee0ec5013b9d0c05c8f694d0639940677d9094d6..be36b19845cf7f9e4c5169ec89a0acf880cace38 100644 (file)
@@ -255,6 +255,19 @@ ldap_send_server_request(
 
        use_connection( ld, lc );
 
+#ifdef LDAP_CONNECTIONLESS
+       if ( LDAP_IS_UDP( ld )) {
+               BerElement tmpber = *ber;
+               ber_rewind( &tmpber );
+               rc = ber_write( &tmpber, ld->ld_options.ldo_peer,
+                       sizeof( struct sockaddr ), 0 );
+               if ( rc == -1 ) {
+                       ld->ld_errno = LDAP_ENCODING_ERROR;
+                       return rc;
+               }
+       }
+#endif
+
        /* If we still have an incomplete write, try to finish it before
         * dealing with the new request. If we don't finish here, return
         * LDAP_BUSY and let the caller retry later. We only allow a single
@@ -377,11 +390,13 @@ ldap_new_connection( LDAP *ld, LDAPURLDesc **srvlist, int use_ldsb,
                async = LDAP_BOOL_GET( &ld->ld_options, LDAP_BOOL_CONNECT_ASYNC );
 
                for ( srvp = srvlist; *srvp != NULL; srvp = &(*srvp)->lud_next ) {
-                       if ( ldap_int_open_connection( ld, lc, *srvp, async) != -1 )
-                       {
+                       int             rc;
+
+                       rc = ldap_int_open_connection( ld, lc, *srvp, async );
+                       if ( rc != -1 ) {
                                srv = *srvp;
 
-                               if ( ld->ld_urllist_proc ) {
+                               if ( ld->ld_urllist_proc && ( !async || rc != -2 ) ) {
                                        ld->ld_urllist_proc( ld, srvlist, srvp, ld->ld_urllist_params );
                                }
 
@@ -465,7 +480,10 @@ ldap_new_connection( LDAP *ld, LDAPURLDesc **srvlist, int use_ldsb,
                        ++lc->lconn_refcnt;     /* avoid premature free */
                        ld->ld_defconn = lc;
 
-                       Debug( LDAP_DEBUG_TRACE, "anonymous rebind via ldap_bind_s\n", 0, 0, 0);
+                       Debug( LDAP_DEBUG_TRACE,
+                               "anonymous rebind via ldap_sasl_bind(\"\")\n",
+                               0, 0, 0);
+
 #ifdef LDAP_R_COMPILE
                        ldap_pvt_thread_mutex_unlock( &ld->ld_req_mutex );
                        ldap_pvt_thread_mutex_unlock( &ld->ld_res_mutex );
@@ -503,7 +521,13 @@ ldap_new_connection( LDAP *ld, LDAPURLDesc **srvlist, int use_ldsb,
                                                break;
 
                                        default:
-                                               assert( 0 );
+                                               Debug( LDAP_DEBUG_TRACE,
+                                                       "ldap_new_connection %p: "
+                                                       "unexpected response %d "
+                                                       "from BIND request id=%d\n",
+                                                       (void *) ld, ldap_msgtype( res ), msgid );
+                                               err = -1;
+                                               break;
                                        }
                                }
                        }
@@ -991,7 +1015,7 @@ ldap_chase_v3referrals( LDAP *ld, LDAPRequest *lr, char **refs, int sref, char *
                                if ( lp == origreq ) {
                                        lp = lp->lr_child;
                                } else {
-                                       lp = lr->lr_refnext;
+                                       lp = lp->lr_refnext;
                                }
                        }
                        if ( looped ) {
index 994c52bad79208bca9656baf7d50dc232473478c..c492eb94125643f313a3c32bc08f69ae8b244a95 100644 (file)
@@ -263,9 +263,8 @@ wait4msg(
        int             rc;
        struct timeval  tv = { 0 },
                        tv0 = { 0 },
-                       *tvp;
-       time_t          start_time = 0;
-       time_t          tmp_time;
+                       start_time_tv = { 0 },
+                       *tvp = NULL;
        LDAPConn        *lc;
 
        assert( ld != NULL );
@@ -290,13 +289,16 @@ wait4msg(
        }
 #endif /* LDAP_DEBUG */
 
-       if ( timeout == NULL ) {
-               tvp = NULL;
-       } else {
+       if ( timeout != NULL ) {
                tv0 = *timeout;
                tv = *timeout;
                tvp = &tv;
-               start_time = time( NULL );
+#ifdef HAVE_GETTIMEOFDAY
+               gettimeofday( &start_time_tv, NULL );
+#else /* ! HAVE_GETTIMEOFDAY */
+               time( &start_time_tv.tv_sec );
+               start_time_tv.tv_usec = 0;
+#endif /* ! HAVE_GETTIMEOFDAY */
        }
                    
        rc = LDAP_MSG_X_KEEP_LOOKING;
@@ -423,18 +425,49 @@ wait4msg(
                }
 
                if ( rc == LDAP_MSG_X_KEEP_LOOKING && tvp != NULL ) {
-                       tmp_time = time( NULL );
-                       tv0.tv_sec -= ( tmp_time - start_time );
-                       if ( tv0.tv_sec <= 0 ) {
-                               rc = 0; /* timed out */
+                       struct timeval  curr_time_tv = { 0 },
+                                       delta_time_tv = { 0 };
+
+#ifdef HAVE_GETTIMEOFDAY
+                       gettimeofday( &curr_time_tv, NULL );
+#else /* ! HAVE_GETTIMEOFDAY */
+                       time( &curr_time_tv.tv_sec );
+                       curr_time_tv.tv_usec = 0;
+#endif /* ! HAVE_GETTIMEOFDAY */
+
+                       /* delta_time = tmp_time - start_time */
+                       delta_time_tv.tv_sec = curr_time_tv.tv_sec - start_time_tv.tv_sec;
+                       delta_time_tv.tv_usec = curr_time_tv.tv_usec - start_time_tv.tv_usec;
+                       if ( delta_time_tv.tv_usec < 0 ) {
+                               delta_time_tv.tv_sec--;
+                               delta_time_tv.tv_usec += 1000000;
+                       }
+
+                       /* tv0 < delta_time ? */
+                       if ( ( tv0.tv_sec < delta_time_tv.tv_sec ) ||
+                            ( ( tv0.tv_sec == delta_time_tv.tv_sec ) && ( tv0.tv_usec < delta_time_tv.tv_usec ) ) )
+                       {
+                               rc = 0; /* timed out */
                                ld->ld_errno = LDAP_TIMEOUT;
                                break;
                        }
+
+                       /* tv0 -= delta_time */
+                       tv0.tv_sec -= delta_time_tv.tv_sec;
+                       tv0.tv_usec -= delta_time_tv.tv_usec;
+                       if ( tv0.tv_usec < 0 ) {
+                               tv0.tv_sec--;
+                               tv0.tv_usec += 1000000;
+                       }
+
                        tv.tv_sec = tv0.tv_sec;
+                       tv.tv_usec = tv0.tv_usec;
+
+                       Debug( LDAP_DEBUG_TRACE, "wait4msg ld %p %ld s %ld us to go\n",
+                               (void *)ld, (long) tv.tv_sec, (long) tv.tv_usec );
 
-                       Debug( LDAP_DEBUG_TRACE, "wait4msg ld %p %ld secs to go\n",
-                               (void *)ld, (long) tv.tv_sec, 0 );
-                       start_time = tmp_time;
+                       start_time_tv.tv_sec = curr_time_tv.tv_sec;
+                       start_time_tv.tv_usec = curr_time_tv.tv_usec;
                }
        }
 
index a09b8301cab484ef5b618f3795008c456a859f4d..2f27eddd6eff8fce4abd505cc02577e7198f082c 100644 (file)
@@ -259,8 +259,9 @@ ldap_build_search_req(
        LDAP_NEXT_MSGID( ld, *idp );
 #ifdef LDAP_CONNECTIONLESS
        if ( LDAP_IS_UDP(ld) ) {
-           err = ber_write( ber, ld->ld_options.ldo_peer,
-                   sizeof(struct sockaddr), 0);
+               struct sockaddr sa = {0};
+               /* dummy, filled with ldo_peer in request.c */
+           err = ber_write( ber, &sa, sizeof( sa ), 0 );
        }
        if ( LDAP_IS_UDP(ld) && ld->ld_options.ldo_version == LDAP_VERSION2) {
            char *dn = ld->ld_options.ldo_cldapdn;
index 0200e01dacf72073409d7a1c2ef81d67385883fb..05c66eec099f75aaab2e79bdb306df9857703ea4 100644 (file)
@@ -408,12 +408,14 @@ ldap_create_sort_control(
        LDAPControl **ctrlp )
 {
        struct berval   value;
-       BerElement      *ber;
 
        assert( ld != NULL );
        assert( LDAP_VALID( ld ) );
 
-       if ( ld == NULL ) return LDAP_PARAM_ERROR;
+       if ( ld == NULL ) {
+               return LDAP_PARAM_ERROR;
+       }
+
        if ( ctrlp == NULL ) {
                ld->ld_errno = LDAP_PARAM_ERROR;
                return ld->ld_errno;
@@ -421,19 +423,11 @@ ldap_create_sort_control(
 
        ld->ld_errno = ldap_create_sort_control_value( ld, keyList, &value );
        if ( ld->ld_errno == LDAP_SUCCESS ) {
-               if ((ber = ldap_alloc_ber_with_options(ld)) == NULL) {
-                       ld->ld_errno = LDAP_NO_MEMORY;
-                       return LDAP_NO_MEMORY;
-               }
-       
-               ld->ld_errno = ldap_create_control( LDAP_CONTROL_SORTREQUEST,
-                       ber, isCritical, ctrlp );
-               if ( ld->ld_errno == LDAP_SUCCESS ) {
-                       (*ctrlp)->ldctl_value = value;
-               } else {
+               ld->ld_errno = ldap_control_create( LDAP_CONTROL_SORTREQUEST,
+                       isCritical, &value, 0, ctrlp );
+               if ( ld->ld_errno != LDAP_SUCCESS ) {
                        LDAP_FREE( value.bv_val );
                }
-               ber_free(ber, 1);
        }
 
        return ld->ld_errno;
diff --git a/libraries/libldap/stctrl.c b/libraries/libldap/stctrl.c
new file mode 100644 (file)
index 0000000..4dc197c
--- /dev/null
@@ -0,0 +1,301 @@
+/* $OpenLDAP$ */
+/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
+ *
+ * Copyright 1998-2007 The OpenLDAP Foundation.
+ * Portions Copyright 2007 Pierangelo Masarati.
+ * 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>.
+ */
+/* ACKNOWLEDGEMENTS:
+ * This work was developed by Pierangelo Masarati for inclusion in
+ * OpenLDAP Software.
+ */
+
+#include "portable.h"
+
+#include <stdio.h>
+#include <ac/stdlib.h>
+#include <ac/string.h>
+#include <ac/time.h>
+
+#include "ldap-int.h"
+
+#ifdef LDAP_CONTROL_X_SESSION_TRACKING
+
+/*
+ * Client-side of <draft-wahl-ldap-session-03>
+ */
+
+int
+ldap_create_session_tracking_value(
+       LDAP            *ld,
+       char            *sessionSourceIp,
+       char            *sessionSourceName,
+       char            *formatOID,
+       struct berval   *sessionTrackingIdentifier,
+       struct berval   *value )
+{
+       BerElement      *ber = NULL;
+       ber_tag_t       tag;
+
+       struct berval   ip, name, oid, id;
+
+       if ( ld == NULL ||
+               formatOID == NULL ||
+               value == NULL )
+       {
+param_error:;
+               if ( ld ) {
+                       ld->ld_errno = LDAP_PARAM_ERROR;
+               }
+
+               return LDAP_PARAM_ERROR;
+       }
+
+       assert( LDAP_VALID( ld ) );
+
+       /* check sizes according to I.D. */
+       if ( sessionSourceIp == NULL ) {
+               BER_BVSTR( &ip, "" );
+
+       } else {
+               ber_str2bv( sessionSourceIp, 0, 0, &ip );
+               /* NOTE: we're strict because we don't want
+                * to send out bad data */
+               if ( ip.bv_len > 128 ) goto param_error;
+       }
+
+       if ( sessionSourceName == NULL ) {
+               BER_BVSTR( &name, "" );
+
+       } else {
+               ber_str2bv( sessionSourceName, 0, 0, &name );
+               /* NOTE: we're strict because we don't want
+                * to send out bad data */
+               if ( name.bv_len > 65536 ) goto param_error;
+       }
+
+       ber_str2bv( formatOID, 0, 0, &oid );
+       /* NOTE: we're strict because we don't want
+        * to send out bad data */
+       if ( oid.bv_len > 1024 ) goto param_error;
+
+       if ( sessionTrackingIdentifier == NULL ||
+               sessionTrackingIdentifier->bv_val == NULL )
+       {
+               BER_BVSTR( &id, "" );
+
+       } else {
+               id = *sessionTrackingIdentifier;
+       }
+
+       /* prepare value */
+       value->bv_val = NULL;
+       value->bv_len = 0;
+
+       ber = ldap_alloc_ber_with_options( ld );
+       if ( ber == NULL ) {
+               ld->ld_errno = LDAP_NO_MEMORY;
+               return ld->ld_errno;
+       }
+
+       tag = ber_printf( ber, "{OOOO}", &ip, &name, &oid, &id );
+       if ( tag == LBER_ERROR ) {
+               ld->ld_errno = LDAP_ENCODING_ERROR;
+               goto done;
+       }
+
+       if ( ber_flatten2( ber, value, 1 ) == -1 ) {
+               ld->ld_errno = LDAP_NO_MEMORY;
+       }
+
+done:;
+       if ( ber != NULL ) {
+               ber_free( ber, 1 );
+       }
+
+       return ld->ld_errno;
+}
+
+/*
+ * NOTE: this API is bad; it could be much more efficient...
+ */
+int
+ldap_create_session_tracking_control(
+       LDAP            *ld,
+       char            *sessionSourceIp,
+       char            *sessionSourceName,
+       char            *formatOID,
+       struct berval   *sessionTrackingIdentifier,
+       LDAPControl     **ctrlp )
+{
+       struct berval   value;
+
+       if ( ctrlp == NULL ) {
+               ld->ld_errno = LDAP_PARAM_ERROR;
+               return ld->ld_errno;
+       }
+
+       ld->ld_errno = ldap_create_session_tracking_value( ld,
+               sessionSourceIp, sessionSourceName, formatOID,
+               sessionTrackingIdentifier, &value );
+       if ( ld->ld_errno == LDAP_SUCCESS ) {
+               ld->ld_errno = ldap_control_create( LDAP_CONTROL_X_SESSION_TRACKING,
+                       0, &value, 0, ctrlp );
+               if ( ld->ld_errno != LDAP_SUCCESS ) {
+                       LDAP_FREE( value.bv_val );
+               }
+       }
+
+       return ld->ld_errno;
+}
+
+int
+ldap_parse_session_tracking_control(
+       LDAP *ld,
+       LDAPControl *ctrl,
+       struct berval *ip,
+       struct berval *name,
+       struct berval *oid,
+       struct berval *id )
+{
+       BerElement      *ber;
+       ber_tag_t       tag;
+       ber_len_t       len;
+
+       if ( ld == NULL || 
+               ctrl == NULL || 
+               ip == NULL ||
+               name == NULL ||
+               oid == NULL ||
+               id == NULL )
+       {
+               if ( ld ) {
+                       ld->ld_errno = LDAP_PARAM_ERROR;
+               }
+
+               /* NOTE: we want the caller to get all or nothing;
+                * we could allow some of the pointers to be NULL,
+                * if one does not want part of the data */
+               return LDAP_PARAM_ERROR;
+       }
+
+       BER_BVZERO( ip );
+       BER_BVZERO( name );
+       BER_BVZERO( oid );
+       BER_BVZERO( id );
+
+       ber = ber_init( &ctrl->ldctl_value );
+
+       if ( ber == NULL ) {
+               ld->ld_errno = LDAP_NO_MEMORY;
+               return ld->ld_errno;
+       }
+
+       tag = ber_skip_tag( ber, &len );
+       if ( tag != LBER_SEQUENCE ) {
+               tag = LBER_ERROR;
+               goto error;
+       }
+
+       /* sessionSourceIp */
+       tag = ber_peek_tag( ber, &len );
+       if ( tag == LBER_DEFAULT ) {
+               tag = LBER_ERROR;
+               goto error;
+       }
+
+       if ( len == 0 ) {
+               tag = ber_skip_tag( ber, &len );
+
+       } else {
+               if ( len > 128 ) {
+                       /* should be LDAP_DECODING_ERROR,
+                        * but we're liberal in what we accept */
+               }
+               tag = ber_scanf( ber, "o", ip );
+       }
+
+       /* sessionSourceName */
+       tag = ber_peek_tag( ber, &len );
+       if ( tag == LBER_DEFAULT ) {
+               tag = LBER_ERROR;
+               goto error;
+       }
+
+       if ( len == 0 ) {
+               tag = ber_skip_tag( ber, &len );
+
+       } else {
+               if ( len > 65536 ) {
+                       /* should be LDAP_DECODING_ERROR,
+                        * but we're liberal in what we accept */
+               }
+               tag = ber_scanf( ber, "o", name );
+       }
+
+       /* formatOID */
+       tag = ber_peek_tag( ber, &len );
+       if ( tag == LBER_DEFAULT ) {
+               tag = LBER_ERROR;
+               goto error;
+       }
+
+       if ( len == 0 ) {
+               ld->ld_errno = LDAP_DECODING_ERROR;
+               goto error;
+
+       } else {
+               if ( len > 1024 ) {
+                       /* should be LDAP_DECODING_ERROR,
+                        * but we're liberal in what we accept */
+               }
+               tag = ber_scanf( ber, "o", oid );
+       }
+
+       /* FIXME: should check if it is an OID... leave it to the caller */
+
+       /* sessionTrackingIdentifier */
+       tag = ber_peek_tag( ber, &len );
+       if ( tag == LBER_DEFAULT ) {
+               tag = LBER_ERROR;
+               goto error;
+       }
+
+       if ( len == 0 ) {
+               tag = ber_skip_tag( ber, &len );
+
+       } else {
+#if 0
+               if ( len > 65536 ) {
+                       /* should be LDAP_DECODING_ERROR,
+                        * but we're liberal in what we accept */
+               }
+#endif
+               tag = ber_scanf( ber, "o", id );
+       }
+
+       /* closure */
+       tag = ber_skip_tag( ber, &len );
+       if ( tag == LBER_DEFAULT && len == 0 ) {
+               tag = 0;
+       }
+
+error:;
+       (void)ber_free( ber, 1 );
+
+       if ( tag == LBER_ERROR ) {
+               return LDAP_DECODING_ERROR;
+       }
+
+       return ld->ld_errno;
+}
+
+#endif /* LDAP_CONTROL_X_SESSION_TRACKING */
index 7b87e9a90d7a89de4d96a901ee1b007196a18a56..b3125301a2ce34bc06b9dc7e1e635bf34d13a64e 100644 (file)
@@ -277,7 +277,8 @@ main( int argc, char **argv )
        char            passwd[64], dn[256], rdn[64], attr[64], value[256];
        char            filter[256], *host, **types;
        char            **exdn;
-       char            *usage = "usage: %s [-u] [-h host] [-d level] [-s dnsuffix] [-p port] [-t file] [-T file]\n";
+       static const char usage[] =
+               "usage: %s [-u] [-h host] [-d level] [-s dnsuffix] [-p port] [-t file] [-T file]\n";
        int             bound, all, scope, attrsonly;
        LDAPMessage     *res;
        LDAPMod         **mods, **attrs;
index 2d14794a19457567c03405a82b58e9e177034062..8d15e94ead3d58d239f6c91c28d5e51f49a8edd5 100644 (file)
@@ -1,4 +1,4 @@
-/* tls.c - Handle tls/ssl using SSLeay or OpenSSL. */
+/* tls.c - Handle tls/ssl using SSLeay, OpenSSL or GNUTLS. */
 /* $OpenLDAP$ */
 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
  *
  * top-level directory of the distribution or, alternatively, at
  * <http://www.OpenLDAP.org/license.html>.
  */
+/* ACKNOWLEDGEMENTS: GNUTLS support written by Howard Chu and
+ * Matt Backes; sponsored by The Written Word (thewrittenword.com)
+ * and Stanford University (stanford.edu).
+ */
 
 #include "portable.h"
 #include "ldap_config.h"
 #include <ldap_pvt_thread.h>
 #endif
 
+#ifdef HAVE_GNUTLS
+#include <gnutls/gnutls.h>
+#include <gnutls/x509.h>
+#include <gcrypt.h>
+
+#define DH_BITS        (1024)
+
+#else
 #ifdef HAVE_OPENSSL_SSL_H
 #include <openssl/ssl.h>
 #include <openssl/x509v3.h>
 #elif defined( HAVE_SSL_H )
 #include <ssl.h>
 #endif
-
-static int  tls_opt_trace = 1;
-static char *tls_opt_randfile = NULL;
+#endif
 
 #define HAS_TLS( sb )  ber_sockbuf_ctrl( sb, LBER_SB_OPT_HAS_IO, \
                                (void *)&sb_tls_sbio )
 
+#endif /* HAVE_TLS */
+
+/* RFC2459 minimum required set of supported attribute types
+ * in a certificate DN
+ */
+typedef struct oid_name {
+       struct berval oid;
+       struct berval name;
+} oid_name;
+
+#define        CN_OID  oids[0].oid.bv_val
+
+static oid_name oids[] = {
+       { BER_BVC("2.5.4.3"), BER_BVC("cn") },
+       { BER_BVC("2.5.4.4"), BER_BVC("sn") },
+       { BER_BVC("2.5.4.6"), BER_BVC("c") },
+       { BER_BVC("2.5.4.7"), BER_BVC("l") },
+       { BER_BVC("2.5.4.8"), BER_BVC("st") },
+       { BER_BVC("2.5.4.10"), BER_BVC("o") },
+       { BER_BVC("2.5.4.11"), BER_BVC("ou") },
+       { BER_BVC("2.5.4.12"), BER_BVC("title") },
+       { BER_BVC("2.5.4.41"), BER_BVC("name") },
+       { BER_BVC("2.5.4.42"), BER_BVC("givenName") },
+       { BER_BVC("2.5.4.43"), BER_BVC("initials") },
+       { BER_BVC("2.5.4.44"), BER_BVC("generationQualifier") },
+       { BER_BVC("2.5.4.46"), BER_BVC("dnQualifier") },
+       { BER_BVC("1.2.840.113549.1.9.1"), BER_BVC("email") },
+       { BER_BVC("0.9.2342.19200300.100.1.25"), BER_BVC("dc") },
+       { BER_BVNULL, BER_BVNULL }
+};
+
+#ifdef HAVE_TLS
+#ifdef HAVE_GNUTLS
+
+typedef struct tls_cipher_suite {
+       const char *name;
+       gnutls_kx_algorithm_t kx;
+       gnutls_cipher_algorithm_t cipher;
+       gnutls_mac_algorithm_t mac;
+       gnutls_protocol_t version;
+} tls_cipher_suite;
+
+static tls_cipher_suite *ciphers;
+static int n_ciphers;
+
+/* sorta replacing SSL_CTX */
+typedef struct tls_ctx {
+       struct ldapoptions *lo;
+       gnutls_certificate_credentials_t cred;
+       gnutls_dh_params_t dh_params;
+       unsigned long verify_depth;
+       int refcount;
+       int *kx_list;
+       int *cipher_list;
+       int *mac_list;
+#ifdef LDAP_R_COMPILE
+       ldap_pvt_thread_mutex_t ref_mutex;
+#endif
+} tls_ctx;
+
+/* sorta replacing SSL */
+typedef struct tls_session {
+       tls_ctx *ctx;
+       gnutls_session_t session;
+       struct berval peer_der_dn;
+} tls_session;
+
+#ifdef LDAP_R_COMPILE
+
+static int
+ldap_pvt_gcry_mutex_init( void **priv )
+{
+       int err = 0;
+       ldap_pvt_thread_mutex_t *lock = LDAP_MALLOC( sizeof( ldap_pvt_thread_mutex_t ));
+
+       if ( !lock )
+               err = ENOMEM;
+       if ( !err ) {
+               err = ldap_pvt_thread_mutex_init( lock );
+               if ( err )
+                       LDAP_FREE( lock );
+               else
+                       *priv = lock;
+       }
+       return err;
+}
+static int
+ldap_pvt_gcry_mutex_destroy( void **lock )
+{
+       int err = ldap_pvt_thread_mutex_destroy( *lock );
+       LDAP_FREE( *lock );
+       return err;
+}
+static int
+ldap_pvt_gcry_mutex_lock( void **lock )
+{
+       return ldap_pvt_thread_mutex_lock( *lock );
+}
+static int
+ldap_pvt_gcry_mutex_unlock( void **lock )
+{
+       return ldap_pvt_thread_mutex_unlock( *lock );
+}
+
+static struct gcry_thread_cbs ldap_generic_thread_cbs = {
+       GCRY_THREAD_OPTION_USER,
+       NULL,
+       ldap_pvt_gcry_mutex_init,
+       ldap_pvt_gcry_mutex_destroy,
+       ldap_pvt_gcry_mutex_lock,
+       ldap_pvt_gcry_mutex_unlock,
+       NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+static void
+tls_init_threads( void )
+{
+       gcry_control (GCRYCTL_SET_THREAD_CBS, &ldap_generic_thread_cbs);
+}
+#endif /* LDAP_R_COMPILE */
+
+void
+ldap_pvt_tls_ctx_free ( void *c )
+{
+       int refcount;
+       tls_ctx *ctx = c;
+
+       if ( !ctx ) return;
+
+#ifdef LDAP_R_COMPILE
+       ldap_pvt_thread_mutex_lock( &ctx->ref_mutex );
+#endif
+       refcount = --ctx->refcount;
+#ifdef LDAP_R_COMPILE
+       ldap_pvt_thread_mutex_unlock( &ctx->ref_mutex );
+#endif
+       if ( refcount )
+               return;
+       LDAP_FREE( ctx->kx_list );
+       gnutls_certificate_free_credentials( ctx->cred );
+       ber_memfree ( ctx );
+}
+
+static void *
+tls_ctx_new ( struct ldapoptions *lo )
+{
+       tls_ctx *ctx;
+
+       ctx = ber_memcalloc ( 1, sizeof (*ctx) );
+       if ( ctx ) {
+               ctx->lo = lo;
+               if ( gnutls_certificate_allocate_credentials( &ctx->cred )) {
+                       ber_memfree( ctx );
+                       return NULL;
+               }
+               ctx->refcount = 1;
+#ifdef LDAP_R_COMPILE
+               ldap_pvt_thread_mutex_init( &ctx->ref_mutex );
+#endif
+       }
+       return ctx;
+}
+
+static void
+tls_ctx_ref( tls_ctx *ctx )
+{
+#ifdef LDAP_R_COMPILE
+       ldap_pvt_thread_mutex_lock( &ctx->ref_mutex );
+#endif
+       ctx->refcount++;
+#ifdef LDAP_R_COMPILE
+       ldap_pvt_thread_mutex_unlock( &ctx->ref_mutex );
+#endif
+}
+
+tls_session *
+tls_session_new ( tls_ctx * ctx, int is_server )
+{
+       tls_session *session;
+
+       session = ber_memcalloc ( 1, sizeof (*session) );
+       if ( !session )
+               return NULL;
+
+       session->ctx = ctx;
+       gnutls_init( &session->session, is_server ? GNUTLS_SERVER : GNUTLS_CLIENT );
+       gnutls_set_default_priority( session->session );
+       if ( ctx->kx_list ) {
+               gnutls_kx_set_priority( session->session, ctx->kx_list );
+               gnutls_cipher_set_priority( session->session, ctx->cipher_list );
+               gnutls_mac_set_priority( session->session, ctx->mac_list );
+       }
+       if ( ctx->cred )
+               gnutls_credentials_set( session->session, GNUTLS_CRD_CERTIFICATE, ctx->cred );
+       
+       if ( is_server ) {
+               int flag = 0;
+               if ( ctx->lo->ldo_tls_require_cert ) {
+                       flag = GNUTLS_CERT_REQUEST;
+                       if ( ctx->lo->ldo_tls_require_cert == LDAP_OPT_X_TLS_DEMAND ||
+                               ctx->lo->ldo_tls_require_cert == LDAP_OPT_X_TLS_HARD )
+                               flag = GNUTLS_CERT_REQUIRE;
+                       gnutls_certificate_server_set_request( session->session, flag );
+               }
+       }
+       return session;
+} 
+
+void
+tls_session_free ( tls_session * session )
+{
+       ber_memfree ( session );
+}
+
+#define        tls_session_connect( ssl )      gnutls_handshake( ssl->session )
+#define        tls_session_accept( ssl )       gnutls_handshake( ssl->session )
+
+/* suites is a string of colon-separated cipher suite names. */
+static int
+tls_parse_ciphers( tls_ctx *ctx, char *suites )
+{
+       char *ptr, *end;
+       int i, j, len, num;
+       int *list, nkx = 0, ncipher = 0, nmac = 0;
+       int *kx, *cipher, *mac;
+
+       num = 0;
+       ptr = suites;
+       do {
+               end = strchr(ptr, ':');
+               if ( end )
+                       len = end - ptr;
+               else
+                       len = strlen(ptr);
+               for (i=0; i<n_ciphers; i++) {
+                       if ( !strncasecmp( ciphers[i].name, ptr, len )) {
+                               num++;
+                               break;
+                       }
+               }
+               if ( i == n_ciphers ) {
+                       /* unrecognized cipher suite */
+                       return -1;
+               }
+       } while (end);
+
+       /* Space for all 3 lists */
+       list = LDAP_MALLOC( (num+1) * sizeof(int) * 3 );
+       if ( !list )
+               return -1;
+       kx = list;
+       cipher = kx+num+1;
+       mac = cipher+num+1;
+
+       ptr = suites;
+       do {
+               end = strchr(ptr, ':');
+               if ( end )
+                       len = end - ptr;
+               else
+                       len = strlen(ptr);
+               for (i=0; i<n_ciphers; i++) {
+                       /* For each cipher suite, insert its algorithms into
+                        * their respective priority lists. Make sure they
+                        * only appear once in each list.
+                        */
+                       if ( !strncasecmp( ciphers[i].name, ptr, len )) {
+                               for (j=0; j<nkx; j++)
+                                       if ( kx[j] == ciphers[i].kx )
+                                               break;
+                               if ( j == nkx )
+                                       kx[nkx++] = ciphers[i].kx;
+                               for (j=0; j<ncipher; j++)
+                                       if ( cipher[j] == ciphers[i].cipher )
+                                               break;
+                               if ( j == ncipher ) 
+                                       cipher[ncipher++] = ciphers[i].cipher;
+                               for (j=0; j<nmac; j++)
+                                       if ( mac[j] == ciphers[i].mac )
+                                               break;
+                               if ( j == nmac )
+                                       mac[nmac++] = ciphers[i].mac;
+                               break;
+                       }
+               }
+       } while (end);
+       kx[nkx] = 0;
+       cipher[ncipher] = 0;
+       mac[nmac] = 0;
+       ctx->kx_list = kx;
+       ctx->cipher_list = cipher;
+       ctx->mac_list = mac;
+       return 0;
+}
+
+#else /* OpenSSL */
+
+typedef SSL_CTX tls_ctx;
+typedef SSL tls_session;
+
+static int  tls_opt_trace = 1;
+static char *tls_opt_randfile = NULL;
+
 static void tls_report_error( void );
 
 static void tls_info_cb( const SSL *ssl, int where, int ret );
 static int tls_verify_cb( int ok, X509_STORE_CTX *ctx );
 static int tls_verify_ok( int ok, X509_STORE_CTX *ctx );
 static RSA * tls_tmp_rsa_cb( SSL *ssl, int is_export, int key_length );
-static STACK_OF(X509_NAME) * get_ca_list( char * bundle, char * dir );
 
 static DH * tls_tmp_dh_cb( SSL *ssl, int is_export, int key_length );
 
@@ -88,12 +400,18 @@ static void tls_locking_cb( int mode, int type, const char *file, int line )
        }
 }
 
-/*
- * an extra mutex for the default ctx.
- */
+static unsigned long tls_thread_self( void )
+{
+       /* FIXME: CRYPTO_set_id_callback only works when ldap_pvt_thread_t
+        * is an integral type that fits in an unsigned long
+        */
 
-static ldap_pvt_thread_mutex_t tls_def_ctx_mutex;
-static ldap_pvt_thread_mutex_t tls_connect_mutex;
+       /* force an error if the ldap_pvt_thread_t type is too large */
+       enum { ok = sizeof( ldap_pvt_thread_t ) <= sizeof( unsigned long ) };
+       typedef struct { int dummy: ok ? 1 : -1; } Check[ok ? 1 : -1];
+
+       return (unsigned long) ldap_pvt_thread_self();
+}
 
 static void tls_init_threads( void )
 {
@@ -103,21 +421,79 @@ static void tls_init_threads( void )
                ldap_pvt_thread_mutex_init( &tls_mutexes[i] );
        }
        CRYPTO_set_locking_callback( tls_locking_cb );
-       CRYPTO_set_id_callback( ldap_pvt_thread_self );
-       /* FIXME: CRYPTO_set_id_callback only works when ldap_pvt_thread_t
-        * is an integral type that fits in an unsigned long
-        */
-
-       ldap_pvt_thread_mutex_init( &tls_def_ctx_mutex );
-       ldap_pvt_thread_mutex_init( &tls_connect_mutex );
+       CRYPTO_set_id_callback( tls_thread_self );
 }
 #endif /* LDAP_R_COMPILE */
 
+void
+ldap_pvt_tls_ctx_free ( void *c )
+{
+
+       SSL_CTX_free( c );
+}
+
+static void *
+tls_ctx_new( struct ldapoptions *lo )
+{
+       return SSL_CTX_new( SSLv23_method() );
+}
+
+static void
+tls_ctx_ref( void *c )
+{
+       SSL_CTX *ctx = c;
+       CRYPTO_add( &ctx->references, 1, CRYPTO_LOCK_SSL_CTX );
+}
+
+static tls_session *
+tls_session_new( tls_ctx *ctx, int is_server )
+{
+       return SSL_new( ctx );
+}
+
+#define        tls_session_connect( ssl )      SSL_connect( ssl )
+#define        tls_session_accept( ssl )       SSL_accept( ssl )
+
+static STACK_OF(X509_NAME) *
+get_ca_list( char * bundle, char * dir )
+{
+       STACK_OF(X509_NAME) *ca_list = NULL;
+
+       if ( bundle ) {
+               ca_list = SSL_load_client_CA_file( bundle );
+       }
+#if defined(HAVE_DIRENT_H) || defined(dirent)
+       if ( dir ) {
+               int freeit = 0;
+
+               if ( !ca_list ) {
+                       ca_list = sk_X509_NAME_new_null();
+                       freeit = 1;
+               }
+               if ( !SSL_add_dir_cert_subjects_to_stack( ca_list, dir ) &&
+                       freeit ) {
+                       sk_X509_NAME_free( ca_list );
+                       ca_list = NULL;
+               }
+       }
+#endif
+       return ca_list;
+}
+
+#endif /* HAVE_GNUTLS */
+
+#ifdef LDAP_R_COMPILE
+/*
+ * an extra mutex for the default ctx.
+ */
+static ldap_pvt_thread_mutex_t tls_def_ctx_mutex;
+#endif
+
 void
 ldap_int_tls_destroy( struct ldapoptions *lo )
 {
        if ( lo->ldo_tls_ctx ) {
-               SSL_CTX_free( lo->ldo_tls_ctx );
+               ldap_pvt_tls_ctx_free( lo->ldo_tls_ctx );
                lo->ldo_tls_ctx = NULL;
        }
 
@@ -145,6 +521,12 @@ ldap_int_tls_destroy( struct ldapoptions *lo )
                LDAP_FREE( lo->ldo_tls_ciphersuite );
                lo->ldo_tls_ciphersuite = NULL;
        }
+#ifdef HAVE_GNUTLS
+       if ( lo->ldo_tls_crlfile ) {
+               LDAP_FREE( lo->ldo_tls_crlfile );
+               lo->ldo_tls_crlfile = NULL;
+       }
+#endif
 }
 
 /*
@@ -157,6 +539,12 @@ ldap_pvt_tls_destroy( void )
 
        ldap_int_tls_destroy( lo );
 
+#ifdef HAVE_GNUTLS
+       LDAP_FREE( ciphers );
+       ciphers = NULL;
+
+       gnutls_global_deinit();
+#else
        EVP_cleanup();
        ERR_remove_state(0);
        ERR_free_strings();
@@ -165,6 +553,7 @@ ldap_pvt_tls_destroy( void )
                LDAP_FREE( tls_opt_randfile );
                tls_opt_randfile = NULL;
        }
+#endif
 }
 
 /*
@@ -177,6 +566,43 @@ ldap_pvt_tls_init( void )
 
        if ( tls_initialized++ ) return 0;
 
+#ifdef LDAP_R_COMPILE
+       tls_init_threads();
+       ldap_pvt_thread_mutex_init( &tls_def_ctx_mutex );
+#endif
+
+#ifdef HAVE_GNUTLS
+       gnutls_global_init ();
+
+       /* GNUtls cipher suite handling: The library ought to parse suite
+        * names for us, but it doesn't. It will return a list of suite names
+        * that it supports, so we can do parsing ourselves. It ought to tell
+        * us how long the list is, but it doesn't do that either, so we just
+        * have to count it manually...
+        */
+       {
+               int i = 0;
+               tls_cipher_suite *ptr, tmp;
+               char cs_id[2];
+
+               while ( gnutls_cipher_suite_info( i, cs_id, &tmp.kx, &tmp.cipher,
+                       &tmp.mac, &tmp.version ))
+                       i++;
+               n_ciphers = i;
+
+               /* Store a copy */
+               ciphers = LDAP_MALLOC(n_ciphers * sizeof(tls_cipher_suite));
+               if ( !ciphers )
+                       return -1;
+               for ( i=0; i<n_ciphers; i++ ) {
+                       ciphers[i].name = gnutls_cipher_suite_info( i, cs_id,
+                               &ciphers[i].kx, &ciphers[i].cipher, &ciphers[i].mac,
+                               &ciphers[i].version );
+               }
+       }
+
+#else /* !HAVE_GNUTLS */
+
 #ifdef HAVE_EBCDIC
        {
                char *file = LDAP_STRDUP( tls_opt_randfile );
@@ -188,15 +614,13 @@ ldap_pvt_tls_init( void )
        (void) tls_seed_PRNG( tls_opt_randfile );
 #endif
 
-#ifdef LDAP_R_COMPILE
-       tls_init_threads();
-#endif
-
        SSL_load_error_strings();
        SSLeay_add_ssl_algorithms();
 
        /* FIXME: mod_ssl does this */
        X509V3_add_standard_extensions();
+
+#endif /* HAVE_GNUTLS */
        return 0;
 }
 
@@ -206,14 +630,17 @@ ldap_pvt_tls_init( void )
 static int
 ldap_int_tls_init_ctx( struct ldapoptions *lo, int is_server )
 {
-       STACK_OF(X509_NAME) *calist;
        int i, rc = 0;
        char *ciphersuite = lo->ldo_tls_ciphersuite;
        char *cacertfile = lo->ldo_tls_cacertfile;
        char *cacertdir = lo->ldo_tls_cacertdir;
        char *certfile = lo->ldo_tls_certfile;
        char *keyfile = lo->ldo_tls_keyfile;
+#ifdef HAVE_GNUTLS
+       char *crlfile = lo->ldo_tls_crlfile;
+#else
        char *dhfile = lo->ldo_tls_dhfile;
+#endif
 
        if ( lo->ldo_tls_ctx )
                return 0;
@@ -235,10 +662,6 @@ ldap_int_tls_init_ctx( struct ldapoptions *lo, int is_server )
                cacertfile = LDAP_STRDUP( cacertfile );
                __atoe( cacertfile );
        }
-       if ( cacertdir ) {
-               cacertdir = LDAP_STRDUP( cacertdir );
-               __atoe( cacertdir );
-       }
        if ( certfile ) {
                certfile = LDAP_STRDUP( certfile );
                __atoe( certfile );
@@ -247,20 +670,100 @@ ldap_int_tls_init_ctx( struct ldapoptions *lo, int is_server )
                keyfile = LDAP_STRDUP( keyfile );
                __atoe( keyfile );
        }
+#ifdef HAVE_GNUTLS
+       if ( crlfile ) {
+               crlfile = LDAP_STRDUP( crlfile );
+               __atoe( crlfile );
+       }
+#else
+       if ( cacertdir ) {
+               cacertdir = LDAP_STRDUP( cacertdir );
+               __atoe( cacertdir );
+       }
        if ( dhfile ) {
                dhfile = LDAP_STRDUP( dhfile );
                __atoe( dhfile );
        }
 #endif
-       lo->ldo_tls_ctx = SSL_CTX_new( SSLv23_method() );
+#endif
+       lo->ldo_tls_ctx = tls_ctx_new( lo );
        if ( lo->ldo_tls_ctx == NULL ) {
+#ifdef HAVE_GNUTLS
+               Debug( LDAP_DEBUG_ANY,
+                  "TLS: could not allocate default ctx.\n",
+                       0,0,0);
+#else
                Debug( LDAP_DEBUG_ANY,
                   "TLS: could not allocate default ctx (%lu).\n",
                        ERR_peek_error(),0,0);
+#endif
                rc = -1;
                goto error_exit;
        }
 
+#ifdef HAVE_GNUTLS
+       if ( lo->ldo_tls_ciphersuite &&
+               tls_parse_ciphers( lo->ldo_tls_ctx,
+                       ciphersuite )) {
+               Debug( LDAP_DEBUG_ANY,
+                          "TLS: could not set cipher list %s.\n",
+                          lo->ldo_tls_ciphersuite, 0, 0 );
+               rc = -1;
+               goto error_exit;
+       }
+
+       if (lo->ldo_tls_cacertdir != NULL) {
+               Debug( LDAP_DEBUG_ANY, 
+                      "TLS: warning: cacertdir not implemented for gnutls\n",
+                      NULL, NULL, NULL );
+       }
+
+       if (lo->ldo_tls_cacertfile != NULL) {
+               rc = gnutls_certificate_set_x509_trust_file( 
+                       ((tls_ctx*) lo->ldo_tls_ctx)->cred,
+                       cacertfile,
+                       GNUTLS_X509_FMT_PEM );
+               if ( rc < 0 ) goto error_exit;
+       }
+
+       if ( lo->ldo_tls_certfile && lo->ldo_tls_keyfile ) {
+               rc = gnutls_certificate_set_x509_key_file( 
+                       ((tls_ctx*) lo->ldo_tls_ctx)->cred,
+                       certfile,
+                       keyfile,
+                       GNUTLS_X509_FMT_PEM );
+               if ( rc ) goto error_exit;
+       } else if ( lo->ldo_tls_certfile || lo->ldo_tls_keyfile ) {
+               Debug( LDAP_DEBUG_ANY, 
+                      "TLS: only one of certfile and keyfile specified\n",
+                      NULL, NULL, NULL );
+               rc = 1;
+               goto error_exit;
+       }
+
+       if ( lo->ldo_tls_dhfile ) {
+               Debug( LDAP_DEBUG_ANY, 
+                      "TLS: warning: ignoring dhfile\n", 
+                      NULL, NULL, NULL );
+       }
+
+       if ( lo->ldo_tls_crlfile ) {
+               rc = gnutls_certificate_set_x509_crl_file( 
+                       ((tls_ctx*) lo->ldo_tls_ctx)->cred,
+                       crlfile,
+                       GNUTLS_X509_FMT_PEM );
+               if ( rc < 0 ) goto error_exit;
+       }
+       if ( is_server ) {
+               gnutls_dh_params_init (&((tls_ctx*) 
+                                       lo->ldo_tls_ctx)->dh_params);
+               gnutls_dh_params_generate2 (((tls_ctx*) 
+                                                lo->ldo_tls_ctx)->dh_params, 
+                                               DH_BITS);
+       }
+
+#else /* !HAVE_GNUTLS */
+
        if ( is_server ) {
                SSL_CTX_set_session_id_context( lo->ldo_tls_ctx,
                        (const unsigned char *) "OpenLDAP", sizeof("OpenLDAP")-1 );
@@ -293,6 +796,7 @@ ldap_int_tls_init_ctx( struct ldapoptions *lo, int is_server )
                }
 
                if ( is_server ) {
+                       STACK_OF(X509_NAME) *calist;
                        /* List of CA names to send to a client */
                        calist = get_ca_list( cacertfile, cacertdir );
                        if ( !calist ) {
@@ -392,18 +896,24 @@ ldap_int_tls_init_ctx( struct ldapoptions *lo, int is_server )
        }
 #endif
 
+#endif /* HAVE_GNUTLS */
+
 error_exit:
        if ( rc == -1 && lo->ldo_tls_ctx != NULL ) {
-               SSL_CTX_free( lo->ldo_tls_ctx );
+               ldap_pvt_tls_ctx_free( lo->ldo_tls_ctx );
                lo->ldo_tls_ctx = NULL;
        }
 #ifdef HAVE_EBCDIC
        LDAP_FREE( ciphersuite );
        LDAP_FREE( cacertfile );
-       LDAP_FREE( cacertdir );
        LDAP_FREE( certfile );
        LDAP_FREE( keyfile );
+#ifdef HAVE_GNUTLS
+       LDAP_FREE( crlfile );
+#else
+       LDAP_FREE( cacertdir );
        LDAP_FREE( dhfile );
+#endif
 #endif
        return rc;
 }
@@ -426,47 +936,21 @@ ldap_pvt_tls_init_def_ctx( int is_server )
        return rc;
 }
 
-static STACK_OF(X509_NAME) *
-get_ca_list( char * bundle, char * dir )
-{
-       STACK_OF(X509_NAME) *ca_list = NULL;
-
-       if ( bundle ) {
-               ca_list = SSL_load_client_CA_file( bundle );
-       }
-#if defined(HAVE_DIRENT_H) || defined(dirent)
-       if ( dir ) {
-               int freeit = 0;
-
-               if ( !ca_list ) {
-                       ca_list = sk_X509_NAME_new_null();
-                       freeit = 1;
-               }
-               if ( !SSL_add_dir_cert_subjects_to_stack( ca_list, dir ) &&
-                       freeit ) {
-                       sk_X509_NAME_free( ca_list );
-                       ca_list = NULL;
-               }
-       }
-#endif
-       return ca_list;
-}
-
-static SSL *
+static tls_session *
 alloc_handle( void *ctx_arg, int is_server )
 {
-       SSL_CTX *ctx;
-       SSL     *ssl;
+       tls_ctx *ctx;
+       tls_session     *ssl;
 
        if ( ctx_arg ) {
-               ctx = (SSL_CTX *) ctx_arg;
+               ctx = ctx_arg;
        } else {
                struct ldapoptions *lo = LDAP_INT_GLOBAL_OPT();   
                if ( ldap_pvt_tls_init_def_ctx( is_server ) < 0 ) return NULL;
                ctx = lo->ldo_tls_ctx;
        }
 
-       ssl = SSL_new( ctx );
+       ssl = tls_session_new( ctx, is_server );
        if ( ssl == NULL ) {
                Debug( LDAP_DEBUG_ANY,"TLS: can't create ssl handle.\n",0,0,0);
                return NULL;
@@ -475,24 +959,37 @@ alloc_handle( void *ctx_arg, int is_server )
 }
 
 static int
-update_flags( Sockbuf *sb, SSL * ssl, int rc )
+update_flags( Sockbuf *sb, tls_session * ssl, int rc )
 {
-       int err = SSL_get_error(ssl, rc);
-
        sb->sb_trans_needs_read  = 0;
        sb->sb_trans_needs_write = 0;
 
-       if (err == SSL_ERROR_WANT_READ) {
+#ifdef HAVE_GNUTLS
+       if ( rc != GNUTLS_E_INTERRUPTED && rc != GNUTLS_E_AGAIN )
+               return 0;
+
+       switch (gnutls_record_get_direction (ssl->session)) {
+       case 0: 
+               sb->sb_trans_needs_read = 1;
+               return 1;
+       case 1:
+               sb->sb_trans_needs_write = 1;
+               return 1;
+       }
+#else /* !HAVE_GNUTLS */
+       rc = SSL_get_error(ssl, rc);
+       if (rc == SSL_ERROR_WANT_READ) {
                sb->sb_trans_needs_read  = 1;
                return 1;
 
-       } else if (err == SSL_ERROR_WANT_WRITE) {
+       } else if (rc == SSL_ERROR_WANT_WRITE) {
                sb->sb_trans_needs_write = 1;
                return 1;
 
-       } else if (err == SSL_ERROR_WANT_CONNECT) {
+       } else if (rc == SSL_ERROR_WANT_CONNECT) {
                return 1;
        }
+#endif /* HAVE_GNUTLS */
        return 0;
 }
 
@@ -501,17 +998,49 @@ update_flags( Sockbuf *sb, SSL * ssl, int rc )
  */
 
 struct tls_data {
-       SSL                     *ssl;
+       tls_session                     *ssl;
        Sockbuf_IO_Desc         *sbiod;
 };
 
-static BIO_METHOD sb_tls_bio_method;
+#ifdef HAVE_GNUTLS
+
+static ssize_t
+sb_gtls_recv( gnutls_transport_ptr_t ptr, void *buf, size_t len )
+{
+       struct tls_data         *p;
+
+       if ( buf == NULL || len <= 0 ) return 0;
+
+       p = (struct tls_data *)ptr;
+
+       if ( p == NULL || p->sbiod == NULL ) {
+               return 0;
+       }
+
+       return LBER_SBIOD_READ_NEXT( p->sbiod, buf, len );
+}
+
+static ssize_t
+sb_gtls_send( gnutls_transport_ptr_t ptr, const void *buf, size_t len )
+{
+       struct tls_data         *p;
+       
+       if ( buf == NULL || len <= 0 ) return 0;
+       
+       p = (struct tls_data *)ptr;
+
+       if ( p == NULL || p->sbiod == NULL ) {
+               return 0;
+       }
+
+       return LBER_SBIOD_WRITE_NEXT( p->sbiod, (char *)buf, len );
+}
 
 static int
 sb_tls_setup( Sockbuf_IO_Desc *sbiod, void *arg )
 {
        struct tls_data         *p;
-       BIO                     *bio;
+       tls_session     *session = arg;
 
        assert( sbiod != NULL );
 
@@ -520,11 +1049,11 @@ sb_tls_setup( Sockbuf_IO_Desc *sbiod, void *arg )
                return -1;
        }
        
-       p->ssl = (SSL *)arg;
+       gnutls_transport_set_ptr( session->session, (gnutls_transport_ptr)p );
+       gnutls_transport_set_pull_function( session->session, sb_gtls_recv );
+       gnutls_transport_set_push_function( session->session, sb_gtls_send );
+       p->ssl = arg;
        p->sbiod = sbiod;
-       bio = BIO_new( &sb_tls_bio_method );
-       bio->ptr = (void *)p;
-       SSL_set_bio( p->ssl, bio, bio );
        sbiod->sbiod_pvt = p;
        return 0;
 }
@@ -538,7 +1067,8 @@ sb_tls_remove( Sockbuf_IO_Desc *sbiod )
        assert( sbiod->sbiod_pvt != NULL );
 
        p = (struct tls_data *)sbiod->sbiod_pvt;
-       SSL_free( p->ssl );
+       gnutls_deinit ( p->ssl->session );
+       LBER_FREE( p->ssl );
        LBER_FREE( sbiod->sbiod_pvt );
        sbiod->sbiod_pvt = NULL;
        return 0;
@@ -553,7 +1083,7 @@ sb_tls_close( Sockbuf_IO_Desc *sbiod )
        assert( sbiod->sbiod_pvt != NULL );
 
        p = (struct tls_data *)sbiod->sbiod_pvt;
-       SSL_shutdown( p->ssl );
+       gnutls_bye ( p->ssl->session, GNUTLS_SHUT_RDWR );
        return 0;
 }
 
@@ -568,11 +1098,11 @@ sb_tls_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg )
        p = (struct tls_data *)sbiod->sbiod_pvt;
        
        if ( opt == LBER_SB_OPT_GET_SSL ) {
-               *((SSL **)arg) = p->ssl;
+               *((tls_session **)arg) = p->ssl;
                return 1;
-
+               
        } else if ( opt == LBER_SB_OPT_DATA_READY ) {
-               if( SSL_pending( p->ssl ) > 0 ) {
+               if( gnutls_record_check_pending( p->ssl->session ) > 0 ) {
                        return 1;
                }
        }
@@ -592,17 +1122,24 @@ sb_tls_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len)
 
        p = (struct tls_data *)sbiod->sbiod_pvt;
 
-       ret = SSL_read( p->ssl, (char *)buf, len );
-#ifdef HAVE_WINSOCK
-       errno = WSAGetLastError();
-#endif
-       err = SSL_get_error( p->ssl, ret );
-       if (err == SSL_ERROR_WANT_READ ) {
+       ret = gnutls_record_recv ( p->ssl->session, buf, len );
+       switch (ret) {
+       case GNUTLS_E_INTERRUPTED:
+       case GNUTLS_E_AGAIN:
                sbiod->sbiod_sb->sb_trans_needs_read = 1;
                sock_errset(EWOULDBLOCK);
-       }
-       else
+               ret = 0;
+               break;
+       case GNUTLS_E_REHANDSHAKE:
+               for ( ret = gnutls_handshake ( p->ssl->session );
+                     ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN;
+                     ret = gnutls_handshake ( p->ssl->session ) );
+               sbiod->sbiod_sb->sb_trans_needs_read = 1;
+               ret = 0;
+               break;
+       default:
                sbiod->sbiod_sb->sb_trans_needs_read = 0;
+       }
        return ret;
 }
 
@@ -618,30 +1155,19 @@ sb_tls_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len)
 
        p = (struct tls_data *)sbiod->sbiod_pvt;
 
-       ret = SSL_write( p->ssl, (char *)buf, len );
-#ifdef HAVE_WINSOCK
-       errno = WSAGetLastError();
-#endif
-       err = SSL_get_error( p->ssl, ret );
-       if (err == SSL_ERROR_WANT_WRITE ) {
+       ret = gnutls_record_send ( p->ssl->session, (char *)buf, len );
+
+       if ( ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN ) {
                sbiod->sbiod_sb->sb_trans_needs_write = 1;
                sock_errset(EWOULDBLOCK);
-
+               ret = 0;
        } else {
                sbiod->sbiod_sb->sb_trans_needs_write = 0;
        }
        return ret;
 }
 
-static Sockbuf_IO sb_tls_sbio =
-{
-       sb_tls_setup,           /* sbi_setup */
-       sb_tls_remove,          /* sbi_remove */
-       sb_tls_ctrl,            /* sbi_ctrl */
-       sb_tls_read,            /* sbi_read */
-       sb_tls_write,           /* sbi_write */
-       sb_tls_close            /* sbi_close */
-};
+#else /* !HAVE_GNUTLS */
 
 static int
 sb_tls_bio_create( BIO *b ) {
@@ -734,23 +1260,195 @@ sb_tls_bio_gets( BIO *b, char *buf, int len )
 }
 
 static int
-sb_tls_bio_puts( BIO *b, const char *str )
+sb_tls_bio_puts( BIO *b, const char *str )
+{
+       return sb_tls_bio_write( b, str, strlen( str ) );
+}
+       
+static BIO_METHOD sb_tls_bio_method =
+{
+       ( 100 | 0x400 ),                /* it's a source/sink BIO */
+       "sockbuf glue",
+       sb_tls_bio_write,
+       sb_tls_bio_read,
+       sb_tls_bio_puts,
+       sb_tls_bio_gets,
+       sb_tls_bio_ctrl,
+       sb_tls_bio_create,
+       sb_tls_bio_destroy
+};
+
+static int
+sb_tls_setup( Sockbuf_IO_Desc *sbiod, void *arg )
+{
+       struct tls_data         *p;
+       BIO                     *bio;
+
+       assert( sbiod != NULL );
+
+       p = LBER_MALLOC( sizeof( *p ) );
+       if ( p == NULL ) {
+               return -1;
+       }
+       
+       p->ssl = (SSL *)arg;
+       p->sbiod = sbiod;
+       bio = BIO_new( &sb_tls_bio_method );
+       bio->ptr = (void *)p;
+       SSL_set_bio( p->ssl, bio, bio );
+       sbiod->sbiod_pvt = p;
+       return 0;
+}
+
+static int
+sb_tls_remove( Sockbuf_IO_Desc *sbiod )
+{
+       struct tls_data         *p;
+       
+       assert( sbiod != NULL );
+       assert( sbiod->sbiod_pvt != NULL );
+
+       p = (struct tls_data *)sbiod->sbiod_pvt;
+       SSL_free( p->ssl );
+       LBER_FREE( sbiod->sbiod_pvt );
+       sbiod->sbiod_pvt = NULL;
+       return 0;
+}
+
+static int
+sb_tls_close( Sockbuf_IO_Desc *sbiod )
+{
+       struct tls_data         *p;
+       
+       assert( sbiod != NULL );
+       assert( sbiod->sbiod_pvt != NULL );
+
+       p = (struct tls_data *)sbiod->sbiod_pvt;
+       SSL_shutdown( p->ssl );
+       return 0;
+}
+
+static int
+sb_tls_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg )
+{
+       struct tls_data         *p;
+       
+       assert( sbiod != NULL );
+       assert( sbiod->sbiod_pvt != NULL );
+
+       p = (struct tls_data *)sbiod->sbiod_pvt;
+       
+       if ( opt == LBER_SB_OPT_GET_SSL ) {
+               *((SSL **)arg) = p->ssl;
+               return 1;
+
+       } else if ( opt == LBER_SB_OPT_DATA_READY ) {
+               if( SSL_pending( p->ssl ) > 0 ) {
+                       return 1;
+               }
+       }
+       
+       return LBER_SBIOD_CTRL_NEXT( sbiod, opt, arg );
+}
+
+static ber_slen_t
+sb_tls_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len)
+{
+       struct tls_data         *p;
+       ber_slen_t              ret;
+       int                     err;
+
+       assert( sbiod != NULL );
+       assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
+
+       p = (struct tls_data *)sbiod->sbiod_pvt;
+
+       ret = SSL_read( p->ssl, (char *)buf, len );
+#ifdef HAVE_WINSOCK
+       errno = WSAGetLastError();
+#endif
+       err = SSL_get_error( p->ssl, ret );
+       if (err == SSL_ERROR_WANT_READ ) {
+               sbiod->sbiod_sb->sb_trans_needs_read = 1;
+               sock_errset(EWOULDBLOCK);
+       }
+       else
+               sbiod->sbiod_sb->sb_trans_needs_read = 0;
+       return ret;
+}
+
+static ber_slen_t
+sb_tls_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len)
+{
+       struct tls_data         *p;
+       ber_slen_t              ret;
+       int                     err;
+
+       assert( sbiod != NULL );
+       assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
+
+       p = (struct tls_data *)sbiod->sbiod_pvt;
+
+       ret = SSL_write( p->ssl, (char *)buf, len );
+#ifdef HAVE_WINSOCK
+       errno = WSAGetLastError();
+#endif
+       err = SSL_get_error( p->ssl, ret );
+       if (err == SSL_ERROR_WANT_WRITE ) {
+               sbiod->sbiod_sb->sb_trans_needs_write = 1;
+               sock_errset(EWOULDBLOCK);
+
+       } else {
+               sbiod->sbiod_sb->sb_trans_needs_write = 0;
+       }
+       return ret;
+}
+
+#endif
+
+static Sockbuf_IO sb_tls_sbio =
+{
+       sb_tls_setup,           /* sbi_setup */
+       sb_tls_remove,          /* sbi_remove */
+       sb_tls_ctrl,            /* sbi_ctrl */
+       sb_tls_read,            /* sbi_read */
+       sb_tls_write,           /* sbi_write */
+       sb_tls_close            /* sbi_close */
+};
+
+#ifdef HAVE_GNUTLS
+/* Certs are not automatically varified during the handshake */
+static int
+tls_cert_verify( tls_session *ssl )
 {
-       return sb_tls_bio_write( b, str, strlen( str ) );
+       unsigned int status = 0;
+       int err;
+       time_t now = time(0);
+
+       err = gnutls_certificate_verify_peers2( ssl->session, &status );
+       if ( err < 0 ) {
+               Debug( LDAP_DEBUG_ANY,"TLS: gnutls_certificate_verify_peers2 failed %d\n",
+                       err,0,0 );
+               return -1;
+       }
+       if ( status ) {
+               Debug( LDAP_DEBUG_TRACE,"TLS: peer cert untrusted or revoked (0x%x)\n",
+                       status, 0,0 );
+               return -1;
+       }
+       if ( gnutls_certificate_expiration_time_peers( ssl->session ) < now ) {
+               Debug( LDAP_DEBUG_ANY, "TLS: peer certificate is expired\n",
+                       0, 0, 0 );
+               return -1;
+       }
+       if ( gnutls_certificate_activation_time_peers( ssl->session ) > now ) {
+               Debug( LDAP_DEBUG_ANY, "TLS: peer certificate not yet active\n",
+                       0, 0, 0 );
+               return -1;
+       }
+       return 0;
 }
-       
-static BIO_METHOD sb_tls_bio_method =
-{
-       ( 100 | 0x400 ),                /* it's a source/sink BIO */
-       "sockbuf glue",
-       sb_tls_bio_write,
-       sb_tls_bio_read,
-       sb_tls_bio_puts,
-       sb_tls_bio_gets,
-       sb_tls_bio_ctrl,
-       sb_tls_bio_create,
-       sb_tls_bio_destroy
-};
+#endif /* HAVE_GNUTLS */
 
 /*
  * Call this to do a TLS connect on a sockbuf. ctx_arg can be
@@ -770,14 +1468,14 @@ ldap_int_tls_connect( LDAP *ld, LDAPConn *conn )
 {
        Sockbuf *sb = conn->lconn_sb;
        int     err;
-       SSL     *ssl;
+       tls_session     *ssl;
 
        if ( HAS_TLS( sb ) ) {
                ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_SSL, (void *)&ssl );
 
        } else {
                struct ldapoptions *lo;
-               SSL_CTX *ctx;
+               tls_ctx *ctx;
 
                ctx = ld->ld_options.ldo_tls_ctx;
 
@@ -796,7 +1494,7 @@ ldap_int_tls_connect( LDAP *ld, LDAPConn *conn )
                if( ctx == NULL ) {
                        ctx = lo->ldo_tls_ctx;
                        ld->ld_options.ldo_tls_ctx = ctx;
-                       CRYPTO_add( &ctx->references, 1, CRYPTO_LOCK_SSL_CTX );
+                       tls_ctx_ref( ctx );
                }
                if ( ld->ld_options.ldo_tls_connect_cb )
                        ld->ld_options.ldo_tls_connect_cb( ld, ssl, ctx,
@@ -806,24 +1504,37 @@ ldap_int_tls_connect( LDAP *ld, LDAPConn *conn )
                        lo->ldo_tls_connect_cb( ld, ssl, ctx, lo->ldo_tls_connect_arg );
        }
 
-       err = SSL_connect( ssl );
+       err = tls_session_connect( ssl );
 
 #ifdef HAVE_WINSOCK
        errno = WSAGetLastError();
 #endif
 
-       if ( err <= 0 ) {
+#ifdef HAVE_GNUTLS
+       if ( err < 0 )
+#else
+       if ( err <= 0 )
+#endif
+       {
                if ( update_flags( sb, ssl, err )) {
                        return 1;
                }
 
-               if ((err = ERR_peek_error())) {
-                       char buf[256];
-
+#ifndef HAVE_GNUTLS
+               if ((err = ERR_peek_error()))
+#endif
+               {
                        if ( ld->ld_error ) {
                                LDAP_FREE( ld->ld_error );
                        }
-                       ld->ld_error = LDAP_STRDUP(ERR_error_string(err, buf));
+#ifdef HAVE_GNUTLS
+                       ld->ld_error = LDAP_STRDUP(gnutls_strerror( err ));
+#else
+                       {
+                               char buf[256];
+                               ld->ld_error = LDAP_STRDUP(ERR_error_string(err, buf));
+                       }
+#endif
 #ifdef HAVE_EBCDIC
                        if ( ld->ld_error ) __etoa(ld->ld_error);
 #endif
@@ -841,6 +1552,14 @@ ldap_int_tls_connect( LDAP *ld, LDAPConn *conn )
                return -1;
        }
 
+#ifdef HAVE_GNUTLS
+       if ( ld->ld_options.ldo_tls_require_cert != LDAP_OPT_X_TLS_NEVER ) {
+               err = tls_cert_verify( ssl );
+               if ( err && ld->ld_options.ldo_tls_require_cert != LDAP_OPT_X_TLS_ALLOW )
+                       return err;
+       }
+#endif
+
        return 0;
 }
 
@@ -852,7 +1571,7 @@ int
 ldap_pvt_tls_accept( Sockbuf *sb, void *ctx_arg )
 {
        int     err;
-       SSL     *ssl;
+       tls_session     *ssl;
 
        if ( HAS_TLS( sb ) ) {
                ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_SSL, (void *)&ssl );
@@ -869,23 +1588,27 @@ ldap_pvt_tls_accept( Sockbuf *sb, void *ctx_arg )
                        LBER_SBIOD_LEVEL_TRANSPORT, (void *)ssl );
        }
 
-#ifdef LDAP_R_COMPILE
-       ldap_pvt_thread_mutex_lock( &tls_connect_mutex );
-#endif
-       err = SSL_accept( ssl );
-#ifdef LDAP_R_COMPILE
-       ldap_pvt_thread_mutex_unlock( &tls_connect_mutex );
-#endif
+       err = tls_session_accept( ssl );
 
 #ifdef HAVE_WINSOCK
        errno = WSAGetLastError();
 #endif
-       if ( err <= 0 ) {
+
+#ifdef HAVE_GNUTLS
+       if ( err < 0 )
+#else
+       if ( err <= 0 )
+#endif
+       {
                if ( update_flags( sb, ssl, err )) return 1;
 
+#ifdef HAVE_GNUTLS
+               Debug( LDAP_DEBUG_ANY,"TLS: can't accept: %s.\n",
+                       gnutls_strerror( err ),0,0 );
+#else
                Debug( LDAP_DEBUG_ANY,"TLS: can't accept.\n",0,0,0 );
-
                tls_report_error();
+#endif
                ber_sockbuf_remove_io( sb, &sb_tls_sbio,
                        LBER_SBIOD_LEVEL_TRANSPORT );
 #ifdef LDAP_DEBUG
@@ -895,6 +1618,13 @@ ldap_pvt_tls_accept( Sockbuf *sb, void *ctx_arg )
                return -1;
        }
 
+#ifdef HAVE_GNUTLS
+       if ( ssl->ctx->lo->ldo_tls_require_cert != LDAP_OPT_X_TLS_NEVER ) {
+               err = tls_cert_verify( ssl );
+               if ( err && ssl->ctx->lo->ldo_tls_require_cert != LDAP_OPT_X_TLS_ALLOW )
+                       return err;
+       }
+#endif
        return 0;
 }
 
@@ -922,6 +1652,60 @@ ldap_tls_inplace( LDAP *ld )
        return ldap_pvt_tls_inplace( sb );
 }
 
+#ifdef HAVE_GNUTLS
+static void
+x509_cert_get_dn( struct berval *cert, struct berval *dn, int get_subject )
+{
+       BerElementBuffer berbuf;
+       BerElement *ber = (BerElement *)&berbuf;
+       ber_tag_t tag;
+       ber_len_t len;
+       ber_int_t i;
+
+       ber_init2( ber, cert, LBER_USE_DER );
+       tag = ber_skip_tag( ber, &len );        /* Sequence */
+       tag = ber_skip_tag( ber, &len );        /* Sequence */
+       tag = ber_skip_tag( ber, &len );        /* Context + Constructed (version) */
+       if ( tag == 0xa0 )      /* Version is optional */
+               tag = ber_get_int( ber, &i );   /* Int: Version */
+       tag = ber_get_int( ber, &i );   /* Int: Serial */
+       tag = ber_skip_tag( ber, &len );        /* Sequence: Signature */
+       ber_skip_data( ber, len );
+       if ( !get_subject ) {
+               tag = ber_peek_tag( ber, &len );        /* Sequence: Issuer DN */
+       } else {
+               tag = ber_skip_tag( ber, &len );
+               ber_skip_data( ber, len );
+               tag = ber_skip_tag( ber, &len );        /* Sequence: Validity */
+               ber_skip_data( ber, len );
+               tag = ber_peek_tag( ber, &len );        /* Sequence: Subject DN */
+       }
+       len = ber_ptrlen( ber );
+       dn->bv_val = cert->bv_val + len;
+       dn->bv_len = cert->bv_len - len;
+}
+
+static int
+tls_get_cert_dn( tls_session *session, struct berval *dnbv )
+{
+       if ( !session->peer_der_dn.bv_val ) {
+               const gnutls_datum_t *peer_cert_list;
+               int list_size;
+               struct berval bv;
+
+               peer_cert_list = gnutls_certificate_get_peers( session->session, 
+                                                       &list_size );
+               if ( !peer_cert_list ) return LDAP_INVALID_CREDENTIALS;
+
+               bv.bv_len = peer_cert_list->size;
+               bv.bv_val = peer_cert_list->data;
+
+               x509_cert_get_dn( &bv, &session->peer_der_dn, 1 );
+               *dnbv = session->peer_der_dn;
+       }
+       return 0;
+}
+#else /* !HAVE_GNUTLS */
 static X509 *
 tls_get_cert( SSL *s )
 {
@@ -936,52 +1720,207 @@ tls_get_cert( SSL *s )
        return SSL_get_peer_certificate(s);
 }
 
+static int
+tls_get_cert_dn( tls_session *session, struct berval *dnbv )
+{
+       X509_NAME *xn;
+       X509 *x = tls_get_cert( session );
+
+       if ( !x )
+               return LDAP_INVALID_CREDENTIALS;
+
+       xn = X509_get_subject_name(x);
+       dnbv->bv_len = i2d_X509_NAME( xn, NULL );
+       dnbv->bv_val = xn->bytes->data;
+       return 0;
+}
+#endif /* HAVE_GNUTLS */
+
 int
 ldap_pvt_tls_get_peer_dn( void *s, struct berval *dn,
        LDAPDN_rewrite_dummy *func, unsigned flags )
 {
-       X509 *x;
-       X509_NAME *xn;
+       tls_session *session = s;
+       struct berval bvdn;
        int rc;
 
-       x = tls_get_cert((SSL *)s);
+       rc = tls_get_cert_dn( session, &bvdn );
+       if ( rc ) return rc;
 
-       if (!x) return LDAP_INVALID_CREDENTIALS;
-       
-       xn = X509_get_subject_name(x);
-       rc = ldap_X509dn2bv(xn, dn, (LDAPDN_rewrite_func *)func, flags);
-       X509_free(x);
+       rc = ldap_X509dn2bv( &bvdn, dn, 
+                           (LDAPDN_rewrite_func *)func, flags);
        return rc;
 }
 
-char *
-ldap_pvt_tls_get_peer_hostname( void *s )
+/* what kind of hostname were we given? */
+#define        IS_DNS  0
+#define        IS_IP4  1
+#define        IS_IP6  2
+
+#ifdef HAVE_GNUTLS
+
+int
+ldap_pvt_tls_check_hostname( LDAP *ld, void *s, const char *name_in )
 {
-       X509 *x;
-       X509_NAME *xn;
-       char buf[2048], *p;
-       int ret;
+       tls_session *session = s;
+       int i, ret;
+       const gnutls_datum_t *peer_cert_list;
+       int list_size;
+       struct berval bv;
+       char altname[NI_MAXHOST];
+       size_t altnamesize;
+
+       gnutls_x509_crt_t cert;
+       gnutls_datum_t *x;
+       const char *name;
+       char *ptr;
+       char *domain = NULL;
+#ifdef LDAP_PF_INET6
+       struct in6_addr addr;
+#else
+       struct in_addr addr;
+#endif
+       int n, len1 = 0, len2 = 0;
+       int ntype = IS_DNS;
+       time_t now = time(0);
 
-       x = tls_get_cert((SSL *)s);
-       if (!x) return NULL;
+       if( ldap_int_hostname &&
+               ( !name_in || !strcasecmp( name_in, "localhost" ) ) )
+       {
+               name = ldap_int_hostname;
+       } else {
+               name = name_in;
+       }
+
+       peer_cert_list = gnutls_certificate_get_peers( session->session, 
+                                               &list_size );
+       if ( !peer_cert_list ) {
+               Debug( LDAP_DEBUG_ANY,
+                       "TLS: unable to get peer certificate.\n",
+                       0, 0, 0 );
+               /* If this was a fatal condition, things would have
+                * aborted long before now.
+                */
+               return LDAP_SUCCESS;
+       }
+       ret = gnutls_x509_crt_init( &cert );
+       if ( ret < 0 )
+               return LDAP_LOCAL_ERROR;
+       ret = gnutls_x509_crt_import( cert, peer_cert_list, GNUTLS_X509_FMT_DER );
+       if ( ret ) {
+               gnutls_x509_crt_deinit( cert );
+               return LDAP_LOCAL_ERROR;
+       }
+
+#ifdef LDAP_PF_INET6
+       if (name[0] == '[' && strchr(name, ']')) {
+               char *n2 = ldap_strdup(name+1);
+               *strchr(n2, ']') = 2;
+               if (inet_pton(AF_INET6, n2, &addr))
+                       ntype = IS_IP6;
+               LDAP_FREE(n2);
+       } else 
+#endif
+       if ((ptr = strrchr(name, '.')) && isdigit((unsigned char)ptr[1])) {
+               if (inet_aton(name, (struct in_addr *)&addr)) ntype = IS_IP4;
+       }
        
-       xn = X509_get_subject_name(x);
+       if (ntype == IS_DNS) {
+               len1 = strlen(name);
+               domain = strchr(name, '.');
+               if (domain) {
+                       len2 = len1 - (domain-name);
+               }
+       }
 
-       ret = X509_NAME_get_text_by_NID(xn, NID_commonName, buf, sizeof(buf));
-       if( ret == -1 ) {
-               X509_free(x);
-               return NULL;
+       for ( i=0, ret=0; ret >= 0; i++ ) {
+               altnamesize = sizeof(altname);
+               ret = gnutls_x509_crt_get_subject_alt_name( cert, i, 
+                       altname, &altnamesize, NULL );
+               if ( ret < 0 ) break;
+
+               /* ignore empty */
+               if ( altnamesize == 0 ) continue;
+
+               if ( ret == GNUTLS_SAN_DNSNAME ) {
+                       if (ntype != IS_DNS) continue;
+       
+                       /* Is this an exact match? */
+                       if ((len1 == altnamesize) && !strncasecmp(name, altname, len1)) {
+                               break;
+                       }
+
+                       /* Is this a wildcard match? */
+                       if (domain && (altname[0] == '*') && (altname[1] == '.') &&
+                               (len2 == altnamesize-1) && !strncasecmp(domain, &altname[1], len2))
+                       {
+                               break;
+                       }
+               } else if ( ret == GNUTLS_SAN_IPADDRESS ) {
+                       if (ntype == IS_DNS) continue;
+
+#ifdef LDAP_PF_INET6
+                       if (ntype == IS_IP6 && altnamesize != sizeof(struct in6_addr)) {
+                               continue;
+                       } else
+#endif
+                       if (ntype == IS_IP4 && altnamesize != sizeof(struct in_addr)) {
+                               continue;
+                       }
+                       if (!memcmp(altname, &addr, altnamesize)) {
+                               break;
+                       }
+               }
        }
+       if ( ret >= 0 ) {
+               ret = LDAP_SUCCESS;
+       } else {
+               altnamesize = sizeof(altname);
+               ret = gnutls_x509_crt_get_dn_by_oid( cert, CN_OID,
+                       0, 0, altname, &altnamesize );
+               if ( ret < 0 ) {
+                       Debug( LDAP_DEBUG_ANY,
+                               "TLS: unable to get common name from peer certificate.\n",
+                               0, 0, 0 );
+                       ret = LDAP_CONNECT_ERROR;
+                       if ( ld->ld_error ) {
+                               LDAP_FREE( ld->ld_error );
+                       }
+                       ld->ld_error = LDAP_STRDUP(
+                               _("TLS: unable to get CN from peer certificate"));
 
-       p = LDAP_STRDUP(buf);
-       X509_free(x);
-       return p;
+               } else {
+                       ret = LDAP_LOCAL_ERROR;
+                       if ( len1 == altnamesize && strncasecmp(name, altname, altnamesize) == 0 ) {
+                               ret = LDAP_SUCCESS;
+
+                       } else if (( altname[0] == '*' ) && ( altname[1] == '.' )) {
+                                       /* Is this a wildcard match? */
+                               if( domain &&
+                                       (len2 == altnamesize-1) && !strncasecmp(domain, &altname[1], len2)) {
+                                       ret = LDAP_SUCCESS;
+                               }
+                       }
+               }
+
+               if( ret == LDAP_LOCAL_ERROR ) {
+                       altname[altnamesize] = '\0';
+                       Debug( LDAP_DEBUG_ANY, "TLS: hostname (%s) does not match "
+                               "common name in certificate (%s).\n", 
+                               name, altname, 0 );
+                       ret = LDAP_CONNECT_ERROR;
+                       if ( ld->ld_error ) {
+                               LDAP_FREE( ld->ld_error );
+                       }
+                       ld->ld_error = LDAP_STRDUP(
+                               _("TLS: hostname does not match CN in peer certificate"));
+               }
+       }
+       gnutls_x509_crt_deinit( cert );
+       return ret;
 }
 
-/* what kind of hostname were we given? */
-#define        IS_DNS  0
-#define        IS_IP4  1
-#define        IS_IP6  2
+#else /* !HAVE_GNUTLS */
 
 int
 ldap_pvt_tls_check_hostname( LDAP *ld, void *s, const char *name_in )
@@ -1155,27 +2094,7 @@ ldap_pvt_tls_check_hostname( LDAP *ld, void *s, const char *name_in )
        X509_free(x);
        return ret;
 }
-
-const char *
-ldap_pvt_tls_get_peer_issuer( void *s )
-{
-#if 0  /* currently unused; see ldap_pvt_tls_get_peer_dn() if needed */
-       X509 *x;
-       X509_NAME *xn;
-       char buf[2048], *p;
-
-       x = SSL_get_peer_certificate((SSL *)s);
-
-       if (!x) return NULL;
-       
-       xn = X509_get_issuer_name(x);
-       p = LDAP_STRDUP(X509_NAME_oneline(xn, buf, sizeof(buf)));
-       X509_free(x);
-       return p;
-#else
-       return NULL;
 #endif
-}
 
 int
 ldap_int_tls_config( LDAP *ld, int option, const char *arg )
@@ -1190,6 +2109,9 @@ ldap_int_tls_config( LDAP *ld, int option, const char *arg )
        case LDAP_OPT_X_TLS_RANDOM_FILE:
        case LDAP_OPT_X_TLS_CIPHER_SUITE:
        case LDAP_OPT_X_TLS_DHFILE:
+#ifdef HAVE_GNUTLS
+       case LDAP_OPT_X_TLS_CRLFILE:
+#endif
                return ldap_pvt_tls_set_option( ld, option, (void *) arg );
 
        case LDAP_OPT_X_TLS_REQUIRE_CERT:
@@ -1267,8 +2189,7 @@ ldap_pvt_tls_get_option( LDAP *ld, int option, void *arg )
        case LDAP_OPT_X_TLS_CTX:
                *(void **)arg = lo->ldo_tls_ctx;
                if ( lo->ldo_tls_ctx ) {
-                       SSL_CTX *ctx = lo->ldo_tls_ctx;
-                       CRYPTO_add( &ctx->references, 1, CRYPTO_LOCK_SSL_CTX );
+                       tls_ctx_ref( lo->ldo_tls_ctx );
                }
                break;
        case LDAP_OPT_X_TLS_CACERTFILE:
@@ -1291,6 +2212,12 @@ ldap_pvt_tls_get_option( LDAP *ld, int option, void *arg )
                *(char **)arg = lo->ldo_tls_dhfile ?
                        LDAP_STRDUP( lo->ldo_tls_dhfile ) : NULL;
                break;
+#ifdef HAVE_GNUTLS
+       case LDAP_OPT_X_TLS_CRLFILE:
+               *(char **)arg = lo->ldo_tls_crlfile ?
+                       LDAP_STRDUP( lo->ldo_tls_crlfile ) : NULL;
+               break;
+#endif
        case LDAP_OPT_X_TLS_REQUIRE_CERT:
                *(int *)arg = lo->ldo_tls_require_cert;
                break;
@@ -1304,8 +2231,12 @@ ldap_pvt_tls_get_option( LDAP *ld, int option, void *arg )
                        LDAP_STRDUP( lo->ldo_tls_ciphersuite ) : NULL;
                break;
        case LDAP_OPT_X_TLS_RANDOM_FILE:
+#ifdef HAVE_OPENSSL
                *(char **)arg = tls_opt_randfile ?
                        LDAP_STRDUP( tls_opt_randfile ) : NULL;
+#else
+               *(char **)arg = NULL;
+#endif
                break;
        case LDAP_OPT_X_TLS_SSL_CTX: {
                void *retval = 0;
@@ -1373,9 +2304,9 @@ ldap_pvt_tls_set_option( LDAP *ld, int option, void *arg )
 
        case LDAP_OPT_X_TLS_CTX:
                if ( lo->ldo_tls_ctx )
-                       SSL_CTX_free( lo->ldo_tls_ctx );
+                       ldap_pvt_tls_ctx_free( lo->ldo_tls_ctx );
                lo->ldo_tls_ctx = arg;
-               CRYPTO_add( &((SSL_CTX *)arg)->references, 1, CRYPTO_LOCK_SSL_CTX );
+               tls_ctx_ref( lo->ldo_tls_ctx );
                return 0;
        case LDAP_OPT_X_TLS_CONNECT_CB:
                lo->ldo_tls_connect_cb = (LDAP_TLS_CONNECT_CB *)arg;
@@ -1403,6 +2334,12 @@ ldap_pvt_tls_set_option( LDAP *ld, int option, void *arg )
                if ( lo->ldo_tls_dhfile ) LDAP_FREE( lo->ldo_tls_dhfile );
                lo->ldo_tls_dhfile = arg ? LDAP_STRDUP( (char *) arg ) : NULL;
                return 0;
+#ifdef HAVE_GNUTLS
+       case LDAP_OPT_X_TLS_CRLFILE:
+               if ( lo->ldo_tls_crlfile ) LDAP_FREE( lo->ldo_tls_crlfile );
+               lo->ldo_tls_crlfile = arg ? LDAP_STRDUP( (char *) arg ) : NULL;
+               return 0;
+#endif
        case LDAP_OPT_X_TLS_REQUIRE_CERT:
                if ( !arg ) return -1;
                switch( *(int *) arg ) {
@@ -1435,14 +2372,16 @@ ldap_pvt_tls_set_option( LDAP *ld, int option, void *arg )
        case LDAP_OPT_X_TLS_RANDOM_FILE:
                if ( ld != NULL )
                        return -1;
+#ifdef HAVE_OPENSSL
                if (tls_opt_randfile ) LDAP_FREE (tls_opt_randfile );
                tls_opt_randfile = arg ? LDAP_STRDUP( (char *) arg ) : NULL;
+#endif
                break;
 
        case LDAP_OPT_X_TLS_NEWCTX:
                if ( !arg ) return -1;
                if ( lo->ldo_tls_ctx )
-                       SSL_CTX_free( lo->ldo_tls_ctx );
+                       ldap_pvt_tls_ctx_free( lo->ldo_tls_ctx );
                lo->ldo_tls_ctx = NULL;
                return ldap_int_tls_init_ctx( lo, *(int *)arg );
        default:
@@ -1495,6 +2434,7 @@ ldap_int_tls_start ( LDAP *ld, LDAPConn *conn, LDAPURLDesc *srv )
        return LDAP_SUCCESS;
 }
 
+#ifdef HAVE_OPENSSL
 /* Derived from openssl/apps/s_cb.c */
 static void
 tls_info_cb( const SSL *ssl, int where, int ret )
@@ -1822,6 +2762,8 @@ tls_tmp_dh_cb( SSL *ssl, int is_export, int key_length )
 }
 #endif
 
+#endif /* HAVE_OPENSSL */
+
 void *
 ldap_pvt_tls_sb_ctx( Sockbuf *sb )
 {
@@ -1840,11 +2782,17 @@ ldap_pvt_tls_sb_ctx( Sockbuf *sb )
 int
 ldap_pvt_tls_get_strength( void *s )
 {
-#ifdef HAVE_TLS
+#ifdef HAVE_OPENSSL
        SSL_CIPHER *c;
 
        c = SSL_get_current_cipher((SSL *)s);
        return SSL_CIPHER_get_bits(c, NULL);
+#elif defined(HAVE_GNUTLS)
+       tls_session *session = s;
+       gnutls_cipher_algorithm_t c;
+
+       c = gnutls_cipher_get( session->session );
+       return gnutls_cipher_get_key_size( c );
 #else
        return 0;
 #endif
@@ -1855,18 +2803,36 @@ int
 ldap_pvt_tls_get_my_dn( void *s, struct berval *dn, LDAPDN_rewrite_dummy *func, unsigned flags )
 {
 #ifdef HAVE_TLS
+       struct berval der_dn;
+       int rc;
+#ifdef HAVE_OPENSSL
        X509 *x;
        X509_NAME *xn;
-       int rc;
 
        x = SSL_get_certificate((SSL *)s);
 
        if (!x) return LDAP_INVALID_CREDENTIALS;
        
        xn = X509_get_subject_name(x);
-       rc = ldap_X509dn2bv(xn, dn, (LDAPDN_rewrite_func *)func, flags );
+       der_dn.bv_len = i2d_X509_NAME( xn, NULL );
+       der_dn.bv_val = xn->bytes->data;
+#elif defined(HAVE_GNUTLS)
+       tls_session *session = s;
+       const gnutls_datum_t *x;
+       struct berval bv;
+
+       x = gnutls_certificate_get_ours( session->session );
+
+       if (!x) return LDAP_INVALID_CREDENTIALS;
+       
+       bv.bv_val = x->data;
+       bv.bv_len = x->size;
+
+       x509_cert_get_dn( &bv, &der_dn, 1 );
+#endif
+       rc = ldap_X509dn2bv(&der_dn, dn, (LDAPDN_rewrite_func *)func, flags );
        return rc;
-#else
+#else /* !HAVE_TLS */
        return LDAP_NOT_SUPPORTED;
 #endif
 }
@@ -1932,3 +2898,234 @@ ldap_start_tls_s ( LDAP *ld,
 #endif
 }
 
+/* These tags probably all belong in lber.h, but they're
+ * not normally encountered when processing LDAP, so maybe
+ * they belong somewhere else instead.
+ */
+
+#define LBER_TAG_OID           ((ber_tag_t) 0x06UL)
+
+/* Tags for string types used in a DirectoryString.
+ *
+ * Note that IA5string is not one of the defined choices for
+ * DirectoryString in X.520, but it gets used for email AVAs.
+ */
+#define        LBER_TAG_UTF8           ((ber_tag_t) 0x0cUL)
+#define        LBER_TAG_PRINTABLE      ((ber_tag_t) 0x13UL)
+#define        LBER_TAG_TELETEX        ((ber_tag_t) 0x14UL)
+#define        LBER_TAG_IA5            ((ber_tag_t) 0x16UL)
+#define        LBER_TAG_UNIVERSAL      ((ber_tag_t) 0x1cUL)
+#define        LBER_TAG_BMP            ((ber_tag_t) 0x1eUL)
+
+static oid_name *
+find_oid( struct berval *oid )
+{
+       int i;
+
+       for ( i=0; !BER_BVISNULL( &oids[i].oid ); i++ ) {
+               if ( oids[i].oid.bv_len != oid->bv_len ) continue;
+               if ( !strcmp( oids[i].oid.bv_val, oid->bv_val ))
+                       return &oids[i];
+       }
+       return NULL;
+}
+
+/* Convert a structured DN from an X.509 certificate into an LDAPV3 DN.
+ * x509_name must be raw DER. If func is non-NULL, the
+ * constructed DN will use numeric OIDs to identify attributeTypes,
+ * and the func() will be invoked to rewrite the DN with the given
+ * flags.
+ *
+ * Otherwise the DN will use shortNames from a hardcoded table.
+ */
+int
+ldap_X509dn2bv( void *x509_name, struct berval *bv, LDAPDN_rewrite_func *func,
+       unsigned flags )
+{
+       LDAPDN  newDN;
+       LDAPRDN newRDN;
+       LDAPAVA *newAVA, *baseAVA;
+       BerElementBuffer berbuf;
+       BerElement *ber = (BerElement *)&berbuf;
+       char oids[8192], *oidptr = oids, *oidbuf = NULL;
+       void *ptrs[2048];
+       char *dn_end, *rdn_end;
+       int i, navas, nrdns, rc = LDAP_SUCCESS;
+       size_t dnsize, oidrem = sizeof(oids), oidsize = 0;
+       int csize;
+       ber_tag_t tag;
+       ber_len_t len;
+       oid_name *oidname;
+
+       struct berval   Oid, Val, oid2, *in = x509_name;
+
+       assert( bv != NULL );
+
+       bv->bv_len = 0;
+       bv->bv_val = NULL;
+
+       navas = 0;
+       nrdns = 0;
+
+       /* A DN is a SEQUENCE of RDNs. An RDN is a SET of AVAs.
+        * An AVA is a SEQUENCE of attr and value.
+        * Count the number of AVAs and RDNs
+        */
+       ber_init2( ber, in, LBER_USE_DER );
+       tag = ber_peek_tag( ber, &len );
+       if ( tag != LBER_SEQUENCE )
+               return LDAP_DECODING_ERROR;
+
+       for ( tag = ber_first_element( ber, &len, &dn_end );
+               tag == LBER_SET;
+               tag = ber_next_element( ber, &len, dn_end )) {
+               nrdns++;
+               for ( tag = ber_first_element( ber, &len, &rdn_end );
+                       tag == LBER_SEQUENCE;
+                       tag = ber_next_element( ber, &len, rdn_end )) {
+                       tag = ber_skip_tag( ber, &len );
+                       ber_skip_data( ber, len );
+                       navas++;
+               }
+       }
+
+       /* Allocate the DN/RDN/AVA stuff as a single block */    
+       dnsize = sizeof(LDAPRDN) * (nrdns+1);
+       dnsize += sizeof(LDAPAVA *) * (navas+nrdns);
+       dnsize += sizeof(LDAPAVA) * navas;
+       if (dnsize > sizeof(ptrs)) {
+               newDN = (LDAPDN)LDAP_MALLOC( dnsize );
+               if ( newDN == NULL )
+                       return LDAP_NO_MEMORY;
+       } else {
+               newDN = (LDAPDN)(char *)ptrs;
+       }
+       
+       newDN[nrdns] = NULL;
+       newRDN = (LDAPRDN)(newDN + nrdns+1);
+       newAVA = (LDAPAVA *)(newRDN + navas + nrdns);
+       baseAVA = newAVA;
+
+       /* Rewind and start extracting */
+       ber_rewind( ber );
+
+       tag = ber_first_element( ber, &len, &dn_end );
+       for ( i = nrdns - 1; i >= 0; i-- ) {
+               newDN[i] = newRDN;
+
+               for ( tag = ber_first_element( ber, &len, &rdn_end );
+                       tag == LBER_SEQUENCE;
+                       tag = ber_next_element( ber, &len, rdn_end )) {
+
+                       *newRDN++ = newAVA;
+                       tag = ber_skip_tag( ber, &len );
+                       tag = ber_get_stringbv( ber, &Oid, LBER_BV_NOTERM );
+                       if ( tag != LBER_TAG_OID ) {
+                               rc = LDAP_DECODING_ERROR;
+                               goto nomem;
+                       }
+
+                       oid2.bv_val = oidptr;
+                       oid2.bv_len = oidrem;
+                       if ( ber_decode_oid( &Oid, &oid2 ) < 0 ) {
+                               rc = LDAP_DECODING_ERROR;
+                               goto nomem;
+                       }
+                       oidname = find_oid( &oid2 );
+                       if ( !oidname ) {
+                               newAVA->la_attr = oid2;
+                               oidptr += oid2.bv_len + 1;
+                               oidrem -= oid2.bv_len + 1;
+
+                               /* Running out of OID buffer space? */
+                               if (oidrem < 128) {
+                                       if ( oidsize == 0 ) {
+                                               oidsize = sizeof(oids) * 2;
+                                               oidrem = oidsize;
+                                               oidbuf = LDAP_MALLOC( oidsize );
+                                               if ( oidbuf == NULL ) goto nomem;
+                                               oidptr = oidbuf;
+                                       } else {
+                                               char *old = oidbuf;
+                                               oidbuf = LDAP_REALLOC( oidbuf, oidsize*2 );
+                                               if ( oidbuf == NULL ) goto nomem;
+                                               /* Buffer moved! Fix AVA pointers */
+                                               if ( old != oidbuf ) {
+                                                       LDAPAVA *a;
+                                                       long dif = oidbuf - old;
+
+                                                       for (a=baseAVA; a<=newAVA; a++){
+                                                               if (a->la_attr.bv_val >= old &&
+                                                                       a->la_attr.bv_val <= (old + oidsize))
+                                                                       a->la_attr.bv_val += dif;
+                                                       }
+                                               }
+                                               oidptr = oidbuf + oidsize - oidrem;
+                                               oidrem += oidsize;
+                                               oidsize *= 2;
+                                       }
+                               }
+                       } else {
+                               if ( func ) {
+                                       newAVA->la_attr = oidname->oid;
+                               } else {
+                                       newAVA->la_attr = oidname->name;
+                               }
+                       }
+                       tag = ber_get_stringbv( ber, &Val, LBER_BV_NOTERM );
+                       switch(tag) {
+                       case LBER_TAG_UNIVERSAL:
+                               /* This uses 32-bit ISO 10646-1 */
+                               csize = 4; goto to_utf8;
+                       case LBER_TAG_BMP:
+                               /* This uses 16-bit ISO 10646-1 */
+                               csize = 2; goto to_utf8;
+                       case LBER_TAG_TELETEX:
+                               /* This uses 8-bit, assume ISO 8859-1 */
+                               csize = 1;
+to_utf8:               rc = ldap_ucs_to_utf8s( &Val, csize, &newAVA->la_value );
+                               newAVA->la_flags |= LDAP_AVA_FREE_VALUE;
+                               if (rc != LDAP_SUCCESS) goto nomem;
+                               newAVA->la_flags = LDAP_AVA_NONPRINTABLE;
+                               break;
+                       case LBER_TAG_UTF8:
+                               newAVA->la_flags = LDAP_AVA_NONPRINTABLE;
+                               /* This is already in UTF-8 encoding */
+                       case LBER_TAG_IA5:
+                       case LBER_TAG_PRINTABLE:
+                               /* These are always 7-bit strings */
+                               newAVA->la_value = Val;
+                       default:
+                               ;
+                       }
+                       newAVA->la_private = NULL;
+                       newAVA->la_flags = LDAP_AVA_STRING;
+                       newAVA++;
+               }
+               *newRDN++ = NULL;
+               tag = ber_next_element( ber, &len, dn_end );
+       }
+               
+       if ( func ) {
+               rc = func( newDN, flags, NULL );
+               if ( rc != LDAP_SUCCESS )
+                       goto nomem;
+       }
+
+       rc = ldap_dn2bv_x( newDN, bv, LDAP_DN_FORMAT_LDAPV3, NULL );
+
+nomem:
+       for (;baseAVA < newAVA; baseAVA++) {
+               if (baseAVA->la_flags & LDAP_AVA_FREE_ATTR)
+                       LDAP_FREE( baseAVA->la_attr.bv_val );
+               if (baseAVA->la_flags & LDAP_AVA_FREE_VALUE)
+                       LDAP_FREE( baseAVA->la_value.bv_val );
+       }
+
+       if ( oidsize != 0 )
+               LDAP_FREE( oidbuf );
+       if ( newDN != (LDAPDN)(char *) ptrs )
+               LDAP_FREE( newDN );
+       return rc;
+}
+
index 1eadf029f152df0f0a7d4d209ce323eb45b49fc7..6a6e076b56fa16c8a13a0b4f1f12a714639ffb6e 100644 (file)
@@ -20,7 +20,7 @@
 
 /*
  *  LDAP URLs look like this:
- *    ldap[is]://host:port[/[dn[?[attributes][?[scope][?[filter][?exts]]]]]]
+ *    ldap[is]://host[:port][/[dn[?[attributes][?[scope][?[filter][?exts]]]]]]
  *
  *  where:
  *   attributes is a comma separated list
@@ -533,12 +533,17 @@ desc2str_len( LDAPURLDesc *u )
 {
        int             sep = 0;
        int             len = 0;
+       int             is_ipc = 0;
        struct berval   scope;
 
-       if ( u == NULL ) {
+       if ( u == NULL || u->lud_scheme == NULL ) {
                return -1;
        }
 
+       if ( !strcmp( "ldapi", u->lud_scheme )) {
+               is_ipc = 1;
+       }
+
        if ( u->lud_exts ) {
                len += hex_escape_len_list( u->lud_exts, URLESC_COMMA );
                if ( !sep ) {
@@ -547,7 +552,7 @@ desc2str_len( LDAPURLDesc *u )
        }
 
        if ( u->lud_filter ) {
-               len +=  hex_escape_len( u->lud_filter, URLESC_NONE );
+               len += hex_escape_len( u->lud_filter, URLESC_NONE );
                if ( !sep ) {
                        sep = 4;
                }
@@ -561,7 +566,7 @@ desc2str_len( LDAPURLDesc *u )
        }
 
        if ( u->lud_attrs ) {
-               len +=  hex_escape_len_list( u->lud_attrs, URLESC_NONE );
+               len += hex_escape_len_list( u->lud_attrs, URLESC_NONE );
                if ( !sep ) {
                        sep = 2;
                }
@@ -587,6 +592,9 @@ desc2str_len( LDAPURLDesc *u )
        } else {
                if ( u->lud_host && u->lud_host[0] ) {
                        len += hex_escape_len( u->lud_host, URLESC_SLASH );
+                       if ( !is_ipc && strchr( u->lud_host, ':' )) {
+                               len += 2;       /* IPv6, [] */
+                       }
                }
        }
 
@@ -595,12 +603,14 @@ desc2str_len( LDAPURLDesc *u )
        return len;
 }
 
-int
+static int
 desc2str( LDAPURLDesc *u, char *s, int len )
 {
        int             i;
        int             sep = 0;
        int             sofar = 0;
+       int             is_v6 = 0;
+       int             is_ipc = 0;
        struct berval   scope = BER_BVNULL;
 
        if ( u == NULL ) {
@@ -611,6 +621,10 @@ desc2str( LDAPURLDesc *u, char *s, int len )
                return -1;
        }
 
+       if ( u->lud_scheme && !strcmp( "ldapi", u->lud_scheme )) {
+               is_ipc = 1;
+       }
+
        ldap_pvt_scope2bv( u->lud_scope, &scope );
 
        if ( u->lud_exts ) {
@@ -625,17 +639,31 @@ desc2str( LDAPURLDesc *u, char *s, int len )
                sep = 1;
        }
 
+       if ( !is_ipc && u->lud_host && strchr( u->lud_host, ':' )) {
+               is_v6 = 1;
+       }
+
        if ( u->lud_port ) {
-               len -= sprintf( s, "%s://%s:%d%n", u->lud_scheme,
+               len -= sprintf( s, "%s://%s%s%s:%d%n", u->lud_scheme,
+                               is_v6 ? "[" : "",
                                u->lud_host ? u->lud_host : "",
+                               is_v6 ? "]" : "",
                                u->lud_port, &sofar );
 
        } else {
                len -= sprintf( s, "%s://%n", u->lud_scheme, &sofar );
                if ( u->lud_host && u->lud_host[0] ) {
+                       if ( is_v6 ) {
+                               s[sofar++] = '[';
+                               len--;
+                       }
                        i = hex_escape( &s[sofar], len, u->lud_host, URLESC_SLASH );
                        sofar += i;
                        len -= i;
+                       if ( is_v6 ) {
+                               s[sofar++] = ']';
+                               len--;
+                       }
                }
        }
 
@@ -765,7 +793,7 @@ ldap_url_parse_ext( LDAP_CONST char *url_in, LDAPURLDesc **ludpp, unsigned flags
 
        LDAPURLDesc     *ludp;
        char    *p, *q, *r;
-       int             i, enclosed;
+       int             i, enclosed, proto, is_v6 = 0;
        const char *scheme = NULL;
        const char *url_tmp;
        char *url;
@@ -795,6 +823,11 @@ ldap_url_parse_ext( LDAP_CONST char *url_in, LDAPURLDesc **ludpp, unsigned flags
 
        assert( scheme != NULL );
 
+       proto = ldap_pvt_url_scheme2proto( scheme );
+       if ( proto == -1 ) {
+               return LDAP_URL_ERR_BADSCHEME;
+       }
+
        /* make working copy of the remainder of the URL */
        url = LDAP_STRDUP( url_tmp );
        if ( url == NULL ) {
@@ -839,62 +872,83 @@ ldap_url_parse_ext( LDAP_CONST char *url_in, LDAPURLDesc **ludpp, unsigned flags
 
        /* scan forward for '/' that marks end of hostport and begin. of dn */
        p = strchr( url, '/' );
+       q = NULL;
 
        if( p != NULL ) {
                /* terminate hostport; point to start of dn */
                *p++ = '\0';
+       } else {
+               /* check for Novell kludge, see below */
+               p = strchr( url, '?' );
+               if ( p ) {
+                       *p++ = '\0';
+                       q = p;
+                       p = NULL;
+               }
        }
 
-       /* IPv6 syntax with [ip address]:port */
-       if ( *url == '[' ) {
-               r = strchr( url, ']' );
-               if ( r == NULL ) {
-                       LDAP_FREE( url );
-                       ldap_free_urldesc( ludp );
-                       return LDAP_URL_ERR_BADURL;
+       if ( proto != LDAP_PROTO_IPC ) {
+               /* IPv6 syntax with [ip address]:port */
+               if ( *url == '[' ) {
+                       r = strchr( url, ']' );
+                       if ( r == NULL ) {
+                               LDAP_FREE( url );
+                               ldap_free_urldesc( ludp );
+                               return LDAP_URL_ERR_BADURL;
+                       }
+                       *r++ = '\0';
+                       q = strchr( r, ':' );
+                       if ( q && q != r ) {
+                               LDAP_FREE( url );
+                               ldap_free_urldesc( ludp );
+                               return LDAP_URL_ERR_BADURL;
+                       }
+                       is_v6 = 1;
+               } else {
+                       q = strchr( url, ':' );
                }
-               *r++ = '\0';
-               q = strchr( r, ':' );
-       } else {
-               q = strchr( url, ':' );
-       }
 
-       if ( q != NULL ) {
-               char    *next;
+               if ( q != NULL ) {
+                       char    *next;
 
-               *q++ = '\0';
-               ldap_pvt_hex_unescape( q );
+                       *q++ = '\0';
+                       ldap_pvt_hex_unescape( q );
 
-               if( *q == '\0' ) {
-                       LDAP_FREE( url );
-                       ldap_free_urldesc( ludp );
-                       return LDAP_URL_ERR_BADURL;
-               }
+                       if( *q == '\0' ) {
+                               LDAP_FREE( url );
+                               ldap_free_urldesc( ludp );
+                               return LDAP_URL_ERR_BADURL;
+                       }
 
-               ludp->lud_port = strtol( q, &next, 10 );
-               if ( next == q || next[0] != '\0' ) {
-                       LDAP_FREE( url );
-                       ldap_free_urldesc( ludp );
-                       return LDAP_URL_ERR_BADURL;
+                       ludp->lud_port = strtol( q, &next, 10 );
+                       if ( next == q || next[0] != '\0' ) {
+                               LDAP_FREE( url );
+                               ldap_free_urldesc( ludp );
+                               return LDAP_URL_ERR_BADURL;
+                       }
+                       /* check for Novell kludge */
+                       if ( !p ) {
+                               if ( *next != '\0' ) {
+                                       q = &next[1];
+                               } else {
+                                       q = NULL;
+                               }
+                       }
                }
-       }
 
-       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;
+               if ( ( flags & LDAP_PVT_URL_PARSE_DEF_PORT ) && ludp->lud_port == 0 ) {
+                       if ( strcmp( ludp->lud_scheme, "ldaps" ) == 0 ) {
+                               ludp->lud_port = LDAPS_PORT;
+                       } else {
+                               ludp->lud_port = LDAP_PORT;
+                       }
                }
        }
 
        ldap_pvt_hex_unescape( url );
 
        /* If [ip address]:port syntax, url is [ip and we skip the [ */
-       ludp->lud_host = LDAP_STRDUP( url + ( *url == '[' ) );
+       ludp->lud_host = LDAP_STRDUP( url + is_v6 );
 
        if( ludp->lud_host == NULL ) {
                LDAP_FREE( url );
@@ -919,28 +973,25 @@ ldap_url_parse_ext( LDAP_CONST char *url_in, LDAPURLDesc **ludpp, unsigned flags
         * but we need to account for it. Fortunately it can't be confused with
         * anything real.
         */
-       if( (p == NULL) && (q != NULL) && ((q = strchr( q, '?')) != NULL)) {
-               q++;            
+       if( (p == NULL) && (q != NULL) && (*q == '?') ) {
                /* ? immediately followed by question */
-               if( *q == '?') {
-                       q++;
-                       if( *q != '\0' ) {
-                               /* parse dn part */
-                               ldap_pvt_hex_unescape( q );
-                               ludp->lud_dn = LDAP_STRDUP( q );
+               q++;
+               if( *q != '\0' ) {
+                       /* parse dn part */
+                       ldap_pvt_hex_unescape( q );
+                       ludp->lud_dn = LDAP_STRDUP( q );
 
-                       } else if ( !( flags & LDAP_PVT_URL_PARSE_NOEMPTY_DN ) ) {
-                               ludp->lud_dn = LDAP_STRDUP( "" );
+               } else if ( !( flags & LDAP_PVT_URL_PARSE_NOEMPTY_DN ) ) {
+                       ludp->lud_dn = LDAP_STRDUP( "" );
 
-                       } else {
-                               check_dn = 0;
-                       }
+               } else {
+                       check_dn = 0;
+               }
 
-                       if ( check_dn && ludp->lud_dn == NULL ) {
-                               LDAP_FREE( url );
-                               ldap_free_urldesc( ludp );
-                               return LDAP_URL_ERR_MEM;
-                       }
+               if ( check_dn && ludp->lud_dn == NULL ) {
+                       LDAP_FREE( url );
+                       ldap_free_urldesc( ludp );
+                       return LDAP_URL_ERR_MEM;
                }
        }
 
index 87db0b676a01f1265ac9aa0338d18f4f6d7f625b..59c6db78be5822f0f28f3f2ef94f6d3f0fdd81c6 100644 (file)
@@ -122,5 +122,7 @@ main(int argc, char *argv[])
                }
        }
 
+       fprintf( stdout, "URL: %s\n", ldap_url_desc2str( lud ));
+
        return EXIT_SUCCESS;
 }
index f301a2e6410d579cd4d8975ca305df8c5b2f9437..f0c4cb446e0b4e058d8bd843776f03ccb1656d0a 100644 (file)
@@ -210,7 +210,6 @@ ldap_create_vlv_control(
        LDAPControl **ctrlp )
 {
        struct berval   value;
-       BerElement      *ber;
 
        if ( ctrlp == NULL ) {
                ld->ld_errno = LDAP_PARAM_ERROR;
@@ -219,19 +218,12 @@ ldap_create_vlv_control(
 
        ld->ld_errno = ldap_create_vlv_control_value( ld, vlvinfop, &value );
        if ( ld->ld_errno == LDAP_SUCCESS ) {
-               if ((ber = ldap_alloc_ber_with_options(ld)) == NULL) {
-                       ld->ld_errno = LDAP_NO_MEMORY;
-                       return LDAP_NO_MEMORY;
-               }
 
-               ld->ld_errno = ldap_create_control( LDAP_CONTROL_VLVREQUEST,
-                       ber, 1, ctrlp );
-               if ( ld->ld_errno == LDAP_SUCCESS ) {
-                       (*ctrlp)->ldctl_value = value;
-               } else {
+               ld->ld_errno = ldap_control_create( LDAP_CONTROL_VLVREQUEST,
+                       1, &value, 0, ctrlp );
+               if ( ld->ld_errno != LDAP_SUCCESS ) {
                        LDAP_FREE( value.bv_val );
                }
-               ber_free(ber, 1);
        }
 
        return ld->ld_errno;
index f52f427518ed0adab50f0bd2fd7abeb788885bff..48df9f7550c4661d0b0f65c6afced1dee6cf3efb 100644 (file)
@@ -28,7 +28,7 @@ XXSRCS    = apitest.c test.c \
        request.c os-ip.c url.c pagectrl.c sortctrl.c vlvctrl.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 ldap_sync.c
+       turn.c ppolicy.c dds.c txn.c ldap_sync.c stctrl.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
@@ -44,7 +44,7 @@ OBJS  = threads.lo rdwr.lo rmutex.lo tpool.lo  rq.lo \
        request.lo os-ip.lo url.lo pagectrl.lo sortctrl.lo vlvctrl.lo \
        init.lo options.lo print.lo string.lo util-int.lo schema.lo \
        charray.lo tls.lo os-local.lo dnssrv.lo utf-8.lo utf-8-conv.lo \
-       turn.lo ppolicy.lo dds.lo txn.lo ldap_sync.lo
+       turn.lo ppolicy.lo dds.lo txn.lo ldap_sync.lo stctrl.lo
 
 LDAP_INCDIR= ../../include       
 LDAP_LIBDIR= ../../libraries
index 87ed67fa02b3ae8a1d9ad7931d92fead52201e03..2d271252bc871766955f9065688462c956bfbad4 100644 (file)
@@ -57,7 +57,7 @@
  *
  * Run-time configuration:
  *
- *  Setup of memory debugging tools:
+ *  Memory debugging tools:
  *   Tools that report uninitialized memory accesses should disable
  *   such warnings about the function debug_already_initialized().
  *   Alternatively, include "noreinit" (below) in $LDAP_THREAD_DEBUG.
@@ -274,19 +274,16 @@ get_options( void )
        if( s != NULL ) {
                while( *(s += strspn( s, ", \t\r\n" )) != '\0' ) {
                        size_t optlen = strcspn( s, ", \t\r\n" );
-                       const struct option_info_s *oi;
-                       for( oi = option_info; oi->name; oi++ ) {
-                               if( strncasecmp( oi->name, s, optlen ) == 0 ) {
-                                       if( oi->name && oi->name[optlen] == '\0' ) {
-                                               *oi->var = oi->val;
-                                       } else {
-                                               fprintf( stderr,
-                                                       "== thr_debug: Unknown $%s option '%.*s' ==\n",
-                                                       "LDAP_THREAD_DEBUG", (int) optlen, s );
-                                       }
-                                       break;
-                               }
-                       }
+                       const struct option_info_s *oi = option_info;
+                       while( oi->name &&
+                                  (strncasecmp( oi->name, s, optlen ) || oi->name[optlen]) )
+                               oi++;
+                       if( oi->name )
+                               *oi->var = oi->val;
+                       else
+                               fprintf( stderr,
+                                       "== thr_debug: Unknown $%s option '%.*s' ==\n",
+                                       "LDAP_THREAD_DEBUG", (int) optlen, s );
                        s += optlen;
                }
        }
@@ -383,9 +380,8 @@ ldap_debug_thread_assert_mutex_owner(
 static void debug_noop( void );
 static int debug_already_initialized( const ldap_debug_usage_info_t *usage );
 
-/* Names used to give clearer error messages */
+/* Name used for clearer error message */
 #define IS_COPY_OR_MOVED(usage) ((usage)->self != SCRAMBLE( usage ))
-enum { Is_destroyed = 1 };
 
 #define DUMMY_ADDR(usage) \
        (wraptype == Wrap_scramble \
@@ -408,18 +404,22 @@ init_usage( ldap_debug_usage_info_t *usage, const char *msg )
                                free( dummy );
                        } );
                }
-               usage->self = SCRAMBLE( usage );
                if( wraptype != Wrap_noalloc ) {
                        unsigned char *dummy = malloc( 1 );
                        assert( dummy != NULL );
                        if( wraptype == Wrap_scramble ) {
                                usage->mem.num = SCRAMBLE( dummy );
+                               /* Verify that ptr<->integer casts work on this host */
                                assert( UNSCRAMBLE_dummyp( usage->mem.num ) == dummy );
                        } else {
                                usage->mem.ptr = dummy + wrap_offset;
                        }
                }
+       } else {
+               /* Unused, but set for readability in debugger */
+               usage->mem.ptr = NULL;
        }
+       usage->self = SCRAMBLE( usage );        /* If nomem, only for debugger */
        usage->magic = ldap_debug_magic;
        usage->state = ldap_debug_state_inited;
 }
@@ -428,6 +428,8 @@ init_usage( ldap_debug_usage_info_t *usage, const char *msg )
 static void
 check_usage( const ldap_debug_usage_info_t *usage, const char *msg )
 {
+       enum { Is_destroyed = 1 };      /* Name used for clearer error message */
+
        if( usage->magic != ldap_debug_magic ) {
                ERROR( usage->magic, msg );
                return;
@@ -474,14 +476,24 @@ debug_noop( void )
 {
 }
 
-/* Return true if the resource is initialized and not copied/realloced. */
-/* Valid programs access uninitialized memory here unless "noreinit".   */
+/*
+ * Valid programs access uninitialized memory here unless "noreinit".
+ *
+ * Returns true if the resource is initialized and not copied/realloced.
+ */
 static int
 debug_already_initialized( const ldap_debug_usage_info_t *usage )
 {
-       return (usage->state == ldap_debug_state_inited &&
-               !IS_COPY_OR_MOVED( usage ) &&
-               usage->magic == ldap_debug_magic);
+       /*
+        * 'ret' keeps the Valgrind warning "Conditional jump or move
+        * depends on uninitialised value(s)" _inside_ this function.
+        */
+       volatile int ret = 0;
+       if( usage->state == ldap_debug_state_inited )
+               if( !IS_COPY_OR_MOVED( usage ) )
+               if( usage->magic == ldap_debug_magic )
+                               ret = 1;
+       return ret;
 }
 
 #endif /* LDAP_THREAD_DEBUG_WRAP */
@@ -489,7 +501,7 @@ debug_already_initialized( const ldap_debug_usage_info_t *usage )
 
 #if !(LDAP_THREAD_DEBUG_THREAD_ID +0)
 
-typedef int ldap_debug_thread_t;
+typedef void ldap_debug_thread_t;
 #define init_thread_info()     {}
 #define with_thread_info_lock(statements) { statements; }
 #define thread_info_detached(t)        0
@@ -577,13 +589,13 @@ remove_thread_info( ldap_debug_thread_t *t, const char *msg )
                (thread_info[thread_info_used] = t   )->idx = thread_info_used;
 }
 
-ldap_debug_thread_t *
-get_thread_info( ldap_pvt_thread_t *thread, const char *msg )
+static ldap_debug_thread_t *
+get_thread_info( ldap_pvt_thread_t thread, const char *msg )
 {
        unsigned int i;
        ldap_debug_thread_t *t;
        for( i = 0; i < thread_info_used; i++ ) {
-               if( ldap_pvt_thread_equal( *thread, thread_info[i]->wrapped ) )
+               if( ldap_pvt_thread_equal( thread, thread_info[i]->wrapped ) )
                        break;
        }
        ERROR_IF( i == thread_info_used, msg );
@@ -714,7 +726,9 @@ static void
 thread_exiting( const char *how, const char *msg )
 {
        ldap_pvt_thread_t thread;
+#if 0 /* Detached threads may exit after ldap_debug_thread_destroy(). */
        ERROR_IF( !threading_enabled, msg );
+#endif
        thread = ldap_pvt_thread_self();
        if( tracethreads ) {
                char buf[40];
@@ -723,8 +737,7 @@ thread_exiting( const char *how, const char *msg )
        }
        if( threadID ) {
                with_thread_info_lock({
-                       ldap_debug_thread_t *t = get_thread_info(
-                               &thread, msg );
+                       ldap_debug_thread_t *t = get_thread_info( thread, msg );
                        if( thread_info_detached( t ) )
                                remove_thread_info( t, msg );
                });
@@ -786,6 +799,8 @@ ldap_pvt_thread_create(
        }
        if( rc ) {
                ERROR( rc, "ldap_pvt_thread_create" );
+               if( wrap_threads )
+                       free( arg );
        } else {
                if( tracethreads ) {
                        char buf[40], buf2[40];
@@ -816,7 +831,7 @@ ldap_pvt_thread_join( ldap_pvt_thread_t thread, void **thread_return )
        }
        if( threadID )
                with_thread_info_lock( {
-                       t = get_thread_info( &thread, "ldap_pvt_thread_join" );
+                       t = get_thread_info( thread, "ldap_pvt_thread_join" );
                        ERROR_IF( thread_info_detached( t ), "ldap_pvt_thread_join" );
                } );
        rc = ldap_int_thread_join( thread, thread_return );
@@ -1159,7 +1174,7 @@ ldap_pvt_thread_pool_submit(
 {
        int rc, has_pool;
        ERROR_IF( !threading_enabled, "ldap_pvt_thread_pool_submit" );
-       has_pool = (tpool != NULL && *tpool != NULL);
+       has_pool = (tpool && *tpool);
        rc = ldap_int_thread_pool_submit( tpool, start_routine, arg );
        if( has_pool )
                ERROR_IF( rc, "ldap_pvt_thread_pool_submit" );
@@ -1187,7 +1202,7 @@ ldap_pvt_thread_pool_destroy( ldap_pvt_thread_pool_t *tpool, int run_pending )
 {
        int rc, has_pool;
        ERROR_IF( !threading_enabled, "ldap_pvt_thread_pool_destroy" );
-       has_pool = (tpool != NULL && *tpool != NULL);
+       has_pool = (tpool && *tpool);
        rc = ldap_int_thread_pool_destroy( tpool, run_pending );
        if( has_pool ) {
                if( rc ) {
index f378cfcaf8b6515db6f12ef46d037d141b90ad3a..4e0a45b4321b44872a5b8f20915ce6fd1341288f 100644 (file)
@@ -55,6 +55,12 @@ static pthread_mutexattr_t mutex_attr;
 #  define LDAP_INT_THREAD_MUTEXATTR_DEFAULT &mutex_attr
 #endif
 
+#if HAVE_PTHREADS < 7
+#define ERRVAL(val)    ((val) < 0 ? errno : 0)
+#else
+#define ERRVAL(val)    (val)
+#endif
+
 int
 ldap_int_thread_initialize( void )
 {
@@ -84,7 +90,7 @@ ldap_pvt_thread_set_concurrency(int n)
 {
 #ifdef HAVE_PTHREAD_SETCONCURRENCY
        return pthread_setconcurrency( n );
-#elif HAVE_THR_SETCONCURRENCY
+#elif defined(HAVE_THR_SETCONCURRENCY)
        return thr_setconcurrency( n );
 #else
        return 0;
@@ -98,7 +104,7 @@ ldap_pvt_thread_get_concurrency(void)
 {
 #ifdef HAVE_PTHREAD_GETCONCURRENCY
        return pthread_getconcurrency();
-#elif HAVE_THR_GETCONCURRENCY
+#elif defined(HAVE_THR_GETCONCURRENCY)
        return thr_getconcurrency();
 #else
        return 0;
@@ -157,6 +163,7 @@ ldap_pvt_thread_create( ldap_pvt_thread_t * thread,
 #else
        rtn = pthread_create( thread, &attr, start_routine, arg );
 #endif
+
 #if HAVE_PTHREADS > 5
        pthread_attr_destroy(&attr);
 #else
@@ -183,26 +190,18 @@ ldap_pvt_thread_join( ldap_pvt_thread_t thread, void **thread_return )
 {
 #if HAVE_PTHREADS < 7
        void *dummy;
-
        if (thread_return==NULL)
          thread_return=&dummy;
-
-       if ( pthread_join( thread, thread_return ) < 0 ) return errno;
-       return 0;
-#else
-       return pthread_join( thread, thread_return );
 #endif
+       return ERRVAL( pthread_join( thread, thread_return ) );
 }
 
 int 
 ldap_pvt_thread_kill( ldap_pvt_thread_t thread, int signo )
 {
-#if ( HAVE_PTHREAD_KILL && HAVE_PTHREADS > 6 )
+#if defined(HAVE_PTHREAD_KILL) && HAVE_PTHREADS > 4
        /* MacOS 10.1 is detected as v10 but has no pthread_kill() */
-       return pthread_kill( thread, signo );
-#elif ( HAVE_PTHREAD_KILL && HAVE_PTHREADS > 4 )
-       if ( pthread_kill( thread, signo ) < 0 ) return errno;
-       return 0;
+       return ERRVAL( pthread_kill( thread, signo ) );
 #else
        /* pthread package with DCE */
        if (kill( getpid(), signo )<0)
@@ -223,7 +222,8 @@ ldap_pvt_thread_yield( void )
        select( 0, NULL, NULL, NULL, &tv );
 #endif
        return 0;
-#elif HAVE_THR_YIELD
+
+#elif defined(HAVE_THR_YIELD)
        thr_yield();
        return 0;
 
@@ -237,6 +237,7 @@ ldap_pvt_thread_yield( void )
 #elif HAVE_PTHREADS == 6
        pthread_yield(NULL);
        return 0;
+
 #else
        pthread_yield();
        return 0;
@@ -246,114 +247,64 @@ ldap_pvt_thread_yield( void )
 int 
 ldap_pvt_thread_cond_init( ldap_pvt_thread_cond_t *cond )
 {
-#if HAVE_PTHREADS < 7
-       if ( pthread_cond_init( cond, LDAP_INT_THREAD_CONDATTR_DEFAULT ) < 0 )
-               return errno;
-       return 0;
-#else
-       return pthread_cond_init( cond, LDAP_INT_THREAD_CONDATTR_DEFAULT );
-#endif
+       return ERRVAL( pthread_cond_init(
+               cond, LDAP_INT_THREAD_CONDATTR_DEFAULT ) );
 }
 
 int 
 ldap_pvt_thread_cond_destroy( ldap_pvt_thread_cond_t *cond )
 {
-#if HAVE_PTHREADS < 7
-       if ( pthread_cond_destroy( cond ) < 0 ) return errno;
-       return 0;
-#else
-       return pthread_cond_destroy( cond );
-#endif
+       return ERRVAL( pthread_cond_destroy( cond ) );
 }
        
 int 
 ldap_pvt_thread_cond_signal( ldap_pvt_thread_cond_t *cond )
 {
-#if HAVE_PTHREADS < 7
-       if ( pthread_cond_signal( cond ) < 0 ) return errno;
-       return 0;
-#else
-       return pthread_cond_signal( cond );
-#endif
+       return ERRVAL( pthread_cond_signal( cond ) );
 }
 
 int
 ldap_pvt_thread_cond_broadcast( ldap_pvt_thread_cond_t *cond )
 {
-#if HAVE_PTHREADS < 7
-       if ( pthread_cond_broadcast( cond ) < 0 ) return errno;
-       return 0;
-#else
-       return pthread_cond_broadcast( cond );
-#endif
+       return ERRVAL( pthread_cond_broadcast( cond ) );
 }
 
 int 
 ldap_pvt_thread_cond_wait( ldap_pvt_thread_cond_t *cond, 
                      ldap_pvt_thread_mutex_t *mutex )
 {
-#if HAVE_PTHREADS < 7
-       if ( pthread_cond_wait( cond, mutex ) < 0 ) return errno;
-       return 0;
-#else
-       return pthread_cond_wait( cond, mutex );
-#endif
+       return ERRVAL( pthread_cond_wait( cond, mutex ) );
 }
 
 int 
 ldap_pvt_thread_mutex_init( ldap_pvt_thread_mutex_t *mutex )
 {
-#if HAVE_PTHREADS < 7
-       if ( pthread_mutex_init( mutex, LDAP_INT_THREAD_MUTEXATTR_DEFAULT )<0)
-               return errno;
-       return 0;
-#else
-       return pthread_mutex_init( mutex, LDAP_INT_THREAD_MUTEXATTR_DEFAULT );
-#endif
+       return ERRVAL( pthread_mutex_init(
+               mutex, LDAP_INT_THREAD_MUTEXATTR_DEFAULT ) );
 }
 
 int 
 ldap_pvt_thread_mutex_destroy( ldap_pvt_thread_mutex_t *mutex )
 {
-#if HAVE_PTHREADS < 7
-       if ( pthread_mutex_destroy( mutex ) < 0 ) return errno;
-       return 0;
-#else
-       return pthread_mutex_destroy( mutex );
-#endif
+       return ERRVAL( pthread_mutex_destroy( mutex ) );
 }
 
 int 
 ldap_pvt_thread_mutex_lock( ldap_pvt_thread_mutex_t *mutex )
 {
-#if HAVE_PTHREADS < 7
-       if ( pthread_mutex_lock( mutex ) < 0 ) return errno;
-       return 0;
-#else
-       return pthread_mutex_lock( mutex );
-#endif
+       return ERRVAL( pthread_mutex_lock( mutex ) );
 }
 
 int 
 ldap_pvt_thread_mutex_trylock( ldap_pvt_thread_mutex_t *mutex )
 {
-#if HAVE_PTHREADS < 7
-       if ( pthread_mutex_trylock( mutex ) < 0 ) return errno;
-       return 0;
-#else
-       return pthread_mutex_trylock( mutex );
-#endif
+       return ERRVAL( pthread_mutex_trylock( mutex ) );
 }
 
 int 
 ldap_pvt_thread_mutex_unlock( ldap_pvt_thread_mutex_t *mutex )
 {
-#if HAVE_PTHREADS < 7
-       if ( pthread_mutex_unlock( mutex ) < 0 ) return errno;
-       return 0;
-#else
-       return pthread_mutex_unlock( mutex );
-#endif
+       return ERRVAL( pthread_mutex_unlock( mutex ) );
 }
 
 ldap_pvt_thread_t ldap_pvt_thread_self( void )
@@ -366,83 +317,43 @@ ldap_pvt_thread_t ldap_pvt_thread_self( void )
 int 
 ldap_pvt_thread_rdwr_init( ldap_pvt_thread_rdwr_t *rw )
 {
-#if HAVE_PTHREADS < 7
-       if ( pthread_rwlock_init( rw, NULL ) < 0 ) return errno;
-       return 0;
-#else
-       return pthread_rwlock_init( rw, NULL );
-#endif
+       return ERRVAL( pthread_rwlock_init( rw, NULL ) );
 }
 
 int 
 ldap_pvt_thread_rdwr_destroy( ldap_pvt_thread_rdwr_t *rw )
 {
-#if HAVE_PTHREADS < 7
-       if ( pthread_rwlock_destroy( rw ) < 0 ) return errno;
-       return 0;
-#else
-       return pthread_rwlock_destroy( rw );
-#endif
+       return ERRVAL( pthread_rwlock_destroy( rw ) );
 }
 
 int ldap_pvt_thread_rdwr_rlock( ldap_pvt_thread_rdwr_t *rw )
 {
-#if HAVE_PTHREADS < 7
-       if ( pthread_rwlock_rdlock( rw ) < 0 ) return errno;
-       return 0;
-#else
-       return pthread_rwlock_rdlock( rw );
-#endif
+       return ERRVAL( pthread_rwlock_rdlock( rw ) );
 }
 
 int ldap_pvt_thread_rdwr_rtrylock( ldap_pvt_thread_rdwr_t *rw )
 {
-#if HAVE_PTHREADS < 7
-       if ( pthread_rwlock_tryrdlock( rw ) < 0 ) return errno;
-       return 0;
-#else
-       return pthread_rwlock_tryrdlock( rw );
-#endif
+       return ERRVAL( pthread_rwlock_tryrdlock( rw ) );
 }
 
 int ldap_pvt_thread_rdwr_runlock( ldap_pvt_thread_rdwr_t *rw )
 {
-#if HAVE_PTHREADS < 7
-       if ( pthread_rwlock_unlock( rw ) < 0 ) return errno;
-       return 0;
-#else
-       return pthread_rwlock_unlock( rw );
-#endif
+       return ERRVAL( pthread_rwlock_unlock( rw ) );
 }
 
 int ldap_pvt_thread_rdwr_wlock( ldap_pvt_thread_rdwr_t *rw )
 {
-#if HAVE_PTHREADS < 7
-       if ( pthread_rwlock_wrlock( rw ) < 0 ) return errno;
-       return 0;
-#else
-       return pthread_rwlock_wrlock( rw );
-#endif
+       return ERRVAL( pthread_rwlock_wrlock( rw ) );
 }
 
 int ldap_pvt_thread_rdwr_wtrylock( ldap_pvt_thread_rdwr_t *rw )
 {
-#if HAVE_PTHREADS < 7
-       if ( pthread_rwlock_trywrlock( rw ) < 0 ) return errno;
-       return 0;
-#else
-       return pthread_rwlock_trywrlock( rw );
-#endif
+       return ERRVAL( pthread_rwlock_trywrlock( rw ) );
 }
 
 int ldap_pvt_thread_rdwr_wunlock( ldap_pvt_thread_rdwr_t *rw )
 {
-#if HAVE_PTHREADS < 7
-       if ( pthread_rwlock_unlock( rw ) < 0 ) return errno;
-       return 0;
-#else
-       return pthread_rwlock_unlock( rw );
-#endif
+       return ERRVAL( pthread_rwlock_unlock( rw ) );
 }
 
 #endif /* HAVE_PTHREAD_RWLOCK_DESTROY */
index 1b18ff8fe0ec5d4708f0ff6e6408b60028f317b0..fa1d2ae4628058114f9d3098b1319e40ad6c8259 100644 (file)
 typedef enum ldap_int_thread_pool_state_e {
        LDAP_INT_THREAD_POOL_RUNNING,
        LDAP_INT_THREAD_POOL_FINISHING,
-       LDAP_INT_THREAD_POOL_STOPPING,
-       LDAP_INT_THREAD_POOL_PAUSING
+       LDAP_INT_THREAD_POOL_STOPPING
 } ldap_int_thread_pool_state_t;
 
+/* Thread-specific key with data and optional free function */
 typedef struct ldap_int_thread_key_s {
        void *ltk_key;
        void *ltk_data;
@@ -48,48 +48,76 @@ typedef struct ldap_int_thread_key_s {
  * We don't expect to use many...
  */
 #define        MAXKEYS 32
+
+/* Max number of threads */
 #define        LDAP_MAXTHR     1024    /* must be a power of 2 */
 
+/* Context: thread ID and thread-specific key/data pairs */
 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;
 
+/* Simple {thread ID -> context} hash table; key=ctx->ltu_id.
+ * Protected by ldap_pvt_thread_pool_mutex except during pauses,
+ * when it is read-only (used by pool_purgekey and pool_context).
+ * Protected by tpool->ltp_mutex during pauses.
+ */
 static struct {
-       ldap_pvt_thread_t id;
        ldap_int_thread_userctx_t *ctx;
+       /* ctx is valid when not NULL or DELETED_THREAD_CTX */
+#      define DELETED_THREAD_CTX (&ldap_int_main_thrctx + 1) /* dummy addr */
 } thread_keys[LDAP_MAXTHR];
-       
 
-typedef struct ldap_int_thread_ctx_s {
+#define        TID_HASH(tid, hash) do { \
+       unsigned const char *ptr_ = (unsigned const char *)&(tid); \
+       unsigned i_; \
+       for (i_ = 0, (hash) = ptr_[0]; ++i_ < sizeof(tid);) \
+               (hash) += ((hash) << 5) ^ ptr_[i_]; \
+} while(0)
+
+
+/* Task for a thread to perform */
+typedef struct ldap_int_thread_task_s {
        union {
-       LDAP_STAILQ_ENTRY(ldap_int_thread_ctx_s) q;
-       LDAP_SLIST_ENTRY(ldap_int_thread_ctx_s) l;
-       LDAP_SLIST_ENTRY(ldap_int_thread_ctx_s) al;
-       } ltc_next;
-       ldap_pvt_thread_start_t *ltc_start_routine;
-       void *ltc_arg;
-} ldap_int_thread_ctx_t;
+               LDAP_STAILQ_ENTRY(ldap_int_thread_task_s) q;
+               LDAP_SLIST_ENTRY(ldap_int_thread_task_s) l;
+       } ltt_next;
+       ldap_pvt_thread_start_t *ltt_start_routine;
+       void *ltt_arg;
+} ldap_int_thread_task_t;
 
 struct ldap_int_thread_pool_s {
        LDAP_STAILQ_ENTRY(ldap_int_thread_pool_s) ltp_next;
+
+       /* protect members below, and protect thread_keys[] during pauses */
        ldap_pvt_thread_mutex_t ltp_mutex;
+
+       /* not paused and something to do for pool_<wrapper/pause/destroy>() */
        ldap_pvt_thread_cond_t ltp_cond;
+
+       /* ltp_active_count <= 1 && ltp_pause */
        ldap_pvt_thread_cond_t ltp_pcond;
-       LDAP_STAILQ_HEAD(tcq, ldap_int_thread_ctx_s) ltp_pending_list;
-       LDAP_SLIST_HEAD(tcl, ldap_int_thread_ctx_s) ltp_free_list;
-       LDAP_SLIST_HEAD(tclq, ldap_int_thread_ctx_s) ltp_active_list;
+
+       /* pending tasks, and unused task objects */
+       LDAP_STAILQ_HEAD(tcq, ldap_int_thread_task_s) ltp_pending_list;
+       LDAP_SLIST_HEAD(tcl, ldap_int_thread_task_s) ltp_free_list;
+
        ldap_int_thread_pool_state_t ltp_state;
-       long ltp_max_count;
-       long ltp_max_pending;
-       long ltp_pending_count;
-       long ltp_active_count;
-       long ltp_open_count;
-       long ltp_starting;
+
+       /* some active request needs to be the sole active request */
+       int ltp_pause;
+
+       long ltp_max_count;                     /* max number of threads in pool, or 0 */
+       long ltp_max_pending;           /* max pending or paused requests, or 0 */
+       long ltp_pending_count;         /* pending or paused requests */
+       long ltp_active_count;          /* active, not paused requests */
+       long ltp_open_count;            /* number of threads */
+       long ltp_starting;                      /* currenlty starting threads */
 };
 
+static int ldap_int_has_thread_pool = 0;
 static LDAP_STAILQ_HEAD(tpq, ldap_int_thread_pool_s)
        ldap_int_thread_pool_list =
        LDAP_STAILQ_HEAD_INITIALIZER(ldap_int_thread_pool_list);
@@ -98,16 +126,13 @@ static ldap_pvt_thread_mutex_t ldap_pvt_thread_pool_mutex;
 
 static void *ldap_int_thread_pool_wrapper( void *pool );
 
-static ldap_pvt_thread_t ldap_int_main_tid;
-
+/* Context of the main thread */
 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;
-
+       ldap_int_main_thrctx.ltu_id = ldap_pvt_thread_self();
        return ldap_pvt_thread_mutex_init(&ldap_pvt_thread_pool_mutex);
 }
 
@@ -123,131 +148,8 @@ ldap_int_thread_pool_shutdown ( void )
        return(0);
 }
 
-typedef struct ldap_lazy_sem_t {
-       ldap_pvt_thread_mutex_t ls_mutex;
-       ldap_pvt_thread_cond_t  ls_cond;
-       int ls_sem_value;
-       /*
-        * when more than ls_lazy_count number of resources
-        * becmoes available, the thread wating for the resources will
-        * be waken up in order to prevent frequent blocking/waking-up
-        */
-       unsigned int ls_lazy_count;
-       /*
-        * only one thread(listener) will wait on this semaphore
-        * using a flag instead of a list
-        */
-       int ls_wait;
-} ldap_lazy_sem_t;
-
-ldap_lazy_sem_t* thread_pool_sem = NULL;
-
-int
-ldap_lazy_sem_init( unsigned int value, unsigned int lazyness )
-{
-       thread_pool_sem = (ldap_lazy_sem_t*) LDAP_CALLOC(1,
-               sizeof( ldap_lazy_sem_t ));
-
-       if( thread_pool_sem == NULL ) return -1;
-
-       ldap_pvt_thread_mutex_init( &thread_pool_sem->ls_mutex );
-       ldap_pvt_thread_cond_init( &thread_pool_sem->ls_cond );
-       thread_pool_sem->ls_sem_value = value;
-       thread_pool_sem->ls_lazy_count = lazyness;
-       thread_pool_sem->ls_wait = 0;
-
-       return 0;
-}
-
-/* FIXME: move to some approprite header */
-int ldap_lazy_sem_dec( ldap_lazy_sem_t* ls );
-int ldap_lazy_sem_wait ( ldap_lazy_sem_t* ls );
-
-/*
- * ldap_lazy_sem_wait is used if a caller is blockable(listener).
- * Otherwise use ldap_lazy_sem_dec (worker)
- */
-int
-ldap_lazy_sem_op_submit( ldap_lazy_sem_t* ls )
-{
-       if ( ls == NULL ) return -1;
-
-       /* only worker thread has its thread ctx */
-       if ( ldap_pvt_thread_pool_context() ) {
-               /* worker thread */
-               return ldap_lazy_sem_dec( ls );
-       } else {
-               /* listener */
-               return ldap_lazy_sem_wait( ls );
-       }
-}
-
-/*
- * test if given semaphore's count is zero.
- * If 0, the caller is blocked 
- * If not, the count is decremented.
- */
-int
-ldap_lazy_sem_wait ( ldap_lazy_sem_t* ls )
-{
-       ldap_pvt_thread_mutex_lock( &ls->ls_mutex );
-
-lazy_sem_retry:
-       if ( ls->ls_sem_value <= 0 ) {
-               /* no more avaliable resources */
-               ls->ls_wait = 1;
-               ldap_pvt_thread_cond_wait( &ls->ls_cond, &ls->ls_mutex );
-               goto lazy_sem_retry;
-       } else {
-               /* avaliable resources */
-               ls->ls_sem_value--;
-       }
-
-       ldap_pvt_thread_mutex_unlock( &ls->ls_mutex );
-
-       return 0;
-}
-
-/*
- * decrement the count without blocking
- * even when the count becomes less than or equal to 0
- */
-int
-ldap_lazy_sem_dec( ldap_lazy_sem_t* ls )
-{
-       ldap_pvt_thread_mutex_lock( &ls->ls_mutex );
-
-       ls->ls_sem_value--;
-
-       ldap_pvt_thread_mutex_unlock( &ls->ls_mutex );
-
-       return 0;
-}
-
-/*
- * Increment the count by one and test if it is greater or
- * equal to lazyness. If it is, wake up a blocked thread.
- */
-int
-ldap_lazy_sem_post( ldap_lazy_sem_t* ls )
-{
-       if( ls == NULL ) return (-1);
-
-       ldap_pvt_thread_mutex_lock( &ls->ls_mutex );
-
-       ls->ls_sem_value++;
-       if ( ls->ls_wait ) {
-               if ( ls->ls_sem_value >= ls->ls_lazy_count ) {
-                       ls->ls_wait = 0;
-                       ldap_pvt_thread_cond_signal( &ls->ls_cond );
-               }
-       }
-
-       ldap_pvt_thread_mutex_unlock( &ls->ls_mutex );
-
-       return 0;
-}
 
+/* Create a thread pool */
 int
 ldap_pvt_thread_pool_init (
        ldap_pvt_thread_pool_t *tpool,
@@ -257,6 +159,14 @@ ldap_pvt_thread_pool_init (
        ldap_pvt_thread_pool_t pool;
        int rc;
 
+       /* multiple pools are currently not supported (ITS#4943) */
+       assert(!ldap_int_has_thread_pool);
+
+       if (! (0 <= max_threads && max_threads <= LDAP_MAXTHR))
+               max_threads = 0;
+       if (max_pending < 0)
+               max_pending = 0;
+
        *tpool = NULL;
        pool = (ldap_pvt_thread_pool_t) LDAP_CALLOC(1,
                sizeof(struct ldap_int_thread_pool_s));
@@ -272,12 +182,13 @@ ldap_pvt_thread_pool_init (
        rc = ldap_pvt_thread_cond_init(&pool->ltp_pcond);
        if (rc != 0)
                return(rc);
+
+       ldap_int_has_thread_pool = 1;
        pool->ltp_state = LDAP_INT_THREAD_POOL_RUNNING;
        pool->ltp_max_count = max_threads;
        pool->ltp_max_pending = max_pending;
        LDAP_STAILQ_INIT(&pool->ltp_pending_list);
        LDAP_SLIST_INIT(&pool->ltp_free_list);
-       LDAP_SLIST_INIT(&pool->ltp_active_list);
        ldap_pvt_thread_mutex_lock(&ldap_pvt_thread_pool_mutex);
        LDAP_STAILQ_INSERT_TAIL(&ldap_int_thread_pool_list, pool, ltp_next);
        ldap_pvt_thread_mutex_unlock(&ldap_pvt_thread_pool_mutex);
@@ -307,6 +218,7 @@ ldap_pvt_thread_pool_init (
                ldap_pvt_thread_mutex_lock(&ldap_pvt_thread_pool_mutex);
                LDAP_STAILQ_REMOVE(ldap_int_thread_pool_list, pool, 
                        ldap_int_thread_pool_s, ltp_next);
+               ldap_int_has_thread_pool = 0;
                ldap_pvt_thread_mutex_unlock(&ldap_pvt_thread_pool_mutex);
                ldap_pvt_thread_cond_destroy(&pool->ltp_pcond);
                ldap_pvt_thread_cond_destroy(&pool->ltp_cond);
@@ -320,18 +232,15 @@ ldap_pvt_thread_pool_init (
        return(0);
 }
 
-#define        TID_HASH(tid, hash) do { unsigned i; \
-       unsigned char *ptr = (unsigned char *)&(tid); \
-       for (i=0, hash=0; i<sizeof(tid); i++) hash += ptr[i]; } while(0)
 
+/* Submit a task to be performed by the thread pool */
 int
 ldap_pvt_thread_pool_submit (
        ldap_pvt_thread_pool_t *tpool,
        ldap_pvt_thread_start_t *start_routine, void *arg )
 {
        struct ldap_int_thread_pool_s *pool;
-       ldap_int_thread_ctx_t *ctx;
-       int need_thread = 0;
+       ldap_int_thread_task_t *task;
        ldap_pvt_thread_t thr;
 
        if (tpool == NULL)
@@ -343,112 +252,95 @@ ldap_pvt_thread_pool_submit (
                return(-1);
 
        ldap_pvt_thread_mutex_lock(&pool->ltp_mutex);
-       if ((pool->ltp_state != LDAP_INT_THREAD_POOL_RUNNING &&
-               pool->ltp_state != LDAP_INT_THREAD_POOL_PAUSING)
-               || (pool->ltp_max_pending > 0
+       if (pool->ltp_state != LDAP_INT_THREAD_POOL_RUNNING
+               || (pool->ltp_max_pending
                        && pool->ltp_pending_count >= pool->ltp_max_pending))
        {
                ldap_pvt_thread_mutex_unlock(&pool->ltp_mutex);
                return(-1);
        }
-       ctx = LDAP_SLIST_FIRST(&pool->ltp_free_list);
-       if (ctx) {
-               LDAP_SLIST_REMOVE_HEAD(&pool->ltp_free_list, ltc_next.l);
+
+       task = LDAP_SLIST_FIRST(&pool->ltp_free_list);
+       if (task) {
+               LDAP_SLIST_REMOVE_HEAD(&pool->ltp_free_list, ltt_next.l);
        } else {
-               ctx = (ldap_int_thread_ctx_t *) LDAP_MALLOC(
-                       sizeof(ldap_int_thread_ctx_t));
-               if (ctx == NULL) {
+               task = (ldap_int_thread_task_t *) LDAP_MALLOC(sizeof(*task));
+               if (task == NULL) {
                        ldap_pvt_thread_mutex_unlock(&pool->ltp_mutex);
                        return(-1);
                }
        }
 
-       ctx->ltc_start_routine = start_routine;
-       ctx->ltc_arg = arg;
+       task->ltt_start_routine = start_routine;
+       task->ltt_arg = arg;
 
        pool->ltp_pending_count++;
-       LDAP_STAILQ_INSERT_TAIL(&pool->ltp_pending_list, ctx, ltc_next.q);
-       if (pool->ltp_state == LDAP_INT_THREAD_POOL_PAUSING) {
+       LDAP_STAILQ_INSERT_TAIL(&pool->ltp_pending_list, task, ltt_next.q);
+       if (pool->ltp_pause) {
                ldap_pvt_thread_mutex_unlock(&pool->ltp_mutex);
                return(0);
        }
        ldap_pvt_thread_cond_signal(&pool->ltp_cond);
        if (pool->ltp_open_count < pool->ltp_active_count + pool->ltp_pending_count
-               && (pool->ltp_open_count < pool->ltp_max_count ||
-                       pool->ltp_max_count <= 0 ))
+               && (pool->ltp_open_count <
+                       (pool->ltp_max_count ? pool->ltp_max_count : LDAP_MAXTHR)))
        {
                pool->ltp_open_count++;
                pool->ltp_starting++;
-               need_thread = 1;
-       }
-       ldap_pvt_thread_mutex_unlock(&pool->ltp_mutex);
-
-#ifdef LDAP_PVT_THREAD_POOL_SEM_LOAD_CONTROL
-       ldap_lazy_sem_op_submit( thread_pool_sem );
-#endif
-
-       if (need_thread) {
-               int rc;
-
-               ldap_pvt_thread_mutex_lock(&pool->ltp_mutex);
-
-               rc = ldap_pvt_thread_create( &thr, 1,
-                       ldap_int_thread_pool_wrapper, pool );
-               if (rc == 0) {
-                       int hash;
-                       pool->ltp_starting--;
-
-                       /* assign this thread ID to a key slot; start
-                        * at the thread ID itself (mod LDAP_MAXTHR) and
-                        * look for an empty slot.
-                        */
-                       TID_HASH(thr, hash);
-                       for (rc = hash & (LDAP_MAXTHR-1);
-                               !ldap_pvt_thread_equal(thread_keys[rc].id, tid_zero);
-                               rc = (rc+1) & (LDAP_MAXTHR-1));
-                       thread_keys[rc].id = thr;
-               } else {
+               if (0 != ldap_pvt_thread_create(
+                       &thr, 1, ldap_int_thread_pool_wrapper, pool))
+               {
                        /* couldn't create thread.  back out of
                         * ltp_open_count and check for even worse things.
                         */
-                       pool->ltp_open_count--;
                        pool->ltp_starting--;
+                       pool->ltp_open_count--;
                        if (pool->ltp_open_count == 0) {
                                /* no open threads at all?!?
                                 */
-                               ldap_int_thread_ctx_t *ptr;
-                               LDAP_STAILQ_FOREACH(ptr, &pool->ltp_pending_list, ltc_next.q)
-                                       if (ptr == ctx) break;
-                               if (ptr == ctx) {
-                                       /* no open threads, context not handled, so
-                                        * back out of ltp_pending_count, free the context,
+                               ldap_int_thread_task_t *ptr;
+
+                               /* let pool_destroy know there are no more threads */
+                               ldap_pvt_thread_cond_signal(&pool->ltp_cond);
+
+                               LDAP_STAILQ_FOREACH(ptr, &pool->ltp_pending_list, ltt_next.q)
+                                       if (ptr == task) break;
+                               if (ptr == task) {
+                                       /* no open threads, task not handled, so
+                                        * back out of ltp_pending_count, free the task,
                                         * report the error.
                                         */
-                                       LDAP_STAILQ_REMOVE(&pool->ltp_pending_list, ctx, 
-                                               ldap_int_thread_ctx_s, ltc_next.q);
-                                       pool->ltp_pending_count++;
+                                       LDAP_STAILQ_REMOVE(&pool->ltp_pending_list, task,
+                                               ldap_int_thread_task_s, ltt_next.q);
+                                       pool->ltp_pending_count--;
                                        ldap_pvt_thread_mutex_unlock(&pool->ltp_mutex);
-                                       LDAP_FREE(ctx);
+                                       LDAP_FREE(task);
                                        return(-1);
                                }
                        }
                        /* there is another open thread, so this
-                        * context will be handled eventually.
-                        * continue on and signal that the context
-                        * is waiting.
+                        * task will be handled eventually.
+                        * continue on, we have signalled that
+                        * the task is waiting.
                         */
                }
-               ldap_pvt_thread_mutex_unlock(&pool->ltp_mutex);
        }
 
+       ldap_pvt_thread_mutex_unlock(&pool->ltp_mutex);
        return(0);
 }
 
+/* Set max #threads.  value <= 0 means max supported #threads (LDAP_MAXTHR) */
 int
-ldap_pvt_thread_pool_maxthreads ( ldap_pvt_thread_pool_t *tpool, int max_threads )
+ldap_pvt_thread_pool_maxthreads(
+       ldap_pvt_thread_pool_t *tpool,
+       int max_threads )
 {
        struct ldap_int_thread_pool_s *pool;
 
+       if (! (0 <= max_threads && max_threads <= LDAP_MAXTHR))
+               max_threads = 0;
+
        if (tpool == NULL)
                return(-1);
 
@@ -463,8 +355,12 @@ ldap_pvt_thread_pool_maxthreads ( ldap_pvt_thread_pool_t *tpool, int max_threads
        return(0);
 }
 
+/* Inspect the pool */
 int
-ldap_pvt_thread_pool_query ( ldap_pvt_thread_pool_t *tpool, ldap_pvt_thread_pool_param_t param, void *value )
+ldap_pvt_thread_pool_query(
+       ldap_pvt_thread_pool_t *tpool,
+       ldap_pvt_thread_pool_param_t param,
+       void *value )
 {
        struct ldap_int_thread_pool_s   *pool;
        int                             count = -1;
@@ -526,21 +422,27 @@ ldap_pvt_thread_pool_query ( ldap_pvt_thread_pool_t *tpool, ldap_pvt_thread_pool
                        { "running",    LDAP_INT_THREAD_POOL_RUNNING },
                        { "finishing",  LDAP_INT_THREAD_POOL_FINISHING },
                        { "stopping",   LDAP_INT_THREAD_POOL_STOPPING },
-                       { "pausing",    LDAP_INT_THREAD_POOL_PAUSING },
                        { NULL }
                };
                int             i;
 
-               for ( i = 0; str2state[ i ].name != NULL; i++ ) {
-                       if ( str2state[ i ].state == pool->ltp_state ) {
-                               break;
+               if ( pool->ltp_pause ) {
+                       *((char **)value) = "pausing";
+               } else {
+                       for ( i = 0; str2state[ i ].name != NULL; i++ ) {
+                               if ( str2state[ i ].state == pool->ltp_state ) {
+                                       break;
+                               }
                        }
+                       *((char **)value) = str2state[ i ].name;
                }
-               *((char **)value) = str2state[ i ].name;
-               if ( str2state[ i ].name != NULL ) {
+               if ( *((char **)value) != NULL ) {
                        count = -2;
                }
                } break;
+
+       case LDAP_PVT_THREAD_POOL_PARAM_UNKNOWN:
+               break;
        }
        ldap_pvt_thread_mutex_unlock( &pool->ltp_mutex );
 
@@ -570,11 +472,12 @@ ldap_pvt_thread_pool_backload ( ldap_pvt_thread_pool_t *tpool )
        return rc;
 }
 
+/* Destroy the pool after making its threads finish */
 int
 ldap_pvt_thread_pool_destroy ( ldap_pvt_thread_pool_t *tpool, int run_pending )
 {
        struct ldap_int_thread_pool_s *pool, *pptr;
-       ldap_int_thread_ctx_t *ctx;
+       ldap_int_thread_task_t *task;
 
        if (tpool == NULL)
                return(-1);
@@ -598,73 +501,85 @@ ldap_pvt_thread_pool_destroy ( ldap_pvt_thread_pool_t *tpool, int run_pending )
                ? LDAP_INT_THREAD_POOL_FINISHING
                : LDAP_INT_THREAD_POOL_STOPPING;
 
-       if ( pool->ltp_open_count ) {
-               ldap_pvt_thread_cond_broadcast(&pool->ltp_cond);
+       while (pool->ltp_open_count) {
+               if (!pool->ltp_pause)
+                       ldap_pvt_thread_cond_broadcast(&pool->ltp_cond);
                ldap_pvt_thread_cond_wait(&pool->ltp_cond, &pool->ltp_mutex);
        }
        ldap_pvt_thread_mutex_unlock(&pool->ltp_mutex);
 
-       while ((ctx = LDAP_STAILQ_FIRST(&pool->ltp_pending_list)) != NULL)
+       while ((task = LDAP_STAILQ_FIRST(&pool->ltp_pending_list)) != NULL)
        {
-               LDAP_STAILQ_REMOVE_HEAD(&pool->ltp_pending_list, ltc_next.q);
-               LDAP_FREE(ctx);
+               LDAP_STAILQ_REMOVE_HEAD(&pool->ltp_pending_list, ltt_next.q);
+               LDAP_FREE(task);
        }
 
-       while ((ctx = LDAP_SLIST_FIRST(&pool->ltp_free_list)) != NULL)
+       while ((task = LDAP_SLIST_FIRST(&pool->ltp_free_list)) != NULL)
        {
-               LDAP_SLIST_REMOVE_HEAD(&pool->ltp_free_list, ltc_next.l);
-               LDAP_FREE(ctx);
+               LDAP_SLIST_REMOVE_HEAD(&pool->ltp_free_list, ltt_next.l);
+               LDAP_FREE(task);
        }
 
        ldap_pvt_thread_cond_destroy(&pool->ltp_pcond);
        ldap_pvt_thread_cond_destroy(&pool->ltp_cond);
        ldap_pvt_thread_mutex_destroy(&pool->ltp_mutex);
        LDAP_FREE(pool);
-#ifdef LDAP_PVT_THREAD_POOL_SEM_LOAD_CONTROL
-       if ( thread_pool_sem ) {
-               LDAP_FREE( thread_pool_sem );
-       }
-#endif
+       ldap_int_has_thread_pool = 0;
        return(0);
 }
 
+/* Thread loop.  Accept and handle submitted tasks. */
 static void *
 ldap_int_thread_pool_wrapper ( 
        void *xpool )
 {
        struct ldap_int_thread_pool_s *pool = xpool;
-       ldap_int_thread_ctx_t *ctx;
-       ldap_int_thread_userctx_t uctx;
-       int i, keyslot, hash;
+       ldap_int_thread_task_t *task;
+       ldap_int_thread_userctx_t ctx, *kctx;
+       unsigned i, keyslot, hash;
 
-       if (pool == NULL)
-               return NULL;
+       assert(pool != NULL);
 
        for ( i=0; i<MAXKEYS; i++ ) {
-               uctx.ltu_key[i].ltk_key = NULL;
+               ctx.ltu_key[i].ltk_key = NULL;
        }
 
-       uctx.ltu_id = ldap_pvt_thread_self();
+       ctx.ltu_id = ldap_pvt_thread_self();
+       TID_HASH(ctx.ltu_id, hash);
 
        ldap_pvt_thread_mutex_lock(&pool->ltp_mutex);
 
-       /* store pointer to our keys */
-       TID_HASH(uctx.ltu_id, hash);
-       for (i = hash & (LDAP_MAXTHR-1);
-                               !ldap_pvt_thread_equal(thread_keys[i].id, uctx.ltu_id);
-                               i = (i+1) & (LDAP_MAXTHR-1));
-       thread_keys[i].ctx = &uctx;
-       keyslot = i;
-
-       while (pool->ltp_state != LDAP_INT_THREAD_POOL_STOPPING) {
-               ctx = LDAP_STAILQ_FIRST(&pool->ltp_pending_list);
-               if (ctx) {
-                       LDAP_STAILQ_REMOVE_HEAD(&pool->ltp_pending_list, ltc_next.q);
-               } else {
+       /* thread_keys[] is read-only when paused */
+       while (pool->ltp_pause)
+               ldap_pvt_thread_cond_wait(&pool->ltp_cond, &pool->ltp_mutex);
+
+       /* find a key slot to give this thread ID and store a
+        * pointer to our keys there; start at the thread ID
+        * itself (mod LDAP_MAXTHR) and look for an empty slot.
+        */
+       ldap_pvt_thread_mutex_lock(&ldap_pvt_thread_pool_mutex);
+       for (keyslot = hash & (LDAP_MAXTHR-1);
+               (kctx = thread_keys[keyslot].ctx) && kctx != DELETED_THREAD_CTX;
+               keyslot = (keyslot+1) & (LDAP_MAXTHR-1));
+       thread_keys[keyslot].ctx = &ctx;
+       ldap_pvt_thread_mutex_unlock(&ldap_pvt_thread_pool_mutex);
+
+       pool->ltp_starting--;
+
+       for (;;) {
+               while (pool->ltp_pause)
+                       ldap_pvt_thread_cond_wait(&pool->ltp_cond, &pool->ltp_mutex);
+
+               if (pool->ltp_state == LDAP_INT_THREAD_POOL_STOPPING)
+                       break;
+
+               task = LDAP_STAILQ_FIRST(&pool->ltp_pending_list);
+               if (task == NULL) {
                        if (pool->ltp_state == LDAP_INT_THREAD_POOL_FINISHING)
                                break;
-                       if (pool->ltp_max_count > 0
-                               && pool->ltp_open_count > pool->ltp_max_count)
+
+                       if (pool->ltp_open_count >
+                               (pool->ltp_max_count ? pool->ltp_max_count : LDAP_MAXTHR))
                        {
                                /* too many threads running (can happen if the
                                 * maximum threads value is set during ongoing
@@ -680,53 +595,41 @@ ldap_int_thread_pool_wrapper (
                         * always have at least one thread open).  the check
                         * should be like this:
                         *   if (pool->ltp_open_count > 1 && pool->ltp_starting == 0)
-                        *       check timer, leave thread (break;)
+                        *       check timer, wait if ltp_pause, leave thread (break;)
                         *
                         * Just use pthread_cond_timedwait if we want to
                         * check idle time.
                         */
 
-                       if (pool->ltp_state == LDAP_INT_THREAD_POOL_RUNNING
-                               || pool->ltp_state == LDAP_INT_THREAD_POOL_PAUSING)
-                       {
-                               ldap_pvt_thread_cond_wait(&pool->ltp_cond, &pool->ltp_mutex);
-                       }
-
+                       assert(pool->ltp_state == LDAP_INT_THREAD_POOL_RUNNING);
+                       ldap_pvt_thread_cond_wait(&pool->ltp_cond, &pool->ltp_mutex);
                        continue;
                }
 
+               LDAP_STAILQ_REMOVE_HEAD(&pool->ltp_pending_list, ltt_next.q);
                pool->ltp_pending_count--;
-
-               LDAP_SLIST_INSERT_HEAD(&pool->ltp_active_list, ctx, ltc_next.al);
                pool->ltp_active_count++;
                ldap_pvt_thread_mutex_unlock(&pool->ltp_mutex);
 
-               ctx->ltc_start_routine(&uctx, ctx->ltc_arg);
+               task->ltt_start_routine(&ctx, task->ltt_arg);
 
-#ifdef LDAP_PVT_THREAD_POOL_SEM_LOAD_CONTROL
-               ldap_lazy_sem_post( thread_pool_sem );
-#endif
                ldap_pvt_thread_mutex_lock(&pool->ltp_mutex);
-               LDAP_SLIST_REMOVE(&pool->ltp_active_list, ctx,
-                       ldap_int_thread_ctx_s, ltc_next.al);
-               LDAP_SLIST_INSERT_HEAD(&pool->ltp_free_list, ctx, ltc_next.l);
+               LDAP_SLIST_INSERT_HEAD(&pool->ltp_free_list, task, ltt_next.l);
                pool->ltp_active_count--;
-
-               if (pool->ltp_state == LDAP_INT_THREAD_POOL_PAUSING) {
-                       if (pool->ltp_active_count < 2) {
-                               ldap_pvt_thread_cond_signal(&pool->ltp_pcond);
-                       }
-                       ldap_pvt_thread_cond_wait(&pool->ltp_cond, &pool->ltp_mutex);
-               }
+               /* let pool_pause know when it is the sole active thread */
+               if (pool->ltp_active_count < 2)
+                       ldap_pvt_thread_cond_signal(&pool->ltp_pcond);
        }
 
-       ldap_pvt_thread_pool_context_reset(&uctx);
+       /* The ltp_mutex lock protects ctx->ltu_key from pool_purgekey()
+        * during this call, since it prevents new pauses. */
+       ldap_pvt_thread_pool_context_reset(&ctx);
 
-       thread_keys[keyslot].ctx = NULL;
-       thread_keys[keyslot].id = tid_zero;
+       ldap_pvt_thread_mutex_lock(&ldap_pvt_thread_pool_mutex);
+       thread_keys[keyslot].ctx = DELETED_THREAD_CTX;
+       ldap_pvt_thread_mutex_unlock(&ldap_pvt_thread_pool_mutex);
 
        pool->ltp_open_count--;
-
        /* let pool_destroy know we're all done */
        if (pool->ltp_open_count < 1)
                ldap_pvt_thread_cond_signal(&pool->ltp_cond);
@@ -737,6 +640,7 @@ ldap_int_thread_pool_wrapper (
        return(NULL);
 }
 
+/* Pause the pool.  Return when all other threads are paused. */
 int
 ldap_pvt_thread_pool_pause ( 
        ldap_pvt_thread_pool_t *tpool )
@@ -754,22 +658,30 @@ ldap_pvt_thread_pool_pause (
        ldap_pvt_thread_mutex_lock(&pool->ltp_mutex);
 
        /* If someone else has already requested a pause, we have to wait */
-       while (pool->ltp_state == LDAP_INT_THREAD_POOL_PAUSING) {
+       if (pool->ltp_pause) {
                pool->ltp_pending_count++;
                pool->ltp_active_count--;
-               ldap_pvt_thread_cond_wait(&pool->ltp_cond, &pool->ltp_mutex);
+               /* let the other pool_pause() know when it can proceed */
+               if (pool->ltp_active_count < 2)
+                       ldap_pvt_thread_cond_signal(&pool->ltp_pcond);
+               do {
+                       ldap_pvt_thread_cond_wait(&pool->ltp_cond, &pool->ltp_mutex);
+               } while (pool->ltp_pause);
                pool->ltp_pending_count--;
                pool->ltp_active_count++;
        }
-       /* Wait for everyone else to finish */
-       pool->ltp_state = LDAP_INT_THREAD_POOL_PAUSING;
+
+       /* Wait for everyone else to pause or finish */
+       pool->ltp_pause = 1;
        while (pool->ltp_active_count > 1) {
                ldap_pvt_thread_cond_wait(&pool->ltp_pcond, &pool->ltp_mutex);
        }
+
        ldap_pvt_thread_mutex_unlock(&pool->ltp_mutex);
        return(0);
 }
 
+/* End a pause */
 int
 ldap_pvt_thread_pool_resume ( 
        ldap_pvt_thread_pool_t *tpool )
@@ -785,13 +697,15 @@ ldap_pvt_thread_pool_resume (
                return(0);
 
        ldap_pvt_thread_mutex_lock(&pool->ltp_mutex);
-
-       pool->ltp_state = LDAP_INT_THREAD_POOL_RUNNING;
+       pool->ltp_pause = 0;
        ldap_pvt_thread_cond_broadcast(&pool->ltp_cond);
        ldap_pvt_thread_mutex_unlock(&pool->ltp_mutex);
        return(0);
 }
 
+/*
+ * Get the key's data and optionally free function in the given context.
+ */
 int ldap_pvt_thread_pool_getkey(
        void *xctx,
        void *key,
@@ -801,7 +715,7 @@ int ldap_pvt_thread_pool_getkey(
        ldap_int_thread_userctx_t *ctx = xctx;
        int i;
 
-       if ( !ctx || !data ) return EINVAL;
+       if ( !ctx || !key || !data ) return EINVAL;
 
        for ( i=0; i<MAXKEYS && ctx->ltu_key[i].ltk_key; i++ ) {
                if ( ctx->ltu_key[i].ltk_key == key ) {
@@ -813,6 +727,23 @@ int ldap_pvt_thread_pool_getkey(
        return ENOENT;
 }
 
+static void
+clear_key_idx( ldap_int_thread_userctx_t *ctx, int i )
+{
+       for ( ; i < MAXKEYS-1 && ctx->ltu_key[i+1].ltk_key; i++ )
+               ctx->ltu_key[i] = ctx->ltu_key[i+1];
+       ctx->ltu_key[i].ltk_key = NULL;
+}
+
+/*
+ * Set or remove data for the key in the given context.
+ * key can be any unique pointer.
+ * kfree() is an optional function to free the data (but not the key):
+ *   pool_context_reset() and pool_purgekey() call kfree(key, data),
+ *   but pool_setkey() does not.  For pool_setkey() it is the caller's
+ *   responsibility to free any existing data with the same key.
+ *   kfree() must not call functions taking a tpool argument.
+ */
 int ldap_pvt_thread_pool_setkey(
        void *xctx,
        void *key,
@@ -820,19 +751,30 @@ int ldap_pvt_thread_pool_setkey(
        ldap_pvt_thread_pool_keyfree_t *kfree )
 {
        ldap_int_thread_userctx_t *ctx = xctx;
-       int i;
+       int i, found;
 
        if ( !ctx || !key ) return EINVAL;
 
-       for ( i=0; i<MAXKEYS; i++ ) {
-               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;
+       for ( i=found=0; i<MAXKEYS; i++ ) {
+               if ( ctx->ltu_key[i].ltk_key == key ) {
+                       found = 1;
+                       break;
+               } else if ( !ctx->ltu_key[i].ltk_key ) {
+                       break;
                }
        }
-       return ENOMEM;
+
+       if ( data || kfree ) {
+               if ( i>=MAXKEYS )
+                       return ENOMEM;
+               ctx->ltu_key[i].ltk_key = key;
+               ctx->ltu_key[i].ltk_data = data;
+               ctx->ltu_key[i].ltk_free = kfree;
+       } else if ( found ) {
+               clear_key_idx( ctx, i );
+       }
+
+       return 0;
 }
 
 /* Free all elements with this key, no matter which thread they're in.
@@ -843,16 +785,17 @@ void ldap_pvt_thread_pool_purgekey( void *key )
        int i, j;
        ldap_int_thread_userctx_t *ctx;
 
+       assert ( key != NULL );
+
        for ( i=0; i<LDAP_MAXTHR; i++ ) {
-               if ( thread_keys[i].ctx ) {
-                       ctx = thread_keys[i].ctx;
-                       for ( j=0; j<MAXKEYS; j++ ) {
+               ctx = thread_keys[i].ctx;
+               if ( ctx && ctx != DELETED_THREAD_CTX ) {
+                       for ( j=0; j<MAXKEYS && ctx->ltu_key[j].ltk_key; j++ ) {
                                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;
+                                       clear_key_idx( ctx, j );
                                        break;
                                }
                        }
@@ -861,6 +804,7 @@ void ldap_pvt_thread_pool_purgekey( void *key )
 }
 
 /*
+ * Find the context of the current thread.
  * This is necessary if the caller does not have access to the
  * thread context handle (for example, a slapd plugin calling
  * slapi_search_internal()). No doubt it is more efficient
@@ -870,21 +814,35 @@ void ldap_pvt_thread_pool_purgekey( void *key )
 void *ldap_pvt_thread_pool_context( )
 {
        ldap_pvt_thread_t tid;
-       int i, hash;
+       unsigned i, hash;
+       ldap_int_thread_userctx_t *ctx;
 
        tid = ldap_pvt_thread_self();
-       if ( ldap_pvt_thread_equal( tid, ldap_int_main_tid ))
+       if ( ldap_pvt_thread_equal( tid, ldap_int_main_thrctx.ltu_id ))
                return &ldap_int_main_thrctx;
 
        TID_HASH( tid, hash );
-       for (i = hash & (LDAP_MAXTHR-1);
-               !ldap_pvt_thread_equal(thread_keys[i].id, tid_zero) &&
-               !ldap_pvt_thread_equal(thread_keys[i].id, tid);
-               i = (i+1) & (LDAP_MAXTHR-1));
+       i = hash &= (LDAP_MAXTHR-1);
+       ldap_pvt_thread_mutex_lock(&ldap_pvt_thread_pool_mutex);
+       do {
+               ctx = thread_keys[i].ctx;
+               if ( ctx == DELETED_THREAD_CTX )
+                       continue;
+               if ( !ctx || ldap_pvt_thread_equal(thread_keys[i].ctx->ltu_id, tid) )
+                       goto done;
+       } while ( (i = (i+1) & (LDAP_MAXTHR-1)) != hash );
+       ctx = NULL;
+ done:
+       ldap_pvt_thread_mutex_unlock(&ldap_pvt_thread_pool_mutex);
 
-       return thread_keys[i].ctx;
+       return ctx;
 }
 
+/*
+ * Free the context's keys.
+ * Must not call functions taking a tpool argument (because this
+ * thread already holds ltp_mutex when called from pool_wrapper()).
+ */
 void ldap_pvt_thread_pool_context_reset( void *vctx )
 {
        ldap_int_thread_userctx_t *ctx = vctx;
index 603c9ae2ae1fa393dddb8bb43a3e090869b5eaf4..eacd3fefec3572115af0c54d7d9f7c0f564545a1 100644 (file)
@@ -56,7 +56,7 @@ lutil_detach( int debug, int do_close )
 
 #ifdef HAVE_SYSCONF
        nbits = sysconf( _SC_OPEN_MAX );
-#elif HAVE_GETDTABLESIZE
+#elif defined(HAVE_GETDTABLESIZE)
        nbits = getdtablesize();
 #else
        nbits = FD_SETSIZE;
@@ -70,7 +70,7 @@ lutil_detach( int debug, int do_close )
 
        if ( debug == 0 ) {
                for ( i = 0; i < 5; i++ ) {
-#if HAVE_THR
+#ifdef HAVE_THR
                        switch ( fork1() )
 #else
                        switch ( fork() )
index a6cf7404fd517c3ded713a17b3323b1cbf92ef9c..607f36eeef33069bc9063a71b3342a98d2026776 100644 (file)
@@ -60,7 +60,7 @@
 char *
 lutil_getpass( const char *prompt )
 {
-#if !defined(HAVE_POSIX_TERMIOS) && !defined(HAVE_SGTTY_H)
+#if !defined(HAVE_TERMIOS_H) && !defined(HAVE_SGTTY_H)
        static char buf[256];
        int i, c;
 
index 97d87982abf19755b707a6eaedb30de47a9cf90a..a128423036d2f1ae495bce773e56b3334503c60b 100644 (file)
 #include <ucred.h>
 #endif
 
+#ifdef LDAP_PF_LOCAL_SENDMSG
+#include <lber.h>
+#ifdef HAVE_SYS_UIO_H
+#include <sys/uio.h>
+#endif
+#include <sys/stat.h>
+#endif
+
 #ifdef HAVE_SYS_UCRED_H
 #ifdef HAVE_GRP_H
 #include <grp.h>       /* for NGROUPS on Tru64 5.1 */
 #include <sys/ucred.h>
 #endif
 
-#if !defined(HAVE_GETPEERUCRED) && \
-       !defined(SO_PEERCRED) && !defined(LOCAL_PEERCRED) && \
-       defined(HAVE_SENDMSG) && (defined(HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTSLEN) || \
-               defined(HAVE_STRUCT_MSGHDR_MSG_CONTROL))
-#define DO_SENDMSG
-#ifdef HAVE_SYS_UIO_H
-#include <sys/uio.h>
-#endif
-#include <sys/stat.h>
-#endif
-
 #include <stdlib.h>
 
-
-int getpeereid( int s, uid_t *euid, gid_t *egid )
+int lutil_getpeereid( int s, uid_t *euid, gid_t *egid
+#ifdef LDAP_PF_LOCAL_SENDMSG
+       , struct berval *peerbv
+#endif
+       )
 {
 #ifdef LDAP_PF_LOCAL
 #if defined( HAVE_GETPEERUCRED )
@@ -62,7 +62,7 @@ int getpeereid( int s, uid_t *euid, gid_t *egid )
 
 #elif defined( SO_PEERCRED )
        struct ucred peercred;
-       socklen_t peercredlen = sizeof peercred;
+       ber_socklen_t peercredlen = sizeof peercred;
 
        if(( getsockopt( s, SOL_SOCKET, SO_PEERCRED,
                (void *)&peercred, &peercredlen ) == 0 )
@@ -75,7 +75,7 @@ int getpeereid( int s, uid_t *euid, gid_t *egid )
 
 #elif defined( LOCAL_PEERCRED )
        struct xucred peercred;
-       socklen_t peercredlen = sizeof peercred;
+       ber_socklen_t peercredlen = sizeof peercred;
 
        if(( getsockopt( s, LOCAL_PEERCRED, 1,
                (void *)&peercred, &peercredlen ) == 0 )
@@ -85,9 +85,8 @@ int getpeereid( int s, uid_t *euid, gid_t *egid )
                *egid = peercred.cr_gid;
                return 0;
        }
-#elif defined( DO_SENDMSG )
-       char dummy[8];
-       int err, fd[2];
+#elif defined( LDAP_PF_LOCAL_SENDMSG ) && defined( MSG_WAITALL )
+       int err, fd;
        struct iovec iov;
        struct msghdr msg = {0};
 # ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
@@ -97,52 +96,68 @@ int getpeereid( int s, uid_t *euid, gid_t *egid )
 # ifndef CMSG_LEN
 # define CMSG_LEN(len)         (_CMSG_ALIGN(sizeof(struct cmsghdr)) + (len))
 # endif
-       union {
+       struct {
                struct cmsghdr cm;
-               unsigned char control[CMSG_SPACE(sizeof(int))];
-       } control_un;
+               int fd;
+       } control_st;
        struct cmsghdr *cmsg;
 # endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
        struct stat st;
+       struct sockaddr_un lname, rname;
+       ber_socklen_t llen, rlen;
 
-       msg.msg_name = NULL;
-       msg.msg_namelen = 0;
+       rlen = sizeof(rname);
+       llen = sizeof(lname);
+       memset( &lname, 0, sizeof( lname ));
+       getsockname(s, (struct sockaddr *)&lname, &llen);
 
-       iov.iov_base = dummy;
-       iov.iov_len = sizeof dummy;
+       iov.iov_base = peerbv->bv_val;
+       iov.iov_len = peerbv->bv_len;
        msg.msg_iov = &iov;
        msg.msg_iovlen = 1;
+       peerbv->bv_len = 0;
+
 # ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
-       msg.msg_control = control_un.control;
-       msg.msg_controllen = sizeof( control_un.control );
+       msg.msg_control = &control_st;
+       msg.msg_controllen = sizeof( struct cmsghdr ) + sizeof( int );  /* no padding! */
 
        cmsg = CMSG_FIRSTHDR( &msg );
+# else
+       msg.msg_accrights = (char *)&fd;
+       msg.msg_accrightslen = sizeof(fd);
+# endif
 
        /*
         * AIX returns a bogus file descriptor if recvmsg() is
         * called with MSG_PEEK (is this a bug?). Hence we need
         * to receive the Abandon PDU.
         */
-       if( recvmsg( s, &msg, MSG_WAITALL ) >= 0 &&
+       err = recvmsg( s, &msg, MSG_WAITALL );
+       if( err >= 0 &&
+# ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
            cmsg->cmsg_len == CMSG_LEN( sizeof(int) ) &&
            cmsg->cmsg_level == SOL_SOCKET &&
-           cmsg->cmsg_type == SCM_RIGHTS )
+           cmsg->cmsg_type == SCM_RIGHTS
 # else
-       msg.msg_accrights = (char *)fd;
-       msg.msg_accrightslen = sizeof(fd);
-       if( recvmsg( s, &msg, MSG_PEEK) >= 0 && msg.msg_accrightslen == sizeof(int) )
+               msg.msg_accrightslen == sizeof(int)
 # endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL*/
-       {
+       ) {
+               int mode = S_IFIFO|S_ISUID|S_IRWXU;
+
                /* We must receive a valid descriptor, it must be a pipe,
-                * and it must only be accessible by its owner.
+                * it must only be accessible by its owner, and it must
+                * have the name of our socket written on it.
                 */
+               peerbv->bv_len = err;
 # ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
-               fd[0] = (*(int *)CMSG_DATA( cmsg ));
+               fd = (*(int *)CMSG_DATA( cmsg ));
 # endif
-               err = fstat( fd[0], &st );
-               close(fd[0]);
-               if( err == 0 && S_ISFIFO(st.st_mode) &&
-                       ((st.st_mode & (S_IRWXG|S_IRWXO)) == 0))
+               err = fstat( fd, &st );
+               if ( err == 0 )
+                       rlen = read(fd, &rname, rlen);
+               close(fd);
+               if( err == 0 && st.st_mode == mode &&
+                       llen == rlen && !memcmp(&lname, &rname, llen))
                {
                        *euid = st.st_uid;
                        *egid = st.st_gid;
@@ -151,7 +166,7 @@ int getpeereid( int s, uid_t *euid, gid_t *egid )
        }
 #elif defined(SOCKCREDSIZE)
        struct msghdr msg;
-       socklen_t crmsgsize;
+       ber_socklen_t crmsgsize;
        void *crmsg;
        struct cmsghdr *cmp;
        struct sockcred *sc;
index 2af75fb73236caec40a64534769da10db1b26c6e..482a604d62b13f7c3756ea8c5941572c6d6fabb3 100644 (file)
@@ -865,6 +865,9 @@ ldif_read_record(
                                                fp2 = ldif_open_url( ptr );
                                                if ( fp2 ) {
                                                        LDIFFP *lnew = ber_memalloc( sizeof( LDIFFP ));
+                                                       if ( lnew == NULL ) {
+                                                               return 0;
+                                                       }
                                                        lnew->prev = lfp->prev;
                                                        lnew->fp = lfp->fp;
                                                        lfp->prev = lnew;
index b808e6abdb7d58c04cd99cc204a73109108e198c..00d91dfb2f2027b4d35dbbf6c20dff2008da56c3 100644 (file)
 
 #undef LOCK_API
 
-#if HAVE_LOCKF && defined(F_LOCK)
+#if defined(HAVE_LOCKF) && defined(F_LOCK)
 #      define USE_LOCKF 1
 #      define LOCK_API "lockf"
 #endif
 
-#if !defined(LOCK_API) && HAVE_FCNTL
+#if !defined(LOCK_API) && defined(HAVE_FCNTL)
 #      ifdef HAVE_FCNTL_H
 #              include <fcntl.h>
 #      endif
@@ -48,8 +48,8 @@
 #      endif
 #endif
 
-#if !defined(LOCK_API) && HAVE_FLOCK
-#      if HAVE_SYS_FILE_H
+#if !defined(LOCK_API) && defined(HAVE_FLOCK)
+#      ifdef HAVE_SYS_FILE_H
 #              include <sys/file.h>
 #      endif
 #      define USE_FLOCK 1
index c84cda736765d76c5cc7a5a27ae49e4cb69a6793..c6d9ff4163856341bec2308e84bf210f8d1b43de 100644 (file)
@@ -44,7 +44,7 @@ lutil_get_filed_password(
        }
 
        passwd->bv_val = NULL;
-       passwd->bv_len = 4196;
+       passwd->bv_len = 4096;
 
 #ifdef HAVE_FSTAT
        {
@@ -56,7 +56,8 @@ lutil_get_filed_password(
                                        filename );
                        }
 
-                       passwd->bv_len = sb.st_size;
+                       if ( sb.st_size )
+                               passwd->bv_len = sb.st_size;
                }
        }
 #endif /* HAVE_FSTAT */
index ffbd29846e67b03fadbcd18010c79a319b3c4d32..50b5a29ddcfeae2b07c69e601e13cf1648702d5a 100644 (file)
@@ -49,6 +49,8 @@ lutil_sasl_freedefs(
        void *defaults )
 {
        lutilSASLdefaults *defs = defaults;
+
+       assert( defs != NULL );
        
        if (defs->mech) ber_memfree(defs->mech);
        if (defs->realm) ber_memfree(defs->realm);
index c2e62200355b60e492a42924a6ad546871824bfd..308a758224b44be175b2d465b2634b2fb441f184 100644 (file)
@@ -35,7 +35,8 @@ int lutil_pair( ber_socket_t sds[2] )
        return pipe( sds );
 #else
        struct sockaddr_in si;
-       int rc, len = sizeof(si);
+       int rc;
+       ber_socklen_t len = sizeof(si);
        ber_socket_t sd;
 
        sd = socket( AF_INET, SOCK_DGRAM, 0 );
index e2bbe74ad6410577e49bc94e2e9e5e956d5c1f3b..b5d4f6e68ae6d0fd962524bab9649535fb1bcefa 100644 (file)
@@ -41,6 +41,8 @@
 
 #ifdef HAVE_UUID_TO_STR
 #  include <sys/uuid.h>
+#elif defined( HAVE_UUID_GENERATE )
+#  include <uuid/uuid.h>
 #elif defined( _WIN32 )
 #  include <rpc.h>
 #else
@@ -56,7 +58,7 @@
 #include <lutil.h>
 
 /* not needed for Windows */
-#if !defined(HAVE_UUID_TO_STR) && !defined(_WIN32)
+#if !defined(HAVE_UUID_TO_STR) && !defined(HAVE_UUID_GENERATE) && !defined(_WIN32)
 static unsigned char *
 lutil_eaddr( void )
 {
@@ -251,7 +253,7 @@ mul64ll(unsigned long i1, unsigned long i2)
 
 #endif /* ULONG_MAX >= 64 bits || HAVE_LONG_LONG */
 
-#endif /* !HAVE_UUID_TO_STR && !_WIN32 */
+#endif /* !HAVE_UUID_TO_STR && !HAVE_UUID_GENERATE && !_WIN32 */
 
 /*
 ** All we really care about is an ISO UUID string.  The format of a UUID is:
@@ -298,6 +300,13 @@ lutil_uuidstr( char *buf, size_t len )
 
        return l;
 
+#elif defined( HAVE_UUID_GENERATE )
+       uuid_t uu;
+
+       uuid_generate( uu );
+       uuid_unparse_lower( uu, buf );
+       return strlen( buf );
+       
 #elif defined( _WIN32 )
        UUID uuid;
        unsigned char *uuidstr;
@@ -371,6 +380,47 @@ lutil_uuidstr( char *buf, size_t len )
 #endif
 }
 
+int
+lutil_uuidstr_from_normalized(
+       char            *uuid,
+       size_t          uuidlen,
+       char            *buf,
+       size_t          buflen )
+{
+       unsigned char nibble;
+       int i, d = 0;
+
+       assert( uuid != NULL );
+       assert( buf != NULL );
+
+       if ( uuidlen != 16 ) return -1;
+       if ( buflen < 36 ) return -1;
+
+       for ( i = 0; i < 16; i++ ) {
+               if ( i == 4 || i == 6 || i == 8 || i == 10 ) {
+                       buf[(i<<1)+d] = '-';
+                       d += 1;
+               }
+
+               nibble = (uuid[i] >> 4) & 0xF;
+               if ( nibble < 10 ) {
+                       buf[(i<<1)+d] = nibble + '0';
+               } else {
+                       buf[(i<<1)+d] = nibble - 10 + 'a';
+               }
+
+               nibble = (uuid[i]) & 0xF;
+               if ( nibble < 10 ) {
+                       buf[(i<<1)+d+1] = nibble + '0';
+               } else {
+                       buf[(i<<1)+d+1] = nibble - 10 + 'a';
+               }
+       }
+
+       if ( buflen > 36 ) buf[36] = '\0';
+       return 36;
+}
+
 #ifdef TEST
 int
 main(int argc, char **argv)
index 4fc47ae36a40d131051beda180200815ae664e79..010cca46caf2f774776da0fae3215ab236501741 100644 (file)
@@ -13,5 +13,5 @@
 ## top-level directory of the distribution or, alternatively, at
 ## <http://www.OpenLDAP.org/license.html>.
 
-SUBDIRS= slapd slurpd
+SUBDIRS= slapd
 
index e19e739a8f624b9ee7f5c047878c40efc4e16999..fcc9a4ce83050225027d316650e06131e27fbda1 100644 (file)
@@ -29,7 +29,7 @@ SRCS  = main.c globals.c bconfig.c config.c daemon.c \
                dn.c compare.c modify.c delete.c modrdn.c ch_malloc.c \
                value.c ava.c bind.c unbind.c abandon.c filterentry.c \
                phonetic.c acl.c str2filter.c aclparse.c init.c user.c \
-               repl.c lock.c controls.c extended.c passwd.c \
+               lock.c controls.c extended.c passwd.c \
                schema.c schema_check.c schema_init.c schema_prep.c \
                schemaparse.c ad.c at.c mr.c syntax.c oc.c saslauthz.c \
                oidm.c starttls.c index.c sets.c referral.c root_dse.c \
@@ -47,7 +47,7 @@ OBJS  = main.o globals.o bconfig.o config.o daemon.o \
                dn.o compare.o modify.o delete.o modrdn.o ch_malloc.o \
                value.o ava.o bind.o unbind.o abandon.o filterentry.o \
                phonetic.o acl.o str2filter.o aclparse.o init.o user.o \
-               repl.o lock.o controls.o extended.o passwd.o \
+               lock.o controls.o extended.o passwd.o \
                schema.o schema_check.o schema_init.o schema_prep.o \
                schemaparse.o ad.o at.o mr.o syntax.o oc.o saslauthz.o \
                oidm.o starttls.o index.o sets.o referral.o root_dse.o \
index bd09f3e81106a69531068121c479269dbac3c209..c77dc1e25e34756e0783c7c0305fe8170146a648 100644 (file)
@@ -37,7 +37,8 @@ do_abandon( Operation *op, SlapReply *rs )
        ber_int_t       id;
        Operation       *o;
 
-       Debug( LDAP_DEBUG_TRACE, "do_abandon\n", 0, 0, 0 );
+       Debug( LDAP_DEBUG_TRACE, "%s do_abandon\n",
+               op->o_log_prefix, 0, 0 );
 
        /*
         * Parse the abandon request.  It looks like this:
@@ -46,7 +47,8 @@ do_abandon( Operation *op, SlapReply *rs )
         */
 
        if ( ber_scanf( op->o_ber, "i", &id ) == LBER_ERROR ) {
-               Debug( LDAP_DEBUG_ANY, "do_abandon: ber_scanf failed\n", 0, 0 ,0 );
+               Debug( LDAP_DEBUG_ANY, "%s do_abandon: ber_scanf failed\n",
+                       op->o_log_prefix, 0, 0 );
                send_ldap_discon( op, rs, LDAP_PROTOCOL_ERROR, "decoding error" );
                return SLAPD_DISCONNECT;
        }
@@ -55,15 +57,17 @@ do_abandon( Operation *op, SlapReply *rs )
                op->o_log_prefix, (long) id, 0, 0, 0 );
 
        if( get_ctrls( op, rs, 0 ) != LDAP_SUCCESS ) {
-               Debug( LDAP_DEBUG_ANY, "do_abandon: get_ctrls failed\n", 0, 0 ,0 );
+               Debug( LDAP_DEBUG_ANY, "%s do_abandon: get_ctrls failed\n",
+                       op->o_log_prefix, 0, 0 );
                return rs->sr_err;
        } 
 
-       Debug( LDAP_DEBUG_ARGS, "do_abandon: id=%ld\n", (long) id, 0 ,0 );
+       Debug( LDAP_DEBUG_ARGS, "%s do_abandon: id=%ld\n",
+               op->o_log_prefix, (long) id, 0 );
 
        if( id <= 0 ) {
-               Debug( LDAP_DEBUG_ANY,
-                       "do_abandon: bad msgid %ld\n", (long) id, 0, 0 );
+               Debug( LDAP_DEBUG_ANY, "%s do_abandon: bad msgid %ld\n",
+                       op->o_log_prefix, (long) id, 0 );
                return LDAP_SUCCESS;
        }
 
@@ -91,7 +95,7 @@ do_abandon( Operation *op, SlapReply *rs )
                LDAP_STAILQ_FOREACH( o, &op->o_conn->c_pending_ops, o_next ) {
                        if ( o->o_msgid == id ) {
                                LDAP_STAILQ_REMOVE( &op->o_conn->c_pending_ops,
-                                       o, slap_op, o_next );
+                                       o, Operation, o_next );
                                LDAP_STAILQ_NEXT(o, o_next) = NULL;
                                op->o_conn->c_n_ops_pending--;
                                slap_op_free( o );
@@ -102,8 +106,9 @@ do_abandon( Operation *op, SlapReply *rs )
 
        ldap_pvt_thread_mutex_unlock( &op->o_conn->c_mutex );
 
-       Debug( LDAP_DEBUG_TRACE, "do_abandon: op=%ld %sfound\n",
-               (long) id, o ? "" : "not ", 0 );
+       Debug( LDAP_DEBUG_TRACE, "%s do_abandon: op=%ld %sfound\n",
+               op->o_log_prefix,
+               (long) id, o ? "" : "not " );
        return rs->sr_err;
 }
 
index a86e3acd1fe1380a4bf31a9284b0c94bd3869eac..ac786ace756f4faad96051293d1125abf3ebd89d 100644 (file)
@@ -676,6 +676,7 @@ aci_init( void )
        static slap_syntax_defs_rec aci_syntax_def = {
                "( 1.3.6.1.4.1.4203.666.2.1 DESC 'OpenLDAP Experimental ACI' )",
                        SLAP_SYNTAX_HIDE,
+                       NULL,
                        OpenLDAPaciValidate,
                        OpenLDAPaciPretty
        };
index 59478d83a6b2c4605ab2ccb5767e3ac3c6a0406b..14cc43894f160a2a3d421b4346d1fd003168dbf0 100644 (file)
@@ -304,7 +304,7 @@ fe_access_allowed(
        be_orig = op->o_bd;
 
        if ( op->o_bd == NULL ) {
-               op->o_bd = select_backend( &op->o_req_ndn, 0, 0 );
+               op->o_bd = select_backend( &op->o_req_ndn, 0 );
                if ( op->o_bd == NULL )
                        op->o_bd = frontendDB;
        }
@@ -2053,7 +2053,7 @@ acl_set_cb_gather( Operation *op, SlapReply *rs )
                        }
                }
 
-               if ( bvals ) {
+               if ( bvalsp ) {
                        p->bvals = slap_set_join( p->cookie, p->bvals,
                                        ( '|' | SLAP_SET_RREF ), bvalsp );
                }
@@ -2111,7 +2111,7 @@ acl_set_gather( SetCookie *cookie, struct berval *name, AttributeDescription *de
                goto url_done;
        }
 
-       op2.o_bd = select_backend( &op2.o_req_ndn, 0, 1 );
+       op2.o_bd = select_backend( &op2.o_req_ndn, 1 );
        if ( ( op2.o_bd == NULL ) || ( op2.o_bd->be_search == NULL ) ) {
                rc = LDAP_NO_SUCH_OBJECT;
                goto url_done;
index a48c7bdc39d46b30a6a15785887ea10a051ba67f..0e79845f37ad7fc6787eb2fab0c2916daf188f2b 100644 (file)
@@ -58,7 +58,7 @@ typedef struct Attr_option {
        int           prefix;   /* NAME is a tag and range prefix */
 } Attr_option;
 
-static Attr_option lang_option = { { sizeof("lang-")-1, "lang-" }, 1 };
+static Attr_option lang_option = { BER_BVC("lang-"), 1 };
 
 /* Options sorted by name, and number of options */
 static Attr_option *options = &lang_option;
@@ -213,8 +213,8 @@ int slap_bv2ad(
                        *text = "zero length option is invalid";
                        return rtn;
                
-               } else if ( optlen == sizeof("binary")-1 &&
-                       strncasecmp( opt, "binary", sizeof("binary")-1 ) == 0 )
+               } else if ( optlen == STRLENOF("binary") &&
+                       strncasecmp( opt, "binary", STRLENOF("binary") ) == 0 )
                {
                        /* binary option */
                        if( slap_ad_is_binary( &desc ) ) {
@@ -356,10 +356,10 @@ done:;
                if (desc.ad_tags.bv_len || desc.ad_flags != SLAP_DESC_NONE) {
                        dlen = desc.ad_type->sat_cname.bv_len + 1;
                        if (desc.ad_tags.bv_len) {
-                               dlen += 1+desc.ad_tags.bv_len;
+                               dlen += 1 + desc.ad_tags.bv_len;
                        }
-                       if( slap_ad_is_binary( &desc ) ) {
-                               dlen += sizeof(";binary")+desc.ad_tags.bv_len;
+                       if ( slap_ad_is_binary( &desc ) ) {
+                               dlen += 1 + STRLENOF(";binary") + desc.ad_tags.bv_len;
                        }
                }
 
@@ -384,7 +384,7 @@ done:;
                                lp = NULL;
                                if( desc.ad_tags.bv_len ) {
                                        lp = desc.ad_tags.bv_val;
-                                       while( strncasecmp(lp, "binary", sizeof("binary")-1) < 0
+                                       while( strncasecmp(lp, "binary", STRLENOF("binary")) < 0
                                               && (lp = strchr( lp, ';' )) != NULL )
                                                ++lp;
                                        if( lp != desc.ad_tags.bv_val ) {
@@ -906,12 +906,14 @@ str2anlist( AttributeName *an, char *in, const char *brkstr )
        }
 
        an = ch_realloc( an, ( i + j + 1 ) * sizeof( AttributeName ) );
-       BER_BVZERO( &an[i + j].an_name );
        anew = an + i;
        for ( s = ldap_pvt_strtok( str, brkstr, &lasts );
                s != NULL;
                s = ldap_pvt_strtok( NULL, brkstr, &lasts ) )
        {
+               /* put a stop mark */
+               BER_BVZERO( &anew[1].an_name );
+
                anew->an_desc = NULL;
                anew->an_oc = NULL;
                anew->an_oc_exclude = 0;
@@ -961,10 +963,8 @@ str2anlist( AttributeName *an, char *in, const char *brkstr )
        return( an );
 
 reterr:
-       for ( i = 0; an[i].an_name.bv_val; i++ ) {
-               free( an[i].an_name.bv_val );
-       }
-       free( an );
+       anlist_free( an, 1, NULL );
+
        /*
         * overwrites input string
         * on error!
@@ -974,6 +974,24 @@ reterr:
        return NULL;
 }
 
+void
+anlist_free( AttributeName *an, int freename, void *ctx )
+{
+       if ( an == NULL ) {
+               return;
+       }
+
+       if ( freename ) {
+               int     i;
+
+               for ( i = 0; an[i].an_name.bv_val; i++ ) {
+                       ber_memfree_x( an[i].an_name.bv_val, ctx );
+               }
+       }
+
+       ber_memfree_x( an, ctx );
+}
+
 char **anlist2charray_x( AttributeName *an, int dup, void *ctx )
 {
     char **attrs;
@@ -1131,7 +1149,7 @@ file2anlist( AttributeName *an, const char *fname, const char *brkstr )
                }
                an = str2anlist( an, line, brkstr );
                if ( an == NULL )
-                       return NULL;
+                       break;
                lcur = line;
        }
        ch_free( line );
index 8d22d54afc255c11b7a4279192511b2cc75d4713..280fb4f20f5c083b564285330ebe7fa6c993f885 100644 (file)
@@ -49,7 +49,9 @@ do_add( Operation *op, SlapReply *rs )
        int             rc = 0;
        int             freevals = 1;
 
-       Debug( LDAP_DEBUG_TRACE, "do_add\n", 0, 0, 0 );
+       Debug( LDAP_DEBUG_TRACE, "%s do_add\n",
+               op->o_log_prefix, 0, 0 );
+
        /*
         * Parse the add request.  It looks like this:
         *
@@ -64,26 +66,14 @@ do_add( Operation *op, SlapReply *rs )
 
        /* get the name */
        if ( ber_scanf( ber, "{m", /*}*/ &dn ) == LBER_ERROR ) {
-               Debug( LDAP_DEBUG_ANY, "do_add: ber_scanf failed\n", 0, 0, 0 );
+               Debug( LDAP_DEBUG_ANY, "%s do_add: ber_scanf failed\n",
+                       op->o_log_prefix, 0, 0 );
                send_ldap_discon( op, rs, LDAP_PROTOCOL_ERROR, "decoding error" );
                return SLAPD_DISCONNECT;
        }
 
-       op->ora_e = entry_alloc();
-
-       rs->sr_err = dnPrettyNormal( NULL, &dn, &op->o_req_dn, &op->o_req_ndn,
-               op->o_tmpmemctx );
-
-       if ( rs->sr_err != LDAP_SUCCESS ) {
-               Debug( LDAP_DEBUG_ANY, "do_add: invalid dn (%s)\n", dn.bv_val, 0, 0 );
-               send_ldap_error( op, rs, LDAP_INVALID_DN_SYNTAX, "invalid DN" );
-               goto done;
-       }
-
-       ber_dupbv( &op->ora_e->e_name, &op->o_req_dn );
-       ber_dupbv( &op->ora_e->e_nname, &op->o_req_ndn );
-
-       Debug( LDAP_DEBUG_ARGS, "do_add: dn (%s)\n", op->ora_e->e_dn, 0, 0 );
+       Debug( LDAP_DEBUG_ARGS, "%s do_add: dn (%s)\n",
+               op->o_log_prefix, dn.bv_val, 0 );
 
        /* get the attrs */
        for ( tag = ber_first_element( ber, &len, &last ); tag != LBER_DEFAULT;
@@ -97,15 +87,16 @@ do_add( Operation *op, SlapReply *rs )
                rtag = ber_scanf( ber, "{m{W}}", &tmp.sml_type, &tmp.sml_values );
 
                if ( rtag == LBER_ERROR ) {
-                       Debug( LDAP_DEBUG_ANY, "do_add: decoding error\n", 0, 0, 0 );
+                       Debug( LDAP_DEBUG_ANY, "%s do_add: decoding error\n",
+                               op->o_log_prefix, 0, 0 );
                        send_ldap_discon( op, rs, LDAP_PROTOCOL_ERROR, "decoding error" );
                        rs->sr_err = SLAPD_DISCONNECT;
                        goto done;
                }
 
                if ( tmp.sml_values == NULL ) {
-                       Debug( LDAP_DEBUG_ANY, "no values for type %s\n",
-                               tmp.sml_type.bv_val, 0, 0 );
+                       Debug( LDAP_DEBUG_ANY, "%s do_add: no values for type %s\n",
+                               op->o_log_prefix, tmp.sml_type.bv_val, 0 );
                        send_ldap_error( op, rs, LDAP_PROTOCOL_ERROR,
                                "no values for attribute type" );
                        goto done;
@@ -125,26 +116,42 @@ do_add( Operation *op, SlapReply *rs )
        }
 
        if ( ber_scanf( ber, /*{*/ "}") == LBER_ERROR ) {
-               Debug( LDAP_DEBUG_ANY, "do_add: ber_scanf failed\n", 0, 0, 0 );
+               Debug( LDAP_DEBUG_ANY, "%s do_add: ber_scanf failed\n",
+                       op->o_log_prefix, 0, 0 );
                send_ldap_discon( op, rs, LDAP_PROTOCOL_ERROR, "decoding error" );
                rs->sr_err = SLAPD_DISCONNECT;
                goto done;
        }
 
        if ( get_ctrls( op, rs, 1 ) != LDAP_SUCCESS ) {
-               Debug( LDAP_DEBUG_ANY, "do_add: get_ctrls failed\n", 0, 0, 0 );
+               Debug( LDAP_DEBUG_ANY, "%s do_add: get_ctrls failed\n",
+                       op->o_log_prefix, 0, 0 );
                goto done;
        } 
 
+       rs->sr_err = dnPrettyNormal( NULL, &dn, &op->o_req_dn, &op->o_req_ndn,
+               op->o_tmpmemctx );
+
+       if ( rs->sr_err != LDAP_SUCCESS ) {
+               Debug( LDAP_DEBUG_ANY, "%s do_add: invalid dn (%s)\n",
+                       op->o_log_prefix, dn.bv_val, 0 );
+               send_ldap_error( op, rs, LDAP_INVALID_DN_SYNTAX, "invalid DN" );
+               goto done;
+       }
+
+       op->ora_e = entry_alloc();
+       ber_dupbv( &op->ora_e->e_name, &op->o_req_dn );
+       ber_dupbv( &op->ora_e->e_nname, &op->o_req_ndn );
+
+       Statslog( LDAP_DEBUG_STATS, "%s ADD dn=\"%s\"\n",
+           op->o_log_prefix, op->o_req_dn.bv_val, 0, 0, 0 );
+
        if ( modlist == NULL ) {
                send_ldap_error( op, rs, LDAP_PROTOCOL_ERROR,
                        "no attributes provided" );
                goto done;
        }
 
-       Statslog( LDAP_DEBUG_STATS, "%s ADD dn=\"%s\"\n",
-           op->o_log_prefix, op->ora_e->e_name.bv_val, 0, 0, 0 );
-
        if ( dn_match( &op->ora_e->e_nname, &slap_empty_bv ) ) {
                /* protocolError may be a more appropriate error */
                send_ldap_error( op, rs, LDAP_ALREADY_EXISTS,
@@ -220,21 +227,18 @@ done:;
 int
 fe_op_add( Operation *op, SlapReply *rs )
 {
-       int             manageDSAit;
        Modifications   **modtail = &op->ora_modlist;
        int             rc = 0;
        BackendDB       *op_be, *bd = op->o_bd;
        char            textbuf[ SLAP_TEXT_BUFLEN ];
        size_t          textlen = sizeof( textbuf );
 
-       manageDSAit = get_manageDSAit( op );
-
        /*
         * We could be serving multiple database backends.  Select the
         * appropriate one, or send a referral to our "referral server"
         * if we don't hold it.
         */
-       op->o_bd = select_backend( &op->ora_e->e_nname, manageDSAit, 1 );
+       op->o_bd = select_backend( &op->ora_e->e_nname, 1 );
        if ( op->o_bd == NULL ) {
                op->o_bd = bd;
                rs->sr_ref = referral_rewrite( default_referral,
@@ -257,7 +261,7 @@ fe_op_add( Operation *op, SlapReply *rs )
        /* If we've got a glued backend, check the real backend */
        op_be = op->o_bd;
        if ( SLAP_GLUE_INSTANCE( op->o_bd )) {
-               op->o_bd = select_backend( &op->ora_e->e_nname, manageDSAit, 0 );
+               op->o_bd = select_backend( &op->ora_e->e_nname, 0 );
        }
 
        /* check restrictions */
@@ -290,7 +294,6 @@ fe_op_add( Operation *op, SlapReply *rs )
                int repl_user = be_isupdate( op );
                if ( !SLAP_SINGLE_SHADOW(op->o_bd) || repl_user ) {
                        int             update = !BER_BVISEMPTY( &op->o_bd->be_update_ndn );
-                       slap_callback   cb = { NULL, slap_replog_cb, NULL, NULL };
 
                        op->o_bd = op_be;
 
@@ -322,9 +325,6 @@ fe_op_add( Operation *op, SlapReply *rs )
                                        send_ldap_result( op, rs );
                                        goto done;
                                }
-
-                               cb.sc_next = op->o_callback;
-                               op->o_callback = &cb;
                        }
 
                        rc = op->o_bd->be_add( op, rs );
index 37d467ad127e658ee0ee0021998f4a13cfa22924..c7bb16d56f3b41c9ccd4518e38381cc68f783bd7 100644 (file)
@@ -32,7 +32,7 @@
 #include <ac/assert.h>
 #include <sys/types.h>
 #include <sys/stat.h>
-#if HAVE_SYS_FILE_H
+#ifdef HAVE_SYS_FILE_H
 #include <sys/file.h>
 #endif
 #include <fcntl.h>
index 4538f5b5d4c4d8f1619bf818b4b392a8916515eb..e70f10e969ba1eaaa5a1e59fec80366a3c6fdb82 100644 (file)
@@ -74,7 +74,7 @@ struct aindexrec {
 
 static Avlnode *attr_index = NULL;
 static Avlnode *attr_cache = NULL;
-static LDAP_STAILQ_HEAD(ATList, slap_attribute_type) attr_list
+static LDAP_STAILQ_HEAD(ATList, AttributeType) attr_list
        = LDAP_STAILQ_HEAD_INITIALIZER(attr_list);
 
 /* Last hardcoded attribute registered */
@@ -253,7 +253,7 @@ at_delete( AttributeType *at )
 {
        at->sat_flags |= SLAP_AT_DELETED;
 
-       LDAP_STAILQ_REMOVE(&attr_list,at,slap_attribute_type,sat_next);
+       LDAP_STAILQ_REMOVE(&attr_list, at, AttributeType, sat_next);
 
        at_delete_names( at );
 }
@@ -459,6 +459,7 @@ at_insert(
                                
                                /* Keep old oid, free new oid;
                                 * Keep old ads, free new ads;
+                                * Keep old ad_mutex, free new ad_mutex;
                                 * Keep new everything else, free old
                                 */
                                tmp = *old_sat;
@@ -467,6 +468,8 @@ at_insert(
                                tmp.sat_oid = sat->sat_oid;
                                old_sat->sat_ad = tmp.sat_ad;
                                tmp.sat_ad = sat->sat_ad;
+                               old_sat->sat_ad_mutex = tmp.sat_ad_mutex;
+                               tmp.sat_ad_mutex = sat->sat_ad_mutex;
                                *sat = tmp;
 
                                /* Check for basic ad pointing at old cname */
@@ -751,9 +754,12 @@ at_add(
                        goto error_return;
                }
 
-               if( sat->sat_syntax != NULL && sat->sat_syntax != syn ) {
-                       code = SLAP_SCHERR_ATTR_BAD_SUP;
-                       goto error_return;
+               if ( sat->sat_syntax != NULL && sat->sat_syntax != syn ) {
+                       /* BEWARE: no loop detection! */
+                       if ( syn_is_sup( sat->sat_syntax, syn ) ) {
+                               code = SLAP_SCHERR_ATTR_BAD_SUP;
+                               goto error_return;
+                       }
                }
 
                sat->sat_syntax = syn;
index 4e418e3032780459f670c8cb38414a108d76ab83..315442466f4403587a8ba80ed6fb722294c40814 100644 (file)
@@ -185,9 +185,10 @@ comp_tree_free( Attribute *a )
 void
 attrs_free( Attribute *a )
 {
-       Attribute *b, *tail, *next;
-
        if ( a ) {
+               Attribute *b = (Attribute *)0xBAD, *tail, *next;
+
+               /* save tail */
                tail = a;
                do {
                        next = a->a_next;
@@ -198,6 +199,8 @@ attrs_free( Attribute *a )
                } while ( next );
 
                ldap_pvt_thread_mutex_lock( &attr_mutex );
+               /* replace NULL with current attr list and let attr list
+                * start from last attribute returned to list */
                tail->a_next = attr_list;
                attr_list = b;
                ldap_pvt_thread_mutex_unlock( &attr_mutex );
index 1f70e8ef409150b5e70ca5abbd385d64782b78eb..88f5feb533ba88dee3406596714bb40a93ca143e 100644 (file)
@@ -35,7 +35,7 @@ bdb_add(Operation *op, SlapReply *rs )
        DB_TXN          *ltid = NULL, *lt2;
        struct bdb_op_info opinfo = {0};
        int subentry;
-       u_int32_t       locker = 0, rlocker = 0;
+       BDB_LOCKER      locker = 0, rlocker = 0;
        DB_LOCK         lock;
 
        int             num_retries = 0;
index d564bfedfcba079672592a1336a5332e17da88bf..51edd51c0be372cf94374e4c79fdf6a0e78f2d76 100644 (file)
@@ -58,6 +58,28 @@ LDAP_BEGIN_DECL
 #define        BDB_PAGESIZE    4096    /* BDB's original default */
 #endif
 
+/* 4.6.18 redefines cursor->locker */
+#if DB_VERSION_FULL >= 0x04060012
+
+struct __db_locker {
+       u_int32_t       id;
+};
+
+typedef struct __db_locker * BDB_LOCKER;
+
+extern int __lock_getlocker(DB_LOCKTAB *lt, u_int32_t locker, int create, DB_LOCKER **ret);
+
+#define CURSOR_SETLOCKER(cursor, id)   cursor->locker = id
+#define        CURSOR_GETLOCKER(cursor)        cursor->locker
+#else
+
+typedef u_int32_t BDB_LOCKER;
+
+#define CURSOR_SETLOCKER(cursor, id)   cursor->locker = id
+#define CURSOR_GETLOCKER(cursor)       cursor->locker
+
+#endif
+
 #define DEFAULT_CACHE_SIZE     1000
 
 /* The default search IDL stack cache depth */
@@ -131,10 +153,11 @@ typedef struct bdb_cache {
        int             c_maxsize;
        int             c_cursize;
        int             c_minfree;
+       int             c_eimax;
        int             c_eiused;       /* EntryInfo's in use */
        int             c_leaves;       /* EntryInfo leaf nodes */
        int             c_purging;
-       u_int32_t       c_locker;       /* used by lru cleaner */
+       BDB_LOCKER      c_locker;       /* used by lru cleaner */
        ldap_pvt_thread_rdwr_t c_rwlock;
        ldap_pvt_thread_mutex_t c_lru_mutex;
        ldap_pvt_thread_mutex_t c_count_mutex;
@@ -208,6 +231,12 @@ struct bdb_info {
        char            *bi_db_config_path;
        BerVarray       bi_db_config;
        bdb_monitor_t   bi_monitor;
+
+#ifdef BDB_MONITOR_IDX
+       ldap_pvt_thread_mutex_t bi_idx_mutex;
+       Avlnode         *bi_idx;
+#endif /* BDB_MONITOR_IDX */
+
        int             bi_flags;
 #define        BDB_IS_OPEN             0x01
 #define        BDB_HAS_CONFIG  0x02
@@ -223,6 +252,7 @@ struct bdb_info {
 #define bi_id2entry    bi_databases[BDB_ID2ENTRY]
 #define bi_dn2id       bi_databases[BDB_DN2ID]
 
+
 struct bdb_lock_info {
        struct bdb_lock_info *bli_next;
        ID              bli_id;
@@ -232,14 +262,14 @@ struct bdb_lock_info {
 struct bdb_op_info {
        BackendDB*      boi_bdb;
        DB_TXN*         boi_txn;
+       BDB_LOCKER      boi_locker;
        u_int32_t       boi_err;
-       u_int32_t       boi_locker;
        int             boi_acl_cache;
        struct bdb_lock_info *boi_locks;        /* used when no txn */
 };
 
 #define        DB_OPEN(db, file, name, type, flags, mode) \
-       (db)->open(db, file, name, type, flags, mode)
+       ((db)->open)(db, file, name, type, flags, mode)
 
 #if DB_VERSION_MAJOR < 4
 #define LOCK_DETECT(env,f,t,a)         lock_detect(env, f, t, a)
@@ -270,7 +300,13 @@ struct bdb_op_info {
 #if DB_VERSION_FULL >= 0x04010011
 #undef DB_OPEN
 #define        DB_OPEN(db, file, name, type, flags, mode) \
-       (db)->open(db, NULL, file, name, type, flags, mode)
+       ((db)->open)(db, NULL, file, name, type, flags, mode)
+#endif
+
+/* BDB 4.6.18 makes locker a struct instead of an int */
+#if DB_VERSION_FULL >= 0x04060012
+#undef TXN_ID
+#define TXN_ID(txn)    (txn)->locker
 #endif
 
 #endif
index 84f3a38a0ef33ca47c4e8ed6aa0cd29b95eae216..3f6b37a908a9b02116471645c4afcebd982c2ddf 100644 (file)
@@ -32,19 +32,37 @@ bdb_bind( Operation *op, SlapReply *rs )
 
        AttributeDescription *password = slap_schema.si_ad_userPassword;
 
-       u_int32_t       locker;
+       BDB_LOCKER      locker;
        DB_LOCK         lock;
 
        Debug( LDAP_DEBUG_ARGS,
                "==> " LDAP_XSTRING(bdb_bind) ": dn: %s\n",
                op->o_req_dn.bv_val, 0, 0);
 
+#ifdef LDAP_DEVEL
        /* allow noauth binds */
-       if ( op->oq_bind.rb_method == LDAP_AUTH_SIMPLE && be_isroot_pw( op )) {
-               ber_dupbv( &op->oq_bind.rb_edn, be_root_dn( op->o_bd ) );
-               /* front end will send result */
-               return LDAP_SUCCESS;
+       switch ( be_rootdn_bind( op, rs ) ) {
+       case SLAP_CB_CONTINUE:
+               break;
+
+       default:
+               /* in case of success, frontend will send result;
+                * otherwise, be_rootdn_bind() did */
+               return rs->sr_err;
+       }
+
+#else /* traditional */
+       /* allow noauth binds */
+       switch ( be_rootdn_bind( op, NULL ) ) {
+       case LDAP_SUCCESS:
+               /* frontend will send result */
+               return rs->sr_err;
+
+       default:
+               /* give the database a chanche */
+               break;
        }
+#endif /* traditional */
 
        rs->sr_err = LOCK_ID(bdb->bi_dbenv, &locker);
        switch(rs->sr_err) {
index 7f93b3bad1096373bf04c069f3da0cf9fd66a3a5..c6d48112ce7cbf8a8878046d19ef3c47c27dd34f 100644 (file)
@@ -63,9 +63,9 @@ bdb_cache_entryinfo_new( Cache *cache )
                if ( cache->c_eifree ) {
                        ei = cache->c_eifree;
                        cache->c_eifree = ei->bei_lrunext;
+                       ei->bei_finders = 0;
                }
                ldap_pvt_thread_mutex_unlock( &cache->c_eifree_mutex );
-               ei->bei_finders = 0;
        }
        if ( !ei ) {
                ei = ch_calloc(1, sizeof(EntryInfo));
@@ -155,11 +155,17 @@ bdb_cache_lru_link( struct bdb_info *bdb, EntryInfo *ei )
  * alternatives though.
  */
 
+#if DB_VERSION_FULL >= 0x04060012
+#define BDB_LOCKID(locker)     locker->id
+#else
+#define BDB_LOCKID(locker)     locker
+#endif
+
 /* Atomically release and reacquire a lock */
 int
 bdb_cache_entry_db_relock(
        struct bdb_info *bdb,
-       u_int32_t locker,
+       BDB_LOCKER locker,
        EntryInfo *ei,
        int rw,
        int tryOnly,
@@ -183,7 +189,7 @@ bdb_cache_entry_db_relock(
        list[1].lock = *lock;
        list[1].mode = rw ? DB_LOCK_WRITE : DB_LOCK_READ;
        list[1].obj = &lockobj;
-       rc = bdb->bi_dbenv->lock_vec(bdb->bi_dbenv, locker, tryOnly ? DB_LOCK_NOWAIT : 0,
+       rc = bdb->bi_dbenv->lock_vec(bdb->bi_dbenv, BDB_LOCKID(locker), tryOnly ? DB_LOCK_NOWAIT : 0,
                list, 2, NULL );
 
        if (rc && !tryOnly) {
@@ -198,7 +204,7 @@ bdb_cache_entry_db_relock(
 }
 
 static int
-bdb_cache_entry_db_lock( struct bdb_info *bdb, u_int32_t locker, EntryInfo *ei,
+bdb_cache_entry_db_lock( struct bdb_info *bdb, BDB_LOCKER locker, EntryInfo *ei,
        int rw, int tryOnly, DB_LOCK *lock )
 {
 #ifdef NO_DB_LOCK
@@ -218,7 +224,7 @@ bdb_cache_entry_db_lock( struct bdb_info *bdb, u_int32_t locker, EntryInfo *ei,
        lockobj.data = &ei->bei_id;
        lockobj.size = sizeof(ei->bei_id) + 1;
 
-       rc = LOCK_GET(bdb->bi_dbenv, locker, tryOnly ? DB_LOCK_NOWAIT : 0,
+       rc = LOCK_GET(bdb->bi_dbenv, BDB_LOCKID(locker), tryOnly ? DB_LOCK_NOWAIT : 0,
                                        &lockobj, db_rw, lock);
        if (rc && !tryOnly) {
                Debug( LDAP_DEBUG_TRACE,
@@ -457,7 +463,7 @@ int
 hdb_cache_find_parent(
        Operation *op,
        DB_TXN *txn,
-       u_int32_t       locker,
+       BDB_LOCKER      locker,
        ID id,
        EntryInfo **res )
 {
@@ -631,7 +637,7 @@ bdb_cache_lru_purge( struct bdb_info *bdb )
        if ( slapMode & SLAP_TOOL_READONLY )
                eimax = 0;
        else
-               eimax = bdb->bi_cache.c_maxsize * 4;
+               eimax = bdb->bi_cache.c_eimax;
 
        /* Look for an unused entry to remove */
        for ( elru = bdb->bi_cache.c_lruhead; elru; elru = elnext ) {
@@ -742,7 +748,7 @@ bdb_cache_find_id(
        ID                              id,
        EntryInfo       **eip,
        int             islocked,
-       u_int32_t       locker,
+       BDB_LOCKER      locker,
        DB_LOCK         *lock )
 {
        struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
@@ -963,7 +969,7 @@ bdb_cache_add(
        EntryInfo *eip,
        Entry *e,
        struct berval *nrdn,
-       u_int32_t locker,
+       BDB_LOCKER locker,
        DB_LOCK *lock )
 {
        EntryInfo *new, ei;
@@ -1038,7 +1044,7 @@ bdb_cache_modify(
        struct bdb_info *bdb,
        Entry *e,
        Attribute *newAttrs,
-       u_int32_t locker,
+       BDB_LOCKER locker,
        DB_LOCK *lock )
 {
        EntryInfo *ei = BEI(e);
@@ -1068,7 +1074,7 @@ bdb_cache_modrdn(
        struct berval *nrdn,
        Entry *new,
        EntryInfo *ein,
-       u_int32_t locker,
+       BDB_LOCKER locker,
        DB_LOCK *lock )
 {
        EntryInfo *ei = BEI(e), *pei;
@@ -1163,7 +1169,7 @@ int
 bdb_cache_delete(
        struct bdb_info *bdb,
     Entry              *e,
-    u_int32_t  locker,
+    BDB_LOCKER locker,
     DB_LOCK    *lock )
 {
        EntryInfo *ei = BEI(e);
@@ -1328,11 +1334,11 @@ bdb_lru_print( Cache *cache )
 {
        EntryInfo       *e;
 
-       fprintf( stderr, "LRU circle head: %p\n", cache->c_lruhead );
+       fprintf( stderr, "LRU circle head: %p\n", (void *) cache->c_lruhead );
        fprintf( stderr, "LRU circle (tail forward):\n" );
        for ( e = cache->c_lrutail; ; ) {
                fprintf( stderr, "\t%p, %p id %ld rdn \"%s\"\n",
-                       e, e->bei_e, e->bei_id, e->bei_nrdn.bv_val );
+                       (void *) e, (void *) e->bei_e, e->bei_id, e->bei_nrdn.bv_val );
                e = e->bei_lrunext;
                if ( e == cache->c_lrutail )
                        break;
@@ -1340,7 +1346,7 @@ bdb_lru_print( Cache *cache )
        fprintf( stderr, "LRU circle (tail backward):\n" );
        for ( e = cache->c_lrutail; ; ) {
                fprintf( stderr, "\t%p, %p id %ld rdn \"%s\"\n",
-                       e, e->bei_e, e->bei_id, e->bei_nrdn.bv_val );
+                       (void *) e, (void *) e->bei_e, e->bei_id, e->bei_nrdn.bv_val );
                e = e->bei_lruprev;
                if ( e == cache->c_lrutail )
                        break;
@@ -1354,9 +1360,15 @@ static void
 bdb_locker_id_free( void *key, void *data )
 {
        DB_ENV *env = key;
-       u_int32_t lockid = (long)data;
+       u_int32_t lockid;
        int rc;
 
+#if DB_VERSION_FULL >= 0x04060012
+       BDB_LOCKER lptr = data;
+       lockid = lptr->id;
+#else
+       lockid = (long)data;
+#endif
        rc = XLOCK_ID_FREE( env, lockid );
        if ( rc == EINVAL ) {
                DB_LOCKREQ lr;
@@ -1385,7 +1397,7 @@ bdb_locker_flush( DB_ENV *env )
 }
 
 int
-bdb_locker_id( Operation *op, DB_ENV *env, u_int32_t *locker )
+bdb_locker_id( Operation *op, DB_ENV *env, BDB_LOCKER *locker )
 {
        int i, rc;
        u_int32_t lockid;
@@ -1415,7 +1427,14 @@ bdb_locker_id( Operation *op, DB_ENV *env, u_int32_t *locker )
                if ( rc != 0) {
                        return rc;
                }
+#if DB_VERSION_FULL >= 0x04060012
+               { BDB_LOCKER lptr;
+               __lock_getlocker( env->lk_handle, lockid, 0, &lptr );
+               data = lptr;
+               }
+#else
                data = (void *)((long)lockid);
+#endif
                if ( ( rc = ldap_pvt_thread_pool_setkey( ctx, env,
                        data, bdb_locker_id_free ) ) ) {
                        XLOCK_ID_FREE( env, lockid );
@@ -1427,7 +1446,11 @@ bdb_locker_id( Operation *op, DB_ENV *env, u_int32_t *locker )
        } else {
                lockid = (long)data;
        }
+#if DB_VERSION_FULL >= 0x04060012
+       *locker = data;
+#else
        *locker = lockid;
+#endif
        return 0;
 }
 #endif /* BDB_REUSE_LOCKERS */
index 4999ec7d46ee53213c72a94bced5c0eed0a9dd1f..972071314c1df14ad87c8f4f56f8e94f3727212a 100644 (file)
@@ -30,7 +30,7 @@ bdb_compare( Operation *op, SlapReply *rs )
        Attribute       *a;
        int             manageDSAit = get_manageDSAit( op );
 
-       u_int32_t       locker;
+       BDB_LOCKER      locker;
        DB_LOCK         lock;
 
        rs->sr_err = LOCK_ID(bdb->bi_dbenv, &locker);
index 4d92f2f834361846eab0ccbe1279e07782f8d27d..3895cf30c9175f0eee7979df909e1d0b34df482c 100644 (file)
@@ -86,6 +86,11 @@ static ConfigTable bdbcfg[] = {
                "( OLcfgDbAt:1.5 NAME 'olcDbDirtyRead' "
                "DESC 'Allow reads of uncommitted data' "
                "SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL },
+       { "dncachesize", "size", 2, 2, 0, ARG_INT|ARG_OFFSET,
+               (void *)offsetof(struct bdb_info, bi_cache.c_eimax),
+               "( OLcfgDbAt:1.12 NAME 'olcDbDNcacheSize' "
+                       "DESC 'DN cache size' "
+                       "SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
        { "idlcachesize", "size", 2, 2, 0, ARG_INT|ARG_OFFSET,
                (void *)offsetof(struct bdb_info,bi_idl_cache_max_size),
                "( OLcfgDbAt:1.6 NAME 'olcDbIDLcacheSize' "
@@ -140,7 +145,7 @@ static ConfigOCs bdbocs[] = {
                "olcDbNoSync $ olcDbDirtyRead $ olcDbIDLcacheSize $ "
                "olcDbIndex $ olcDbLinearIndex $ olcDbLockDetect $ "
                "olcDbMode $ olcDbSearchStack $ olcDbShmKey $ "
-               "olcDbCacheFree ) )",
+               "olcDbCacheFree $ olcDbDNcacheSize ) )",
                        Cft_Database, bdbcfg },
        { NULL, 0, NULL }
 };
@@ -179,19 +184,20 @@ bdb_online_index( void *ctx, void *arg )
 
        Connection conn = {0};
        OperationBuffer opbuf;
-       Operation *op = (Operation *) &opbuf;
+       Operation *op;
 
        DBC *curs;
        DBT key, data;
        DB_TXN *txn;
        DB_LOCK lock;
-       u_int32_t locker;
+       BDB_LOCKER locker;
        ID id, nid;
        EntryInfo *ei;
        int rc, getnext = 1;
        int i;
 
-       connection_fake_init( &conn, op, ctx );
+       connection_fake_init( &conn, &opbuf, ctx );
+       op = &opbuf.ob_op;
 
        op->o_bd = be;
 
@@ -319,9 +325,9 @@ bdb_cf_cleanup( ConfigArgs *c )
        
        if ( bdb->bi_flags & BDB_RE_OPEN ) {
                bdb->bi_flags ^= BDB_RE_OPEN;
-               rc = c->be->bd_info->bi_db_close( c->be );
+               rc = c->be->bd_info->bi_db_close( c->be, NULL );
                if ( rc == 0 )
-                       rc = c->be->bd_info->bi_db_open( c->be );
+                       rc = c->be->bd_info->bi_db_open( c->be, NULL );
                /* If this fails, we need to restart */
                if ( rc ) {
                        slapd_shutdown = 2;
@@ -472,7 +478,6 @@ bdb_cf_gen( ConfigArgs *c )
                        bdb->bi_db_config_path = NULL;
                        c->cleanup = bdb_cf_cleanup;
                        ldap_pvt_thread_pool_purgekey( bdb->bi_dbenv );
-                       ldap_pvt_thread_pool_purgekey( ((char *)bdb->bi_dbenv) + 1 );
                        break;
                case BDB_NOSYNC:
                        bdb->bi_dbenv->set_flags( bdb->bi_dbenv, DB_TXN_NOSYNC, 0 );
index 42f9f8b88320a495dc2ed2d683a8c2cbc982b3d5..35529c79231b31e5d29c047cae8f103a2b0624cb 100644 (file)
@@ -114,7 +114,7 @@ bdb_db_cache(
        rc = db->bdi_db->set_flags( db->bdi_db, DB_DUP | DB_DUPSORT );
 
        file = ch_malloc( strlen( name ) + sizeof(BDB_SUFFIX) );
-       sprintf( file, "%s" BDB_SUFFIX, name );
+       sprintf( file, "%s%s", name, BDB_SUFFIX );
 
 #ifdef HAVE_EBCDIC
        __atoe( file );
index 37b7a13cc9e091e603532ae55981ab0e07e46833..c9fdba93d6ab159c01569aa6686ea4415e306b07 100644 (file)
@@ -38,7 +38,7 @@ bdb_delete( Operation *op, SlapReply *rs )
        struct bdb_op_info opinfo = {0};
        ID      eid;
 
-       u_int32_t       locker = 0;
+       BDB_LOCKER      locker = 0;
        DB_LOCK         lock, plock;
 
        int             num_retries = 0;
@@ -100,7 +100,7 @@ txnReturn:
        ctrls[num_ctrls] = 0;
 
        /* allocate CSN */
-       if ( BER_BVISEMPTY( &op->o_csn )) {
+       if ( BER_BVISNULL( &op->o_csn ) ) {
                struct berval csn;
                char csnbuf[LDAP_LUTIL_CSNSTR_BUFSIZE];
 
index 5211f8e9b863e572368a2c088e5fe0f65f7d074e..9df6d4f6d3e553565fab5005b4e54362468e5090 100644 (file)
@@ -34,7 +34,7 @@ bdb_dn2entry(
        struct berval *dn,
        EntryInfo **e,
        int matched,
-       u_int32_t locker,
+       BDB_LOCKER locker,
        DB_LOCK *lock )
 {
        EntryInfo *ei = NULL;
index 07acfeb2d51d04522d208135f04e8855fbbf2dc2..3f83cf4fc6944799f0db63f575c2898f4976e852 100644 (file)
@@ -332,7 +332,7 @@ bdb_dn2id_children(
 int
 bdb_dn2idl(
        Operation *op,
-       u_int32_t locker,
+       BDB_LOCKER locker,
        struct berval *ndn,
        EntryInfo *ei,
        ID *ids,
@@ -712,7 +712,7 @@ int
 hdb_dn2id_parent(
        Operation *op,
        DB_TXN *txn,
-       u_int32_t       locker,
+       BDB_LOCKER      locker,
        EntryInfo *ei,
        ID *idp )
 {
@@ -738,7 +738,7 @@ hdb_dn2id_parent(
        rc = db->cursor( db, txn, &cursor, bdb->bi_db_opflags );
        if ( rc ) return rc;
        if ( !txn && locker ) {
-               cursor->locker = locker;
+               CURSOR_SETLOCKER(cursor, locker);
        }
 
        data.ulen = sizeof(diskNode) + (SLAP_LDAPDN_MAXLEN * 2);
@@ -833,7 +833,7 @@ hdb_dn2id_children(
 struct dn2id_cookie {
        struct bdb_info *bdb;
        Operation *op;
-       u_int32_t locker;
+       BDB_LOCKER locker;
        EntryInfo *ei;
        ID *ids;
        ID *tmp;
@@ -1064,7 +1064,7 @@ gotit:
 int
 hdb_dn2idl(
        Operation       *op,
-       u_int32_t locker,
+       BDB_LOCKER locker,
        struct berval *ndn,
        EntryInfo       *ei,
        ID *ids,
index e88395f784277f0733963635dd86f22f48a0ae82..cd41d4eaccc0123f47d11dfabee47901ac110404 100644 (file)
 
 static int presence_candidates(
        Operation *op,
-       u_int32_t locker,
+       BDB_LOCKER locker,
        AttributeDescription *desc,
        ID *ids );
 
 static int equality_candidates(
        Operation *op,
-       u_int32_t locker,
+       BDB_LOCKER locker,
        AttributeAssertion *ava,
        ID *ids,
        ID *tmp );
 static int inequality_candidates(
        Operation *op,
-       u_int32_t locker,
+       BDB_LOCKER locker,
        AttributeAssertion *ava,
        ID *ids,
        ID *tmp,
        int gtorlt );
 static int approx_candidates(
        Operation *op,
-       u_int32_t locker,
+       BDB_LOCKER locker,
        AttributeAssertion *ava,
        ID *ids,
        ID *tmp );
 static int substring_candidates(
        Operation *op,
-       u_int32_t locker,
+       BDB_LOCKER locker,
        SubstringsAssertion *sub,
        ID *ids,
        ID *tmp );
 
 static int list_candidates(
        Operation *op,
-       u_int32_t locker,
+       BDB_LOCKER locker,
        Filter *flist,
        int ftype,
        ID *ids,
@@ -69,7 +69,7 @@ static int list_candidates(
 static int
 ext_candidates(
         Operation *op,
-               u_int32_t locker,
+               BDB_LOCKER locker,
         MatchingRuleAssertion *mra,
         ID *ids,
         ID *tmp,
@@ -79,7 +79,7 @@ ext_candidates(
 static int
 comp_candidates (
        Operation *op,
-       u_int32_t locker,
+       BDB_LOCKER locker,
        MatchingRuleAssertion *mra,
        ComponentFilter *f,
        ID *ids,
@@ -89,7 +89,7 @@ comp_candidates (
 static int
 ava_comp_candidates (
                Operation *op,
-               u_int32_t locker,
+               BDB_LOCKER locker,
                AttributeAssertion *ava,
                AttributeAliasing *aa,
                ID *ids,
@@ -100,7 +100,7 @@ ava_comp_candidates (
 int
 bdb_filter_candidates(
        Operation *op,
-       u_int32_t locker,
+       BDB_LOCKER locker,
        Filter  *f,
        ID *ids,
        ID *tmp,
@@ -231,7 +231,7 @@ out:
 static int
 comp_list_candidates(
        Operation *op,
-       u_int32_t locker,
+       BDB_LOCKER locker,
        MatchingRuleAssertion* mra,
        ComponentFilter *flist,
        int     ftype,
@@ -296,7 +296,7 @@ comp_list_candidates(
 static int
 comp_equality_candidates (
         Operation *op,
-       u_int32_t locker,
+       BDB_LOCKER locker,
         MatchingRuleAssertion *mra,
        ComponentAssertion *ca,
         ID *ids,
@@ -344,9 +344,6 @@ comp_equality_candidates (
         if( rc != LDAP_SUCCESS ) {
                 return 0;
         }
-        if ( db == NULL ) {
-                return 0;
-        }
 
         if( !mr ) {
                 return 0;
@@ -410,7 +407,7 @@ comp_equality_candidates (
 static int
 ava_comp_candidates (
        Operation *op,
-       u_int32_t locker,
+       BDB_LOCKER locker,
        AttributeAssertion *ava,
        AttributeAliasing *aa,
        ID *ids,
@@ -434,7 +431,7 @@ ava_comp_candidates (
 static int
 comp_candidates (
        Operation *op,
-       u_int32_t locker,
+       BDB_LOCKER locker,
        MatchingRuleAssertion *mra,
        ComponentFilter *f,
        ID *ids,
@@ -483,7 +480,7 @@ comp_candidates (
 static int
 ext_candidates(
         Operation *op,
-               u_int32_t locker,
+               BDB_LOCKER locker,
         MatchingRuleAssertion *mra,
         ID *ids,
         ID *tmp,
@@ -562,7 +559,7 @@ ext_candidates(
 static int
 list_candidates(
        Operation *op,
-       u_int32_t locker,
+       BDB_LOCKER locker,
        Filter  *flist,
        int             ftype,
        ID *ids,
@@ -628,7 +625,7 @@ list_candidates(
 static int
 presence_candidates(
        Operation *op,
-       u_int32_t locker,
+       BDB_LOCKER locker,
        AttributeDescription *desc,
        ID *ids )
 {
@@ -650,19 +647,19 @@ presence_candidates(
        rc = bdb_index_param( op->o_bd, desc, LDAP_FILTER_PRESENT,
                &db, &mask, &prefix );
 
-       if( rc != LDAP_SUCCESS ) {
+       if( rc == LDAP_INAPPROPRIATE_MATCHING ) {
+               /* not indexed */
                Debug( LDAP_DEBUG_TRACE,
-                       "<= bdb_presence_candidates: (%s) index_param "
-                       "returned=%d\n",
-                       desc->ad_cname.bv_val, rc, 0 );
+                       "<= bdb_presence_candidates: (%s) not indexed\n",
+                       desc->ad_cname.bv_val, 0, 0 );
                return 0;
        }
 
-       if( db == NULL ) {
-               /* not indexed */
+       if( rc != LDAP_SUCCESS ) {
                Debug( LDAP_DEBUG_TRACE,
-                       "<= bdb_presence_candidates: (%s) not indexed\n",
-                       desc->ad_cname.bv_val, 0, 0 );
+                       "<= bdb_presence_candidates: (%s) index_param "
+                       "returned=%d\n",
+                       desc->ad_cname.bv_val, rc, 0 );
                return 0;
        }
 
@@ -699,7 +696,7 @@ done:
 static int
 equality_candidates(
        Operation *op,
-       u_int32_t locker,
+       BDB_LOCKER locker,
        AttributeAssertion *ava,
        ID *ids,
        ID *tmp )
@@ -721,18 +718,18 @@ equality_candidates(
        rc = bdb_index_param( op->o_bd, ava->aa_desc, LDAP_FILTER_EQUALITY,
                &db, &mask, &prefix );
 
-       if( rc != LDAP_SUCCESS ) {
+       if ( rc == LDAP_INAPPROPRIATE_MATCHING ) {
                Debug( LDAP_DEBUG_ANY,
-                       "<= bdb_equality_candidates: (%s) "
-                       "index_param failed (%d)\n",
-                       ava->aa_desc->ad_cname.bv_val, rc, 0 );
+                       "<= bdb_equality_candidates: (%s) not indexed\n", 
+                       ava->aa_desc->ad_cname.bv_val, 0, 0 );
                return 0;
        }
 
-       if ( db == NULL ) {
+       if( rc != LDAP_SUCCESS ) {
                Debug( LDAP_DEBUG_ANY,
-                       "<= bdb_equality_candidates: (%s) not indexed\n", 
-                       ava->aa_desc->ad_cname.bv_val, 0, 0 );
+                       "<= bdb_equality_candidates: (%s) "
+                       "index_param failed (%d)\n",
+                       ava->aa_desc->ad_cname.bv_val, rc, 0 );
                return 0;
        }
 
@@ -816,7 +813,7 @@ equality_candidates(
 static int
 approx_candidates(
        Operation *op,
-       u_int32_t locker,
+       BDB_LOCKER locker,
        AttributeAssertion *ava,
        ID *ids,
        ID *tmp )
@@ -838,18 +835,18 @@ approx_candidates(
        rc = bdb_index_param( op->o_bd, ava->aa_desc, LDAP_FILTER_APPROX,
                &db, &mask, &prefix );
 
-       if( rc != LDAP_SUCCESS ) {
+       if ( rc == LDAP_INAPPROPRIATE_MATCHING ) {
                Debug( LDAP_DEBUG_ANY,
-                       "<= bdb_approx_candidates: (%s) "
-                       "index_param failed (%d)\n",
-                       ava->aa_desc->ad_cname.bv_val, rc, 0 );
+                       "<= bdb_approx_candidates: (%s) not indexed\n",
+                       ava->aa_desc->ad_cname.bv_val, 0, 0 );
                return 0;
        }
 
-       if ( db == NULL ) {
+       if( rc != LDAP_SUCCESS ) {
                Debug( LDAP_DEBUG_ANY,
-                       "<= bdb_approx_candidates: (%s) not indexed\n",
-                       ava->aa_desc->ad_cname.bv_val, 0, 0 );
+                       "<= bdb_approx_candidates: (%s) "
+                       "index_param failed (%d)\n",
+                       ava->aa_desc->ad_cname.bv_val, rc, 0 );
                return 0;
        }
 
@@ -936,7 +933,7 @@ approx_candidates(
 static int
 substring_candidates(
        Operation *op,
-       u_int32_t locker,
+       BDB_LOCKER locker,
        SubstringsAssertion     *sub,
        ID *ids,
        ID *tmp )
@@ -958,18 +955,18 @@ substring_candidates(
        rc = bdb_index_param( op->o_bd, sub->sa_desc, LDAP_FILTER_SUBSTRINGS,
                &db, &mask, &prefix );
 
-       if( rc != LDAP_SUCCESS ) {
+       if ( rc == LDAP_INAPPROPRIATE_MATCHING ) {
                Debug( LDAP_DEBUG_ANY,
-                       "<= bdb_substring_candidates: (%s) "
-                       "index_param failed (%d)\n",
-                       sub->sa_desc->ad_cname.bv_val, rc, 0 );
+                       "<= bdb_substring_candidates: (%s) not indexed\n",
+                       sub->sa_desc->ad_cname.bv_val, 0, 0 );
                return 0;
        }
 
-       if ( db == NULL ) {
+       if( rc != LDAP_SUCCESS ) {
                Debug( LDAP_DEBUG_ANY,
-                       "<= bdb_substring_candidates: (%s) not indexed\n",
-                       sub->sa_desc->ad_cname.bv_val, 0, 0 );
+                       "<= bdb_substring_candidates: (%s) "
+                       "index_param failed (%d)\n",
+                       sub->sa_desc->ad_cname.bv_val, rc, 0 );
                return 0;
        }
 
@@ -1052,7 +1049,7 @@ substring_candidates(
 static int
 inequality_candidates(
        Operation *op,
-       u_int32_t locker,
+       BDB_LOCKER locker,
        AttributeAssertion *ava,
        ID *ids,
        ID *tmp,
@@ -1075,18 +1072,18 @@ inequality_candidates(
        rc = bdb_index_param( op->o_bd, ava->aa_desc, LDAP_FILTER_EQUALITY,
                &db, &mask, &prefix );
 
-       if( rc != LDAP_SUCCESS ) {
+       if ( rc == LDAP_INAPPROPRIATE_MATCHING ) {
                Debug( LDAP_DEBUG_ANY,
-                       "<= bdb_inequality_candidates: (%s) "
-                       "index_param failed (%d)\n",
-                       ava->aa_desc->ad_cname.bv_val, rc, 0 );
+                       "<= bdb_inequality_candidates: (%s) not indexed\n", 
+                       ava->aa_desc->ad_cname.bv_val, 0, 0 );
                return 0;
        }
 
-       if ( db == NULL ) {
+       if( rc != LDAP_SUCCESS ) {
                Debug( LDAP_DEBUG_ANY,
-                       "<= bdb_inequality_candidates: (%s) not indexed\n", 
-                       ava->aa_desc->ad_cname.bv_val, 0, 0 );
+                       "<= bdb_inequality_candidates: (%s) "
+                       "index_param failed (%d)\n",
+                       ava->aa_desc->ad_cname.bv_val, rc, 0 );
                return 0;
        }
 
index 5c693c14a74040f2c712729cf8df8b6fd9e96380..98c75bb9fa952e6b69ca561d72b4b2edf30c8c9f 100644 (file)
@@ -93,7 +93,7 @@ int bdb_id2entry_update(
 int bdb_id2entry(
        BackendDB *be,
        DB_TXN *tid,
-       u_int32_t locker,
+       BDB_LOCKER locker,
        ID id,
        Entry **e )
 {
@@ -121,26 +121,27 @@ int bdb_id2entry(
        if ( rc ) return rc;
 
        /* Use our own locker if needed */
-       if ( !tid && locker )
-               cursor->locker = locker;
+       if ( !tid && locker ) {
+               CURSOR_SETLOCKER( cursor, locker );
+       }
 
        /* Get the nattrs / nvals counts first */
        data.ulen = data.dlen = sizeof(buf);
        data.data = buf;
        rc = cursor->c_get( cursor, &key, &data, DB_SET );
-       if ( rc ) goto leave;
+       if ( rc ) goto finish;
 
 
        eh.bv.bv_val = buf;
        eh.bv.bv_len = data.size;
        rc = entry_header( &eh );
-       if ( rc ) goto leave;
+       if ( rc ) goto finish;
 
        /* Get the size */
        data.flags ^= DB_DBT_PARTIAL;
        data.ulen = 0;
        rc = cursor->c_get( cursor, &key, &data, DB_CURRENT );
-       if ( rc != DB_BUFFER_SMALL ) goto leave;
+       if ( rc != DB_BUFFER_SMALL ) goto finish;
 
        /* Allocate a block and retrieve the data */
        off = eh.data - eh.bv.bv_val;
@@ -155,7 +156,7 @@ int bdb_id2entry(
 
        rc = cursor->c_get( cursor, &key, &data, DB_CURRENT );
 
-leave:
+finish:
        cursor->c_close( cursor );
 
        if( rc != 0 ) {
@@ -317,7 +318,7 @@ int bdb_entry_get(
        int     rc;
        const char *at_name = at ? at->ad_cname.bv_val : "(null)";
 
-       u_int32_t       locker = 0;
+       BDB_LOCKER      locker = 0;
        DB_LOCK         lock;
        int             free_lock_id = 0;
 
index c84486d79040e2ddc2a5aa79cd3351680f0eff5d..35d6d4890d4d228f5fb6f51a262e6621b7997f79 100644 (file)
@@ -480,7 +480,7 @@ int
 bdb_idl_fetch_key(
        BackendDB       *be,
        DB                      *db,
-       u_int32_t locker,
+       BDB_LOCKER locker,
        DBT                     *key,
        ID                      *ids,
        DBC                     **saved_cursor,
@@ -559,7 +559,7 @@ bdb_idl_fetch_key(
                                "cursor failed: %s (%d)\n", db_strerror(rc), rc, 0 );
                        return rc;
                }
-               cursor->locker = locker;
+               CURSOR_SETLOCKER( cursor, locker );
        } else {
                cursor = *saved_cursor;
        }
index 94d181de7e3dfe7a86d20d4f37228731d042a97b..e193dae30d90e5ab122931421e12b28f2dbe0ac5 100644 (file)
@@ -97,12 +97,32 @@ int bdb_index_param(
 {
        AttrInfo *ai;
        int rc;
-       slap_mask_t mask;
+       slap_mask_t mask, type = 0;
        DB *db;
 
        ai = index_mask( be, desc, prefixp );
 
-       if( !ai ) {
+       if ( !ai ) {
+#ifdef BDB_MONITOR_IDX
+               switch ( ftype ) {
+               case LDAP_FILTER_PRESENT:
+                       type = SLAP_INDEX_PRESENT;
+                       break;
+               case LDAP_FILTER_APPROX:
+                       type = SLAP_INDEX_APPROX;
+                       break;
+               case LDAP_FILTER_EQUALITY:
+                       type = SLAP_INDEX_EQUALITY;
+                       break;
+               case LDAP_FILTER_SUBSTRINGS:
+                       type = SLAP_INDEX_SUBSTR;
+                       break;
+               default:
+                       return LDAP_INAPPROPRIATE_MATCHING;
+               }
+               bdb_monitor_idx_add( be->be_private, desc, type );
+#endif /* BDB_MONITOR_IDX */
+
                return LDAP_INAPPROPRIATE_MATCHING;
        }
        mask = ai->ai_indexmask;
@@ -115,6 +135,7 @@ int bdb_index_param(
 
        switch( ftype ) {
        case LDAP_FILTER_PRESENT:
+               type = SLAP_INDEX_PRESENT;
                if( IS_SLAP_INDEX( mask, SLAP_INDEX_PRESENT ) ) {
                        *prefixp = presence_key;
                        goto done;
@@ -122,6 +143,7 @@ int bdb_index_param(
                break;
 
        case LDAP_FILTER_APPROX:
+               type = SLAP_INDEX_APPROX;
                if ( desc->ad_type->sat_approx ) {
                        if( IS_SLAP_INDEX( mask, SLAP_INDEX_APPROX ) ) {
                                goto done;
@@ -133,12 +155,14 @@ int bdb_index_param(
                /* fall thru */
 
        case LDAP_FILTER_EQUALITY:
+               type = SLAP_INDEX_EQUALITY;
                if( IS_SLAP_INDEX( mask, SLAP_INDEX_EQUALITY ) ) {
                        goto done;
                }
                break;
 
        case LDAP_FILTER_SUBSTRINGS:
+               type = SLAP_INDEX_SUBSTR;
                if( IS_SLAP_INDEX( mask, SLAP_INDEX_SUBSTR ) ) {
                        goto done;
                }
@@ -148,6 +172,10 @@ int bdb_index_param(
                return LDAP_OTHER;
        }
 
+#ifdef BDB_MONITOR_IDX
+       bdb_monitor_idx_add( be->be_private, desc, type );
+#endif /* BDB_MONITOR_IDX */
+
        return LDAP_INAPPROPRIATE_MATCHING;
 
 done:
@@ -435,6 +463,10 @@ int bdb_index_recrun(
        AttrList *al;
        int i, rc = 0;
 
+       /* Never index ID 0 */
+       if ( id == 0 )
+               return 0;
+
        for (i=base; i<bdb->bi_nattrs; i+=slap_tool_thread_max) {
                ir = ir0 + i;
                if ( !ir->ai ) continue;
@@ -472,6 +504,10 @@ bdb_index_entry(
        struct berval value = {0};
 #endif
 
+       /* Never index ID 0 */
+       if ( e->e_id == 0 )
+               return 0;
+
        Debug( LDAP_DEBUG_TRACE, "=> index_entry_%s( %ld, \"%s\" )\n",
                opid == SLAP_INDEX_DELETE_OP ? "del" : "add",
                (long) e->e_id, e->e_dn );
index e4566c67bed7531c30bf5004810536888d390116..01af4c2c4682e5559ef6c034fa5b99e237400850 100644 (file)
@@ -26,6 +26,7 @@
 #include <lutil.h>
 #include <ldap_rq.h>
 #include "alock.h"
+#include "config.h"
 
 static const struct bdbi_database {
        char *file;
@@ -41,8 +42,12 @@ static const struct bdbi_database {
 typedef void * db_malloc(size_t);
 typedef void * db_realloc(void *, size_t);
 
+#define bdb_db_init    BDB_SYMBOL(db_init)
+#define bdb_db_open BDB_SYMBOL(db_open)
+#define bdb_db_close BDB_SYMBOL(db_close)
+
 static int
-bdb_db_init( BackendDB *be )
+bdb_db_init( BackendDB *be, ConfigReply *cr )
 {
        struct bdb_info *bdb;
        int rc;
@@ -79,15 +84,6 @@ bdb_db_init( BackendDB *be )
        ldap_pvt_thread_rdwr_init( &bdb->bi_idl_tree_rwlock );
        ldap_pvt_thread_mutex_init( &bdb->bi_idl_tree_lrulock );
 
-       {
-               Entry *e = entry_alloc();
-               e->e_id = 0;
-               e->e_private = &bdb->bi_cache.c_dntree;
-               BER_BVSTR( &e->e_name, "" );
-               BER_BVSTR( &e->e_nname, "" );
-               bdb->bi_cache.c_dntree.bei_e = e;
-       }
-
        be->be_private = bdb;
        be->be_cf_ocs = be->bd_info->bi_cf_ocs;
 
@@ -97,10 +93,10 @@ bdb_db_init( BackendDB *be )
 }
 
 static int
-bdb_db_close( BackendDB *be );
+bdb_db_close( BackendDB *be, ConfigReply *cr );
 
 static int
-bdb_db_open( BackendDB *be )
+bdb_db_open( BackendDB *be, ConfigReply *cr )
 {
        int rc, i;
        struct bdb_info *bdb = (struct bdb_info *) be->be_private;
@@ -108,24 +104,28 @@ bdb_db_open( BackendDB *be )
        u_int32_t flags;
        char path[MAXPATHLEN];
        char *dbhome;
+       Entry *e = NULL;
        int do_recover = 0, do_alock_recover = 0;
        int alockt, quick = 0;
 
        if ( be->be_suffix == NULL ) {
                Debug( LDAP_DEBUG_ANY,
-                       "bdb_db_open: need suffix\n",
-                       0, 0, 0 );
+                       LDAP_XSTRING(bdb_db_open) ": need suffix\n",
+                       1, 0, 0 );
                return -1;
        }
 
        Debug( LDAP_DEBUG_ARGS,
-               "bdb_db_open: %s\n",
+               LDAP_XSTRING(bdb_db_open) ": %s\n",
                be->be_suffix[0].bv_val, 0, 0 );
 
 #ifndef BDB_MULTIPLE_SUFFIXES
        if ( be->be_suffix[1].bv_val ) {
-       Debug( LDAP_DEBUG_ANY,
-               "bdb_db_open: only one suffix allowed\n", 0, 0, 0 );
+               if (cr) {
+                       snprintf(cr->msg, sizeof(cr->msg), "only one suffix allowed");
+                       Debug( LDAP_DEBUG_ANY,
+                               LDAP_XSTRING(bdb_db_open) ": %s\n", cr->msg, 0, 0 );
+               }
                return -1;
        }
 #endif
@@ -134,9 +134,9 @@ bdb_db_open( BackendDB *be )
        rc = stat( bdb->bi_dbenv_home, &stat1 );
        if( rc !=0 ) {
                Debug( LDAP_DEBUG_ANY,
-                       "bdb_db_open: Cannot access database directory %s (%d)\n",
+                       LDAP_XSTRING(bdb_db_open) ": Cannot access database directory %s (%d)\n",
                        bdb->bi_dbenv_home, errno, 0 );
-                       return -1;
+               return -1;
        }
 
        /* Perform database use arbitration/recovery logic */
@@ -156,19 +156,19 @@ bdb_db_open( BackendDB *be )
 
        if( rc == ALOCK_RECOVER ) {
                Debug( LDAP_DEBUG_ANY,
-                       "bdb_db_open: unclean shutdown detected;"
+                       LDAP_XSTRING(bdb_db_open) ": unclean shutdown detected;"
                        " attempting recovery.\n", 
                        0, 0, 0 );
                do_alock_recover = 1;
                do_recover = DB_RECOVER;
        } else if( rc == ALOCK_BUSY ) {
                Debug( LDAP_DEBUG_ANY,
-                       "bdb_db_open: database already in use\n", 
+                       LDAP_XSTRING(bdb_db_open) ": database already in use\n", 
                        0, 0, 0 );
                return -1;
        } else if( rc != ALOCK_CLEAN ) {
                Debug( LDAP_DEBUG_ANY,
-                       "bdb_db_open: alock package is unstable\n", 
+                       LDAP_XSTRING(bdb_db_open) ": alock package is unstable\n", 
                        0, 0, 0 );
                return -1;
        }
@@ -186,7 +186,7 @@ bdb_db_open( BackendDB *be )
                        if( stat( path, &stat2 ) == 0 ) {
                                if( stat2.st_mtime < stat1.st_mtime ) {
                                        Debug( LDAP_DEBUG_ANY,
-                                               "bdb_db_open: DB_CONFIG for suffix %s has changed.\n"
+                                               LDAP_XSTRING(bdb_db_open) ": DB_CONFIG for suffix %s has changed.\n"
                                                "Performing database recovery to activate new settings.\n",
                                                be->be_suffix[0].bv_val, 0, 0 );
                                        do_recover = DB_RECOVER;
@@ -196,7 +196,7 @@ bdb_db_open( BackendDB *be )
        }
        else {
                Debug( LDAP_DEBUG_ANY,
-                       "bdb_db_open: Warning - No DB_CONFIG file found "
+                       LDAP_XSTRING(bdb_db_open) ": Warning - No DB_CONFIG file found "
                        "in directory %s: (%d)\n"
                        "Expect poor performance for suffix %s.\n",
                        bdb->bi_dbenv_home, errno, be->be_suffix[0].bv_val );
@@ -208,7 +208,7 @@ bdb_db_open( BackendDB *be )
         */
        if ( do_recover && ( slapMode & SLAP_TOOL_READONLY )) {
                Debug( LDAP_DEBUG_ANY,
-                       "bdb_db_open: Recovery skipped in read-only mode. "
+                       LDAP_XSTRING(bdb_db_open) ": Recovery skipped in read-only mode. "
                        "Run manual recovery if errors are encountered.\n",
                        0, 0, 0 );
                do_recover = 0;
@@ -218,7 +218,7 @@ bdb_db_open( BackendDB *be )
        /* An existing environment in Quick mode has nothing to recover. */
        if ( alockt && do_recover ) {
                Debug( LDAP_DEBUG_ANY,
-                       "bdb_db_open: cannot recover, database must be reinitialized.\n", 
+                       LDAP_XSTRING(bdb_db_open) ": cannot recover, database must be reinitialized.\n", 
                        0, 0, 0 );
                rc = -1;
                goto fail;
@@ -227,7 +227,7 @@ bdb_db_open( BackendDB *be )
        rc = db_env_create( &bdb->bi_dbenv, 0 );
        if( rc != 0 ) {
                Debug( LDAP_DEBUG_ANY,
-                       "bdb_db_open: db_env_create failed: %s (%d)\n",
+                       LDAP_XSTRING(bdb_db_open) ": db_env_create failed: %s (%d)\n",
                        db_strerror(rc), rc, 0 );
                goto fail;
        }
@@ -244,10 +244,11 @@ bdb_db_open( BackendDB *be )
         * currently requested modes, remove it.
         */
        if ( !do_recover && ( alockt ^ quick )) {
+shm_retry:
                rc = bdb->bi_dbenv->remove( bdb->bi_dbenv, dbhome, DB_FORCE );
                if ( rc ) {
                        Debug( LDAP_DEBUG_ANY,
-                               "bdb_db_open: dbenv remove failed: %s (%d)\n",
+                               LDAP_XSTRING(bdb_db_open) ": dbenv remove failed: %s (%d)\n",
                                db_strerror(rc), rc, 0 );
                        bdb->bi_dbenv = NULL;
                        goto fail;
@@ -255,7 +256,7 @@ bdb_db_open( BackendDB *be )
                rc = db_env_create( &bdb->bi_dbenv, 0 );
                if( rc != 0 ) {
                        Debug( LDAP_DEBUG_ANY,
-                               "bdb_db_open: db_env_create failed: %s (%d)\n",
+                               LDAP_XSTRING(bdb_db_open) ": db_env_create failed: %s (%d)\n",
                                db_strerror(rc), rc, 0 );
                        goto fail;
                }
@@ -274,7 +275,7 @@ bdb_db_open( BackendDB *be )
                        bdb->bi_dbenv_xflags, 1);
                if( rc != 0 ) {
                        Debug( LDAP_DEBUG_ANY,
-                               "bdb_db_open: dbenv_set_flags failed: %s (%d)\n",
+                               LDAP_XSTRING(bdb_db_open) ": dbenv_set_flags failed: %s (%d)\n",
                                db_strerror(rc), rc, 0 );
                        goto fail;
                }
@@ -283,7 +284,7 @@ bdb_db_open( BackendDB *be )
 #define        BDB_TXN_FLAGS   (DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_TXN)
 
        Debug( LDAP_DEBUG_TRACE,
-               "bdb_db_open: dbenv_open(%s)\n",
+               LDAP_XSTRING(bdb_db_open) ": dbenv_open(%s)\n",
                bdb->bi_dbenv_home, 0, 0);
 
        flags = DB_INIT_MPOOL | DB_CREATE | DB_THREAD;
@@ -296,12 +297,25 @@ bdb_db_open( BackendDB *be )
                bdb->bi_dbenv->set_shm_key( bdb->bi_dbenv, bdb->bi_shm_key );
                flags |= DB_SYSTEM_MEM;
        }
-       rc = bdb->bi_dbenv->open( bdb->bi_dbenv, dbhome,
+       rc = (bdb->bi_dbenv->open)( bdb->bi_dbenv, dbhome,
                        flags | do_recover, bdb->bi_dbenv_mode );
 
        if ( rc ) {
+               /* Regular open failed, probably a missing shm environment.
+                * Start over, do a recovery.
+                */
+               if ( !do_recover && bdb->bi_shm_key ) {
+                       bdb->bi_dbenv->close( bdb->bi_dbenv, 0 );
+                       rc = db_env_create( &bdb->bi_dbenv, 0 );
+                       if( rc == 0 ) {
+                               Debug( LDAP_DEBUG_ANY, LDAP_XSTRING(bdb_db_open)
+                                       ": Shared memory env open failed, assuming stale env\n",
+                                       0, 0, 0 );
+                               goto shm_retry;
+                       }
+               }
                Debug( LDAP_DEBUG_ANY,
-                       "bdb_db_open: Database cannot be %s, err %d. "
+                       LDAP_XSTRING(bdb_db_open) ": Database cannot be %s, err %d. "
                        "Restore from backup!\n",
                                do_recover ? "recovered" : "opened", rc, 0);
                goto fail;
@@ -309,7 +323,7 @@ bdb_db_open( BackendDB *be )
 
        if ( do_alock_recover && alock_recover (&bdb->bi_alock_info) != 0 ) {
                Debug( LDAP_DEBUG_ANY,
-                       "bdb_db_open: alock_recover failed\n",
+                       LDAP_XSTRING(bdb_db_open) ": alock_recover failed\n",
                        0, 0, 0 );
                rc = -1;
                goto fail;
@@ -323,6 +337,11 @@ bdb_db_open( BackendDB *be )
        }
 #endif
 
+       /* Default dncache to 2x entrycache */
+       if ( bdb->bi_cache.c_maxsize && !bdb->bi_cache.c_eimax ) {
+               bdb->bi_cache.c_eimax = bdb->bi_cache.c_maxsize * 2;
+       }
+
        if ( bdb->bi_idl_cache_max_size ) {
                bdb->bi_idl_tree = NULL;
                bdb->bi_idl_cache_size = 0;
@@ -347,7 +366,7 @@ bdb_db_open( BackendDB *be )
                rc = db_create( &db->bdi_db, bdb->bi_dbenv, 0 );
                if( rc != 0 ) {
                        Debug( LDAP_DEBUG_ANY,
-                               "bdb_db_open: db_create(%s) failed: %s (%d)\n",
+                               LDAP_XSTRING(bdb_db_open) ": db_create(%s) failed: %s (%d)\n",
                                bdb->bi_dbenv_home, db_strerror(rc), rc );
                        goto fail;
                }
@@ -408,7 +427,7 @@ bdb_db_open( BackendDB *be )
                        snprintf( buf, sizeof(buf), "%s/%s", 
                                bdb->bi_dbenv_home, bdbi_databases[i].file );
                        Debug( LDAP_DEBUG_ANY,
-                               "bdb_db_open: db_open(%s) failed: %s (%d)\n",
+                               LDAP_XSTRING(bdb_db_open) ": db_open(%s) failed: %s (%d)\n",
                                buf, db_strerror(rc), rc );
                        db->bdi_db->close( db->bdi_db, 0 );
                        goto fail;
@@ -426,15 +445,38 @@ bdb_db_open( BackendDB *be )
        rc = bdb_last_id( be, NULL );
        if( rc != 0 ) {
                Debug( LDAP_DEBUG_ANY,
-                       "bdb_db_open: last_id(%s) failed: %s (%d)\n",
+                       LDAP_XSTRING(bdb_db_open) ": last_id(%s) failed: %s (%d)\n",
                        bdb->bi_dbenv_home, db_strerror(rc), rc );
                goto fail;
        }
 
        if ( !quick ) {
+#if DB_VERSION_FULL >= 0x04060012
+               u_int32_t lid;
+               XLOCK_ID(bdb->bi_dbenv, &lid);
+               __lock_getlocker(bdb->bi_dbenv->lk_handle, lid, 0, &bdb->bi_cache.c_locker);
+#else
                XLOCK_ID(bdb->bi_dbenv, &bdb->bi_cache.c_locker);
+#endif
        }
 
+       entry_prealloc( bdb->bi_cache.c_maxsize );
+       attr_prealloc( bdb->bi_cache.c_maxsize * 20 );
+
+       /* setup for empty-DN contexts */
+       if ( BER_BVISEMPTY( &be->be_nsuffix[0] )) {
+               rc = bdb_id2entry( be, NULL, 0, 0, &e );
+       }
+       if ( !e ) {
+               e = entry_alloc();
+               e->e_id = 0;
+               ber_dupbv( &e->e_name, (struct berval *)&slap_empty_bv );
+               ber_dupbv( &e->e_nname, (struct berval *)&slap_empty_bv );
+       }
+       e->e_ocflags = SLAP_OC_GLUE|SLAP_OC__END;
+       e->e_private = &bdb->bi_cache.c_dntree;
+       bdb->bi_cache.c_dntree.bei_e = e;
+
        /* monitor setup */
        rc = bdb_monitor_db_open( be );
        if ( rc != 0 ) {
@@ -443,17 +485,15 @@ bdb_db_open( BackendDB *be )
 
        bdb->bi_flags |= BDB_IS_OPEN;
 
-       entry_prealloc( bdb->bi_cache.c_maxsize );
-       attr_prealloc( bdb->bi_cache.c_maxsize * 20 );
        return 0;
 
 fail:
-       bdb_db_close( be );
+       bdb_db_close( be, NULL );
        return rc;
 }
 
 static int
-bdb_db_close( BackendDB *be )
+bdb_db_close( BackendDB *be, ConfigReply *cr )
 {
        int rc;
        struct bdb_info *bdb = (struct bdb_info *) be->be_private;
@@ -463,6 +503,15 @@ bdb_db_close( BackendDB *be )
        /* monitor handling */
        (void)bdb_monitor_db_close( be );
 
+       {
+               Entry *e = bdb->bi_cache.c_dntree.bei_e;
+               if ( e ) {
+                       bdb->bi_cache.c_dntree.bei_e = NULL;
+                       e->e_private = NULL;
+                       bdb_entry_return( e );
+               }
+       }
+
        bdb->bi_flags &= ~BDB_IS_OPEN;
 
        ber_bvarray_free( bdb->bi_db_config );
@@ -500,7 +549,11 @@ bdb_db_close( BackendDB *be )
        if( bdb->bi_dbenv ) {
                /* Free cache locker if we enabled locking */
                if ( !( slapMode & SLAP_TOOL_QUICK )) {
+#if DB_VERSION_FULL >= 0x04060012
+                       XLOCK_ID_FREE(bdb->bi_dbenv, bdb->bi_cache.c_locker->id);
+#else
                        XLOCK_ID_FREE(bdb->bi_dbenv, bdb->bi_cache.c_locker);
+#endif
                        bdb->bi_cache.c_locker = 0;
                }
 #ifdef BDB_REUSE_LOCKERS
@@ -539,7 +592,7 @@ bdb_db_close( BackendDB *be )
 }
 
 static int
-bdb_db_destroy( BackendDB *be )
+bdb_db_destroy( BackendDB *be, ConfigReply *cr )
 {
        struct bdb_info *bdb = (struct bdb_info *) be->be_private;
 
@@ -564,16 +617,6 @@ bdb_db_destroy( BackendDB *be )
        ldap_pvt_thread_rdwr_destroy( &bdb->bi_idl_tree_rwlock );
        ldap_pvt_thread_mutex_destroy( &bdb->bi_idl_tree_lrulock );
 
-       {
-               Entry *e;
-               e = bdb->bi_cache.c_dntree.bei_e;
-               bdb->bi_cache.c_dntree.bei_e = NULL;
-               e->e_private = NULL;
-               BER_BVZERO( &e->e_name );
-               BER_BVZERO( &e->e_nname );
-               entry_free( e );
-       }
-
        ch_free( bdb );
        be->be_private = NULL;
 
@@ -695,7 +738,6 @@ bdb_back_initialize(
        bi->bi_tool_entry_reindex = bdb_tool_entry_reindex;
        bi->bi_tool_sync = 0;
        bi->bi_tool_dn2id_get = bdb_tool_dn2id_get;
-       bi->bi_tool_id2entry_get = bdb_tool_id2entry_get;
        bi->bi_tool_entry_modify = bdb_tool_entry_modify;
 
        bi->bi_connection_init = 0;
index 7128a6c5dbd182d583c8d010ba2a43246df767cb..161caf7011e3fd7f45c26253fb269c2df7aa645b 100644 (file)
@@ -30,7 +30,7 @@ int
 bdb_key_read(
        Backend *be,
        DB *db,
-       u_int32_t locker,
+       BDB_LOCKER locker,
        struct berval *k,
        ID *ids,
        DBC **saved_cursor,
index 408ad24f6a4d1454d2366884790b75c6e0bddd79..df1cf3dfcad38c64a75ca3c54f3cdd6c9e07b42d 100644 (file)
@@ -281,7 +281,7 @@ bdb_modify( Operation *op, SlapReply *rs )
        Entry           dummy = {0};
        int                     fakeroot = 0;
 
-       u_int32_t       locker = 0;
+       BDB_LOCKER      locker = 0;
        DB_LOCK         lock;
 
        int             num_retries = 0;
@@ -522,7 +522,7 @@ retry:      /* transaction retry */
        }
        /* Modify the entry */
        dummy = *e;
-       rs->sr_err = bdb_modify_internal( op, lt2, op->oq_modify.rs_modlist,
+       rs->sr_err = bdb_modify_internal( op, lt2, op->orm_modlist,
                &dummy, &rs->sr_text, textbuf, textlen );
 
        if( rs->sr_err != LDAP_SUCCESS ) {
@@ -588,6 +588,8 @@ retry:      /* transaction retry */
                } else {
                        rs->sr_err = LDAP_X_NO_OPERATION;
                        ltid = NULL;
+                       /* Only free attrs if they were dup'd.  */
+                       if ( dummy.e_attrs == e->e_attrs ) dummy.e_attrs = NULL;
                        goto return_results;
                }
        } else {
index 1497a19822f5ac2c82003eea9f37171ce3635837..bb6dea16f3fdd2827c07a187c993ba3aa15d1c9a 100644 (file)
@@ -46,7 +46,7 @@ bdb_modrdn( Operation *op, SlapReply *rs )
 
        int             manageDSAit = get_manageDSAit( op );
 
-       u_int32_t       locker = 0;
+       BDB_LOCKER      locker = 0;
        DB_LOCK         lock, plock, nplock;
 
        int             num_retries = 0;
@@ -542,6 +542,8 @@ retry:      /* transaction retry */
                struct berval bv = {0, NULL};
                dnNormalize( 0, NULL, NULL, &new_dn, &bv, op->o_tmpmemctx );
                ber_dupbv( &new_ndn, &bv );
+               /* FIXME: why not call dnNormalize() w/o ctx? */
+               op->o_tmpfree( bv.bv_val, op->o_tmpmemctx );
        }
 
        Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(bdb_modrdn) ": new ndn=%s\n",
index 9114fac70b8ade71f5b883173f4b6eb4ddca6251..ffde364a270893baae2427d8c1705e33066fcd10 100644 (file)
 static ObjectClass             *oc_olmBDBDatabase;
 
 static AttributeDescription    *ad_olmBDBEntryCache,
-       *ad_olmBDBEntryInfo, *ad_olmBDBIDLCache,
+       *ad_olmBDBDNCache, *ad_olmBDBIDLCache,
        *ad_olmDbDirectory;
 
+#ifdef BDB_MONITOR_IDX
+static int
+bdb_monitor_idx_entry_add(
+       struct bdb_info *bdb,
+       Entry           *e );
+
+static AttributeDescription    *ad_olmBDBNotIndexed;
+#endif /* BDB_MONITOR_IDX */
+
 /*
  * NOTE: there's some confusion in monitor OID arc;
  * by now, let's consider:
@@ -71,12 +80,12 @@ static struct {
                &ad_olmBDBEntryCache },
 
        { "( olmBDBAttributes:2 "
-               "NAME ( 'olmBDBEntryInfo' ) "
-               "DESC 'Number of items in EntryInfo Cache' "
+               "NAME ( 'olmBDBDNCache' ) "
+               "DESC 'Number of items in DN Cache' "
                "SUP monitorCounter "
                "NO-USER-MODIFICATION "
                "USAGE dSAOperation )",
-               &ad_olmBDBEntryInfo },
+               &ad_olmBDBDNCache },
 
        { "( olmBDBAttributes:3 "
                "NAME ( 'olmBDBIDLCache' ) "
@@ -95,6 +104,16 @@ static struct {
                "USAGE dSAOperation )",
                &ad_olmDbDirectory },
 
+#ifdef BDB_MONITOR_IDX
+       { "( olmBDBAttributes:5 "
+               "NAME ( 'olmBDBNotIndexed' ) "
+               "DESC 'Missing indexes resulting from candidate selection' "
+               "SUP monitoredInfo "
+               "NO-USER-MODIFICATION "
+               "USAGE dSAOperation )",
+               &ad_olmBDBNotIndexed },
+#endif /* BDB_MONITOR_IDX */
+
        { NULL }
 };
 
@@ -109,9 +128,12 @@ static struct {
                "SUP top AUXILIARY "
                "MAY ( "
                        "olmBDBEntryCache "
-                       "$ olmBDBEntryInfo "
+                       "$ olmBDBDNCache "
                        "$ olmBDBIDLCache "
                        "$ olmDbDirectory "
+#ifdef BDB_MONITOR_IDX
+                       "$ olmBDBNotIndexed "
+#endif /* BDB_MONITOR_IDX */
                        ") )",
                &oc_olmBDBDatabase },
 
@@ -139,7 +161,7 @@ bdb_monitor_update(
        bv.bv_len = snprintf( buf, sizeof( buf ), "%d", bdb->bi_cache.c_cursize );
        ber_bvreplace( &a->a_vals[ 0 ], &bv );
 
-       a = attr_find( e->e_attrs, ad_olmBDBEntryInfo );
+       a = attr_find( e->e_attrs, ad_olmBDBDNCache );
        assert( a != NULL );
        bv.bv_len = snprintf( buf, sizeof( buf ), "%d", bdb->bi_cache.c_eiused );
        ber_bvreplace( &a->a_vals[ 0 ], &bv );
@@ -149,6 +171,10 @@ bdb_monitor_update(
        bv.bv_len = snprintf( buf, sizeof( buf ), "%d", bdb->bi_idl_cache_size );
        ber_bvreplace( &a->a_vals[ 0 ], &bv );
        
+#ifdef BDB_MONITOR_IDX
+       bdb_monitor_idx_entry_add( bdb, e );
+#endif /* BDB_MONITOR_IDX */
+
        return SLAP_CB_CONTINUE;
 }
 
@@ -275,11 +301,20 @@ bdb_monitor_db_init( BackendDB *be )
 {
        struct bdb_info         *bdb = (struct bdb_info *) be->be_private;
 
+       if ( SLAP_GLUE_SUBORDINATE( be ) ) {
+               return 0;
+       }
+
        if ( bdb_monitor_initialize() == LDAP_SUCCESS ) {
                /* monitoring in back-bdb is on by default */
                SLAP_DBFLAGS( be ) |= SLAP_DBFLAG_MONITORING;
        }
 
+#ifdef BDB_MONITOR_IDX
+       bdb->bi_idx = NULL;
+       ldap_pvt_thread_mutex_init( &bdb->bi_idx_mutex );
+#endif /* BDB_MONITOR_IDX */
+
        bdb->bi_monitor.bdm_scope = -1;
 
        return 0;
@@ -304,6 +339,10 @@ bdb_monitor_db_open( BackendDB *be )
                return 0;
        }
 
+       if ( SLAP_GLUE_SUBORDINATE( be ) ) {
+               return 0;
+       }
+
        mi = backend_info( "monitor" );
        if ( !mi || !mi->bi_extra ) {
                SLAP_DBFLAGS( be ) ^= SLAP_DBFLAG_MONITORING;
@@ -386,7 +425,7 @@ bdb_monitor_db_open( BackendDB *be )
                next->a_nvals = next->a_vals;
                next = next->a_next;
 
-               next->a_desc = ad_olmBDBEntryInfo;
+               next->a_desc = ad_olmBDBDNCache;
                value_add_one( &next->a_vals, &bv );
                next->a_nvals = next->a_vals;
                next = next->a_next;
@@ -455,8 +494,12 @@ bdb_monitor_db_open( BackendDB *be )
        cb->mc_free = bdb_monitor_free;
        cb->mc_private = (void *)bdb;
 
-       rc = mbe->register_entry_attrs( NULL, a, cb,
-               base, bdb->bi_monitor.bdm_scope, filter );
+       /* make sure the database is registered; then add monitor attributes */
+       rc = mbe->register_database( be );
+       if ( rc == 0 ) {
+               rc = mbe->register_entry_attrs( NULL, a, cb,
+                       base, bdb->bi_monitor.bdm_scope, filter );
+       }
 
 cleanup:;
        if ( rc != 0 ) {
@@ -496,6 +539,10 @@ bdb_monitor_db_close( BackendDB *be )
 {
        struct bdb_info         *bdb = (struct bdb_info *) be->be_private;
 
+       if ( SLAP_GLUE_SUBORDINATE( be ) ) {
+               return 0;
+       }
+
        if ( !BER_BVISNULL( &bdb->bi_monitor.bdm_filter ) ) {
                BackendInfo             *mi = backend_info( "monitor" );
                monitor_extra_t         *mbe;
@@ -525,5 +572,217 @@ bdb_monitor_db_close( BackendDB *be )
 int
 bdb_monitor_db_destroy( BackendDB *be )
 {
+       if ( SLAP_GLUE_SUBORDINATE( be ) ) {
+               return 0;
+       }
+
+#ifdef BDB_MONITOR_IDX
+       {
+               struct bdb_info         *bdb = (struct bdb_info *) be->be_private;
+
+               /* TODO: free tree */
+               ldap_pvt_thread_mutex_destroy( &bdb->bi_idx_mutex );
+               avl_free( bdb->bi_idx, ch_free );
+       }
+#endif /* BDB_MONITOR_IDX */
+
        return 0;
 }
+
+#ifdef BDB_MONITOR_IDX
+
+#define BDB_MONITOR_IDX_TYPES  (4)
+
+typedef struct monitor_idx_t monitor_idx_t;
+
+struct monitor_idx_t {
+       AttributeDescription    *idx_ad;
+       unsigned long           idx_count[BDB_MONITOR_IDX_TYPES];
+};
+
+static int
+bdb_monitor_bitmask2key( slap_mask_t bitmask )
+{
+       int     key;
+
+       for ( key = 0; key < 8*sizeof(slap_mask_t) && !( bitmask & 0x1U ); key++ ) {
+               bitmask >>= 1;
+       }
+
+       return key;
+}
+
+static struct berval idxbv[] = {
+       BER_BVC( "present=" ),
+       BER_BVC( "equality=" ),
+       BER_BVC( "approx=" ),
+       BER_BVC( "substr=" ),
+       BER_BVNULL
+};
+
+static ber_len_t
+bdb_monitor_idx2len( monitor_idx_t *idx )
+{
+       int             i;
+       ber_len_t       len = 0;
+
+       for ( i = 0; i < BDB_MONITOR_IDX_TYPES; i++ ) {
+               if ( idx->idx_count[ i ] != 0 ) {
+                       len += idxbv[i].bv_len;
+               }
+       }
+
+       return len;
+}
+
+static int
+monitor_idx_cmp( const void *p1, const void *p2 )
+{
+       const monitor_idx_t     *idx1 = (const monitor_idx_t *)p1;
+       const monitor_idx_t     *idx2 = (const monitor_idx_t *)p2;
+
+       return SLAP_PTRCMP( idx1->idx_ad, idx2->idx_ad );
+}
+
+static int
+monitor_idx_dup( void *p1, void *p2 )
+{
+       monitor_idx_t   *idx1 = (monitor_idx_t *)p1;
+       monitor_idx_t   *idx2 = (monitor_idx_t *)p2;
+
+       return SLAP_PTRCMP( idx1->idx_ad, idx2->idx_ad ) == 0 ? -1 : 0;
+}
+
+int
+bdb_monitor_idx_add(
+       struct bdb_info         *bdb,
+       AttributeDescription    *desc,
+       slap_mask_t             type )
+{
+       monitor_idx_t           idx_dummy = { 0 },
+                               *idx;
+       int                     rc = 0, key;
+
+       idx_dummy.idx_ad = desc;
+       key = bdb_monitor_bitmask2key( type ) - 1;
+       if ( key >= BDB_MONITOR_IDX_TYPES ) {
+               /* invalid index type */
+               return -1;
+       }
+
+       ldap_pvt_thread_mutex_lock( &bdb->bi_idx_mutex );
+
+       idx = (monitor_idx_t *)avl_find( bdb->bi_idx,
+               (caddr_t)&idx_dummy, monitor_idx_cmp );
+       if ( idx == NULL ) {
+               idx = (monitor_idx_t *)ch_calloc( sizeof( monitor_idx_t ), 1 );
+               idx->idx_ad = desc;
+               idx->idx_count[ key ] = 1;
+
+               switch ( avl_insert( &bdb->bi_idx, (caddr_t)idx, 
+                       monitor_idx_cmp, monitor_idx_dup ) )
+               {
+               case 0:
+                       break;
+
+               default:
+                       ch_free( idx );
+                       rc = -1;
+               }
+
+       } else {
+               idx->idx_count[ key ]++;
+       }
+
+       ldap_pvt_thread_mutex_unlock( &bdb->bi_idx_mutex );
+
+       return rc;
+}
+
+static int
+bdb_monitor_idx_apply( void *v_idx, void *v_valp )
+{
+       monitor_idx_t   *idx = (monitor_idx_t *)v_idx;
+       BerVarray       *valp = (BerVarray *)v_valp;
+
+       struct berval   bv;
+       char            *ptr;
+       char            count_buf[ BDB_MONITOR_IDX_TYPES ][ SLAP_TEXT_BUFLEN ];
+       ber_len_t       count_len[ BDB_MONITOR_IDX_TYPES ],
+                       idx_len;
+       int             i, num = 0;
+
+       idx_len = bdb_monitor_idx2len( idx );
+
+       bv.bv_len = 0;
+       for ( i = 0; i < BDB_MONITOR_IDX_TYPES; i++ ) {
+               if ( idx->idx_count[ i ] == 0 ) {
+                       continue;
+               }
+
+               count_len[ i ] = snprintf( count_buf[ i ],
+                       sizeof( count_buf[ i ] ), "%lu", idx->idx_count[ i ] );
+               bv.bv_len += count_len[ i ];
+               num++;
+       }
+
+       bv.bv_len += idx->idx_ad->ad_cname.bv_len
+               + num
+               + idx_len;
+       ptr = bv.bv_val = ch_malloc( bv.bv_len + 1 );
+       ptr = lutil_strcopy( ptr, idx->idx_ad->ad_cname.bv_val );
+       for ( i = 0; i < BDB_MONITOR_IDX_TYPES; i++ ) {
+               if ( idx->idx_count[ i ] == 0 ) {
+                       continue;
+               }
+
+               ptr[ 0 ] = '#';
+               ++ptr;
+               ptr = lutil_strcopy( ptr, idxbv[ i ].bv_val );
+               ptr = lutil_strcopy( ptr, count_buf[ i ] );
+       }
+
+       ber_bvarray_add( valp, &bv );
+
+       return 0;
+}
+
+static int
+bdb_monitor_idx_entry_add(
+       struct bdb_info *bdb,
+       Entry           *e )
+{
+       BerVarray       vals = NULL;
+       Attribute       *a;
+
+       a = attr_find( e->e_attrs, ad_olmBDBNotIndexed );
+
+       ldap_pvt_thread_mutex_lock( &bdb->bi_idx_mutex );
+
+       avl_apply( bdb->bi_idx, bdb_monitor_idx_apply,
+               &vals, -1, AVL_INORDER );
+
+       ldap_pvt_thread_mutex_unlock( &bdb->bi_idx_mutex );
+
+       if ( vals != NULL ) {
+               if ( a != NULL ) {
+                       assert( a->a_nvals == a->a_vals );
+
+                       ber_bvarray_free( a->a_vals );
+
+               } else {
+                       Attribute       **ap;
+
+                       for ( ap = &e->e_attrs; *ap != NULL; ap = &(*ap)->a_next )
+                               ;
+                       *ap = attr_alloc( ad_olmBDBNotIndexed );
+                       a = *ap;
+               }
+               a->a_vals = vals;
+               a->a_nvals = a->a_vals;
+       }
+
+       return 0;
+}
+
+#endif /* BDB_MONITOR_IDX */
index 77aaf6c68853f4d8deb82202b8ad8e6f1068a9f8..b69325f2aa65f64a350b72daa907b172e94c94b5 100644 (file)
@@ -84,7 +84,7 @@ bdb_db_cache(
 
 int bdb_dn2entry LDAP_P(( Operation *op, DB_TXN *tid,
        struct berval *dn, EntryInfo **e, int matched,
-       u_int32_t locker, DB_LOCK *lock ));
+       BDB_LOCKER locker, DB_LOCK *lock ));
 
 /*
  * dn2id.c
@@ -120,7 +120,7 @@ int bdb_dn2id_children(
 
 int bdb_dn2idl(
        Operation *op,
-       u_int32_t locker,
+       BDB_LOCKER locker,
        struct berval *ndn,
        EntryInfo *ei,
        ID *ids,
@@ -133,7 +133,7 @@ int bdb_dn2idl(
 int bdb_dn2id_parent(
        Operation *op,
        DB_TXN *txn,
-       u_int32_t locker,
+       BDB_LOCKER locker,
        EntryInfo *ei,
        ID *idp );
 
@@ -168,7 +168,7 @@ char *ebcdic_dberror( int rc );
 
 int bdb_filter_candidates(
        Operation *op,
-       u_int32_t locker,
+       BDB_LOCKER locker,
        Filter  *f,
        ID *ids,
        ID *tmp,
@@ -202,7 +202,7 @@ int bdb_id2entry_delete(
 int bdb_id2entry(
        BackendDB *be,
        DB_TXN *tid,
-       u_int32_t locker,
+       BDB_LOCKER locker,
        ID id,
        Entry **e);
 #endif
@@ -285,7 +285,7 @@ unsigned bdb_idl_search( ID *ids, ID id );
 int bdb_idl_fetch_key(
        BackendDB       *be,
        DB                      *db,
-       u_int32_t locker,
+       BDB_LOCKER locker,
        DBT                     *key,
        ID                      *ids,
        DBC                     **saved_cursor,
@@ -391,7 +391,7 @@ extern int
 bdb_key_read(
     Backend    *be,
        DB *db,
-       u_int32_t locker,
+       BDB_LOCKER locker,
     struct berval *k,
        ID *ids,
     DBC **saved_cursor,
@@ -443,6 +443,15 @@ int bdb_monitor_db_open( BackendDB *be );
 int bdb_monitor_db_close( BackendDB *be );
 int bdb_monitor_db_destroy( BackendDB *be );
 
+#ifdef BDB_MONITOR_IDX
+#define bdb_monitor_idx_add    BDB_SYMBOL(monitor_idx_add)
+int
+bdb_monitor_idx_add(
+       struct bdb_info         *bdb,
+       AttributeDescription    *desc,
+       slap_mask_t             type );
+#endif /* BDB_MONITOR_IDX */
+
 /*
  * cache.c
  */
@@ -504,7 +513,7 @@ int bdb_cache_add(
        EntryInfo *pei,
        Entry   *e,
        struct berval *nrdn,
-       u_int32_t locker,
+       BDB_LOCKER locker,
        DB_LOCK *lock
 );
 int bdb_cache_modrdn(
@@ -513,14 +522,14 @@ int bdb_cache_modrdn(
        struct berval *nrdn,
        Entry   *new,
        EntryInfo *ein,
-       u_int32_t locker,
+       BDB_LOCKER locker,
        DB_LOCK *lock
 );
 int bdb_cache_modify(
        struct bdb_info *bdb,
        Entry *e,
        Attribute *newAttrs,
-       u_int32_t locker,
+       BDB_LOCKER locker,
        DB_LOCK *lock
 );
 int bdb_cache_find_ndn(
@@ -539,21 +548,21 @@ int bdb_cache_find_id(
        ID              id,
        EntryInfo **eip,
        int     islocked,
-       u_int32_t       locker,
+       BDB_LOCKER      locker,
        DB_LOCK         *lock
 );
 int
 bdb_cache_find_parent(
        Operation *op,
        DB_TXN *txn,
-       u_int32_t       locker,
+       BDB_LOCKER      locker,
        ID id,
        EntryInfo **res
 );
 int bdb_cache_delete(
        struct bdb_info *bdb,
        Entry   *e,
-       u_int32_t locker,
+       BDB_LOCKER locker,
        DB_LOCK *lock
 );
 void bdb_cache_delete_cleanup(
@@ -573,7 +582,7 @@ int hdb_cache_load(
 #define bdb_cache_entry_db_relock              BDB_SYMBOL(cache_entry_db_relock)
 int bdb_cache_entry_db_relock(
        struct bdb_info *bdb,
-       u_int32_t locker,
+       BDB_LOCKER locker,
        EntryInfo *ei,
        int rw,
        int tryOnly,
@@ -587,7 +596,7 @@ int bdb_cache_entry_db_unlock(
 
 #define bdb_locker_id                          BDB_SYMBOL(locker_id)
 #define bdb_locker_flush                       BDB_SYMBOL(locker_flush)
-int bdb_locker_id( Operation *op, DB_ENV *env, u_int32_t *locker );
+int bdb_locker_id( Operation *op, DB_ENV *env, BDB_LOCKER *locker );
 void bdb_locker_flush( DB_ENV *env );
 
 #define        LOCK_ID_FREE(env, locker)       ((void)0)
@@ -632,7 +641,6 @@ bdb_trans_backoff( int num_retries );
 #define bdb_tool_entry_put             BDB_SYMBOL(tool_entry_put)
 #define bdb_tool_entry_reindex         BDB_SYMBOL(tool_entry_reindex)
 #define bdb_tool_dn2id_get             BDB_SYMBOL(tool_dn2id_get)
-#define bdb_tool_id2entry_get          BDB_SYMBOL(tool_id2entry_get)
 #define bdb_tool_entry_modify          BDB_SYMBOL(tool_entry_modify)
 #define bdb_tool_idl_add               BDB_SYMBOL(tool_idl_add)
 
@@ -663,7 +671,6 @@ extern BI_tool_entry_get            bdb_tool_entry_get;
 extern BI_tool_entry_put               bdb_tool_entry_put;
 extern BI_tool_entry_reindex           bdb_tool_entry_reindex;
 extern BI_tool_dn2id_get               bdb_tool_dn2id_get;
-extern BI_tool_id2entry_get            bdb_tool_id2entry_get;
 extern BI_tool_entry_modify            bdb_tool_entry_modify;
 
 int bdb_tool_idl_add( BackendDB *be, DB *db, DB_TXN *txn, DBT *key, ID id );
index d31056eebbc91bd0e28ea1e6ed1983e532ceaad7..29b3831e72ea8d6fc52c726fc3051dcf20960095 100644 (file)
@@ -28,7 +28,7 @@ bdb_referrals( Operation *op, SlapReply *rs )
        EntryInfo *ei;
        int rc = LDAP_SUCCESS;
 
-       u_int32_t       locker;
+       BDB_LOCKER      locker;
        DB_LOCK         lock;
 
        if( op->o_tag == LDAP_REQ_SEARCH ) {
@@ -87,8 +87,8 @@ dn2entry_retry:
                if ( e != NULL ) {
                        Debug( LDAP_DEBUG_TRACE,
                                LDAP_XSTRING(bdb_referrals)
-                               ": op=%ld target=\"%s\" matched=\"%s\"\n",
-                               (long) op->o_tag, op->o_req_dn.bv_val, e->e_name.bv_val );
+                               ": tag=%lu target=\"%s\" matched=\"%s\"\n",
+                               (unsigned long)op->o_tag, op->o_req_dn.bv_val, e->e_name.bv_val );
 
                        if( is_entry_referral( e ) ) {
                                BerVarray ref = get_entry_referrals( op, e );
@@ -138,8 +138,8 @@ dn2entry_retry:
 
                Debug( LDAP_DEBUG_TRACE,
                        LDAP_XSTRING(bdb_referrals)
-                       ": op=%ld target=\"%s\" matched=\"%s\"\n",
-                       (long) op->o_tag, op->o_req_dn.bv_val, e->e_name.bv_val );
+                       ": tag=%lu target=\"%s\" matched=\"%s\"\n",
+                       (unsigned long)op->o_tag, op->o_req_dn.bv_val, e->e_name.bv_val );
 
                rs->sr_matched = e->e_name.bv_val;
                if( rs->sr_ref != NULL ) {
index 94dd7c87ae4eb34b86dc54402d68b708a08d4b4e..5f0f583c693a6268d054c150001ee4993786b84d 100644 (file)
@@ -31,7 +31,7 @@ static int search_candidates(
        Operation *op,
        SlapReply *rs,
        Entry *e,
-       u_int32_t locker,
+       BDB_LOCKER locker,
        ID      *ids,
        ID      *scopes );
 
@@ -51,7 +51,7 @@ static Entry * deref_base (
        SlapReply *rs,
        Entry *e,
        Entry **matched,
-       u_int32_t locker,
+       BDB_LOCKER locker,
        DB_LOCK *lock,
        ID      *tmp,
        ID      *visited )
@@ -143,7 +143,7 @@ static int search_aliases(
        Operation *op,
        SlapReply *rs,
        Entry *e,
-       u_int32_t locker,
+       BDB_LOCKER locker,
        ID *ids,
        ID *scopes,
        ID *stack )
@@ -321,7 +321,7 @@ bdb_search( Operation *op, SlapReply *rs )
        ID              lastid = NOID;
        AttributeName   *attrs;
 
-       u_int32_t       locker = 0;
+       BDB_LOCKER      locker = 0;
        DB_LOCK         lock;
        struct  bdb_op_info     *opinfo = NULL;
        DB_TXN                  *ltid = NULL;
@@ -660,6 +660,15 @@ loop_begin:
                        goto done;
                }
 
+               /* mostly needed by internal searches,
+                * e.g. related to syncrepl, for whom
+                * abandon does not get set... */
+               if ( slapd_shutdown ) {
+                       rs->sr_err = LDAP_UNAVAILABLE;
+                       send_ldap_disconnect( op, rs );
+                       goto done;
+               }
+
                /* check time limit */
                if ( op->ors_tlimit != SLAP_NO_LIMIT
                                && slap_get_time() > stoptime )
@@ -1011,7 +1020,7 @@ static int search_candidates(
        Operation *op,
        SlapReply *rs,
        Entry *e,
-       u_int32_t locker,
+       BDB_LOCKER locker,
        ID      *ids,
        ID      *scopes )
 {
index f22a057ec9ade75e921edaf8c59f927186575015..f8cf1e138dec0cd0b50300b97d7938e5061e3b61 100644 (file)
@@ -27,7 +27,8 @@
 static DBC *cursor = NULL;
 static DBT key, data;
 static EntryHeader eh;
-static int eoff;
+static ID nid, previd = NOID;
+static char ehbuf[16];
 
 typedef struct dn_id {
        ID id;
@@ -74,7 +75,11 @@ static ldap_pvt_thread_mutex_t bdb_tool_index_mutex;
 static ldap_pvt_thread_cond_t bdb_tool_index_cond_main;
 static ldap_pvt_thread_cond_t bdb_tool_index_cond_work;
 
+static ldap_pvt_thread_mutex_t bdb_tool_trickle_mutex;
+static ldap_pvt_thread_cond_t bdb_tool_trickle_cond;
+
 static void * bdb_tool_index_task( void *ctx, void *ptr );
+static void * bdb_tool_trickle_task( void *ctx, void *ptr );
 
 int bdb_tool_entry_open(
        BackendDB *be, int mode )
@@ -84,7 +89,9 @@ int bdb_tool_entry_open(
        /* initialize key and data thangs */
        DBTzero( &key );
        DBTzero( &data );
-       key.flags = DB_DBT_REALLOC;
+       key.flags = DB_DBT_USERMEM;
+       key.data = &nid;
+       key.size = key.ulen = sizeof( nid );
        data.flags = DB_DBT_USERMEM;
 
        if (cursor == NULL) {
@@ -97,24 +104,29 @@ int bdb_tool_entry_open(
        }
 
        /* Set up for threaded slapindex */
-       if (( slapMode & (SLAP_TOOL_QUICK|SLAP_TOOL_READONLY)) == SLAP_TOOL_QUICK
-               && bdb->bi_nattrs ) {
+       if (( slapMode & (SLAP_TOOL_QUICK|SLAP_TOOL_READONLY)) == SLAP_TOOL_QUICK ) {
                if ( !bdb_tool_info ) {
-                       int i;
+                       ldap_pvt_thread_mutex_init( &bdb_tool_trickle_mutex );
+                       ldap_pvt_thread_cond_init( &bdb_tool_trickle_cond );
+                       ldap_pvt_thread_pool_submit( &connection_pool, bdb_tool_trickle_task, bdb->bi_dbenv );
+
                        ldap_pvt_thread_mutex_init( &bdb_tool_index_mutex );
                        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;
-                       for (i=1; i<slap_tool_thread_max; i++) {
-                               int *ptr = ch_malloc( sizeof( int ));
-                               *ptr = i;
-                               ldap_pvt_thread_pool_submit( &connection_pool,
-                                       bdb_tool_index_task, ptr );
+                       if ( bdb->bi_nattrs ) {
+                               int i;
+                               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;
+                               for (i=1; i<slap_tool_thread_max; i++) {
+                                       int *ptr = ch_malloc( sizeof( int ));
+                                       *ptr = i;
+                                       ldap_pvt_thread_pool_submit( &connection_pool,
+                                               bdb_tool_index_task, ptr );
+                               }
                        }
+                       bdb_tool_info = bdb;
                }
-               bdb_tool_info = bdb;
        }
 
        return 0;
@@ -125,16 +137,15 @@ int bdb_tool_entry_close(
 {
        if ( bdb_tool_info ) {
                slapd_shutdown = 1;
+               ldap_pvt_thread_mutex_lock( &bdb_tool_trickle_mutex );
+               ldap_pvt_thread_cond_signal( &bdb_tool_trickle_cond );
+               ldap_pvt_thread_mutex_unlock( &bdb_tool_trickle_mutex );
                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_work );
                ldap_pvt_thread_mutex_unlock( &bdb_tool_index_mutex );
        }
 
-       if( key.data ) {
-               ch_free( key.data );
-               key.data = NULL;
-       }
        if( eh.bv.bv_val ) {
                ch_free( eh.bv.bv_val );
                eh.bv.bv_val = NULL;
@@ -168,15 +179,14 @@ ID bdb_tool_entry_next(
        int rc;
        ID id;
        struct bdb_info *bdb = (struct bdb_info *) be->be_private;
-       char buf[16], *dptr;
 
        assert( be != NULL );
        assert( slapMode & SLAP_TOOL_MODE );
        assert( bdb != NULL );
-       
+
        /* Get the header */
-       data.ulen = data.dlen = sizeof( buf );
-       data.data = buf;
+       data.ulen = data.dlen = sizeof( ehbuf );
+       data.data = ehbuf;
        data.flags |= DB_DBT_PARTIAL;
        rc = cursor->c_get( cursor, &key, &data, DB_NEXT );
 
@@ -198,17 +208,8 @@ ID bdb_tool_entry_next(
                }
        }
 
-       dptr = eh.bv.bv_val;
-       eh.bv.bv_val = buf;
-       eh.bv.bv_len = data.size;
-       rc = entry_header( &eh );
-       eoff = eh.data - eh.bv.bv_val;
-       eh.bv.bv_val = dptr;
-       if( rc ) {
-               return NOID;
-       }
-
        BDB_DISK2ID( key.data, &id );
+       previd = id;
        return id;
 }
 
@@ -238,41 +239,39 @@ ID bdb_tool_dn2id_get(
        return ei->bei_id;
 }
 
-int bdb_tool_id2entry_get(
-       Backend *be,
-       ID id,
-       Entry **e
-)
-{
-       int rc = bdb_id2entry( be, NULL, 0, id, e );
-
-       if ( rc == DB_NOTFOUND && id == 0 ) {
-               Entry *dummy = ch_calloc( 1, sizeof(Entry) );
-               struct berval gluebv = BER_BVC("glue");
-               dummy->e_name.bv_val = ch_strdup( "" );
-               dummy->e_nname.bv_val = ch_strdup( "" );
-               attr_merge_one( dummy, slap_schema.si_ad_objectClass, &gluebv, NULL );
-               attr_merge_one( dummy, slap_schema.si_ad_structuralObjectClass,
-                       &gluebv, NULL );
-               *e = dummy;
-               rc = LDAP_SUCCESS;
-       }
-       return rc;
-}
-
 Entry* bdb_tool_entry_get( BackendDB *be, ID id )
 {
-       int rc;
        Entry *e = NULL;
+       char *dptr;
+       int rc, eoff;
 
        assert( be != NULL );
        assert( slapMode & SLAP_TOOL_MODE );
 
+       if ( id != previd ) {
+               data.ulen = data.dlen = sizeof( ehbuf );
+               data.data = ehbuf;
+               data.flags |= DB_DBT_PARTIAL;
+
+               BDB_ID2DISK( id, &nid );
+               rc = cursor->c_get( cursor, &key, &data, DB_SET );
+               if ( rc ) goto done;
+       }
+
+       /* Get the header */
+       dptr = eh.bv.bv_val;
+       eh.bv.bv_val = ehbuf;
+       eh.bv.bv_len = data.size;
+       rc = entry_header( &eh );
+       eoff = eh.data - eh.bv.bv_val;
+       eh.bv.bv_val = dptr;
+       if ( rc ) goto done;
+
        /* Get the size */
-       data.flags ^= DB_DBT_PARTIAL;
+       data.flags &= ~DB_DBT_PARTIAL;
        data.ulen = 0;
     rc = cursor->c_get( cursor, &key, &data, DB_CURRENT );
-       if ( rc != DB_BUFFER_SMALL ) goto leave;
+       if ( rc != DB_BUFFER_SMALL ) goto done;
 
        /* Allocate a block and retrieve the data */
        eh.bv.bv_len = eh.nvals * sizeof( struct berval ) + data.size;
@@ -285,7 +284,7 @@ Entry* bdb_tool_entry_get( BackendDB *be, ID id )
        eh.data += eoff;
 
     rc = cursor->c_get( cursor, &key, &data, DB_CURRENT );
-       if ( rc ) goto leave;
+       if ( rc ) goto done;
 
 #ifdef SLAP_ZONE_ALLOC
        /* FIXME: will add ctx later */
@@ -307,7 +306,7 @@ Entry* bdb_tool_entry_get( BackendDB *be, ID id )
                        op.o_tmpmemctx = NULL;
                        op.o_tmpmfuncs = &ch_mfuncs;
 
-                       rc = bdb_cache_find_parent( &op, NULL, cursor->locker, id, &ei );
+                       rc = bdb_cache_find_parent( &op, NULL, CURSOR_GETLOCKER(cursor), id, &ei );
                        if ( rc == LDAP_SUCCESS ) {
                                bdb_cache_entryinfo_unlock( ei );
                                e->e_private = ei;
@@ -319,7 +318,7 @@ Entry* bdb_tool_entry_get( BackendDB *be, ID id )
                }
 #endif
        }
-leave:
+done:
        return e;
 }
 
@@ -522,6 +521,12 @@ ID bdb_tool_entry_put(
                goto done;
        }
 
+       if (( slapMode & SLAP_TOOL_QUICK ) && (( e->e_id & 0xfff ) == 0xfff )) {
+               ldap_pvt_thread_mutex_lock( &bdb_tool_trickle_mutex );
+               ldap_pvt_thread_cond_signal( &bdb_tool_trickle_cond );
+               ldap_pvt_thread_mutex_unlock( &bdb_tool_trickle_mutex );
+       }
+
        if ( !bdb->bi_linear_index )
                rc = bdb_tool_index_add( &op, tid, e );
        if( rc != 0 ) {
@@ -1087,6 +1092,25 @@ int bdb_tool_idl_add(
 }
 #endif
 
+static void *
+bdb_tool_trickle_task( void *ctx, void *ptr )
+{
+       DB_ENV *env = ptr;
+       int wrote;
+
+       ldap_pvt_thread_mutex_lock( &bdb_tool_trickle_mutex );
+       while ( 1 ) {
+               ldap_pvt_thread_cond_wait( &bdb_tool_trickle_cond,
+                       &bdb_tool_trickle_mutex );
+               if ( slapd_shutdown )
+                       break;
+               env->memp_trickle( env, 30, &wrote );
+       }
+       ldap_pvt_thread_mutex_unlock( &bdb_tool_trickle_mutex );
+
+       return NULL;
+}
+
 static void *
 bdb_tool_index_task( void *ctx, void *ptr )
 {
index 20fd959fc591aa8f28babe399e2e22333b7a292a..6bf68fda5d9d7c39b3bdfbe22037fa1a7b013da7 100644 (file)
 
 int
 dnssrv_back_bind(
-    Operation          *op,
-    SlapReply          *rs )
+       Operation       *op,
+       SlapReply       *rs )
 {
-       Debug( LDAP_DEBUG_TRACE, "DNSSRV: bind %s (%d)\n",
-               op->o_req_dn.bv_val == NULL ? "" : op->o_req_dn.bv_val, 
-               op->oq_bind.rb_method, NULL );
-               
-       if ( op->oq_bind.rb_method == LDAP_AUTH_SIMPLE &&
-               !BER_BVISNULL( &op->oq_bind.rb_cred ) &&
-               !BER_BVISEMPTY( &op->oq_bind.rb_cred ) )
+       Debug( LDAP_DEBUG_TRACE, "DNSSRV: bind dn=\"%s\" (%d)\n",
+               BER_BVISNULL( &op->o_req_dn ) ? "" : op->o_req_dn.bv_val, 
+               op->orb_method, 0 );
+
+       /* allow rootdn as a means to auth without the need to actually
+        * contact the proxied DSA */
+       switch ( be_rootdn_bind( op, NULL ) ) {
+       case LDAP_SUCCESS:
+               /* frontend will send result */
+               return rs->sr_err;
+
+       default:
+               /* treat failure and like any other bind, otherwise
+                * it could reveal the DN of the rootdn */
+               break;
+       }
+
+       if ( !BER_BVISNULL( &op->orb_cred ) &&
+               !BER_BVISEMPTY( &op->orb_cred ) )
        {
+               /* simple bind */
                Statslog( LDAP_DEBUG_STATS,
-                       "%s DNSSRV BIND dn=\"%s\" provided passwd\n",
+                       "%s DNSSRV BIND dn=\"%s\" provided cleartext passwd\n",
                        op->o_log_prefix,
                        BER_BVISNULL( &op->o_req_dn ) ? "" : op->o_req_dn.bv_val , 0, 0, 0 );
 
-               Debug( LDAP_DEBUG_TRACE,
-                       "DNSSRV: BIND dn=\"%s\" provided cleartext password\n",
-                       BER_BVISNULL( &op->o_req_dn ) ? "" : op->o_req_dn.bv_val, 0, 0 );
-
                send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
                        "you shouldn't send strangers your password" );
 
        } else {
+               /* unauthenticated bind */
+               /* NOTE: we're not going to get here anyway:
+                * unauthenticated bind is dealt with by the frontend */
                Debug( LDAP_DEBUG_TRACE, "DNSSRV: BIND dn=\"%s\"\n",
                        BER_BVISNULL( &op->o_req_dn ) ? "" : op->o_req_dn.bv_val, 0, 0 );
 
index 365e47dfdb5fd27415a993910f15512a88318829..0e5baca33bb17ed3f1bd9cd65433ee4629d05882 100644 (file)
 #include <stdio.h>
 
 #include <ac/socket.h>
+#include <ac/param.h>
+#include <ac/string.h>
 
 #include "slap.h"
+#include "config.h"
 #include "proto-dnssrv.h"
 
 int
@@ -89,14 +92,16 @@ dnssrv_back_open(
 
 int
 dnssrv_back_db_init(
-    Backend    *be )
+       Backend *be,
+       ConfigReply *cr)
 {
        return 0;
 }
 
 int
 dnssrv_back_db_destroy(
-    Backend    *be )
+       Backend *be,
+       ConfigReply *cr )
 {
        return 0;
 }
index 9a5c4f5422a3acdf0a3f3b524bf328e484e1d264..8398162ee45f795b1a57e08acac1a9bc5d6c110b 100644 (file)
@@ -93,8 +93,7 @@ ldap_back_add(
 
 retry:
        ctrls = op->o_ctrls;
-       rs->sr_err = ldap_back_proxy_authz_ctrl( &lc->lc_bound_ndn,
-               li->li_version, &li->li_idassert, op, rs, &ctrls );
+       rs->sr_err = ldap_back_controls_add( op, rs, lc, &ctrls );
        if ( rs->sr_err != LDAP_SUCCESS ) {
                send_ldap_result( op, rs );
                goto cleanup;
@@ -109,13 +108,13 @@ retry:
                retrying &= ~LDAP_BACK_RETRYING;
                if ( ldap_back_retry( &lc, op, rs, LDAP_BACK_SENDERR ) ) {
                        /* if the identity changed, there might be need to re-authz */
-                       (void)ldap_back_proxy_authz_ctrl_free( op, &ctrls );
+                       (void)ldap_back_controls_free( op, rs, &ctrls );
                        goto retry;
                }
        }
 
 cleanup:
-       (void)ldap_back_proxy_authz_ctrl_free( op, &ctrls );
+       (void)ldap_back_controls_free( op, rs, &ctrls );
 
        if ( attrs ) {
                for ( --i; i >= 0; --i ) {
index 442869861d3eab48719c871f845b5ebfe3fe5b45..374a959c7417615859cf555b743aa641c90b50f9 100644 (file)
@@ -310,6 +310,11 @@ typedef struct ldapinfo_t {
 
 #define        LDAP_BACK_F_QUARANTINE          (0x00010000U)
 
+#ifdef SLAP_CONTROL_X_SESSION_TRACKING
+#define        LDAP_BACK_F_ST_REQUEST          (0x00020000U)
+#define        LDAP_BACK_F_ST_RESPONSE         (0x00040000U)
+#endif /* SLAP_CONTROL_X_SESSION_TRACKING */
+
 #define        LDAP_BACK_ISSET_F(ff,f)         ( ( (ff) & (f) ) == (f) )
 #define        LDAP_BACK_ISMASK_F(ff,m,f)      ( ( (ff) & (m) ) == (f) )
 
@@ -343,6 +348,11 @@ typedef struct ldapinfo_t {
 
 #define        LDAP_BACK_QUARANTINE(li)        LDAP_BACK_ISSET( (li), LDAP_BACK_F_QUARANTINE )
 
+#ifdef SLAP_CONTROL_X_SESSION_TRACKING
+#define        LDAP_BACK_ST_REQUEST(li)        LDAP_BACK_ISSET( (li), LDAP_BACK_F_ST_REQUEST)
+#define        LDAP_BACK_ST_RESPONSE(li)       LDAP_BACK_ISSET( (li), LDAP_BACK_F_ST_RESPONSE)
+#endif /* SLAP_CONTROL_X_SESSION_TRACKING */
+
        int                     li_version;
 
        /* cached connections; 
index 2247405128a9da26f849df66bc59d27be58750ba..e5878a2cbd965e22919dc4042d9be6f46356faa6 100644 (file)
@@ -173,10 +173,23 @@ ldap_back_bind( Operation *op, SlapReply *rs )
        ldapinfo_t              *li = (ldapinfo_t *) op->o_bd->be_private;
        ldapconn_t              *lc;
 
-       int                     rc = 0;
+       LDAPControl             **ctrls = NULL;
+       struct berval           save_o_dn;
+       int                     save_o_do_not_cache,
+                               rc = 0;
        ber_int_t               msgid;
        ldap_back_send_t        retrying = LDAP_BACK_RETRYING;
 
+       /* allow rootdn as a means to auth without the need to actually
+        * contact the proxied DSA */
+       switch ( be_rootdn_bind( op, rs ) ) {
+       case SLAP_CB_CONTINUE:
+               break;
+
+       default:
+               return rs->sr_err;
+       }
+
        lc = ldap_back_getconn( op, rs, LDAP_BACK_BIND_SERR, NULL, NULL );
        if ( !lc ) {
                return rs->sr_err;
@@ -195,11 +208,27 @@ ldap_back_bind( Operation *op, SlapReply *rs )
        }
        LDAP_BACK_CONN_ISBOUND_CLEAR( lc );
 
+       /* don't add proxyAuthz; set the bindDN */
+       save_o_dn = op->o_dn;
+       save_o_do_not_cache = op->o_do_not_cache;
+       op->o_dn = op->o_req_dn;
+       op->o_do_not_cache = 1;
+
+       ctrls = op->o_ctrls;
+       rc = ldap_back_controls_add( op, rs, lc, &ctrls );
+       op->o_dn = save_o_dn;
+       op->o_do_not_cache = save_o_do_not_cache;
+       if ( rc != LDAP_SUCCESS ) {
+               send_ldap_result( op, rs );
+               ldap_back_release_conn( li, lc );
+               return( rc );
+       }
+
 retry:;
        /* method is always LDAP_AUTH_SIMPLE if we got here */
        rs->sr_err = ldap_sasl_bind( lc->lc_ld, op->o_req_dn.bv_val,
                        LDAP_SASL_SIMPLE,
-                       &op->orb_cred, op->o_ctrls, NULL, &msgid );
+                       &op->orb_cred, ctrls, NULL, &msgid );
        /* FIXME: should we always retry, or only when piping the bind
         * in the "override" connection pool? */
        rc = ldap_back_op_result( lc, op, rs, msgid,
@@ -212,6 +241,8 @@ retry:;
                }
        }
 
+       ldap_back_controls_free( op, rs, &ctrls );
+
        if ( rc == LDAP_SUCCESS ) {
                /* If defined, proxyAuthz will be used also when
                 * back-ldap is the authorizing backend; for this
@@ -781,13 +812,13 @@ ldap_back_getconn(
                        op->o_ndn = op->o_req_ndn;
                }
                isproxyauthz = ldap_back_is_proxy_authz( op, rs, sendok, binddn, bindcred );
-               if ( isproxyauthz == -1 ) {
-                       return NULL;
-               }
                if ( op->o_tag == LDAP_REQ_BIND ) {
                        op->o_dn = save_o_dn;
                        op->o_ndn = save_o_ndn;
                }
+               if ( isproxyauthz == -1 ) {
+                       return NULL;
+               }
 
                lc_curr.lc_local_ndn = op->o_ndn;
                /* Explicit binds must not be shared;
@@ -1189,6 +1220,17 @@ done:;
        ldap_pvt_thread_mutex_unlock( &li->li_quarantine_mutex );
 }
 
+static int
+ldap_back_dobind_cb(
+       Operation *op,
+       SlapReply *rs
+)
+{
+       ber_tag_t *tptr = op->o_callback->sc_private;
+       op->o_tag = *tptr;
+       return SLAP_CB_CONTINUE;
+}
+
 /*
  * ldap_back_dobind_int
  *
@@ -1213,6 +1255,8 @@ ldap_back_dobind_int(
                        isbound,
                        binding = 0;
        ber_int_t       msgid;
+       ber_tag_t       o_tag = op->o_tag;
+       slap_callback cb = {0};
 
        assert( lcp != NULL );
        assert( retries >= 0 );
@@ -1284,10 +1328,16 @@ retry_lock:;
         * then bind as the asserting identity and explicitly 
         * add the proxyAuthz control to every operation with the
         * dn bound to the connection as control value.
-        * This is done also if this is the authrizing backend,
+        * This is done also if this is the authorizing backend,
         * but the "override" flag is given to idassert.
         * It allows to use SASL bind and yet proxyAuthz users
         */
+       op->o_tag = LDAP_REQ_BIND;
+       cb.sc_next = op->o_callback;
+       cb.sc_private = &o_tag;
+       cb.sc_response = ldap_back_dobind_cb;
+       op->o_callback = &cb;
+
        if ( LDAP_BACK_CONN_ISIDASSERT( lc ) ) {
                if ( BER_BVISEMPTY( &binddn ) && BER_BVISEMPTY( &bindcred ) ) {
                        /* if we got here, it shouldn't return result */
@@ -1323,6 +1373,14 @@ retry_lock:;
                                li->li_acl_authcID.bv_val,
                                li->li_acl_passwd.bv_val,
                                NULL );
+               if ( defaults == NULL ) {
+                       rs->sr_err = LDAP_OTHER;
+                       LDAP_BACK_CONN_ISBOUND_CLEAR( lc );
+                       if ( sendok & LDAP_BACK_SENDERR ) {
+                               send_ldap_result( op, rs );
+                       }
+                       goto done;
+               }
 
                rs->sr_err = ldap_sasl_interactive_bind_s( lc->lc_ld,
                                li->li_acl_authcDN.bv_val,
@@ -1401,11 +1459,15 @@ retry:;
                if ( rs->sr_err != LDAP_SUCCESS &&
                        ( sendok & LDAP_BACK_SENDERR ) )
                {
+                       if ( op->o_callback == &cb )
+                               op->o_callback = cb.sc_next;
+                       op->o_tag = o_tag;
                        rs->sr_text = "Internal proxy bind failure";
                        send_ldap_result( op, rs );
                }
 
-               return 0;
+               rc = 0;
+               goto leave;
        }
 
        rc = ldap_back_op_result( lc, op, rs, msgid,
@@ -1424,6 +1486,11 @@ done:;
                ldap_set_rebind_proc( lc->lc_ld, li->li_rebind_f, lc );
        }
 
+leave:;
+       if ( op->o_callback == &cb )
+               op->o_callback = cb.sc_next;
+       op->o_tag = o_tag;
+
        return rc;
 }
 
@@ -1673,18 +1740,44 @@ retry:;
                        if ( rc != LDAP_SUCCESS ) {
                                rs->sr_err = rc;
                        }
-                       if ( refs != NULL ) {
-                               int     i;
-
-                               for ( i = 0; refs[ i ] != NULL; i++ )
-                                       /* count */ ;
-                               rs->sr_ref = op->o_tmpalloc( sizeof( struct berval ) * ( i + 1 ),
-                                       op->o_tmpmemctx );
-                               for ( i = 0; refs[ i ] != NULL; i++ ) {
-                                       ber_str2bv( refs[ i ], 0, 0, &rs->sr_ref[ i ] );
+
+                       /* RFC 4511: referrals can only appear
+                        * if result code is LDAP_REFERRAL */
+                       if ( refs != NULL
+                               && refs[ 0 ] != NULL
+                               && refs[ 0 ][ 0 ] != '\0' )
+                       {
+                               if ( rs->sr_err != LDAP_REFERRAL ) {
+                                       Debug( LDAP_DEBUG_ANY,
+                                               "%s ldap_back_op_result: "
+                                               "got referrals with err=%d\n",
+                                               op->o_log_prefix,
+                                               rs->sr_err, 0 );
+
+                               } else {
+                                       int     i;
+
+                                       for ( i = 0; refs[ i ] != NULL; i++ )
+                                               /* count */ ;
+                                       rs->sr_ref = op->o_tmpalloc( sizeof( struct berval ) * ( i + 1 ),
+                                               op->o_tmpmemctx );
+                                       for ( i = 0; refs[ i ] != NULL; i++ ) {
+                                               ber_str2bv( refs[ i ], 0, 0, &rs->sr_ref[ i ] );
+                                       }
+                                       BER_BVZERO( &rs->sr_ref[ i ] );
                                }
-                               BER_BVZERO( &rs->sr_ref[ i ] );
+
+                       } else if ( rs->sr_err == LDAP_REFERRAL ) {
+                               Debug( LDAP_DEBUG_ANY,
+                                       "%s ldap_back_op_result: "
+                                       "got err=%d with null "
+                                       "or empty referrals\n",
+                                       op->o_log_prefix,
+                                       rs->sr_err, 0 );
+
+                               rs->sr_err = LDAP_NO_SUCH_OBJECT;
                        }
+
                        if ( ctrls != NULL ) {
                                rs->sr_ctrls = ctrls;
                        }
@@ -1739,12 +1832,14 @@ retry:;
        rs->sr_text = NULL;
 
        if ( rs->sr_ref ) {
-               assert( refs != NULL );
-               ber_memvfree( (void **)refs );
                op->o_tmpfree( rs->sr_ref, op->o_tmpmemctx );
                rs->sr_ref = NULL;
        }
 
+       if ( refs ) {
+               ber_memvfree( (void **)refs );
+       }
+
        if ( ctrls ) {
                assert( rs->sr_ctrls != NULL );
                ldap_controls_free( ctrls );
@@ -2025,6 +2120,14 @@ ldap_back_proxy_authz_bind(
                                li->li_idassert_authcID.bv_val,
                                li->li_idassert_passwd.bv_val,
                                authzID.bv_val );
+               if ( defaults == NULL ) {
+                       rs->sr_err = LDAP_OTHER;
+                       LDAP_BACK_CONN_ISBOUND_CLEAR( lc );
+                       if ( sendok & LDAP_BACK_SENDERR ) {
+                               send_ldap_result( op, rs );
+                       }
+                       goto done;
+               }
 
                rs->sr_err = ldap_sasl_interactive_bind_s( lc->lc_ld, binddn->bv_val,
                                li->li_idassert_sasl_mech.bv_val, NULL, NULL,
@@ -2128,38 +2231,19 @@ done:;
  */
 int
 ldap_back_proxy_authz_ctrl(
+               Operation       *op,
+               SlapReply       *rs,
                struct berval   *bound_ndn,
                int             version,
                slap_idassert_t *si,
-               Operation       *op,
-               SlapReply       *rs,
-               LDAPControl     ***pctrls )
+               LDAPControl     *ctrl )
 {
-       LDAPControl             **ctrls = NULL;
-       int                     i = 0;
        slap_idassert_mode_t    mode;
        struct berval           assertedID,
                                ndn;
        int                     isroot = 0;
 
-       *pctrls = NULL;
-
-       rs->sr_err = LDAP_SUCCESS;
-
-       /* don't proxyAuthz if protocol is not LDAPv3 */
-       switch ( version ) {
-       case LDAP_VERSION3:
-               break;
-
-       case 0:
-               if ( op->o_protocol == 0 || op->o_protocol == LDAP_VERSION3 ) {
-                       break;
-               }
-               /* fall thru */
-
-       default:
-               goto done;
-       }
+       rs->sr_err = SLAP_CB_CONTINUE;
 
        /* FIXME: SASL/EXTERNAL over ldapi:// doesn't honor the authcID,
         * but if it is not set this test fails.  We need a different
@@ -2232,7 +2316,7 @@ ldap_back_proxy_authz_ctrl(
                        authcDN = ndn;
                }
                rc = slap_sasl_matches( op, si->si_authz,
-                               &authcDN, & authcDN );
+                               &authcDN, &authcDN );
                if ( rc != LDAP_SUCCESS ) {
                        if ( si->si_flags & LDAP_BACK_AUTH_PRESCRIPTIVE ) {
                                /* ndn is not authorized
@@ -2309,32 +2393,20 @@ ldap_back_proxy_authz_ctrl(
                goto done;
        }
 
-       if ( op->o_ctrls ) {
-               for ( i = 0; op->o_ctrls[ i ]; i++ )
-                       /* just count ctrls */ ;
-       }
-
-       ctrls = op->o_tmpalloc( sizeof( LDAPControl * ) * (i + 2) + sizeof( LDAPControl ),
-                       op->o_tmpmemctx );
-       ctrls[ 0 ] = (LDAPControl *)&ctrls[ i + 2 ];
-       
-       ctrls[ 0 ]->ldctl_oid = LDAP_CONTROL_PROXY_AUTHZ;
-       ctrls[ 0 ]->ldctl_iscritical = 1;
-
        switch ( si->si_mode ) {
        /* already in u:ID or dn:DN form */
        case LDAP_BACK_IDASSERT_OTHERID:
        case LDAP_BACK_IDASSERT_OTHERDN:
-               ber_dupbv_x( &ctrls[ 0 ]->ldctl_value, &assertedID, op->o_tmpmemctx );
+               ber_dupbv_x( &ctrl->ldctl_value, &assertedID, op->o_tmpmemctx );
                break;
 
        /* needs the dn: prefix */
        default:
-               ctrls[ 0 ]->ldctl_value.bv_len = assertedID.bv_len + STRLENOF( "dn:" );
-               ctrls[ 0 ]->ldctl_value.bv_val = op->o_tmpalloc( ctrls[ 0 ]->ldctl_value.bv_len + 1,
+               ctrl->ldctl_value.bv_len = assertedID.bv_len + STRLENOF( "dn:" );
+               ctrl->ldctl_value.bv_val = op->o_tmpalloc( ctrl->ldctl_value.bv_len + 1,
                                op->o_tmpmemctx );
-               AC_MEMCPY( ctrls[ 0 ]->ldctl_value.bv_val, "dn:", STRLENOF( "dn:" ) );
-               AC_MEMCPY( &ctrls[ 0 ]->ldctl_value.bv_val[ STRLENOF( "dn:" ) ],
+               AC_MEMCPY( ctrl->ldctl_value.bv_val, "dn:", STRLENOF( "dn:" ) );
+               AC_MEMCPY( &ctrl->ldctl_value.bv_val[ STRLENOF( "dn:" ) ],
                                assertedID.bv_val, assertedID.bv_len + 1 );
                break;
        }
@@ -2344,7 +2416,7 @@ ldap_back_proxy_authz_ctrl(
         * this hack provides compatibility with those DSAs that
         * implement it this way */
        if ( si->si_flags & LDAP_BACK_AUTH_OBSOLETE_ENCODING_WORKAROUND ) {
-               struct berval           authzID = ctrls[ 0 ]->ldctl_value;
+               struct berval           authzID = ctrl->ldctl_value;
                BerElementBuffer        berbuf;
                BerElement              *ber = (BerElement *)&berbuf;
                ber_tag_t               tag;
@@ -2358,7 +2430,7 @@ ldap_back_proxy_authz_ctrl(
                        goto free_ber;
                }
 
-               if ( ber_flatten2( ber, &ctrls[ 0 ]->ldctl_value, 1 ) == -1 ) {
+               if ( ber_flatten2( ber, &ctrl->ldctl_value, 1 ) == -1 ) {
                        rs->sr_err = LDAP_OTHER;
                        goto free_ber;
                }
@@ -2368,22 +2440,17 @@ free_ber:;
                ber_free_buf( ber );
 
                if ( rs->sr_err != LDAP_SUCCESS ) {
-                       op->o_tmpfree( ctrls, op->o_tmpmemctx );
-                       ctrls = NULL;
                        goto done;
                }
 
        } else if ( si->si_flags & LDAP_BACK_AUTH_OBSOLETE_PROXY_AUTHZ ) {
-               struct berval           authzID = ctrls[ 0 ]->ldctl_value,
+               struct berval           authzID = ctrl->ldctl_value,
                                        tmp;
                BerElementBuffer        berbuf;
                BerElement              *ber = (BerElement *)&berbuf;
                ber_tag_t               tag;
 
                if ( strncasecmp( authzID.bv_val, "dn:", STRLENOF( "dn:" ) ) != 0 ) {
-                       op->o_tmpfree( ctrls[ 0 ]->ldctl_value.bv_val, op->o_tmpmemctx );
-                       op->o_tmpfree( ctrls, op->o_tmpmemctx );
-                       ctrls = NULL;
                        rs->sr_err = LDAP_PROTOCOL_ERROR;
                        goto done;
                }
@@ -2403,7 +2470,7 @@ free_ber:;
                        goto free_ber2;
                }
 
-               if ( ber_flatten2( ber, &ctrls[ 0 ]->ldctl_value, 1 ) == -1 ) {
+               if ( ber_flatten2( ber, &ctrl->ldctl_value, 1 ) == -1 ) {
                        rs->sr_err = LDAP_OTHER;
                        goto free_ber2;
                }
@@ -2413,20 +2480,119 @@ free_ber2:;
                ber_free_buf( ber );
 
                if ( rs->sr_err != LDAP_SUCCESS ) {
-                       op->o_tmpfree( ctrls, op->o_tmpmemctx );
-                       ctrls = NULL;
                        goto done;
                }
 
-               ctrls[ 0 ]->ldctl_oid = LDAP_CONTROL_OBSOLETE_PROXY_AUTHZ;
+               ctrl->ldctl_oid = LDAP_CONTROL_OBSOLETE_PROXY_AUTHZ;
+       }
+
+done:;
+
+       return rs->sr_err;
+}
+
+/*
+ * Add controls;
+ *
+ * if any needs to be added, it is prepended to existing ones,
+ * in a newly allocated array.  The companion function
+ * ldap_back_controls_free() must be used to restore the original
+ * status of op->o_ctrls.
+ */
+int
+ldap_back_controls_add(
+               Operation       *op,
+               SlapReply       *rs,
+               ldapconn_t      *lc,
+               LDAPControl     ***pctrls )
+{
+       ldapinfo_t      *li = (ldapinfo_t *)op->o_bd->be_private;
+
+       LDAPControl     **ctrls = NULL;
+       /* set to the maximum number of controls this backend can add */
+       LDAPControl     c[ 2 ] = { 0 };
+       int             i = 0, j = 0;
+
+       *pctrls = NULL;
+
+       rs->sr_err = LDAP_SUCCESS;
+
+       /* don't add controls if protocol is not LDAPv3 */
+       switch ( li->li_version ) {
+       case LDAP_VERSION3:
+               break;
+
+       case 0:
+               if ( op->o_protocol == 0 || op->o_protocol == LDAP_VERSION3 ) {
+                       break;
+               }
+               /* fall thru */
+
+       default:
+               goto done;
+       }
+
+       /* proxyAuthz for identity assertion */
+       switch ( ldap_back_proxy_authz_ctrl( op, rs, &lc->lc_bound_ndn,
+               li->li_version, &li->li_idassert, &c[ j ] ) )
+       {
+       case SLAP_CB_CONTINUE:
+               break;
+
+       case LDAP_SUCCESS:
+               j++;
+               break;
+
+       default:
+               goto done;
+       }
+
+#ifdef SLAP_CONTROL_X_SESSION_TRACKING
+       /* session tracking */
+       if ( LDAP_BACK_ST_REQUEST( li ) ) {
+               switch ( slap_ctrl_session_tracking_request_add( op, rs, &c[ j ] ) ) {
+               case SLAP_CB_CONTINUE:
+                       break;
+
+               case LDAP_SUCCESS:
+                       j++;
+                       break;
+
+               default:
+                       goto done;
+               }
+       }
+#endif /* SLAP_CONTROL_X_SESSION_TRACKING */
+
+       if ( rs->sr_err == SLAP_CB_CONTINUE ) {
+               rs->sr_err = LDAP_SUCCESS;
+       }
+
+       if ( j == 0 ) {
+               goto done;
        }
 
+       if ( op->o_ctrls ) {
+               for ( i = 0; op->o_ctrls[ i ]; i++ )
+                       /* just count ctrls */ ;
+       }
+
+       ctrls = op->o_tmpalloc( sizeof( LDAPControl * ) * (i + j + 1) + j * sizeof( LDAPControl ),
+                       op->o_tmpmemctx );
+       ctrls[ 0 ] = (LDAPControl *)&ctrls[ i + j + 1 ];
+       *ctrls[ 0 ] = c[ 0 ];
+       for ( i = 1; i < j; i++ ) {
+               ctrls[ i ] = &ctrls[ 0 ][ i ];
+               *ctrls[ i ] = c[ i ];
+       }
+
+       i = 0;
        if ( op->o_ctrls ) {
                for ( i = 0; op->o_ctrls[ i ]; i++ ) {
-                       ctrls[ i + 1 ] = op->o_ctrls[ i ];
+                       ctrls[ i + j ] = op->o_ctrls[ i ];
                }
        }
-       ctrls[ i + 1 ] = NULL;
+       ctrls[ i + j ] = NULL;
 
 done:;
        if ( ctrls == NULL ) {
@@ -2439,18 +2605,25 @@ done:;
 }
 
 int
-ldap_back_proxy_authz_ctrl_free( Operation *op, LDAPControl ***pctrls )
+ldap_back_controls_free( Operation *op, SlapReply *rs, LDAPControl ***pctrls )
 {
        LDAPControl     **ctrls = *pctrls;
 
-       /* we assume that the first control is the proxyAuthz
-        * added by back-ldap, so it's the only one we explicitly 
-        * free */
+       /* we assume that the controls added by the proxy come first,
+        * so as soon as we find op->o_ctrls[ 0 ] we can stop */
        if ( ctrls && ctrls != op->o_ctrls ) {
+               int     i;
+
                assert( ctrls[ 0 ] != NULL );
 
-               if ( !BER_BVISNULL( &ctrls[ 0 ]->ldctl_value ) ) {
-                       op->o_tmpfree( ctrls[ 0 ]->ldctl_value.bv_val, op->o_tmpmemctx );
+               for ( i = 0; ctrls[ i ] != NULL; i++ ) {
+                       if ( op->o_ctrls && ctrls[ i ] == op->o_ctrls[ 0 ] ) {
+                               break;
+                       }
+
+                       if ( !BER_BVISNULL( &ctrls[ i ]->ldctl_value ) ) {
+                               op->o_tmpfree( ctrls[ i ]->ldctl_value.bv_val, op->o_tmpmemctx );
+                       }
                }
 
                op->o_tmpfree( ctrls, op->o_tmpmemctx );
index 3bf88376c498221e8884f773d27032506af59cbf..509a65b187cc4093d3ec0f807c8bcb0390688ef9 100644 (file)
@@ -112,7 +112,7 @@ static int ldap_chain_db_init_common( BackendDB     *be );
 static int ldap_chain_db_init_one( BackendDB *be );
 static int ldap_chain_db_open_one( BackendDB *be );
 #define        ldap_chain_db_close_one(be)     (0)
-#define        ldap_chain_db_destroy_one(be)   (lback)->bi_db_destroy( (be) )
+#define        ldap_chain_db_destroy_one(be, rs)       (lback)->bi_db_destroy( (be), (rs) )
 
 typedef struct ldap_chain_cb_t {
        ldap_chain_status_t     lb_status;
@@ -418,7 +418,7 @@ ldap_chain_op(
                LDAPURLDesc     *srv = NULL;
                struct berval   save_req_dn = op->o_req_dn,
                                save_req_ndn = op->o_req_ndn,
-                               dn,
+                               dn = BER_BVNULL,
                                pdn = BER_BVNULL,
                                ndn = BER_BVNULL;
                int             temporary = 0;
@@ -449,17 +449,24 @@ Document: RFC 4511
                }
 
                /* normalize DN */
-               ber_str2bv( srv->lud_dn, 0, 0, &dn );
-               rc = dnPrettyNormal( NULL, &dn, &pdn, &ndn, op->o_tmpmemctx );
-               if ( rc == LDAP_SUCCESS ) {
-                       /* remove DN essentially because later on 
-                        * ldap_initialize() will parse the URL 
-                        * as a comma-separated URL list */
+               rc = LDAP_SUCCESS;
+               srv->lud_scope = LDAP_SCOPE_DEFAULT;
+               if ( srv->lud_dn != NULL ) {
+                       ber_str2bv( srv->lud_dn, 0, 0, &dn );
+                       rc = dnPrettyNormal( NULL, &dn, &pdn, &ndn, op->o_tmpmemctx );
+                       if ( rc == LDAP_SUCCESS ) {
+                               /* remove DN essentially because later on 
+                                * ldap_initialize() will parse the URL 
+                                * as a comma-separated URL list */
+                               srv->lud_dn = "";
+                       }
+
+               } else {
                        srv->lud_dn = "";
-                       srv->lud_scope = LDAP_SCOPE_DEFAULT;
-                       li.li_uri = ldap_url_desc2str( srv );
-                       srv->lud_dn = dn.bv_val;
                }
+
+               li.li_uri = ldap_url_desc2str( srv );
+               srv->lud_dn = dn.bv_val;
                ldap_free_urldesc( srv );
 
                if ( rc != LDAP_SUCCESS ) {
@@ -500,7 +507,7 @@ Document: RFC 4511
                        if ( rc != 0 ) {
                                lip->li_uri = NULL;
                                lip->li_bvuri = NULL;
-                               (void)ldap_chain_db_destroy_one( op->o_bd );
+                               (void)ldap_chain_db_destroy_one( op->o_bd, NULL);
                                goto cleanup;
                        }
 
@@ -539,7 +546,7 @@ cleanup:;
                        lip->li_uri = NULL;
                        lip->li_bvuri = NULL;
                        (void)ldap_chain_db_close_one( op->o_bd );
-                       (void)ldap_chain_db_destroy_one( op->o_bd );
+                       (void)ldap_chain_db_destroy_one( op->o_bd, NULL );
                }
 
 further_cleanup:;
@@ -629,16 +636,19 @@ ldap_chain_search(
                }
 
                /* normalize DN */
-               ber_str2bv( srv->lud_dn, 0, 0, &dn );
-               rc = dnPrettyNormal( NULL, &dn, &pdn, &ndn, op->o_tmpmemctx );
-               if ( rc == LDAP_SUCCESS ) {
-                       /* remove DN essentially because later on 
-                        * ldap_initialize() will parse the URL 
-                        * as a comma-separated URL list */
-                       srv->lud_dn = "";
-                       srv->lud_scope = LDAP_SCOPE_DEFAULT;
-                       li.li_uri = ldap_url_desc2str( srv );
-                       srv->lud_dn = dn.bv_val;
+               rc = LDAP_INVALID_SYNTAX;
+               if ( srv->lud_dn != NULL ) {
+                       ber_str2bv( srv->lud_dn, 0, 0, &dn );
+                       rc = dnPrettyNormal( NULL, &dn, &pdn, &ndn, op->o_tmpmemctx );
+                       if ( rc == LDAP_SUCCESS ) {
+                               /* remove DN essentially because later on 
+                                * ldap_initialize() will parse the URL 
+                                * as a comma-separated URL list */
+                               srv->lud_dn = "";
+                               srv->lud_scope = LDAP_SCOPE_DEFAULT;
+                               li.li_uri = ldap_url_desc2str( srv );
+                               srv->lud_dn = dn.bv_val;
+                       }
                }
                ldap_free_urldesc( srv );
 
@@ -681,7 +691,7 @@ ldap_chain_search(
                        if ( rc != 0 ) {
                                lip->li_uri = NULL;
                                lip->li_bvuri = NULL;
-                               (void)ldap_chain_db_destroy_one( op->o_bd );
+                               (void)ldap_chain_db_destroy_one( op->o_bd, NULL );
                                goto cleanup;
                        }
 
@@ -723,7 +733,7 @@ cleanup:;
                        lip->li_uri = NULL;
                        lip->li_bvuri = NULL;
                        (void)ldap_chain_db_close_one( op->o_bd );
-                       (void)ldap_chain_db_destroy_one( op->o_bd );
+                       (void)ldap_chain_db_destroy_one( op->o_bd, NULL );
                }
                
 further_cleanup:;
@@ -778,7 +788,7 @@ ldap_chain_response( Operation *op, SlapReply *rs )
        slap_callback   *sc = op->o_callback,
                        sc2 = { 0 };
        int             rc = 0;
-       char            *text = NULL;
+       const char      *text = NULL;
        const char      *matched;
        BerVarray       ref;
        struct berval   ndn = op->o_ndn;
@@ -918,6 +928,7 @@ ldap_chain_response( Operation *op, SlapReply *rs )
                 * to send it... */
                /* FIXME: what about chaining? */
                if ( rc != SLAPD_ABANDON ) {
+                       rs->sr_err = rc;
                        send_ldap_extended( op, rs );
                        rc = LDAP_SUCCESS;
                }
@@ -1181,7 +1192,7 @@ chain_ldadd( CfEntryInfo *p, Entry *e, ConfigArgs *ca )
 
 done:;
        if ( rc != LDAP_SUCCESS ) {
-               (void)ldap_chain_db_destroy_one( ca->be );
+               (void)ldap_chain_db_destroy_one( ca->be, NULL );
                ch_free( ca->be );
                ca->be = NULL;
        }
@@ -1206,9 +1217,9 @@ ldap_chain_cfadd_apply( void *datum, void *arg )
        struct berval                   bv;
 
        /* FIXME: should not hardcode "olcDatabase" here */
-       bv.bv_len = snprintf( lca->ca->msg, sizeof( lca->ca->msg ),
+       bv.bv_len = snprintf( lca->ca->cr_msg, sizeof( lca->ca->cr_msg ),
                "olcDatabase={%d}%s", lca->count, lback->bi_type );
-       bv.bv_val = lca->ca->msg;
+       bv.bv_val = lca->ca->cr_msg;
 
        lca->ca->be->be_private = (void *)li;
        config_build_entry( lca->op, lca->rs, lca->p->e_private, lca->ca,
@@ -1468,11 +1479,11 @@ chain_cf_gen( ConfigArgs *c )
 
        case CH_MAX_DEPTH:
                if ( c->value_int < 0 ) {
-                       snprintf( c->msg, sizeof( c->msg ),
+                       snprintf( c->cr_msg, sizeof( c->cr_msg ),
                                "<%s> invalid max referral depth %d",
                                c->argv[0], c->value_int );
                        Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
-                               c->log, c->msg, 0 );
+                               c->log, c->cr_msg, 0 );
                        rc = 1;
                        break;
                }
@@ -1495,7 +1506,8 @@ chain_cf_gen( ConfigArgs *c )
 
 static int
 ldap_chain_db_init(
-       BackendDB *be )
+       BackendDB *be,
+       ConfigReply *cr )
 {
        slap_overinst   *on = (slap_overinst *)be->bd_info;
        ldap_chain_t    *lc = NULL;
@@ -1626,7 +1638,7 @@ private_destroy:;
 
                                db.bd_info = lback;
                                db.be_private = (void *)lc->lc_cfg_li;
-                               ldap_chain_db_destroy_one( &db );
+                               ldap_chain_db_destroy_one( &db, NULL );
                                lc->lc_cfg_li = NULL;
 
                        } else {
@@ -1679,7 +1691,7 @@ ldap_chain_db_apply( void *datum, void *arg )
 
        lca->be->be_private = (void *)li;
 
-       return lca->func( lca->be );
+       return lca->func( lca->be, NULL );
 }
 
 static int
@@ -1702,7 +1714,7 @@ ldap_chain_db_func(
                        db.bd_info = lback;
                        db.be_private = lc->lc_common_li;
 
-                       rc = func( &db );
+                       rc = func( &db, NULL );
 
                        if ( rc != 0 ) {
                                return rc;
@@ -1726,7 +1738,8 @@ ldap_chain_db_func(
 
 static int
 ldap_chain_db_open(
-       BackendDB       *be )
+       BackendDB       *be,
+       ConfigReply     *cr )
 {
        slap_overinst   *on = (slap_overinst *) be->bd_info;
        ldap_chain_t    *lc = (ldap_chain_t *)on->on_bi.bi_private;
@@ -1758,14 +1771,16 @@ ldap_chain_db_open(
 
 static int
 ldap_chain_db_close(
-       BackendDB       *be )
+       BackendDB       *be,
+       ConfigReply     *cr )
 {
        return ldap_chain_db_func( be, db_close );
 }
 
 static int
 ldap_chain_db_destroy(
-       BackendDB       *be )
+       BackendDB       *be,
+       ConfigReply     *cr )
 {
        slap_overinst   *on = (slap_overinst *) be->bd_info;
        ldap_chain_t    *lc = (ldap_chain_t *)on->on_bi.bi_private;
@@ -1797,7 +1812,7 @@ ldap_chain_db_init_common(
 
        be->bd_info = lback;
        be->be_private = NULL;
-       rc = lback->bi_db_init( be );
+       rc = lback->bi_db_init( be, NULL );
        if ( rc != 0 ) {
                return rc;
        }
@@ -1832,7 +1847,7 @@ ldap_chain_db_init_one(
 
        be->bd_info = lback;
        be->be_private = NULL;
-       t = lback->bi_db_init( be );
+       t = lback->bi_db_init( be, NULL );
        if ( t != 0 ) {
                return t;
        }
@@ -1876,7 +1891,7 @@ ldap_chain_db_open_one(
                }
        }
 
-       return lback->bi_db_open( be );
+       return lback->bi_db_open( be, NULL );
 }
 
 typedef struct ldap_chain_conn_apply_t {
index a0a1b598075ffc0c58a399431916519a1169884b..740be2475171d943be20c4eea501305d9e37f815 100644 (file)
@@ -51,8 +51,7 @@ ldap_back_compare(
 
 retry:
        ctrls = op->o_ctrls;
-       rc = ldap_back_proxy_authz_ctrl( &lc->lc_bound_ndn,
-               li->li_version, &li->li_idassert, op, rs, &ctrls );
+       rc = ldap_back_controls_add( op, rs, lc, &ctrls );
        if ( rc != LDAP_SUCCESS ) {
                send_ldap_result( op, rs );
                goto cleanup;
@@ -69,13 +68,13 @@ retry:
                retrying &= ~LDAP_BACK_RETRYING;
                if ( ldap_back_retry( &lc, op, rs, LDAP_BACK_SENDERR ) ) {
                        /* if the identity changed, there might be need to re-authz */
-                       (void)ldap_back_proxy_authz_ctrl_free( op, &ctrls );
+                       (void)ldap_back_controls_free( op, rs, &ctrls );
                        goto retry;
                }
        }
 
 cleanup:
-       (void)ldap_back_proxy_authz_ctrl_free( op, &ctrls );
+       (void)ldap_back_controls_free( op, rs, &ctrls );
        
        if ( lc != NULL ) {
                ldap_back_release_conn( li, lc );
index 78a2f2d25c12dd4e402038d75bea29ba4630fa24..389e17d29ca18ba88a04eaaa8da3aef2b9335a2e 100644 (file)
@@ -69,6 +69,7 @@ enum {
        LDAP_BACK_CFG_CONNPOOLMAX,
        LDAP_BACK_CFG_CANCEL,
        LDAP_BACK_CFG_QUARANTINE,
+       LDAP_BACK_CFG_ST_REQUEST,
        LDAP_BACK_CFG_REWRITE,
 
        LDAP_BACK_CFG_LAST
@@ -183,7 +184,7 @@ static ConfigTable ldapcfg[] = {
                        "SYNTAX OMsDirectoryString "
                        "X-ORDERED 'VALUES' )",
                NULL, NULL },
-       { "rebind-as-user", "NO|yes", 1, 2, 0,
+       { "rebind-as-user", "true|FALSE", 1, 2, 0,
                ARG_MAGIC|ARG_ON_OFF|LDAP_BACK_CFG_REBIND,
                ldap_back_cf_gen, "( OLcfgDbAt:3.10 "
                        "NAME 'olcDbRebindAsUser' "
@@ -191,7 +192,7 @@ static ConfigTable ldapcfg[] = {
                        "SYNTAX OMsBoolean "
                        "SINGLE-VALUE )",
                NULL, NULL },
-       { "chase-referrals", "YES|no", 2, 2, 0,
+       { "chase-referrals", "true|FALSE", 2, 2, 0,
                ARG_MAGIC|ARG_ON_OFF|LDAP_BACK_CFG_CHASE,
                ldap_back_cf_gen, "( OLcfgDbAt:3.11 "
                        "NAME 'olcDbChaseReferrals' "
@@ -199,7 +200,7 @@ static ConfigTable ldapcfg[] = {
                        "SYNTAX OMsBoolean "
                        "SINGLE-VALUE )",
                NULL, NULL },
-       { "t-f-support", "NO|yes|discover", 2, 2, 0,
+       { "t-f-support", "true|FALSE|discover", 2, 2, 0,
                ARG_MAGIC|LDAP_BACK_CFG_T_F,
                ldap_back_cf_gen, "( OLcfgDbAt:3.12 "
                        "NAME 'olcDbTFSupport' "
@@ -207,7 +208,7 @@ static ConfigTable ldapcfg[] = {
                        "SYNTAX OMsDirectoryString "
                        "SINGLE-VALUE )",
                NULL, NULL },
-       { "proxy-whoami", "NO|yes", 1, 2, 0,
+       { "proxy-whoami", "true|FALSE", 1, 2, 0,
                ARG_MAGIC|ARG_ON_OFF|LDAP_BACK_CFG_WHOAMI,
                ldap_back_cf_gen, "( OLcfgDbAt:3.13 "
                        "NAME 'olcDbProxyWhoAmI' "
@@ -223,7 +224,7 @@ static ConfigTable ldapcfg[] = {
                        "SYNTAX OMsDirectoryString "
                        "SINGLE-VALUE )",
                NULL, NULL },
-       { "idle-timeout", "timeout", 2, 0, 0,
+       { "idle-timeout", "timeout", 2, 2, 0,
                ARG_MAGIC|LDAP_BACK_CFG_IDLE_TIMEOUT,
                ldap_back_cf_gen, "( OLcfgDbAt:3.15 "
                        "NAME 'olcDbIdleTimeout' "
@@ -231,7 +232,7 @@ static ConfigTable ldapcfg[] = {
                        "SYNTAX OMsDirectoryString "
                        "SINGLE-VALUE )",
                NULL, NULL },
-       { "conn-ttl", "ttl", 2, 0, 0,
+       { "conn-ttl", "ttl", 2, 2, 0,
                ARG_MAGIC|LDAP_BACK_CFG_CONN_TTL,
                ldap_back_cf_gen, "( OLcfgDbAt:3.16 "
                        "NAME 'olcDbConnTtl' "
@@ -239,7 +240,7 @@ static ConfigTable ldapcfg[] = {
                        "SYNTAX OMsDirectoryString "
                        "SINGLE-VALUE )",
                NULL, NULL },
-       { "network-timeout", "timeout", 2, 0, 0,
+       { "network-timeout", "timeout", 2, 2, 0,
                ARG_MAGIC|LDAP_BACK_CFG_NETWORK_TIMEOUT,
                ldap_back_cf_gen, "( OLcfgDbAt:3.17 "
                        "NAME 'olcDbNetworkTimeout' "
@@ -247,7 +248,7 @@ static ConfigTable ldapcfg[] = {
                        "SYNTAX OMsDirectoryString "
                        "SINGLE-VALUE )",
                NULL, NULL },
-       { "protocol-version", "version", 2, 0, 0,
+       { "protocol-version", "version", 2, 2, 0,
                ARG_MAGIC|ARG_INT|LDAP_BACK_CFG_VERSION,
                ldap_back_cf_gen, "( OLcfgDbAt:3.18 "
                        "NAME 'olcDbProtocolVersion' "
@@ -255,7 +256,7 @@ static ConfigTable ldapcfg[] = {
                        "SYNTAX OMsInteger "
                        "SINGLE-VALUE )",
                NULL, NULL },
-       { "single-conn", "TRUE/FALSE", 2, 0, 0,
+       { "single-conn", "true|FALSE", 2, 2, 0,
                ARG_MAGIC|ARG_ON_OFF|LDAP_BACK_CFG_SINGLECONN,
                ldap_back_cf_gen, "( OLcfgDbAt:3.19 "
                        "NAME 'olcDbSingleConn' "
@@ -263,7 +264,7 @@ static ConfigTable ldapcfg[] = {
                        "SYNTAX OMsBoolean "
                        "SINGLE-VALUE )",
                NULL, NULL },
-       { "cancel", "ABANDON|ignore|exop", 2, 0, 0,
+       { "cancel", "ABANDON|ignore|exop", 2, 2, 0,
                ARG_MAGIC|LDAP_BACK_CFG_CANCEL,
                ldap_back_cf_gen, "( OLcfgDbAt:3.20 "
                        "NAME 'olcDbCancel' "
@@ -271,7 +272,7 @@ static ConfigTable ldapcfg[] = {
                        "SYNTAX OMsDirectoryString "
                        "SINGLE-VALUE )",
                NULL, NULL },
-       { "quarantine", "retrylist", 2, 0, 0,
+       { "quarantine", "retrylist", 2, 2, 0,
                ARG_MAGIC|LDAP_BACK_CFG_QUARANTINE,
                ldap_back_cf_gen, "( OLcfgDbAt:3.21 "
                        "NAME 'olcDbQuarantine' "
@@ -279,7 +280,7 @@ static ConfigTable ldapcfg[] = {
                        "SYNTAX OMsDirectoryString "
                        "SINGLE-VALUE )",
                NULL, NULL },
-       { "use-temporary-conn", "TRUE/FALSE", 2, 0, 0,
+       { "use-temporary-conn", "true|FALSE", 2, 2, 0,
                ARG_MAGIC|ARG_ON_OFF|LDAP_BACK_CFG_USETEMP,
                ldap_back_cf_gen, "( OLcfgDbAt:3.22 "
                        "NAME 'olcDbUseTemporaryConn' "
@@ -287,7 +288,7 @@ static ConfigTable ldapcfg[] = {
                        "SYNTAX OMsBoolean "
                        "SINGLE-VALUE )",
                NULL, NULL },
-       { "conn-pool-max", "<n>", 2, 0, 0,
+       { "conn-pool-max", "<n>", 2, 2, 0,
                ARG_MAGIC|ARG_INT|LDAP_BACK_CFG_CONNPOOLMAX,
                ldap_back_cf_gen, "( OLcfgDbAt:3.23 "
                        "NAME 'olcDbConnectionPoolMax' "
@@ -295,6 +296,16 @@ static ConfigTable ldapcfg[] = {
                        "SYNTAX OMsInteger "
                        "SINGLE-VALUE )",
                NULL, NULL },
+#ifdef SLAP_CONTROL_X_SESSION_TRACKING
+       { "session-tracking-request", "true|FALSE", 2, 2, 0,
+               ARG_MAGIC|ARG_ON_OFF|LDAP_BACK_CFG_ST_REQUEST,
+               ldap_back_cf_gen, "( OLcfgDbAt:3.24 "
+                       "NAME 'olcDbSessionTrackingRequest' "
+                       "DESC 'Add session tracking control to proxied requests' "
+                       "SYNTAX OMsBoolean "
+                       "SINGLE-VALUE )",
+               NULL, NULL },
+#endif /* SLAP_CONTROL_X_SESSION_TRACKING */
        { "suffixmassage", "[virtual]> <real", 2, 3, 0,
                ARG_STRING|ARG_MAGIC|LDAP_BACK_CFG_REWRITE,
                ldap_back_cf_gen, NULL, NULL, NULL },
@@ -554,11 +565,11 @@ slap_idassert_authzfrom_parse( ConfigArgs *c, slap_idassert_t *si )
                || strcasecmp( c->argv[ 1 ], "dn.regex:.*" ) == 0 )
        {
                if ( si->si_authz != NULL ) {
-                       snprintf( c->msg, sizeof( c->msg ),
+                       snprintf( c->cr_msg, sizeof( c->cr_msg ),
                                "\"idassert-authzFrom <authz>\": "
                                "\"%s\" conflicts with existing authz rules",
                                c->argv[ 1 ] );
-                       Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+                       Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
                        return 1;
                }
  
@@ -567,20 +578,20 @@ slap_idassert_authzfrom_parse( ConfigArgs *c, slap_idassert_t *si )
                return 0;
  
        } else if ( ( si->si_flags & LDAP_BACK_AUTH_AUTHZ_ALL ) ) {
-               snprintf( c->msg, sizeof( c->msg ),
+               snprintf( c->cr_msg, sizeof( c->cr_msg ),
                        "\"idassert-authzFrom <authz>\": "
                        "\"<authz>\" conflicts with \"*\"" );
-               Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+               Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
                return 1;
        }
        
        ber_str2bv( c->argv[ 1 ], 0, 0, &in );
        rc = authzNormalize( 0, NULL, NULL, &in, &bv, NULL );
        if ( rc != LDAP_SUCCESS ) {
-               snprintf( c->msg, sizeof( c->msg ),
+               snprintf( c->cr_msg, sizeof( c->cr_msg ),
                        "\"idassert-authzFrom <authz>\": "
                        "invalid syntax" );
-               Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+               Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
                return 1;
        }
   
@@ -601,11 +612,11 @@ slap_idassert_parse( ConfigArgs *c, slap_idassert_t *si )
 
                        j = verb_to_mask( argvi, idassert_mode );
                        if ( BER_BVISNULL( &idassert_mode[ j ].word ) ) {
-                               snprintf( c->msg, sizeof( c->msg ),
+                               snprintf( c->cr_msg, sizeof( c->cr_msg ),
                                        "\"idassert-bind <args>\": "
                                        "unknown mode \"%s\"",
                                        argvi );
-                               Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+                               Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
                                return 1;
                        }
 
@@ -616,11 +627,11 @@ slap_idassert_parse( ConfigArgs *c, slap_idassert_t *si )
 
                        if ( strcasecmp( argvi, "native" ) == 0 ) {
                                if ( si->si_bc.sb_method != LDAP_AUTH_SASL ) {
-                                       snprintf( c->msg, sizeof( c->msg ),
+                                       snprintf( c->cr_msg, sizeof( c->cr_msg ),
                                                "\"idassert-bind <args>\": "
                                                "authz=\"native\" incompatible "
                                                "with auth method" );
-                                       Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+                                       Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
                                        return 1;
                                }
                                si->si_flags |= LDAP_BACK_AUTH_NATIVE_AUTHZ;
@@ -629,11 +640,11 @@ slap_idassert_parse( ConfigArgs *c, slap_idassert_t *si )
                                si->si_flags &= ~LDAP_BACK_AUTH_NATIVE_AUTHZ;
 
                        } else {
-                               snprintf( c->msg, sizeof( c->msg ),
+                               snprintf( c->cr_msg, sizeof( c->cr_msg ),
                                        "\"idassert-bind <args>\": "
                                        "unknown authz \"%s\"",
                                        argvi );
-                               Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+                               Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
                                return 1;
                        }
 
@@ -643,11 +654,11 @@ slap_idassert_parse( ConfigArgs *c, slap_idassert_t *si )
                        int     j, err = 0;
 
                        if ( flags == NULL ) {
-                               snprintf( c->msg, sizeof( c->msg ),
+                               snprintf( c->cr_msg, sizeof( c->cr_msg ),
                                        "\"idassert-bind <args>\": "
                                        "unable to parse flags \"%s\"",
                                        argvi );
-                               Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+                               Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
                                return 1;
                        }
 
@@ -691,11 +702,11 @@ slap_idassert_parse( ConfigArgs *c, slap_idassert_t *si )
                                        }
 
                                } else {
-                                       snprintf( c->msg, sizeof( c->msg ),
+                                       snprintf( c->cr_msg, sizeof( c->cr_msg ),
                                                "\"idassert-bind <args>\": "
                                                "unknown flag \"%s\"",
                                                flags[ j ] );
-                                       Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+                                       Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
                                        err = 1;
                                        break;
                                }
@@ -1117,6 +1128,12 @@ ldap_back_cf_gen( ConfigArgs *c )
                        }
                        break;
 
+#ifdef SLAP_CONTROL_X_SESSION_TRACKING
+               case LDAP_BACK_CFG_ST_REQUEST:
+                       c->value_int = LDAP_BACK_ST_REQUEST( li );
+                       break;
+#endif /* SLAP_CONTROL_X_SESSION_TRACKING */
+
                default:
                        /* FIXME: we need to handle all... */
                        assert( 0 );
@@ -1233,6 +1250,12 @@ ldap_back_cf_gen( ConfigArgs *c )
                        li->li_flags &= ~LDAP_BACK_F_QUARANTINE;
                        break;
 
+#ifdef SLAP_CONTROL_X_SESSION_TRACKING
+               case LDAP_BACK_CFG_ST_REQUEST:
+                       li->li_flags &= ~LDAP_BACK_F_ST_REQUEST;
+                       break;
+#endif /* SLAP_CONTROL_X_SESSION_TRACKING */
+
                default:
                        /* FIXME: we need to handle all... */
                        assert( 0 );
@@ -1297,11 +1320,11 @@ ldap_back_cf_gen( ConfigArgs *c )
                                why = "unknown reason";
                                break;
                        }
-                       snprintf( c->msg, sizeof( c->msg),
+                       snprintf( c->cr_msg, sizeof( c->cr_msg),
                                        "unable to parse uri \"%s\" "
                                        "in \"uri <uri>\" line: %s",
                                        c->value_string, why );
-                       Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+                       Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
                        urlrc = 1;
                        goto done_url;
                }
@@ -1317,13 +1340,13 @@ ldap_back_cf_gen( ConfigArgs *c )
                                        || tmpludp->lud_filter != NULL
                                        || tmpludp->lud_exts != NULL )
                        {
-                               snprintf( c->msg, sizeof( c->msg ),
+                               snprintf( c->cr_msg, sizeof( c->cr_msg ),
                                                "warning, only protocol, "
                                                "host and port allowed "
                                                "in \"uri <uri>\" statement "
                                                "for uri #%d of \"%s\"",
                                                i, c->argv[ 1 ] );
-                               Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+                               Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
                        }
                }
 
@@ -1352,12 +1375,12 @@ ldap_back_cf_gen( ConfigArgs *c )
                        urllist[ i ]  = ldap_url_desc2str( &tmplud );
 
                        if ( urllist[ i ] == NULL ) {
-                               snprintf( c->msg, sizeof( c->msg),
+                               snprintf( c->cr_msg, sizeof( c->cr_msg),
                                        "unable to rebuild uri "
                                        "in \"uri <uri>\" statement "
                                        "for \"%s\"",
                                        c->argv[ 1 ] );
-                               Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+                               Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
                                urlrc = 1;
                                goto done_url;
                        }
@@ -1413,11 +1436,11 @@ done_url:;
                        break;
 
                default:
-                       snprintf( c->msg, sizeof( c->msg),
+                       snprintf( c->cr_msg, sizeof( c->cr_msg),
                                "\"acl-authcDN <DN>\" incompatible "
                                "with auth method %d",
                                li->li_acl_authmethod );
-                       Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+                       Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
                        return 1;
                }
                if ( !BER_BVISNULL( &li->li_acl_authcDN ) ) {
@@ -1439,11 +1462,11 @@ done_url:;
                        break;
 
                default:
-                       snprintf( c->msg, sizeof( c->msg ),
+                       snprintf( c->cr_msg, sizeof( c->cr_msg ),
                                "\"acl-passwd <cred>\" incompatible "
                                "with auth method %d",
                                li->li_acl_authmethod );
-                       Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+                       Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
                        return 1;
                }
                if ( !BER_BVISNULL( &li->li_acl_passwd ) ) {
@@ -1558,11 +1581,11 @@ done_url:;
                        break;
 
                default:
-                       snprintf( c->msg, sizeof( c->msg ),
+                       snprintf( c->cr_msg, sizeof( c->cr_msg ),
                                "\"idassert-authcDN <DN>\" incompatible "
                                "with auth method %d",
                                li->li_idassert_authmethod );
-                       Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+                       Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
                        return 1;
                }
                if ( !BER_BVISNULL( &li->li_idassert_authcDN ) ) {
@@ -1584,11 +1607,11 @@ done_url:;
                        break;
 
                default:
-                       snprintf( c->msg, sizeof( c->msg ),
+                       snprintf( c->cr_msg, sizeof( c->cr_msg ),
                                "\"idassert-passwd <cred>\" incompatible "
                                "with auth method %d",
                                li->li_idassert_authmethod );
-                       Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+                       Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
                        return 1;
                }
                if ( !BER_BVISNULL( &li->li_idassert_passwd ) ) {
@@ -1603,10 +1626,10 @@ done_url:;
 
        case LDAP_BACK_CFG_IDASSERT_METHOD:
                /* no longer supported */
-               snprintf( c->msg, sizeof( c->msg ),
+               snprintf( c->cr_msg, sizeof( c->cr_msg ),
                        "\"idassert-method <args>\": "
                        "no longer supported; use \"idassert-bind\"" );
-               Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+               Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
                return 1;
 
        case LDAP_BACK_CFG_IDASSERT_BIND:
@@ -1649,10 +1672,10 @@ done_url:;
                        int             rc;
 
                        if ( li->li_uri == NULL ) {
-                               snprintf( c->msg, sizeof( c->msg ),
-                                       "need URI to discover \"cancel\" support "
-                                       "in \"cancel exop-discover\"" );
-                               Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+                               snprintf( c->cr_msg, sizeof( c->cr_msg ),
+                                       "need URI to discover absolute filters support "
+                                       "in \"t-f-support discover\"" );
+                               Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
                                return 1;
                        }
 
@@ -1691,10 +1714,10 @@ done_url:;
                                unsigned        u;
 
                                if ( lutil_atoux( &u, c->argv[ i ], 0 ) != 0 ) {
-                                       snprintf( c->msg, sizeof( c->msg),
+                                       snprintf( c->cr_msg, sizeof( c->cr_msg),
                                                "unable to parse timeout \"%s\"",
                                                c->argv[ i ] );
-                                       Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+                                       Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
                                        return 1;
                                }
 
@@ -1706,10 +1729,10 @@ done_url:;
                        }
 
                        if ( slap_cf_aux_table_parse( c->argv[ i ], li->li_timeout, timeout_table, "slapd-ldap timeout" ) ) {
-                               snprintf( c->msg, sizeof( c->msg),
+                               snprintf( c->cr_msg, sizeof( c->cr_msg),
                                        "unable to parse timeout \"%s\"",
                                        c->argv[ i ] );
-                               Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+                               Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
                                return 1;
                        }
                }
@@ -1719,10 +1742,10 @@ done_url:;
                unsigned long   t;
 
                if ( lutil_parse_time( c->argv[ 1 ], &t ) != 0 ) {
-                       snprintf( c->msg, sizeof( c->msg),
+                       snprintf( c->cr_msg, sizeof( c->cr_msg),
                                "unable to parse idle timeout \"%s\"",
                                c->argv[ 1 ] );
-                       Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+                       Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
                        return 1;
                }
                li->li_idle_timeout = (time_t)t;
@@ -1732,10 +1755,10 @@ done_url:;
                unsigned long   t;
 
                if ( lutil_parse_time( c->argv[ 1 ], &t ) != 0 ) {
-                       snprintf( c->msg, sizeof( c->msg),
+                       snprintf( c->cr_msg, sizeof( c->cr_msg),
                                "unable to parse conn ttl\"%s\"",
                                c->argv[ 1 ] );
-                       Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+                       Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
                        return 1;
                }
                li->li_conn_ttl = (time_t)t;
@@ -1745,10 +1768,10 @@ done_url:;
                unsigned long   t;
 
                if ( lutil_parse_time( c->argv[ 1 ], &t ) != 0 ) {
-                       snprintf( c->msg, sizeof( c->msg),
+                       snprintf( c->cr_msg, sizeof( c->cr_msg),
                                "unable to parse network timeout \"%s\"",
                                c->argv[ 1 ] );
-                       Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+                       Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
                        return 1;
                }
                li->li_network_timeout = (time_t)t;
@@ -1756,11 +1779,11 @@ done_url:;
 
        case LDAP_BACK_CFG_VERSION:
                if ( c->value_int != 0 && ( c->value_int < LDAP_VERSION_MIN || c->value_int > LDAP_VERSION_MAX ) ) {
-                       snprintf( c->msg, sizeof( c->msg ),
+                       snprintf( c->cr_msg, sizeof( c->cr_msg ),
                                "unsupported version \"%s\" "
                                "in \"protocol-version <version>\"",
                                c->argv[ 1 ] );
-                       Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+                       Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
                        return 1;
                }
 
@@ -1789,7 +1812,7 @@ done_url:;
                if ( c->value_int < LDAP_BACK_CONN_PRIV_MIN
                        || c->value_int > LDAP_BACK_CONN_PRIV_MAX )
                {
-                       snprintf( c->msg, sizeof( c->msg ),
+                       snprintf( c->cr_msg, sizeof( c->cr_msg ),
                                "invalid max size " "of privileged "
                                "connections pool \"%s\" "
                                "in \"conn-pool-max <n> "
@@ -1797,7 +1820,7 @@ done_url:;
                                c->argv[ 1 ],
                                LDAP_BACK_CONN_PRIV_MIN,
                                LDAP_BACK_CONN_PRIV_MAX );
-                       Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+                       Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
                        return 1;
                }
                li->li_conn_priv_max = c->value_int;
@@ -1821,10 +1844,10 @@ done_url:;
                        int             rc;
 
                        if ( li->li_uri == NULL ) {
-                               snprintf( c->msg, sizeof( c->msg ),
+                               snprintf( c->cr_msg, sizeof( c->cr_msg ),
                                        "need URI to discover \"cancel\" support "
                                        "in \"cancel exop-discover\"" );
-                               Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+                               Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
                                return 1;
                        }
 
@@ -1847,15 +1870,15 @@ done_url:;
 
        case LDAP_BACK_CFG_QUARANTINE:
                if ( LDAP_BACK_QUARANTINE( li ) ) {
-                       snprintf( c->msg, sizeof( c->msg ),
+                       snprintf( c->cr_msg, sizeof( c->cr_msg ),
                                "quarantine already defined" );
-                       Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+                       Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
                        return 1;
                }
                rc = slap_retry_info_parse( c->argv[1], &li->li_quarantine,
-                       c->msg, sizeof( c->msg ) );
+                       c->cr_msg, sizeof( c->cr_msg ) );
                if ( rc ) {
-                       Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+                       Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
 
                } else {
                        ldap_pvt_thread_mutex_init( &li->li_quarantine_mutex );
@@ -1866,13 +1889,24 @@ done_url:;
                }
                break;
 
+#ifdef SLAP_CONTROL_X_SESSION_TRACKING
+       case LDAP_BACK_CFG_ST_REQUEST:
+               if ( c->value_int ) {
+                       li->li_flags |= LDAP_BACK_F_ST_REQUEST;
+
+               } else {
+                       li->li_flags &= ~LDAP_BACK_F_ST_REQUEST;
+               }
+               break;
+#endif /* SLAP_CONTROL_X_SESSION_TRACKING */
+
        case LDAP_BACK_CFG_REWRITE:
-               snprintf( c->msg, sizeof( c->msg ),
+               snprintf( c->cr_msg, sizeof( c->cr_msg ),
                        "rewrite/remap capabilities have been moved "
                        "to the \"rwm\" overlay; see slapo-rwm(5) "
                        "for details (hint: add \"overlay rwm\" "
                        "and prefix all directives with \"rwm-\")" );
-               Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+               Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
                return 1;
                
        default:
index 4f1e67ddf87e4a68bb442e1bac69587764596024..f10c7d0bbbbe22461052bb33ae2f5a3cd67aa17c 100644 (file)
@@ -50,8 +50,7 @@ ldap_back_delete(
 
 retry:
        ctrls = op->o_ctrls;
-       rc = ldap_back_proxy_authz_ctrl( &lc->lc_bound_ndn,
-               li->li_version, &li->li_idassert, op, rs, &ctrls );
+       rc = ldap_back_controls_add( op, rs, lc, &ctrls );
        if ( rc != LDAP_SUCCESS ) {
                send_ldap_result( op, rs );
                rc = rs->sr_err;
@@ -67,13 +66,13 @@ retry:
                retrying &= ~LDAP_BACK_RETRYING;
                if ( ldap_back_retry( &lc, op, rs, LDAP_BACK_SENDERR ) ) {
                        /* if the identity changed, there might be need to re-authz */
-                       (void)ldap_back_proxy_authz_ctrl_free( op, &ctrls );
+                       (void)ldap_back_controls_free( op, rs, &ctrls );
                        goto retry;
                }
        }
 
 cleanup:
-       (void)ldap_back_proxy_authz_ctrl_free( op, &ctrls );
+       (void)ldap_back_controls_free( op, rs, &ctrls );
 
        if ( lc != NULL ) {
                ldap_back_release_conn( li, lc );
index 95a167f6131f620ed5f19e6fc6121ec5a8f0e701..42424683ed5c49e8745ab6569add6180ac21508f 100644 (file)
@@ -237,7 +237,7 @@ static int ldap_distproc_db_init_common( BackendDB  *be );
 static int ldap_distproc_db_init_one( BackendDB *be );
 #define        ldap_distproc_db_open_one(be)           (lback)->bi_db_open( (be) )
 #define        ldap_distproc_db_close_one(be)          (0)
-#define        ldap_distproc_db_destroy_one(be)        (lback)->bi_db_destroy( (be) )
+#define        ldap_distproc_db_destroy_one(be, ca)    (lback)->bi_db_destroy( (be), (ca) )
 
 static int
 ldap_distproc_parse_ctrl(
@@ -447,7 +447,7 @@ distproc_ldadd( CfEntryInfo *p, Entry *e, ConfigArgs *ca )
 
 done:;
        if ( rc != LDAP_SUCCESS ) {
-               (void)ldap_distproc_db_destroy_one( ca->be );
+               (void)ldap_distproc_db_destroy_one( ca->be, NULL );
                ch_free( ca->be );
                ca->be = NULL;
        }
@@ -472,9 +472,9 @@ ldap_distproc_cfadd_apply( void *datum, void *arg )
        struct berval                   bv;
 
        /* FIXME: should not hardcode "olcDatabase" here */
-       bv.bv_len = snprintf( lca->ca->msg, sizeof( lca->ca->msg ),
+       bv.bv_len = snprintf( lca->ca->cr_msg, sizeof( lca->ca->cr_msg ),
                "olcDatabase={%d}%s", lca->count, lback->bi_type );
-       bv.bv_val = lca->ca->msg;
+       bv.bv_val = lca->ca->cr_msg;
 
        lca->ca->be->be_private = (void *)li;
        config_build_entry( lca->op, lca->rs, lca->p->e_private, lca->ca,
@@ -567,7 +567,8 @@ distproc_cfgen( ConfigArgs *c )
 
 static int
 ldap_distproc_db_init(
-       BackendDB *be )
+       BackendDB *be,
+       ConfigReply *cr )
 {
        slap_overinst   *on = (slap_overinst *)be->bd_info;
        ldap_distproc_t *lc = NULL;
@@ -659,7 +660,7 @@ private_destroy:;
 
                                db.bd_info = lback;
                                db.be_private = (void *)lc->lc_cfg_li;
-                               ldap_distproc_db_destroy_one( &db );
+                               ldap_distproc_db_destroy_one( &db, NULL );
                                lc->lc_cfg_li = NULL;
 
                        } else {
@@ -712,7 +713,7 @@ ldap_distproc_db_apply( void *datum, void *arg )
 
        lca->be->be_private = (void *)li;
 
-       return lca->func( lca->be );
+       return lca->func( lca->be, NULL );
 }
 
 static int
@@ -735,7 +736,7 @@ ldap_distproc_db_func(
                        db.bd_info = lback;
                        db.be_private = lc->lc_common_li;
 
-                       rc = func( &db );
+                       rc = func( &db, NULL );
 
                        if ( rc != 0 ) {
                                return rc;
@@ -759,21 +760,24 @@ ldap_distproc_db_func(
 
 static int
 ldap_distproc_db_open(
-       BackendDB       *be )
+       BackendDB       *be,
+       ConfigReply     *cr )
 {
        return ldap_distproc_db_func( be, db_open );
 }
 
 static int
 ldap_distproc_db_close(
-       BackendDB       *be )
+       BackendDB       *be,
+       ConfigReply     *cr )
 {
        return ldap_distproc_db_func( be, db_close );
 }
 
 static int
 ldap_distproc_db_destroy(
-       BackendDB       *be )
+       BackendDB       *be,
+       ConfigReply     *cr )
 {
        slap_overinst   *on = (slap_overinst *) be->bd_info;
        ldap_distproc_t *lc = (ldap_distproc_t *)on->on_bi.bi_private;
@@ -804,7 +808,7 @@ ldap_distproc_db_init_common(
 
        be->bd_info = lback;
        be->be_private = NULL;
-       t = lback->bi_db_init( be );
+       t = lback->bi_db_init( be, NULL );
        if ( t != 0 ) {
                return t;
        }
@@ -835,7 +839,7 @@ ldap_distproc_db_init_one(
 
        be->bd_info = lback;
        be->be_private = NULL;
-       t = lback->bi_db_init( be );
+       t = lback->bi_db_init( be, NULL );
        if ( t != 0 ) {
                return t;
        }
index 38dbfcd71105a186412fce941b49825da89f99cc..cf3aacbb71ebf2504c1b3ef1523b7ac48b92d6e0 100644 (file)
 #include "back-ldap.h"
 #include "lber_pvt.h"
 
-static BI_op_extended ldap_back_exop_passwd;
-static BI_op_extended ldap_back_exop_generic;
+typedef int (ldap_back_exop_f)( Operation *op, SlapReply *rs, ldapconn_t **lc );
+
+static ldap_back_exop_f ldap_back_exop_passwd;
+static ldap_back_exop_f ldap_back_exop_generic;
 
 static struct exop {
-       struct berval   oid;
-       BI_op_extended  *extended;
+       struct berval           oid;
+       ldap_back_exop_f        *extended;
 } exop_table[] = {
        { BER_BVC(LDAP_EXOP_MODIFY_PASSWD),     ldap_back_exop_passwd },
        { BER_BVNULL, NULL }
 };
 
 static int
-ldap_back_extended_one( Operation *op, SlapReply *rs, BI_op_extended exop )
+ldap_back_extended_one( Operation *op, SlapReply *rs, ldap_back_exop_f exop )
 {
        ldapinfo_t      *li = (ldapinfo_t *) op->o_bd->be_private;
 
        ldapconn_t      *lc = NULL;
-       LDAPControl     **oldctrls = NULL;
+       LDAPControl     **ctrls = NULL, **oldctrls = NULL;
        int             rc;
 
        /* FIXME: this needs to be called here, so it is
@@ -56,9 +58,8 @@ ldap_back_extended_one( Operation *op, SlapReply *rs, BI_op_extended exop )
                return -1;
        }
 
-       oldctrls = op->o_ctrls;
-       if ( ldap_back_proxy_authz_ctrl( &lc->lc_bound_ndn,
-               li->li_version, &li->li_idassert, op, rs, &op->o_ctrls ) )
+       ctrls = op->o_ctrls;
+       if ( ldap_back_controls_add( op, rs, lc, &ctrls ) )
        {
                op->o_ctrls = oldctrls;
                send_ldap_extended( op, rs );
@@ -68,13 +69,11 @@ ldap_back_extended_one( Operation *op, SlapReply *rs, BI_op_extended exop )
                goto done;
        }
 
-       rc = exop( op, rs );
+       op->o_ctrls = ctrls;
+       rc = exop( op, rs, &lc );
 
-       if ( op->o_ctrls && op->o_ctrls != oldctrls ) {
-               free( op->o_ctrls[ 0 ] );
-               free( op->o_ctrls );
-       }
        op->o_ctrls = oldctrls;
+       (void)ldap_back_controls_free( op, rs, &ctrls );
 
 done:;
        if ( lc != NULL ) {
@@ -106,35 +105,90 @@ ldap_back_extended(
 
 static int
 ldap_back_exop_passwd(
-               Operation       *op,
-               SlapReply       *rs )
+       Operation       *op,
+       SlapReply       *rs,
+       ldapconn_t      **lcp )
 {
        ldapinfo_t      *li = (ldapinfo_t *) op->o_bd->be_private;
 
-       ldapconn_t      *lc = NULL;
+       ldapconn_t      *lc = *lcp;
        req_pwdexop_s   *qpw = &op->oq_pwdexop;
        LDAPMessage     *res;
        ber_int_t       msgid;
-       int             rc, isproxy;
+       int             rc, isproxy, freedn = 0;
        int             do_retry = 1;
-       char *text = NULL;
+       char            *text = NULL;
+       struct berval   dn = op->o_req_dn,
+                       ndn = op->o_req_ndn;
+
+       assert( lc != NULL );
+       assert( rs->sr_ctrls == NULL );
+
+       if ( BER_BVISNULL( &ndn ) && op->ore_reqdata != NULL ) {
+               /* NOTE: most of this code is mutuated
+                * from slap_passwd_parse(); we can't call
+                * that function since now the request data
+                * has been destroyed by NULL-terminating
+                * the bervals.  Luckily enough, we only need
+                * the first berval... */
+
+               ber_tag_t tag;
+               ber_len_t len = -1;
+               BerElementBuffer berbuf;
+               BerElement *ber = (BerElement *)&berbuf;
+
+               struct berval   tmpid = BER_BVNULL;
+
+               if ( op->ore_reqdata->bv_len == 0 ) {
+                       return LDAP_PROTOCOL_ERROR;
+               }
 
-       if ( !ldap_back_dobind( &lc, op, rs, LDAP_BACK_SENDERR ) ) {
-               return -1;
+               /* ber_init2 uses reqdata directly, doesn't allocate new buffers */
+               ber_init2( ber, op->ore_reqdata, 0 );
+
+               tag = ber_scanf( ber, "{" /*}*/ );
+
+               if ( tag == LBER_ERROR ) {
+                       return LDAP_PROTOCOL_ERROR;
+               }
+
+               tag = ber_peek_tag( ber, &len );
+               if ( tag == LDAP_TAG_EXOP_MODIFY_PASSWD_ID ) {
+                       tag = ber_scanf( ber, "m", &tmpid );
+
+                       if ( tag == LBER_ERROR ) {
+                               return LDAP_PROTOCOL_ERROR;
+                       }
+               }
+
+               if ( !BER_BVISEMPTY( &tmpid ) ) {
+                       rs->sr_err = dnPrettyNormal( NULL, &tmpid, &dn,
+                               &ndn, op->o_tmpmemctx );
+                       if ( rs->sr_err != LDAP_SUCCESS ) {
+                               /* should have been successfully parsed earlier! */
+                               return rs->sr_err;
+                       }
+                       freedn = 1;
+
+               } else {
+                       dn = op->o_dn;
+                       ndn = op->o_ndn;
+               }
        }
 
-       isproxy = ber_bvcmp( &op->o_req_ndn, &op->o_ndn );
+       isproxy = ber_bvcmp( &ndn, &op->o_ndn );
 
        Debug( LDAP_DEBUG_ARGS, "==> ldap_back_exop_passwd(\"%s\")%s\n",
-               op->o_req_dn.bv_val, isproxy ? " (proxy)" : "", 0 );
+               dn.bv_val, isproxy ? " (proxy)" : "", 0 );
 
 retry:
-       rc = ldap_passwd( lc->lc_ld, isproxy ? &op->o_req_dn : NULL,
+       rc = ldap_passwd( lc->lc_ld, isproxy ? &dn : NULL,
                qpw->rs_old.bv_val ? &qpw->rs_old : NULL,
                qpw->rs_new.bv_val ? &qpw->rs_new : NULL,
                op->o_ctrls, NULL, &msgid );
 
        if ( rc == LDAP_SUCCESS ) {
+               /* TODO: set timeout? */
                if ( ldap_result( lc->lc_ld, msgid, LDAP_MSG_ALL, NULL, &res ) == -1 ) {
                        ldap_get_option( lc->lc_ld, LDAP_OPT_ERROR_NUMBER, &rc );
                        rs->sr_err = rc;
@@ -151,7 +205,7 @@ retry:
                        rc = ldap_parse_result( lc->lc_ld, res, &rs->sr_err,
                                        (char **)&rs->sr_matched,
                                        &text,
-                                       NULL, NULL, 0 );
+                                       NULL, &rs->sr_ctrls, 0 );
 
                        if ( rc == LDAP_SUCCESS ) {
                                if ( rs->sr_err == LDAP_SUCCESS ) {
@@ -204,19 +258,30 @@ retry:
                ldap_back_quarantine( op, rs );
        }
 
+       if ( freedn ) {
+               op->o_tmpfree( dn.bv_val, op->o_tmpmemctx );
+               op->o_tmpfree( ndn.bv_val, op->o_tmpmemctx );
+       }
+
        /* these have to be freed anyway... */
        if ( rs->sr_matched ) {
                free( (char *)rs->sr_matched );
                rs->sr_matched = NULL;
        }
 
+       if ( rs->sr_ctrls ) {
+               ldap_controls_free( rs->sr_ctrls );
+               rs->sr_ctrls = NULL;
+       }
+
        if ( text ) {
                free( text );
                rs->sr_text = NULL;
        }
 
-       if ( lc != NULL ) {
-               ldap_back_release_conn( li, lc );
+       /* in case, cleanup handler */
+       if ( lc == NULL ) {
+               *lcp = NULL;
        }
 
        return rc;
@@ -225,20 +290,20 @@ retry:
 static int
 ldap_back_exop_generic(
        Operation       *op,
-       SlapReply       *rs )
+       SlapReply       *rs,
+       ldapconn_t      **lcp )
 {
        ldapinfo_t      *li = (ldapinfo_t *) op->o_bd->be_private;
 
-       ldapconn_t      *lc = NULL;
+       ldapconn_t      *lc = *lcp;
        LDAPMessage     *res;
        ber_int_t       msgid;
        int             rc;
        int             do_retry = 1;
-       char *text = NULL;
+       char            *text = NULL;
 
-       if ( !ldap_back_dobind( &lc, op, rs, LDAP_BACK_SENDERR ) ) {
-               return -1;
-       }
+       assert( lc != NULL );
+       assert( rs->sr_ctrls == NULL );
 
        Debug( LDAP_DEBUG_ARGS, "==> ldap_back_exop_generic(%s, \"%s\")\n",
                op->ore_reqoid.bv_val, op->o_req_dn.bv_val, 0 );
@@ -249,6 +314,7 @@ retry:
                op->o_ctrls, NULL, &msgid );
 
        if ( rc == LDAP_SUCCESS ) {
+               /* TODO: set timeout? */
                if ( ldap_result( lc->lc_ld, msgid, LDAP_MSG_ALL, NULL, &res ) == -1 ) {
                        ldap_get_option( lc->lc_ld, LDAP_OPT_ERROR_NUMBER, &rc );
                        rs->sr_err = rc;
@@ -265,7 +331,7 @@ retry:
                        rc = ldap_parse_result( lc->lc_ld, res, &rs->sr_err,
                                        (char **)&rs->sr_matched,
                                        &text,
-                                       NULL, NULL, 0 );
+                                       NULL, &rs->sr_ctrls, 0 );
                        if ( rc == LDAP_SUCCESS ) {
                                if ( rs->sr_err == LDAP_SUCCESS ) {
                                        rc = ldap_parse_extended_result( lc->lc_ld, res,
@@ -310,13 +376,19 @@ retry:
                rs->sr_matched = NULL;
        }
 
+       if ( rs->sr_ctrls ) {
+               ldap_controls_free( rs->sr_ctrls );
+               rs->sr_ctrls = NULL;
+       }
+
        if ( text ) {
                free( text );
                rs->sr_text = NULL;
        }
 
-       if ( lc != NULL ) {
-               ldap_back_release_conn( li, lc );
+       /* in case, cleanup handler */
+       if ( lc == NULL ) {
+               *lcp = NULL;
        }
 
        return rc;
index d9a4ff61c4250aca3d77f24a1a85a48c428c4e5a..32b07b2f8c5c8e504e4ac3b7a983d55d2f189999 100644 (file)
@@ -29,6 +29,7 @@
 #include <ac/socket.h>
 
 #include "slap.h"
+#include "config.h"
 #include "back-ldap.h"
 
 int
@@ -98,7 +99,7 @@ ldap_back_initialize( BackendInfo *bi )
 }
 
 int
-ldap_back_db_init( Backend *be )
+ldap_back_db_init( Backend *be, ConfigReply *cr )
 {
        ldapinfo_t      *li;
        int             rc;
@@ -168,7 +169,7 @@ ldap_back_db_init( Backend *be )
 }
 
 int
-ldap_back_db_open( BackendDB *be )
+ldap_back_db_open( BackendDB *be, ConfigReply *cr )
 {
        ldapinfo_t      *li = (ldapinfo_t *)be->be_private;
 
@@ -255,7 +256,7 @@ ldap_back_conn_free( void *v_lc )
 }
 
 int
-ldap_back_db_close( Backend *be )
+ldap_back_db_close( Backend *be, ConfigReply *cr )
 {
        int             rc = 0;
 
@@ -267,7 +268,7 @@ ldap_back_db_close( Backend *be )
 }
 
 int
-ldap_back_db_destroy( Backend *be )
+ldap_back_db_destroy( Backend *be, ConfigReply *cr )
 {
        if ( be->be_private ) {
                ldapinfo_t      *li = ( ldapinfo_t * )be->be_private;
index 3c287cd8db02c67fffdebdc2b239da4e1f119849..7b5817f0665df164f345603acf20e353051e5bb7 100644 (file)
@@ -52,7 +52,7 @@ ldap_back_modify(
                return rs->sr_err;
        }
 
-       for ( i = 0, ml = op->oq_modify.rs_modlist; ml; i++, ml = ml->sml_next )
+       for ( i = 0, ml = op->orm_modlist; ml; i++, ml = ml->sml_next )
                /* just count mods */ ;
 
        modv = (LDAPMod **)ch_malloc( ( i + 1 )*sizeof( LDAPMod * )
@@ -64,7 +64,7 @@ ldap_back_modify(
        mods = (LDAPMod *)&modv[ i + 1 ];
 
        isupdate = be_shadow_update( op );
-       for ( i = 0, ml = op->oq_modify.rs_modlist; ml; ml = ml->sml_next ) {
+       for ( i = 0, ml = op->orm_modlist; ml; ml = ml->sml_next ) {
                if ( !isupdate && !get_relax( op ) && ml->sml_desc->ad_type->sat_no_user_mod  )
                {
                        continue;
@@ -99,8 +99,7 @@ ldap_back_modify(
 
 retry:;
        ctrls = op->o_ctrls;
-       rc = ldap_back_proxy_authz_ctrl( &lc->lc_bound_ndn,
-               li->li_version, &li->li_idassert, op, rs, &ctrls );
+       rc = ldap_back_controls_add( op, rs, lc, &ctrls );
        if ( rc != LDAP_SUCCESS ) {
                send_ldap_result( op, rs );
                rc = -1;
@@ -116,13 +115,13 @@ retry:;
                retrying &= ~LDAP_BACK_RETRYING;
                if ( ldap_back_retry( &lc, op, rs, LDAP_BACK_SENDERR ) ) {
                        /* if the identity changed, there might be need to re-authz */
-                       (void)ldap_back_proxy_authz_ctrl_free( op, &ctrls );
+                       (void)ldap_back_controls_free( op, rs, &ctrls );
                        goto retry;
                }
        }
 
 cleanup:;
-       (void)ldap_back_proxy_authz_ctrl_free( op, &ctrls );
+       (void)ldap_back_controls_free( op, rs, &ctrls );
 
        for ( i = 0; modv[ i ]; i++ ) {
                ch_free( modv[ i ]->mod_bvalues );
index 8fa02ef6e2a216c6f6cc430095a7984433ec1e91..d6e3b018542093f10c2d6d51c6e72f1e1675cb12 100644 (file)
@@ -74,8 +74,7 @@ ldap_back_modrdn(
 
 retry:
        ctrls = op->o_ctrls;
-       rc = ldap_back_proxy_authz_ctrl( &lc->lc_bound_ndn,
-               li->li_version, &li->li_idassert, op, rs, &ctrls );
+       rc = ldap_back_controls_add( op, rs, lc, &ctrls );
        if ( rc != LDAP_SUCCESS ) {
                send_ldap_result( op, rs );
                rc = -1;
@@ -92,13 +91,13 @@ retry:
                retrying &= ~LDAP_BACK_RETRYING;
                if ( ldap_back_retry( &lc, op, rs, LDAP_BACK_SENDERR ) ) {
                        /* if the identity changed, there might be need to re-authz */
-                       (void)ldap_back_proxy_authz_ctrl_free( op, &ctrls );
+                       (void)ldap_back_controls_free( op, rs, &ctrls );
                        goto retry;
                }
        }
 
 cleanup:
-       (void)ldap_back_proxy_authz_ctrl_free( op, &ctrls );
+       (void)ldap_back_controls_free( op, rs, &ctrls );
 
        if ( lc != NULL ) {
                ldap_back_release_conn( li, lc );
index 8eca7f6593a204e53e5e4d0eb76b255754f04b5e..9bc413338735ec3ea5d5b374621a40014dad91cf 100644 (file)
@@ -63,6 +63,7 @@ extern void ldap_back_conn_free( void *c );
 
 extern ldapconn_t * ldap_back_conn_delete( ldapinfo_t *li, ldapconn_t *lc );
 
+#if 0
 extern int
 ldap_back_proxy_authz_ctrl(
                struct berval   *bound_ndn,
@@ -76,6 +77,26 @@ extern int
 ldap_back_proxy_authz_ctrl_free(
                Operation       *op,
                LDAPControl     ***pctrls );
+#endif
+
+extern int
+ldap_back_proxy_authz_ctrl(
+               Operation       *op,
+               SlapReply       *rs,
+               struct berval   *bound_ndn,
+               int             version,
+               slap_idassert_t *si,
+               LDAPControl     *ctrl );
+
+extern int
+ldap_back_controls_add(
+               Operation       *op,
+               SlapReply       *rs,
+               ldapconn_t      *lc,
+               LDAPControl     ***pctrls );
+
+extern int
+ldap_back_controls_free( Operation *op, SlapReply *rs, LDAPControl ***pctrls );
 
 extern void
 ldap_back_quarantine(
index 1154d44d826706c17a5013187d9a5c52d13620e0..4c4f078fb1442d45dfa8853506eb5430b4ee4ae9 100644 (file)
@@ -158,6 +158,8 @@ ldap_back_search(
        int             freetext = 0;
        int             do_retry = 1, dont_retry = 0;
        LDAPControl     **ctrls = NULL;
+       char            **references = NULL;
+
        /* FIXME: shouldn't this be null? */
        const char      *save_matched = rs->sr_matched;
 
@@ -203,8 +205,7 @@ ldap_back_search(
        }
 
        ctrls = op->o_ctrls;
-       rc = ldap_back_proxy_authz_ctrl( &lc->lc_bound_ndn,
-               li->li_version, &li->li_idassert, op, rs, &ctrls );
+       rc = ldap_back_controls_add( op, rs, lc, &ctrls );
        if ( rc != LDAP_SUCCESS ) {
                goto finish;
        }
@@ -328,12 +329,18 @@ retry:
                        e = ldap_first_entry( lc->lc_ld, res );
                        rc = ldap_build_entry( op, e, &ent, &bdn );
                        if ( rc == LDAP_SUCCESS ) {
+                               ldap_get_entry_controls( lc->lc_ld, res, &rs->sr_ctrls );
                                rs->sr_entry = &ent;
                                rs->sr_attrs = op->ors_attrs;
                                rs->sr_operational_attrs = NULL;
                                rs->sr_flags = 0;
                                rs->sr_err = LDAP_SUCCESS;
                                rc = rs->sr_err = send_search_entry( op, rs );
+                               if ( rs->sr_ctrls ) {
+                                       ldap_controls_free( rs->sr_ctrls );
+                                       rs->sr_ctrls = NULL;
+                               }
+                               rs->sr_entry = NULL;
                                if ( !BER_BVISNULL( &ent.e_name ) ) {
                                        assert( ent.e_name.bv_val != bdn.bv_val );
                                        op->o_tmpfree( ent.e_name.bv_val, op->o_tmpmemctx );
@@ -356,8 +363,6 @@ retry:
                        }
 
                } else if ( rc == LDAP_RES_SEARCH_REFERENCE ) {
-                       char            **references = NULL;
-
                        do_retry = 0;
                        rc = ldap_parse_reference( lc->lc_ld, res,
                                        &references, &rs->sr_ctrls, 1 );
@@ -383,6 +388,7 @@ retry:
                                BER_BVZERO( &rs->sr_ref[ cnt ] );
 
                                /* ignore return value by now */
+                               rs->sr_entry = NULL;
                                ( void )send_search_reference( op, rs );
 
                        } else {
@@ -398,6 +404,7 @@ retry:
                                ber_memvfree( (void **)references );
                                op->o_tmpfree( rs->sr_ref, op->o_tmpmemctx );
                                rs->sr_ref = NULL;
+                               references = NULL;
                        }
 
                        if ( rs->sr_ctrls ) {
@@ -406,7 +413,7 @@ retry:
                        }
 
                } else {
-                       char            **references = NULL, *err = NULL;
+                       char            *err = NULL;
 
                        rc = ldap_parse_result( lc->lc_ld, res, &rs->sr_err,
                                        &match.bv_val, &err,
@@ -420,41 +427,50 @@ retry:
                                freetext = 1;
                        }
 
-                       if ( references && references[ 0 ] && references[ 0 ][ 0 ] ) {
-                               int     cnt;
-
+                       /* RFC 4511: referrals can only appear
+                        * if result code is LDAP_REFERRAL */
+                       if ( references 
+                               && references[ 0 ]
+                               && references[ 0 ][ 0 ] )
+                       {
                                if ( rs->sr_err != LDAP_REFERRAL ) {
-                                       /* FIXME: error */
                                        Debug( LDAP_DEBUG_ANY,
                                                "%s ldap_back_search: "
-                                               "got referrals with %d\n",
+                                               "got referrals with err=%d\n",
                                                op->o_log_prefix,
                                                rs->sr_err, 0 );
-                                       rs->sr_err = LDAP_REFERRAL;
-                               }
 
-                               for ( cnt = 0; references[ cnt ]; cnt++ )
-                                       /* NO OP */ ;
+                               } else {
+                                       int     cnt;
+
+                                       for ( cnt = 0; references[ cnt ]; cnt++ )
+                                               /* NO OP */ ;
                                
-                               rs->sr_ref = op->o_tmpalloc( ( cnt + 1 ) * sizeof( struct berval ),
-                                       op->o_tmpmemctx );
+                                       rs->sr_ref = op->o_tmpalloc( ( cnt + 1 ) * sizeof( struct berval ),
+                                               op->o_tmpmemctx );
 
-                               for ( cnt = 0; references[ cnt ]; cnt++ ) {
-                                       /* duplicating ...*/
-                                       ber_str2bv( references[ cnt ], 0, 1, &rs->sr_ref[ cnt ] );
+                                       for ( cnt = 0; references[ cnt ]; cnt++ ) {
+                                               /* duplicating ...*/
+                                               ber_str2bv( references[ cnt ], 0, 0, &rs->sr_ref[ cnt ] );
+                                       }
+                                       BER_BVZERO( &rs->sr_ref[ cnt ] );
                                }
-                               BER_BVZERO( &rs->sr_ref[ cnt ] );
+
+                       } else if ( rs->sr_err == LDAP_REFERRAL ) {
+                               Debug( LDAP_DEBUG_ANY,
+                                       "%s ldap_back_search: "
+                                       "got err=%d with null "
+                                       "or empty referrals\n",
+                                       op->o_log_prefix,
+                                       rs->sr_err, 0 );
+
+                               rs->sr_err = LDAP_NO_SUCH_OBJECT;
                        }
 
                        if ( match.bv_val != NULL ) {
                                match.bv_len = strlen( match.bv_val );
                        }
 
-                       /* cleanup */
-                       if ( references ) {
-                               ber_memvfree( (void **)references );
-                       }
-
                        rc = 0;
                        break;
                }
@@ -512,7 +528,7 @@ finish:;
                send_ldap_result( op, rs );
        }
 
-       (void)ldap_back_proxy_authz_ctrl_free( op, &ctrls );
+       (void)ldap_back_controls_free( op, rs, &ctrls );
 
        if ( rs->sr_ctrls ) {
                ldap_controls_free( rs->sr_ctrls );
@@ -541,10 +557,14 @@ finish:;
        }
 
        if ( rs->sr_ref ) {
-               ber_bvarray_free_x( rs->sr_ref, op->o_tmpmemctx );
+               op->o_tmpfree( rs->sr_ref, op->o_tmpmemctx );
                rs->sr_ref = NULL;
        }
 
+       if ( references ) {
+               ber_memvfree( (void **)references );
+       }
+
        if ( attrs ) {
                ch_free( attrs );
        }
@@ -798,8 +818,7 @@ ldap_back_entry_get(
 
 retry:
        ctrls = op->o_ctrls;
-       rc = ldap_back_proxy_authz_ctrl( &lc->lc_bound_ndn,
-               li->li_version, &li->li_idassert, op, &rs, &ctrls );
+       rc = ldap_back_controls_add( op, &rs, lc, &ctrls );
        if ( rc != LDAP_SUCCESS ) {
                goto cleanup;
        }
@@ -812,7 +831,7 @@ retry:
                        do_retry = 0;
                        if ( ldap_back_retry( &lc, op, &rs, LDAP_BACK_DONTSEND ) ) {
                                /* if the identity changed, there might be need to re-authz */
-                               (void)ldap_back_proxy_authz_ctrl_free( op, &ctrls );
+                               (void)ldap_back_controls_free( op, &rs, &ctrls );
                                goto retry;
                        }
                }
@@ -839,7 +858,7 @@ retry:
        }
 
 cleanup:
-       (void)ldap_back_proxy_authz_ctrl_free( op, &ctrls );
+       (void)ldap_back_controls_free( op, &rs, &ctrls );
 
        if ( result ) {
                ldap_msgfree( result );
index 855e63889f85a912adb206c2a78455c42dd10b2a..4ad7603367506a8e50251f62efc7e701084e91f8 100644 (file)
@@ -86,7 +86,6 @@ dn2path(struct berval * dn, struct berval * suffixdn, struct berval * base_path,
        struct berval *res)
 {
        char *ptr, *sep, *end;
-       struct berval bv;
 
        assert( dn != NULL );
        assert( !BER_BVISNULL( dn ) );
@@ -108,19 +107,22 @@ dn2path(struct berval * dn, struct berval * suffixdn, struct berval * base_path,
        }
        strcpy(ptr, LDIF);
 #if IX_FSL != IX_DNL
-       bv = *res;
-       while ( ptr = ber_bvchr( &bv, IX_DNL ) ) {
-               *ptr++ = IX_FSL;
-               assert( ( ptr - bv.bv_val ) <= bv.bv_len );
-               bv.bv_len -= ( ptr - bv.bv_val );
-               bv.bv_val = ptr;
-               ptr = ber_bvchr( &bv, IX_DNR );
-               if ( !ptr )
-                       break;
-               *ptr++ = IX_FSR;
-               assert( ( ptr - bv.bv_val ) <= bv.bv_len );
-               bv.bv_len -= ( ptr - bv.bv_val );
-               bv.bv_val = ptr;
+       {
+               struct berval bv;
+               bv = *res;
+               while ( ptr = ber_bvchr( &bv, IX_DNL ) ) {
+                       *ptr++ = IX_FSL;
+                       assert( ( ptr - bv.bv_val ) <= bv.bv_len );
+                       bv.bv_len -= ( ptr - bv.bv_val );
+                       bv.bv_val = ptr;
+                       ptr = ber_bvchr( &bv, IX_DNR );
+                       if ( !ptr )
+                               break;
+                       *ptr++ = IX_FSR;
+                       assert( ( ptr - bv.bv_val ) <= bv.bv_len );
+                       bv.bv_len -= ( ptr - bv.bv_val );
+                       bv.bv_val = ptr;
+               }
        }
 #endif
 }
@@ -156,14 +158,16 @@ static char * slurp_file(int fd) {
        return entry;
 }
 
+/*
+ * return number of bytes written, or -1 in case of error
+ * do not return numbers less than -1
+ */
 static int spew_file(int fd, char * spew, int len) {
        int writeres = 0;
        
        while(len > 0) {
                writeres = write(fd, spew, len);
                if(writeres == -1) {
-                       Debug( LDAP_DEBUG_ANY, "could not spew write: %s\n",
-                               STRERROR( errno ), 0, 0 );
                        return -1;
                }
                else {
@@ -174,23 +178,28 @@ static int spew_file(int fd, char * spew, int len) {
        return writeres;
 }
 
-static int spew_entry(Entry * e, struct berval * path) {
-       int rs;
+static int
+spew_entry( Entry * e, struct berval * path, int dolock, int *save_errnop )
+{
+       int rs, save_errno = 0;
        int openres;
-       int spew_res;
+       int res, spew_res;
        int entry_length;
        char * entry_as_string;
+       char *tmpfname = NULL;
 
-       openres = open(path->bv_val, O_WRONLY|O_CREAT|O_TRUNC, S_IREAD | S_IWRITE);
-       if(openres == -1) {
-               if(errno == ENOENT)
-                       rs = LDAP_NO_SUCH_OBJECT;
-               else
-                       rs = LDAP_UNWILLING_TO_PERFORM;
-               Debug( LDAP_DEBUG_ANY, "could not open \"%s\": %s\n",
-                       path->bv_val, STRERROR( errno ), 0 );
-       }
-       else {
+       tmpfname = ch_malloc( path->bv_len + STRLENOF( "XXXXXX" ) + 1 );
+       AC_MEMCPY( tmpfname, path->bv_val, path->bv_len );
+       AC_MEMCPY( &tmpfname[ path->bv_len ], "XXXXXX", STRLENOF( "XXXXXX" ) + 1 );
+
+       openres = mkstemp( tmpfname );
+       if ( openres == -1 ) {
+               save_errno = errno;
+               rs = LDAP_UNWILLING_TO_PERFORM;
+               Debug( LDAP_DEBUG_ANY, "could not create tmpfile \"%s\": %s\n",
+                       tmpfname, STRERROR( save_errno ), 0 );
+
+       } else {
                struct berval rdn;
                int tmp;
 
@@ -203,7 +212,23 @@ static int spew_entry(Entry * e, struct berval * path) {
                        rdn.bv_len = tmp;
                }
 
+               spew_res = -2;
+               if ( dolock ) {
+                       ldap_pvt_thread_mutex_lock(&entry2str_mutex);
+               }
+
                entry_as_string = entry2str(e, &entry_length);
+               if ( entry_as_string != NULL ) {
+                       spew_res = spew_file( openres,
+                               entry_as_string, entry_length );
+                       if ( spew_res == -1 ) {
+                               save_errno = errno;
+                       }
+               }
+
+               if ( dolock ) {
+                       ldap_pvt_thread_mutex_unlock(&entry2str_mutex);
+               }
 
                /* Restore full DN */
                if ( rdn.bv_len != e->e_name.bv_len ) {
@@ -211,19 +236,47 @@ static int spew_entry(Entry * e, struct berval * path) {
                        e->e_name.bv_len = rdn.bv_len;
                }
 
-               if(entry_as_string == NULL) {
-                       rs = LDAP_UNWILLING_TO_PERFORM;
-                       close(openres);
+               res = close( openres );
+               rs = LDAP_UNWILLING_TO_PERFORM;
+
+               if ( spew_res > -2 ) {
+                       if ( res == -1 || spew_res == -1 ) {
+                               if ( save_errno == 0 ) {
+                                       save_errno = errno;
+                               }
+                               Debug( LDAP_DEBUG_ANY, "write error to tmpfile \"%s\": %s\n",
+                                       tmpfname, STRERROR( save_errno ), 0 );
+
+                       } else {
+                               res = rename( tmpfname, path->bv_val );
+                               if ( res == 0 ) {
+                                       rs = LDAP_SUCCESS;
+
+                               } else {
+                                       save_errno = errno;
+                                       switch ( save_errno ) {
+                                       case ENOENT:
+                                               rs = LDAP_NO_SUCH_OBJECT;
+                                               break;
+
+                                       default:
+                                               break;
+                                       }
+                               }
+                       }
                }
-               else {
-                       spew_res = spew_file(openres, entry_as_string, entry_length);
-                       close(openres);
-                       if(spew_res == -1)
-                               rs = LDAP_UNWILLING_TO_PERFORM;
-                       else
-                               rs = LDAP_SUCCESS;
+
+               if ( rs != LDAP_SUCCESS ) {
+                       unlink( tmpfname );
                }
        }
+
+       ch_free( tmpfname );
+
+       if ( rs != LDAP_SUCCESS && save_errnop != NULL ) {
+               *save_errnop = save_errno;
+       }
+
        return rs;
 }
 
@@ -299,7 +352,7 @@ typedef struct bvlist {
        struct bvlist *next;
        struct berval bv;
        struct berval num;
-       unsigned int inum;
+       int inum;
        int off;
 } bvlist;
 
@@ -481,14 +534,14 @@ enum_tree(
        enumCookie *ck
 )
 {
-       struct ldif_info *ni = (struct ldif_info *) ck->op->o_bd->be_private;
+       struct ldif_info *li = (struct ldif_info *) ck->op->o_bd->be_private;
        struct berval path;
        struct berval pdn, pndn;
        int rc;
 
        dnParent( &ck->op->o_req_dn, &pdn );
        dnParent( &ck->op->o_req_ndn, &pndn );
-       dn2path( &ck->op->o_req_ndn, &ck->op->o_bd->be_nsuffix[0], &ni->li_base_path, &path);
+       dn2path( &ck->op->o_req_ndn, &ck->op->o_bd->be_nsuffix[0], &li->li_base_path, &path);
        rc = r_enum_tree(ck, &path, &pdn, &pndn);
        ch_free( path.bv_val );
        return rc;
@@ -592,7 +645,7 @@ static int apply_modify_to_entry(Entry * entry,
 int
 ldif_back_referrals( Operation *op, SlapReply *rs )
 {
-       struct ldif_info        *ni = NULL;
+       struct ldif_info        *li = NULL;
        Entry                   *entry;
        int                     rc = LDAP_SUCCESS;
 
@@ -608,9 +661,9 @@ ldif_back_referrals( Operation *op, SlapReply *rs )
                return rc;
        }
 
-       ni = (struct ldif_info *)op->o_bd->be_private;
-       ldap_pvt_thread_rdwr_rlock( &ni->li_rdwr );
-       entry = (Entry *)get_entry( op, &ni->li_base_path );
+       li = (struct ldif_info *)op->o_bd->be_private;
+       ldap_pvt_thread_rdwr_rlock( &li->li_rdwr );
+       entry = get_entry( op, &li->li_base_path );
 
        /* no object is found for them */
        if ( entry == NULL ) {
@@ -629,10 +682,10 @@ ldif_back_referrals( Operation *op, SlapReply *rs )
                        op->o_req_dn = pndn;
                        op->o_req_ndn = pndn;
 
-                       entry = (Entry *)get_entry( op, &ni->li_base_path );
+                       entry = get_entry( op, &li->li_base_path );
                }
 
-               ldap_pvt_thread_rdwr_runlock( &ni->li_rdwr );
+               ldap_pvt_thread_rdwr_runlock( &li->li_rdwr );
 
                op->o_req_dn = odn;
                op->o_req_ndn = ondn;
@@ -641,8 +694,8 @@ ldif_back_referrals( Operation *op, SlapReply *rs )
                rs->sr_matched = NULL;
                if ( entry != NULL ) {
                        Debug( LDAP_DEBUG_TRACE,
-                               "ldif_back_referrals: op=%ld target=\"%s\" matched=\"%s\"\n",
-                               (long) op->o_tag, op->o_req_dn.bv_val, entry->e_name.bv_val );
+                               "ldif_back_referrals: tag=%lu target=\"%s\" matched=\"%s\"\n",
+                               (unsigned long) op->o_tag, op->o_req_dn.bv_val, entry->e_name.bv_val );
 
                        if ( is_entry_referral( entry ) ) {
                                rc = LDAP_OTHER;
@@ -682,7 +735,7 @@ ldif_back_referrals( Operation *op, SlapReply *rs )
                return rc;
        }
 
-       ldap_pvt_thread_rdwr_runlock( &ni->li_rdwr );
+       ldap_pvt_thread_rdwr_runlock( &li->li_rdwr );
 
        if ( is_entry_referral( entry ) ) {
                /* entry is a referral */
@@ -691,8 +744,8 @@ ldif_back_referrals( Operation *op, SlapReply *rs )
                        refs, &entry->e_name, &op->o_req_dn, LDAP_SCOPE_DEFAULT );
 
                Debug( LDAP_DEBUG_TRACE,
-                       "ldif_back_referrals: op=%ld target=\"%s\" matched=\"%s\"\n",
-                       (long) op->o_tag, op->o_req_dn.bv_val, entry->e_name.bv_val );
+                       "ldif_back_referrals: tag=%lu target=\"%s\" matched=\"%s\"\n",
+                       (unsigned long) op->o_tag, op->o_req_dn.bv_val, entry->e_name.bv_val );
 
                rs->sr_matched = entry->e_name.bv_val;
                if ( rs->sr_ref != NULL ) {
@@ -718,23 +771,29 @@ ldif_back_referrals( Operation *op, SlapReply *rs )
 static int
 ldif_back_bind( Operation *op, SlapReply *rs )
 {
-       struct ldif_info *ni = NULL;
+       struct ldif_info *li = NULL;
        Attribute * a = NULL;
        AttributeDescription *password = slap_schema.si_ad_userPassword;
        int return_val = 0;
        Entry * entry = NULL;
 
-       ni = (struct ldif_info *) op->o_bd->be_private;
-       ldap_pvt_thread_rdwr_rlock(&ni->li_rdwr);
-       entry = (Entry *) get_entry(op, &ni->li_base_path);
+       switch ( be_rootdn_bind( op, rs ) ) {
+       case SLAP_CB_CONTINUE:
+               break;
+
+       default:
+               /* in case of success, front end will send result;
+                * otherwise, be_rootdn_bind() did */
+               return rs->sr_err;
+       }
+
+       li = (struct ldif_info *) op->o_bd->be_private;
+       ldap_pvt_thread_rdwr_rlock(&li->li_rdwr);
+       entry = get_entry(op, &li->li_base_path);
 
        /* no object is found for them */
        if(entry == NULL) {
-               if(be_isroot_pw(op)) {
-                       rs->sr_err = return_val = LDAP_SUCCESS;
-               } else {
-                       rs->sr_err = return_val = LDAP_INVALID_CREDENTIALS;
-               }
+               rs->sr_err = return_val = LDAP_INVALID_CREDENTIALS;
                goto return_result;
        }
 
@@ -758,7 +817,7 @@ ldif_back_bind( Operation *op, SlapReply *rs )
        goto return_result;
 
  return_result:
-       ldap_pvt_thread_rdwr_runlock(&ni->li_rdwr);
+       ldap_pvt_thread_rdwr_runlock(&li->li_rdwr);
        if(return_val != 0)
                send_ldap_result( op, rs );
        if(entry != NULL)
@@ -768,21 +827,21 @@ ldif_back_bind( Operation *op, SlapReply *rs )
 
 static int ldif_back_search(Operation *op, SlapReply *rs)
 {
-       struct ldif_info *ni = (struct ldif_info *) op->o_bd->be_private;
+       struct ldif_info *li = (struct ldif_info *) op->o_bd->be_private;
        enumCookie ck = { NULL, NULL, NULL, 0, 0 };
 
        ck.op = op;
        ck.rs = rs;
-       ldap_pvt_thread_rdwr_rlock(&ni->li_rdwr);
+       ldap_pvt_thread_rdwr_rlock(&li->li_rdwr);
        rs->sr_err = enum_tree( &ck );
-       ldap_pvt_thread_rdwr_runlock(&ni->li_rdwr);
+       ldap_pvt_thread_rdwr_runlock(&li->li_rdwr);
        send_ldap_result(op, rs);
 
        return rs->sr_err;
 }
 
 static int ldif_back_add(Operation *op, SlapReply *rs) {
-       struct ldif_info *ni = (struct ldif_info *) op->o_bd->be_private;
+       struct ldif_info *li = (struct ldif_info *) op->o_bd->be_private;
        Entry * e = op->ora_e;
        struct berval dn = e->e_nname;
        struct berval leaf_path = BER_BVNULL;
@@ -800,9 +859,9 @@ static int ldif_back_add(Operation *op, SlapReply *rs) {
                &rs->sr_text, textbuf, sizeof( textbuf ), 1 );
        if ( rs->sr_err != LDAP_SUCCESS ) goto send_res;
 
-       ldap_pvt_thread_rdwr_wlock(&ni->li_rdwr);
+       ldap_pvt_thread_rdwr_wlock(&li->li_rdwr);
 
-       dn2path(&dn, &op->o_bd->be_nsuffix[0], &ni->li_base_path, &leaf_path);
+       dn2path(&dn, &op->o_bd->be_nsuffix[0], &li->li_base_path, &leaf_path);
 
        if(leaf_path.bv_val != NULL) {
                struct berval base = BER_BVNULL;
@@ -833,9 +892,7 @@ static int ldif_back_add(Operation *op, SlapReply *rs) {
                if(rs->sr_err == LDAP_SUCCESS) {
                        statres = stat(leaf_path.bv_val, &stats);
                        if(statres == -1 && errno == ENOENT) {
-                               ldap_pvt_thread_mutex_lock(&entry2str_mutex);
-                               rs->sr_err = (int) spew_entry(e, &leaf_path);
-                               ldap_pvt_thread_mutex_unlock(&entry2str_mutex);
+                               rs->sr_err = spew_entry(e, &leaf_path, 1, NULL);
                        }
                        else if ( statres == -1 ) {
                                rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
@@ -849,7 +906,7 @@ static int ldif_back_add(Operation *op, SlapReply *rs) {
                SLAP_FREE(leaf_path.bv_val);
        }
 
-       ldap_pvt_thread_rdwr_wunlock(&ni->li_rdwr);
+       ldap_pvt_thread_rdwr_wunlock(&li->li_rdwr);
 
 send_res:
        Debug( LDAP_DEBUG_TRACE, 
@@ -857,11 +914,11 @@ send_res:
                                rs->sr_text : "", 0);
        send_ldap_result(op, rs);
        slap_graduate_commit_csn( op );
-       return 0;
+       return rs->sr_err;
 }
 
 static int ldif_back_modify(Operation *op, SlapReply *rs) {
-       struct ldif_info *ni = (struct ldif_info *) op->o_bd->be_private;
+       struct ldif_info *li = (struct ldif_info *) op->o_bd->be_private;
        Modifications * modlst = op->orm_modlist;
        struct berval path = BER_BVNULL;
        Entry * entry = NULL;
@@ -869,19 +926,16 @@ static int ldif_back_modify(Operation *op, SlapReply *rs) {
 
        slap_mods_opattrs( op, &op->orm_modlist, 1 );
 
-       ldap_pvt_thread_rdwr_wlock(&ni->li_rdwr);
-       dn2path(&op->o_req_ndn, &op->o_bd->be_nsuffix[0], &ni->li_base_path,
+       ldap_pvt_thread_rdwr_wlock(&li->li_rdwr);
+       dn2path(&op->o_req_ndn, &op->o_bd->be_nsuffix[0], &li->li_base_path,
                &path);
-       entry = (Entry *) get_entry(op, &ni->li_base_path);
+       entry = get_entry(op, &li->li_base_path);
 
        if(entry != NULL) {
                rs->sr_err = apply_modify_to_entry(entry, modlst, op, rs);
                if(rs->sr_err == LDAP_SUCCESS) {
                        int save_errno;
-                       ldap_pvt_thread_mutex_lock(&entry2str_mutex);
-                       spew_res = spew_entry(entry, &path);
-                       save_errno = errno;
-                       ldap_pvt_thread_mutex_unlock(&entry2str_mutex);
+                       spew_res = spew_entry(entry, &path, 1, &save_errno);
                        if(spew_res == -1) {
                                Debug( LDAP_DEBUG_ANY,
                                        "%s ldif_back_modify: could not output entry \"%s\": %s\n",
@@ -899,14 +953,14 @@ 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_rdwr_wunlock(&ni->li_rdwr);
+       ldap_pvt_thread_rdwr_wunlock(&li->li_rdwr);
        send_ldap_result(op, rs);
        slap_graduate_commit_csn( op );
-       return 0;
+       return rs->sr_err;
 }
 
 static int ldif_back_delete(Operation *op, SlapReply *rs) {
-       struct ldif_info *ni = (struct ldif_info *) op->o_bd->be_private;
+       struct ldif_info *li = (struct ldif_info *) op->o_bd->be_private;
        struct berval path = BER_BVNULL;
        int res = 0;
 
@@ -919,32 +973,48 @@ static int ldif_back_delete(Operation *op, SlapReply *rs) {
                slap_get_csn( op, &csn, 1 );
        }
 
-       ldap_pvt_thread_rdwr_wlock(&ni->li_rdwr);
-       dn2path(&op->o_req_ndn, &op->o_bd->be_nsuffix[0], &ni->li_base_path, &path);
+       ldap_pvt_thread_rdwr_wlock(&li->li_rdwr);
+       dn2path(&op->o_req_ndn, &op->o_bd->be_nsuffix[0], &li->li_base_path, &path);
 
        path.bv_val[path.bv_len - STRLENOF(LDIF)] = '\0';
        res = rmdir(path.bv_val);
        path.bv_val[path.bv_len - STRLENOF(LDIF)] = '.';
-       if ( res && errno != ENOENT ) {
-               rs->sr_err = LDAP_NOT_ALLOWED_ON_NONLEAF;
-       } else {
-               res = unlink(path.bv_val);
-       }
+       rs->sr_err = LDAP_SUCCESS;
+       if ( res ) {
+               switch ( errno ) {
+               case ENOTEMPTY:
+                       rs->sr_err = LDAP_NOT_ALLOWED_ON_NONLEAF;
+                       break;
 
-       if(res == -1) {
-               if(errno == ENOENT)
+               case ENOENT:
                        rs->sr_err = LDAP_NO_SUCH_OBJECT;
-               else
+                       break;
+
+               default:
                        rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
+                       break;
+               }
+
+       } else {
+               res = unlink(path.bv_val);
+               if ( res == -1 ) {
+                       switch ( errno ) {
+                       case ENOENT:
+                               rs->sr_err = LDAP_NO_SUCH_OBJECT;
+                               break;
+
+                       default:
+                               rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
+                               break;
+                       }
+               }
        }
-       else
-               rs->sr_err = LDAP_SUCCESS;
 
        SLAP_FREE(path.bv_val);
-       ldap_pvt_thread_rdwr_wunlock(&ni->li_rdwr);
+       ldap_pvt_thread_rdwr_wunlock(&li->li_rdwr);
        send_ldap_result(op, rs);
        slap_graduate_commit_csn( op );
-       return 0;
+       return rs->sr_err;
 }
 
 
@@ -967,7 +1037,7 @@ static int move_entry(Entry * entry, struct berval * ndn,
                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);
+                       res = spew_entry(entry, &newpath, 0, NULL);
                        if(res != -1) {
                                /* if this fails we should log something bad */
                                res = unlink(path.bv_val);
@@ -1007,7 +1077,7 @@ static int move_entry(Entry * entry, struct berval * ndn,
 static int
 ldif_back_modrdn(Operation *op, SlapReply *rs)
 {
-       struct ldif_info *ni = (struct ldif_info *) op->o_bd->be_private;
+       struct ldif_info *li = (struct ldif_info *) op->o_bd->be_private;
        struct berval new_dn = BER_BVNULL, new_ndn = BER_BVNULL;
        struct berval p_dn;
        Entry * entry = NULL;
@@ -1015,8 +1085,8 @@ ldif_back_modrdn(Operation *op, SlapReply *rs)
 
        slap_mods_opattrs( op, &op->orr_modlist, 1 );
 
-       ldap_pvt_thread_rdwr_wlock( &ni->li_rdwr );
-       entry = (Entry *) get_entry( op, &ni->li_base_path );
+       ldap_pvt_thread_rdwr_wlock( &li->li_rdwr );
+       entry = get_entry( op, &li->li_base_path );
 
        /* build the mods to the entry */
        if ( entry != NULL ) {
@@ -1030,7 +1100,7 @@ ldif_back_modrdn(Operation *op, SlapReply *rs)
                        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 );
+                       np = get_entry( op, &li->li_base_path );
                        op->o_req_dn = op_dn;
                        op->o_req_ndn = op_ndn;
                        if ( np == NULL ) {
@@ -1053,7 +1123,7 @@ ldif_back_modrdn(Operation *op, SlapReply *rs)
                        rs->sr_err = move_entry( entry, &op->o_req_ndn,
                                                &new_ndn,
                                                &op->o_bd->be_nsuffix[0],
-                                               &ni->li_base_path );
+                                               &li->li_base_path );
                } else {
                        rs->sr_err = res;
                }
@@ -1067,10 +1137,10 @@ no_such_object:;
                entry_free( entry );
        }
        rs->sr_text = "";
-       ldap_pvt_thread_rdwr_wunlock( &ni->li_rdwr );
+       ldap_pvt_thread_rdwr_wunlock( &li->li_rdwr );
        send_ldap_result( op, rs );
        slap_graduate_commit_csn( op );
-       return 0;
+       return rs->sr_err;
 }
 
 /* return LDAP_SUCCESS IFF we can retrieve the specified entry.
@@ -1083,19 +1153,19 @@ int ldif_back_entry_get(
        int rw,
        Entry **ent )
 {
-       struct ldif_info *ni = (struct ldif_info *) op->o_bd->be_private;
+       struct ldif_info *li = (struct ldif_info *) op->o_bd->be_private;
        struct berval op_dn = op->o_req_dn, op_ndn = op->o_req_ndn;
 
        assert( ndn != NULL );
        assert( !BER_BVISNULL( ndn ) );
 
-       ldap_pvt_thread_rdwr_rlock( &ni->li_rdwr );
+       ldap_pvt_thread_rdwr_rlock( &li->li_rdwr );
        op->o_req_dn = *ndn;
        op->o_req_ndn = *ndn;
-       *ent = (Entry *) get_entry( op, &ni->li_base_path );
+       *ent = get_entry( op, &li->li_base_path );
        op->o_req_dn = op_dn;
        op->o_req_ndn = op_ndn;
-       ldap_pvt_thread_rdwr_runlock( &ni->li_rdwr );
+       ldap_pvt_thread_rdwr_runlock( &li->li_rdwr );
 
        if ( *ent && oc && !is_entry_objectclass_or_sub( *ent, oc ) ) {
                entry_free( *ent );
@@ -1105,72 +1175,69 @@ int ldif_back_entry_get(
        return ( *ent == NULL ? 1 : 0 );
 }
 
-static int ldif_tool_entry_open(BackendDB * be, int mode) {
-       struct ldif_info *ni = (struct ldif_info *) be->be_private;
-       ni->li_tool_current = 0;
+static int ldif_tool_entry_open(BackendDB *be, int mode) {
+       struct ldif_info *li = (struct ldif_info *) be->be_private;
+       li->li_tool_current = 0;
        return 0;
 }                                      
 
 static int ldif_tool_entry_close(BackendDB * be) {
-       struct ldif_info *ni = (struct ldif_info *) be->be_private;
+       struct ldif_info *li = (struct ldif_info *) be->be_private;
 
-       SLAP_FREE(ni->li_tool_cookie.entries);
+       SLAP_FREE(li->li_tool_cookie.entries);
        return 0;
 }
 
+static ID ldif_tool_entry_next(BackendDB *be)
+{
+       struct ldif_info *li = (struct ldif_info *) be->be_private;
+       if(li->li_tool_current >= li->li_tool_cookie.eind)
+               return NOID;
+       else
+               return ++li->li_tool_current;
+}
+
 static ID
 ldif_tool_entry_first(BackendDB *be)
 {
-       struct ldif_info *ni = (struct ldif_info *) be->be_private;
-       ID id = 1; /* first entry in the array of entries shifted by one */
+       struct ldif_info *li = (struct ldif_info *) be->be_private;
 
-       ni->li_tool_current = 1;
-       if(ni->li_tool_cookie.entries == NULL) {
+       if(li->li_tool_cookie.entries == NULL) {
                Operation op = {0};
 
                op.o_bd = be;
                op.o_req_dn = *be->be_suffix;
                op.o_req_ndn = *be->be_nsuffix;
                op.ors_scope = LDAP_SCOPE_SUBTREE;
-               ni->li_tool_cookie.op = &op;
-               (void)enum_tree( &ni->li_tool_cookie );
-               ni->li_tool_cookie.op = NULL;
+               li->li_tool_cookie.op = &op;
+               (void)enum_tree( &li->li_tool_cookie );
+               li->li_tool_cookie.op = NULL;
        }
-       return id;
-}
-
-static ID ldif_tool_entry_next(BackendDB *be)
-{
-       struct ldif_info *ni = (struct ldif_info *) be->be_private;
-       ni->li_tool_current += 1;
-       if(ni->li_tool_current > ni->li_tool_cookie.eind)
-               return NOID;
-       else
-               return ni->li_tool_current;
+       return ldif_tool_entry_next( be );
 }
 
 static Entry * ldif_tool_entry_get(BackendDB * be, ID id) {
-       struct ldif_info *ni = (struct ldif_info *) be->be_private;
+       struct ldif_info *li = (struct ldif_info *) be->be_private;
        Entry * e;
 
-       if(id > ni->li_tool_cookie.eind || id < 1)
+       if(id > li->li_tool_cookie.eind || id < 1)
                return NULL;
        else {
-               e = ni->li_tool_cookie.entries[id - 1];
-               ni->li_tool_cookie.entries[id - 1] = NULL;
+               e = li->li_tool_cookie.entries[id - 1];
+               li->li_tool_cookie.entries[id - 1] = NULL;
                return e;
        }
 }
 
 static ID ldif_tool_entry_put(BackendDB * be, Entry * e, struct berval *text) {
-       struct ldif_info *ni = (struct ldif_info *) be->be_private;
+       struct ldif_info *li = (struct ldif_info *) be->be_private;
        struct berval dn = e->e_nname;
        struct berval leaf_path = BER_BVNULL;
        struct stat stats;
        int statres;
        int res = LDAP_SUCCESS;
 
-       dn2path(&dn, &be->be_nsuffix[0], &ni->li_base_path, &leaf_path);
+       dn2path(&dn, &be->be_nsuffix[0], &li->li_base_path, &leaf_path);
 
        if(leaf_path.bv_val != NULL) {
                struct berval base = BER_BVNULL;
@@ -1197,7 +1264,7 @@ static ID ldif_tool_entry_put(BackendDB * be, Entry * e, struct berval *text) {
                if(res == LDAP_SUCCESS) {
                        statres = stat(leaf_path.bv_val, &stats);
                        if(statres == -1 && errno == ENOENT) {
-                               res = (int) spew_entry(e, &leaf_path);
+                               res = spew_entry(e, &leaf_path, 0, NULL);
                        }
                        else /* it already exists */
                                res = LDAP_ALREADY_EXISTS;
@@ -1214,37 +1281,33 @@ static ID ldif_tool_entry_put(BackendDB * be, Entry * e, struct berval *text) {
 }
 
 static int
-ldif_back_db_init( BackendDB *be )
+ldif_back_db_init( BackendDB *be, ConfigReply *cr )
 {
-       struct ldif_info *ni;
+       struct ldif_info *li;
 
-       ni = ch_calloc( 1, sizeof(struct ldif_info) );
-       be->be_private = ni;
+       li = ch_calloc( 1, sizeof(struct ldif_info) );
+       be->be_private = li;
        be->be_cf_ocs = ldifocs;
-       ldap_pvt_thread_rdwr_init(&ni->li_rdwr);
+       ldap_pvt_thread_rdwr_init(&li->li_rdwr);
        return 0;
 }
 
 static int
-ldif_back_db_destroy(
-                          Backend      *be
-                          )
+ldif_back_db_destroy( Backend *be, ConfigReply *cr )
 {
-       struct ldif_info *ni = be->be_private;
+       struct ldif_info *li = be->be_private;
 
-       ch_free(ni->li_base_path.bv_val);
-       ldap_pvt_thread_rdwr_destroy(&ni->li_rdwr);
+       ch_free(li->li_base_path.bv_val);
+       ldap_pvt_thread_rdwr_destroy(&li->li_rdwr);
        free( be->be_private );
        return 0;
 }
 
 static int
-ldif_back_db_open(
-                       Backend *be
-                       )
+ldif_back_db_open( Backend *be, ConfigReply *cr)
 {
-       struct ldif_info *ni = (struct ldif_info *) be->be_private;
-       if( BER_BVISEMPTY(&ni->li_base_path)) {/* missing base path */
+       struct ldif_info *li = (struct ldif_info *) be->be_private;
+       if( BER_BVISEMPTY(&li->li_base_path)) {/* missing base path */
                Debug( LDAP_DEBUG_ANY, "missing base path for back-ldif\n", 0, 0, 0);
                return 1;
        }
@@ -1312,7 +1375,6 @@ ldif_back_initialize(
        bi->bi_tool_sync = 0;
        
        bi->bi_tool_dn2id_get = 0;
-       bi->bi_tool_id2entry_get = 0;
        bi->bi_tool_entry_modify = 0;
 
        bi->bi_cf_ocs = ldifocs;
index ddd651f7a9d6a63b0a3b2ea29a721a0e98f0435f..cfa3e73f5a8367d2bc3a2c12e03ed23bbbea2d52 100644 (file)
@@ -169,8 +169,7 @@ meta_back_add( Operation *op, SlapReply *rs )
 
 retry:;
        ctrls = op->o_ctrls;
-       if ( ldap_back_proxy_authz_ctrl( &mc->mc_conns[ candidate ].msc_bound_ndn,
-               mt->mt_version, &mt->mt_idassert, op, rs, &ctrls ) != LDAP_SUCCESS )
+       if ( meta_back_controls_add( op, rs, mc, candidate, &ctrls ) != LDAP_SUCCESS )
        {
                send_ldap_result( op, rs );
                goto cleanup;
@@ -184,13 +183,13 @@ retry:;
                do_retry = 0;
                if ( meta_back_retry( op, rs, &mc, candidate, LDAP_BACK_SENDERR ) ) {
                        /* if the identity changed, there might be need to re-authz */
-                       (void)ldap_back_proxy_authz_ctrl_free( op, &ctrls );
+                       (void)ldap_back_controls_free( op, rs, &ctrls );
                        goto retry;
                }
        }
 
 cleanup:;
-       (void)ldap_back_proxy_authz_ctrl_free( op, &ctrls );
+       (void)ldap_back_controls_free( op, rs, &ctrls );
 
        for ( --i; i >= 0; --i ) {
                free( attrs[ i ]->mod_bvalues );
index 04d7ba885cb685a64885fb10bc01194e812c64dd..2f7b080e8ba0f31562f704f9d9ebf18cd124f7f3 100644 (file)
@@ -31,6 +31,7 @@
 
 /* String rewrite library */
 #include "rewrite.h"
+
 LDAP_BEGIN_DECL
 
 /*
@@ -40,9 +41,6 @@ LDAP_BEGIN_DECL
 #define META_BACK_PRINT_CONNTREE 0
 #endif /* !META_BACK_PRINT_CONNTREE */
 
-struct slap_conn;
-struct slap_op;
-
 /* from back-ldap.h before rwm removal */
 struct ldapmap {
        int drop_missing;
@@ -223,7 +221,7 @@ typedef struct metasingleconn_t {
 } metasingleconn_t;
 
 typedef struct metaconn_t {
-       struct slap_conn        *mc_conn;
+       Connection              *mc_conn;
 #define        lc_conn                 mc_conn
        unsigned                mc_refcnt;
 
@@ -312,6 +310,11 @@ typedef struct metatarget_t {
 #define        META_BACK_TGT_CANCEL_DISCOVER(mt)       META_BACK_TGT_ISMASK( (mt), LDAP_BACK_F_CANCEL_MASK2, LDAP_BACK_F_CANCEL_EXOP_DISCOVER )
 #define        META_BACK_TGT_QUARANTINE(mt)            META_BACK_TGT_ISSET( (mt), LDAP_BACK_F_QUARANTINE )
 
+#ifdef SLAP_CONTROL_X_SESSION_TRACKING
+#define        META_BACK_TGT_ST_REQUEST(mt)            META_BACK_TGT_ISSET( (mt), LDAP_BACK_F_ST_REQUEST )
+#define        META_BACK_TGT_ST_RESPONSE(mt)           META_BACK_TGT_ISSET( (mt), LDAP_BACK_F_ST_RESPONSE )
+#endif /* SLAP_CONTROL_X_SESSION_TRACKING */
+
        int                     mt_version;
        time_t                  mt_network_timeout;
        struct timeval          mt_bind_timeout;
index f0297d4a1b6c07db2b275c7d262d1290cf8e751a..bae5a477829799959517cfca5f2ea6072803a2b7 100644 (file)
@@ -64,7 +64,7 @@ meta_back_bind( Operation *op, SlapReply *rs )
                        gotit = 0,
                        isroot = 0;
 
-       SlapReply       *candidates = meta_back_candidates_get( op );
+       SlapReply       *candidates;
 
        rs->sr_err = LDAP_SUCCESS;
 
@@ -72,24 +72,22 @@ meta_back_bind( Operation *op, SlapReply *rs )
                op->o_log_prefix, op->o_req_dn.bv_val, 0 );
 
        /* the test on the bind method should be superfluous */
-       if ( op->orb_method == LDAP_AUTH_SIMPLE
-               && be_isroot_dn( op->o_bd, &op->o_req_ndn ) )
-       {
-               if ( !be_isroot_pw( op ) ) {
-                       rs->sr_err = LDAP_INVALID_CREDENTIALS;
-                       rs->sr_text = NULL;
-                       send_ldap_result( op, rs );
-                       return rs->sr_err;
-               }
-
+       switch ( be_rootdn_bind( op, rs ) ) {
+       case LDAP_SUCCESS:
                if ( META_BACK_DEFER_ROOTDN_BIND( mi ) ) {
-                       rs->sr_err = LDAP_SUCCESS;
-                       rs->sr_text = NULL;
                        /* frontend will return success */
                        return rs->sr_err;
                }
 
                isroot = 1;
+               /* fallthru */
+
+       case SLAP_CB_CONTINUE:
+               break;
+
+       default:
+               /* be_rootdn_bind() sent result */
+               return rs->sr_err;
        }
 
        /* we need meta_back_getconn() not send result even on error,
@@ -124,6 +122,8 @@ meta_back_bind( Operation *op, SlapReply *rs )
                return rs->sr_err;
        }
 
+       candidates = meta_back_candidates_get( op );
+
        /*
         * Each target is scanned ...
         */
@@ -326,6 +326,9 @@ meta_back_bind_op_result(
                ">>> %s meta_back_bind_op_result[%d]\n",
                op->o_log_prefix, candidate, 0 );
 
+       /* make sure this is clean */
+       assert( rs->sr_ctrls == NULL );
+
        if ( rs->sr_err == LDAP_SUCCESS ) {
                time_t          stoptime = (time_t)(-1),
                                timeout;
@@ -457,6 +460,9 @@ meta_back_single_bind(
        metasingleconn_t        *msc = &mc->mc_conns[ candidate ];
        int                     msgid;
        dncookie                dc;
+       struct berval           save_o_dn;
+       int                     save_o_do_not_cache;
+       LDAPControl             **ctrls = NULL;
        
        if ( !BER_BVISNULL( &msc->msc_bound_ndn ) ) {
                ch_free( msc->msc_bound_ndn.bv_val );
@@ -484,6 +490,20 @@ meta_back_single_bind(
                return rs->sr_err;
        }
 
+       /* don't add proxyAuthz; set the bindDN */
+       save_o_dn = op->o_dn;
+       save_o_do_not_cache = op->o_do_not_cache;
+       op->o_do_not_cache = 1;
+       op->o_dn = op->o_req_dn;
+
+       ctrls = op->o_ctrls;
+       rs->sr_err = meta_back_controls_add( op, rs, mc, candidate, &ctrls );
+       op->o_dn = save_o_dn;
+       op->o_do_not_cache = save_o_do_not_cache;
+       if ( rs->sr_err != LDAP_SUCCESS ) {
+               goto return_results;
+       }
+
        /* FIXME: this fixes the bind problem right now; we need
         * to use the asynchronous version to get the "matched"
         * and more in case of failure ... */
@@ -492,12 +512,15 @@ meta_back_single_bind(
        for (;;) {
                rs->sr_err = ldap_sasl_bind( msc->msc_ld, mdn.bv_val,
                        LDAP_SASL_SIMPLE, &op->orb_cred,
-                       op->o_ctrls, NULL, &msgid );
+                       ctrls, NULL, &msgid );
                if ( rs->sr_err != LDAP_X_CONNECTING ) {
                        break;
                }
                ldap_pvt_thread_yield();
        }
+
+       ldap_back_controls_free( op, rs, &ctrls );
+
        meta_back_bind_op_result( op, rs, mc, candidate, msgid, LDAP_BACK_DONTSEND );
        if ( rs->sr_err != LDAP_SUCCESS ) {
                goto return_results;
@@ -636,7 +659,7 @@ meta_back_dobind(
                                i,
                                isroot = 0;
 
-       SlapReply               *candidates = meta_back_candidates_get( op );
+       SlapReply               *candidates;
 
        if ( be_isroot( op ) ) {
                isroot = 1;
@@ -656,6 +679,8 @@ meta_back_dobind(
                goto done;
        }
 
+       candidates = meta_back_candidates_get( op );
+
        for ( i = 0; i < mi->mi_ntargets; i++ ) {
                metatarget_t            *mt = mi->mi_targets[ i ];
                metasingleconn_t        *msc = &mc->mc_conns[ i ];
@@ -1018,18 +1043,44 @@ retry:;
                                if ( rc != LDAP_SUCCESS ) {
                                        rs->sr_err = rc;
                                }
-                               if ( refs != NULL ) {
-                                       int     i;
+
+                               /* RFC 4511: referrals can only appear
+                                * if result code is LDAP_REFERRAL */
+                               if ( refs != NULL
+                                       && refs[ 0 ] != NULL
+                                       && refs[ 0 ][ 0 ] != '\0' )
+                               {
+                                       if ( rs->sr_err != LDAP_REFERRAL ) {
+                                               Debug( LDAP_DEBUG_ANY,
+                                                       "%s meta_back_op_result[%d]: "
+                                                       "got referrals with err=%d\n",
+                                                       op->o_log_prefix,
+                                                       candidate, rs->sr_err );
+
+                                       } else {
+                                               int     i;
        
-                                       for ( i = 0; refs[ i ] != NULL; i++ )
-                                               /* count */ ;
-                                       rs->sr_ref = op->o_tmpalloc( sizeof( struct berval ) * ( i + 1 ),
-                                               op->o_tmpmemctx );
-                                       for ( i = 0; refs[ i ] != NULL; i++ ) {
-                                               ber_str2bv( refs[ i ], 0, 0, &rs->sr_ref[ i ] );
+                                               for ( i = 0; refs[ i ] != NULL; i++ )
+                                                       /* count */ ;
+                                               rs->sr_ref = op->o_tmpalloc( sizeof( struct berval ) * ( i + 1 ),
+                                                       op->o_tmpmemctx );
+                                               for ( i = 0; refs[ i ] != NULL; i++ ) {
+                                                       ber_str2bv( refs[ i ], 0, 0, &rs->sr_ref[ i ] );
+                                               }
+                                               BER_BVZERO( &rs->sr_ref[ i ] );
                                        }
-                                       BER_BVZERO( &rs->sr_ref[ i ] );
+
+                               } else if ( rs->sr_err == LDAP_REFERRAL ) {
+                                       Debug( LDAP_DEBUG_ANY,
+                                               "%s meta_back_op_result[%d]: "
+                                               "got err=%d with null "
+                                               "or empty referrals\n",
+                                               op->o_log_prefix,
+                                               candidate, rs->sr_err );
+
+                                       rs->sr_err = LDAP_NO_SUCH_OBJECT;
                                }
+
                                if ( ctrls != NULL ) {
                                        rs->sr_ctrls = ctrls;
                                }
@@ -1173,9 +1224,11 @@ retry:;
                ldap_memfree( text );
        }
        if ( rs->sr_ref ) {
-               assert( refs != NULL );
-               ber_memvfree( (void **)refs );
                op->o_tmpfree( rs->sr_ref, op->o_tmpmemctx );
+               rs->sr_ref = NULL;
+       }
+       if ( refs ) {
+               ber_memvfree( (void **)refs );
        }
        if ( ctrls ) {
                assert( rs->sr_ctrls != NULL );
@@ -1392,6 +1445,14 @@ meta_back_proxy_authz_cred(
                                mt->mt_idassert_authcID.bv_val,
                                mt->mt_idassert_passwd.bv_val,
                                authzID.bv_val );
+               if ( defaults == NULL ) {
+                       rs->sr_err = LDAP_OTHER;
+                       LDAP_BACK_CONN_ISBOUND_CLEAR( msc );
+                       if ( sendok & LDAP_BACK_SENDERR ) {
+                               send_ldap_result( op, rs );
+                       }
+                       goto done;
+               }
 
                rs->sr_err = ldap_sasl_interactive_bind_s( msc->msc_ld, binddn->bv_val,
                                mt->mt_idassert_sasl_mech.bv_val, NULL, NULL,
@@ -1496,3 +1557,120 @@ meta_back_proxy_authz_bind( metaconn_t *mc, int candidate, Operation *op, SlapRe
 
        return LDAP_BACK_CONN_ISBOUND( msc );
 }
+
+/*
+ * Add controls;
+ *
+ * if any needs to be added, it is prepended to existing ones,
+ * in a newly allocated array.  The companion function
+ * ldap_back_controls_free() must be used to restore the original
+ * status of op->o_ctrls.
+ */
+int
+meta_back_controls_add(
+               Operation       *op,
+               SlapReply       *rs,
+               metaconn_t      *mc,
+               int             candidate,
+               LDAPControl     ***pctrls )
+{
+       metainfo_t              *mi = (metainfo_t *)op->o_bd->be_private;
+       metatarget_t            *mt = mi->mi_targets[ candidate ];
+       metasingleconn_t        *msc = &mc->mc_conns[ candidate ];
+
+       LDAPControl             **ctrls = NULL;
+       /* set to the maximum number of controls this backend can add */
+       LDAPControl             c[ 2 ] = { 0 };
+       int                     i = 0, j = 0;
+
+       *pctrls = NULL;
+
+       rs->sr_err = LDAP_SUCCESS;
+
+       /* don't add controls if protocol is not LDAPv3 */
+       switch ( mt->mt_version ) {
+       case LDAP_VERSION3:
+               break;
+
+       case 0:
+               if ( op->o_protocol == 0 || op->o_protocol == LDAP_VERSION3 ) {
+                       break;
+               }
+               /* fall thru */
+
+       default:
+               goto done;
+       }
+
+       /* proxyAuthz for identity assertion */
+       switch ( ldap_back_proxy_authz_ctrl( op, rs, &msc->msc_bound_ndn,
+               mt->mt_version, &mt->mt_idassert, &c[ j ] ) )
+       {
+       case SLAP_CB_CONTINUE:
+               break;
+
+       case LDAP_SUCCESS:
+               j++;
+               break;
+
+       default:
+               goto done;
+       }
+
+#ifdef SLAP_CONTROL_X_SESSION_TRACKING
+       /* session tracking */
+       if ( META_BACK_TGT_ST_REQUEST( mt ) ) {
+               switch ( slap_ctrl_session_tracking_request_add( op, rs, &c[ j ] ) ) {
+               case SLAP_CB_CONTINUE:
+                       break;
+
+               case LDAP_SUCCESS:
+                       j++;
+                       break;
+
+               default:
+                       goto done;
+               }
+       }
+#endif /* SLAP_CONTROL_X_SESSION_TRACKING */
+
+       if ( rs->sr_err == SLAP_CB_CONTINUE ) {
+               rs->sr_err = LDAP_SUCCESS;
+       }
+
+       if ( j == 0 ) {
+               goto done;
+       }
+
+       if ( op->o_ctrls ) {
+               for ( i = 0; op->o_ctrls[ i ]; i++ )
+                       /* just count ctrls */ ;
+       }
+
+       ctrls = op->o_tmpalloc( sizeof( LDAPControl * ) * (i + j + 1) + j * sizeof( LDAPControl ),
+                       op->o_tmpmemctx );
+       ctrls[ 0 ] = (LDAPControl *)&ctrls[ i + j + 1 ];
+       *ctrls[ 0 ] = c[ 0 ];
+       for ( i = 1; i < j; i++ ) {
+               ctrls[ i ] = &ctrls[ 0 ][ i ];
+               *ctrls[ i ] = c[ i ];
+       }
+
+       i = 0;
+       if ( op->o_ctrls ) {
+               for ( i = 0; op->o_ctrls[ i ]; i++ ) {
+                       ctrls[ i + j ] = op->o_ctrls[ i ];
+               }
+       }
+       ctrls[ i + j ] = NULL;
+
+done:;
+       if ( ctrls == NULL ) {
+               ctrls = op->o_ctrls;
+       }
+
+       *pctrls = ctrls;
+       
+       return rs->sr_err;
+}
+
index 0a8cf10e6bf7803ac194220ba7cfb4a2d3f74e02..b381daf89eb315bef307f576b2bb1f89851fae79 100644 (file)
@@ -113,8 +113,7 @@ meta_back_compare( Operation *op, SlapReply *rs )
 
 retry:;
        ctrls = op->o_ctrls;
-       rc = ldap_back_proxy_authz_ctrl( &mc->mc_conns[ candidate ].msc_bound_ndn,
-               mt->mt_version, &mt->mt_idassert, op, rs, &ctrls );
+       rc = meta_back_controls_add( op, rs, mc, candidate, &ctrls );
        if ( rc != LDAP_SUCCESS ) {
                send_ldap_result( op, rs );
                goto cleanup;
@@ -130,13 +129,13 @@ retry:;
                do_retry = 0;
                if ( meta_back_retry( op, rs, &mc, candidate, LDAP_BACK_SENDERR ) ) {
                        /* if the identity changed, there might be need to re-authz */
-                       (void)ldap_back_proxy_authz_ctrl_free( op, &ctrls );
+                       (void)ldap_back_controls_free( op, rs, &ctrls );
                        goto retry;
                }
        }
 
 cleanup:;
-       (void)ldap_back_proxy_authz_ctrl_free( op, &ctrls );
+       (void)ldap_back_controls_free( op, rs, &ctrls );
 
        if ( mdn.bv_val != op->o_req_dn.bv_val ) {
                free( mdn.bv_val );
index d90e40ec2526dc860c17b908704ab898c46c40c1..92947b8bec67040aa6d3e14e6a1688fba6bb45b4 100644 (file)
@@ -111,13 +111,11 @@ meta_back_db_config(
        /* URI of server to query */
        if ( strcasecmp( argv[ 0 ], "uri" ) == 0 ) {
                int             i = mi->mi_ntargets;
-#if 0
-               int             j;
-#endif /* uncomment if uri MUST be a branch of suffix */
                LDAPURLDesc     *ludp, *tmpludp;
                struct berval   dn;
                int             rc;
                int             c;
+               BackendDB       *tmp_bd;
 
                metatarget_t    *mt;
                
@@ -282,26 +280,14 @@ meta_back_db_config(
                /*
                 * uri MUST be a branch of suffix!
                 */
-#if 0 /* too strict a constraint */
-               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",
-                               fname, lineno, 0 );
-                       return 1;
-               }
-#else
-               /*
-                * uri MUST be a branch of a suffix!
-                */
-               if ( select_backend( &mt->mt_nsuffix, 0, 0 ) == NULL ) {
+               tmp_bd = select_backend( &mt->mt_nsuffix, 0 );
+               if ( tmp_bd == NULL || tmp_bd->be_private != be->be_private )
+               {
                        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",
+       "%s: line %d: <naming context> of URI does not resolve to this database.\n",
                                fname, lineno, 0 );
                        return 1;
                }
-#endif
 
        /* subtree-exclude */
        } else if ( strcasecmp( argv[ 0 ], "subtree-exclude" ) == 0 ) {
@@ -1235,10 +1221,42 @@ idassert-authzFrom      "dn:<rootdn>"
                } else {
                        mi->mi_targets[ mi->mi_ntargets - 1 ]->mt_flags |= LDAP_BACK_F_QUARANTINE;
                }
+
+#ifdef SLAP_CONTROL_X_SESSION_TRACKING
+       /* session tracking request */
+       } else if ( strcasecmp( argv[ 0 ], "session-tracking-request" ) == 0 ) {
+               unsigned        *flagsp = mi->mi_ntargets ?
+                               &mi->mi_targets[ mi->mi_ntargets - 1 ]->mt_flags
+                               : &mi->mi_flags;
+
+               if ( argc != 2 ) {
+                       Debug( LDAP_DEBUG_ANY,
+       "%s: line %d: \"session-tracking-request {TRUE|false}\" needs 1 argument.\n",
+                               fname, lineno, 0 );
+                       return( 1 );
+               }
+
+               /* this is the default; we add it because the default might change... */
+               switch ( check_true_false( argv[ 1 ] ) ) {
+               case 1:
+                       *flagsp |= LDAP_BACK_F_ST_REQUEST;
+                       break;
+
+               case 0:
+                       *flagsp &= ~LDAP_BACK_F_ST_REQUEST;
+                       break;
+
+               default:
+                       Debug( LDAP_DEBUG_ANY,
+               "%s: line %d: \"session-tracking-request {TRUE|false}\": unknown argument \"%s\".\n",
+                               fname, lineno, argv[ 1 ] );
+                       return( 1 );
+               }
+#endif /* SLAP_CONTROL_X_SESSION_TRACKING */
        
        /* dn massaging */
        } else if ( strcasecmp( argv[ 0 ], "suffixmassage" ) == 0 ) {
-               BackendDB       *tmp_be;
+               BackendDB       *tmp_bd;
                int             i = mi->mi_ntargets - 1, rc;
                struct berval   dn, nvnc, pvnc, nrnc, prnc;
 
@@ -1270,17 +1288,17 @@ idassert-authzFrom      "dn:<rootdn>"
                ber_str2bv( argv[ 1 ], 0, 0, &dn );
                if ( dnPrettyNormal( NULL, &dn, &pvnc, &nvnc, NULL ) != LDAP_SUCCESS ) {
                        Debug( LDAP_DEBUG_ANY, "%s: line %d: "
-                                       "suffix '%s' is invalid\n",
+                                       "suffix \"%s\" is invalid\n",
                                        fname, lineno, argv[ 1 ] );
                        return 1;
                }
                
-               tmp_be = select_backend( &nvnc, 0, 0 );
-               if ( tmp_be != NULL && tmp_be != be ) {
+               tmp_bd = select_backend( &nvnc, 0 );
+               if ( tmp_bd != NULL && tmp_bd->be_private != be->be_private ) {
                        Debug( LDAP_DEBUG_ANY, 
-       "%s: line %d: suffix already in use by another backend in"
-       " \"suffixMassage <suffix> <massaged suffix>\"\n",
-                               fname, lineno, 0 );
+       "%s: line %d: <suffix> \"%s\" already in use by another database, in "
+       "\"suffixMassage <suffix> <massaged suffix>\"\n",
+                               fname, lineno, pvnc.bv_val );
                        free( pvnc.bv_val );
                        free( nvnc.bv_val );
                        return 1;                                               
@@ -1289,33 +1307,27 @@ idassert-authzFrom      "dn:<rootdn>"
                ber_str2bv( argv[ 2 ], 0, 0, &dn );
                if ( dnPrettyNormal( NULL, &dn, &prnc, &nrnc, NULL ) != LDAP_SUCCESS ) {
                        Debug( LDAP_DEBUG_ANY, "%s: line %d: "
-                               "massaged suffix '%s' is invalid\n",
+                               "massaged suffix \"%s\" is invalid\n",
                                fname, lineno, argv[ 2 ] );
                        free( pvnc.bv_val );
                        free( nvnc.bv_val );
                        return 1;
                }
        
-#if 0  
-               tmp_be = select_backend( &nrnc, 0, 0 );
-               if ( tmp_be != NULL ) {
-                       Debug( LDAP_DEBUG_ANY,
-       "%s: line %d: massaged suffix already in use by another backend in" 
-       " \"suffixMassage <suffix> <massaged suffix>\"\n",
-                                fname, lineno, 0 );
+               tmp_bd = select_backend( &nrnc, 0 );
+               if ( tmp_bd != NULL && tmp_bd->be_private == be->be_private ) {
+                       Debug( LDAP_DEBUG_ANY, 
+       "%s: line %d: warning: <massaged suffix> \"%s\" point to this database, in "
+       "\"suffixMassage <suffix> <massaged suffix>\"\n",
+                               fname, lineno, prnc.bv_val );
                        free( pvnc.bv_val );
                        free( nvnc.bv_val );
-                       free( prnc.bv_val );
-                       free( nrnc.bv_val );
-                        return 1;
+                       return 1;                                               
                }
-#endif
-               
+
                /*
                 * The suffix massaging is emulated by means of the
                 * rewrite capabilities
-                * FIXME: no extra rewrite capabilities should be added
-                * to the database
                 */
                rc = suffix_massage_config( mi->mi_targets[ i ]->mt_rwmap.rwm_rw,
                                &pvnc, &nvnc, &prnc, &nrnc );
index 8f1eaac21b794ae66fa905441342b7ceea9cc7ae..da4d7553cd7b49b64051ba7578c7b65e1e40eb6b 100644 (file)
@@ -67,8 +67,7 @@ meta_back_delete( Operation *op, SlapReply *rs )
 
 retry:;
        ctrls = op->o_ctrls;
-       if ( ldap_back_proxy_authz_ctrl( &mc->mc_conns[ candidate ].msc_bound_ndn,
-               mt->mt_version, &mt->mt_idassert, op, rs, &ctrls ) != LDAP_SUCCESS )
+       if ( meta_back_controls_add( op, rs, mc, candidate, &ctrls ) != LDAP_SUCCESS )
        {
                send_ldap_result( op, rs );
                goto cleanup;
@@ -82,13 +81,13 @@ retry:;
                do_retry = 0;
                if ( meta_back_retry( op, rs, &mc, candidate, LDAP_BACK_SENDERR ) ) {
                        /* if the identity changed, there might be need to re-authz */
-                       (void)ldap_back_proxy_authz_ctrl_free( op, &ctrls );
+                       (void)ldap_back_controls_free( op, rs, &ctrls );
                        goto retry;
                }
        }
 
 cleanup:;
-       (void)ldap_back_proxy_authz_ctrl_free( op, &ctrls );
+       (void)ldap_back_controls_free( op, rs, &ctrls );
 
        if ( mdn.bv_val != op->o_req_dn.bv_val ) {
                free( mdn.bv_val );
index 89f27ad8182ff97736b71c8cdad83bf6f93c66a5..a530d7cd89240c7307cfd42c33409fea7c4153cf 100644 (file)
@@ -23,6 +23,7 @@
 #include <ac/socket.h>
 
 #include "slap.h"
+#include "config.h"
 #include "../back-ldap/back-ldap.h"
 #include "back-meta.h"
 
@@ -87,7 +88,8 @@ meta_back_initialize(
 
 int
 meta_back_db_init(
-       Backend         *be )
+       Backend         *be,
+       ConfigReply     *cr)
 {
        metainfo_t      *mi;
        int             i;
@@ -128,7 +130,8 @@ meta_back_db_init(
 
 int
 meta_back_db_open(
-       Backend         *be )
+       Backend         *be,
+       ConfigReply     *cr )
 {
        metainfo_t      *mi = (metainfo_t *)be->be_private;
 
@@ -328,7 +331,8 @@ target_free(
 
 int
 meta_back_db_destroy(
-       Backend         *be )
+       Backend         *be,
+       ConfigReply     *cr )
 {
        metainfo_t      *mi;
 
index 4d6aa59b61fc49f73c169052028a73363da0870d..1871ebbddf9521c2306f4548c1dd6dfbc023e378 100644 (file)
@@ -326,7 +326,7 @@ ldap_back_int_filter_map_rewrite(
                fstr->bv_val = malloc( fstr->bv_len + 1 );
 
                snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s=%s)",
-                       atmp.bv_val, vtmp.bv_val );
+                       atmp.bv_val, vtmp.bv_len ? vtmp.bv_val : "" );
 
                ber_memfree( vtmp.bv_val );
                break;
@@ -343,7 +343,7 @@ ldap_back_int_filter_map_rewrite(
                fstr->bv_val = malloc( fstr->bv_len + 1 );
 
                snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s>=%s)",
-                       atmp.bv_val, vtmp.bv_val );
+                       atmp.bv_val, vtmp.bv_len ? vtmp.bv_val : "" );
 
                ber_memfree( vtmp.bv_val );
                break;
@@ -360,7 +360,7 @@ ldap_back_int_filter_map_rewrite(
                fstr->bv_val = malloc( fstr->bv_len + 1 );
 
                snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s<=%s)",
-                       atmp.bv_val, vtmp.bv_val );
+                       atmp.bv_val, vtmp.bv_len ? vtmp.bv_val : "" );
 
                ber_memfree( vtmp.bv_val );
                break;
@@ -377,7 +377,7 @@ ldap_back_int_filter_map_rewrite(
                fstr->bv_val = malloc( fstr->bv_len + 1 );
 
                snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s~=%s)",
-                       atmp.bv_val, vtmp.bv_val );
+                       atmp.bv_val, vtmp.bv_len ? vtmp.bv_val : "" );
 
                ber_memfree( vtmp.bv_val );
                break;
@@ -407,7 +407,7 @@ ldap_back_int_filter_map_rewrite(
 
                        snprintf( &fstr->bv_val[len - 2], vtmp.bv_len + 3,
                                /* "(attr=" */ "%s*)",
-                               vtmp.bv_val );
+                               vtmp.bv_len ? vtmp.bv_val : "" );
 
                        ber_memfree( vtmp.bv_val );
                }
@@ -422,7 +422,7 @@ ldap_back_int_filter_map_rewrite(
 
                                snprintf( &fstr->bv_val[len - 1], vtmp.bv_len + 3,
                                        /* "(attr=[init]*[any*]" */ "%s*)",
-                                       vtmp.bv_val );
+                                       vtmp.bv_len ? vtmp.bv_val : "" );
                                ber_memfree( vtmp.bv_val );
                        }
                }
@@ -437,7 +437,7 @@ ldap_back_int_filter_map_rewrite(
 
                        snprintf( &fstr->bv_val[len - 1], vtmp.bv_len + 3,
                                /* "(attr=[init*][any*]" */ "%s)",
-                               vtmp.bv_val );
+                               vtmp.bv_len ? vtmp.bv_val : "" );
 
                        ber_memfree( vtmp.bv_val );
                }
@@ -482,7 +482,7 @@ ldap_back_int_filter_map_rewrite(
                        fstr->bv_val = ch_realloc( fstr->bv_val, fstr->bv_len + 1 );
 
                        snprintf( &fstr->bv_val[len-1], vtmp.bv_len + 2, 
-                               /*"("*/ "%s)", vtmp.bv_val );
+                               /*"("*/ "%s)", vtmp.bv_len ? vtmp.bv_val : "" );
 
                        ch_free( vtmp.bv_val );
                }
@@ -514,7 +514,7 @@ ldap_back_int_filter_map_rewrite(
                        f->f_mr_dnattrs ? ":dn" : "",
                        !BER_BVISEMPTY( &f->f_mr_rule_text ) ? ":" : "",
                        !BER_BVISEMPTY( &f->f_mr_rule_text ) ? f->f_mr_rule_text.bv_val : "",
-                       vtmp.bv_val );
+                       vtmp.bv_len ? vtmp.bv_val : "" );
                ber_memfree( vtmp.bv_val );
                break;
 
index a1088c793279b9426497d11e8244c7934940f2d5..ef117860e0bd2dbd8a0281bbf7ca197ee398d497 100644 (file)
@@ -178,8 +178,7 @@ meta_back_modify( Operation *op, SlapReply *rs )
 
 retry:;
        ctrls = op->o_ctrls;
-       rc = ldap_back_proxy_authz_ctrl( &mc->mc_conns[ candidate ].msc_bound_ndn,
-               mt->mt_version, &mt->mt_idassert, op, rs, &ctrls );
+       rc = meta_back_controls_add( op, rs, mc, candidate, &ctrls );
        if ( rc != LDAP_SUCCESS ) {
                send_ldap_result( op, rs );
                goto cleanup;
@@ -193,13 +192,13 @@ retry:;
                do_retry = 0;
                if ( meta_back_retry( op, rs, &mc, candidate, LDAP_BACK_SENDERR ) ) {
                        /* if the identity changed, there might be need to re-authz */
-                       (void)ldap_back_proxy_authz_ctrl_free( op, &ctrls );
+                       (void)ldap_back_controls_free( op, rs, &ctrls );
                        goto retry;
                }
        }
 
 cleanup:;
-       (void)ldap_back_proxy_authz_ctrl_free( op, &ctrls );
+       (void)ldap_back_controls_free( op, rs, &ctrls );
 
        if ( mdn.bv_val != op->o_req_dn.bv_val ) {
                free( mdn.bv_val );
index 2a14b272085af0f9aaad7ec76bd6491871357d3d..66222cfefda2caeabbd255182585dddf34638db4 100644 (file)
@@ -120,8 +120,7 @@ meta_back_modrdn( Operation *op, SlapReply *rs )
 
 retry:;
        ctrls = op->o_ctrls;
-       if ( ldap_back_proxy_authz_ctrl( &mc->mc_conns[ candidate ].msc_bound_ndn,
-               mt->mt_version, &mt->mt_idassert, op, rs, &ctrls ) != LDAP_SUCCESS )
+       if ( meta_back_controls_add( op, rs, mc, candidate, &ctrls ) != LDAP_SUCCESS )
        {
                send_ldap_result( op, rs );
                goto cleanup;
@@ -137,13 +136,13 @@ retry:;
                do_retry = 0;
                if ( meta_back_retry( op, rs, &mc, candidate, LDAP_BACK_SENDERR ) ) {
                        /* if the identity changed, there might be need to re-authz */
-                       (void)ldap_back_proxy_authz_ctrl_free( op, &ctrls );
+                       (void)ldap_back_controls_free( op, rs, &ctrls );
                        goto retry;
                }
        }
 
 cleanup:;
-       (void)ldap_back_proxy_authz_ctrl_free( op, &ctrls );
+       (void)ldap_back_controls_free( op, rs, &ctrls );
 
        if ( mdn.bv_val != op->o_req_dn.bv_val ) {
                free( mdn.bv_val );
index ba163e9f093469de4a8e22e6bf62d6b45d081197..c9e435b41d08cdf48f0e7605ca3a5ec021357e5b 100644 (file)
@@ -232,10 +232,10 @@ meta_search_dobind_init(
 
        assert( msc->msc_ld != NULL );
 
-       /* connect must be async */
-retry:;
+       /* connect must be async only the first time... */
        ldap_set_option( msc->msc_ld, LDAP_OPT_CONNECT_ASYNC, LDAP_OPT_ON );
 
+retry:;
        rc = ldap_sasl_bind( msc->msc_ld, binddn.bv_val, LDAP_SASL_SIMPLE, &cred,
                        NULL, NULL, &candidates[ candidate ].sr_msgid );
 
@@ -316,6 +316,7 @@ down:;
                if ( *mcp == NULL ) {
                        retcode = META_SEARCH_ERR;
                        rs->sr_err = LDAP_UNAVAILABLE;
+                       candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;
                        break;
                }
                /* fall thru */
@@ -597,8 +598,7 @@ meta_back_search_start(
 
 retry:;
        ctrls = op->o_ctrls;
-       if ( ldap_back_proxy_authz_ctrl( &msc->msc_bound_ndn,
-               mt->mt_version, &mt->mt_idassert, op, rs, &ctrls )
+       if ( meta_back_controls_add( op, rs, *mcp, candidate, &ctrls )
                != LDAP_SUCCESS )
        {
                candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;
@@ -624,12 +624,13 @@ retry:;
                if ( nretries && meta_back_retry( op, rs, mcp, candidate, LDAP_BACK_DONTSEND ) ) {
                        nretries = 0;
                        /* if the identity changed, there might be need to re-authz */
-                       (void)ldap_back_proxy_authz_ctrl_free( op, &ctrls );
+                       (void)ldap_back_controls_free( op, rs, &ctrls );
                        goto retry;
                }
 
                if ( *mcp == NULL ) {
                        retcode = META_SEARCH_ERR;
+                       candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;
                        break;
                }
                /* fall thru */
@@ -640,7 +641,7 @@ retry:;
        }
 
 done:;
-       (void)ldap_back_proxy_authz_ctrl_free( op, &ctrls );
+       (void)ldap_back_controls_free( op, rs, &ctrls );
 
        if ( mapped_attrs ) {
                free( mapped_attrs );
@@ -678,7 +679,7 @@ meta_back_search( Operation *op, SlapReply *rs )
        dncookie        dc;
        int             is_ok = 0;
        void            *savepriv;
-       SlapReply       *candidates = meta_back_candidates_get( op );
+       SlapReply       *candidates = NULL;
 
        /*
         * controls are set in ldap_back_dobind()
@@ -695,6 +696,7 @@ getconn:;
        dc.conn = op->o_conn;
        dc.rs = rs;
 
+       if ( candidates == NULL ) candidates = meta_back_candidates_get( op );
        /*
         * Inits searches
         */
@@ -870,7 +872,6 @@ getconn:;
                int     gotit = 0,
                        doabandon = 0,
                        alreadybound = ncandidates;
-               time_t  curr_time = 0;
 
                /* check timeout */
                if ( timeout && lastres_time > 0
@@ -1223,6 +1224,8 @@ really_bad:;
                                                candidates[ i ].sr_type = REP_RESULT;
                                        }
        
+                                       candidates[ i ].sr_msgid = META_MSGID_IGNORE;
+
                                        /* NOTE: ignores response controls
                                         * (and intermediate response controls
                                         * as well, except for those with search
@@ -1241,16 +1244,15 @@ really_bad:;
                                                NULL /* &candidates[ i ].sr_ctrls (unused) */ ,
                                                0 );
                                        if ( rs->sr_err != LDAP_SUCCESS ) {
-                                               ldap_get_option( msc->msc_ld,
-                                                       LDAP_OPT_ERROR_NUMBER,
-                                                       &rs->sr_err );
-                                               sres = slap_map_api2result( rs );
+                                               sres = slap_map_api2result( &candidates[ i ] );
                                                candidates[ i ].sr_type = REP_RESULT;
                                                ldap_msgfree( res );
                                                res = NULL;
                                                goto really_bad;
                                        }
 
+                                       rs->sr_err = candidates[ i ].sr_err;
+
                                        /* massage matchedDN if need be */
                                        if ( candidates[ i ].sr_matched != NULL ) {
                                                struct berval   match, mmatch;
@@ -1276,37 +1278,60 @@ really_bad:;
                                        }
 
                                        /* add references to array */
-                                       if ( references ) {
-                                               BerVarray       sr_ref;
-                                               int             cnt;
+                                       /* RFC 4511: referrals can only appear
+                                        * if result code is LDAP_REFERRAL */
+                                       if ( references != NULL
+                                               && references[ 0 ] != NULL
+                                               && references[ 0 ][ 0 ] != '\0' )
+                                       {
+                                               if ( rs->sr_err != LDAP_REFERRAL ) {
+                                                       Debug( LDAP_DEBUG_ANY,
+                                                               "%s meta_back_search[%ld]: "
+                                                               "got referrals with err=%d\n",
+                                                               op->o_log_prefix,
+                                                               i, rs->sr_err );
+
+                                               } else {
+                                                       BerVarray       sr_ref;
+                                                       int             cnt;
        
-                                               for ( cnt = 0; references[ cnt ]; cnt++ )
-                                                       ;
+                                                       for ( cnt = 0; references[ cnt ]; cnt++ )
+                                                               ;
        
-                                               sr_ref = ch_calloc( sizeof( struct berval ), cnt + 1 );
+                                                       sr_ref = ch_calloc( sizeof( struct berval ), cnt + 1 );
        
-                                               for ( cnt = 0; references[ cnt ]; cnt++ ) {
-                                                       ber_str2bv( references[ cnt ], 0, 1, &sr_ref[ cnt ] );
-                                               }
-                                               BER_BVZERO( &sr_ref[ cnt ] );
+                                                       for ( cnt = 0; references[ cnt ]; cnt++ ) {
+                                                               ber_str2bv( references[ cnt ], 0, 1, &sr_ref[ cnt ] );
+                                                       }
+                                                       BER_BVZERO( &sr_ref[ cnt ] );
        
-                                               ( void )ldap_back_referral_result_rewrite( &dc, sr_ref );
+                                                       ( void )ldap_back_referral_result_rewrite( &dc, sr_ref );
                                        
-                                               /* cleanup */
-                                               ber_memvfree( (void **)references );
-       
-                                               if ( rs->sr_v2ref == NULL ) {
-                                                       rs->sr_v2ref = sr_ref;
+                                                       if ( rs->sr_v2ref == NULL ) {
+                                                               rs->sr_v2ref = sr_ref;
 
-                                               } else {
-                                                       for ( cnt = 0; !BER_BVISNULL( &sr_ref[ cnt ] ); cnt++ ) {
-                                                               ber_bvarray_add( &rs->sr_v2ref, &sr_ref[ cnt ] );
+                                                       } else {
+                                                               for ( cnt = 0; !BER_BVISNULL( &sr_ref[ cnt ] ); cnt++ ) {
+                                                                       ber_bvarray_add( &rs->sr_v2ref, &sr_ref[ cnt ] );
+                                                               }
+                                                               ber_memfree( sr_ref );
                                                        }
-                                                       ber_memfree( sr_ref );
                                                }
+
+                                       } else if ( rs->sr_err == LDAP_REFERRAL ) {
+                                               Debug( LDAP_DEBUG_ANY,
+                                                       "%s meta_back_search[%ld]: "
+                                                       "got err=%d with null "
+                                                       "or empty referrals\n",
+                                                       op->o_log_prefix,
+                                                       i, rs->sr_err );
+
+                                               rs->sr_err = LDAP_NO_SUCH_OBJECT;
                                        }
+
+                                       /* cleanup */
+                                       ber_memvfree( (void **)references );
        
-                                       rs->sr_err = candidates[ i ].sr_err;
                                        sres = slap_map_api2result( rs );
        
                                        if ( LogTest( LDAP_DEBUG_TRACE | LDAP_DEBUG_ANY ) ) {
@@ -1387,7 +1412,6 @@ really_bad:;
                                         * When no candidates are left,
                                         * the outer cycle finishes
                                         */
-                                       candidates[ i ].sr_msgid = META_MSGID_IGNORE;
                                        assert( ncandidates > 0 );
                                        --ncandidates;
        
@@ -1444,10 +1468,16 @@ free_message:;
                /* check for abandon */
                if ( op->o_abandon || LDAP_BACK_CONN_ABANDON( mc ) ) {
                        for ( i = 0; i < mi->mi_ntargets; i++ ) {
-                               if ( candidates[ i ].sr_msgid >= 0 ) {
-                                       if ( META_IS_BINDING( &candidates[ i ] ) ) {
+                               if ( candidates[ i ].sr_msgid >= 0
+                                       || candidates[ i ].sr_msgid == META_MSGID_CONNECTING )
+                               {
+                                       if ( META_IS_BINDING( &candidates[ i ] )
+                                               || candidates[ i ].sr_msgid == META_MSGID_CONNECTING )
+                                       {
                                                ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex );
-                                               if ( LDAP_BACK_CONN_BINDING( &mc->mc_conns[ i ] ) ) {
+                                               if ( LDAP_BACK_CONN_BINDING( &mc->mc_conns[ i ] )
+                                                       || candidates[ i ].sr_msgid == META_MSGID_CONNECTING )
+                                               {
                                                        /* if still binding, destroy */
 
 #ifdef DEBUG_205
@@ -1644,23 +1674,35 @@ finish:;
                        continue;
                }
 
-               if ( mc && META_IS_BINDING( &candidates[ i ] ) ) {
-                       ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex );
-                       if ( LDAP_BACK_CONN_BINDING( &mc->mc_conns[ i ] ) ) {
-                               assert( candidates[ i ].sr_msgid >= 0 );
-                               assert( mc->mc_conns[ i ].msc_ld != NULL );
+               if ( mc ) {
+                       if ( META_IS_BINDING( &candidates[ i ] )
+                               || candidates[ i ].sr_msgid == META_MSGID_CONNECTING )
+                       {
+                               ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex );
+                               if ( LDAP_BACK_CONN_BINDING( &mc->mc_conns[ i ] )
+                                       || candidates[ i ].sr_msgid == META_MSGID_CONNECTING )
+                               {
+                                       assert( candidates[ i ].sr_msgid >= 0
+                                               || candidates[ i ].sr_msgid == META_MSGID_CONNECTING );
+                                       assert( mc->mc_conns[ i ].msc_ld != NULL );
 
 #ifdef DEBUG_205
-                               Debug( LDAP_DEBUG_ANY, "### %s meta_back_search(cleanup) "
-                                       "ldap_unbind_ext[%ld] ld=%p\n",
-                                       op->o_log_prefix, i, (void *)mc->mc_conns[i].msc_ld );
+                                       Debug( LDAP_DEBUG_ANY, "### %s meta_back_search(cleanup) "
+                                               "ldap_unbind_ext[%ld] ld=%p\n",
+                                               op->o_log_prefix, i, (void *)mc->mc_conns[i].msc_ld );
 #endif /* DEBUG_205 */
 
-                               /* if still binding, destroy */
-                               meta_clear_one_candidate( op, mc, i );
+                                       /* if still binding, destroy */
+                                       meta_clear_one_candidate( op, mc, i );
+                               }
+                               ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
+                               META_BINDING_CLEAR( &candidates[ i ] );
+
+                       } else if ( candidates[ i ].sr_msgid >= 0 ) {
+                               (void)meta_back_cancel( mc, op, rs,
+                                       candidates[ i ].sr_msgid, i,
+                                       LDAP_BACK_DONTSEND );
                        }
-                       ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
-                       META_BINDING_CLEAR( &candidates[ i ] );
                }
 
                if ( candidates[ i ].sr_matched ) {
@@ -1718,6 +1760,7 @@ meta_send_entry(
 {
        metainfo_t              *mi = ( metainfo_t * )op->o_bd->be_private;
        struct berval           a, mapped;
+       int                     check_duplicate_attrs = 0;
        Entry                   ent = { 0 };
        BerElement              ber = *e->lm_ber;
        Attribute               *attr, **attrp;
@@ -1784,6 +1827,10 @@ meta_send_entry(
                        ( void )ber_scanf( &ber, "x" /* [W] */ );
                        continue;
                }
+               if ( mapped.bv_val != a.bv_val ) {
+                       /* will need to check for duplicate attrs */
+                       check_duplicate_attrs++;
+               }
                attr = attr_alloc( NULL );
                if ( attr == NULL ) {
                        continue;
@@ -1856,6 +1903,7 @@ meta_send_entry(
                                ldap_back_map( &mi->mi_targets[ target ]->mt_rwmap.rwm_oc,
                                                bv, &mapped, BACKLDAP_REMAP );
                                if ( BER_BVISNULL( &mapped ) || mapped.bv_val[0] == '\0') {
+remove_oc:;
                                        free( bv->bv_val );
                                        BER_BVZERO( bv );
                                        if ( --last < 0 ) {
@@ -1866,8 +1914,23 @@ meta_send_entry(
                                        bv--;
 
                                } else if ( mapped.bv_val != bv->bv_val ) {
-                                       free( bv->bv_val );
-                                       ber_dupbv( bv, &mapped );
+                                       int     i;
+
+                                       for ( i = 0; !BER_BVISNULL( &attr->a_vals[ i ] ); i++ ) {
+                                               if ( &attr->a_vals[ i ] == bv ) {
+                                                       continue;
+                                               }
+
+                                               if ( ber_bvstrcasecmp( &mapped, &attr->a_vals[ i ] ) == 0 ) {
+                                                       break;
+                                               }
+                                       }
+
+                                       if ( !BER_BVISNULL( &attr->a_vals[ i ] ) ) {
+                                               goto remove_oc;
+                                       }
+
+                                       ber_bvreplace( bv, &mapped );
                                }
                        }
                /*
@@ -1955,8 +2018,53 @@ meta_send_entry(
                attrp = &attr->a_next;
 next_attr:;
        }
+
+       /* only check if some mapping occurred */
+       if ( check_duplicate_attrs ) {
+               Attribute       **ap;
+
+               for ( ap = &ent.e_attrs; *ap != NULL; ap = &(*ap)->a_next ) {
+                       Attribute       **tap;
+
+                       for ( tap = &(*ap)->a_next; *tap != NULL; ) {
+                               if ( (*tap)->a_desc == (*ap)->a_desc ) {
+                                       Entry           e = { 0 };
+                                       Modification    mod = { 0 };
+                                       const char      *text = NULL;
+                                       char            textbuf[ SLAP_TEXT_BUFLEN ];
+                                       Attribute       *next = (*tap)->a_next;
+
+                                       BER_BVSTR( &e.e_name, "" );
+                                       BER_BVSTR( &e.e_nname, "" );
+                                       e.e_attrs = *ap;
+                                       mod.sm_op = LDAP_MOD_ADD;
+                                       mod.sm_desc = (*ap)->a_desc;
+                                       mod.sm_type = mod.sm_desc->ad_cname;
+                                       mod.sm_values = (*tap)->a_vals;
+                                       mod.sm_nvalues = (*tap)->a_nvals;
+
+                                       (void)modify_add_values( &e, &mod,
+                                               /* permissive */ 1,
+                                               &text, textbuf, sizeof( textbuf ) );
+
+                                       /* should not insert new attrs! */
+                                       assert( e.e_attrs == *ap );
+
+                                       attr_free( *tap );
+                                       *tap = next;
+
+                               } else {
+                                       tap = &(*tap)->a_next;
+                               }
+                       }
+               }
+       }
+
+       ldap_get_entry_controls( mc->mc_conns[target].msc_ld,
+               e, &rs->sr_ctrls );
        rs->sr_entry = &ent;
        rs->sr_attrs = op->ors_attrs;
+       rs->sr_operational_attrs = NULL;
        rs->sr_flags = 0;
        rs->sr_err = LDAP_SUCCESS;
        rc = send_search_entry( op, rs );
@@ -1967,7 +2075,10 @@ next_attr:;
        }
        rs->sr_entry = NULL;
        rs->sr_attrs = NULL;
-       
+       if ( rs->sr_ctrls != NULL ) {
+               ldap_controls_free( rs->sr_ctrls );
+               rs->sr_ctrls = NULL;
+       }
        if ( !BER_BVISNULL( &ent.e_name ) ) {
                free( ent.e_name.bv_val );
                BER_BVZERO( &ent.e_name );
index 79bf0858727c2ea9a9c1cb966f7cf065ba73ed69..6e1ad91793b0d98d00bac7cd7005cb2648d2aa91 100644 (file)
@@ -74,6 +74,8 @@ typedef struct monitor_entry_t {
        struct monitor_callback_t       *mp_cb;         /* callback sequence */
 } monitor_entry_t;
 
+struct entry_limbo_t;                  /* in init.c */
+
 typedef struct monitor_info_t {
 
        /*
@@ -135,7 +137,7 @@ typedef struct monitor_info_t {
        AttributeDescription    *mi_ad_readOnly;
        AttributeDescription    *mi_ad_restrictedOperation;
 
-       void                    *mi_entry_limbo;
+       struct entry_limbo_t    *mi_entry_limbo;
 } monitor_info_t;
 
 /*
@@ -285,6 +287,10 @@ typedef struct monitor_extra_t {
        monitor_subsys_t * (*get_subsys_by_dn)( struct berval *ndn, int sub );
 
        int (*register_subsys)( monitor_subsys_t *ms );
+       int (*register_backend)( BackendInfo *bi );
+       int (*register_database)( BackendDB *be );
+       int (*register_overlay_info)( slap_overinst *on );
+       int (*register_overlay)( BackendDB *be );
        int (*register_entry)( Entry *e, monitor_callback_t *cb,
                monitor_subsys_t *ms, unsigned long flags );
        int (*register_entry_parent)( Entry *e, monitor_callback_t *cb,
index bc7dbc5298874172f67dd9176199c03671dee393..984253479b3922cdc63d35802760a08f20f16cb9 100644 (file)
@@ -35,11 +35,8 @@ monitor_back_bind( Operation *op, SlapReply *rs )
 {
        Debug(LDAP_DEBUG_ARGS, "==> monitor_back_bind: dn: %s\n", 
                        op->o_req_dn.bv_val, 0, 0 );
-       
-       if ( op->oq_bind.rb_method == LDAP_AUTH_SIMPLE 
-                       && be_isroot_pw( op ) )
-       {
-               ber_dupbv( &op->oq_bind.rb_edn, be_root_dn( op->o_bd ) );
+
+       if ( be_isroot_pw( op ) ) {
                return LDAP_SUCCESS;
        }
 
index 09eb118d23afef1f75f4f2b5d530eded766f068c..3a8df66624c29f16ea9093b82eaa169708566282 100644 (file)
@@ -27,7 +27,7 @@
 #include "back-monitor.h"
 
 int
-monitor_back_compare( struct slap_op *op, struct slap_rep *rs)
+monitor_back_compare( Operation *op, SlapReply *rs )
 {
        monitor_info_t  *mi = ( monitor_info_t * ) op->o_bd->be_private;
        Entry           *e, *matched = NULL;
index 2ae676a0c9644ab43d71a49380ecf982303721a7..f09001ed2b0070e05e8d160f7789b91018a1563f 100644 (file)
@@ -341,6 +341,112 @@ monitor_subsys_database_init_one(
        return 0;
 }
 
+int
+monitor_back_register_database(
+       BackendDB               *be )
+{
+       monitor_info_t          *mi;
+       Entry                   *e_database, **ep;
+       int                     i, rc;
+       monitor_entry_t         *mp;
+       monitor_subsys_t        *ms_backend,
+                               *ms_database,
+                               *ms_overlay;
+       struct berval           bv;
+       char                    buf[ BACKMONITOR_BUFSIZE ];
+
+       assert( be_monitor != NULL );
+
+       if ( !monitor_subsys_is_opened() ) {
+               return monitor_back_register_database_limbo( be );
+       }
+
+       mi = ( monitor_info_t * )be_monitor->be_private;
+
+       ms_backend = monitor_back_get_subsys( SLAPD_MONITOR_BACKEND_NAME );
+       if ( ms_backend == NULL ) {
+               Debug( LDAP_DEBUG_ANY,
+                       "monitor_back_register_database: "
+                       "unable to get "
+                       "\"" SLAPD_MONITOR_BACKEND_NAME "\" "
+                       "subsystem\n",
+                       0, 0, 0 );
+               return -1;
+       }
+
+       ms_database = monitor_back_get_subsys( SLAPD_MONITOR_DATABASE_NAME );
+       if ( ms_database == NULL ) {
+               Debug( LDAP_DEBUG_ANY,
+                       "monitor_back_register_database: "
+                       "unable to get "
+                       "\"" SLAPD_MONITOR_DATABASE_NAME "\" "
+                       "subsystem\n",
+                       0, 0, 0 );
+               return -1;
+       }
+
+       ms_overlay = monitor_back_get_subsys( SLAPD_MONITOR_OVERLAY_NAME );
+       if ( ms_overlay == NULL ) {
+               Debug( LDAP_DEBUG_ANY,
+                       "monitor_back_register_database: "
+                       "unable to get "
+                       "\"" SLAPD_MONITOR_OVERLAY_NAME "\" "
+                       "subsystem\n",
+                       0, 0, 0 );
+               return -1;
+       }
+
+       if ( monitor_cache_get( mi, &ms_database->mss_ndn, &e_database ) ) {
+               Debug( LDAP_DEBUG_ANY,
+                       "monitor_subsys_database_init: "
+                       "unable to get entry \"%s\"\n",
+                       ms_database->mss_ndn.bv_val, 0, 0 );
+               return( -1 );
+       }
+
+       mp = ( monitor_entry_t * )e_database->e_private;
+       for ( i = -1, ep = &mp->mp_children; *ep; i++ ) {
+               Attribute       *a;
+
+               a = attr_find( (*ep)->e_attrs, slap_schema.si_ad_namingContexts );
+               if ( a ) {
+                       int             j, k;
+
+                       for ( j = 0; !BER_BVISNULL( &a->a_nvals[ j ] ); j++ ) {
+                               for ( k = 0; !BER_BVISNULL( &be->be_nsuffix[ k ] ); k++ ) {
+                                       if ( dn_match( &a->a_nvals[ j ], &be->be_nsuffix[ k ] ) ) {
+                                               rc = 0;
+                                               goto done;
+                                       }
+                               }
+                       }
+               }
+
+               mp = ( monitor_entry_t * )(*ep)->e_private;
+
+               assert( mp != NULL );
+               ep = &mp->mp_next;
+       }
+
+       bv.bv_val = buf;
+       bv.bv_len = snprintf( buf, sizeof( buf ), "cn=Database %d", i );
+       if ( bv.bv_len >= sizeof( buf ) ) {
+               rc = -1;
+               goto done;
+       }
+       
+       rc = monitor_subsys_database_init_one( mi, be,
+               ms_database, ms_backend, ms_overlay, &bv, e_database, &ep );
+       if ( rc != 0 ) {
+               goto done;
+       }
+
+done:;
+       monitor_cache_release( mi, e_database );
+
+       return rc;
+}
+
 int
 monitor_subsys_database_init(
        BackendDB               *be,
index 978d1301c8809a38fe35f8398196d4c73fad8e22..3df03cba3a14f9dbb1d121445cf32184b682c076 100644 (file)
@@ -52,6 +52,10 @@ static const monitor_extra_t monitor_extra = {
        monitor_back_get_subsys_by_dn,
 
        monitor_back_register_subsys,
+       monitor_back_register_backend,
+       monitor_back_register_database,
+       monitor_back_register_overlay_info,
+       monitor_back_register_overlay,
        monitor_back_register_entry,
        monitor_back_register_entry_parent,
        monitor_back_register_entry_attrs,
@@ -221,6 +225,12 @@ static struct monitor_subsys_t known_monitor_subsys[] = {
                }, { NULL }
 };
 
+int
+monitor_subsys_is_opened( void )
+{
+       return monitor_subsys_opened;
+}
+
 int
 monitor_back_register_subsys(
        monitor_subsys_t        *ms )
@@ -245,7 +255,7 @@ monitor_back_register_subsys(
        /* if a subsystem is registered __AFTER__ subsystem 
         * initialization (depending on the sequence the databases
         * are listed in slapd.conf), init it */
-       if ( monitor_subsys_opened ) {
+       if ( monitor_subsys_is_opened() ) {
 
                /* FIXME: this should only be possible
                 * if be_monitor is already initialized */
@@ -265,11 +275,20 @@ enum {
        LIMBO_ENTRY,
        LIMBO_ENTRY_PARENT,
        LIMBO_ATTRS,
-       LIMBO_CB
+       LIMBO_CB,
+       LIMBO_BACKEND,
+       LIMBO_DATABASE,
+       LIMBO_OVERLAY_INFO,
+       LIMBO_OVERLAY,
+
+       LIMBO_LAST
 };
 
 typedef struct entry_limbo_t {
        int                     el_type;
+       BackendInfo             *el_bi;
+       BackendDB               *el_be;
+       slap_overinst           *el_on;
        Entry                   *el_e;
        Attribute               *el_a;
        struct berval           el_ndn;
@@ -288,6 +307,83 @@ monitor_back_is_configured( void )
        return be_monitor != NULL;
 }
 
+int
+monitor_back_register_backend(
+       BackendInfo             *bi )
+{
+       return -1;
+}
+
+int
+monitor_back_register_overlay_info(
+       slap_overinst           *on )
+{
+       return -1;
+}
+
+int
+monitor_back_register_overlay(
+       BackendDB               *be )
+{
+       return -1;
+}
+
+int
+monitor_back_register_backend_limbo(
+       BackendInfo             *bi )
+{
+       return -1;
+}
+
+int
+monitor_back_register_database_limbo(
+       BackendDB               *be )
+{
+       entry_limbo_t   **elpp, el = { 0 };
+       monitor_info_t  *mi;
+
+       if ( be_monitor == NULL ) {
+               Debug( LDAP_DEBUG_ANY,
+                       "monitor_back_register_database_limbo: "
+                       "monitor database not configured.\n",
+                       0, 0, 0 );
+               return -1;
+       }
+
+       mi = ( monitor_info_t * )be_monitor->be_private;
+
+
+       el.el_type = LIMBO_DATABASE;
+
+       el.el_be = be;
+       
+       for ( elpp = &mi->mi_entry_limbo;
+                       *elpp;
+                       elpp = &(*elpp)->el_next )
+               /* go to last */;
+
+       *elpp = (entry_limbo_t *)ch_malloc( sizeof( entry_limbo_t ) );
+
+       el.el_next = NULL;
+       **elpp = el;
+
+       return 0;
+}
+
+int
+monitor_back_register_overlay_info_limbo(
+       slap_overinst           *on )
+{
+       return -1;
+}
+
+int
+monitor_back_register_overlay_limbo(
+       BackendDB               *be )
+{
+       return -1;
+}
+
 int
 monitor_back_register_entry(
        Entry                   *e,
@@ -311,7 +407,7 @@ monitor_back_register_entry(
        assert( e != NULL );
        assert( e->e_private == NULL );
        
-       if ( monitor_subsys_opened ) {
+       if ( monitor_subsys_is_opened() ) {
                Entry           *e_parent = NULL,
                                *e_new = NULL,
                                **ep = NULL;
@@ -433,7 +529,7 @@ done:;
                el.el_mss = mss;
                el.el_flags = flags;
 
-               for ( elpp = (entry_limbo_t **)&mi->mi_entry_limbo;
+               for ( elpp = &mi->mi_entry_limbo;
                                *elpp;
                                elpp = &(*elpp)->el_next )
                        /* go to last */;
@@ -490,7 +586,7 @@ monitor_back_register_entry_parent(
                return -1;
        }
 
-       if ( monitor_subsys_opened ) {
+       if ( monitor_subsys_is_opened() ) {
                Entry           *e_parent = NULL,
                                *e_new = NULL,
                                **ep = NULL;
@@ -647,7 +743,7 @@ done:;
                el.el_mss = mss;
                el.el_flags = flags;
 
-               for ( elpp = (entry_limbo_t **)&mi->mi_entry_limbo;
+               for ( elpp = &mi->mi_entry_limbo;
                                *elpp;
                                elpp = &(*elpp)->el_next )
                        /* go to last */;
@@ -717,9 +813,9 @@ monitor_search2ndn(
                return -1;
        }
 
-       op = (Operation *) &opbuf;
        thrctx = ldap_pvt_thread_pool_context();
-       connection_fake_init( &conn, op, thrctx );
+       connection_fake_init( &conn, &opbuf, thrctx );
+       op = &opbuf.ob_op;
 
        op->o_tag = LDAP_REQ_SEARCH;
 
@@ -858,7 +954,7 @@ monitor_back_register_entry_attrs(
                return -1;
        }
 
-       if ( monitor_subsys_opened ) {
+       if ( monitor_subsys_is_opened() ) {
                Entry                   *e = NULL;
                Attribute               **atp = NULL;
                monitor_entry_t         *mp = NULL;
@@ -980,7 +1076,7 @@ done:;
                el.el_a = attrs_dup( a );
                el.el_cb = cb;
 
-               for ( elpp = (entry_limbo_t **)&mi->mi_entry_limbo;
+               for ( elpp = &mi->mi_entry_limbo;
                                *elpp;
                                elpp = &(*elpp)->el_next )
                        /* go to last */;
@@ -1058,7 +1154,7 @@ monitor_back_unregister_entry(
 
        assert( mi != NULL );
 
-       if ( monitor_subsys_opened ) {
+       if ( monitor_subsys_is_opened() ) {
                Entry                   *e = NULL;
                monitor_entry_t         *mp = NULL;
                monitor_callback_t      *cb = NULL;
@@ -1093,7 +1189,7 @@ monitor_back_unregister_entry(
        } else {
                entry_limbo_t   **elpp;
 
-               for ( elpp = (entry_limbo_t **)&mi->mi_entry_limbo;
+               for ( elpp = &mi->mi_entry_limbo;
                        *elpp;
                        elpp = &(*elpp)->el_next )
                {
@@ -1107,6 +1203,9 @@ monitor_back_unregister_entry(
                                for ( cb = elp->el_cb; cb; cb = next ) {
                                        /* FIXME: call callbacks? */
                                        next = cb->mc_next;
+                                       if ( cb->mc_dispose ) {
+                                               cb->mc_dispose( &cb->mc_private );
+                                       }
                                        ch_free( cb );
                                }
                                assert( elp->el_e != NULL );
@@ -1171,7 +1270,7 @@ monitor_back_unregister_entry_parent(
                return -1;
        }
 
-       if ( monitor_subsys_opened ) {
+       if ( monitor_subsys_is_opened() ) {
                Entry                   *e = NULL;
                monitor_entry_t         *mp = NULL;
 
@@ -1224,7 +1323,7 @@ monitor_back_unregister_entry_parent(
        } else {
                entry_limbo_t   **elpp;
 
-               for ( elpp = (entry_limbo_t **)&mi->mi_entry_limbo;
+               for ( elpp = &mi->mi_entry_limbo;
                        *elpp;
                        elpp = &(*elpp)->el_next )
                {
@@ -1241,6 +1340,9 @@ monitor_back_unregister_entry_parent(
                                for ( cb = elp->el_cb; cb; cb = next ) {
                                        /* FIXME: call callbacks? */
                                        next = cb->mc_next;
+                                       if ( cb->mc_dispose ) {
+                                               cb->mc_dispose( &cb->mc_private );
+                                       }
                                        ch_free( cb );
                                }
                                assert( elp->el_e != NULL );
@@ -1326,7 +1428,7 @@ monitor_back_unregister_entry_attrs(
                return -1;
        }
 
-       if ( monitor_subsys_opened ) {
+       if ( monitor_subsys_is_opened() ) {
                Entry                   *e = NULL;
                monitor_entry_t         *mp = NULL;
                int                     freeit = 0;
@@ -1400,14 +1502,12 @@ monitor_back_unregister_entry_attrs(
                        ber_memfree( ndn.bv_val );
                }
 
-               if ( e ) {
-                       monitor_cache_release( mi, e );
-               }
+               monitor_cache_release( mi, e );
 
        } else {
                entry_limbo_t   **elpp;
 
-               for ( elpp = (entry_limbo_t **)&mi->mi_entry_limbo;
+               for ( elpp = &mi->mi_entry_limbo;
                        *elpp;
                        elpp = &(*elpp)->el_next )
                {
@@ -1423,6 +1523,9 @@ monitor_back_unregister_entry_attrs(
                                for ( cb = elp->el_cb; cb; cb = next ) {
                                        /* FIXME: call callbacks? */
                                        next = cb->mc_next;
+                                       if ( cb->mc_dispose ) {
+                                               cb->mc_dispose( &cb->mc_private );
+                                       }
                                        ch_free( cb );
                                }
                                assert( elp->el_e == NULL );
@@ -1933,7 +2036,6 @@ monitor_back_initialize(
        bi->bi_tool_entry_reindex = 0;
        bi->bi_tool_sync = 0;
        bi->bi_tool_dn2id_get = 0;
-       bi->bi_tool_id2entry_get = 0;
        bi->bi_tool_entry_modify = 0;
 
        bi->bi_connection_init = 0;
@@ -1956,7 +2058,8 @@ monitor_back_initialize(
 
 int
 monitor_back_db_init(
-       BackendDB       *be )
+       BackendDB       *be,
+       ConfigReply     *c)
 {
        int                     rc;
        struct berval           dn = BER_BVC( SLAPD_MONITOR_DN ),
@@ -1967,23 +2070,24 @@ monitor_back_db_init(
        monitor_subsys_t        *ms;
 
        /*
-        * register subsys
+        * database monitor can be defined once only
         */
-       for ( ms = known_monitor_subsys; ms->mss_name != NULL; ms++ ) {
-               if ( monitor_back_register_subsys( ms ) ) {
-                       return -1;
+       if ( be_monitor != NULL ) {
+               if (c) {
+                       snprintf(c->msg, sizeof(c->msg),"only one monitor database allowed");
                }
+               return( -1 );
        }
+       be_monitor = be;
 
        /*
-        * database monitor can be defined once only
+        * register subsys
         */
-       if ( be_monitor != NULL ) {
-               Debug( LDAP_DEBUG_ANY,
-                       "only one monitor database is allowed\n", 0, 0, 0 );
-               return( -1 );
+       for ( ms = known_monitor_subsys; ms->mss_name != NULL; ms++ ) {
+               if ( monitor_back_register_subsys( ms ) ) {
+                       return -1;
+               }
        }
-       be_monitor = be;
 
        /* indicate system schema supported */
        SLAP_BFLAGS(be) |= SLAP_BFLAG_MONITOR;
@@ -2005,7 +2109,7 @@ monitor_back_db_init(
 
        be->be_private = &monitor_info;
 
-       be2 = select_backend( &ndn, 0, 0 );
+       be2 = select_backend( &ndn, 0 );
        if ( be2 != be ) {
                char    *type = be2->bd_info->bi_type;
 
@@ -2014,19 +2118,60 @@ monitor_back_db_init(
                        type = oi->oi_orig->bi_type;
                }
 
-               Debug( LDAP_DEBUG_ANY,
-                       "\"monitor\" database serving namingContext \"%s\" "
-                       "is hidden by \"%s\" database serving namingContext \"%s\".\n",
-                       pdn.bv_val, type, be2->be_nsuffix[ 0 ].bv_val );
+               if (c) {
+                       snprintf(c->msg, sizeof(c->msg),
+                                       "\"monitor\" database serving namingContext \"%s\" "
+                                       "is hidden by \"%s\" database serving namingContext \"%s\".\n",
+                                       pdn.bv_val, type, be2->be_nsuffix[ 0 ].bv_val );
+               }
                return -1;
        }
 
        return 0;
 }
 
+static void
+monitor_back_destroy_limbo_entry(
+       entry_limbo_t   *el,
+       int             dispose )
+{
+       if ( el->el_e ) {
+               entry_free( el->el_e );
+       }
+       if ( el->el_a ) {
+               attrs_free( el->el_a );
+       }
+       if ( !BER_BVISNULL( &el->el_ndn ) ) {
+               ber_memfree( el->el_ndn.bv_val );
+       }
+       if ( !BER_BVISNULL( &el->el_nbase ) ) {
+               ber_memfree( el->el_nbase.bv_val );
+       }
+       if ( !BER_BVISNULL( &el->el_filter ) ) {
+               ber_memfree( el->el_filter.bv_val );
+       }
+
+       /* NOTE: callbacks are not copied; so only free them
+        * if disposing of */
+       if ( el->el_cb && dispose != 0 ) {
+               monitor_callback_t *next;
+
+               for ( ; el->el_cb; el->el_cb = next ) {
+                       next = el->el_cb->mc_next;
+                       if ( el->el_cb->mc_dispose ) {
+                               el->el_cb->mc_dispose( &el->el_cb->mc_private );
+                       }
+                       ch_free( el->el_cb );
+               }
+       }
+
+       ch_free( el );
+}
+
 int
 monitor_back_db_open(
-       BackendDB       *be )
+       BackendDB       *be,
+       ConfigReply     *cr)
 {
        monitor_info_t          *mi = (monitor_info_t *)be->be_private;
        struct monitor_subsys_t **ms;
@@ -2046,6 +2191,8 @@ monitor_back_db_open(
                " attributes, which must be explicitly requested."),
                BER_BVNULL };
 
+       int                     retcode = 0;
+
        assert( be_monitor != NULL );
        if ( be != be_monitor ) {
                be_monitor = be;
@@ -2225,7 +2372,7 @@ monitor_back_db_open(
        monitor_subsys_opened = 1;
 
        if ( mi->mi_entry_limbo ) {
-               entry_limbo_t   *el = (entry_limbo_t *)mi->mi_entry_limbo;
+               entry_limbo_t   *el = mi->mi_entry_limbo;
 
                for ( ; el; ) {
                        entry_limbo_t   *tmp;
@@ -2271,41 +2418,40 @@ monitor_back_db_open(
                                                &el->el_filter );
                                break;
 
+                       case LIMBO_BACKEND:
+                               rc = monitor_back_register_backend( el->el_bi );
+                               break;
+
+                       case LIMBO_DATABASE:
+                               rc = monitor_back_register_database( el->el_be );
+                               break;
+
+                       case LIMBO_OVERLAY_INFO:
+                               rc = monitor_back_register_overlay_info( el->el_on );
+                               break;
+
+                       case LIMBO_OVERLAY:
+                               rc = monitor_back_register_overlay( el->el_be );
+                               break;
+
                        default:
                                assert( 0 );
                        }
 
-                       if ( el->el_e ) {
-                               entry_free( el->el_e );
-                       }
-                       if ( el->el_a ) {
-                               attrs_free( el->el_a );
-                       }
-                       if ( !BER_BVISNULL( &el->el_ndn ) ) {
-                               ber_memfree( el->el_ndn.bv_val );
-                       }
-                       if ( !BER_BVISNULL( &el->el_nbase ) ) {
-                               ber_memfree( el->el_nbase.bv_val );
-                       }
-                       if ( !BER_BVISNULL( &el->el_filter ) ) {
-                               ber_memfree( el->el_filter.bv_val );
-                       }
-                       if ( el->el_cb && rc != 0 ) {
-                               if ( el->el_cb->mc_dispose ) {
-                                       el->el_cb->mc_dispose( &el->el_cb->mc_private );
-                               }
-                               ch_free( el->el_cb );
-                       }
-
                        tmp = el;
                        el = el->el_next;
-                       ch_free( tmp );
+                       monitor_back_destroy_limbo_entry( tmp, rc );
+
+                       if ( rc != 0 ) {
+                               /* try all, but report error at end */
+                               retcode = 1;
+                       }
                }
 
                mi->mi_entry_limbo = NULL;
        }
 
-       return( 0 );
+       return retcode;
 }
 
 int
@@ -2342,7 +2488,8 @@ monitor_back_db_config(
 
 int
 monitor_back_db_destroy(
-       BackendDB       *be )
+       BackendDB       *be,
+       ConfigReply     *cr)
 {
        monitor_info_t  *mi = ( monitor_info_t * )be->be_private;
 
@@ -2372,6 +2519,16 @@ monitor_back_db_destroy(
 
                ch_free( monitor_subsys );
        }
+
+       if ( mi->mi_entry_limbo ) {
+               entry_limbo_t   *el = mi->mi_entry_limbo;
+
+               for ( ; el; ) {
+                       entry_limbo_t *tmp = el;
+                       el = el->el_next;
+                       monitor_back_destroy_limbo_entry( tmp, 1 );
+               }
+       }
        
        ldap_pvt_thread_mutex_destroy( &monitor_info.mi_cache_mutex );
 
index c25261b07c4890ddd72567ca371be3d910c3a713..8f6d07d29f75b595daa825a5de82ea10fc8127bc 100644 (file)
@@ -111,7 +111,7 @@ monitor_subsys_log_modify(
        int             rc = LDAP_OTHER;
        int             newlevel = ldap_syslog;
        Attribute       *save_attrs;
-       Modifications   *modlist = op->oq_modify.rs_modlist;
+       Modifications   *modlist = op->orm_modlist;
        Modifications   *ml;
 
        ldap_pvt_thread_mutex_lock( &monitor_log_mutex );
index a8d6c887dbc68bc54fe08032f58c65a8afe364d3..5001bfabcf3af857d70761598ca6c9ed72a97f5b 100644 (file)
@@ -62,7 +62,7 @@ monitor_back_modify( Operation *op, SlapReply *rs )
                return rs->sr_err;
        }
 
-       if ( !acl_check_modlist( op, e, op->oq_modify.rs_modlist )) {
+       if ( !acl_check_modlist( op, e, op->orm_modlist )) {
                rc = LDAP_INSUFFICIENT_ACCESS;
 
        } else {
index 48bbcd5f70978bcf69cc3546e43e2ab5d7b95e7a..74bd27402c2805d361cacb098eec6c8bb4ff937c 100644 (file)
@@ -34,12 +34,12 @@ struct monitor_ops_t {
 } monitor_op[] = {
        { BER_BVC( "cn=Bind" ),         BER_BVNULL },
        { BER_BVC( "cn=Unbind" ),       BER_BVNULL },
+       { BER_BVC( "cn=Search" ),       BER_BVNULL },
+       { BER_BVC( "cn=Compare" ),      BER_BVNULL },
+       { BER_BVC( "cn=Modify" ),       BER_BVNULL },
+       { BER_BVC( "cn=Modrdn" ),       BER_BVNULL },
        { BER_BVC( "cn=Add" ),          BER_BVNULL },
        { BER_BVC( "cn=Delete" ),       BER_BVNULL },
-       { BER_BVC( "cn=Modrdn" ),       BER_BVNULL },
-       { BER_BVC( "cn=Modify" ),       BER_BVNULL },
-       { BER_BVC( "cn=Compare" ),      BER_BVNULL },
-       { BER_BVC( "cn=Search" ),       BER_BVNULL },
        { BER_BVC( "cn=Abandon" ),      BER_BVNULL },
        { BER_BVC( "cn=Extended" ),     BER_BVNULL },
        { BER_BVNULL,                   BER_BVNULL }
index 66306e23ae50968591a0ae3b2dd0505f605a858b..f09522db1ff77b7585c08eece0e32014d42a2a06 100644 (file)
@@ -135,8 +135,35 @@ monitor_entry_stub LDAP_P((
  * init
  */
 extern int
+monitor_subsys_is_opened LDAP_P((
+       void ));
+extern int
 monitor_back_register_subsys LDAP_P((
        monitor_subsys_t        *ms ));
+extern int
+monitor_back_register_backend LDAP_P((
+       BackendInfo             *bi ));
+extern int
+monitor_back_register_database LDAP_P((
+       BackendDB               *be ));
+extern int
+monitor_back_register_overlay_info LDAP_P((
+       slap_overinst           *on ));
+extern int
+monitor_back_register_overlay LDAP_P((
+       BackendDB               *be ));
+extern int
+monitor_back_register_backend_limbo LDAP_P((
+       BackendInfo             *bi ));
+extern int
+monitor_back_register_database_limbo LDAP_P((
+       BackendDB               *be ));
+extern int
+monitor_back_register_overlay_info_limbo LDAP_P((
+       slap_overinst           *on ));
+extern int
+monitor_back_register_overlay_limbo LDAP_P((
+       BackendDB               *be ));
 extern monitor_subsys_t *
 monitor_back_get_subsys LDAP_P((
        const char              *name ));
index 2d96339fa4a7541cd3e6fbdb521d783dcbe0d4b2..f3450d8315dc4ec4e28e90f829cb355101a0e300 100644 (file)
@@ -46,7 +46,7 @@ monitor_subsys_time_init(
        
        Entry           *e, **ep, *e_time;
        monitor_entry_t *mp;
-       struct berval bv;
+       struct berval   bv, value;
 
        assert( be != NULL );
 
@@ -73,8 +73,8 @@ monitor_subsys_time_init(
        if ( e == NULL ) {
                Debug( LDAP_DEBUG_ANY,
                        "monitor_subsys_time_init: "
-                       "unable to create entry \"cn=Start,%s\"\n",
-                       ms->mss_ndn.bv_val, 0, 0 );
+                       "unable to create entry \"%s,%s\"\n",
+                       bv.bv_val, ms->mss_ndn.bv_val, 0 );
                return( -1 );
        }
        attr_merge_normalize_one( e, mi->mi_ad_monitorTimestamp,
@@ -92,8 +92,8 @@ monitor_subsys_time_init(
        if ( monitor_cache_add( mi, e ) ) {
                Debug( LDAP_DEBUG_ANY,
                        "monitor_subsys_time_init: "
-                       "unable to add entry \"cn=Start,%s\"\n",
-                       ms->mss_ndn.bv_val, 0, 0 );
+                       "unable to add entry \"%s,%s\"\n",
+                       bv.bv_val, ms->mss_ndn.bv_val, 0 );
                return( -1 );
        }
        
@@ -109,8 +109,8 @@ monitor_subsys_time_init(
        if ( e == NULL ) {
                Debug( LDAP_DEBUG_ANY,
                        "monitor_subsys_time_init: "
-                       "unable to create entry \"cn=Current,%s\"\n",
-                       ms->mss_ndn.bv_val, 0, 0 );
+                       "unable to create entry \"%s,%s\"\n",
+                       bv.bv_val, ms->mss_ndn.bv_val, 0 );
                return( -1 );
        }
        attr_merge_normalize_one( e, mi->mi_ad_monitorTimestamp,
@@ -128,8 +128,45 @@ monitor_subsys_time_init(
        if ( monitor_cache_add( mi, e ) ) {
                Debug( LDAP_DEBUG_ANY,
                        "monitor_subsys_time_init: "
-                       "unable to add entry \"cn=Current,%s\"\n",
-                       ms->mss_ndn.bv_val, 0, 0 );
+                       "unable to add entry \"%s,%s\"\n",
+                       bv.bv_val, ms->mss_ndn.bv_val, 0 );
+               return( -1 );
+       }
+       
+       *ep = e;
+       ep = &mp->mp_next;
+
+       /*
+        * Uptime
+        */
+       BER_BVSTR( &bv, "cn=Uptime" );
+       e = monitor_entry_stub( &ms->mss_dn, &ms->mss_ndn, &bv,
+               mi->mi_oc_monitoredObject, mi, NULL, NULL );
+       if ( e == NULL ) {
+               Debug( LDAP_DEBUG_ANY,
+                       "monitor_subsys_time_init: "
+                       "unable to create entry \"%s,%s\"\n",
+                       bv.bv_val, ms->mss_ndn.bv_val, 0 );
+               return( -1 );
+       }
+       BER_BVSTR( &value, "0" );
+       attr_merge_normalize_one( e, mi->mi_ad_monitoredInfo,
+               &value, NULL );
+
+       mp = monitor_entrypriv_create();
+       if ( mp == NULL ) {
+               return -1;
+       }
+       e->e_private = ( void * )mp;
+       mp->mp_info = ms;
+       mp->mp_flags = ms->mss_flags \
+               | MONITOR_F_SUB | MONITOR_F_PERSISTENT;
+
+       if ( monitor_cache_add( mi, e ) ) {
+               Debug( LDAP_DEBUG_ANY,
+                       "monitor_subsys_time_init: "
+                       "unable to add entry \"%s,%s\"\n",
+                       bv.bv_val, ms->mss_ndn.bv_val, 0 );
                return( -1 );
        }
        
@@ -148,7 +185,8 @@ monitor_subsys_time_update(
        Entry                   *e )
 {
        monitor_info_t          *mi = ( monitor_info_t * )op->o_bd->be_private;
-       static struct berval    bv_current = BER_BVC( "cn=current" );
+       static struct berval    bv_current = BER_BVC( "cn=current" ),
+                               bv_uptime = BER_BVC( "cn=uptime" );
        struct berval           rdn;
 
        assert( mi != NULL );
@@ -200,6 +238,29 @@ monitor_subsys_time_update(
                assert( len == a->a_vals[ 0 ].bv_len );
                AC_MEMCPY( a->a_vals[ 0 ].bv_val, tmbuf, len );
 
+               /* FIXME: touch modifyTimestamp? */
+
+       } else if ( dn_match( &rdn, &bv_uptime ) ) {
+               Attribute       *a;
+               double          diff;
+               char            buf[ BACKMONITOR_BUFSIZE ];
+               struct berval   bv;
+
+               a = attr_find( e->e_attrs, mi->mi_ad_monitoredInfo );
+               if ( a == NULL ) {
+                       return rs->sr_err = LDAP_OTHER;
+               }
+
+               diff = difftime( slap_get_time(), starttime );
+               bv.bv_len = snprintf( buf, sizeof( buf ), "%lu",
+                       (unsigned long) diff );
+               bv.bv_val = buf;
+
+               ber_bvreplace( &a->a_vals[ 0 ], &bv );
+               if ( a->a_nvals != a->a_vals ) {
+                       ber_bvreplace( &a->a_nvals[ 0 ], &bv );
+               }
+
                /* FIXME: touch modifyTimestamp? */
        }
 
index 4fc58ef961998d296cd07b430bde9bcdd5f4bca9..29673f9a4202190225ade93adc83466b72a05c2c 100644 (file)
@@ -24,6 +24,7 @@
 #include <ac/string.h>
 
 #include "slap.h"
+#include "config.h"
 
 struct null_info {
        int     ni_bind_allowed;
@@ -68,6 +69,20 @@ null_back_false( Operation *op, SlapReply *rs )
 }
 
 
+/* for overlays */
+int null_back_entry_get(
+       Operation *op,
+       struct berval *ndn,
+       ObjectClass *oc,
+       AttributeDescription *at,
+       int rw,
+       Entry **ent )
+{
+       *ent = NULL;
+       return 1;
+}
+
+
 /* Slap tools */
 
 static int
@@ -146,7 +161,7 @@ null_back_db_config(
 }
 
 static int
-null_back_db_init( BackendDB *be )
+null_back_db_init( BackendDB *be, ConfigReply *cr )
 {
        struct null_info *ni = ch_calloc( 1, sizeof(struct null_info) );
        ni->ni_bind_allowed = 0;
@@ -156,7 +171,7 @@ null_back_db_init( BackendDB *be )
 }
 
 static int
-null_back_db_destroy( Backend *be )
+null_back_db_destroy( Backend *be, ConfigReply *cr )
 {
        free( be->be_private );
        return 0;
@@ -194,6 +209,8 @@ null_back_initialize( BackendInfo *bi )
        bi->bi_connection_init = 0;
        bi->bi_connection_destroy = 0;
 
+       bi->bi_entry_get_rw = null_back_entry_get;
+
        bi->bi_tool_entry_open = null_tool_entry_open;
        bi->bi_tool_entry_close = null_tool_entry_close;
        bi->bi_tool_entry_first = null_tool_entry_next;
index 4e20ff628c10f6759befdde6445cf0a7c6eb8a25..ca1281267db979d292ac1ccac6ba5da1e8438e9e 100644 (file)
 #
 #      database        perl
 #      suffix          "o=AnyOrg,c=US"
-#      perlModulePath  /path/to/this/file
+#      perlModulePath  /directory/containing/this/module
 #      perlModule      SampleLDAP
+#
+# See the slapd-perl(5) manual page for details.
 
 package SampleLDAP;
-
+use strict;
+use warnings;
 use POSIX;
 
-sub new
-{
-       my $class = shift;
+$SampleLDAP::VERSION = '1.01';
+
+sub new {
+    my $class = shift;
 
-       my $this = {};
-       bless $this, $class;
-        print STDERR "Here in new\n";
-       print STDERR "Posix Var " . BUFSIZ . " and " . FILENAME_MAX . "\n";
-       return $this;
+    my $this = {};
+    bless $this, $class;
+    print {*STDERR} "Here in new\n";
+    print {*STDERR} 'Posix Var ' . BUFSIZ . ' and ' . FILENAME_MAX . "\n";
+    return $this;
 }
 
-sub init
-{
-       return 0;
+sub init {
+    return 0;
 }
 
-sub search
-{
-       my $this = shift;
-       my($base, $scope, $deref, $sizeLim, $timeLim, $filterStr, $attrOnly, @attrs ) = @_;
-        print STDERR "====$filterStr====\n";
-       $filterStr =~ s/\(|\)//g;
-       $filterStr =~ s/=/: /;
+sub search {
+    my $this = shift;
+    my ( $base, $scope, $deref, $sizeLim, $timeLim, $filterStr, $attrOnly,
+        @attrs )
+      = @_;
+    print {*STDERR}, "====$filterStr====\n";
+    $filterStr =~ s/\(|\)//gm;
+    $filterStr =~ s/=/: /m;
 
-       my @match_dn = ();
-       foreach my $dn ( keys %$this ) {
-               if ( $this->{ $dn } =~ /$filterStr/im ) {
-                       push @match_dn, $dn;
-                       last if ( scalar @match_dn == $sizeLim );
+    my @match_dn = ();
+    for my $dn ( keys %{$this} ) {
+        if ( $this->{$dn} =~ /$filterStr/imx ) {
+            push @match_dn, $dn;
+            last if ( scalar @match_dn == $sizeLim );
 
-               }
-       }
+        }
+    }
 
-       my @match_entries = ();
-       
-       foreach my $dn ( @match_dn )  {
-               push @match_entries, $this->{ $dn };
-       }
+    my @match_entries = ();
 
-       return ( 0 , @match_entries );
+    for my $dn (@match_dn) {
+        push @match_entries, $this->{$dn};
+    }
+
+    return ( 0, @match_entries );
 
 }
 
-sub compare
-{
-       my $this = shift;
-       my ( $dn, $avaStr ) = @_;
-       my $rc = 5; # LDAP_COMPARE_FALSE
+sub compare {
+    my $this = shift;
+    my ( $dn, $avaStr ) = @_;
+    my $rc = 5;    # LDAP_COMPARE_FALSE
 
-       $avaStr =~ s/=/: /;
+    $avaStr =~ s/=/: /m;
 
-       if ( $this->{ $dn } =~ /$avaStr/im ) {
-               $rc = 6; # LDAP_COMPARE_TRUE
-       }
+    if ( $this->{$dn} =~ /$avaStr/im ) {
+        $rc = 6;    # LDAP_COMPARE_TRUE
+    }
 
-       return $rc;
+    return $rc;
 }
 
-sub modify
-{
-       my $this = shift;
+sub modify {
+    my $this = shift;
 
-       my ( $dn, @list ) = @_;
+    my ( $dn, @list ) = @_;
 
-       while ( @list > 0 ) {
-               my $action = shift @list;
-               my $key    = shift @list;
-               my $value  = shift @list;
+    while ( @list > 0 ) {
+        my $action = shift @list;
+        my $key    = shift @list;
+        my $value  = shift @list;
 
-               if( $action eq "ADD" ) {
-                       $this->{ $dn } .= "$key: $value\n";
+        if ( $action eq 'ADD' ) {
+            $this->{$dn} .= "$key: $value\n";
 
-               }
-               elsif( $action eq "DELETE" ) {
-                       $this->{ $dn } =~ s/^$key:\s*$value\n//mi ;
+        }
+        elsif ( $action eq 'DELETE' ) {
+            $this->{$dn} =~ s/^$key:\s*$value\n//im;
 
-               }
-               elsif( $action eq "REPLACE" ) {
-                       $this->{ $dn } =~ s/$key: .*$/$key: $value/im ;
-               }
-       }
+        }
+        elsif ( $action eq 'REPLACE' ) {
+            $this->{$dn} =~ s/$key: .*$/$key: $value/im;
+        }
+    }
 
-       return 0;
+    return 0;
 }
 
-sub add
-{
-       my $this = shift;
-
-       my ( $entryStr ) = @_;
+sub add {
+    my $this = shift;
 
-       my ( $dn ) = ( $entryStr =~ /dn:\s(.*)$/m );
+    my ($entryStr) = @_;
 
-       #
-       # This needs to be here until a normalized dn is
-       # passed to this routine.
-       #
-       $dn = uc( $dn );
-       $dn =~ s/\s*//g;
+    my ($dn) = ( $entryStr =~ /dn:\s(.*)$/m );
 
+    #
+    # This needs to be here until a normalized dn is
+    # passed to this routine.
+    #
+    $dn = uc $dn;
+    $dn =~ s/\s*//gm;
 
-       $this->{$dn} = $entryStr;
+    $this->{$dn} = $entryStr;
 
-       return 0;
+    return 0;
 }
 
-sub modrdn
-{
-       my $this = shift;
+sub modrdn {
+    my $this = shift;
 
-       my ( $dn, $newdn, $delFlag ) = @_;
+    my ( $dn, $newdn, $delFlag ) = @_;
 
-       $this->{ $newdn } = $this->{ $dn };
+    $this->{$newdn} = $this->{$dn};
 
-       if( $delFlag ) {
-               delete $this->{ $dn };
-       }
-       return 0;
+    if ($delFlag) {
+        delete $this->{$dn};
+    }
+    return 0;
 
 }
 
-sub delete
-{
-       my $this = shift;
+sub delete {
+    my $this = shift;
+
+    my ($dn) = @_;
 
-       my ( $dn ) = @_;
-       
-        print STDERR "XXXXXX $dn XXXXXXX\n";
-       delete $this->{$dn};
+    print {*STDERR} "XXXXXX $dn XXXXXXX\n";
+    delete $this->{$dn};
+    return 0;
 }
 
-sub config
-{
-       my $this = shift;
+sub config {
+    my $this = shift;
 
-       my ( @args ) = @_;
-        local $, = " - ";
-        print STDERR @args;
-        print STDERR "\n";
-       return 0;
+    my (@args) = @_;
+    local $, = ' - ';
+    print {*STDERR} @args;
+    print {*STDERR} "\n";
+    return 0;
 }
 
 1;
index 2e19370f49a15a75140341ca3c79c606ca475875..878c48dfb04a0b9a4eec3e3e6ab569677e48b299 100644 (file)
@@ -32,6 +32,16 @@ perl_back_bind(
 
        PerlBackend *perl_back = (PerlBackend *) op->o_bd->be_private;
 
+       /* allow rootdn as a means to auth without the need to actually
+        * contact the proxied DSA */
+       switch ( be_rootdn_bind( op, rs ) ) {
+       case SLAP_CB_CONTINUE:
+               break;
+
+       default:
+               return rs->sr_err;
+       }
+
 #if defined(HAVE_WIN32_ASPERL) || defined(USE_ITHREADS)
        PERL_SET_CONTEXT( PERL_INTERPRETER );
 #endif
index 46257972332983a40191a35df9ebd990d8761907..c1d0b05566bd0e0a1cf7f64fc01be085c884dd89 100644 (file)
@@ -16,7 +16,7 @@
  */
 
 #include "perl_back.h"
-
+#include "../config.h"
 /**********************************************************
  *
  * Close
@@ -39,7 +39,8 @@ perl_back_close(
 
 int
 perl_back_db_destroy(
-       BackendDB *be
+       BackendDB *be,
+       ConfigReply *cr
 )
 {
        free( be->be_private );
index a695a8f97f82bc9276ac8c6091888413561a661f..8d69a6fbc1a94e9a93547208b255d9ccb5eaa7b1 100644 (file)
@@ -16,6 +16,7 @@
  */
 
 #include "perl_back.h"
+#include "../config.h"
 
 static void perl_back_xs_init LDAP_P((PERL_BACK_XS_INIT_PARAMS));
 EXT void boot_DynaLoader LDAP_P((PERL_BACK_BOOT_DYNALOADER_PARAMS));
@@ -85,7 +86,8 @@ perl_back_initialize(
 
 int
 perl_back_db_init(
-       BackendDB       *be
+       BackendDB       *be,
+       ConfigReply     *cr
 )
 {
        be->be_private = (PerlBackend *) ch_malloc( sizeof(PerlBackend) );
@@ -100,7 +102,8 @@ perl_back_db_init(
 
 int
 perl_back_db_open(
-       BackendDB       *be
+       BackendDB       *be,
+       ConfigReply     *cr
 )
 {
        int count;
index 6ef139cbaf0a09cddd7dc878648242b12910039d..75a6a81eff4824ff2ebe93eec19326382c6ea419 100644 (file)
@@ -13,8 +13,8 @@
 ## top-level directory of the distribution or, alternatively, at
 ## <http://www.OpenLDAP.org/license.html>.
 
-SRCS   = init.c config.c op.c
-OBJS   = init.lo config.lo op.lo
+SRCS   = init.c op.c
+OBJS   = init.lo op.lo
 
 LDAP_INCDIR= ../../../include       
 LDAP_LIBDIR= ../../../libraries
diff --git a/servers/slapd/back-relay/config.c b/servers/slapd/back-relay/config.c
deleted file mode 100644 (file)
index 503da6e..0000000
+++ /dev/null
@@ -1,181 +0,0 @@
-/* config.c - relay backend configuration file routine */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 2004-2007 The OpenLDAP Foundation.
- * Portions Copyright 2004 Pierangelo Masarati.
- * 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>.
- */
-/* ACKNOWLEDGEMENTS:
- * This work was initially developed by Pierangelo Masaratifor inclusion
- * in OpenLDAP Software.
- */
-
-#include "portable.h"
-
-#include <stdio.h>
-
-#include "slap.h"
-#include "back-relay.h"
-
-int
-relay_back_db_config(
-       BackendDB       *be,
-       const char      *fname,
-       int             lineno,
-       int             argc,
-       char            **argv )
-{
-       relay_back_info *ri = (struct relay_back_info *)be->be_private;
-
-       if ( ri == NULL ) {
-               Log2( LDAP_DEBUG_ANY, LDAP_LEVEL_ERR,
-                       "%s: line %d: relay backend info is null.\n",
-                       fname, lineno );
-               return 1;
-       }
-
-       /* real naming context */
-       if ( strcasecmp( argv[ 0 ], "relay" ) == 0 ) {
-               struct berval   dn, ndn, pdn;
-               int             rc;
-               BackendDB       *bd;
-
-               switch ( argc ) {
-               case 3:
-                       if ( strcmp( argv[ 2 ], "massage" ) != 0 ) {
-                               Log3( LDAP_DEBUG_ANY, LDAP_LEVEL_ERR,
-                                       "%s: line %d: "
-                                       "unknown arg[#2]=\"%s\" "
-                                       "in \"relay <dn> [massage]\" line\n",
-                                       fname, lineno, argv[ 2 ] );
-                               return 1;
-                       }
-
-                       if ( be->be_nsuffix == NULL ) {
-                               Log2( LDAP_DEBUG_ANY, LDAP_LEVEL_ERR,
-                                       "%s: line %d: "
-                                       "\"relay\" directive "
-                                       "must appear after \"suffix\".\n",
-                                       fname, lineno );
-                               return 1;
-                       }
-
-                       if ( !BER_BVISNULL( &be->be_nsuffix[ 1 ] ) ) {
-                               Log2( LDAP_DEBUG_ANY, LDAP_LEVEL_ERR,
-                                       "%s: line %d: "
-                                       "relayng of multiple suffix "
-                                       "database not supported.\n",
-                                       fname, lineno );
-                               return 1;
-                       }
-                       /* fallthru */
-
-               case 2:
-                       break;
-
-               case 1:
-                       Log2( LDAP_DEBUG_ANY, LDAP_LEVEL_ERR,
-                               "%s: line %d: missing relay suffix "
-                               "in \"relay <dn> [massage]\" line.\n",
-                               fname, lineno );
-                       return 1;
-
-               default:
-                       Log2( LDAP_DEBUG_ANY, LDAP_LEVEL_ERR,
-                               "%s: line %d: extra cruft "
-                               "in \"relay <dn> [massage]\" line.\n",
-                               fname, lineno );
-                       return 1;
-               }
-
-               if ( !BER_BVISNULL( &ri->ri_realsuffix ) ) {
-                       Log2( LDAP_DEBUG_ANY, LDAP_LEVEL_ERR,
-                               "%s: line %d: "
-                               "relay dn already specified.\n",
-                               fname, lineno );
-                       return 1;
-               }
-
-               /* The man page says that the "relay" directive
-                * automatically instantiates slapo-rwm; I don't
-                * like this very much any more, I'd prefer to
-                * have automatic instantiation only when "massage"
-                * is specified, so one has better control on
-                * where the overlay gets instantiated, but this
-                * would break compatibility.  One can still control
-                * where the overlay is instantiated by moving
-                * around the "relay" directive, although this could
-                * make slapd.conf a bit confusing. */
-               if ( overlay_config( be, "rwm", -1, NULL ) ) {
-                       Log2( LDAP_DEBUG_ANY, LDAP_LEVEL_ERR,
-                               "%s: line %d: unable to install "
-                               "rwm overlay "
-                               "in \"relay <dn> [massage]\" line\n",
-                               fname, lineno );
-                       return 1;
-               }
-
-               dn.bv_val = argv[ 1 ];
-               dn.bv_len = strlen( argv[ 1 ] );
-               rc = dnPrettyNormal( NULL, &dn, &pdn, &ndn, NULL );
-               if ( rc != LDAP_SUCCESS ) {
-                       Log3( LDAP_DEBUG_ANY, LDAP_LEVEL_ERR,
-                               "%s: line %d: "
-                               "relay dn \"%s\" is invalid "
-                               "in \"relay <dn> [massage]\" line\n",
-                               fname, lineno, argv[ 1 ] );
-                       return 1;
-               }
-
-               bd = select_backend( &ndn, 0, 1 );
-               if ( bd == NULL ) {
-                       Log3( LDAP_DEBUG_ANY, LDAP_LEVEL_ERR,
-                               "%s: line %d: "
-                               "cannot find database "
-                               "of relay dn \"%s\" "
-                               "in \"relay <dn> [massage]\" line\n",
-                               fname, lineno, argv[ 1 ] );
-                       rc = 1;
-                       goto relay_done;
-
-               } else if ( bd->be_private == be->be_private ) {
-                       Log3( LDAP_DEBUG_ANY, LDAP_LEVEL_ERR,
-                               "%s: line %d: "
-                               "relay dn \"%s\" would call self "
-                               "in \"relay <dn> [massage]\" line\n",
-                               fname, lineno, pdn.bv_val );
-                       rc = 1;
-                       goto relay_done;
-               }
-
-               ri->ri_realsuffix = ndn;
-
-               if ( argc == 3 ) {
-                       char    *cargv[ 4 ];
-
-                       cargv[ 0 ] = "rwm-suffixmassage";
-                       cargv[ 1 ] = be->be_suffix[0].bv_val;
-                       cargv[ 2 ] = pdn.bv_val;
-                       cargv[ 3 ] = NULL;
-
-                       rc = be->be_config( be, fname, lineno, 3, cargv );
-               }
-
-relay_done:;
-               ch_free( pdn.bv_val );
-
-               return rc;
-       }
-
-       /* anything else */
-       return SLAP_CONF_UNKNOWN;
-}
-
index c8219e1e206cd6275a43a4bc572115f88e05b9b1..f5c42410136a530a26c84f399c0b4587f806df25 100644 (file)
 #include <ac/string.h>
 
 #include "slap.h"
+#include "config.h"
 #include "back-relay.h"
 
+static ConfigDriver relay_back_cf;
+
+static ConfigTable relaycfg[] = {
+       { "relay", "relay", 2, 2, 0,
+               ARG_MAGIC|ARG_DN,
+               relay_back_cf, "( OLcfgDbAt:5.1 "
+                       "NAME 'olcRelay' "
+                       "DESC 'Relay DN' "
+                       "SYNTAX OMsDN "
+                       "SINGLE-VALUE )",
+               NULL, NULL },
+       { NULL }
+};
+
+static ConfigOCs relayocs[] = {
+       { "( OLcfgDbOc:5.1 "
+               "NAME 'olcRelayConfig' "
+               "DESC 'Relay backend configuration' "
+               "SUP olcDatabaseConfig "
+               "MAY ( olcRelay "
+               ") )",
+                       Cft_Database, relaycfg},
+       { NULL, 0, NULL }
+};
+
+static int
+relay_back_cf( ConfigArgs *c )
+{
+       relay_back_info *ri = ( relay_back_info * )c->be->be_private;
+       int             rc = 0;
+
+       if ( c->op == SLAP_CONFIG_EMIT ) {
+               if ( ri != NULL && !BER_BVISNULL( &ri->ri_realsuffix ) ) {
+                       value_add_one( &c->rvalue_vals, &ri->ri_realsuffix );
+                       return 0;
+               }
+               return 1;
+
+       } else if ( c->op == LDAP_MOD_DELETE ) {
+               if ( !BER_BVISNULL( &ri->ri_realsuffix ) ) {
+                       ch_free( ri->ri_realsuffix.bv_val );
+                       BER_BVZERO( &ri->ri_realsuffix );
+                       ri->ri_bd = NULL;
+                       return 0;
+               }
+               return 1;
+
+       } else {
+               BackendDB *bd;
+
+               assert( ri != NULL );
+               assert( BER_BVISNULL( &ri->ri_realsuffix ) );
+
+               if ( c->be->be_nsuffix == NULL ) {
+                       snprintf( c->cr_msg, sizeof( c->cr_msg),
+                               "\"relay\" directive "
+                               "must appear after \"suffix\"" );
+                       Log2( LDAP_DEBUG_ANY, LDAP_LEVEL_ERR,
+                               "%s: %s.\n", c->log, c->cr_msg );
+                       rc = 1;
+                       goto relay_done;
+               }
+
+               if ( !BER_BVISNULL( &c->be->be_nsuffix[ 1 ] ) ) {
+                       snprintf( c->cr_msg, sizeof( c->cr_msg),
+                               "relaying of multiple suffix "
+                               "database not supported" );
+                       Log2( LDAP_DEBUG_ANY, LDAP_LEVEL_ERR,
+                               "%s: %s.\n", c->log, c->cr_msg );
+                       rc = 1;
+                       goto relay_done;
+               }
+
+               bd = select_backend( &c->value_ndn, 1 );
+               if ( bd == NULL ) {
+                       snprintf( c->cr_msg, sizeof( c->cr_msg),
+                               "cannot find database "
+                               "of relay dn \"%s\" "
+                               "in \"olcRelay <dn>\"\n",
+                               c->value_dn.bv_val );
+                       Log2( LDAP_DEBUG_ANY, LDAP_LEVEL_ERR,
+                               "%s: %s.\n", c->log, c->cr_msg );
+                       rc = 1;
+                       goto relay_done;
+
+               } else if ( bd->be_private == c->be->be_private ) {
+                       snprintf( c->cr_msg, sizeof( c->cr_msg),
+                               "relay dn \"%s\" would call self "
+                               "in \"relay <dn>\" line\n",
+                               c->value_dn.bv_val );
+                       Log2( LDAP_DEBUG_ANY, LDAP_LEVEL_ERR,
+                               "%s: %s.\n", c->log, c->cr_msg );
+                       rc = 1;
+                       goto relay_done;
+               }
+
+               ri->ri_realsuffix = c->value_ndn;
+               BER_BVZERO( &c->value_ndn );
+
+relay_done:;
+               ch_free( c->value_dn.bv_val );
+               ch_free( c->value_ndn.bv_val );
+       }
+
+       return rc;
+}
+
 int
 relay_back_initialize( BackendInfo *bi )
 {
@@ -36,10 +144,10 @@ relay_back_initialize( BackendInfo *bi )
        bi->bi_destroy = 0;
 
        bi->bi_db_init = relay_back_db_init;
-       bi->bi_db_config = relay_back_db_config;
+       bi->bi_db_config = config_generic_wrapper;
        bi->bi_db_open = relay_back_db_open;
 #if 0
-       bi->bi_db_close =relay_back_db_close;
+       bi->bi_db_close = relay_back_db_close;
 #endif
        bi->bi_db_destroy = relay_back_db_destroy;
 
@@ -65,11 +173,13 @@ relay_back_initialize( BackendInfo *bi )
        bi->bi_connection_init = relay_back_connection_init;
        bi->bi_connection_destroy = relay_back_connection_destroy;
 
-       return 0;
+       bi->bi_cf_ocs = relayocs;
+
+       return config_register_schema( relaycfg, relayocs );
 }
 
 int
-relay_back_db_init( Backend *be )
+relay_back_db_init( Backend *be, ConfigReply *cr)
 {
        relay_back_info         *ri;
 
@@ -84,20 +194,22 @@ relay_back_db_init( Backend *be )
        BER_BVZERO( &ri->ri_realsuffix );
        ri->ri_massage = 0;
 
+       be->be_cf_ocs = be->bd_info->bi_cf_ocs;
+
        be->be_private = (void *)ri;
 
        return 0;
 }
 
 int
-relay_back_db_open( Backend *be )
+relay_back_db_open( Backend *be, ConfigReply *cr )
 {
        relay_back_info         *ri = (relay_back_info *)be->be_private;
 
        assert( ri != NULL );
 
        if ( !BER_BVISNULL( &ri->ri_realsuffix ) ) {
-               ri->ri_bd = select_backend( &ri->ri_realsuffix, 0, 1 );
+               ri->ri_bd = select_backend( &ri->ri_realsuffix, 1 );
 
                /* must be there: it was during config! */
                assert( ri->ri_bd != NULL );
@@ -114,13 +226,13 @@ relay_back_db_open( Backend *be )
 }
 
 int
-relay_back_db_close( Backend *be )
+relay_back_db_close( Backend *be, ConfigReply *cr )
 {
        return 0;
 }
 
 int
-relay_back_db_destroy( Backend *be )
+relay_back_db_destroy( Backend *be, ConfigReply *cr)
 {
        relay_back_info         *ri = (relay_back_info *)be->be_private;
 
index 0c463cc20318fc6d9518fd543dd05d35297dc1aa..0616472458cd3600b2fb7e0bd8104da13ed2d888 100644 (file)
@@ -26,7 +26,7 @@
 #include "back-relay.h"
 
 static int
-relay_back_swap_bd( struct slap_op *op, struct slap_rep *rs )
+relay_back_swap_bd( Operation *op, SlapReply *rs )
 {
        slap_callback   *cb = op->o_callback;
        BackendDB       *be = op->o_bd;
@@ -38,7 +38,7 @@ relay_back_swap_bd( struct slap_op *op, struct slap_rep *rs )
 }
 
 static void
-relay_back_add_cb( slap_callback *cb, struct slap_op *op )
+relay_back_add_cb( slap_callback *cb, Operation *op )
 {
        cb->sc_next = op->o_callback;
        cb->sc_response = relay_back_swap_bd;
@@ -55,15 +55,15 @@ relay_back_add_cb( slap_callback *cb, struct slap_op *op )
  *     any valid error         send as error result
  */
 static BackendDB *
-relay_back_select_backend( struct slap_op *op, struct slap_rep *rs, int err )
+relay_back_select_backend( Operation *op, SlapReply *rs, int err, int dosend )
 {
        relay_back_info         *ri = (relay_back_info *)op->o_bd->be_private;
        BackendDB               *bd = ri->ri_bd;
 
-       if ( bd == NULL ) {
-               bd = select_backend( &op->o_req_ndn, 0, 1 );
+       if ( bd == NULL && !BER_BVISNULL( &op->o_req_ndn ) ) {
+               bd = select_backend( &op->o_req_ndn, 1 );
                if ( bd == op->o_bd ) {
-                       if ( err > LDAP_SUCCESS ) {
+                       if ( err > LDAP_SUCCESS && dosend ) {
                                send_ldap_error( op, rs,
                                                LDAP_UNWILLING_TO_PERFORM, 
                                                "back-relay would call self" );
@@ -74,17 +74,21 @@ relay_back_select_backend( struct slap_op *op, struct slap_rep *rs, int err )
 
        if ( bd == NULL && err > -1 ) {
                if ( default_referral ) {
-                       rs->sr_ref = referral_rewrite( default_referral,
-                               NULL, &op->o_req_dn, LDAP_SCOPE_DEFAULT );
-                       if ( !rs->sr_ref ) {
-                               rs->sr_ref = default_referral;
-                       }
-
                        rs->sr_err = LDAP_REFERRAL;
-                       send_ldap_result( op, rs );
-
-                       if ( rs->sr_ref != default_referral ) {
-                               ber_bvarray_free( rs->sr_ref );
+                       if ( dosend ) {
+                               rs->sr_ref = referral_rewrite(
+                                       default_referral,
+                                       NULL, &op->o_req_dn,
+                                       LDAP_SCOPE_DEFAULT );
+                               if ( !rs->sr_ref ) {
+                                       rs->sr_ref = default_referral;
+                               }
+
+                               send_ldap_result( op, rs );
+
+                               if ( rs->sr_ref != default_referral ) {
+                                       ber_bvarray_free( rs->sr_ref );
+                               }
                        }
 
                } else {
@@ -92,7 +96,9 @@ relay_back_select_backend( struct slap_op *op, struct slap_rep *rs, int err )
                         * LDAP_NO_SUCH_OBJECT for other operations.
                         * noSuchObject cannot be returned by bind */
                        rs->sr_err = err;
-                       send_ldap_result( op, rs );
+                       if ( dosend ) {
+                               send_ldap_result( op, rs );
+                       }
                }
        }
 
@@ -100,12 +106,22 @@ relay_back_select_backend( struct slap_op *op, struct slap_rep *rs, int err )
 }
 
 int
-relay_back_op_bind( struct slap_op *op, struct slap_rep *rs )
+relay_back_op_bind( Operation *op, SlapReply *rs )
 {
        BackendDB               *bd;
        int                     rc = 1;
 
-       bd = relay_back_select_backend( op, rs, LDAP_INVALID_CREDENTIALS );
+       /* allow rootdn as a means to auth without the need to actually
+        * contact the proxied DSA */
+       switch ( be_rootdn_bind( op, rs ) ) {
+       case SLAP_CB_CONTINUE:
+               break;
+
+       default:
+               return rs->sr_err;
+       }
+
+       bd = relay_back_select_backend( op, rs, LDAP_INVALID_CREDENTIALS, 1 );
        if ( bd == NULL ) {
                return rc;
        }
@@ -117,7 +133,7 @@ relay_back_op_bind( struct slap_op *op, struct slap_rep *rs )
                relay_back_add_cb( &cb, op );
 
                op->o_bd = bd;
-               rc = ( bd->be_bind )( op, rs );
+               rc = bd->be_bind( op, rs );
                op->o_bd = be;
 
                if ( op->o_callback == &cb ) {
@@ -134,15 +150,14 @@ relay_back_op_bind( struct slap_op *op, struct slap_rep *rs )
 }
 
 int
-relay_back_op_unbind( struct slap_op *op, struct slap_rep *rs )
+relay_back_op_unbind( Operation *op, SlapReply *rs )
 {
-       relay_back_info         *ri = (relay_back_info *)op->o_bd->be_private;
        BackendDB               *bd;
        int                     rc = 1;
 
-       bd = ri->ri_bd;
+       bd = relay_back_select_backend( op, rs, LDAP_SUCCESS, 0 );
        if ( bd == NULL ) {
-               bd = select_backend( &op->o_req_ndn, 0, 1 );
+               return 1;
        }
 
        if ( bd && bd->be_unbind ) {
@@ -152,7 +167,7 @@ relay_back_op_unbind( struct slap_op *op, struct slap_rep *rs )
                relay_back_add_cb( &cb, op );
 
                op->o_bd = bd;
-               rc = ( bd->be_unbind )( op, rs );
+               rc = bd->be_unbind( op, rs );
                op->o_bd = be;
 
                if ( op->o_callback == &cb ) {
@@ -165,12 +180,12 @@ relay_back_op_unbind( struct slap_op *op, struct slap_rep *rs )
 }
 
 int
-relay_back_op_search( struct slap_op *op, struct slap_rep *rs )
+relay_back_op_search( Operation *op, SlapReply *rs )
 {
        BackendDB               *bd;
        int                     rc = 1;
 
-       bd = relay_back_select_backend( op, rs, LDAP_NO_SUCH_OBJECT );
+       bd = relay_back_select_backend( op, rs, LDAP_NO_SUCH_OBJECT, 1 );
        if ( bd == NULL ) {
                return 1;
        }
@@ -182,7 +197,7 @@ relay_back_op_search( struct slap_op *op, struct slap_rep *rs )
                relay_back_add_cb( &cb, op );
 
                op->o_bd = bd;
-               rc = ( bd->be_search )( op, rs );
+               rc = bd->be_search( op, rs );
                op->o_bd = be;
 
                if ( op->o_callback == &cb ) {
@@ -200,12 +215,12 @@ relay_back_op_search( struct slap_op *op, struct slap_rep *rs )
 }
 
 int
-relay_back_op_compare( struct slap_op *op, struct slap_rep *rs )
+relay_back_op_compare( Operation *op, SlapReply *rs )
 {
        BackendDB               *bd;
        int                     rc = 1;
 
-       bd = relay_back_select_backend( op, rs, LDAP_NO_SUCH_OBJECT );
+       bd = relay_back_select_backend( op, rs, LDAP_NO_SUCH_OBJECT, 1 );
        if ( bd == NULL ) {
                return 1;
        }
@@ -217,7 +232,7 @@ relay_back_op_compare( struct slap_op *op, struct slap_rep *rs )
                relay_back_add_cb( &cb, op );
 
                op->o_bd = bd;
-               rc = ( bd->be_compare )( op, rs );
+               rc = bd->be_compare( op, rs );
                op->o_bd = be;
 
                if ( op->o_callback == &cb ) {
@@ -235,12 +250,12 @@ relay_back_op_compare( struct slap_op *op, struct slap_rep *rs )
 }
 
 int
-relay_back_op_modify( struct slap_op *op, struct slap_rep *rs )
+relay_back_op_modify( Operation *op, SlapReply *rs )
 {
        BackendDB               *bd;
        int                     rc = 1;
 
-       bd = relay_back_select_backend( op, rs, LDAP_NO_SUCH_OBJECT );
+       bd = relay_back_select_backend( op, rs, LDAP_NO_SUCH_OBJECT, 1 );
        if ( bd == NULL ) {
                return 1;
        }
@@ -252,7 +267,7 @@ relay_back_op_modify( struct slap_op *op, struct slap_rep *rs )
                relay_back_add_cb( &cb, op );
 
                op->o_bd = bd;
-               rc = ( bd->be_modify )( op, rs );
+               rc = bd->be_modify( op, rs );
                op->o_bd = be;
 
                if ( op->o_callback == &cb ) {
@@ -270,12 +285,12 @@ relay_back_op_modify( struct slap_op *op, struct slap_rep *rs )
 }
 
 int
-relay_back_op_modrdn( struct slap_op *op, struct slap_rep *rs )
+relay_back_op_modrdn( Operation *op, SlapReply *rs )
 {
        BackendDB               *bd;
        int                     rc = 1;
 
-       bd = relay_back_select_backend( op, rs, LDAP_NO_SUCH_OBJECT );
+       bd = relay_back_select_backend( op, rs, LDAP_NO_SUCH_OBJECT, 1 );
        if ( bd == NULL ) {
                return 1;
        }
@@ -287,7 +302,7 @@ relay_back_op_modrdn( struct slap_op *op, struct slap_rep *rs )
                relay_back_add_cb( &cb, op );
 
                op->o_bd = bd;
-               rc = ( bd->be_modrdn )( op, rs );
+               rc = bd->be_modrdn( op, rs );
                op->o_bd = be;
 
                if ( op->o_callback == &cb ) {
@@ -305,12 +320,12 @@ relay_back_op_modrdn( struct slap_op *op, struct slap_rep *rs )
 }
 
 int
-relay_back_op_add( struct slap_op *op, struct slap_rep *rs )
+relay_back_op_add( Operation *op, SlapReply *rs )
 {
        BackendDB               *bd;
        int                     rc = 1;
 
-       bd = relay_back_select_backend( op, rs, LDAP_NO_SUCH_OBJECT );
+       bd = relay_back_select_backend( op, rs, LDAP_NO_SUCH_OBJECT, 1 );
        if ( bd == NULL ) {
                return 1;
        }
@@ -322,7 +337,7 @@ relay_back_op_add( struct slap_op *op, struct slap_rep *rs )
                relay_back_add_cb( &cb, op );
 
                op->o_bd = bd;
-               rc = ( bd->be_add )( op, rs );
+               rc = bd->be_add( op, rs );
                op->o_bd = be;
 
                if ( op->o_callback == &cb ) {
@@ -340,12 +355,12 @@ relay_back_op_add( struct slap_op *op, struct slap_rep *rs )
 }
 
 int
-relay_back_op_delete( struct slap_op *op, struct slap_rep *rs )
+relay_back_op_delete( Operation *op, SlapReply *rs )
 {
        BackendDB               *bd;
        int                     rc = 1;
 
-       bd = relay_back_select_backend( op, rs, LDAP_NO_SUCH_OBJECT );
+       bd = relay_back_select_backend( op, rs, LDAP_NO_SUCH_OBJECT, 1 );
        if ( bd == NULL ) {
                return 1;
        }
@@ -357,7 +372,7 @@ relay_back_op_delete( struct slap_op *op, struct slap_rep *rs )
                relay_back_add_cb( &cb, op );
 
                op->o_bd = bd;
-               rc = ( bd->be_delete )( op, rs );
+               rc = bd->be_delete( op, rs );
                op->o_bd = be;
 
                if ( op->o_callback == &cb ) {
@@ -370,12 +385,12 @@ relay_back_op_delete( struct slap_op *op, struct slap_rep *rs )
 }
 
 int
-relay_back_op_abandon( struct slap_op *op, struct slap_rep *rs )
+relay_back_op_abandon( Operation *op, SlapReply *rs )
 {
        BackendDB               *bd;
        int                     rc = 1;
 
-       bd = relay_back_select_backend( op, rs, -1 );
+       bd = relay_back_select_backend( op, rs, LDAP_SUCCESS, 0 );
        if ( bd == NULL ) {
                return 1;
        }
@@ -387,7 +402,7 @@ relay_back_op_abandon( struct slap_op *op, struct slap_rep *rs )
                relay_back_add_cb( &cb, op );
 
                op->o_bd = bd;
-               rc = ( bd->be_abandon )( op, rs );
+               rc = bd->be_abandon( op, rs );
                op->o_bd = be;
 
                if ( op->o_callback == &cb ) {
@@ -400,12 +415,12 @@ relay_back_op_abandon( struct slap_op *op, struct slap_rep *rs )
 }
 
 int
-relay_back_op_cancel( struct slap_op *op, struct slap_rep *rs )
+relay_back_op_cancel( Operation *op, SlapReply *rs )
 {
        BackendDB               *bd;
        int                     rc = 1;
 
-       bd = relay_back_select_backend( op, rs, LDAP_NO_SUCH_OBJECT );
+       bd = relay_back_select_backend( op, rs, LDAP_CANNOT_CANCEL, 0 );
        if ( bd == NULL ) {
                return 1;
        }
@@ -417,7 +432,7 @@ relay_back_op_cancel( struct slap_op *op, struct slap_rep *rs )
                relay_back_add_cb( &cb, op );
 
                op->o_bd = bd;
-               rc = ( bd->be_cancel )( op, rs );
+               rc = bd->be_cancel( op, rs );
                op->o_bd = be;
 
                if ( op->o_callback == &cb ) {
@@ -435,12 +450,12 @@ relay_back_op_cancel( struct slap_op *op, struct slap_rep *rs )
 }
 
 int
-relay_back_op_extended( struct slap_op *op, struct slap_rep *rs )
+relay_back_op_extended( Operation *op, SlapReply *rs )
 {
        BackendDB               *bd;
        int                     rc = 1;
 
-       bd = relay_back_select_backend( op, rs, LDAP_NO_SUCH_OBJECT );
+       bd = relay_back_select_backend( op, rs, LDAP_NO_SUCH_OBJECT, 0 );
        if ( bd == NULL ) {
                return 1;
        }
@@ -452,7 +467,7 @@ relay_back_op_extended( struct slap_op *op, struct slap_rep *rs )
                relay_back_add_cb( &cb, op );
 
                op->o_bd = bd;
-               rc = ( bd->be_extended )( op, rs );
+               rc = bd->be_extended( op, rs );
                op->o_bd = be;
 
                if ( op->o_callback == &cb ) {
@@ -470,7 +485,7 @@ relay_back_op_extended( struct slap_op *op, struct slap_rep *rs )
 }
 
 int
-relay_back_entry_release_rw( struct slap_op *op, Entry *e, int rw )
+relay_back_entry_release_rw( Operation *op, Entry *e, int rw )
 {
        relay_back_info         *ri = (relay_back_info *)op->o_bd->be_private;
        BackendDB               *bd;
@@ -478,7 +493,7 @@ relay_back_entry_release_rw( struct slap_op *op, Entry *e, int rw )
 
        bd = ri->ri_bd;
        if ( bd == NULL) {
-               bd = select_backend( &op->o_req_ndn, 0, 1 );
+               bd = select_backend( &op->o_req_ndn, 1 );
                if ( bd == NULL ) {
                        return 1;
                }
@@ -488,7 +503,7 @@ relay_back_entry_release_rw( struct slap_op *op, Entry *e, int rw )
                BackendDB       *be = op->o_bd;
 
                op->o_bd = bd;
-               rc = ( bd->be_release )( op, e, rw );
+               rc = bd->be_release( op, e, rw );
                op->o_bd = be;
        }
 
@@ -497,7 +512,7 @@ relay_back_entry_release_rw( struct slap_op *op, Entry *e, int rw )
 }
 
 int
-relay_back_entry_get_rw( struct slap_op *op, struct berval *ndn,
+relay_back_entry_get_rw( Operation *op, struct berval *ndn,
        ObjectClass *oc, AttributeDescription *at, int rw, Entry **e )
 {
        relay_back_info         *ri = (relay_back_info *)op->o_bd->be_private;
@@ -506,7 +521,7 @@ relay_back_entry_get_rw( struct slap_op *op, struct berval *ndn,
 
        bd = ri->ri_bd;
        if ( bd == NULL) {
-               bd = select_backend( &op->o_req_ndn, 0, 1 );
+               bd = select_backend( &op->o_req_ndn, 1 );
                if ( bd == NULL ) {
                        return 1;
                }
@@ -516,7 +531,7 @@ relay_back_entry_get_rw( struct slap_op *op, struct berval *ndn,
                BackendDB       *be = op->o_bd;
 
                op->o_bd = bd;
-               rc = ( bd->be_fetch )( op, ndn, oc, at, rw, e );
+               rc = bd->be_fetch( op, ndn, oc, at, rw, e );
                op->o_bd = be;
        }
 
@@ -532,12 +547,12 @@ relay_back_entry_get_rw( struct slap_op *op, struct berval *ndn,
  * naming context... mmmh.
  */
 int
-relay_back_chk_referrals( struct slap_op *op, struct slap_rep *rs )
+relay_back_chk_referrals( Operation *op, SlapReply *rs )
 {
        BackendDB               *bd;
        int                     rc = 0;
 
-       bd = relay_back_select_backend( op, rs, LDAP_SUCCESS );
+       bd = relay_back_select_backend( op, rs, LDAP_SUCCESS, 1 );
        /* FIXME: this test only works if there are no overlays, so
         * it is nearly useless; if made stricter, no nested back-relays
         * can be instantiated... too bad. */
@@ -561,7 +576,7 @@ relay_back_chk_referrals( struct slap_op *op, struct slap_rep *rs )
                relay_back_add_cb( &cb, op );
 
                op->o_bd = bd;
-               rc = ( bd->be_chk_referrals )( op, rs );
+               rc = bd->be_chk_referrals( op, rs );
                op->o_bd = be;
 
                if ( op->o_callback == &cb ) {
@@ -574,18 +589,17 @@ relay_back_chk_referrals( struct slap_op *op, struct slap_rep *rs )
 }
 
 int
-relay_back_operational( struct slap_op *op, struct slap_rep *rs )
+relay_back_operational( Operation *op, SlapReply *rs )
 {
-       relay_back_info         *ri = (relay_back_info *)op->o_bd->be_private;
        BackendDB               *bd;
        int                     rc = 1;
 
-       bd = ri->ri_bd;
-       if ( bd == NULL) {
-               bd = select_backend( &op->o_req_ndn, 0, 1 );
-               if ( bd == NULL ) {
-                       return 1;
-               }
+       bd = relay_back_select_backend( op, rs, LDAP_SUCCESS, 0 );
+       /* FIXME: this test only works if there are no overlays, so
+        * it is nearly useless; if made stricter, no nested back-relays
+        * can be instantiated... too bad. */
+       if ( bd == NULL || bd == op->o_bd ) {
+               return 0;
        }
 
        if ( bd->be_operational ) {
@@ -595,7 +609,7 @@ relay_back_operational( struct slap_op *op, struct slap_rep *rs )
                relay_back_add_cb( &cb, op );
 
                op->o_bd = bd;
-               rc = ( bd->be_operational )( op, rs );
+               rc = bd->be_operational( op, rs );
                op->o_bd = be;
 
                if ( op->o_callback == &cb ) {
@@ -608,25 +622,25 @@ relay_back_operational( struct slap_op *op, struct slap_rep *rs )
 }
 
 int
-relay_back_has_subordinates( struct slap_op *op, Entry *e, int *hasSubs )
+relay_back_has_subordinates( Operation *op, Entry *e, int *hasSubs )
 {
-       relay_back_info         *ri = (relay_back_info *)op->o_bd->be_private;
+       SlapReply               rs = { 0 };
        BackendDB               *bd;
        int                     rc = 1;
 
-       bd = ri->ri_bd;
-       if ( bd == NULL) {
-               bd = select_backend( &op->o_req_ndn, 0, 1 );
-               if ( bd == NULL ) {
-                       return 1;
-               }
+       bd = relay_back_select_backend( op, &rs, LDAP_SUCCESS, 0 );
+       /* FIXME: this test only works if there are no overlays, so
+        * it is nearly useless; if made stricter, no nested back-relays
+        * can be instantiated... too bad. */
+       if ( bd == NULL || bd == op->o_bd ) {
+               return 0;
        }
 
        if ( bd->be_has_subordinates ) {
                BackendDB       *be = op->o_bd;
 
                op->o_bd = bd;
-               rc = ( bd->be_has_subordinates )( op, e, hasSubs );
+               rc = bd->be_has_subordinates( op, e, hasSubs );
                op->o_bd = be;
        }
 
@@ -635,7 +649,7 @@ relay_back_has_subordinates( struct slap_op *op, Entry *e, int *hasSubs )
 }
 
 int
-relay_back_connection_init( BackendDB *bd, struct slap_conn *c )
+relay_back_connection_init( BackendDB *bd, Connection *c )
 {
        relay_back_info         *ri = (relay_back_info *)bd->be_private;
 
@@ -645,24 +659,24 @@ relay_back_connection_init( BackendDB *bd, struct slap_conn *c )
        }
 
        if ( bd->be_connection_init ) {
-               return ( bd->be_connection_init )( bd, c );
+               return bd->be_connection_init( bd, c );
        }
 
        return 0;
 }
 
 int
-relay_back_connection_destroy( BackendDB *bd, struct slap_conn *c )
+relay_back_connection_destroy( BackendDB *bd, Connection *c )
 {
        relay_back_info         *ri = (relay_back_info *)bd->be_private;
 
        bd = ri->ri_bd;
-       if ( bd == NULL) {
+       if ( bd == NULL ) {
                return 0;
        }
 
        if ( bd->be_connection_destroy ) {
-               return ( bd->be_connection_destroy )( bd, c );
+               return bd->be_connection_destroy( bd, c );
        }
 
        return 0;
index 97ba1c55642ed7613702db9a4c30698fe9f00017..c3945e3145fffc09d43a715048ff33213af1f5e5 100644 (file)
@@ -27,7 +27,6 @@ LDAP_BEGIN_DECL
 extern BI_init                 relay_back_initialize;
 
 extern BI_db_init              relay_back_db_init;
-extern BI_db_config            relay_back_db_config;
 extern BI_db_open              relay_back_db_open;
 extern BI_db_close             relay_back_db_close;
 extern BI_db_destroy           relay_back_db_destroy;
index 32d8865e3ddd7071330d0a0ee4156e22724d6804..dcbbcd4ba8274e271ea1e4b7e57d15c31ad1c001 100644 (file)
@@ -49,6 +49,16 @@ shell_back_bind(
        FILE                    *rfp, *wfp;
        int                     rc;
 
+       /* allow rootdn as a means to auth without the need to actually
+        * contact the proxied DSA */
+       switch ( be_rootdn_bind( op, rs ) ) {
+       case SLAP_CB_CONTINUE:
+               break;
+
+       default:
+               return rs->sr_err;
+       }
+
        if ( si->si_bind == NULL ) {
                send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
                    "bind not implemented" );
index 5724118e5aa6d28290e2fd48532049bd7a491bcb..db9a91d2c844b465d0de92a8144a2bf536ec664f 100644 (file)
@@ -36,6 +36,8 @@
 
 #include "slap.h"
 
+#include "config.h"
+
 #include "shell.h"
 
 int
@@ -76,7 +78,8 @@ shell_back_initialize(
 
 int
 shell_back_db_init(
-    Backend    *be
+       Backend *be,
+       ConfigReply *cr
 )
 {
        struct shellinfo        *si;
@@ -90,7 +93,8 @@ shell_back_db_init(
 
 int
 shell_back_db_destroy(
-    Backend    *be
+       Backend *be,
+       ConfigReply *cr
 )
 {
        free( be->be_private );
index 277c3c1dcd502fec0ffae5fbfe7a493f5815d84c..d87a9bcccf7db3c8211fb3ec93076b8425ba6dff 100644 (file)
@@ -46,7 +46,7 @@ shell_back_modify(
        Modification *mod;
        struct shellinfo        *si = (struct shellinfo *) op->o_bd->be_private;
        AttributeDescription *entry = slap_schema.si_ad_entry;
-       Modifications *ml  = op->oq_modify.rs_modlist;
+       Modifications *ml  = op->orm_modlist;
        Entry e;
        FILE                    *rfp, *wfp;
        int                     i;
index 15406651732e88c61195d95f166eeb2ddbfbf119..ee4871b06bd0cb78f25b085548681431e1cb901e 100644 (file)
@@ -46,10 +46,6 @@ struct shellinfo {
        char    **si_delete;    /* cmd + args to exec for delete  */
 };
 
-struct slap_backend_db;
-struct slap_conn;
-struct slap_op;
-
 extern pid_t forkandexec LDAP_P((
        char **args,
        FILE **rfp,
@@ -57,11 +53,11 @@ extern pid_t forkandexec LDAP_P((
 
 extern void print_suffixes LDAP_P((
        FILE *fp,
-       struct slap_backend_db *bd));
+       BackendDB *bd));
 
 extern int read_and_send_results LDAP_P((
-       struct slap_op *op,
-       struct slap_rep *rs,
+       Operation *op,
+       SlapReply *rs,
        FILE *fp));
 
 LDAP_END_DECL
index ed10958b67c0df14d452773f34b15eb3a16f2a22..501c8bfd9693e73f8891a3672448753e1b509b52 100644 (file)
@@ -1520,7 +1520,7 @@ done:;
        }
 
        if ( !BER_BVISNULL( &bsi.bsi_base_id.eid_ndn ) ) {
-               (void)backsql_free_entryID( op, &bsi.bsi_base_id, 0 );
+               (void)backsql_free_entryID( &bsi.bsi_base_id, 0, op->o_tmpmemctx );
        }
 
        if ( !BER_BVISNULL( &p.e_nname ) ) {
index f21467914824f30008f4f0698489160391fcf4b3..98d06bc5e6c4f90af31aebc3c40fad82b1a1fb45 100644 (file)
@@ -181,6 +181,7 @@ typedef struct {
        SWORD           ncols;
        BerVarray       col_names;
        UDWORD          *col_prec;
+       SQLSMALLINT     *col_type;
        char            **cols;
        SQLINTEGER      *value_len;
 } BACKSQL_ROW_NTS;
@@ -265,31 +266,6 @@ typedef struct backsql_api {
        struct backsql_api      *ba_next;
 } backsql_api;
 
-/*
- * Entry ID structure
- */
-typedef struct backsql_entryID {
-       /* #define BACKSQL_ARBITRARY_KEY to allow a non-numeric key.
-        * It is required by some special applications that use
-        * strings as keys for the main table.
-        * In this case, #define BACKSQL_MAX_KEY_LEN consistently
-        * with the key size definition */
-#ifdef BACKSQL_ARBITRARY_KEY
-       struct berval           eid_id;
-       struct berval           eid_keyval;
-#define BACKSQL_MAX_KEY_LEN    64
-#else /* ! BACKSQL_ARBITRARY_KEY */
-       /* The original numeric key is maintained as default. */
-       unsigned long           eid_id;
-       unsigned long           eid_keyval;
-#endif /* ! BACKSQL_ARBITRARY_KEY */
-
-       unsigned long           eid_oc_id;
-       struct berval           eid_dn;
-       struct berval           eid_ndn;
-       struct backsql_entryID  *eid_next;
-} backsql_entryID;
-
 #ifdef BACKSQL_ARBITRARY_KEY
 #define BACKSQL_ENTRYID_INIT { BER_BVNULL, BER_BVNULL, 0, BER_BVNULL, BER_BVNULL, NULL }
 #else /* ! BACKSQL_ARBITRARY_KEY */
@@ -330,6 +306,7 @@ typedef struct backsql_oc_map_rec {
 typedef struct backsql_at_map_rec {
        /* Description of corresponding LDAP attribute type */
        AttributeDescription    *bam_ad;
+       AttributeDescription    *bam_true_ad;
        /* ObjectClass if bam_ad is objectClass */
        ObjectClass             *bam_oc;
 
@@ -395,14 +372,43 @@ typedef struct berbuf {
 
 #define BB_NULL                { BER_BVNULL, 0 }
 
+/*
+ * Entry ID structure
+ */
+typedef struct backsql_entryID {
+       /* #define BACKSQL_ARBITRARY_KEY to allow a non-numeric key.
+        * It is required by some special applications that use
+        * strings as keys for the main table.
+        * In this case, #define BACKSQL_MAX_KEY_LEN consistently
+        * with the key size definition */
+#ifdef BACKSQL_ARBITRARY_KEY
+       struct berval           eid_id;
+       struct berval           eid_keyval;
+#define BACKSQL_MAX_KEY_LEN    64
+#else /* ! BACKSQL_ARBITRARY_KEY */
+       /* The original numeric key is maintained as default. */
+       unsigned long           eid_id;
+       unsigned long           eid_keyval;
+#endif /* ! BACKSQL_ARBITRARY_KEY */
+
+       unsigned long           eid_oc_id;
+       backsql_oc_map_rec      *eid_oc;
+       struct berval           eid_dn;
+       struct berval           eid_ndn;
+       struct backsql_entryID  *eid_next;
+} backsql_entryID;
+
 /* the function must collect the entry associated to nbase */
 #define BACKSQL_ISF_GET_ID     0x1U
 #define BACKSQL_ISF_GET_ENTRY  ( 0x2U | BACKSQL_ISF_GET_ID )
-#define BACKSQL_ISF_MATCHED    0x4U
+#define BACKSQL_ISF_GET_OC     ( 0x4U | BACKSQL_ISF_GET_ID )
+#define BACKSQL_ISF_MATCHED    0x8U
 #define BACKSQL_IS_GET_ID(f) \
        ( ( (f) & BACKSQL_ISF_GET_ID ) == BACKSQL_ISF_GET_ID )
 #define BACKSQL_IS_GET_ENTRY(f) \
        ( ( (f) & BACKSQL_ISF_GET_ENTRY ) == BACKSQL_ISF_GET_ENTRY )
+#define BACKSQL_IS_GET_OC(f) \
+       ( ( (f) & BACKSQL_ISF_GET_OC ) == BACKSQL_ISF_GET_OC )
 #define BACKSQL_IS_MATCHED(f) \
        ( ( (f) & BACKSQL_ISF_MATCHED ) == BACKSQL_ISF_MATCHED )
 typedef struct backsql_srch_info {
@@ -471,14 +477,16 @@ typedef struct backsql_info {
         */
        struct berval   sql_subtree_cond;
        struct berval   sql_children_cond;
-       char            *sql_oc_query,
-                       *sql_at_query;
-       char            *sql_insentry_stmt,
-                       *sql_delentry_stmt,
-                       *sql_renentry_stmt,
-                       *sql_delobjclasses_stmt;
+       struct berval   sql_dn_match_cond;
+       char            *sql_oc_query;
+       char            *sql_at_query;
+       char            *sql_insentry_stmt;
+       char            *sql_delentry_stmt;
+       char            *sql_renentry_stmt;
+       char            *sql_delobjclasses_stmt;
        char            *sql_id_query;
        char            *sql_has_children_query;
+       char            *sql_list_children_query;
 
        MatchingRule    *sql_caseIgnoreMatch;
        MatchingRule    *sql_telephoneNumberMatch;
@@ -556,9 +564,10 @@ typedef struct backsql_info {
 #define BACKSQL_BASEOBJECT_OC          0
        
        Avlnode         *sql_db_conns;
+       SQLHDBC         sql_dbh;
+       ldap_pvt_thread_mutex_t         sql_dbconn_mutex;
        Avlnode         *sql_oc_by_oc;
        Avlnode         *sql_oc_by_id;
-       ldap_pvt_thread_mutex_t         sql_dbconn_mutex;
        ldap_pvt_thread_mutex_t         sql_schema_mutex;
        SQLHENV         sql_db_env;
 
@@ -582,5 +591,10 @@ typedef struct backsql_info {
 #define BACKSQL_SANITIZE_ERROR( rc ) \
        ( BACKSQL_LEGAL_ERROR( (rc) ) ? (rc) : LDAP_OTHER )
 
+#define BACKSQL_IS_BINARY(ct) \
+       ( (ct) == SQL_BINARY \
+         || (ct) == SQL_VARBINARY \
+         || (ct) == SQL_LONGVARBINARY)
+
 #endif /* __BACKSQL_H__ */
 
index 7db1ac8e5dbf88dca9b463ec654bf6352c22209f..e76b8dbca6be5b30764ebad2c1afeaf1b2616842 100644 (file)
@@ -40,27 +40,20 @@ backsql_bind( Operation *op, SlapReply *rs )
  
        Debug( LDAP_DEBUG_TRACE, "==>backsql_bind()\n", 0, 0, 0 );
 
-       if ( be_isroot_pw( op ) ) {
-               ber_dupbv( &op->oq_bind.rb_edn, be_root_dn( op->o_bd ) );
-               Debug( LDAP_DEBUG_TRACE, "<==backsql_bind() root bind\n", 
-                               0, 0, 0 );
-               return LDAP_SUCCESS;
-       }
-
-       ber_dupbv( &op->oq_bind.rb_edn, &op->o_req_ndn );
-
-       if ( op->oq_bind.rb_method != LDAP_AUTH_SIMPLE ) {
-               rs->sr_err = LDAP_STRONG_AUTH_NOT_SUPPORTED;
-               rs->sr_text = "authentication method not supported"; 
-               send_ldap_result( op, rs );
+       switch ( be_rootdn_bind( op, rs ) ) {
+       case SLAP_CB_CONTINUE:
+               break;
+
+       default:
+               /* in case of success, front end will send result;
+                * otherwise, be_rootdn_bind() did */
+               Debug( LDAP_DEBUG_TRACE, "<==backsql_bind(%d)\n",
+                       rs->sr_err, 0, 0 );
                return rs->sr_err;
        }
 
-       /*
-        * method = LDAP_AUTH_SIMPLE
-        */
        rs->sr_err = backsql_get_db_conn( op, &dbh );
-       if ( !dbh ) {
+       if ( rs->sr_err != LDAP_SUCCESS ) {
                Debug( LDAP_DEBUG_TRACE, "backsql_bind(): "
                        "could not get connection handle - exiting\n",
                        0, 0, 0 );
@@ -101,7 +94,7 @@ backsql_bind( Operation *op, SlapReply *rs )
 
 error_return:;
        if ( !BER_BVISNULL( &bsi.bsi_base_id.eid_ndn ) ) {
-               (void)backsql_free_entryID( op, &bsi.bsi_base_id, 0 );
+               (void)backsql_free_entryID( &bsi.bsi_base_id, 0, op->o_tmpmemctx );
        }
 
        if ( !BER_BVISNULL( &e.e_nname ) ) {
index 8ac1d96b041612d99fa796ab2ef2348c604bc93c..24fe2e9fb126ffcef5ec54bff196ba34d957e0ef 100644 (file)
@@ -42,7 +42,7 @@ backsql_compare( Operation *op, SlapReply *rs )
        Debug( LDAP_DEBUG_TRACE, "==>backsql_compare()\n", 0, 0, 0 );
 
        rs->sr_err = backsql_get_db_conn( op, &dbh );
-       if ( !dbh ) {
+       if ( rs->sr_err != LDAP_SUCCESS ) {
                Debug( LDAP_DEBUG_TRACE, "backsql_compare(): "
                        "could not get connection handle - exiting\n",
                        0, 0, 0 );
@@ -173,7 +173,7 @@ return_results:;
        }
 
        if ( !BER_BVISNULL( &bsi.bsi_base_id.eid_ndn ) ) {
-               (void)backsql_free_entryID( op, &bsi.bsi_base_id, 0 );
+               (void)backsql_free_entryID( &bsi.bsi_base_id, 0, op->o_tmpmemctx );
        }
 
        if ( !BER_BVISNULL( &e.e_nname ) ) {
index e9857fa760c19ac09c1c3b791d63809a0bc099d4..db1170c884bc6b331ad1d65897ba13ca18de9eaf 100644 (file)
@@ -148,7 +148,20 @@ backsql_db_config(
                }
                ber_str2bv( argv[ 1 ], 0, 1, &bi->sql_children_cond );
                Debug( LDAP_DEBUG_TRACE, "<==backsql_db_config(): "
-                       "subtree_cond=%s\n", bi->sql_children_cond.bv_val, 0, 0 );
+                       "children_cond=%s\n", bi->sql_children_cond.bv_val, 0, 0 );
+
+       } else if ( !strcasecmp( argv[ 0 ], "dn_match_cond" ) ) {
+               if ( argc < 2 ) {
+                       Debug( LDAP_DEBUG_TRACE, 
+                               "<==backsql_db_config (%s line %d): "
+                               "missing SQL condition "
+                               "in \"dn_match_cond\" directive\n",
+                               fname, lineno, 0 );
+                       return 1;
+               }
+               ber_str2bv( argv[ 1 ], 0, 1, &bi->sql_dn_match_cond );
+               Debug( LDAP_DEBUG_TRACE, "<==backsql_db_config(): "
+                       "children_cond=%s\n", bi->sql_dn_match_cond.bv_val, 0, 0 );
 
        } else if ( !strcasecmp( argv[ 0 ], "oc_query" ) ) {
                if ( argc < 2 ) {
index 2bfddfda6cefb22a0ebafe900391aa60c402ae71..c04acb0a8df522ec5ff98486bea581d66d06c37e 100644 (file)
@@ -58,8 +58,7 @@ backsql_delete_all_attrs(
        Operation               *op,
        SlapReply               *rs,
        SQLHDBC                 dbh, 
-       backsql_entryID         *e_id,
-       backsql_oc_map_rec      *oc )
+       backsql_entryID         *eid )
 {
        backsql_delete_attr_t   bda;
        int                     rc;
@@ -67,9 +66,9 @@ backsql_delete_all_attrs(
        bda.op = op;
        bda.rs = rs;
        bda.dbh = dbh;
-       bda.e_id = e_id;
+       bda.e_id = eid;
        
-       rc = avl_apply( oc->bom_attrs, backsql_delete_attr_f, &bda,
+       rc = avl_apply( eid->eid_oc->bom_attrs, backsql_delete_attr_f, &bda,
                        BACKSQL_AVL_STOP, AVL_INORDER );
        if ( rc == BACKSQL_AVL_STOP ) {
                return rs->sr_err;
@@ -78,187 +77,31 @@ backsql_delete_all_attrs(
        return LDAP_SUCCESS;
 }
 
-int
-backsql_delete( Operation *op, SlapReply *rs )
+static int
+backsql_delete_int(
+       Operation       *op,
+       SlapReply       *rs,
+       SQLHDBC         dbh,
+       SQLHSTMT        *sthp,
+       backsql_entryID *eid,
+       Entry           **ep )
 {
        backsql_info            *bi = (backsql_info*)op->o_bd->be_private;
-       SQLHDBC                 dbh = SQL_NULL_HDBC;
        SQLHSTMT                sth = SQL_NULL_HSTMT;
        RETCODE                 rc;
        int                     prc = LDAP_SUCCESS;
-       backsql_oc_map_rec      *oc = NULL;
-       backsql_srch_info       bsi = { 0 };
-       backsql_entryID         e_id = { 0 };
-       Entry                   d = { 0 }, p = { 0 }, *e = NULL;
-       struct berval           pdn = BER_BVNULL;
-       int                     manageDSAit = get_manageDSAit( op );
        /* first parameter no */
        SQLUSMALLINT            pno = 0;
 
-       Debug( LDAP_DEBUG_TRACE, "==>backsql_delete(): deleting entry \"%s\"\n",
-                       op->o_req_ndn.bv_val, 0, 0 );
-
-       rs->sr_err = backsql_get_db_conn( op, &dbh );
-       if ( rs->sr_err != LDAP_SUCCESS ) {
-               Debug( LDAP_DEBUG_TRACE, "   backsql_delete(): "
-                       "could not get connection handle - exiting\n", 
-                       0, 0, 0 );
-               rs->sr_text = ( rs->sr_err == LDAP_OTHER )
-                       ? "SQL-backend error" : NULL;
-               e = NULL;
-               goto done;
-       }
-       
-       /*
-        * Get the entry
-        */
-       bsi.bsi_e = &d;
-       rs->sr_err = backsql_init_search( &bsi, &op->o_req_ndn,
-                       LDAP_SCOPE_BASE, 
-                       (time_t)(-1), NULL, dbh, op, rs, slap_anlist_no_attrs,
-                       ( BACKSQL_ISF_MATCHED | BACKSQL_ISF_GET_ENTRY ) );
-       switch ( rs->sr_err ) {
-       case LDAP_SUCCESS:
-               break;
-
-       case LDAP_REFERRAL:
-               if ( manageDSAit && !BER_BVISNULL( &bsi.bsi_e->e_nname ) &&
-                               dn_match( &op->o_req_ndn, &bsi.bsi_e->e_nname ) )
-               {
-                       rs->sr_err = LDAP_SUCCESS;
-                       rs->sr_text = NULL;
-                       rs->sr_matched = NULL;
-                       if ( rs->sr_ref ) {
-                               ber_bvarray_free( rs->sr_ref );
-                               rs->sr_ref = NULL;
-                       }
-                       break;
-               }
-               e = &d;
-               /* fallthru */
-
-       default:
-               Debug( LDAP_DEBUG_TRACE, "backsql_delete(): "
-                       "could not retrieve deleteDN ID - no such entry\n", 
-                       0, 0, 0 );
-               if ( !BER_BVISNULL( &d.e_nname ) ) {
-                       /* FIXME: should always be true! */
-                       e = &d;
-
-               } else {
-                       e = NULL;
-               }
-               goto done;
-       }
-
-       if ( get_assert( op ) &&
-                       ( test_filter( op, &d, get_assertion( op ) )
-                         != LDAP_COMPARE_TRUE ) )
-       {
-               rs->sr_err = LDAP_ASSERTION_FAILED;
-               e = &d;
-               goto done;
-       }
-
-       if ( !access_allowed( op, &d, slap_schema.si_ad_entry, 
-                       NULL, ACL_WDEL, NULL ) )
-       {
-               Debug( LDAP_DEBUG_TRACE, "   backsql_delete(): "
-                       "no write access to entry\n", 
-                       0, 0, 0 );
-               rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
-               e = &d;
-               goto done;
-       }
-
-       rs->sr_err = backsql_has_children( op, dbh, &op->o_req_ndn );
-       switch ( rs->sr_err ) {
-       case LDAP_COMPARE_FALSE:
-               rs->sr_err = LDAP_SUCCESS;
-               break;
-
-       case LDAP_COMPARE_TRUE:
-               if ( get_treeDelete( op ) ) {
-                       /* not supported yet */ ;
-               }
-               Debug( LDAP_DEBUG_TRACE, "   backsql_delete(): "
-                       "entry \"%s\" has children\n",
-                       op->o_req_dn.bv_val, 0, 0 );
-               rs->sr_err = LDAP_NOT_ALLOWED_ON_NONLEAF;
-               rs->sr_text = "subordinate objects must be deleted first";
-               /* fallthru */
-
-       default:
-               e = &d;
-               goto done;
-       }
-
-       oc = backsql_id2oc( bi, bsi.bsi_base_id.eid_oc_id );
-       if ( oc == NULL ) {
-               Debug( LDAP_DEBUG_TRACE, "   backsql_delete(): "
-                       "cannot determine objectclass of entry -- aborting\n",
-                       0, 0, 0 );
-               rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
-               rs->sr_text = "operation not permitted within namingContext";
-               e = NULL;
-               goto done;
-       }
-
-       if ( oc->bom_delete_proc == NULL ) {
-               Debug( LDAP_DEBUG_TRACE, "   backsql_delete(): "
-                       "delete procedure is not defined "
-                       "for this objectclass - aborting\n", 0, 0, 0 );
-               rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
-               rs->sr_text = "operation not permitted within namingContext";
-               e = NULL;
-               goto done;
-       }
-
-       /*
-        * Get the parent
-        */
-       e_id = bsi.bsi_base_id;
-       if ( !be_issuffix( op->o_bd, &op->o_req_ndn ) ) {
-               dnParent( &op->o_req_ndn, &pdn );
-               bsi.bsi_e = &p;
-               rs->sr_err = backsql_init_search( &bsi, &pdn,
-                               LDAP_SCOPE_BASE, 
-                               (time_t)(-1), NULL, dbh, op, rs,
-                               slap_anlist_no_attrs,
-                               BACKSQL_ISF_GET_ENTRY );
-               if ( rs->sr_err != LDAP_SUCCESS ) {
-                       Debug( LDAP_DEBUG_TRACE, "backsql_delete(): "
-                               "could not retrieve deleteDN ID "
-                               "- no such entry\n", 
-                               0, 0, 0 );
-                       e = &p;
-                       goto done;
-               }
-
-               (void)backsql_free_entryID( op, &bsi.bsi_base_id, 0 );
-
-               /* check parent for "children" acl */
-               if ( !access_allowed( op, &p, slap_schema.si_ad_children, 
-                               NULL, ACL_WDEL, NULL ) )
-               {
-                       Debug( LDAP_DEBUG_TRACE, "   backsql_delete(): "
-                               "no write access to parent\n", 
-                               0, 0, 0 );
-                       rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
-                       e = &p;
-                       goto done;
-
-               }
-       }
+       sth = *sthp;
 
        /* avl_apply ... */
-       rs->sr_err = backsql_delete_all_attrs( op, rs, dbh, &e_id, oc );
+       rs->sr_err = backsql_delete_all_attrs( op, rs, dbh, eid );
        if ( rs->sr_err != LDAP_SUCCESS ) {
-               e = &d;
                goto done;
        }
 
-       rc = backsql_Prepare( dbh, &sth, oc->bom_delete_proc, 0 );
+       rc = backsql_Prepare( dbh, &sth, eid->eid_oc->bom_delete_proc, 0 );
        if ( rc != SQL_SUCCESS ) {
                Debug( LDAP_DEBUG_TRACE,
                        "   backsql_delete(): "
@@ -268,42 +111,42 @@ backsql_delete( Operation *op, SlapReply *rs )
 
                rs->sr_err = LDAP_OTHER;
                rs->sr_text = "SQL-backend error";
-               e = NULL;
+               *ep = NULL;
                goto done;
        }
 
-       if ( BACKSQL_IS_DEL( oc->bom_expect_return ) ) {
+       if ( BACKSQL_IS_DEL( eid->eid_oc->bom_expect_return ) ) {
                pno = 1;
                rc = backsql_BindParamInt( sth, 1, SQL_PARAM_OUTPUT, &prc );
                if ( rc != SQL_SUCCESS ) {
                        Debug( LDAP_DEBUG_TRACE,
                                "   backsql_delete(): "
                                "error binding output parameter for objectClass %s\n",
-                               oc->bom_oc->soc_cname.bv_val, 0, 0 );
+                               eid->eid_oc->bom_oc->soc_cname.bv_val, 0, 0 );
                        backsql_PrintErrors( bi->sql_db_env, dbh, 
                                sth, rc );
                        SQLFreeStmt( sth, SQL_DROP );
 
                        rs->sr_text = "SQL-backend error";
                        rs->sr_err = LDAP_OTHER;
-                       e = NULL;
+                       *ep = NULL;
                        goto done;
                }
        }
 
-       rc = backsql_BindParamID( sth, pno + 1, SQL_PARAM_INPUT, &e_id.eid_keyval );
+       rc = backsql_BindParamID( sth, pno + 1, SQL_PARAM_INPUT, &eid->eid_keyval );
        if ( rc != SQL_SUCCESS ) {
                Debug( LDAP_DEBUG_TRACE,
                        "   backsql_delete(): "
                        "error binding keyval parameter for objectClass %s\n",
-                       oc->bom_oc->soc_cname.bv_val, 0, 0 );
+                       eid->eid_oc->bom_oc->soc_cname.bv_val, 0, 0 );
                backsql_PrintErrors( bi->sql_db_env, dbh, 
                        sth, rc );
                SQLFreeStmt( sth, SQL_DROP );
 
                rs->sr_text = "SQL-backend error";
                rs->sr_err = LDAP_OTHER;
-               e = NULL;
+               *ep = NULL;
                goto done;
        }
 
@@ -328,7 +171,6 @@ backsql_delete( Operation *op, SlapReply *rs )
                        rs->sr_err = LDAP_OTHER;
                }
                SQLFreeStmt( sth, SQL_DROP );
-               e = &d;
                goto done;
        }
        SQLFreeStmt( sth, SQL_DROP );
@@ -344,24 +186,24 @@ backsql_delete( Operation *op, SlapReply *rs )
 
                rs->sr_err = LDAP_OTHER;
                rs->sr_text = "SQL-backend error";
-               e = NULL;
+               *ep = NULL;
                goto done;
        }
 
-       rc = backsql_BindParamID( sth, 1, SQL_PARAM_INPUT, &e_id.eid_id );
+       rc = backsql_BindParamID( sth, 1, SQL_PARAM_INPUT, &eid->eid_id );
        if ( rc != SQL_SUCCESS ) {
                Debug( LDAP_DEBUG_TRACE,
                        "   backsql_delete(): "
                        "error binding auxiliary objectClasses "
                        "entry ID parameter for objectClass %s\n",
-                       oc->bom_oc->soc_cname.bv_val, 0, 0 );
+                       eid->eid_oc->bom_oc->soc_cname.bv_val, 0, 0 );
                backsql_PrintErrors( bi->sql_db_env, dbh, 
                        sth, rc );
                SQLFreeStmt( sth, SQL_DROP );
 
                rs->sr_text = "SQL-backend error";
                rs->sr_err = LDAP_OTHER;
-               e = NULL;
+               *ep = NULL;
                goto done;
        }
 
@@ -381,7 +223,7 @@ backsql_delete( Operation *op, SlapReply *rs )
                SQLFreeStmt( sth, SQL_DROP );
                rs->sr_err = LDAP_OTHER;
                rs->sr_text = "SQL-backend error";
-               e = NULL;
+               *ep = NULL;
                goto done;
        }
        SQLFreeStmt( sth, SQL_DROP );
@@ -397,24 +239,24 @@ backsql_delete( Operation *op, SlapReply *rs )
 
                rs->sr_err = LDAP_OTHER;
                rs->sr_text = "SQL-backend error";
-               e = NULL;
+               *ep = NULL;
                goto done;
        }
 
-       rc = backsql_BindParamID( sth, 1, SQL_PARAM_INPUT, &e_id.eid_id );
+       rc = backsql_BindParamID( sth, 1, SQL_PARAM_INPUT, &eid->eid_id );
        if ( rc != SQL_SUCCESS ) {
                Debug( LDAP_DEBUG_TRACE,
                        "   backsql_delete(): "
                        "error binding entry ID parameter "
                        "for objectClass %s\n",
-                       oc->bom_oc->soc_cname.bv_val, 0, 0 );
+                       eid->eid_oc->bom_oc->soc_cname.bv_val, 0, 0 );
                backsql_PrintErrors( bi->sql_db_env, dbh, 
                        sth, rc );
                SQLFreeStmt( sth, SQL_DROP );
 
                rs->sr_text = "SQL-backend error";
                rs->sr_err = LDAP_OTHER;
-               e = NULL;
+               *ep = NULL;
                goto done;
        }
 
@@ -427,12 +269,319 @@ backsql_delete( Operation *op, SlapReply *rs )
                SQLFreeStmt( sth, SQL_DROP );
                rs->sr_err = LDAP_OTHER;
                rs->sr_text = "SQL-backend error";
-               e = NULL;
+               *ep = NULL;
                goto done;
        }
        SQLFreeStmt( sth, SQL_DROP );
 
        rs->sr_err = LDAP_SUCCESS;
+       *ep = NULL;
+
+done:;
+       *sthp = sth;
+
+       return rs->sr_err;
+}
+
+typedef struct backsql_tree_delete_t {
+       Operation       *btd_op;
+       int             btd_rc;
+       backsql_entryID *btd_eid;
+} backsql_tree_delete_t;
+
+static int
+backsql_tree_delete_search_cb( Operation *op, SlapReply *rs )
+{
+       if ( rs->sr_type == REP_SEARCH ) {
+               backsql_info            *bi = (backsql_info*)op->o_bd->be_private;
+               backsql_tree_delete_t   *btd;
+               backsql_entryID         *eid;
+
+               btd = (backsql_tree_delete_t *)op->o_callback->sc_private;
+
+               if ( !access_allowed( btd->btd_op, rs->sr_entry,
+                       slap_schema.si_ad_entry, NULL, ACL_WDEL, NULL )
+                       || !access_allowed( btd->btd_op, rs->sr_entry,
+                       slap_schema.si_ad_children, NULL, ACL_WDEL, NULL ) )
+               {
+                       btd->btd_rc = LDAP_INSUFFICIENT_ACCESS;
+                       return rs->sr_err = LDAP_UNAVAILABLE;
+               }
+
+               assert( rs->sr_entry != NULL );
+               assert( rs->sr_entry->e_private != NULL );
+
+               eid = (backsql_entryID *)rs->sr_entry->e_private;
+               assert( eid->eid_oc != NULL );
+               if ( eid->eid_oc == NULL || eid->eid_oc->bom_delete_proc == NULL ) {
+                       btd->btd_rc = LDAP_UNWILLING_TO_PERFORM;
+                       return rs->sr_err = LDAP_UNAVAILABLE;
+               }
+
+               eid = backsql_entryID_dup( eid, op->o_tmpmemctx );
+               eid->eid_next = btd->btd_eid;
+               btd->btd_eid = eid;
+       }
+
+       return 0;
+}
+
+static int
+backsql_tree_delete(
+       Operation       *op,
+       SlapReply       *rs,
+       SQLHDBC         dbh,
+       SQLHSTMT        *sthp )
+{
+       Operation               op2 = *op;
+       slap_callback           sc = { 0 };
+       SlapReply               rs2 = { 0 };
+       Filter                  f = { 0 };
+       backsql_tree_delete_t   btd = { 0 };
+
+       int                     rc;
+
+       /*
+        * - perform an internal subtree search as the rootdn
+        * - for each entry
+        *      - check access
+        *      - check objectClass and delete method(s)
+        * - for each entry
+        *      - delete
+        * - if successful, commit
+        */
+
+       op2.o_tag = LDAP_REQ_SEARCH;
+       op2.o_protocol = LDAP_VERSION3;
+
+       btd.btd_op = op;
+       sc.sc_private = &btd;
+       sc.sc_response = backsql_tree_delete_search_cb;
+       op2.o_callback = &sc;
+
+       op2.o_dn = op->o_bd->be_rootdn;
+       op2.o_ndn = op->o_bd->be_rootndn;
+
+       op2.o_managedsait = SLAP_CONTROL_CRITICAL;
+
+       op2.ors_scope = LDAP_SCOPE_SUBTREE;
+       op2.ors_deref = LDAP_DEREF_NEVER;
+       op2.ors_slimit = SLAP_NO_LIMIT;
+       op2.ors_tlimit = SLAP_NO_LIMIT;
+       op2.ors_filter = &f;
+       f.f_choice = LDAP_FILTER_PRESENT;
+       f.f_desc = slap_schema.si_ad_objectClass;
+       BER_BVSTR( &op2.ors_filterstr, "(objectClass=*)" );
+       op2.ors_attrs = slap_anlist_all_attributes;
+       op2.ors_attrsonly = 0;
+
+       rc = op->o_bd->be_search( &op2, &rs2 );
+       if ( rc != LDAP_SUCCESS ) {
+               rc = rs->sr_err = btd.btd_rc;
+               rs->sr_text = "subtree delete not possible";
+               send_ldap_result( op, rs );
+               goto clean;
+       }
+
+       for ( ; btd.btd_eid != NULL;
+               btd.btd_eid = backsql_free_entryID( btd.btd_eid,
+                       1, op->o_tmpmemctx ) )
+       {
+               Entry   *e = (void *)0xbad;
+               rc = backsql_delete_int( op, rs, dbh, sthp, btd.btd_eid, &e );
+               if ( rc != LDAP_SUCCESS ) {
+                       break;
+               }
+       }
+
+clean:;
+       for ( ; btd.btd_eid != NULL;
+               btd.btd_eid = backsql_free_entryID( btd.btd_eid,
+                       1, op->o_tmpmemctx ) )
+               ;
+
+       return rc;
+}
+
+int
+backsql_delete( Operation *op, SlapReply *rs )
+{
+       backsql_info            *bi = (backsql_info*)op->o_bd->be_private;
+       SQLHDBC                 dbh = SQL_NULL_HDBC;
+       SQLHSTMT                sth = SQL_NULL_HSTMT;
+       backsql_oc_map_rec      *oc = NULL;
+       backsql_srch_info       bsi = { 0 };
+       backsql_entryID         e_id = { 0 };
+       Entry                   d = { 0 }, p = { 0 }, *e = NULL;
+       struct berval           pdn = BER_BVNULL;
+       int                     manageDSAit = get_manageDSAit( op );
+
+       Debug( LDAP_DEBUG_TRACE, "==>backsql_delete(): deleting entry \"%s\"\n",
+                       op->o_req_ndn.bv_val, 0, 0 );
+
+       rs->sr_err = backsql_get_db_conn( op, &dbh );
+       if ( rs->sr_err != LDAP_SUCCESS ) {
+               Debug( LDAP_DEBUG_TRACE, "   backsql_delete(): "
+                       "could not get connection handle - exiting\n", 
+                       0, 0, 0 );
+               rs->sr_text = ( rs->sr_err == LDAP_OTHER )
+                       ? "SQL-backend error" : NULL;
+               e = NULL;
+               goto done;
+       }
+
+       /*
+        * Get the entry
+        */
+       bsi.bsi_e = &d;
+       rs->sr_err = backsql_init_search( &bsi, &op->o_req_ndn,
+                       LDAP_SCOPE_BASE, 
+                       (time_t)(-1), NULL, dbh, op, rs, slap_anlist_no_attrs,
+                       ( BACKSQL_ISF_MATCHED | BACKSQL_ISF_GET_ENTRY | BACKSQL_ISF_GET_OC ) );
+       switch ( rs->sr_err ) {
+       case LDAP_SUCCESS:
+               break;
+
+       case LDAP_REFERRAL:
+               if ( manageDSAit && !BER_BVISNULL( &bsi.bsi_e->e_nname ) &&
+                               dn_match( &op->o_req_ndn, &bsi.bsi_e->e_nname ) )
+               {
+                       rs->sr_err = LDAP_SUCCESS;
+                       rs->sr_text = NULL;
+                       rs->sr_matched = NULL;
+                       if ( rs->sr_ref ) {
+                               ber_bvarray_free( rs->sr_ref );
+                               rs->sr_ref = NULL;
+                       }
+                       break;
+               }
+               e = &d;
+               /* fallthru */
+
+       default:
+               Debug( LDAP_DEBUG_TRACE, "backsql_delete(): "
+                       "could not retrieve deleteDN ID - no such entry\n", 
+                       0, 0, 0 );
+               if ( !BER_BVISNULL( &d.e_nname ) ) {
+                       /* FIXME: should always be true! */
+                       e = &d;
+
+               } else {
+                       e = NULL;
+               }
+               goto done;
+       }
+
+       if ( get_assert( op ) &&
+                       ( test_filter( op, &d, get_assertion( op ) )
+                         != LDAP_COMPARE_TRUE ) )
+       {
+               rs->sr_err = LDAP_ASSERTION_FAILED;
+               e = &d;
+               goto done;
+       }
+
+       if ( !access_allowed( op, &d, slap_schema.si_ad_entry, 
+                       NULL, ACL_WDEL, NULL ) )
+       {
+               Debug( LDAP_DEBUG_TRACE, "   backsql_delete(): "
+                       "no write access to entry\n", 
+                       0, 0, 0 );
+               rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
+               e = &d;
+               goto done;
+       }
+
+       rs->sr_err = backsql_has_children( op, dbh, &op->o_req_ndn );
+       switch ( rs->sr_err ) {
+       case LDAP_COMPARE_FALSE:
+               rs->sr_err = LDAP_SUCCESS;
+               break;
+
+       case LDAP_COMPARE_TRUE:
+#ifdef SLAP_CONTROL_X_TREE_DELETE
+               if ( get_treeDelete( op ) ) {
+                       rs->sr_err = LDAP_SUCCESS;
+                       break;
+               }
+#endif /* SLAP_CONTROL_X_TREE_DELETE */
+
+               Debug( LDAP_DEBUG_TRACE, "   backsql_delete(): "
+                       "entry \"%s\" has children\n",
+                       op->o_req_dn.bv_val, 0, 0 );
+               rs->sr_err = LDAP_NOT_ALLOWED_ON_NONLEAF;
+               rs->sr_text = "subordinate objects must be deleted first";
+               /* fallthru */
+
+       default:
+               e = &d;
+               goto done;
+       }
+
+       assert( bsi.bsi_base_id.eid_oc != NULL );
+       oc = bsi.bsi_base_id.eid_oc;
+       if ( oc->bom_delete_proc == NULL ) {
+               Debug( LDAP_DEBUG_TRACE, "   backsql_delete(): "
+                       "delete procedure is not defined "
+                       "for this objectclass - aborting\n", 0, 0, 0 );
+               rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
+               rs->sr_text = "operation not permitted within namingContext";
+               e = NULL;
+               goto done;
+       }
+
+       /*
+        * Get the parent
+        */
+       e_id = bsi.bsi_base_id;
+       memset( &bsi.bsi_base_id, 0, sizeof( bsi.bsi_base_id ) );
+       if ( !be_issuffix( op->o_bd, &op->o_req_ndn ) ) {
+               dnParent( &op->o_req_ndn, &pdn );
+               bsi.bsi_e = &p;
+               rs->sr_err = backsql_init_search( &bsi, &pdn,
+                               LDAP_SCOPE_BASE, 
+                               (time_t)(-1), NULL, dbh, op, rs,
+                               slap_anlist_no_attrs,
+                               BACKSQL_ISF_GET_ENTRY );
+               if ( rs->sr_err != LDAP_SUCCESS ) {
+                       Debug( LDAP_DEBUG_TRACE, "backsql_delete(): "
+                               "could not retrieve deleteDN ID "
+                               "- no such entry\n", 
+                               0, 0, 0 );
+                       e = &p;
+                       goto done;
+               }
+
+               (void)backsql_free_entryID( &bsi.bsi_base_id, 0, op->o_tmpmemctx );
+
+               /* check parent for "children" acl */
+               if ( !access_allowed( op, &p, slap_schema.si_ad_children, 
+                               NULL, ACL_WDEL, NULL ) )
+               {
+                       Debug( LDAP_DEBUG_TRACE, "   backsql_delete(): "
+                               "no write access to parent\n", 
+                               0, 0, 0 );
+                       rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
+                       e = &p;
+                       goto done;
+
+               }
+       }
+
+       e = &d;
+#ifdef SLAP_CONTROL_X_TREE_DELETE
+       if ( get_treeDelete( op ) ) {
+               backsql_tree_delete( op, rs, dbh, &sth );
+               if ( rs->sr_err == LDAP_OTHER || rs->sr_err == LDAP_SUCCESS )
+               {
+                       e = NULL;
+               }
+
+       } else
+#endif /* SLAP_CONTROL_X_TREE_DELETE */
+       {
+               backsql_delete_int( op, rs, dbh, &sth, &e_id, &e );
+       }
 
        /*
         * Commit only if all operations succeed
@@ -472,7 +621,7 @@ done:;
        Debug( LDAP_DEBUG_TRACE, "<==backsql_delete()\n", 0, 0, 0 );
 
        if ( !BER_BVISNULL( &e_id.eid_ndn ) ) {
-               (void)backsql_free_entryID( op, &e_id, 0 );
+               (void)backsql_free_entryID( &e_id, 0, op->o_tmpmemctx );
        }
 
        if ( !BER_BVISNULL( &d.e_nname ) ) {
index 39122f2c1064125963e8bd2537d2e29ef3bfe4d4..78f1da14459b6ece37edc0d7eb604450871ab09f 100644 (file)
@@ -36,7 +36,36 @@ struct berval backsql_baseObject_bv = BER_BVC( BACKSQL_BASEOBJECT_IDSTR );
 #endif /* BACKSQL_ARBITRARY_KEY */
 
 backsql_entryID *
-backsql_free_entryID( Operation *op, backsql_entryID *id, int freeit )
+backsql_entryID_dup( backsql_entryID *src, void *ctx )
+{
+       backsql_entryID *dst;
+
+       if ( src == NULL ) return NULL;
+
+       dst = slap_sl_calloc( 1, sizeof( backsql_entryID ), ctx );
+       ber_dupbv_x( &dst->eid_ndn, &src->eid_ndn, ctx );
+       if ( src->eid_dn.bv_val == src->eid_ndn.bv_val ) {
+               dst->eid_dn = dst->eid_ndn;
+       } else {
+               ber_dupbv_x( &dst->eid_dn, &src->eid_dn, ctx );
+       }
+
+#ifdef BACKSQL_ARBITRARY_KEY
+       ber_dupbv_x( &dst->eid_id, &src->eid_id, ctx );
+       ber_dupbv_x( &dst->eid_keyval, &src->eid_keyval, ctx );
+#else /* ! BACKSQL_ARBITRARY_KEY */
+       dst->eid_id = src->eid_id;
+       dst->eid_keyval = src->eid_keyval;
+#endif /* ! BACKSQL_ARBITRARY_KEY */
+
+       dst->eid_oc = src->eid_oc;
+       dst->eid_oc_id = src->eid_oc_id;
+
+       return dst;
+}
+
+backsql_entryID *
+backsql_free_entryID( backsql_entryID *id, int freeit, void *ctx )
 {
        backsql_entryID         *next;
 
@@ -48,28 +77,28 @@ backsql_free_entryID( Operation *op, backsql_entryID *id, int freeit )
                if ( !BER_BVISNULL( &id->eid_dn )
                                && id->eid_dn.bv_val != id->eid_ndn.bv_val )
                {
-                       op->o_tmpfree( id->eid_dn.bv_val, op->o_tmpmemctx );
+                       slap_sl_free( id->eid_dn.bv_val, ctx );
                        BER_BVZERO( &id->eid_dn );
                }
 
-               op->o_tmpfree( id->eid_ndn.bv_val, op->o_tmpmemctx );
+               slap_sl_free( id->eid_ndn.bv_val, ctx );
                BER_BVZERO( &id->eid_ndn );
        }
 
 #ifdef BACKSQL_ARBITRARY_KEY
        if ( !BER_BVISNULL( &id->eid_id ) ) {
-               op->o_tmpfree( id->eid_id.bv_val, op->o_tmpmemctx );
+               slap_sl_free( id->eid_id.bv_val, ctx );
                BER_BVZERO( &id->eid_id );
        }
 
        if ( !BER_BVISNULL( &id->eid_keyval ) ) {
-               op->o_tmpfree( id->eid_keyval.bv_val, op->o_tmpmemctx );
+               slap_sl_free( id->eid_keyval.bv_val, ctx );
                BER_BVZERO( &id->eid_keyval );
        }
 #endif /* BACKSQL_ARBITRARY_KEY */
 
        if ( freeit ) {
-               op->o_tmpfree( id, op->o_tmpmemctx );
+               slap_sl_free( id, ctx );
        }
 
        return next;
@@ -291,7 +320,7 @@ backsql_dn2id(
                                        ldap_err2string( res ) );
 
                                /* cleanup... */
-                               (void)backsql_free_entryID( op, id, 0 );
+                               (void)backsql_free_entryID( id, 0, op->o_tmpmemctx );
                        }
 
                        if ( dn.bv_val != row.cols[ 3 ] ) {
@@ -516,8 +545,8 @@ backsql_get_attr_vals( void *v_at, void *v_bsi )
 #endif /* ! BACKSQL_ARBITRARY_KEY */
 
 #ifdef BACKSQL_PRETTY_VALIDATE
-       validate = at->bam_ad->ad_type->sat_syntax->ssyn_validate;
-       pretty =  at->bam_ad->ad_type->sat_syntax->ssyn_pretty;
+       validate = at->bam_true_ad->ad_type->sat_syntax->ssyn_validate;
+       pretty =  at->bam_true_ad->ad_type->sat_syntax->ssyn_pretty;
 
        if ( validate == NULL && pretty == NULL ) {
                return 1;
@@ -525,8 +554,8 @@ backsql_get_attr_vals( void *v_at, void *v_bsi )
 #endif /* BACKSQL_PRETTY_VALIDATE */
 
 #ifdef BACKSQL_COUNTQUERY
-       if ( at->bam_ad->ad_type->sat_equality ) {
-               normfunc = at->bam_ad->ad_type->sat_equality->smr_normalize;
+       if ( at->bam_true_ad->ad_type->sat_equality ) {
+               normfunc = at->bam_true_ad->ad_type->sat_equality->smr_normalize;
        }
 
        /* Count how many rows will be returned. This avoids memory 
@@ -583,7 +612,7 @@ backsql_get_attr_vals( void *v_at, void *v_bsi )
                return 1;
        }
 
-       attr = attr_find( bsi->bsi_e->e_attrs, at->bam_ad );
+       attr = attr_find( bsi->bsi_e->e_attrs, at->bam_true_ad );
        if ( attr != NULL ) {
                BerVarray       tmp;
 
@@ -615,7 +644,7 @@ backsql_get_attr_vals( void *v_at, void *v_bsi )
                append = 1;
 
                /* Make space for the array of values */
-               attr = attr_alloc( at->bam_ad );
+               attr = attr_alloc( at->bam_true_ad );
                attr->a_vals = ch_calloc( count + 1, sizeof( struct berval ) );
                if ( attr->a_vals == NULL ) {
                        Debug( LDAP_DEBUG_TRACE, "Out of memory!\n", 0,0,0 );
@@ -735,22 +764,38 @@ backsql_get_attr_vals( void *v_at, void *v_bsi )
                                }
 #endif /* BACKSQL_TRACE */
 
-                               /*
-                                * FIXME: what if a binary 
-                                * is fetched?
+                               /* ITS#3386, ITS#3113 - 20070308
+                                * If a binary is fetched?
+                                * must use the actual size read
+                                * from the database.
                                 */
-                               ber_str2bv( row.cols[ i ], 0, 0, &bv );
+                               if ( BACKSQL_IS_BINARY( row.col_type[ i ] ) ) {
+#ifdef BACKSQL_TRACE
+                                       Debug( LDAP_DEBUG_ANY,
+                                               "==>backsql_get_attr_vals(\"%s\"): "
+                                               "column name %s: data is binary; "
+                                               "using database size %ld\n",
+                                               bsi->bsi_e->e_name.bv_val,
+                                               ad->ad_cname.bv_val,
+                                               row.value_len[ i ] );
+#endif /* BACKSQL_TRACE */
+                                       bv.bv_val = row.cols[ i ];
+                                       bv.bv_len = row.value_len[ i ];
+
+                               } else {
+                                       ber_str2bv( row.cols[ i ], 0, 0, &bv );
+                               }
 
 #ifdef BACKSQL_PRETTY_VALIDATE
                                if ( pretty ) {
                                        struct berval   pbv;
 
-                                       retval = pretty( at->bam_ad->ad_type->sat_syntax,
+                                       retval = pretty( at->bam_true_ad->ad_type->sat_syntax,
                                                &bv, &pbv, bsi->bsi_op->o_tmpmemctx );
                                        bv = pbv;
 
                                } else {
-                                       retval = validate( at->bam_ad->ad_type->sat_syntax,
+                                       retval = validate( at->bam_true_ad->ad_type->sat_syntax,
                                                &bv );
                                }
 
@@ -776,7 +821,7 @@ backsql_get_attr_vals( void *v_at, void *v_bsi )
 
 #ifndef BACKSQL_COUNTQUERY
                                (void)backsql_entry_addattr( bsi->bsi_e, 
-                                               at->bam_ad, &bv,
+                                               at->bam_true_ad, &bv,
                                                bsi->bsi_op->o_tmpmemctx );
 
 #else /* BACKSQL_COUNTQUERY */
@@ -784,8 +829,8 @@ backsql_get_attr_vals( void *v_at, void *v_bsi )
                                        struct berval   nbv;
 
                                        retval = (*normfunc)( SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
-                                               at->bam_ad->ad_type->sat_syntax,
-                                               at->bam_ad->ad_type->sat_equality,
+                                               at->bam_true_ad->ad_type->sat_syntax,
+                                               at->bam_true_ad->ad_type->sat_equality,
                                                &bv, &nbv,
                                                bsi->bsi_op->o_tmpmemctx );
 
@@ -909,8 +954,11 @@ backsql_id2entry( backsql_srch_info *bsi, backsql_entryID *eid )
        bsi->bsi_e->e_attrs = NULL;
        bsi->bsi_e->e_private = NULL;
 
-       bsi->bsi_oc = backsql_id2oc( bsi->bsi_op->o_bd->be_private,
+       if ( eid->eid_oc == NULL ) {
+               eid->eid_oc = backsql_id2oc( bsi->bsi_op->o_bd->be_private,
                        eid->eid_oc_id );
+       }
+       bsi->bsi_oc = eid->eid_oc;
        bsi->bsi_c_eid = eid;
 
 #ifndef BACKSQL_ARBITRARY_KEY  
@@ -999,12 +1047,13 @@ next:;
                        || an_find( bsi->bsi_attrs, &AllOper )
                        || an_find( bsi->bsi_attrs, &slap_schema.si_ad_structuralObjectClass->ad_cname ) )
        {
+               ObjectClass     *soc = NULL;
+
                if ( BACKSQL_CHECK_SCHEMA( bi ) ) {
                        Attribute       *a;
                        const char      *text = NULL;
                        char            textbuf[ 1024 ];
                        size_t          textlen = sizeof( textbuf );
-                       ObjectClass     *soc = NULL;
                        struct berval   bv[ 2 ],
                                        *nvals;
                        int             rc = LDAP_SUCCESS;
@@ -1032,20 +1081,32 @@ next:;
                        }
 
                        if ( !bvmatch( &soc->soc_cname, &bsi->bsi_oc->bom_oc->soc_cname ) ) {
+                               if ( !is_object_subclass( bsi->bsi_oc->bom_oc, soc ) ) {
+                                       Debug( LDAP_DEBUG_TRACE, "backsql_id2entry(%s): "
+                                               "computed structuralObjectClass %s "
+                                               "does not match objectClass %s associated "
+                                               "to entry\n",
+                                               bsi->bsi_e->e_name.bv_val, soc->soc_cname.bv_val,
+                                               bsi->bsi_oc->bom_oc->soc_cname.bv_val );
+                                       backsql_entry_clean( op, bsi->bsi_e );
+                                       return rc;
+                               }
+
                                Debug( LDAP_DEBUG_TRACE, "backsql_id2entry(%s): "
                                        "computed structuralObjectClass %s "
-                                       "does not match objectClass %s associated "
+                                       "is subclass of objectClass %s associated "
                                        "to entry\n",
                                        bsi->bsi_e->e_name.bv_val, soc->soc_cname.bv_val,
                                        bsi->bsi_oc->bom_oc->soc_cname.bv_val );
-                               backsql_entry_clean( op, bsi->bsi_e );
-                               return rc;
                        }
+
+               } else {
+                       soc = bsi->bsi_oc->bom_oc;
                }
 
                rc = attr_merge_normalize_one( bsi->bsi_e,
                                slap_schema.si_ad_structuralObjectClass,
-                               &bsi->bsi_oc->bom_oc->soc_cname,
+                               &soc->soc_cname,
                                bsi->bsi_op->o_tmpmemctx );
                if ( rc != LDAP_SUCCESS ) {
                        backsql_entry_clean( op, bsi->bsi_e );
index df67a50006319876b2b04e3000cfc8486e74d4bf..0f9dc65c22b6007cf5de10126cd9622fbf65290f 100644 (file)
@@ -27,6 +27,7 @@
 #include "ac/string.h"
 
 #include "slap.h"
+#include "config.h"
 #include "proto-sql.h"
 
 int
@@ -37,9 +38,10 @@ sql_back_initialize(
                LDAP_CONTROL_ASSERT,
                LDAP_CONTROL_MANAGEDSAIT,
                LDAP_CONTROL_NOOP,
-#if 0 /* SLAP_CONTROL_X_TREE_DELETE */
+#ifdef SLAP_CONTROL_X_TREE_DELETE
                SLAP_CONTROL_X_TREE_DELETE,
 #endif /* SLAP_CONTROL_X_TREE_DELETE */
+               LDAP_CONTROL_PAGEDRESULTS,
                NULL
        };
 
@@ -75,7 +77,6 @@ sql_back_initialize(
        bi->bi_entry_release_rw = backsql_entry_release;
  
        bi->bi_connection_init = 0;
-       bi->bi_connection_destroy = backsql_connection_destroy;
 
        Debug( LDAP_DEBUG_TRACE,"<==sql_back_initialize()\n", 0, 0, 0 );
        return 0;
@@ -92,7 +93,8 @@ backsql_destroy(
 
 int
 backsql_db_init(
-       BackendDB       *bd )
+       BackendDB       *bd,
+       ConfigReply     *cr )
 {
        backsql_info    *bi;
        int             rc = 0;
@@ -116,19 +118,16 @@ backsql_db_init(
 
 int
 backsql_db_destroy(
-       BackendDB       *bd )
+       BackendDB       *bd,
+       ConfigReply     *cr )
 {
        backsql_info    *bi = (backsql_info*)bd->be_private;
  
        Debug( LDAP_DEBUG_TRACE, "==>backsql_db_destroy()\n", 0, 0, 0 );
 
-       ldap_pvt_thread_mutex_lock( &bi->sql_dbconn_mutex );
        backsql_free_db_env( bi );
-       ldap_pvt_thread_mutex_unlock( &bi->sql_dbconn_mutex );
        ldap_pvt_thread_mutex_destroy( &bi->sql_dbconn_mutex );
-       ldap_pvt_thread_mutex_lock( &bi->sql_schema_mutex );
        backsql_destroy_schema_map( bi );
-       ldap_pvt_thread_mutex_unlock( &bi->sql_schema_mutex );
        ldap_pvt_thread_mutex_destroy( &bi->sql_schema_mutex );
 
        if ( bi->sql_dbname ) {
@@ -157,6 +156,9 @@ backsql_db_destroy(
        if ( !BER_BVISNULL( &bi->sql_children_cond ) ) {
                ch_free( bi->sql_children_cond.bv_val );
        }
+       if ( !BER_BVISNULL( &bi->sql_dn_match_cond ) ) {
+               ch_free( bi->sql_dn_match_cond.bv_val );
+       }
        if ( !BER_BVISNULL( &bi->sql_subtree_cond ) ) {
                ch_free( bi->sql_subtree_cond.bv_val );
        }
@@ -216,15 +218,18 @@ backsql_db_destroy(
 
 int
 backsql_db_open(
-       BackendDB       *bd )
+       BackendDB       *bd,
+       ConfigReply     *cr )
 {
        backsql_info    *bi = (backsql_info*)bd->be_private;
-       SQLHDBC         dbh = SQL_NULL_HDBC;
        struct berbuf   bb = BB_NULL;
 
-       OperationBuffer opbuf;
-       Operation*      op = (Operation *) &opbuf;
-       
+       Connection      conn = { 0 };
+       OperationBuffer opbuf;
+       Operation*      op;
+       SQLHDBC         dbh = SQL_NULL_HDBC;
+       void            *thrctx = ldap_pvt_thread_pool_context();
+
        Debug( LDAP_DEBUG_TRACE, "==>backsql_db_open(): "
                "testing RDBMS connection\n", 0, 0, 0 );
        if ( bi->sql_dbname == NULL ) {
@@ -315,18 +320,20 @@ backsql_db_open(
                };
                struct berbuf   bb = BB_NULL;
 
+               Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
+                       "subtree search SQL condition not specified "
+                       "(use \"subtree_cond\" directive in slapd.conf); "
+                       "preparing default\n", 
+                       0, 0, 0);
+
                if ( backsql_prepare_pattern( bi->sql_concat_func, values, 
                                &concat ) ) {
                        Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
-                               "unable to prepare CONCAT pattern", 0, 0, 0 );
+                               "unable to prepare CONCAT pattern for subtree search",
+                               0, 0, 0 );
                        return 1;
                }
                        
-               Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
-                       "subtree search SQL condition not specified "
-                       "(use \"subtree_cond\" directive in slapd.conf)\n", 
-                       0, 0, 0);
-
                if ( bi->sql_upper_func.bv_val ) {
 
                        /*
@@ -358,42 +365,112 @@ backsql_db_open(
                bi->sql_subtree_cond = bb.bb_val;
                        
                Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
-                       "setting \"%s\" as default\n",
+                       "setting \"%s\" as default \"subtree_cond\"\n",
                        bi->sql_subtree_cond.bv_val, 0, 0 );
        }
 
        if ( bi->sql_children_cond.bv_val == NULL ) {
+               /*
+                * Prepare concat function for children search condition
+                */
+               struct berval   concat;
+               struct berval   values[] = {
+                       BER_BVC( "'%,'" ),
+                       BER_BVC( "?" ),
+                       BER_BVNULL
+               };
                struct berbuf   bb = BB_NULL;
 
+               Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
+                       "children search SQL condition not specified "
+                       "(use \"children_cond\" directive in slapd.conf); "
+                       "preparing default\n", 
+                       0, 0, 0);
+
+               if ( backsql_prepare_pattern( bi->sql_concat_func, values, 
+                               &concat ) ) {
+                       Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
+                               "unable to prepare CONCAT pattern for children search", 0, 0, 0 );
+                       return 1;
+               }
+                       
                if ( bi->sql_upper_func.bv_val ) {
 
                        /*
                         * UPPER(ldap_entries.dn) LIKE UPPER(CONCAT('%,',?))
                         */
 
-                       backsql_strfcat_x( &bb, NULL, "blbl",
+                       backsql_strfcat_x( &bb, NULL, "blbbb",
+                                       &bi->sql_upper_func,
+                                       (ber_len_t)STRLENOF( "(ldap_entries.dn) LIKE " ),
+                                               "(ldap_entries.dn) LIKE ",
+                                       &bi->sql_upper_func_open,
+                                       &concat,
+                                       &bi->sql_upper_func_close );
+
+               } else {
+
+                       /*
+                        * ldap_entries.dn LIKE CONCAT('%,',?)
+                        */
+
+                       backsql_strfcat_x( &bb, NULL, "lb",
+                                       (ber_len_t)STRLENOF( "ldap_entries.dn LIKE " ),
+                                               "ldap_entries.dn LIKE ",
+                                       &concat );
+               }
+
+               ch_free( concat.bv_val );
+
+               bi->sql_children_cond = bb.bb_val;
+                       
+               Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
+                       "setting \"%s\" as default \"children_cond\"\n",
+                       bi->sql_children_cond.bv_val, 0, 0 );
+       }
+
+       if ( bi->sql_dn_match_cond.bv_val == NULL ) {
+               /*
+                * Prepare concat function for dn match search condition
+                */
+               struct berbuf   bb = BB_NULL;
+
+               Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
+                       "DN match search SQL condition not specified "
+                       "(use \"dn_match_cond\" directive in slapd.conf); "
+                       "preparing default\n", 
+                       0, 0, 0);
+
+               if ( bi->sql_upper_func.bv_val ) {
+
+                       /*
+                        * UPPER(ldap_entries.dn)=?
+                        */
+
+                       backsql_strfcat_x( &bb, NULL, "blbcb",
                                        &bi->sql_upper_func,
                                        (ber_len_t)STRLENOF( "(ldap_entries.dn)=" ),
                                                "(ldap_entries.dn)=",
-                                       &bi->sql_upper_func,
-                                       (ber_len_t)STRLENOF( "(?)" ), "(?)" );
+                                       &bi->sql_upper_func_open,
+                                       '?',
+                                       &bi->sql_upper_func_close );
 
                } else {
 
                        /*
-                        * ldap_entries.dn LIKE CONCAT('%,',?)
+                        * ldap_entries.dn=?
                         */
 
                        backsql_strfcat_x( &bb, NULL, "l",
                                        (ber_len_t)STRLENOF( "ldap_entries.dn=?" ),
-                                               "ldap_entries.dn=?");
+                                               "ldap_entries.dn=?" );
                }
 
-               bi->sql_children_cond = bb.bb_val;
+               bi->sql_dn_match_cond = bb.bb_val;
                        
                Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
-                       "setting \"%s\" as default\n",
-                       bi->sql_children_cond.bv_val, 0, 0 );
+                       "setting \"%s\" as default \"dn_match_cond\"\n",
+                       bi->sql_dn_match_cond.bv_val, 0, 0 );
        }
 
        if ( bi->sql_oc_query == NULL ) {
@@ -469,16 +546,20 @@ backsql_db_open(
        }
 
        /* This should just be to force schema loading */
-       op->o_hdr = (Opheader *)&op[ 1 ];
-       op->o_connid = (unsigned long)(-1);
+       connection_fake_init( &conn, &opbuf, thrctx );
+       op = &opbuf.ob_op;
        op->o_bd = bd;
        if ( backsql_get_db_conn( op, &dbh ) != LDAP_SUCCESS ) {
                Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
                        "connection failed, exiting\n", 0, 0, 0 );
                return 1;
        }
-
-       if ( backsql_free_db_conn( op ) != SQL_SUCCESS ) {
+       if ( backsql_load_schema_map( bi, dbh ) != LDAP_SUCCESS ) {
+               Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
+                       "schema mapping failed, exiting\n", 0, 0, 0 );
+               return 1;
+       }
+       if ( backsql_free_db_conn( op, dbh ) != SQL_SUCCESS ) {
                Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
                        "connection free failed\n", 0, 0, 0 );
        }
@@ -522,7 +603,7 @@ backsql_db_open(
        }
 
        /*
-        * Prepare children ID selection query
+        * Prepare children count query
         */
        BER_BVZERO( &bb.bb_val );
        bb.bb_len = 0;
@@ -531,7 +612,7 @@ backsql_db_open(
                        "FROM ldap_entries,ldap_entries ",
                        &bi->sql_aliasing, "subordinates "
                        "WHERE subordinates.parent=ldap_entries.id AND ",
-                       &bi->sql_children_cond );
+                       &bi->sql_dn_match_cond );
        bi->sql_has_children_query = bb.bb_val.bv_val;
  
        /*
@@ -563,7 +644,8 @@ backsql_db_open(
 
 int
 backsql_db_close(
-       BackendDB       *bd )
+       BackendDB       *bd,
+       ConfigReply     *cr )
 {
        backsql_info    *bi = (backsql_info*)bd->be_private;
 
@@ -576,23 +658,6 @@ backsql_db_close(
        return 0;
 }
 
-int
-backsql_connection_destroy( Backend *bd, Connection *c )
-{
-       OperationBuffer opbuf;
-       Operation*      op = (Operation *) &opbuf;
-
-       op->o_hdr = (Opheader *)&op[ 1 ];
-       op->o_connid = c->c_connid;
-       op->o_bd = bd;
-
-       Debug( LDAP_DEBUG_TRACE, "==>backsql_connection_destroy()\n", 0, 0, 0 );
-       backsql_free_db_conn( op );
-       Debug( LDAP_DEBUG_TRACE, "<==backsql_connection_destroy()\n", 0, 0, 0 );
-
-       return 0;
-}
-
 #if SLAPD_SQL == SLAPD_MOD_DYNAMIC
 
 /* conditionally define the init_module() function */
index 4ee11dbd58e7bccda9df2e64fdecc73f7526bc05..ca1fc3ba795b1546044ebaaf33e0a0a0fd815ef5 100644 (file)
@@ -67,7 +67,7 @@ backsql_modify( Operation *op, SlapReply *rs )
                        LDAP_SCOPE_BASE, 
                        (time_t)(-1), NULL, dbh, op, rs,
                        slap_anlist_all_attributes,
-                       ( BACKSQL_ISF_MATCHED | BACKSQL_ISF_GET_ENTRY ) );
+                       ( BACKSQL_ISF_MATCHED | BACKSQL_ISF_GET_ENTRY | BACKSQL_ISF_GET_OC ) );
        switch ( rs->sr_err ) {
        case LDAP_SUCCESS:
                break;
@@ -124,17 +124,17 @@ backsql_modify( Operation *op, SlapReply *rs )
 
        slap_mods_opattrs( op, &op->orm_modlist, 1 );
 
-       oc = backsql_id2oc( bi, bsi.bsi_base_id.eid_oc_id );
-       assert( oc != NULL );
+       assert( bsi.bsi_base_id.eid_oc != NULL );
+       oc = bsi.bsi_base_id.eid_oc;
 
-       if ( !acl_check_modlist( op, &m, op->oq_modify.rs_modlist ) ) {
+       if ( !acl_check_modlist( op, &m, op->orm_modlist ) ) {
                rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
                e = &m;
                goto done;
        }
 
        rs->sr_err = backsql_modify_internal( op, rs, dbh, oc,
-                       &bsi.bsi_base_id, op->oq_modify.rs_modlist );
+                       &bsi.bsi_base_id, op->orm_modlist );
        if ( rs->sr_err != LDAP_SUCCESS ) {
                e = &m;
                goto do_transact;
@@ -197,7 +197,7 @@ done:;
        slap_graduate_commit_csn( op );
 
        if ( !BER_BVISNULL( &bsi.bsi_base_id.eid_ndn ) ) {
-               (void)backsql_free_entryID( op, &bsi.bsi_base_id, 0 );
+               (void)backsql_free_entryID( &bsi.bsi_base_id, 0, op->o_tmpmemctx );
        }
 
        if ( !BER_BVISNULL( &m.e_nname ) ) {
index 4634078fdd57eef891ce375e16b4629c8754abf5..1e6805a7fd3ff7220443c50de6b465143265fc90 100644 (file)
@@ -72,7 +72,7 @@ backsql_modrdn( Operation *op, SlapReply *rs )
                        LDAP_SCOPE_BASE, 
                        (time_t)(-1), NULL, dbh, op, rs,
                        slap_anlist_all_attributes,
-                       ( BACKSQL_ISF_MATCHED | BACKSQL_ISF_GET_ENTRY ) );
+                       ( BACKSQL_ISF_MATCHED | BACKSQL_ISF_GET_ENTRY | BACKSQL_ISF_GET_OC ) );
        switch ( rs->sr_err ) {
        case LDAP_SUCCESS:
                break;
@@ -164,6 +164,7 @@ backsql_modrdn( Operation *op, SlapReply *rs )
         */
        bsi.bsi_e = &p;
        e_id = bsi.bsi_base_id;
+       memset( &bsi.bsi_base_id, 0, sizeof( bsi.bsi_base_id ) );
        rs->sr_err = backsql_init_search( &bsi, &pndn,
                        LDAP_SCOPE_BASE, 
                        (time_t)(-1), NULL, dbh, op, rs,
@@ -197,7 +198,7 @@ backsql_modrdn( Operation *op, SlapReply *rs )
        }
 
        if ( newSuperior ) {
-               (void)backsql_free_entryID( op, &bsi.bsi_base_id, 0 );
+               (void)backsql_free_entryID( &bsi.bsi_base_id, 0, op->o_tmpmemctx );
                
                /*
                 * namingContext "" is not supported
@@ -259,6 +260,8 @@ backsql_modrdn( Operation *op, SlapReply *rs )
                new_npdn = &pndn;
        }
 
+       memset( &bsi.bsi_base_id, 0, sizeof( bsi.bsi_base_id ) );
+
        if ( newSuperior && dn_match( &pndn, new_npdn ) ) {
                Debug( LDAP_DEBUG_TRACE, "   backsql_modrdn(): "
                        "newSuperior is equal to old parent - ignored\n",
@@ -395,7 +398,8 @@ backsql_modrdn( Operation *op, SlapReply *rs )
 
        slap_mods_opattrs( op, &op->orr_modlist, 1 );
 
-       oc = backsql_id2oc( bi, e_id.eid_oc_id );
+       assert( e_id.eid_oc != NULL );
+       oc = e_id.eid_oc;
        rs->sr_err = backsql_modify_internal( op, rs, dbh, oc, &e_id, op->orr_modlist );
        slap_graduate_commit_csn( op );
        if ( rs->sr_err != LDAP_SUCCESS ) {
@@ -407,7 +411,7 @@ backsql_modrdn( Operation *op, SlapReply *rs )
                char            textbuf[ SLAP_TEXT_BUFLEN ] = { '\0' };
 
                backsql_entry_clean( op, &r );
-               (void)backsql_free_entryID( op, &e_id, 0 );
+               (void)backsql_free_entryID( &e_id, 0, op->o_tmpmemctx );
 
                bsi.bsi_e = &r;
                rs->sr_err = backsql_init_search( &bsi, &new_ndn,
@@ -510,11 +514,11 @@ done:;
        }
        
        if ( !BER_BVISNULL( &e_id.eid_ndn ) ) {
-               (void)backsql_free_entryID( op, &e_id, 0 );
+               (void)backsql_free_entryID( &e_id, 0, op->o_tmpmemctx );
        }
 
        if ( !BER_BVISNULL( &n_id.eid_ndn ) ) {
-               (void)backsql_free_entryID( op, &n_id, 0 );
+               (void)backsql_free_entryID( &n_id, 0, op->o_tmpmemctx );
        }
 
        if ( !BER_BVISNULL( &r.e_nname ) ) {
index 60252f6d49f3c129bae71b0c03bc8e09b46e47e0..f6fe6aea4ff06f768f96c3286e6c6dd06ccc9cdd 100644 (file)
@@ -189,7 +189,7 @@ backsql_operational(
 
                *ap = backsql_operational_entryUUID( bi, &bsi.bsi_base_id );
 
-               (void)backsql_free_entryID( op, &bsi.bsi_base_id, 0 );
+               (void)backsql_free_entryID( &bsi.bsi_base_id, 0, op->o_tmpmemctx );
 
                if ( bsi.bsi_attrs != NULL ) {
                        op->o_tmpfree( bsi.bsi_attrs, op->o_tmpmemctx );
index 78b9251556bab10f07ba54de97cf797bc8e86d32..3af14d5ee0c63cc463639ff158db184856473433 100644 (file)
@@ -111,24 +111,32 @@ extern struct berval      backsql_baseObject_bv;
 #endif /* BACKSQL_ARBITRARY_KEY */
 
 /* stores in *id the ID in table ldap_entries corresponding to DN, if any */
-int backsql_dn2id( Operation *op, SlapReply *rs, SQLHDBC dbh,
+extern int
+backsql_dn2id( Operation *op, SlapReply *rs, SQLHDBC dbh,
                struct berval *ndn, backsql_entryID *id,
                int matched, int muck );
 
 /* stores in *nchildren the count of children for an entry */
-int backsql_count_children( Operation *op, SQLHDBC dbh,
+extern int
+backsql_count_children( Operation *op, SQLHDBC dbh,
                struct berval *dn, unsigned long *nchildren );
 
 /* returns LDAP_COMPARE_TRUE/LDAP_COMPARE_FALSE if the entry corresponding
  * to DN has/has not children */
-int backsql_has_children( Operation *op, SQLHDBC dbh, struct berval *dn );
+extern int
+backsql_has_children( Operation *op, SQLHDBC dbh, struct berval *dn );
 
-/* frees *id and returns next in list */
-backsql_entryID *backsql_free_entryID( Operation *op, backsql_entryID *id,
-               int freeit );
+/* free *id and return next in list */
+extern backsql_entryID *
+backsql_free_entryID( backsql_entryID *id, int freeit, void *ctx );
 
-/* turns an ID into an entry */
-int backsql_id2entry( backsql_srch_info *bsi, backsql_entryID *id );
+/* turn an ID into an entry */
+extern int
+backsql_id2entry( backsql_srch_info *bsi, backsql_entryID *id );
+
+/* duplicate an entryID */
+extern backsql_entryID *
+backsql_entryID_dup( backsql_entryID *eid, void *ctx );
 
 /*
  * operational.c
@@ -219,9 +227,9 @@ int backsql_init_db_env( backsql_info *si );
 
 int backsql_free_db_env( backsql_info *si );
 
-int backsql_get_db_conn( Operation *op, SQLHDBC *dbh );
+int backsql_get_db_conn( Operation *op, SQLHDBC        *dbh );
 
-int backsql_free_db_conn( Operation *op );
+int backsql_free_db_conn( Operation *op, SQLHDBC dbh );
 
 /*
  * util.c
index 3c6b71e8b066735d73280127a88249c96e82f58b..b35261b468113a73c1ac57f7f48cfcbcd1da4c12 100644 (file)
@@ -32,7 +32,12 @@ CREATE TABLE phones (
        pers_id int NOT NULL 
 );
 
-
+drop table if exists certs;
+CREATE TABLE certs (
+       id int NOT NULL ,
+       cert LONGBLOB NOT NULL,
+       pers_id int NOT NULL 
+);
 
 ALTER TABLE authors_docs  ADD 
        CONSTRAINT PK_authors_docs PRIMARY KEY  
@@ -66,6 +71,12 @@ ALTER TABLE phones  ADD
                id
        ); 
 
+ALTER TABLE certs  ADD 
+       CONSTRAINT PK_certs PRIMARY KEY  
+       (
+               id
+       ); 
+
 drop table if exists referrals;
 CREATE TABLE referrals (
        id int NOT NULL,
index 7bef37495aa2eaa8f2623bdd1a66c21d64e83851..0ccbfb76a2da0a2ad856b3952b45f84758695a76 100644 (file)
@@ -16,3 +16,6 @@ insert into authors_docs (pers_id,doc_id) values (1,2);
 insert into authors_docs (pers_id,doc_id) values (2,1);
 
 insert into referrals (id,name,url) values (1,'Referral','ldap://localhost:9012/');
+
+insert into certs (id,cert,pers_id) values (1,UNHEX('3082036b308202d4a003020102020102300d06092a864886f70d01010405003077310b3009060355040613025553311330110603550408130a43616c69666f726e6961311f301d060355040a13164f70656e4c444150204578616d706c652c204c74642e311330110603550403130a4578616d706c65204341311d301b06092a864886f70d010901160e6361406578616d706c652e636f6d301e170d3033313031373136333331395a170d3034313031363136333331395a307e310b3009060355040613025553311330110603550408130a43616c69666f726e6961311f301d060355040a13164f70656e4c444150204578616d706c652c204c74642e311830160603550403130f557273756c612048616d7073746572311f301d06092a864886f70d01090116107568616d406578616d706c652e636f6d30819f300d06092a864886f70d010101050003818d0030818902818100eec60a7910b57d2e687158ca55eea738d36f10413dfecf31435e1aeeb9713b8e2da7dd2dde6bc6cec03b4987eaa7b037b9eb50e11c71e58088cc282883122cd8329c6f24f6045e6be9d21b9190c8292998267a5f7905292de936262747ab4b76a88a63872c41629a69d32e894d44c896a8d06fab0a1bc7de343c6c1458478f290203010001a381ff3081fc30090603551d1304023000302c06096086480186f842010d041f161d4f70656e53534c2047656e657261746564204365727469666963617465301d0603551d0e04160414a323de136c19ae0c479450e882dfb10ad147f45e3081a10603551d2304819930819680144b6f211a3624d290f943b053472d7de1c0e69823a17ba4793077310b3009060355040613025553311330110603550408130a43616c69666f726e6961311f301d060355040a13164f70656e4c444150204578616d706c652c204c74642e311330110603550403130a4578616d706c65204341311d301b06092a864886f70d010901160e6361406578616d706c652e636f6d820100300d06092a864886f70d010104050003818100881470045bdce95660d6e6af59e6a844aec4b9f5eaea88d4eb7a5a47080afa64750f81a3e47d00fd39c69a17a1c66d29d36f06edc537107f8c592239c2d4da55fb3f1d488e7b2387ad2a551cbd1ceb070ae9e020a9467275cb28798abb4cbfff98ddb3f1e7689b067072392511bb08125b5bec2bc207b7b6b275c47248f29acd'),3);
+
index 1606600fe994dd4e55a49a231f18308219fbe732..d7e88e40faece696ee3a7ee484d273fb8f7bb955 100644 (file)
@@ -80,6 +80,10 @@ values (13,4,'ou','referrals.name','referrals',NULL,NULL,NULL,3,0);
 insert into ldap_attr_mappings (id,oc_map_id,name,sel_expr,from_tbls,join_where,add_proc,delete_proc,param_order,expect_return)
 values (14,4,'ref','referrals.url','referrals',NULL,NULL,NULL,3,0);
 
+insert into ldap_attr_mappings (id,oc_map_id,name,sel_expr,from_tbls,join_where,add_proc,delete_proc,param_order,expect_return)
+values (15,1,'userCertificate','certs.cert','persons,certs',
+        'certs.pers_id=persons.id',NULL,NULL,3,0);
+
 -- entries mapping: each entry must appear in this table, with a unique DN rooted at the database naming context
 --     id              a unique number > 0 identifying the entry
 --     dn              the DN of the entry, in "pretty" form
@@ -113,6 +117,9 @@ values (7,'ou=Referral,dc=example,dc=com',4,1,1);
 insert into ldap_entry_objclasses (entry_id,oc_name)
 values (1,'dcObject');
 
+insert into ldap_entry_objclasses (entry_id,oc_name)
+values (4,'pkiUser');
+
 insert into ldap_entry_objclasses (entry_id,oc_name)
 values (7,'extensibleObject');
 
index 0142dd9b15a1c3e8a6cf1f6234938ef8d5eaab9d..e1c57e785ce04f12e19026b6751458f9519eff5f 100644 (file)
@@ -37,6 +37,14 @@ create table phones (
        pers_id int not null
 );
 
+drop table certs;
+drop sequence certs_id_seq;
+CREATE TABLE certs (
+       id int not null primary key,
+       cert bytea not null,
+       pers_id int not null 
+);
 drop table referrals;
 drop sequence referrals_id_seq;
 create table referrals (
index 7bef37495aa2eaa8f2623bdd1a66c21d64e83851..0e661d4ccc205fea8b16f010453165f233082161 100644 (file)
@@ -16,3 +16,6 @@ insert into authors_docs (pers_id,doc_id) values (1,2);
 insert into authors_docs (pers_id,doc_id) values (2,1);
 
 insert into referrals (id,name,url) values (1,'Referral','ldap://localhost:9012/');
+
+insert into certs (id,cert,pers_id) values (1,decode('MIIDazCCAtSgAwIBAgIBAjANBgkqhkiG9w0BAQQFADB3MQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEfMB0GA1UEChMWT3BlbkxEQVAgRXhhbXBsZSwgTHRkLjETMBEGA1UEAxMKRXhhbXBsZSBDQTEdMBsGCSqGSIb3DQEJARYOY2FAZXhhbXBsZS5jb20wHhcNMDMxMDE3MTYzMzE5WhcNMDQxMDE2MTYzMzE5WjB+MQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEfMB0GA1UEChMWT3BlbkxEQVAgRXhhbXBsZSwgTHRkLjEYMBYGA1UEAxMPVXJzdWxhIEhhbXBzdGVyMR8wHQYJKoZIhvcNAQkBFhB1aGFtQGV4YW1wbGUuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDuxgp5ELV9LmhxWMpV7qc4028QQT3+zzFDXhruuXE7ji2n3S3ea8bOwDtJh+qnsDe561DhHHHlgIjMKCiDEizYMpxvJPYEXmvp0huRkMgpKZgmel95BSkt6TYmJ0erS3aoimOHLEFimmnTLolNRMiWqNBvqwobx940PGwUWEePKQIDAQABo4H/MIH8MAkGA1UdEwQCMAAwLAYJYIZIAYb4QgENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0GA1UdDgQWBBSjI94TbBmuDEeUUOiC37EK0Uf0XjCBoQYDVR0jBIGZMIGWgBRLbyEaNiTSkPlDsFNHLX3hwOaYI6F7pHkwdzELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExHzAdBgNVBAoTFk9wZW5MREFQIEV4YW1wbGUsIEx0ZC4xEzARBgNVBAMTCkV4YW1wbGUgQ0ExHTAbBgkqhkiG9w0BCQEWDmNhQGV4YW1wbGUuY29tggEAMA0GCSqGSIb3DQEBBAUAA4GBAIgUcARb3OlWYNbmr1nmqESuxLn16uqI1Ot6WkcICvpkdQ+Bo+R9AP05xpoXocZtKdNvBu3FNxB/jFkiOcLU2lX7Px1Ijnsjh60qVRy9HOsHCungIKlGcnXLKHmKu0y//5jds/HnaJsGcHI5JRG7CBJbW+wrwge3trJ1xHJI8prN','base64'),3);
+
index df4a79cfde6afb435237d8a6d64decdd3a1eb9ad..d645cf298e781bf9b14929ad7b6a30203309c0a6 100644 (file)
@@ -55,6 +55,8 @@ insert into ldap_attr_mappings (id,oc_map_id,name,sel_expr,from_tbls,join_where,
 
 insert into ldap_attr_mappings (id,oc_map_id,name,sel_expr,from_tbls,join_where,add_proc,delete_proc,param_order,expect_return) values (14,4,'ref','referrals.url','referrals',NULL,'UPDATE referrals SET url=? WHERE id=?','SELECT 1 FROM referrals WHERE url=? and id=? and 1=0',3,0);
 
+insert into ldap_attr_mappings (id,oc_map_id,name,sel_expr,from_tbls,join_where,add_proc,delete_proc,param_order,expect_return) values (15,1,'userCertificate','certs.cert','persons,certs','certs.pers_id=persons.id',NULL,NULL,3,0);
+
 -- entries mapping: each entry must appear in this table, with a unique DN rooted at the database naming context
 --     id              a unique number > 0 identifying the entry
 --     dn              the DN of the entry, in "pretty" form
@@ -80,6 +82,8 @@ insert into ldap_entries (id,dn,oc_map_id,parent,keyval) values (7,'ou=Referral,
 --     oc_name         the name of the objectClass; it MUST match the name of an objectClass that is loaded in slapd's schema
 insert into ldap_entry_objclasses (entry_id,oc_name) values (1,'dcObject');
 
+insert into ldap_entry_objclasses (entry_id,oc_name) values (4,'pkiUser');
+
 insert into ldap_entry_objclasses (entry_id,oc_name) values (7,'extensibleObject');
 
 -- procedures
index d64d5e937e1ecef30a5573e5a2fe9195be18117c..5dbe2ff084274211cc7818b7b8170a61b3083321 100644 (file)
@@ -74,6 +74,14 @@ backsql_cmp_attr( const void *v_m1, const void *v_m2 )
        const backsql_at_map_rec        *m1 = v_m1,
                                        *m2 = v_m2;
 
+       if ( slap_ad_is_binary( m1->bam_ad ) || slap_ad_is_binary( m2->bam_ad ) ) {
+#ifdef BACKSQL_USE_PTR_CMP
+               return SLAP_PTRCMP( m1->bam_ad->ad_type, m2->bam_ad->ad_type );
+#else /* ! BACKSQL_USE_PTR_CMP */
+               return ber_bvcmp( &m1->bam_ad->ad_type->sat_cname, &m2->bam_ad->ad_type->sat_cname );
+#endif /* ! BACKSQL_USE_PTR_CMP */
+       }
+
 #ifdef BACKSQL_USE_PTR_CMP
        return SLAP_PTRCMP( m1->bam_ad, m2->bam_ad );
 #else /* ! BACKSQL_USE_PTR_CMP */
@@ -87,12 +95,26 @@ backsql_dup_attr( void *v_m1, void *v_m2 )
        backsql_at_map_rec              *m1 = v_m1,
                                        *m2 = v_m2;
 
-       assert( m1->bam_ad == m2->bam_ad );
+       if ( slap_ad_is_binary( m1->bam_ad ) || slap_ad_is_binary( m2->bam_ad ) ) {
+#ifdef BACKSQL_USE_PTR_CMP
+               assert( m1->bam_ad->ad_type == m2->bam_ad->ad_type );
+#else /* ! BACKSQL_USE_PTR_CMP */
+               assert( ber_bvcmp( &m1->bam_ad->ad_type->sat_cname, &m2->bam_ad->ad_type->sat_cname ) == 0 );
+#endif /* ! BACKSQL_USE_PTR_CMP */
+
+       } else {
+#ifdef BACKSQL_USE_PTR_CMP
+               assert( m1->bam_ad == m2->bam_ad );
+#else /* ! BACKSQL_USE_PTR_CMP */
+               assert( ber_bvcmp( &m1->bam_ad->ad_cname, &m2->bam_ad->ad_cname ) == 0 );
+#endif /* ! BACKSQL_USE_PTR_CMP */
+       }
 
        /* duplicate definitions of attributeTypes are appended;
         * this allows to define multiple rules for the same 
         * attributeType.  Use with care! */
        for ( ; m1->bam_next ; m1 = m1->bam_next );
+
        m1->bam_next = m2;
        m2->bam_next = NULL;
 
@@ -178,6 +200,7 @@ backsql_add_sysmaps( backsql_info *bi, backsql_oc_map_rec *oc_map )
        at_map = (backsql_at_map_rec *)ch_calloc(1, 
                        sizeof( backsql_at_map_rec ) );
        at_map->bam_ad = slap_schema.si_ad_objectClass;
+       at_map->bam_true_ad = slap_schema.si_ad_objectClass;
        ber_str2bv( "ldap_entry_objclasses.oc_name", 0, 1,
                        &at_map->bam_sel_expr );
        ber_str2bv( "ldap_entry_objclasses,ldap_entries", 0, 1, 
@@ -350,6 +373,26 @@ backsql_oc_get_attr_mapping( void *v_oc, void *v_bas )
                at_map = (backsql_at_map_rec *)ch_calloc( 1,
                                sizeof( backsql_at_map_rec ) );
                at_map->bam_ad = ad;
+               at_map->bam_true_ad = ad;
+               if ( slap_syntax_is_binary( ad->ad_type->sat_syntax )
+                       && !slap_ad_is_binary( ad ) )
+               {
+                       char            buf[ BUFSIZ ];
+                       struct berval   bv;
+                       const char      *text = NULL;
+
+                       bv.bv_val = buf;
+                       bv.bv_len = snprintf( buf, sizeof( buf ), "%s;binary",
+                               ad->ad_cname.bv_val );
+                       at_map->bam_true_ad = NULL;
+                       bas->bas_rc = slap_bv2ad( &bv, &at_map->bam_true_ad, &text );
+                       if ( bas->bas_rc != LDAP_SUCCESS ) {
+                               Debug( LDAP_DEBUG_TRACE, "backsql_oc_get_attr_mapping(): "
+                                       "unable to fetch attribute \"%s\": %s (%d)\n",
+                                       buf, text, rc );
+                               return BACKSQL_AVL_STOP;
+                       }
+               }
 
                ber_str2bv( at_row.cols[ 1 ], 0, 1, &at_map->bam_sel_expr );
                if ( at_row.value_len[ 8 ] < 0 ) {
@@ -717,7 +760,7 @@ backsql_id2oc( backsql_info *bi, unsigned long id )
 backsql_at_map_rec *
 backsql_ad2at( backsql_oc_map_rec* objclass, AttributeDescription *ad )
 {
-       backsql_at_map_rec      tmp, *res;
+       backsql_at_map_rec      tmp = { 0 }, *res;
  
 #ifdef BACKSQL_TRACE
        Debug( LDAP_DEBUG_TRACE, "==>backsql_ad2at(): "
index b9d9365034b735526651ffff4ebd15cb70c633e1..e0777f3e8252d1a9198a88b040c75b67a6a2e896 100644 (file)
@@ -42,6 +42,23 @@ static int backsql_process_filter_like( backsql_srch_info *bsi,
 static int backsql_process_filter_attr( backsql_srch_info *bsi, Filter *f, 
                backsql_at_map_rec *at );
 
+/* For LDAP_CONTROL_PAGEDRESULTS, a 32 bit cookie is available to keep track of
+   the state of paged results. The ldap_entries.id and oc_map_id values of the
+   last entry returned are used as the cookie, so 6 bits are used for the OC id
+   and the other 26 for ldap_entries ID number. If your max(oc_map_id) is more
+   than 63, you will need to steal more bits from ldap_entries ID number and
+   put them into the OC ID part of the cookie. */
+#define SQL_TO_PAGECOOKIE(id, oc) (((id) << 6 ) | ((oc) & 0x3F))
+#define PAGECOOKIE_TO_SQL_ID(pc) ((pc) >> 6)
+#define PAGECOOKIE_TO_SQL_OC(pc) ((pc) & 0x3F)
+
+static int parse_paged_cookie( Operation *op, SlapReply *rs );
+
+static void send_paged_response( 
+       Operation *op,
+       SlapReply *rs,
+       ID  *lastid );
+
 static int
 backsql_attrlist_add( backsql_srch_info *bsi, AttributeDescription *ad )
 {
@@ -62,6 +79,11 @@ backsql_attrlist_add( backsql_srch_info *bsi, AttributeDescription *ad )
                return 1;
        }
 
+       /* strip ';binary' */
+       if ( slap_ad_is_binary( ad ) ) {
+               ad = ad->ad_type->sat_ad;
+       }
+
        for ( ; !BER_BVISNULL( &bsi->bsi_attrs[ n_attrs ].an_name ); n_attrs++ ) {
                an = &bsi->bsi_attrs[ n_attrs ];
                
@@ -317,6 +339,17 @@ backsql_init_search(
                                rs->sr_err = rc;
                        }
                }
+
+               if ( gotit && BACKSQL_IS_GET_OC( flags ) ) {
+                       bsi->bsi_base_id.eid_oc = backsql_id2oc( bi,
+                               bsi->bsi_base_id.eid_oc_id );
+                       if ( bsi->bsi_base_id.eid_oc == NULL ) {
+                               /* error? */
+                               backsql_free_entryID( &bsi->bsi_base_id, 1,
+                                       op->o_tmpmemctx );
+                               rc = rs->sr_err = LDAP_OTHER;
+                       }
+               }
        }
 
        bsi->bsi_status = rc;
@@ -1490,6 +1523,7 @@ backsql_srch_query( backsql_srch_info *bsi, struct berval *query )
                                        (ber_len_t)STRLENOF( "9=9"), "9=9");
 
                } else if ( !BER_BVISNULL( &bi->sql_subtree_cond ) ) {
+                       /* This should always be true... */
                        backsql_strfcat_x( &bsi->bsi_join_where,
                                        bsi->bsi_op->o_tmpmemctx,
                                        "b",
@@ -1517,6 +1551,30 @@ backsql_srch_query( backsql_srch_info *bsi, struct berval *query )
                assert( 0 );
        }
 
+       /* If paged results are in effect, ignore low ldap_entries.id numbers */
+       if ( get_pagedresults(bsi->bsi_op) > SLAP_CONTROL_IGNORED ) {
+               unsigned long lowid = 0;
+
+               /* Pick up the previous ldap_entries.id if the previous page ended in this objectClass */
+               if ( bsi->bsi_oc->bom_id == PAGECOOKIE_TO_SQL_OC( ((PagedResultsState *)bsi->bsi_op->o_pagedresults_state)->ps_cookie ) )
+               {
+                       lowid = PAGECOOKIE_TO_SQL_ID( ((PagedResultsState *)bsi->bsi_op->o_pagedresults_state)->ps_cookie );
+               }
+
+               if ( lowid ) {
+                       char lowidstring[48];
+                       int  lowidlen;
+
+                       lowidlen = snprintf( lowidstring, sizeof( lowidstring ),
+                               " AND ldap_entries.id>%lu", lowid );
+                       backsql_strfcat_x( &bsi->bsi_join_where,
+                                       bsi->bsi_op->o_tmpmemctx,
+                                       "l",
+                                       (ber_len_t)lowidlen,
+                                       lowidstring );
+               }
+       }
+
        rc = backsql_process_filter( bsi, bsi->bsi_filter );
        if ( rc > 0 ) {
                struct berbuf   bb = BB_NULL;
@@ -1596,6 +1654,14 @@ backsql_oc_get_candidates( void *v_oc, void *v_bsi )
                return BACKSQL_AVL_STOP;
        }
 
+       /* If paged results have already completed this objectClass, skip it */
+       if ( get_pagedresults(op) > SLAP_CONTROL_IGNORED ) {
+               if ( oc->bom_id < PAGECOOKIE_TO_SQL_OC( ((PagedResultsState *)op->o_pagedresults_state)->ps_cookie ) )
+               {
+                       return BACKSQL_AVL_CONTINUE;
+               }
+       }
+
        if ( bsi->bsi_n_candidates == -1 ) {
                Debug( LDAP_DEBUG_TRACE, "backsql_oc_get_candidates(): "
                        "unchecked limit has been overcome\n", 0, 0, 0 );
@@ -1860,6 +1926,7 @@ backsql_oc_get_candidates( void *v_oc, void *v_bsi )
                        goto cleanup;
                }
 #endif /* ! BACKSQL_ARBITRARY_KEY */
+               c_id->eid_oc = bsi->bsi_oc;
                c_id->eid_oc_id = bsi->bsi_oc->bom_id;
 
                c_id->eid_dn = pdn;
@@ -1921,6 +1988,7 @@ backsql_search( Operation *op, SlapReply *rs )
        backsql_srch_info       bsi = { 0 };
        backsql_entryID         *eid = NULL;
        struct berval           nbase = BER_BVNULL;
+       unsigned long           lastid = 0;
 
        Debug( LDAP_DEBUG_TRACE, "==>backsql_search(): "
                "base=\"%s\", filter=\"%s\", scope=%d,", 
@@ -2057,6 +2125,15 @@ backsql_search( Operation *op, SlapReply *rs )
                ( op->ors_limit->lms_s_unchecked == -1 ? -2 :
                ( op->ors_limit->lms_s_unchecked ) ) );
 
+       /* If paged results are in effect, check the paging cookie */
+       if ( get_pagedresults( op ) > SLAP_CONTROL_IGNORED ) {
+               rs->sr_err = parse_paged_cookie( op, rs );
+               if ( rs->sr_err != LDAP_SUCCESS ) {
+                       send_ldap_result( op, rs );
+                       goto done;
+               }
+       }
+
        switch ( bsi.bsi_scope ) {
        case LDAP_SCOPE_BASE:
        case BACKSQL_SCOPE_BASE_LIKE:
@@ -2084,9 +2161,9 @@ backsql_search( Operation *op, SlapReply *rs )
                /*
                 * for each objectclass we try to construct query which gets IDs
                 * of entries matching LDAP query filter and scope (or at least 
-                * candidates), and get the IDs
+                * candidates), and get the IDs. Do this in ID order for paging.
                 */
-               avl_apply( bi->sql_oc_by_oc, backsql_oc_get_candidates,
+               avl_apply( bi->sql_oc_by_id, backsql_oc_get_candidates,
                                &bsi, BACKSQL_AVL_STOP, AVL_INORDER );
 
                /* check for abandon */
@@ -2112,9 +2189,9 @@ backsql_search( Operation *op, SlapReply *rs )
         * and then send to client; don't free entry_id if baseObject...
         */
        for ( eid = bsi.bsi_id_list;
-                       eid != NULL; 
-                       eid = backsql_free_entryID( op,
-                               eid, eid == &bsi.bsi_base_id ? 0 : 1 ) )
+               eid != NULL; 
+               eid = backsql_free_entryID( 
+                       eid, eid == &bsi.bsi_base_id ? 0 : 1, op->o_tmpmemctx ) )
        {
                int             rc;
                Attribute       *a_hasSubordinate = NULL,
@@ -2179,7 +2256,6 @@ backsql_search( Operation *op, SlapReply *rs )
                case LDAP_SCOPE_SUBTREE:
                        /* FIXME: this should never fail... */
                        if ( !dnIsSuffix( &eid->eid_ndn, &op->o_req_ndn ) ) {
-                               assert( 0 );
                                goto next_entry2;
                        }
                        break;
@@ -2264,6 +2340,9 @@ backsql_search( Operation *op, SlapReply *rs )
                        rs->sr_ref = NULL;
                        rs->sr_matched = NULL;
                        rs->sr_entry = NULL;
+                       if ( rs->sr_err == LDAP_REFERRAL ) {
+                               rs->sr_err = LDAP_SUCCESS;
+                       }
 
                        goto next_entry;
                }
@@ -2330,12 +2409,24 @@ backsql_search( Operation *op, SlapReply *rs )
 
                if ( test_filter( op, e, op->ors_filter ) == LDAP_COMPARE_TRUE )
                {
+                       /* If paged results are in effect, see if the page limit was exceeded */
+                       if ( get_pagedresults(op) > SLAP_CONTROL_IGNORED ) {
+                               if ( rs->sr_nentries >= ((PagedResultsState *)op->o_pagedresults_state)->ps_size )
+                               {
+                                       e = NULL;
+                                       send_paged_response( op, rs, &lastid );
+                                       goto done;
+                               }
+                               lastid = SQL_TO_PAGECOOKIE( eid->eid_id, eid->eid_oc_id );
+                       }
                        rs->sr_attrs = op->ors_attrs;
                        rs->sr_operational_attrs = NULL;
                        rs->sr_entry = e;
+                       e->e_private = (void *)eid;
                        rs->sr_flags = ( e == &user_entry ) ? REP_ENTRY_MODIFIABLE : 0;
                        /* FIXME: need the whole entry (ITS#3480) */
                        rs->sr_err = send_search_entry( op, rs );
+                       e->e_private = NULL;
                        rs->sr_entry = NULL;
                        rs->sr_attrs = NULL;
                        rs->sr_operational_attrs = NULL;
@@ -2375,13 +2466,17 @@ end_of_search:;
 
 send_results:;
        if ( rs->sr_err != SLAPD_ABANDON ) {
-               send_ldap_result( op, rs );
+               if ( get_pagedresults(op) > SLAP_CONTROL_IGNORED ) {
+                       send_paged_response( op, rs, NULL );
+               } else {
+                       send_ldap_result( op, rs );
+               }
        }
 
        /* cleanup in case of abandon */
        for ( ; eid != NULL; 
-                       eid = backsql_free_entryID( op,
-                               eid, eid == &bsi.bsi_base_id ? 0 : 1 ) )
+               eid = backsql_free_entryID(
+                       eid, eid == &bsi.bsi_base_id ? 0 : 1, op->o_tmpmemctx ) )
                ;
 
        backsql_entry_clean( op, &base_entry );
@@ -2402,7 +2497,7 @@ send_results:;
                slap_callback   cb = { 0 };
 
                op2.o_tag = LDAP_REQ_ADD;
-               op2.o_bd = select_backend( &op->o_bd->be_nsuffix[0], 0, 0 );
+               op2.o_bd = select_backend( &op->o_bd->be_nsuffix[0], 0 );
                op2.ora_e = e;
                op2.o_callback = &cb;
 
@@ -2419,7 +2514,7 @@ send_results:;
 #endif /* BACKSQL_SYNCPROV */
 
 done:;
-       (void)backsql_free_entryID( op, &bsi.bsi_base_id, 0 );
+       (void)backsql_free_entryID( &bsi.bsi_base_id, 0, op->o_tmpmemctx );
 
        if ( bsi.bsi_attrs != NULL ) {
                op->o_tmpfree( bsi.bsi_attrs, op->o_tmpmemctx );
@@ -2462,8 +2557,8 @@ backsql_entry_get(
        *ent = NULL;
 
        rc = backsql_get_db_conn( op, &dbh );
-       if ( !dbh ) {
-               return LDAP_OTHER;
+       if ( rc != LDAP_SUCCESS ) {
+               return rc;
        }
 
        if ( at ) {
@@ -2481,7 +2576,7 @@ backsql_entry_get(
                        BACKSQL_ISF_GET_ENTRY );
 
        if ( !BER_BVISNULL( &bsi.bsi_base_id.eid_ndn ) ) {
-               (void)backsql_free_entryID( op, &bsi.bsi_base_id, 0 );
+               (void)backsql_free_entryID( &bsi.bsi_base_id, 0, op->o_tmpmemctx );
        }
 
        if ( rc == LDAP_SUCCESS ) {
@@ -2563,7 +2658,164 @@ backsql_entry_release(
 {
        backsql_entry_clean( op, e );
 
-       ch_free( e );
+       entry_free( e );
 
        return 0;
 }
+
+
+/* This function is copied verbatim from back-bdb/search.c */
+static int
+parse_paged_cookie( Operation *op, SlapReply *rs )
+{
+       LDAPControl     **c;
+       int             rc = LDAP_SUCCESS;
+       ber_tag_t       tag;
+       ber_int_t       size;
+       BerElement      *ber;
+       struct berval   cookie = BER_BVNULL;
+       PagedResultsState *ps = op->o_pagedresults_state;
+
+       /* this function must be invoked only if the pagedResults
+        * control has been detected, parsed and partially checked
+        * by the frontend */
+       assert( get_pagedresults( op ) > SLAP_CONTROL_IGNORED );
+
+       /* look for the appropriate ctrl structure */
+       for ( c = op->o_ctrls; c[0] != NULL; c++ ) {
+               if ( strcmp( c[0]->ldctl_oid, LDAP_CONTROL_PAGEDRESULTS ) == 0 )
+               {
+                       break;
+               }
+       }
+
+       if ( c[0] == NULL ) {
+               rs->sr_text = "missing pagedResults control";
+               return LDAP_PROTOCOL_ERROR;
+       }
+
+       /* Tested by frontend */
+       assert( c[0]->ldctl_value.bv_len > 0 );
+
+       /* Parse the control value
+        *      realSearchControlValue ::= SEQUENCE {
+        *              size    INTEGER (0..maxInt),
+        *                              -- requested page size from client
+        *                              -- result set size estimate from server
+        *              cookie  OCTET STRING
+        * }
+        */
+       ber = ber_init( &c[0]->ldctl_value );
+       if ( ber == NULL ) {
+               rs->sr_text = "internal error";
+               return LDAP_OTHER;
+       }
+
+       tag = ber_scanf( ber, "{im}", &size, &cookie );
+
+       /* Tested by frontend */
+       assert( tag != LBER_ERROR );
+       assert( size >= 0 );
+
+       /* cookie decoding/checks deferred to backend... */
+       if ( cookie.bv_len ) {
+               PagedResultsCookie reqcookie;
+               if( cookie.bv_len != sizeof( reqcookie ) ) {
+                       /* bad cookie */
+                       rs->sr_text = "paged results cookie is invalid";
+                       rc = LDAP_PROTOCOL_ERROR;
+                       goto done;
+               }
+
+               AC_MEMCPY( &reqcookie, cookie.bv_val, sizeof( reqcookie ));
+
+               if ( reqcookie > ps->ps_cookie ) {
+                       /* bad cookie */
+                       rs->sr_text = "paged results cookie is invalid";
+                       rc = LDAP_PROTOCOL_ERROR;
+                       goto done;
+
+               } else if ( reqcookie < ps->ps_cookie ) {
+                       rs->sr_text = "paged results cookie is invalid or old";
+                       rc = LDAP_UNWILLING_TO_PERFORM;
+                       goto done;
+               }
+
+       } else {
+               /* Initial request.  Initialize state. */
+#if 0
+               if ( op->o_conn->c_pagedresults_state.ps_cookie != 0 ) {
+                       /* There's another pagedResults control on the
+                        * same connection; reject new pagedResults controls 
+                        * (allowed by RFC2696) */
+                       rs->sr_text = "paged results cookie unavailable; try later";
+                       rc = LDAP_UNWILLING_TO_PERFORM;
+                       goto done;
+               }
+#endif
+               ps->ps_cookie = 0;
+               ps->ps_count = 0;
+       }
+
+done:;
+       (void)ber_free( ber, 1 );
+
+       return rc;
+}
+
+/* This function is copied nearly verbatim from back-bdb/search.c */
+static void
+send_paged_response( 
+       Operation       *op,
+       SlapReply       *rs,
+       unsigned long   *lastid )
+{
+       LDAPControl     ctrl, *ctrls[2];
+       BerElementBuffer berbuf;
+       BerElement      *ber = (BerElement *)&berbuf;
+       PagedResultsCookie respcookie;
+       struct berval cookie;
+
+       Debug(LDAP_DEBUG_ARGS,
+               "send_paged_response: lastid=0x%08lx nentries=%d\n", 
+               lastid ? *lastid : 0, rs->sr_nentries, NULL );
+
+       BER_BVZERO( &ctrl.ldctl_value );
+       ctrls[0] = &ctrl;
+       ctrls[1] = NULL;
+
+       ber_init2( ber, NULL, LBER_USE_DER );
+
+       if ( lastid ) {
+               respcookie = ( PagedResultsCookie )(*lastid);
+               cookie.bv_len = sizeof( respcookie );
+               cookie.bv_val = (char *)&respcookie;
+
+       } else {
+               respcookie = ( PagedResultsCookie )0;
+               BER_BVSTR( &cookie, "" );
+       }
+
+       op->o_conn->c_pagedresults_state.ps_cookie = respcookie;
+       op->o_conn->c_pagedresults_state.ps_count =
+               ((PagedResultsState *)op->o_pagedresults_state)->ps_count +
+               rs->sr_nentries;
+
+       /* return size of 0 -- no estimate */
+       ber_printf( ber, "{iO}", 0, &cookie ); 
+
+       if ( ber_flatten2( ber, &ctrls[0]->ldctl_value, 0 ) == -1 ) {
+               goto done;
+       }
+
+       ctrls[0]->ldctl_oid = LDAP_CONTROL_PAGEDRESULTS;
+       ctrls[0]->ldctl_iscritical = 0;
+
+       rs->sr_ctrls = ctrls;
+       rs->sr_err = LDAP_SUCCESS;
+       send_ldap_result( op, rs );
+       rs->sr_ctrls = NULL;
+
+done:
+       (void) ber_free_buf( ber );
+}
index d01d9cbb31e1e403927f9b8e2ed76fd6e131b934..5e40dc2a7bea1d92968b2e37977f61705b4e9246 100644 (file)
 
 #define MAX_ATTR_LEN 16384
 
-typedef struct backsql_db_conn {
-       unsigned long   ldap_cid;
-       SQLHDBC         dbh;
-} backsql_db_conn;
-
 void
 backsql_PrintErrors( SQLHENV henv, SQLHDBC hdbc, SQLHSTMT sth, int rc )
 {
@@ -132,10 +127,6 @@ RETCODE
 backsql_BindRowAsStrings_x( SQLHSTMT sth, BACKSQL_ROW_NTS *row, void *ctx )
 {
        RETCODE         rc;
-       SQLCHAR         colname[ 64 ];
-       SQLSMALLINT     name_len, col_type, col_scale, col_null;
-       UDWORD          col_prec;
-       int             i;
 
        if ( row == NULL ) {
                return SQL_ERROR;
@@ -155,6 +146,11 @@ backsql_BindRowAsStrings_x( SQLHSTMT sth, BACKSQL_ROW_NTS *row, void *ctx )
                backsql_PrintErrors( SQL_NULL_HENV, SQL_NULL_HDBC, sth, rc );
 
        } else {
+               SQLCHAR         colname[ 64 ];
+               SQLSMALLINT     name_len, col_type, col_scale, col_null;
+               UDWORD          col_prec;
+               int             i;
+
 #ifdef BACKSQL_TRACE
                Debug( LDAP_DEBUG_TRACE, "backsql_BindRowAsStrings: "
                        "ncols=%d\n", (int)row->ncols, 0, 0 );
@@ -162,58 +158,115 @@ 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;
+               if ( row->col_names == NULL ) {
+                       goto nomem;
+               }
+
                row->col_prec = (UDWORD *)ber_memcalloc_x( row->ncols,
                                sizeof( UDWORD ), ctx );
-               if ( !row->col_prec ) goto nomem1;
+               if ( row->col_prec == NULL ) {
+                       goto nomem;
+               }
+
+               row->col_type = (SQLSMALLINT *)ber_memcalloc_x( row->ncols,
+                               sizeof( SQLSMALLINT ), ctx );
+               if ( row->col_type == NULL ) {
+                       goto nomem;
+               }
+
+               row->cols = (char **)ber_memcalloc_x( row->ncols + 1, 
+                               sizeof( char * ), ctx );
+               if ( row->cols == NULL ) {
+                       goto nomem;
+               }
+
                row->value_len = (SQLINTEGER *)ber_memcalloc_x( row->ncols,
                                sizeof( SQLINTEGER ), ctx );
-               if ( !row->value_len ) {
+               if ( row->value_len == NULL ) {
+                       goto nomem;
+               }
+
+               if ( 0 ) {
+nomem:
+                       ber_memfree_x( row->col_names, ctx );
+                       row->col_names = NULL;
                        ber_memfree_x( row->col_prec, ctx );
                        row->col_prec = NULL;
-nomem1:                ber_memfree_x( row->cols, ctx );
+                       ber_memfree_x( row->col_type, ctx );
+                       row->col_type = NULL;
+                       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: "
+                       ber_memfree_x( row->value_len, ctx );
+                       row->value_len = NULL;
+
+                       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 ],
+
+               for ( i = 0; i < row->ncols; i++ ) {
+                       SQLSMALLINT     TargetType;
+
+                       rc = SQLDescribeCol( sth, (SQLSMALLINT)(i + 1), &colname[ 0 ],
                                        (SQLUINTEGER)( sizeof( colname ) - 1 ),
                                        &name_len, &col_type,
                                        &col_prec, &col_scale, &col_null );
                        /* FIXME: test rc? */
 
                        ber_str2bv_x( (char *)colname, 0, 1,
-                                       &row->col_names[ i - 1 ], ctx );
+                                       &row->col_names[ i ], ctx );
 #ifdef BACKSQL_TRACE
                        Debug( LDAP_DEBUG_TRACE, "backsql_BindRowAsStrings: "
                                "col_name=%s, col_prec[%d]=%d\n",
-                               colname, (int)i, (int)col_prec );
+                               colname, (int)(i + 1), (int)col_prec );
 #endif /* BACKSQL_TRACE */
                        if ( col_type != SQL_CHAR && col_type != SQL_VARCHAR )
                        {
                                col_prec = MAX_ATTR_LEN;
                        }
 
-                       row->cols[ i - 1 ] = (char *)ber_memcalloc_x( col_prec + 1,
+                       row->cols[ i ] = (char *)ber_memcalloc_x( col_prec + 1,
                                        sizeof( char ), ctx );
-                       row->col_prec[ i - 1 ] = col_prec;
-                       rc = SQLBindCol( sth, (SQLUSMALLINT)i,
-                                        SQL_C_CHAR,
-                                        (SQLPOINTER)row->cols[ i - 1 ],
-                                        col_prec + 1,
-                                        &row->value_len[ i - 1 ] );
+                       row->col_prec[ i ] = col_prec;
+                       row->col_type[ i ] = col_type;
+
+                       /*
+                        * ITS#3386, ITS#3113 - 20070308
+                        * Note: there are many differences between various DPMS and ODBC
+                        * Systems; some support SQL_C_BLOB, SQL_C_BLOB_LOCATOR.  YMMV:
+                        * This has only been tested on Linux/MySQL/UnixODBC
+                        * For BINARY-type Fields (BLOB, etc), read the data as BINARY
+                        */
+                       if ( BACKSQL_IS_BINARY( col_type ) ) {
+#ifdef BACKSQL_TRACE
+                               Debug( LDAP_DEBUG_TRACE, "backsql_BindRowAsStrings: "
+                                       "col_name=%s, col_type[%d]=%d: reading binary data\n",
+                                       colname, (int)(i + 1), (int)col_type);
+#endif /* BACKSQL_TRACE */
+                               TargetType = SQL_C_BINARY;
+
+                       } else {
+                               /* Otherwise read it as Character data */
+#ifdef BACKSQL_TRACE
+                               Debug( LDAP_DEBUG_TRACE, "backsql_BindRowAsStrings: "
+                                       "col_name=%s, col_type[%d]=%d: reading character data\n",
+                                       colname, (int)(i + 1), (int)col_type);
+#endif /* BACKSQL_TRACE */
+                               TargetType = SQL_C_CHAR;
+                       }
+
+                       rc = SQLBindCol( sth, (SQLUSMALLINT)(i + 1),
+                                TargetType,
+                                (SQLPOINTER)row->cols[ i ],
+                                col_prec + 1,
+                                &row->value_len[ i ] );
+
                        /* FIXME: test rc? */
                }
 
-               BER_BVZERO( &row->col_names[ i - 1 ] );
-               row->cols[ i - 1 ] = NULL;
+               BER_BVZERO( &row->col_names[ i ] );
+               row->cols[ i ] = NULL;
        }
 
 #ifdef BACKSQL_TRACE
@@ -237,8 +290,9 @@ backsql_FreeRow_x( BACKSQL_ROW_NTS *row, void *ctx )
        }
 
        ber_bvarray_free_x( row->col_names, ctx );
-       ber_memvfree_x( (void **)row->cols, ctx );
        ber_memfree_x( row->col_prec, ctx );
+       ber_memfree_x( row->col_type, ctx );
+       ber_memvfree_x( (void **)row->cols, ctx );
        ber_memfree_x( row->value_len, ctx );
 
        return SQL_SUCCESS;
@@ -251,29 +305,15 @@ backsql_FreeRow( BACKSQL_ROW_NTS *row )
        return backsql_FreeRow_x( row, NULL );
 }
 
-static int
-backsql_cmp_connid( const void *v_c1, const void *v_c2 )
-{
-       const backsql_db_conn *c1 = v_c1, *c2 = v_c2;
-       if ( c1->ldap_cid > c2->ldap_cid ) {
-               return 1;
-       }
-       
-       if ( c1->ldap_cid < c2->ldap_cid ) {
-               return -1;
-       }
-       
-       return 0;
-}
-
 static void
-backsql_close_db_conn( void *v_conn )
+backsql_close_db_handle( SQLHDBC dbh )
 {
-       backsql_db_conn *conn =         (backsql_db_conn *)v_conn;
-       unsigned long   cid = conn->ldap_cid;
+       if ( dbh == SQL_NULL_HDBC ) {
+               return;
+       }
 
-       Debug( LDAP_DEBUG_TRACE, "==>backsql_close_db_conn(%lu)\n",
-               cid, 0, 0 );
+       Debug( LDAP_DEBUG_TRACE, "==>backsql_close_db_handle(%p)\n",
+               (void *)dbh, 0, 0 );
 
        /*
         * Default transact is SQL_ROLLBACK; commit is required only
@@ -282,21 +322,18 @@ backsql_close_db_conn( void *v_conn )
         */
 
        /* TimesTen */
-       SQLTransact( SQL_NULL_HENV, conn->dbh, SQL_ROLLBACK );
-       SQLDisconnect( conn->dbh );
-       SQLFreeConnect( conn->dbh );
-       ch_free( conn );
+       SQLTransact( SQL_NULL_HENV, dbh, SQL_ROLLBACK );
+       SQLDisconnect( dbh );
+       SQLFreeConnect( dbh );
 
-       Debug( LDAP_DEBUG_TRACE, "<==backsql_close_db_conn(%lu)\n",
-               cid, 0, 0 );
+       Debug( LDAP_DEBUG_TRACE, "<==backsql_close_db_handle(%p)\n",
+               (void *)dbh, 0, 0 );
 }
 
 int
 backsql_conn_destroy(
        backsql_info    *bi )
 {
-       avl_free( bi->sql_db_conns, backsql_close_db_conn );
-
        return 0;
 }
 
@@ -341,42 +378,44 @@ backsql_free_db_env( backsql_info *bi )
 }
 
 static int
-backsql_open_db_conn( backsql_info *bi, unsigned long ldap_cid, backsql_db_conn **pdbc )
+backsql_open_db_handle(
+       backsql_info    *bi,
+       SQLHDBC         *dbhp )
 {
        /* TimesTen */
        char                    DBMSName[ 32 ];
-       backsql_db_conn         *dbc;
        int                     rc;
 
-       assert( pdbc != NULL );
-       *pdbc = NULL;
+       assert( dbhp != NULL );
+       *dbhp = SQL_NULL_HDBC;
  
-       Debug( LDAP_DEBUG_TRACE, "==>backsql_open_db_conn(%lu)\n",
-               ldap_cid, 0, 0 );
+       Debug( LDAP_DEBUG_TRACE, "==>backsql_open_db_handle()\n",
+               0, 0, 0 );
 
-       dbc = (backsql_db_conn *)ch_calloc( 1, sizeof( backsql_db_conn ) );
-       dbc->ldap_cid = ldap_cid;
-       rc = SQLAllocConnect( bi->sql_db_env, &dbc->dbh );
+       rc = SQLAllocConnect( bi->sql_db_env, dbhp );
        if ( !BACKSQL_SUCCESS( rc ) ) {
-               Debug( LDAP_DEBUG_TRACE, "backsql_open_db_conn(%lu): "
-                       "SQLAllocConnect() failed:\n", ldap_cid, 0, 0 );
+               Debug( LDAP_DEBUG_TRACE, "backsql_open_db_handle(): "
+                       "SQLAllocConnect() failed:\n",
+                       0, 0, 0 );
                backsql_PrintErrors( bi->sql_db_env, SQL_NULL_HDBC,
-                               SQL_NULL_HENV, rc );
+                       SQL_NULL_HENV, rc );
                return LDAP_UNAVAILABLE;
        }
 
-       rc = SQLConnect( dbc->dbh,
-                       (SQLCHAR*)bi->sql_dbname, SQL_NTS,
-                       (SQLCHAR*)bi->sql_dbuser, SQL_NTS,
-                       (SQLCHAR*)bi->sql_dbpasswd, SQL_NTS );
+       rc = SQLConnect( *dbhp,
+               (SQLCHAR*)bi->sql_dbname, SQL_NTS,
+               (SQLCHAR*)bi->sql_dbuser, SQL_NTS,
+               (SQLCHAR*)bi->sql_dbpasswd, SQL_NTS );
        if ( rc != SQL_SUCCESS ) {
-               Debug( LDAP_DEBUG_TRACE, "backsql_open_db_conn(%lu): "
+               Debug( LDAP_DEBUG_TRACE, "backsql_open_db_handle(): "
                        "SQLConnect() to database \"%s\" %s.\n",
-                       ldap_cid, bi->sql_dbname,
+                       bi->sql_dbname,
                        rc == SQL_SUCCESS_WITH_INFO ?
-                       "succeeded with info" : "failed" );
-               backsql_PrintErrors( bi->sql_db_env, dbc->dbh, SQL_NULL_HENV, rc );
+                               "succeeded with info" : "failed",
+                       0 );
+               backsql_PrintErrors( bi->sql_db_env, *dbhp, SQL_NULL_HENV, rc );
                if ( rc != SQL_SUCCESS_WITH_INFO ) {
+                       SQLFreeConnect( *dbhp );
                        return LDAP_UNAVAILABLE;
                }
        }
@@ -385,7 +424,7 @@ backsql_open_db_conn( backsql_info *bi, unsigned long ldap_cid, backsql_db_conn
         * TimesTen : Turn off autocommit.  We must explicitly
         * commit any transactions. 
         */
-       SQLSetConnectOption( dbc->dbh, SQL_AUTOCOMMIT, SQL_AUTOCOMMIT_OFF );
+       SQLSetConnectOption( *dbhp, SQL_AUTOCOMMIT, SQL_AUTOCOMMIT_OFF );
 
        /* 
         * See if this connection is to TimesTen.  If it is,
@@ -394,112 +433,100 @@ backsql_open_db_conn( backsql_info *bi, unsigned long ldap_cid, backsql_db_conn
        /* Assume until proven otherwise */
        bi->sql_flags &= ~BSQLF_USE_REVERSE_DN;
        DBMSName[ 0 ] = '\0';
-       rc = SQLGetInfo( dbc->dbh, SQL_DBMS_NAME, (PTR)&DBMSName,
+       rc = SQLGetInfo( *dbhp, SQL_DBMS_NAME, (PTR)&DBMSName,
                        sizeof( DBMSName ), NULL );
        if ( rc == SQL_SUCCESS ) {
                if ( strcmp( DBMSName, "TimesTen" ) == 0 ||
-                               strcmp( DBMSName, "Front-Tier" ) == 0 ) {
-                       Debug( LDAP_DEBUG_TRACE, "backsql_open_db_conn(%lu): "
-                               "TimesTen database!\n", ldap_cid, 0, 0 );
+                       strcmp( DBMSName, "Front-Tier" ) == 0 )
+               {
+                       Debug( LDAP_DEBUG_TRACE, "backsql_open_db_handle(): "
+                               "TimesTen database!\n",
+                               0, 0, 0 );
                        bi->sql_flags |= BSQLF_USE_REVERSE_DN;
                }
+
        } else {
-               Debug( LDAP_DEBUG_TRACE, "backsql_open_db_conn(%lu): "
-                       "SQLGetInfo() failed.\n", ldap_cid, 0, 0 );
-               backsql_PrintErrors( bi->sql_db_env, dbc->dbh, SQL_NULL_HENV, rc );
-               return rc;
+               Debug( LDAP_DEBUG_TRACE, "backsql_open_db_handle(): "
+                       "SQLGetInfo() failed.\n",
+                       0, 0, 0 );
+               backsql_PrintErrors( bi->sql_db_env, *dbhp, SQL_NULL_HENV, rc );
+               SQLDisconnect( *dbhp );
+               SQLFreeConnect( *dbhp );
+               return LDAP_UNAVAILABLE;
        }
        /* end TimesTen */
 
-       Debug( LDAP_DEBUG_TRACE, "backsql_open_db_conn(%lu): "
-               "connected, adding to tree.\n", ldap_cid, 0, 0 );
-       ldap_pvt_thread_mutex_lock( &bi->sql_dbconn_mutex );
-       if ( avl_insert( &bi->sql_db_conns, dbc, backsql_cmp_connid, avl_dup_error ) ) {
-               Debug( LDAP_DEBUG_TRACE, "backsql_open_db_conn(%lu): "
-                       "duplicate connection ID.\n", ldap_cid, 0, 0 );
-               return LDAP_OTHER;
-       }
-       ldap_pvt_thread_mutex_unlock( &bi->sql_dbconn_mutex );
-       Debug( LDAP_DEBUG_TRACE, "<==backsql_open_db_conn(%lu)\n", ldap_cid, 0, 0 );
-
-       *pdbc = dbc;
+       Debug( LDAP_DEBUG_TRACE, "<==backsql_open_db_handle()\n",
+               0, 0, 0 );
 
        return LDAP_SUCCESS;
 }
 
 int
-backsql_free_db_conn( Operation *op )
+backsql_free_db_conn( Operation *op, SQLHDBC dbh )
 {
-       backsql_info            *bi = (backsql_info *)op->o_bd->be_private;
-       backsql_db_conn         tmp = { 0 },
-                               *conn;
-
        Debug( LDAP_DEBUG_TRACE, "==>backsql_free_db_conn()\n", 0, 0, 0 );
-       tmp.ldap_cid = op->o_connid;
-       ldap_pvt_thread_mutex_lock( &bi->sql_dbconn_mutex );
-       conn = avl_delete( &bi->sql_db_conns, &tmp, backsql_cmp_connid );
-       ldap_pvt_thread_mutex_unlock( &bi->sql_dbconn_mutex );
 
-       /*
-        * we have one thread per connection, as I understand -- so we can
-        * get this out of critical section
-        */
-       if ( conn != NULL ) {
-               Debug( LDAP_DEBUG_TRACE, "backsql_free_db_conn(): "
-                       "closing db connection %lu (%p)\n",
-                       op->o_connid, (void *)conn, 0 );
-               backsql_close_db_conn( (void *)conn );
-       }
+       (void)backsql_close_db_handle( dbh );
 
        Debug( LDAP_DEBUG_TRACE, "<==backsql_free_db_conn()\n", 0, 0, 0 );
 
-       return conn ? SQL_SUCCESS : SQL_ERROR;
+       return LDAP_SUCCESS;
+}
+
+static void    *backsql_db_conn_dummy;
+
+static void
+backsql_db_conn_keyfree(
+       void            *key,
+       void            *data )
+{
+       backsql_close_db_handle( (SQLHDBC)data );
 }
 
 int
-backsql_get_db_conn( Operation *op, SQLHDBC *dbh )
+backsql_get_db_conn( Operation *op, SQLHDBC *dbhp )
 {
-       backsql_info            *bi = (backsql_info *)op->o_bd->be_private;
-       backsql_db_conn         *dbc,
-                               tmp = { 0 };
-       int                     rc = LDAP_SUCCESS;
+       backsql_info    *bi = (backsql_info *)op->o_bd->be_private;
+       int             rc = LDAP_SUCCESS;
+       SQLHDBC         dbh = SQL_NULL_HDBC;
 
        Debug( LDAP_DEBUG_TRACE, "==>backsql_get_db_conn()\n", 0, 0, 0 );
 
-       assert( dbh != NULL );
-       *dbh = SQL_NULL_HDBC;
+       assert( dbhp != NULL );
+       *dbhp = SQL_NULL_HDBC;
 
-       tmp.ldap_cid = op->o_connid;
+       if ( op->o_threadctx ) {
+               void            *data = NULL;
 
-       /*
-        * we have one thread per connection, as I understand -- 
-        * so we do not need locking here
-        */
-       dbc = avl_find( bi->sql_db_conns, &tmp, backsql_cmp_connid );
-       if ( !dbc ) {
-               rc = backsql_open_db_conn( bi, op->o_connid, &dbc );
-               if ( rc != LDAP_SUCCESS) {
-                       Debug( LDAP_DEBUG_TRACE, "backsql_get_db_conn(): "
-                               "could not get connection handle "
-                               "-- returning NULL\n", 0, 0, 0 );
-                       return rc;
-               }
+               ldap_pvt_thread_pool_getkey( op->o_threadctx,
+                               &backsql_db_conn_dummy, &data, NULL );
+               dbh = (SQLHDBC)data;
+
+       } else {
+               dbh = bi->sql_dbh;
        }
 
-       ldap_pvt_thread_mutex_lock( &bi->sql_schema_mutex );
-       if ( !BACKSQL_SCHEMA_LOADED( bi ) ) {
-               Debug( LDAP_DEBUG_TRACE, "backsql_get_db_conn(): "
-                       "first call -- reading schema map\n", 0, 0, 0 );
-               rc = backsql_load_schema_map( bi, dbc->dbh );
+       if ( dbh == SQL_NULL_HDBC ) {
+               rc = backsql_open_db_handle( bi, &dbh );
                if ( rc != LDAP_SUCCESS ) {
-                       ldap_pvt_thread_mutex_unlock( &bi->sql_schema_mutex );
-                       backsql_free_db_conn( op );
                        return rc;
                }
+
+               if ( op->o_threadctx ) {
+                       void            *data = NULL;
+
+                       data = (void *)dbh;
+                       ldap_pvt_thread_pool_setkey( op->o_threadctx,
+                                       &backsql_db_conn_dummy, data,
+                                       backsql_db_conn_keyfree );
+
+               } else {
+                       bi->sql_dbh = dbh;
+               }
        }
-       ldap_pvt_thread_mutex_unlock( &bi->sql_schema_mutex );
 
-       *dbh = dbc->dbh;
+       *dbhp = dbh;
 
        Debug( LDAP_DEBUG_TRACE, "<==backsql_get_db_conn()\n", 0, 0, 0 );
 
index 8bb21b559161b42b5437ee0607d6ddc1ff8efe22..3d83060f557712d26bca64b69ec5a54457a18994 100644 (file)
@@ -34,6 +34,7 @@
 #include <sys/stat.h>
 
 #include "slap.h"
+#include "config.h"
 #include "lutil.h"
 #include "lber_pvt.h"
 
@@ -189,7 +190,7 @@ backend_set_controls( BackendDB *be )
 }
 
 /* startup a specific backend database */
-int backend_startup_one(Backend *be)
+int backend_startup_one(Backend *be, ConfigReply *cr)
 {
        int             rc = 0;
 
@@ -208,8 +209,19 @@ int backend_startup_one(Backend *be)
        /* set database controls */
        (void)backend_set_controls( be );
 
+#if 0
+       if ( !BER_BVISEMPTY( &be->be_rootndn )
+               && select_backend( &be->be_rootndn, 0 ) == be
+               && BER_BVISNULL( &be->be_rootpw ) )
+       {
+               /* warning: if rootdn entry is created,
+                * it can take rootdn privileges;
+                * set empty rootpw to prevent */
+       }
+#endif
+
        if ( be->bd_info->bi_db_open ) {
-               rc = be->bd_info->bi_db_open( be );
+               rc = be->bd_info->bi_db_open( be, cr );
                if ( rc == 0 ) {
                        (void)backend_set_controls( be );
 
@@ -228,6 +240,7 @@ int backend_startup(Backend *be)
        int i;
        int rc = 0;
        BackendInfo *bi;
+       ConfigReply cr={0, ""};
 
        if( ! ( nBackendDB > 0 ) ) {
                /* no databases */
@@ -251,12 +264,12 @@ int backend_startup(Backend *be)
                /* append global access controls */
                acl_append( &be->be_acl, frontendDB->be_acl, -1 );
 
-               return backend_startup_one( be );
+               return backend_startup_one( be, &cr );
        }
 
        /* open frontend, if required */
        if ( frontendDB->bd_info->bi_db_open ) {
-               rc = frontendDB->bd_info->bi_db_open( frontendDB );
+               rc = frontendDB->bd_info->bi_db_open( frontendDB, NULL );
                if ( rc != 0 ) {
                        Debug( LDAP_DEBUG_ANY,
                                "backend_startup: bi_db_open(frontend) failed! (%d)\n",
@@ -300,7 +313,7 @@ int backend_startup(Backend *be)
                /* append global access controls */
                acl_append( &be->be_acl, frontendDB->be_acl, -1 );
 
-               rc = backend_startup_one( be );
+               rc = backend_startup_one( be, &cr );
 
                if ( rc ) return rc;
        }
@@ -336,7 +349,7 @@ int backend_shutdown( Backend *be )
                }
 
                if ( be->bd_info->bi_db_close ) {
-                       be->bd_info->bi_db_close( be );
+                       be->bd_info->bi_db_close( be, NULL );
                }
 
                if( be->bd_info->bi_close ) {
@@ -349,7 +362,7 @@ int backend_shutdown( Backend *be )
        /* close each backend database */
        LDAP_STAILQ_FOREACH( be, &backendDB, be_next ) {
                if ( be->bd_info->bi_db_close ) {
-                       be->bd_info->bi_db_close( be );
+                       be->bd_info->bi_db_close( be, NULL );
                }
 
                if(rc != 0) {
@@ -373,7 +386,7 @@ int backend_shutdown( Backend *be )
 
        /* close frontend, if required */
        if ( frontendDB->bd_info->bi_db_close ) {
-               rc = frontendDB->bd_info->bi_db_close ( frontendDB );
+               rc = frontendDB->bd_info->bi_db_close ( frontendDB, NULL );
                if ( rc != 0 ) {
                        Debug( LDAP_DEBUG_ANY,
                                "backend_startup: bi_db_close(frontend) failed! (%d)\n",
@@ -411,14 +424,14 @@ backend_stopdown_one( BackendDB *bd )
        }
 
        if ( bd->bd_info->bi_db_destroy ) {
-               bd->bd_info->bi_db_destroy( bd );
+               bd->bd_info->bi_db_destroy( bd, NULL );
        }
 }
 
 void backend_destroy_one( BackendDB *bd, int dynamic )
 {
        if ( dynamic ) {
-               LDAP_STAILQ_REMOVE(&backendDB, bd, slap_backend_db, be_next );
+               LDAP_STAILQ_REMOVE(&backendDB, bd, BackendDB, be_next );
        }
 
        if ( bd->be_syncinfo ) {
@@ -440,16 +453,6 @@ void backend_destroy_one( BackendDB *bd, int dynamic )
        }
        acl_destroy( bd->be_acl, frontendDB->be_acl );
        limits_destroy( bd->be_limits );
-       if ( bd->be_replogfile ) {
-               ch_free( bd->be_replogfile );
-       }
-       if ( bd->be_replica_argsfile ) {
-               ch_free( bd->be_replica_argsfile );
-       }
-       if ( bd->be_replica_pidfile ) {
-               ch_free( bd->be_replica_pidfile );
-       }
-       destroy_replica_info( bd );
        if ( !BER_BVISNULL( &bd->be_update_ndn ) ) {
                ch_free( bd->be_update_ndn.bv_val );
        }
@@ -486,7 +489,7 @@ int backend_destroy(void)
        bd = frontendDB;
        if ( bd ) {
                if ( bd->bd_info->bi_db_destroy ) {
-                       bd->bd_info->bi_db_destroy( bd );
+                       bd->bd_info->bi_db_destroy( bd, NULL );
                }
                ber_bvarray_free( bd->be_suffix );
                ber_bvarray_free( bd->be_nsuffix );
@@ -500,17 +503,6 @@ int backend_destroy(void)
                        free( bd->be_rootpw.bv_val );
                }
                acl_destroy( bd->be_acl, frontendDB->be_acl );
-
-               if ( bd->be_replogfile != NULL ) {
-                       free( bd->be_replogfile );
-               }
-               if ( bd->be_replica_argsfile ) {
-                       ch_free( bd->be_replica_argsfile );
-               }
-               if ( bd->be_replica_pidfile ) {
-                       ch_free( bd->be_replica_pidfile );
-               }
-               assert( bd->be_replica == NULL );
        }
 
        return 0;
@@ -560,7 +552,7 @@ backend_db_move(
        int idx
 )
 {
-       LDAP_STAILQ_REMOVE(&backendDB, be, slap_backend_db, be_next);
+       LDAP_STAILQ_REMOVE(&backendDB, be, BackendDB, be_next);
        backend_db_insert(be, idx);
 }
 
@@ -568,7 +560,8 @@ BackendDB *
 backend_db_init(
     const char *type,
        BackendDB *b0,
-       int idx )
+       int idx,
+       ConfigReply *cr)
 {
        BackendInfo *bi = backend_info(type);
        BackendDB *be = b0;
@@ -607,14 +600,14 @@ backend_db_init(
        be->be_max_deref_depth = SLAPD_DEFAULT_MAXDEREFDEPTH; 
 
        if ( bi->bi_db_init ) {
-               rc = bi->bi_db_init( be );
+               rc = bi->bi_db_init( be, cr );
        }
 
        if ( rc != 0 ) {
                fprintf( stderr, "database init failed (%s)\n", type );
                /* If we created and linked this be, remove it and free it */
                if ( !b0 ) {
-                       LDAP_STAILQ_REMOVE(&backendDB, be, slap_backend_db, be_next);
+                       LDAP_STAILQ_REMOVE(&backendDB, be, BackendDB, be_next);
                        ch_free( be );
                        be = NULL;
                        nbackends--;
@@ -632,12 +625,12 @@ be_db_close( void )
 
        LDAP_STAILQ_FOREACH( be, &backendDB, be_next ) {
                if ( be->bd_info->bi_db_close ) {
-                       be->bd_info->bi_db_close( be );
+                       be->bd_info->bi_db_close( be, NULL );
                }
        }
 
        if ( frontendDB->bd_info->bi_db_close ) {
-               frontendDB->bd_info->bi_db_close( frontendDB );
+               frontendDB->bd_info->bi_db_close( frontendDB, NULL );
        }
 
 }
@@ -645,12 +638,11 @@ be_db_close( void )
 Backend *
 select_backend(
        struct berval * dn,
-       int manageDSAit,
        int noSubs )
 {
        int             j;
        ber_len_t       len, dnlen = dn->bv_len;
-       Backend         *be, *b2 = NULL;
+       Backend         *be;
 
        LDAP_STAILQ_FOREACH( be, &backendDB, be_next ) {
                if ( be->be_nsuffix == NULL || SLAP_DBHIDDEN( be )) {
@@ -684,28 +676,12 @@ select_backend(
                        if ( strcmp( be->be_nsuffix[j].bv_val,
                                &dn->bv_val[dnlen-len] ) == 0 )
                        {
-                               if( b2 == NULL ) {
-                                       b2 = be;
-
-                                       if( manageDSAit && len == dnlen &&
-                                               !SLAP_GLUE_SUBORDINATE( be ) ) {
-                                               continue;
-                                       }
-                               } else {
-                                       /* If any parts of the tree are glued, use the first
-                                        * match regardless of manageDSAit. Otherwise use the
-                                        * last match.
-                                        */
-                                       if( !( SLAP_DBFLAGS( be ) & ( SLAP_DBFLAG_GLUE_INSTANCE |
-                                               SLAP_DBFLAG_GLUE_SUBORDINATE )))
-                                               b2 = be;
-                               }
-                               return b2;
+                               return be;
                        }
                }
        }
 
-       return b2;
+       return be;
 }
 
 int
@@ -728,6 +704,26 @@ be_issuffix(
        return 0;
 }
 
+int
+be_issubordinate(
+    Backend *be,
+    struct berval *bvsubordinate )
+{
+       int     i;
+
+       if ( be->be_nsuffix == NULL ) {
+               return 0;
+       }
+
+       for ( i = 0; !BER_BVISNULL( &be->be_nsuffix[i] ); i++ ) {
+               if ( dnIsSuffix( bvsubordinate, &be->be_nsuffix[i] ) ) {
+                       return 1;
+               }
+       }
+
+       return 0;
+}
+
 int
 be_isroot_dn( Backend *be, struct berval *ndn )
 {
@@ -780,14 +776,46 @@ be_isroot( Operation *op )
 int
 be_isroot_pw( Operation *op )
 {
-       int result;
+       return be_rootdn_bind( op, NULL ) == LDAP_SUCCESS;
+}
 
-       if ( ! be_isroot_dn( op->o_bd, &op->o_req_ndn ) ) {
-               return 0;
+/*
+ * checks if binding as rootdn
+ *
+ * return value:
+ *     SLAP_CB_CONTINUE                if not the rootdn
+ *     LDAP_SUCCESS                    if rootdn & rootpw
+ *     LDAP_INVALID_CREDENTIALS        if rootdn & !rootpw
+ *
+ * if rs != NULL
+ *     if LDAP_SUCCESS, op->orb_edn is set
+ *     if LDAP_INVALID_CREDENTIALS, response is sent to client
+ */
+int
+be_rootdn_bind( Operation *op, SlapReply *rs )
+{
+       int             rc;
+
+       assert( op->o_tag == LDAP_REQ_BIND );
+       assert( op->orb_method == LDAP_AUTH_SIMPLE );
+
+       if ( !be_isroot_dn( op->o_bd, &op->o_req_ndn ) ) {
+               return SLAP_CB_CONTINUE;
+       }
+
+       if ( BER_BVISNULL( &op->o_bd->be_rootpw ) ) {
+               /* give the database a chance */
+               return SLAP_CB_CONTINUE;
        }
 
        if ( BER_BVISEMPTY( &op->o_bd->be_rootpw ) ) {
-               return 0;
+               /* rootdn bind explicitly disallowed */
+               rc = LDAP_INVALID_CREDENTIALS;
+               if ( rs ) {
+                       goto send_result;
+               }
+
+               return rc;
        }
 
 #ifdef SLAPD_SPASSWD
@@ -795,13 +823,31 @@ be_isroot_pw( Operation *op )
                op->o_conn->c_sasl_authctx, NULL );
 #endif
 
-       result = lutil_passwd( &op->o_bd->be_rootpw, &op->orb_cred, NULL, NULL );
+       rc = lutil_passwd( &op->o_bd->be_rootpw, &op->orb_cred, NULL, NULL );
 
 #ifdef SLAPD_SPASSWD
        ldap_pvt_thread_pool_setkey( op->o_threadctx, slap_sasl_bind, NULL, NULL );
 #endif
 
-       return result == 0;
+       rc = ( rc == 0 ? LDAP_SUCCESS : LDAP_INVALID_CREDENTIALS );
+       if ( rs ) {
+send_result:;
+               rs->sr_err = rc;
+
+               Debug( LDAP_DEBUG_TRACE, "%s: rootdn=\"%s\" bind%s\n", 
+                       op->o_log_prefix, op->o_bd->be_rootdn.bv_val,
+                       rc == LDAP_SUCCESS ? " succeeded" : " failed" );
+
+               if ( rc == LDAP_SUCCESS ) {
+                       /* Set to the pretty rootdn */
+                       ber_dupbv( &op->orb_edn, &op->o_bd->be_rootdn );
+
+               } else {
+                       send_ldap_result( op, rs );
+               }
+       }
+
+       return rc;
 }
 
 int
@@ -1300,7 +1346,7 @@ fe_acl_group(
        GroupAssertion *g;
        Backend *be = op->o_bd;
 
-       op->o_bd = select_backend( gr_ndn, 0, 0 );
+       op->o_bd = select_backend( gr_ndn, 0 );
 
        for ( g = op->o_groups; g; g = g->ga_next ) {
                if ( g->ga_be != op->o_bd || g->ga_oc != group_oc ||
@@ -1321,124 +1367,159 @@ fe_acl_group(
        if ( target && dn_match( &target->e_nname, gr_ndn ) ) {
                e = target;
                rc = 0;
+
        } else {
                op->o_private = NULL;
                rc = be_entry_get_rw( op, gr_ndn, group_oc, group_at, 0, &e );
                e_priv = op->o_private;
                op->o_private = o_priv;
        }
+
        if ( e ) {
                a = attr_find( e->e_attrs, group_at );
                if ( a ) {
-                       /* If the attribute is a subtype of labeledURI, treat this as
-                        * a dynamic group ala groupOfURLs
+                       /* If the attribute is a subtype of labeledURI,
+                        * treat this as a dynamic group ala groupOfURLs
                         */
-                       if (is_at_subtype( group_at->ad_type,
+                       if ( is_at_subtype( group_at->ad_type,
                                slap_schema.si_ad_labeledURI->ad_type ) )
                        {
                                int i;
                                LDAPURLDesc *ludp;
                                struct berval bv, nbase;
                                Filter *filter;
-                               Entry *user;
+                               Entry *user = NULL;
                                void *user_priv = NULL;
                                Backend *b2 = op->o_bd;
 
                                if ( target && dn_match( &target->e_nname, op_ndn ) ) {
                                        user = target;
-                               } else {
-                                       op->o_bd = select_backend( op_ndn, 0, 0 );
-                                       op->o_private = NULL;
-                                       rc = be_entry_get_rw(op, op_ndn, NULL, NULL, 0, &user );
-                                       user_priv = op->o_private;
-                                       op->o_private = o_priv;
                                }
                                
-                               if ( rc == 0 ) {
-                                       rc = LDAP_COMPARE_FALSE;
-                                       for ( i = 0; !BER_BVISNULL( &a->a_vals[i] ); i++ ) {
-                                               if ( ldap_url_parse( a->a_vals[i].bv_val, &ludp ) !=
-                                                       LDAP_URL_SUCCESS )
-                                               {
-                                                       continue;
+                               rc = LDAP_COMPARE_FALSE;
+                               for ( i = 0; !BER_BVISNULL( &a->a_vals[i] ); i++ ) {
+                                       if ( ldap_url_parse( a->a_vals[i].bv_val, &ludp ) !=
+                                               LDAP_URL_SUCCESS )
+                                       {
+                                               continue;
+                                       }
+
+                                       BER_BVZERO( &nbase );
+
+                                       /* host, attrs and extensions parts must be empty */
+                                       if ( ( ludp->lud_host && *ludp->lud_host )
+                                               || ludp->lud_attrs
+                                               || ludp->lud_exts )
+                                       {
+                                               goto loopit;
+                                       }
+
+                                       ber_str2bv( ludp->lud_dn, 0, 0, &bv );
+                                       if ( dnNormalize( 0, NULL, NULL, &bv, &nbase,
+                                               op->o_tmpmemctx ) != LDAP_SUCCESS )
+                                       {
+                                               goto loopit;
+                                       }
+
+                                       switch ( ludp->lud_scope ) {
+                                       case LDAP_SCOPE_BASE:
+                                               if ( !dn_match( &nbase, op_ndn ) ) {
+                                                       goto loopit;
                                                }
-                                               BER_BVZERO( &nbase );
-                                               /* host part must be empty */
-                                               /* attrs and extensions parts must be empty */
-                                               if ( ( ludp->lud_host && *ludp->lud_host ) ||
-                                                       ludp->lud_attrs || ludp->lud_exts )
-                                               {
+                                               break;
+                                       case LDAP_SCOPE_ONELEVEL:
+                                               dnParent( op_ndn, &bv );
+                                               if ( !dn_match( &nbase, &bv ) ) {
                                                        goto loopit;
                                                }
-                                               ber_str2bv( ludp->lud_dn, 0, 0, &bv );
-                                               if ( dnNormalize( 0, NULL, NULL, &bv, &nbase,
-                                                       op->o_tmpmemctx ) != LDAP_SUCCESS )
+                                               break;
+                                       case LDAP_SCOPE_SUBTREE:
+                                               if ( !dnIsSuffix( op_ndn, &nbase ) ) {
+                                                       goto loopit;
+                                               }
+                                               break;
+                                       case LDAP_SCOPE_SUBORDINATE:
+                                               if ( dn_match( &nbase, op_ndn ) ||
+                                                       !dnIsSuffix( op_ndn, &nbase ) )
                                                {
                                                        goto loopit;
                                                }
-                                               switch ( ludp->lud_scope ) {
-                                               case LDAP_SCOPE_BASE:
-                                                       if ( !dn_match( &nbase, op_ndn ) ) {
-                                                               goto loopit;
-                                                       }
-                                                       break;
-                                               case LDAP_SCOPE_ONELEVEL:
-                                                       dnParent( op_ndn, &bv );
-                                                       if ( !dn_match( &nbase, &bv ) ) {
-                                                               goto loopit;
-                                                       }
-                                                       break;
-                                               case LDAP_SCOPE_SUBTREE:
-                                                       if ( !dnIsSuffix( op_ndn, &nbase ) ) {
-                                                               goto loopit;
-                                                       }
-                                                       break;
-                                               case LDAP_SCOPE_SUBORDINATE:
-                                                       if ( dn_match( &nbase, op_ndn ) ||
-                                                               !dnIsSuffix( op_ndn, &nbase ) )
-                                                       {
+                                       }
+
+                                       /* NOTE: this could be NULL
+                                        * if no filter is provided,
+                                        * or if filter parsing fails.
+                                        * In the latter case,
+                                        * we should give up. */
+                                       if ( ludp->lud_filter != NULL && ludp->lud_filter != '\0') {
+                                               filter = str2filter_x( op, ludp->lud_filter );
+                                               if ( filter == NULL ) {
+                                                       /* give up... */
+                                                       rc = LDAP_OTHER;
+                                                       goto loopit;
+                                               }
+
+                                               /* only get user if required
+                                                * and not available yet */
+                                               if ( user == NULL ) {   
+                                                       int rc2;
+
+                                                       op->o_bd = select_backend( op_ndn, 0 );
+                                                       op->o_private = NULL;
+                                                       rc2 = be_entry_get_rw( op, op_ndn, NULL, NULL, 0, &user );
+                                                       user_priv = op->o_private;
+                                                       op->o_private = o_priv;
+                                                       if ( rc2 != 0 ) {
+                                                               /* give up... */
+                                                               rc = LDAP_OTHER;
                                                                goto loopit;
                                                        }
                                                }
-                                               filter = str2filter_x( op, ludp->lud_filter );
-                                               if ( filter ) {
-                                                       if ( test_filter( NULL, user, filter ) ==
-                                                               LDAP_COMPARE_TRUE )
-                                                       {
-                                                               rc = 0;
-                                                       }
-                                                       filter_free_x( op, filter );
+
+                                               if ( test_filter( NULL, user, filter ) ==
+                                                       LDAP_COMPARE_TRUE )
+                                               {
+                                                       rc = 0;
                                                }
+                                               filter_free_x( op, filter );
+                                       }
 loopit:
-                                               ldap_free_urldesc( ludp );
-                                               if ( !BER_BVISNULL( &nbase ) ) {
-                                                       op->o_tmpfree( nbase.bv_val, op->o_tmpmemctx );
-                                               }
-                                               if ( rc == 0 ) break;
+                                       ldap_free_urldesc( ludp );
+                                       if ( !BER_BVISNULL( &nbase ) ) {
+                                               op->o_tmpfree( nbase.bv_val, op->o_tmpmemctx );
                                        }
-                                       if ( user != target ) {
-                                               op->o_private = user_priv;
-                                               be_entry_release_r( op, user );
-                                               op->o_private = o_priv;
+                                       if ( rc != LDAP_COMPARE_FALSE ) {
+                                               break;
                                        }
                                }
+
+                               if ( user != NULL && user != target ) {
+                                       op->o_private = user_priv;
+                                       be_entry_release_r( op, user );
+                                       op->o_private = o_priv;
+                               }
                                op->o_bd = b2;
+
                        } else {
                                rc = value_find_ex( group_at,
-                               SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH |
-                               SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH,
-                               a->a_nvals, op_ndn, op->o_tmpmemctx );
-                               if ( rc == LDAP_NO_SUCH_ATTRIBUTE )
+                                       SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH |
+                                       SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH,
+                                       a->a_nvals, op_ndn, op->o_tmpmemctx );
+                               if ( rc == LDAP_NO_SUCH_ATTRIBUTE ) {
                                        rc = LDAP_COMPARE_FALSE;
+                               }
                        }
+
                } else {
                        rc = LDAP_NO_SUCH_ATTRIBUTE;
                }
+
                if ( e != target ) {
                        op->o_private = e_priv;
                        be_entry_release_r( op, e );
                        op->o_private = o_priv;
                }
+
        } else {
                rc = LDAP_NO_SUCH_OBJECT;
        }
@@ -1455,6 +1536,7 @@ loopit:
                g->ga_next = op->o_groups;
                op->o_groups = g;
        }
+
 done:
        op->o_bd = be;
        return rc;
@@ -1501,7 +1583,7 @@ fe_acl_attribute(
        AccessControlState      acl_state = ACL_STATE_INIT;
        Backend                 *be = op->o_bd;
 
-       op->o_bd = select_backend( edn, 0, 0 );
+       op->o_bd = select_backend( edn, 0 );
 
        if ( target && dn_match( &target->e_nname, edn ) ) {
                e = target;
@@ -1654,7 +1736,7 @@ backend_access(
        assert( edn != NULL );
        assert( access > ACL_NONE );
 
-       op->o_bd = select_backend( edn, 0, 0 );
+       op->o_bd = select_backend( edn, 0 );
 
        if ( target && dn_match( &target->e_nname, edn ) ) {
                e = target;
@@ -1776,7 +1858,7 @@ fe_aux_operational(
                BackendDB               *be_orig = op->o_bd;
 
                /* Let the overlays have a chance at this */
-               op->o_bd = select_backend( &op->o_req_ndn, 0, 0 );
+               op->o_bd = select_backend( &op->o_req_ndn, 0 );
                if ( op->o_bd != NULL && !be_match( op->o_bd, frontendDB ) &&
                        ( SLAP_OPATTRS( rs->sr_attr_flags ) || rs->sr_attrs ) &&
                        op->o_bd->be_operational != NULL )
index 58cdab69b615069a3f5538a22b8e01a2eb7bad8b..78d0633cc2f82c2406173f3e20b4e598d4afbe74 100644 (file)
@@ -35,6 +35,7 @@
 
 #define SLAPD_TOOLS
 #include "slap.h"
+#include "config.h"
 
 typedef struct gluenode {
        BackendDB *gn_be;
@@ -583,7 +584,7 @@ glue_open (
                                        gi->gi_n[i].gn_be->bd_info );
                        /* Let backend.c take care of the rest of startup */
                        if ( !rc )
-                               rc = backend_startup_one( gi->gi_n[i].gn_be );
+                               rc = backend_startup_one( gi->gi_n[i].gn_be, NULL );
                        if ( rc ) break;
                }
                if ( !rc && !bsame && on->on_info->oi_orig->bi_open )
@@ -816,7 +817,8 @@ glue_tool_sync (
 
 static int
 glue_db_init(
-       BackendDB *be
+       BackendDB *be,
+       ConfigReply *cr
 )
 {
        slap_overinst   *on = (slap_overinst *)be->bd_info;
@@ -861,7 +863,6 @@ glue_db_init(
 
        /*FIXME : need to add support */
        oi->oi_bi.bi_tool_dn2id_get = 0;
-       oi->oi_bi.bi_tool_id2entry_get = 0;
        oi->oi_bi.bi_tool_entry_modify = 0;
 
        SLAP_DBFLAGS( be ) |= SLAP_DBFLAG_GLUE_INSTANCE;
@@ -871,7 +872,8 @@ glue_db_init(
 
 static int
 glue_db_destroy (
-       BackendDB *be
+       BackendDB *be,
+       ConfigReply *cr
 )
 {
        slap_overinst   *on = (slap_overinst *)be->bd_info;
@@ -883,7 +885,8 @@ glue_db_destroy (
 
 static int
 glue_db_close( 
-       BackendDB *be
+       BackendDB *be,
+       ConfigReply *cr
 )
 {
        slap_overinst   *on = (slap_overinst *)be->bd_info;
index eccc395fedbca24b2bfd12a6a09b8e8dba2e52f8..874ccf065abf33ff4f1657c6ffffa69c7ed12c02 100644 (file)
@@ -51,14 +51,14 @@ over_db_func(
        func = &oi->oi_orig->bi_db_open;
        if ( func[which] ) {
                be->bd_info = oi->oi_orig;
-               rc = func[which]( be );
+               rc = func[which]( be, NULL );
        }
 
        for (; on && rc == 0; on=on->on_next) {
                be->bd_info = &on->on_bi;
                func = &on->on_bi.bi_db_open;
                if (func[which]) {
-                       rc = func[which]( be );
+                       rc = func[which]( be, NULL );
                }
        }
        be->bd_info = bi_orig;
@@ -147,6 +147,7 @@ over_db_config(
                        ca.bi = &on->on_bi;
                        ct = config_find_keyword( on->on_bi.bi_cf_ocs->co_table, &ca );
                        if ( ct ) {
+                               ca.table = on->on_bi.bi_cf_ocs->co_type;
                                rc = config_add_vals( ct, &ca );
                                if ( rc != SLAP_CONF_UNKNOWN )
                                        break;
@@ -167,7 +168,8 @@ over_db_config(
 
 static int
 over_db_open(
-       BackendDB *be
+       BackendDB *be,
+       ConfigReply *cr
 )
 {
        return over_db_func( be, db_open );
@@ -175,7 +177,8 @@ over_db_open(
 
 static int
 over_db_close(
-       BackendDB *be
+       BackendDB *be,
+       ConfigReply *cr
 )
 {
        slap_overinfo *oi = be->bd_info->bi_private;
@@ -186,13 +189,13 @@ over_db_close(
        for (; on && rc == 0; on=on->on_next) {
                be->bd_info = &on->on_bi;
                if ( be->bd_info->bi_db_close ) {
-                       rc = be->bd_info->bi_db_close( be );
+                       rc = be->bd_info->bi_db_close( be, NULL );
                }
        }
 
        if ( oi->oi_orig->bi_db_close ) {
                be->bd_info = oi->oi_orig;
-               rc = be->bd_info->bi_db_close( be );
+               rc = be->bd_info->bi_db_close( be, NULL );
        }
 
        be->bd_info = bi_orig;
@@ -201,7 +204,8 @@ over_db_close(
 
 static int
 over_db_destroy(
-       BackendDB *be
+       BackendDB *be,
+       ConfigReply *cr
 )
 {
        slap_overinfo *oi = be->bd_info->bi_private;
@@ -1074,7 +1078,7 @@ overlay_destroy_one( BackendDB *be, slap_overinst *on )
                        if ( on->on_bi.bi_db_destroy ) {
                                BackendInfo *bi_orig = be->bd_info;
                                be->bd_info = (BackendInfo *)on;
-                               on->on_bi.bi_db_destroy( be );
+                               on->on_bi.bi_db_destroy( be, NULL );
                                be->bd_info = bi_orig;
                        }
                        free( on );
@@ -1280,7 +1284,7 @@ overlay_config( BackendDB *be, const char *ov, int idx, BackendInfo **res )
        if ( on2->on_bi.bi_db_init ) {
                int rc;
                be->bd_info = (BackendInfo *)on2;
-               rc = on2->on_bi.bi_db_init( be );
+               rc = on2->on_bi.bi_db_init( be, NULL );
                be->bd_info = (BackendInfo *)oi;
                if ( rc ) {
                        *prev = on2->on_next;
index baa42e446c57c2e55e07e7b6744432815ab185fb..19e7b569b339e1a980b4b830498d012680a347c8 100644 (file)
@@ -125,10 +125,10 @@ static ConfigDriver config_requires;
 static ConfigDriver config_security;
 static ConfigDriver config_referral;
 static ConfigDriver config_loglevel;
-static ConfigDriver config_replica;
 static ConfigDriver config_updatedn;
 static ConfigDriver config_updateref;
 static ConfigDriver config_include;
+static ConfigDriver config_obsolete;
 #ifdef HAVE_TLS
 static ConfigDriver config_tls_option;
 static ConfigDriver config_tls_config;
@@ -148,6 +148,7 @@ enum {
        CFG_TLS_DH_FILE,
        CFG_TLS_VERIFY,
        CFG_TLS_CRLCHECK,
+       CFG_TLS_CRL_FILE,
        CFG_CONCUR,
        CFG_THREADS,
        CFG_SALT,
@@ -160,10 +161,6 @@ enum {
        CFG_DIT,
        CFG_ATTR,
        CFG_ATOPT,
-       CFG_REPLICA_ARGSFILE,
-       CFG_REPLICA_PIDFILE,
-       CFG_REPLICATIONINTERVAL,
-       CFG_REPLOG,
        CFG_ROOTDSE,
        CFG_LOGFILE,
        CFG_PLUGIN,
@@ -224,6 +221,9 @@ static OidRec OidMacros[] = {
  * OLcfg{Bk|Db}{Oc|At}:1               -> back-bdb(/back-hdb)
  * OLcfg{Bk|Db}{Oc|At}:2               -> back-ldif
  * OLcfg{Bk|Db}{Oc|At}:3               -> back-ldap
+ * OLcfg{Bk|Db}{Oc|At}:4               -> back-monitor
+ * OLcfg{Bk|Db}{Oc|At}:5               -> back-relay
+ * OLcfg{Bk|Db}{Oc|At}:6               -> back-sql
  */
 
 /*
@@ -239,12 +239,16 @@ 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
- * OLcfgOv{Oc|At}:15           -> auditlog
+ * 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
+ * OLcfgOv{Oc|At}:15                   -> auditlog
+ * OLcfgOv{Oc|At}:16                   -> rwm
+ * OLcfgOv{Oc|At}:17                   -> dyngroup
+ * OLcfgOv{Oc|At}:18                   -> memberof
+ * OLcfgOv{Oc|At}:19                   -> collect
  */
 
 /* alphabetical ordering */
@@ -389,7 +393,7 @@ static ConfigTable config_back_cf_table[] = {
                        "SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL },
        { "moduleload", "file", 2, 0, 0,
 #ifdef SLAPD_MODULES
-               ARG_MAGIC|CFG_MODLOAD, &config_generic,
+               ARG_MAGIC|CFG_MODLOAD|ARG_NO_DELETE, &config_generic,
 #else
                ARG_IGNORED, NULL,
 #endif
@@ -455,20 +459,20 @@ static ConfigTable config_back_cf_table[] = {
                &config_referral, "( OLcfgGlAt:41 NAME 'olcReferral' "
                        "SUP labeledURI SINGLE-VALUE )", NULL, NULL },
        { "replica", "host or uri", 2, 0, 0, ARG_DB|ARG_MAGIC,
-               &config_replica, "( OLcfgDbAt:0.7 NAME 'olcReplica' "
+               &config_obsolete, "( 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' "
+       { "replica-argsfile", NULL, 0, 0, 0, ARG_MAY_DB|ARG_MAGIC,
+               &config_obsolete, "( OLcfgGlAt:43 NAME 'olcReplicaArgsFile' "
                        "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
-       { "replica-pidfile", NULL, 0, 0, 0, ARG_MAY_DB|ARG_MAGIC|ARG_STRING|CFG_REPLICA_PIDFILE,
-               &config_generic, "( OLcfgGlAt:44 NAME 'olcReplicaPidFile' "
+       { "replica-pidfile", NULL, 0, 0, 0, ARG_MAY_DB|ARG_MAGIC,
+               &config_obsolete, "( OLcfgGlAt:44 NAME 'olcReplicaPidFile' "
                        "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
-       { "replicationInterval", NULL, 0, 0, 0, ARG_MAY_DB|ARG_MAGIC|ARG_INT|CFG_REPLICATIONINTERVAL,
-               &config_generic, "( OLcfgGlAt:45 NAME 'olcReplicationInterval' "
+       { "replicationInterval", NULL, 0, 0, 0, ARG_MAY_DB|ARG_MAGIC,
+               &config_obsolete, "( OLcfgGlAt:45 NAME 'olcReplicationInterval' "
                        "SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
-       { "replogfile", "filename", 2, 2, 0, ARG_MAY_DB|ARG_MAGIC|ARG_STRING|CFG_REPLOG,
-               &config_generic, "( OLcfgGlAt:46 NAME 'olcReplogFile' "
+       { "replogfile", "filename", 2, 2, 0, ARG_MAY_DB|ARG_MAGIC,
+               &config_obsolete, "( OLcfgGlAt:46 NAME 'olcReplogFile' "
                        "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
        { "require", "features", 2, 0, 7, ARG_MAY_DB|ARG_MAGIC,
                &config_requires, "( OLcfgGlAt:47 NAME 'olcRequires' "
@@ -616,6 +620,14 @@ static ConfigTable config_back_cf_table[] = {
 #endif
                "( OLcfgGlAt:73 NAME 'olcTLSCRLCheck' "
                        "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
+       { "TLSCRLFile", NULL, 0, 0, 0,
+#if defined(HAVE_GNUTLS)
+               CFG_TLS_CRL_FILE|ARG_STRING|ARG_MAGIC, &config_tls_option,
+#else
+               ARG_IGNORED, NULL,
+#endif
+               "( OLcfgGlAt:82 NAME 'olcTLSCRLFile' "
+                       "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
        { "TLSRandFile", NULL, 0, 0, 0,
 #ifdef HAVE_TLS
                CFG_TLS_RAND|ARG_STRING|ARG_MAGIC, &config_tls_option,
@@ -689,7 +701,7 @@ static ConfigOCs cf_ocs[] = {
                 "olcIndexSubstrIfMaxLen $ olcIndexSubstrIfMinLen $ "
                 "olcIndexSubstrAnyLen $ olcIndexSubstrAnyStep $ olcLocalSSF $ "
                 "olcLogLevel $ "
-                "olcPasswordCryptSaltFormat $ olcPasswordHash $ olcPidFile $ "
+                "olcPasswordCryptSaltFormat $ olcPidFile $ "
                 "olcPluginLogFile $ olcReadOnly $ olcReferral $ "
                 "olcReplogFile $ olcRequires $ olcRestrict $ olcReverseLookup $ "
                 "olcRootDSE $ "
@@ -700,7 +712,7 @@ static ConfigOCs cf_ocs[] = {
                 "olcTLSCACertificatePath $ olcTLSCertificateFile $ "
                 "olcTLSCertificateKeyFile $ olcTLSCipherSuite $ olcTLSCRLCheck $ "
                 "olcTLSRandFile $ olcTLSVerifyClient $ olcTLSDHParamFile $ "
-                "olcToolThreads $ "
+                "olcTLSCRLFile $ olcToolThreads $ "
                 "olcObjectIdentifier $ olcAttributeTypes $ olcObjectClasses $ "
                 "olcDitContentRules ) )", Cft_Global },
        { "( OLcfgGlOc:2 "
@@ -742,7 +754,7 @@ static ConfigOCs cf_ocs[] = {
                "NAME 'olcFrontendConfig' "
                "DESC 'OpenLDAP frontend configuration' "
                "AUXILIARY "
-               "MAY olcDefaultSearchBase )",
+               "MAY ( olcDefaultSearchBase $ olcPasswordHash ) )",
                Cft_Database, NULL, NULL },
 #ifdef SLAPD_MODULES
        { "( OLcfgGlOc:8 "
@@ -789,7 +801,6 @@ config_generic(ConfigArgs *c) {
                        if ( c->be->be_limits ) {
                                char buf[4096*3];
                                struct berval bv;
-                               int i;
 
                                for ( i=0; c->be->be_limits[i]; i++ ) {
                                        bv.bv_len = snprintf( buf, sizeof( buf ), SLAP_X_ORDERED_FMT, i );
@@ -921,25 +932,6 @@ config_generic(ConfigArgs *c) {
                        rc = (!i);
                        break;
                }
-               case CFG_REPLICA_ARGSFILE:
-                       if ( c->be->be_replica_argsfile )
-                               c->value_string = ch_strdup( c->be->be_replica_argsfile );
-                       break;
-               case CFG_REPLICA_PIDFILE:
-                       if ( c->be->be_replica_pidfile )
-                               c->value_string = ch_strdup( c->be->be_replica_pidfile );
-                       break;
-               case CFG_REPLICATIONINTERVAL:
-                       if ( c->be->be_replicationinterval > 0 ) {
-                               c->value_int = c->be->be_replicationinterval;
-                       } else {
-                               rc = 1;
-                       }
-                       break;
-               case CFG_REPLOG:
-                       if ( c->be->be_replogfile )
-                               c->value_string = ch_strdup( c->be->be_replogfile );
-                       break;
                case CFG_ROOTDSE: {
                        ConfigFile *cf = c->private;
                        if ( cf->c_dseFiles ) {
@@ -953,9 +945,9 @@ config_generic(ConfigArgs *c) {
                        if ( sid_list ) {
                                ServerID *si;
                                struct berval bv;
-                               char *ptr;
 
                                for ( si = sid_list; si; si=si->si_next ) {
+                                       assert( si->si_num >= 0 && si->si_num <= SLAP_SYNC_SID_MAX );
                                        if ( !BER_BVISEMPTY( &si->si_url )) {
                                                bv.bv_len = si->si_url.bv_len + 6;
                                                bv.bv_val = ch_malloc( bv.bv_len );
@@ -1097,32 +1089,12 @@ config_generic(ConfigArgs *c) {
                        passwd_salt = NULL;
                        break;
 
-               case CFG_REPLICA_ARGSFILE:
-                       ch_free( c->be->be_replica_argsfile );
-                       c->be->be_replica_argsfile = NULL;
-                       break;
-
-               case CFG_REPLICA_PIDFILE:
-                       ch_free( c->be->be_replica_pidfile );
-                       c->be->be_replica_pidfile = NULL;
-                       break;
-
-               case CFG_REPLICATIONINTERVAL:
-                       c->be->be_replicationinterval = 0;
-                       break;
-
-               case CFG_REPLOG:
-                       ch_free( c->be->be_replogfile );
-                       c->be->be_replogfile = NULL;
-                       break;
-
                case CFG_LOGFILE:
                        ch_free( logfileName );
                        logfileName = NULL;
                        break;
 
                case CFG_SERVERID: {
-                       int i;
                        ServerID *si, **sip;
 
                        for ( i=0, si = sid_list, sip = &sid_list;
@@ -1184,7 +1156,6 @@ config_generic(ConfigArgs *c) {
                                cfn->c_oc_head = cfn->c_oc_tail = NULL;
                        } else {
                                ObjectClass *oc, *prev = NULL;
-                               int i;
 
                                for ( i=0, oc=cfn->c_oc_head; i<c->valx; i++) {
                                        prev = oc;
@@ -1219,7 +1190,6 @@ config_generic(ConfigArgs *c) {
                                cfn->c_at_head = cfn->c_at_tail = NULL;
                        } else {
                                AttributeType *at, *prev = NULL;
-                               int i;
 
                                for ( i=0, at=cfn->c_at_head; i<c->valx; i++) {
                                        prev = at;
@@ -1256,9 +1226,9 @@ config_generic(ConfigArgs *c) {
        switch(c->type) {
                case CFG_BACKEND:
                        if(!(c->bi = backend_info(c->argv[1]))) {
-                               snprintf( c->msg, sizeof( c->msg ), "<%s> failed init", c->argv[0] );
+                               snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> failed init", c->argv[0] );
                                Debug(LDAP_DEBUG_ANY, "%s: %s (%s)!\n",
-                                       c->log, c->msg, c->argv[1] );
+                                       c->log, c->cr_msg, c->argv[1] );
                                return(1);
                        }
                        break;
@@ -1272,11 +1242,11 @@ config_generic(ConfigArgs *c) {
                        } else if ( !strcasecmp( c->argv[1], "frontend" )) {
                                c->be = frontendDB;
                        } else {
-                               c->be = backend_db_init(c->argv[1], NULL, c->valx);
+                               c->be = backend_db_init(c->argv[1], NULL, c->valx, &c->reply);
                                if ( !c->be ) {
-                                       snprintf( c->msg, sizeof( c->msg ), "<%s> failed init", c->argv[0] );
-                                       Debug(LDAP_DEBUG_ANY, "%s: %s (%s)!\n",
-                                               c->log, c->msg, c->argv[1] );
+                                       if ( c->cr_msg[0] == 0 )
+                                               snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> failed init", c->argv[0] );
+                                       Debug(LDAP_DEBUG_ANY, "%s: %s (%s)\n", c->log, c->cr_msg, c->argv[1] );
                                        return(1);
                                }
                        }
@@ -1288,19 +1258,19 @@ config_generic(ConfigArgs *c) {
 
                case CFG_THREADS:
                        if ( c->value_int < 2 ) {
-                               snprintf( c->msg, sizeof( c->msg ),
+                               snprintf( c->cr_msg, sizeof( c->cr_msg ),
                                        "threads=%d smaller than minimum value 2",
                                        c->value_int );
                                Debug(LDAP_DEBUG_ANY, "%s: %s.\n",
-                                       c->log, c->msg, 0 );
+                                       c->log, c->cr_msg, 0 );
                                return 1;
 
                        } else if ( c->value_int > 2 * SLAP_MAX_WORKER_THREADS ) {
-                               snprintf( c->msg, sizeof( c->msg ),
+                               snprintf( c->cr_msg, sizeof( c->cr_msg ),
                                        "warning, threads=%d larger than twice the default (2*%d=%d); YMMV",
                                        c->value_int, SLAP_MAX_WORKER_THREADS, 2 * SLAP_MAX_WORKER_THREADS );
                                Debug(LDAP_DEBUG_ANY, "%s: %s.\n",
-                                       c->log, c->msg, 0 );
+                                       c->log, c->cr_msg, 0 );
                        }
                        if ( slapMode & SLAP_SERVER_MODE )
                                ldap_pvt_thread_pool_maxthreads(&connection_pool, c->value_int);
@@ -1334,9 +1304,9 @@ config_generic(ConfigArgs *c) {
                case CFG_AZPOLICY:
                        ch_free(c->value_string);
                        if (slap_sasl_setpolicy( c->argv[1] )) {
-                               snprintf( c->msg, sizeof( c->msg ), "<%s> unable to parse value", c->argv[0] );
+                               snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> unable to parse value", c->argv[0] );
                                Debug(LDAP_DEBUG_ANY, "%s: %s \"%s\"\n",
-                                       c->log, c->msg, c->argv[1] );
+                                       c->log, c->cr_msg, c->argv[1] );
                                return(1);
                        }
                        break;
@@ -1351,9 +1321,9 @@ config_generic(ConfigArgs *c) {
                        {
                        char *txt = slap_sasl_secprops( c->argv[1] );
                        if ( txt ) {
-                               snprintf( c->msg, sizeof(c->msg), "<%s> %s",
+                               snprintf( c->cr_msg, sizeof(c->cr_msg), "<%s> %s",
                                        c->argv[0], txt );
-                               Debug(LDAP_DEBUG_ANY, "%s: %s\n", c->log, c->msg, 0 );
+                               Debug(LDAP_DEBUG_ANY, "%s: %s\n", c->log, c->cr_msg, 0 );
                                return(1);
                        }
                        break;
@@ -1473,90 +1443,11 @@ config_generic(ConfigArgs *c) {
                        }
                        break;
 
-               case CFG_REPLICA_ARGSFILE:
-                       if(SLAP_MONITOR(c->be)) {
-                               Debug(LDAP_DEBUG_ANY, "%s: "
-                                       "\"replica-argsfile\" should not be used "
-                                       "inside monitor database\n",
-                                       c->log, 0, 0);
-                               /* FIXME: should this be an error? */
-                               return(0);
-                       }
-
-                       if ( c->be->be_replica_argsfile != NULL ) {
-                               /* FIXME: error? */
-                               Debug(LDAP_DEBUG_ANY, "%s: "
-                                       "\"replica-argsfile\" already provided; "
-                                       "replacing \"%s\" with \"%s\".\n",
-                                       c->log, c->be->be_replica_argsfile, c->value_string );
-                               ch_free( c->be->be_replica_argsfile );
-                       }
-
-                       c->be->be_replica_argsfile = c->value_string;
-                       break;
-
-               case CFG_REPLICA_PIDFILE:
-                       if(SLAP_MONITOR(c->be)) {
-                               Debug(LDAP_DEBUG_ANY, "%s: "
-                                       "\"replica-pidfile\" should not be used "
-                                       "inside monitor database\n",
-                                       c->log, 0, 0);
-                               /* FIXME: should this be an error? */
-                               return(0);
-                       }
-
-                       if ( c->be->be_replica_pidfile != NULL ) {
-                               /* FIXME: error? */
-                               Debug(LDAP_DEBUG_ANY, "%s: "
-                                       "\"replica-pidfile\" already provided; "
-                                       "replacing \"%s\" with \"%s\".\n",
-                                       c->log, c->be->be_replica_pidfile, c->value_string );
-                               ch_free( c->be->be_replica_pidfile );
-                       }
-
-                       c->be->be_replica_pidfile = c->value_string;
-                       break;
-
-               case CFG_REPLICATIONINTERVAL:
-                       if(SLAP_MONITOR(c->be)) {
-                               Debug(LDAP_DEBUG_ANY, "%s: "
-                                       "\"replicationinterval\" should not be used "
-                                       "inside monitor database\n",
-                                       c->log, 0, 0);
-                               /* FIXME: should this be an error? */
-                               return(0);
-                       }
-
-                       c->be->be_replicationinterval = c->value_int;
-                       break;
-
-               case CFG_REPLOG:
-                       if(SLAP_MONITOR(c->be)) {
-                               Debug(LDAP_DEBUG_ANY, "%s: "
-                                       "\"replogfile\" should not be used "
-                                       "inside monitor database\n",
-                                       c->log, 0, 0);
-                               /* FIXME: should this be an error? */
-                               return(0);
-                       }
-
-                       if ( c->be->be_replogfile != NULL ) {
-                               /* FIXME: error? */
-                               Debug(LDAP_DEBUG_ANY, "%s: "
-                                       "\"replogfile\" already provided; "
-                                       "replacing \"%s\" with \"%s\".\n",
-                                       c->log, c->be->be_replogfile, c->value_string );
-                               ch_free( c->be->be_replogfile );
-                       }
-
-                       c->be->be_replogfile = c->value_string;
-                       break;
-
                case CFG_ROOTDSE:
                        if(root_dse_read_file(c->argv[1])) {
-                               snprintf( c->msg, sizeof( c->msg ), "<%s> could not read file", c->argv[0] );
+                               snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> could not read file", c->argv[0] );
                                Debug(LDAP_DEBUG_ANY, "%s: %s %s\n",
-                                       c->log, c->msg, c->argv[1] );
+                                       c->log, c->cr_msg, c->argv[1] );
                                return(1);
                        }
                        {
@@ -1572,12 +1463,14 @@ config_generic(ConfigArgs *c) {
                        {
                                ServerID *si, **sip;
                                LDAPURLDesc *lud;
-                               int num = atoi( c->argv[1] );
-                               if ( num < 0 || num > SLAP_SYNC_SID_MAX ) {
-                                       snprintf( c->msg, sizeof( c->msg ),
+                               int num;
+                               if ( lutil_atoi( &num, c->argv[1] ) ||
+                                       num < 0 || num > SLAP_SYNC_SID_MAX )
+                               {
+                                       snprintf( c->cr_msg, sizeof( c->cr_msg ),
                                                "<%s> illegal server ID", c->argv[0] );
                                        Debug(LDAP_DEBUG_ANY, "%s: %s %s\n",
-                                               c->log, c->msg, c->argv[1] );
+                                               c->log, c->cr_msg, c->argv[1] );
                                        return 1;
                                }
                                /* only one value allowed if no URL is given */
@@ -1585,18 +1478,18 @@ config_generic(ConfigArgs *c) {
                                        int len;
 
                                        if ( sid_list && BER_BVISEMPTY( &sid_list->si_url )) {
-                                               snprintf( c->msg, sizeof( c->msg ),
+                                               snprintf( c->cr_msg, sizeof( c->cr_msg ),
                                                        "<%s> only one server ID allowed now", c->argv[0] );
                                                Debug(LDAP_DEBUG_ANY, "%s: %s %s\n",
-                                                       c->log, c->msg, c->argv[1] );
+                                                       c->log, c->cr_msg, c->argv[1] );
                                                return 1;
                                        }
 
                                        if ( ldap_url_parse( c->argv[2], &lud )) {
-                                               snprintf( c->msg, sizeof( c->msg ),
+                                               snprintf( c->cr_msg, sizeof( c->cr_msg ),
                                                        "<%s> invalid URL", c->argv[0] );
                                                Debug(LDAP_DEBUG_ANY, "%s: %s %s\n",
-                                                       c->log, c->msg, c->argv[2] );
+                                                       c->log, c->cr_msg, c->argv[2] );
                                                return 1;
                                        }
                                        len = strlen( c->argv[2] );
@@ -1606,14 +1499,18 @@ config_generic(ConfigArgs *c) {
                                        strcpy( si->si_url.bv_val, c->argv[2] );
                                } else {
                                        if ( sid_list ) {
-                                               snprintf( c->msg, sizeof( c->msg ),
+                                               snprintf( c->cr_msg, sizeof( c->cr_msg ),
                                                        "<%s> unqualified server ID not allowed now", c->argv[0] );
                                                Debug(LDAP_DEBUG_ANY, "%s: %s %s\n",
-                                                       c->log, c->msg, c->argv[1] );
+                                                       c->log, c->cr_msg, c->argv[1] );
                                                return 1;
                                        }
                                        si = ch_malloc( sizeof(ServerID) );
+                                       BER_BVZERO( &si->si_url );
                                        slap_serverID = num;
+                                       Debug( LDAP_DEBUG_CONFIG,
+                                               "%s: SID=%d\n",
+                                               c->log, slap_serverID, 0 );
                                }
                                si->si_next = NULL;
                                si->si_num = num;
@@ -1664,6 +1561,10 @@ config_generic(ConfigArgs *c) {
                                                        ldap_free_urldesc( lu2 );
                                                        if ( isMe ) {
                                                                slap_serverID = si->si_num;
+                                                               Debug( LDAP_DEBUG_CONFIG,
+                                                                       "%s: SID=%d (listener=%s)\n",
+                                                                       c->log, slap_serverID,
+                                                                       l[i]->sl_url.bv_val );
                                                                break;
                                                        }
                                                }
@@ -1683,10 +1584,10 @@ config_generic(ConfigArgs *c) {
 
                case CFG_LASTMOD:
                        if(SLAP_NOLASTMODCMD(c->be)) {
-                               snprintf( c->msg, sizeof( c->msg ), "<%s> not available for %s database",
+                               snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> not available for %s database",
                                        c->argv[0], c->be->bd_info->bi_type );
                                Debug(LDAP_DEBUG_ANY, "%s: %s\n",
-                                       c->log, c->msg, 0 );
+                                       c->log, c->cr_msg, 0 );
                                return(1);
                        }
                        if(c->value_int)
@@ -1697,10 +1598,10 @@ config_generic(ConfigArgs *c) {
 
                case CFG_MIRRORMODE:
                        if(!SLAP_SHADOW(c->be)) {
-                               snprintf( c->msg, sizeof( c->msg ), "<%s> database is not a shadow",
+                               snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> database is not a shadow",
                                        c->argv[0] );
                                Debug(LDAP_DEBUG_ANY, "%s: %s\n",
-                                       c->log, c->msg, 0 );
+                                       c->log, c->cr_msg, 0 );
                                return(1);
                        }
                        if(c->value_int)
@@ -1725,9 +1626,9 @@ config_generic(ConfigArgs *c) {
 
                case CFG_SSTR_IF_MAX:
                        if (c->value_int < index_substr_if_minlen) {
-                               snprintf( c->msg, sizeof( c->msg ), "<%s> invalid value", c->argv[0] );
+                               snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> invalid value", c->argv[0] );
                                Debug(LDAP_DEBUG_ANY, "%s: %s (%d)\n",
-                                       c->log, c->msg, c->value_int );
+                                       c->log, c->cr_msg, c->value_int );
                                return(1);
                        }
                        index_substr_if_maxlen = c->value_int;
@@ -1735,9 +1636,9 @@ config_generic(ConfigArgs *c) {
 
                case CFG_SSTR_IF_MIN:
                        if (c->value_int > index_substr_if_maxlen) {
-                               snprintf( c->msg, sizeof( c->msg ), "<%s> invalid value", c->argv[0] );
+                               snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> invalid value", c->argv[0] );
                                Debug(LDAP_DEBUG_ANY, "%s: %s (%d)\n",
-                                       c->log, c->msg, c->value_int );
+                                       c->log, c->cr_msg, c->value_int );
                                return(1);
                        }
                        index_substr_if_minlen = c->value_int;
@@ -1752,10 +1653,10 @@ config_generic(ConfigArgs *c) {
                                modcur = c->private;
                                /* This should never fail */
                                if ( module_path( modcur->mp_path.bv_val )) {
-                                       snprintf( c->msg, sizeof( c->msg ), "<%s> module path no longer valid",
+                                       snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> module path no longer valid",
                                                c->argv[0] );
                                        Debug(LDAP_DEBUG_ANY, "%s: %s (%s)\n",
-                                               c->log, c->msg, modcur->mp_path.bv_val );
+                                               c->log, c->cr_msg, modcur->mp_path.bv_val );
                                        return(1);
                                }
                        }
@@ -1943,16 +1844,16 @@ config_passwd_hash(ConfigArgs *c) {
        }
        for(i = 1; i < c->argc; i++) {
                if(!lutil_passwd_scheme(c->argv[i])) {
-                       snprintf( c->msg, sizeof( c->msg ), "<%s> scheme not available", c->argv[0] );
+                       snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> scheme not available", c->argv[0] );
                        Debug(LDAP_DEBUG_ANY, "%s: %s (%s)\n",
-                               c->log, c->msg, c->argv[i]);
+                               c->log, c->cr_msg, c->argv[i]);
                } else {
                        ldap_charray_add(&default_passwd_hash, c->argv[i]);
                }
                if(!default_passwd_hash) {
-                       snprintf( c->msg, sizeof( c->msg ), "<%s> no valid hashes found", c->argv[0] );
+                       snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> no valid hashes found", c->argv[0] );
                        Debug(LDAP_DEBUG_ANY, "%s: %s\n",
-                               c->log, c->msg, 0 );
+                               c->log, c->cr_msg, 0 );
                        return(1);
                }
        }
@@ -2012,9 +1913,9 @@ config_sizelimit(ConfigArgs *c) {
                if(!strncasecmp(c->argv[i], "size", 4)) {
                        rc = limits_parse_one(c->argv[i], lim);
                        if ( rc ) {
-                               snprintf( c->msg, sizeof( c->msg ), "<%s> unable to parse value", c->argv[0] );
+                               snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> unable to parse value", c->argv[0] );
                                Debug(LDAP_DEBUG_ANY, "%s: %s \"%s\"\n",
-                                       c->log, c->msg, c->argv[i]);
+                                       c->log, c->cr_msg, c->argv[i]);
                                return(1);
                        }
                } else {
@@ -2022,9 +1923,9 @@ config_sizelimit(ConfigArgs *c) {
                                lim->lms_s_soft = -1;
                        } else {
                                if ( lutil_atoix( &lim->lms_s_soft, c->argv[i], 0 ) != 0 ) {
-                                       snprintf( c->msg, sizeof( c->msg ), "<%s> unable to parse limit", c->argv[0]);
+                                       snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> unable to parse limit", c->argv[0]);
                                        Debug(LDAP_DEBUG_ANY, "%s: %s \"%s\"\n",
-                                               c->log, c->msg, c->argv[i]);
+                                               c->log, c->cr_msg, c->argv[i]);
                                        return(1);
                                }
                        }
@@ -2059,9 +1960,9 @@ config_timelimit(ConfigArgs *c) {
                if(!strncasecmp(c->argv[i], "time", 4)) {
                        rc = limits_parse_one(c->argv[i], lim);
                        if ( rc ) {
-                               snprintf( c->msg, sizeof( c->msg ), "<%s> unable to parse value", c->argv[0] );
+                               snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> unable to parse value", c->argv[0] );
                                Debug(LDAP_DEBUG_ANY, "%s: %s \"%s\"\n",
-                                       c->log, c->msg, c->argv[i]);
+                                       c->log, c->cr_msg, c->argv[i]);
                                return(1);
                        }
                } else {
@@ -2069,9 +1970,9 @@ config_timelimit(ConfigArgs *c) {
                                lim->lms_t_soft = -1;
                        } else {
                                if ( lutil_atoix( &lim->lms_t_soft, c->argv[i], 0 ) != 0 ) {
-                                       snprintf( c->msg, sizeof( c->msg ), "<%s> unable to parse limit", c->argv[0]);
+                                       snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> unable to parse limit", c->argv[0]);
                                        Debug(LDAP_DEBUG_ANY, "%s: %s \"%s\"\n",
-                                               c->log, c->msg, c->argv[i]);
+                                               c->log, c->cr_msg, c->argv[i]);
                                        return(1);
                                }
                        }
@@ -2219,10 +2120,10 @@ config_suffix(ConfigArgs *c)
 
 #ifdef SLAPD_MONITOR_DN
        if(!strcasecmp(c->argv[1], SLAPD_MONITOR_DN)) {
-               snprintf( c->msg, sizeof( c->msg ), "<%s> DN is reserved for monitoring slapd",
+               snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> DN is reserved for monitoring slapd",
                        c->argv[0] );
                Debug(LDAP_DEBUG_ANY, "%s: %s (%s)\n",
-                       c->log, c->msg, SLAPD_MONITOR_DN);
+                       c->log, c->cr_msg, SLAPD_MONITOR_DN);
                return(1);
        }
 #endif
@@ -2232,7 +2133,7 @@ config_suffix(ConfigArgs *c)
        if (SLAP_DBHIDDEN( c->be ))
                tbe = NULL;
        else
-               tbe = select_backend(&ndn, 0, 0);
+               tbe = select_backend(&ndn, 0);
        if(tbe == c->be) {
                Debug( LDAP_DEBUG_ANY, "%s: suffix already served by this backend!.\n",
                        c->log, 0, 0);
@@ -2253,11 +2154,11 @@ config_suffix(ConfigArgs *c)
                                type = oi->oi_orig->bi_type;
                        }
 
-                       snprintf( c->msg, sizeof( c->msg ), "<%s> namingContext \"%s\" "
+                       snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> namingContext \"%s\" "
                                "already served by a preceding %s database",
                                c->argv[0], pdn.bv_val, type );
                        Debug(LDAP_DEBUG_ANY, "%s: %s serving namingContext \"%s\"\n",
-                               c->log, c->msg, tbe->be_suffix[0].bv_val);
+                               c->log, c->cr_msg, tbe->be_suffix[0].bv_val);
                        free(pdn.bv_val);
                        free(ndn.bv_val);
                        return(1);
@@ -2317,12 +2218,12 @@ config_rootpw(ConfigArgs *c) {
                return 0;
        }
 
-       tbe = select_backend(&c->be->be_rootndn, 0, 0);
+       tbe = select_backend(&c->be->be_rootndn, 0);
        if(tbe != c->be) {
-               snprintf( c->msg, sizeof( c->msg ), "<%s> can only be set when rootdn is under suffix",
+               snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> can only be set when rootdn is under suffix",
                        c->argv[0] );
                Debug(LDAP_DEBUG_ANY, "%s: %s\n",
-                       c->log, c->msg, 0);
+                       c->log, c->cr_msg, 0);
                return(1);
        }
        if ( !BER_BVISNULL( &c->be->be_rootpw ))
@@ -2369,9 +2270,9 @@ config_restrict(ConfigArgs *c) {
        }
        i = verbs_to_mask( c->argc, c->argv, restrictable_ops, &restrictops );
        if ( i ) {
-               snprintf( c->msg, sizeof( c->msg ), "<%s> unknown operation", c->argv[0] );
+               snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> unknown operation", c->argv[0] );
                Debug(LDAP_DEBUG_ANY, "%s: %s %s\n",
-                       c->log, c->msg, c->argv[i]);
+                       c->log, c->cr_msg, c->argv[i]);
                return(1);
        }
        if ( restrictops & SLAP_RESTRICT_OP_EXTENDED )
@@ -2405,9 +2306,9 @@ config_allows(ConfigArgs *c) {
        }
        i = verbs_to_mask(c->argc, c->argv, allowable_ops, &allows);
        if ( i ) {
-               snprintf( c->msg, sizeof( c->msg ), "<%s> unknown feature", c->argv[0] );
+               snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> unknown feature", c->argv[0] );
                Debug(LDAP_DEBUG_ANY, "%s: %s %s\n",
-                       c->log, c->msg, c->argv[i]);
+                       c->log, c->cr_msg, c->argv[i]);
                return(1);
        }
        global_allows |= allows;
@@ -2438,9 +2339,9 @@ config_disallows(ConfigArgs *c) {
        }
        i = verbs_to_mask(c->argc, c->argv, disallowable_ops, &disallows);
        if ( i ) {
-               snprintf( c->msg, sizeof( c->msg ), "<%s> unknown feature", c->argv[0] );
+               snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> unknown feature", c->argv[0] );
                Debug(LDAP_DEBUG_ANY, "%s: %s %s\n",
-                       c->log, c->msg, c->argv[i]);
+                       c->log, c->cr_msg, c->argv[i]);
                return(1);
        }
        global_disallows |= disallows;
@@ -2481,13 +2382,13 @@ config_requires(ConfigArgs *c) {
        i = verbs_to_mask(argc, argv, requires_ops, &requires);
        if ( i ) {
                if (strcasecmp( c->argv[ i ], "none" ) == 0 ) {
-                       snprintf( c->msg, sizeof( c->msg ), "<%s> \"none\" (#%d) must be listed first", c->argv[0], i - 1 );
+                       snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> \"none\" (#%d) must be listed first", c->argv[0], i - 1 );
                        Debug(LDAP_DEBUG_ANY, "%s: %s\n",
-                               c->log, c->msg, 0);
+                               c->log, c->cr_msg, 0);
                } else {
-                       snprintf( c->msg, sizeof( c->msg ), "<%s> unknown feature #%d", c->argv[0], i - 1 );
+                       snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> unknown feature #%d", c->argv[0], i - 1 );
                        Debug(LDAP_DEBUG_ANY, "%s: %s \"%s\"\n",
-                               c->log, c->msg, c->argv[i]);
+                               c->log, c->cr_msg, c->argv[i]);
                }
                return(1);
        }
@@ -2560,8 +2461,7 @@ int
 slap_loglevel_get( struct berval *s, int *l )
 {
        int             rc;
-       unsigned long   i;
-       slap_mask_t     m;
+       slap_mask_t     m, i;
 
        if ( loglevel_ops == NULL ) {
                loglevel_init();
@@ -2571,12 +2471,10 @@ slap_loglevel_get( struct berval *s, int *l )
                m |= loglevel_ops[ i ].mask;
        }
 
-       m = ~m;
-
-       for ( i = 1; i <= ( 1 << ( sizeof( int ) * 8 - 1 ) ) && !( m & i ); i <<= 1 )
+       for ( i = 1; m & i; i <<= 1 )
                ;
 
-       if ( !( m & i ) ) {
+       if ( i == 0 ) {
                return -1;
        }
 
@@ -2696,27 +2594,29 @@ config_loglevel(ConfigArgs *c) {
                return 0;
        }
 
-       config_syslog = 0;
-
        for( i=1; i < c->argc; i++ ) {
                int     level;
 
                if ( isdigit((unsigned char)c->argv[i][0]) || c->argv[i][0] == '-' ) {
                        if( lutil_atoi( &level, c->argv[i] ) != 0 ) {
-                               snprintf( c->msg, sizeof( c->msg ), "<%s> unable to parse level", c->argv[0] );
+                               snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> unable to parse level", c->argv[0] );
                                Debug( LDAP_DEBUG_ANY, "%s: %s \"%s\"\n",
-                                       c->log, c->msg, c->argv[i]);
+                                       c->log, c->cr_msg, c->argv[i]);
                                return( 1 );
                        }
                } else {
                        if ( str2loglevel( c->argv[i], &level ) ) {
-                               snprintf( c->msg, sizeof( c->msg ), "<%s> unknown level", c->argv[0] );
+                               snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> unknown level", c->argv[0] );
                                Debug( LDAP_DEBUG_ANY, "%s: %s \"%s\"\n",
-                                       c->log, c->msg, c->argv[i]);
+                                       c->log, c->cr_msg, c->argv[i]);
                                return( 1 );
                        }
                }
-               config_syslog |= level;
+               /* Explicitly setting a zero clears all the levels */
+               if ( level )
+                       config_syslog |= level;
+               else
+                       config_syslog = 0;
        }
        if ( slapMode & SLAP_SERVER_MODE ) {
                ldap_syslog = config_syslog;
@@ -2747,9 +2647,9 @@ config_referral(ConfigArgs *c) {
                return 0;
        }
        if(validate_global_referral(c->argv[1])) {
-               snprintf( c->msg, sizeof( c->msg ), "<%s> invalid URL", c->argv[0] );
+               snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> invalid URL", c->argv[0] );
                Debug(LDAP_DEBUG_ANY, "%s: %s (%s)\n",
-                       c->log, c->msg, c->argv[1]);
+                       c->log, c->cr_msg, c->argv[1]);
                return(1);
        }
 
@@ -2817,16 +2717,16 @@ config_security(ConfigArgs *c) {
                        }
                }
                if ( !tgt ) {
-                       snprintf( c->msg, sizeof( c->msg ), "<%s> unknown factor", c->argv[0] );
+                       snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> unknown factor", c->argv[0] );
                        Debug(LDAP_DEBUG_ANY, "%s: %s %s\n",
-                               c->log, c->msg, c->argv[i]);
+                               c->log, c->cr_msg, c->argv[i]);
                        return(1);
                }
 
                if ( lutil_atou( tgt, src ) != 0 ) {
-                       snprintf( c->msg, sizeof( c->msg ), "<%s> unable to parse factor", c->argv[0] );
+                       snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> unable to parse factor", c->argv[0] );
                        Debug(LDAP_DEBUG_ANY, "%s: %s \"%s\"\n",
-                               c->log, c->msg, c->argv[i]);
+                               c->log, c->cr_msg, c->argv[i]);
                        return(1);
                }
        }
@@ -2849,230 +2749,6 @@ anlist_unparse( AttributeName *an, char *ptr, ber_len_t buflen ) {
        return ptr;
 }
 
-static void
-replica_unparse( struct slap_replica_info *ri, int i, struct berval *bv )
-{
-       int len;
-       char *ptr;
-       struct berval bc = BER_BVNULL;
-       char numbuf[32];
-
-       assert( !BER_BVISNULL( &ri->ri_bindconf.sb_uri ) );
-       
-       BER_BVZERO( bv );
-
-       len = snprintf(numbuf, sizeof( numbuf ), SLAP_X_ORDERED_FMT, i );
-       if ( len >= sizeof( numbuf ) ) {
-               /* FIXME: how can indicate error? */
-               return;
-       }
-
-       if ( ri->ri_nsuffix ) {
-               for (i=0; !BER_BVISNULL( &ri->ri_nsuffix[i] ); i++) {
-                       len += ri->ri_nsuffix[i].bv_len + STRLENOF(" suffix=\"\"");
-               }
-       }
-       if ( ri->ri_attrs ) {
-               len += STRLENOF(" attrs");
-               if ( ri->ri_exclude ) len++;
-               for (i=0; !BER_BVISNULL( &ri->ri_attrs[i].an_name ); i++) {
-                       len += 1 + ri->ri_attrs[i].an_name.bv_len;
-               }
-       }
-       bindconf_unparse( &ri->ri_bindconf, &bc );
-       len += bc.bv_len;
-
-       bv->bv_val = ch_malloc(len + 1);
-       bv->bv_len = len;
-
-       ptr = lutil_strcopy( bv->bv_val, numbuf );
-
-       /* start with URI from bindconf */
-       assert( !BER_BVISNULL( &bc ) );
-       if ( bc.bv_val ) {
-               strcpy( ptr, bc.bv_val );
-               ch_free( bc.bv_val );
-       }
-
-       if ( ri->ri_nsuffix ) {
-               for (i=0; !BER_BVISNULL( &ri->ri_nsuffix[i] ); i++) {
-                       ptr = lutil_strcopy( ptr, " suffix=\"" );
-                       ptr = lutil_strcopy( ptr, ri->ri_nsuffix[i].bv_val );
-                       *ptr++ = '"';
-               }
-       }
-       if ( ri->ri_attrs ) {
-               ptr = lutil_strcopy( ptr, " attrs" );
-               if ( ri->ri_exclude ) *ptr++ = '!';
-               *ptr++ = '=';
-               ptr = anlist_unparse( ri->ri_attrs, ptr, 0 );
-       }
-}
-
-static int
-config_replica(ConfigArgs *c) {
-       int i, nr = -1;
-       char *replicahost = NULL, *replicauri = NULL;
-       LDAPURLDesc *ludp;
-
-       if (c->op == SLAP_CONFIG_EMIT) {
-               if (c->be->be_replica) {
-                       struct berval bv;
-                       for (i=0;c->be->be_replica[i]; i++) {
-                               replica_unparse( c->be->be_replica[i], i, &bv );
-                               ber_bvarray_add( &c->rvalue_vals, &bv );
-                       }
-                       return 0;
-               }
-               return 1;
-       } else if ( c->op == LDAP_MOD_DELETE ) {
-               /* FIXME: there is no replica_free function */
-               if ( c->valx < 0 ) {
-               } else {
-               }
-       }
-       if(SLAP_MONITOR(c->be)) {
-               Debug(LDAP_DEBUG_ANY, "%s: "
-                       "\"replica\" should not be used inside monitor database\n",
-                       c->log, 0, 0);
-               return(0);      /* FIXME: should this be an error? */
-       }
-
-       for(i = 1; i < c->argc; i++) {
-               if(!strncasecmp(c->argv[i], "host=", STRLENOF("host="))) {
-                       ber_len_t       len;
-
-                       if ( replicauri ) {
-                               snprintf( c->msg, sizeof( c->msg ), "<%s> replica host/URI already specified", c->argv[0] );
-                               Debug(LDAP_DEBUG_ANY, "%s: %s \"%s\"\n", c->log, c->msg, replicauri );
-                               return(1);
-                       }
-
-                       replicahost = c->argv[i] + STRLENOF("host=");
-                       len = strlen( replicahost ) + STRLENOF("ldap://");
-                       replicauri = ch_malloc( len + 1 );
-                       snprintf( replicauri, len + 1, "ldap://%s", replicahost );
-                       replicahost = replicauri + STRLENOF( "ldap://");
-                       nr = add_replica_info(c->be, replicauri, replicahost);
-                       break;
-               } else if(!strncasecmp(c->argv[i], "uri=", STRLENOF("uri="))) {
-                       ber_len_t       len;
-
-                       if ( replicauri ) {
-                               snprintf( c->msg, sizeof( c->msg ), "<%s> replica host/URI already specified", c->argv[0] );
-                               Debug(LDAP_DEBUG_ANY, "%s: %s \"%s\"\n", c->log, c->msg, replicauri );
-                               return(1);
-                       }
-
-                       if(ldap_url_parse(c->argv[i] + STRLENOF("uri="), &ludp) != LDAP_SUCCESS) {
-                               snprintf( c->msg, sizeof( c->msg ), "<%s> invalid uri", c->argv[0] );
-                               Debug(LDAP_DEBUG_ANY, "%s: %s\n", c->log, c->msg, 0 );
-                               return(1);
-                       }
-                       if(!ludp->lud_host) {
-                               ldap_free_urldesc(ludp);
-                               snprintf( c->msg, sizeof( c->msg ), "<%s> invalid uri - missing hostname",
-                                       c->argv[0] );
-                               Debug(LDAP_DEBUG_ANY, "%s: %s\n", c->log, c->msg, 0 );
-                               return(1);
-                       }
-
-                       len = strlen(ludp->lud_scheme) + strlen(ludp->lud_host) +
-                               STRLENOF("://") + 1;
-                       if (ludp->lud_port != LDAP_PORT) {
-                               if (ludp->lud_port < 1 || ludp->lud_port > 65535) {
-                                       ldap_free_urldesc(ludp);
-                                       snprintf( c->msg, sizeof( c->msg ), "<%s> invalid port",
-                                               c->argv[0] );
-                                       Debug(LDAP_DEBUG_ANY, "%s: %s\n", c->log, c->msg, 0 );
-                                       return(1);
-                               }
-                               len += STRLENOF(":65535");
-                       }
-                       replicauri = ch_malloc( len );
-                       replicahost = lutil_strcopy( replicauri, ludp->lud_scheme );
-                       replicahost = lutil_strcopy( replicahost, "://" );
-                       if (ludp->lud_port == LDAP_PORT) {
-                               strcpy( replicahost, ludp->lud_host );
-                       } else {
-                               sprintf( replicahost, "%s:%d",ludp->lud_host,ludp->lud_port );
-                       }
-                       ldap_free_urldesc(ludp);
-                       nr = add_replica_info(c->be, replicauri, replicahost);
-                       break;
-               }
-       }
-       if(i == c->argc) {
-               snprintf( c->msg, sizeof( c->msg ), "<%s> missing host or uri", c->argv[0] );
-               Debug(LDAP_DEBUG_ANY, "%s: %s\n", c->log, c->msg, 0 );
-               return(1);
-       } else if(nr == -1) {
-               snprintf( c->msg, sizeof( c->msg ), "<%s> unable to add replica", c->argv[0] );
-               Debug(LDAP_DEBUG_ANY, "%s: %s \"%s\"\n", c->log, c->msg,
-                       replicauri ? replicauri : "" );
-               return(1);
-       } else {
-               for(i = 1; i < c->argc; i++) {
-                       if(!strncasecmp(c->argv[i], "uri=", STRLENOF("uri="))) {
-                               /* 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:
-                                               Debug( LDAP_DEBUG_ANY, "%s: "
-                                                       "suffix \"%s\" in \"replica\" line is not valid for backend.\n",
-                                                       c->log, c->argv[i] + STRLENOF("suffix="), 0);
-                                               return 1;
-                                               break;
-                                       case 2:
-                                               Debug( LDAP_DEBUG_ANY, "%s: "
-                                                       "unable to normalize suffix in \"replica\" line.\n",
-                                                       c->log, 0, 0);
-                                               return 1;
-                                               break;
-                               }
-
-                       } else if (!strncasecmp(c->argv[i], "attr", STRLENOF("attr"))
-                               || !strncasecmp(c->argv[i], "attrs", STRLENOF("attrs")))
-                       {
-                               int exclude = 0;
-                               char *arg = c->argv[i] + STRLENOF("attr");
-                               if (arg[0] == 's') {
-                                       arg++;
-                               } else {
-                                       Debug( LDAP_DEBUG_ANY,
-                                               "%s: \"attr\" "
-                                               "is deprecated (and undocumented); "
-                                               "use \"attrs\" instead.\n",
-                                               c->log, 0, 0 );
-                               }
-                               if(arg[0] == '!') {
-                                       arg++;
-                                       exclude = 1;
-                               }
-                               if(arg[0] != '=') {
-                                       continue;
-                               }
-                               if(add_replica_attrs(c->be, nr, arg + 1, exclude)) {
-                                       snprintf( c->msg, sizeof( c->msg ), "<%s> unknown attribute", c->argv[0] );
-                                       Debug(LDAP_DEBUG_ANY, "%s: %s \"%s\"\n",
-                                               c->log, c->msg, arg + 1);
-                                       return(1);
-                               }
-                       } else if ( bindconf_parse( c->argv[i],
-                                       &c->be->be_replica[nr]->ri_bindconf ) ) {
-                               return(1);
-                       }
-               }
-       }
-       return(0);
-}
-
 static int
 config_updatedn(ConfigArgs *c) {
        if (c->op == SLAP_CONFIG_EMIT) {
@@ -3089,9 +2765,9 @@ config_updatedn(ConfigArgs *c) {
                return 0;
        }
        if(SLAP_SHADOW(c->be)) {
-               snprintf( c->msg, sizeof( c->msg ), "<%s> database already shadowed", c->argv[0] );
+               snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> database already shadowed", c->argv[0] );
                Debug(LDAP_DEBUG_ANY, "%s: %s\n",
-                       c->log, c->msg, 0);
+                       c->log, c->cr_msg, 0);
                return(1);
        }
 
@@ -3151,17 +2827,17 @@ config_updateref(ConfigArgs *c) {
                return 0;
        }
        if(!SLAP_SHADOW(c->be) && !c->be->be_syncinfo) {
-               snprintf( c->msg, sizeof( c->msg ), "<%s> must appear after syncrepl or updatedn",
+               snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> must appear after syncrepl or updatedn",
                        c->argv[0] );
                Debug(LDAP_DEBUG_ANY, "%s: %s\n",
-                       c->log, c->msg, 0);
+                       c->log, c->cr_msg, 0);
                return(1);
        }
 
        if(validate_global_referral(c->argv[1])) {
-               snprintf( c->msg, sizeof( c->msg ), "<%s> invalid URL", c->argv[0] );
+               snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> invalid URL", c->argv[0] );
                Debug(LDAP_DEBUG_ANY, "%s: %s (%s)\n",
-                       c->log, c->msg, c->argv[1]);
+                       c->log, c->cr_msg, c->argv[1]);
                return(1);
        }
        ber_str2bv(c->argv[1], 0, 0, &val);
@@ -3169,6 +2845,17 @@ config_updateref(ConfigArgs *c) {
        return(0);
 }
 
+static int
+config_obsolete(ConfigArgs *c) {
+       if (c->op == SLAP_CONFIG_EMIT)
+               return 1;
+
+       snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> keyword is obsolete (ignored)",
+               c->argv[0] );
+       Debug(LDAP_DEBUG_ANY, "%s: %s\n", c->log, c->cr_msg, 0);
+       return(0);
+}
+
 static int
 config_include(ConfigArgs *c) {
        int savelineno = c->lineno;
@@ -3214,6 +2901,9 @@ config_tls_option(ConfigArgs *c) {
        case CFG_TLS_CA_PATH:   flag = LDAP_OPT_X_TLS_CACERTDIR;        break;
        case CFG_TLS_CA_FILE:   flag = LDAP_OPT_X_TLS_CACERTFILE;       break;
        case CFG_TLS_DH_FILE:   flag = LDAP_OPT_X_TLS_DHFILE;   break;
+#ifdef HAVE_GNUTLS
+       case CFG_TLS_CRL_FILE:  flag = LDAP_OPT_X_TLS_CRLFILE;  break;
+#endif
        default:                Debug(LDAP_DEBUG_ANY, "%s: "
                                        "unknown tls_option <0x%x>\n",
                                        c->log, c->type, 0);
@@ -3374,7 +3064,7 @@ ok:
                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 );
+                               rs->sr_entry->e_name.bv_val, sc->ca->cr_msg, 0 );
                }
        }
        return rs->sr_err;
@@ -3410,7 +3100,7 @@ config_setup_ldif( BackendDB *be, const char *dir, int readit ) {
        if ( !cfb->cb_db.bd_info )
                return 0;       /* FIXME: eventually this will be a fatal error */
 
-       if ( backend_db_init( "ldif", &cfb->cb_db, -1 ) == NULL )
+       if ( backend_db_init( "ldif", &cfb->cb_db, -1, NULL ) == NULL )
                return 1;
 
        cfb->cb_db.be_suffix = be->be_suffix;
@@ -3431,6 +3121,9 @@ config_setup_ldif( BackendDB *be, const char *dir, int readit ) {
        argv[1] = (char *)dir;
        argv[2] = NULL;
        c.argv = argv;
+       c.reply.err = 0;
+       c.reply.msg[0] = 0;
+       c.table = Cft_Database;
 
        ct = config_find_keyword( c.be->be_cf_ocs->co_table, &c );
        if ( !ct )
@@ -3439,15 +3132,15 @@ config_setup_ldif( BackendDB *be, const char *dir, int readit ) {
        if ( config_add_vals( ct, &c ))
                return 1;
 
-       if ( backend_startup_one( &cfb->cb_db ))
+       if ( backend_startup_one( &cfb->cb_db, &c.reply ))
                return 1;
 
        if ( readit ) {
                void *thrctx = ldap_pvt_thread_pool_context();
                int prev_DN_strict;
 
-               op = (Operation *) &opbuf;
-               connection_fake_init( &conn, op, thrctx );
+               connection_fake_init( &conn, &opbuf, thrctx );
+               op = &opbuf.ob_op;
 
                filter.f_desc = slap_schema.si_ad_objectClass;
 
@@ -3546,7 +3239,7 @@ read_config(const char *fname, const char *dir) {
        int rc;
 
        /* Setup the config backend */
-       be = backend_db_init( "config", NULL, 0 );
+       be = backend_db_init( "config", NULL, 0, NULL );
        if ( !be )
                return 1;
 
@@ -3627,7 +3320,7 @@ done:
 static int
 config_back_bind( Operation *op, SlapReply *rs )
 {
-       if ( op->orb_method == LDAP_AUTH_SIMPLE && be_isroot_pw( op )) {
+       if ( be_isroot_pw( op ) ) {
                ber_dupbv( &op->orb_edn, be_root_dn( op->o_bd ));
                /* frontend sends result */
                return LDAP_SUCCESS;
@@ -3667,14 +3360,17 @@ config_send( Operation *op, SlapReply *rs, CfEntryInfo *ce, int depth )
 }
 
 static ConfigTable *
-config_find_table( ConfigOCs **colst, int nocs, AttributeDescription *ad )
+config_find_table( ConfigOCs **colst, int nocs, AttributeDescription *ad,
+       ConfigArgs *ca )
 {
        int i, j;
 
        for (j=0; j<nocs; j++) {
                for (i=0; colst[j]->co_table[i].name; i++)
-                       if ( colst[j]->co_table[i].ad == ad )
+                       if ( colst[j]->co_table[i].ad == ad ) {
+                               ca->table = colst[j]->co_type;
                                return &colst[j]->co_table[i];
+                       }
        }
        return NULL;
 }
@@ -3759,7 +3455,7 @@ check_vals( ConfigTable *ct, ConfigArgs *ca, void *ptr, int isAttr )
        if ( a && ( ad->ad_type->sat_flags & SLAP_AT_ORDERED_VAL )) {
                rc = ordered_value_sort( a, 1 );
                if ( rc ) {
-                       snprintf(ca->msg, sizeof( ca->msg ), "ordered_value_sort failed on attr %s\n",
+                       snprintf(ca->cr_msg, sizeof( ca->cr_msg ), "ordered_value_sort failed on attr %s\n",
                                ad->ad_cname.bv_val );
                        return rc;
                }
@@ -3953,7 +3649,7 @@ check_name_index( CfEntryInfo *parent, ConfigType ce_type, Entry *e,
 {
        CfEntryInfo *ce;
        int index = -1, gotindex = 0, nsibs, rc = 0;
-       int renumber = 0, tailindex = 0, isfrontend = 0;
+       int renumber = 0, tailindex = 0, isfrontend = 0, isconfig = 0;
        char *ptr1, *ptr2 = NULL;
        struct berval rdn;
 
@@ -3968,9 +3664,14 @@ check_name_index( CfEntryInfo *parent, ConfigType ce_type, Entry *e,
 
        /* See if the rdn has an index already */
        dnRdn( &e->e_name, &rdn );
-       if ( ce_type == Cft_Database && !strncmp( rdn.bv_val + rdn.bv_len -
-               STRLENOF("frontend"), "frontend", STRLENOF("frontend") ))
-               isfrontend = 1;
+       if ( ce_type == Cft_Database ) {
+               if ( !strncmp( rdn.bv_val + rdn.bv_len - STRLENOF("frontend"),
+                               "frontend", STRLENOF("frontend") )) 
+                       isfrontend = 1;
+               else if ( !strncmp( rdn.bv_val + rdn.bv_len - STRLENOF("config"),
+                               "config", STRLENOF("config") )) 
+                       isconfig = 1;
+       }
        ptr1 = ber_bvchr( &e->e_name, '{' );
        if ( ptr1 && ptr1 - e->e_name.bv_val < rdn.bv_len ) {
                char    *next;
@@ -3989,6 +3690,9 @@ check_name_index( CfEntryInfo *parent, ConfigType ce_type, Entry *e,
                        if ( index != -1 || !isfrontend )
                                return LDAP_NAMING_VIOLATION;
                }
+               if ( isconfig && index != 0 ){
+                       return LDAP_NAMING_VIOLATION;
+               }
        }
 
        /* count related kids */
@@ -4009,6 +3713,10 @@ check_name_index( CfEntryInfo *parent, ConfigType ce_type, Entry *e,
                                        renumber = 1;
                        }
                }
+               /* config DB is always "0" */
+               if ( isconfig && index == -1 ) {
+                       index = 0;
+               }
                if ( !isfrontend && index == -1 ) {
                        index = nsibs;
                }
@@ -4023,32 +3731,65 @@ check_name_index( CfEntryInfo *parent, ConfigType ce_type, Entry *e,
        return rc;
 }
 
+static int
+count_oc( ObjectClass *oc, ConfigOCs ***copp, int *nocs )
+{
+       ConfigOCs       co, *cop;
+       ObjectClass     **sups;
+
+       co.co_name = &oc->soc_cname;
+       cop = avl_find( CfOcTree, &co, CfOc_cmp );
+       if ( cop ) {
+               int     i;
+
+               /* check for duplicates */
+               for ( i = 0; i < *nocs; i++ ) {
+                       if ( *copp && (*copp)[i] == cop ) {
+                               break;
+                       }
+               }
+
+               if ( i == *nocs ) {
+                       ConfigOCs **tmp = ch_realloc( *copp, (*nocs + 1)*sizeof( ConfigOCs * ) );
+                       if ( tmp == NULL ) {
+                               return -1;
+                       }
+                       *copp = tmp;
+                       (*copp)[*nocs] = cop;
+                       (*nocs)++;
+               }
+       }
+
+       for ( sups = oc->soc_sups; sups && *sups; sups++ ) {
+               if ( count_oc( *sups, copp, nocs ) ) {
+                       return -1;
+               }
+       }
+
+       return 0;
+}
+
 static ConfigOCs **
 count_ocs( Attribute *oc_at, int *nocs )
 {
-       int i, j, n;
-       ConfigOCs co, *coptr, **colst;
+       int             i;
+       ConfigOCs       **colst = NULL;
 
-       /* count the objectclasses */
-       for ( i=0; oc_at->a_nvals[i].bv_val; i++ );
-       n = i;
-       colst = (ConfigOCs **)ch_malloc( n * sizeof(ConfigOCs *));
+       *nocs = 0;
 
-       for ( i=0, j=0; i<n; i++) {
-               co.co_name = &oc_at->a_nvals[i];
-               coptr = avl_find( CfOcTree, &co, CfOc_cmp );
-               
-               /* ignore non-config objectclasses. probably should be
-                * an error, general data doesn't belong here.
-                */
-               if ( !coptr ) continue;
+       for ( i = 0; !BER_BVISNULL( &oc_at->a_nvals[i] ); i++ )
+               /* count attrs */ ;
 
-               /* Ignore the root objectclass, it has no implementation.
-                */
-               if ( coptr->co_type == Cft_Abstract ) continue;
-               colst[j++] = coptr;
+       for ( ; i--; ) {
+               ObjectClass     *oc = oc_bvfind( &oc_at->a_nvals[i] );
+
+               assert( oc != NULL );
+               if ( count_oc( oc, &colst, nocs ) ) {
+                       ch_free( colst );
+                       return NULL;
+               }
        }
-       *nocs = j;
+
        return colst;
 }
 
@@ -4077,8 +3818,9 @@ cfAddSchema( CfEntryInfo *p, Entry *e, ConfigArgs *ca )
 static int
 cfAddDatabase( CfEntryInfo *p, Entry *e, struct config_args_s *ca )
 {
-       if ( p->ce_type != Cft_Global )
+       if ( p->ce_type != Cft_Global ) {
                return LDAP_CONSTRAINT_VIOLATION;
+       }
        ca->be = frontendDB;    /* just to get past check_vals */
        return LDAP_SUCCESS;
 }
@@ -4086,24 +3828,27 @@ cfAddDatabase( CfEntryInfo *p, Entry *e, struct config_args_s *ca )
 static int
 cfAddBackend( CfEntryInfo *p, Entry *e, struct config_args_s *ca )
 {
-       if ( p->ce_type != Cft_Global )
+       if ( p->ce_type != Cft_Global ) {
                return LDAP_CONSTRAINT_VIOLATION;
+       }
        return LDAP_SUCCESS;
 }
 
 static int
 cfAddModule( CfEntryInfo *p, Entry *e, struct config_args_s *ca )
 {
-       if ( p->ce_type != Cft_Global )
+       if ( p->ce_type != Cft_Global ) {
                return LDAP_CONSTRAINT_VIOLATION;
+       }
        return LDAP_SUCCESS;
 }
 
 static int
 cfAddOverlay( CfEntryInfo *p, Entry *e, struct config_args_s *ca )
 {
-       if ( p->ce_type != Cft_Database )
+       if ( p->ce_type != Cft_Database ) {
                return LDAP_CONSTRAINT_VIOLATION;
+       }
        ca->be = p->ce_be;
        return LDAP_SUCCESS;
 }
@@ -4123,28 +3868,28 @@ schema_destroy_one( ConfigArgs *ca, ConfigOCs **colst, int nocs,
                struct berval bv = BER_BVC("olcDitContentRules");
                ad = NULL;
                slap_bv2ad( &bv, &ad, &text );
-               ct = config_find_table( colst, nocs, ad );
+               ct = config_find_table( colst, nocs, ad, ca );
                config_del_vals( ct, ca );
        }
        if ( cfn->c_oc_head ) {
                struct berval bv = BER_BVC("olcObjectClasses");
                ad = NULL;
                slap_bv2ad( &bv, &ad, &text );
-               ct = config_find_table( colst, nocs, ad );
+               ct = config_find_table( colst, nocs, ad, ca );
                config_del_vals( ct, ca );
        }
        if ( cfn->c_at_head ) {
                struct berval bv = BER_BVC("olcAttributeTypes");
                ad = NULL;
                slap_bv2ad( &bv, &ad, &text );
-               ct = config_find_table( colst, nocs, ad );
+               ct = config_find_table( colst, nocs, ad, ca );
                config_del_vals( ct, ca );
        }
        if ( cfn->c_om_head ) {
                struct berval bv = BER_BVC("olcObjectIdentifier");
                ad = NULL;
                slap_bv2ad( &bv, &ad, &text );
-               ct = config_find_table( colst, nocs, ad );
+               ct = config_find_table( colst, nocs, ad, ca );
                config_del_vals( ct, ca );
        }
        cfo = p->ce_private;
@@ -4152,18 +3897,49 @@ schema_destroy_one( ConfigArgs *ca, ConfigOCs **colst, int nocs,
        ch_free( cfn );
 }
 
+static int
+config_add_oc( ConfigOCs **cop, CfEntryInfo *last, Entry *e, ConfigArgs *ca )
+{
+       int             rc = LDAP_CONSTRAINT_VIOLATION;
+       ObjectClass     **ocp;
+
+       if ( (*cop)->co_ldadd ) {
+               rc = (*cop)->co_ldadd( last, e, ca );
+               if ( rc != LDAP_CONSTRAINT_VIOLATION ) {
+                       return rc;
+               }
+       }
+
+       for ( ocp = (*cop)->co_oc->soc_sups; ocp && *ocp; ocp++ ) {
+               ConfigOCs       co = { 0 };
+
+               co.co_name = &(*ocp)->soc_cname;
+               *cop = avl_find( CfOcTree, &co, CfOc_cmp );
+               if ( *cop == NULL ) {
+                       return rc;
+               }
+
+               rc = config_add_oc( cop, last, e, ca );
+               if ( rc != LDAP_CONSTRAINT_VIOLATION ) {
+                       return rc;
+               }
+       }
+
+       return rc;
+}
+
 /* Parse an LDAP entry into config directives */
 static int
 config_add_internal( CfBackInfo *cfb, Entry *e, ConfigArgs *ca, SlapReply *rs,
        int *renum, Operation *op )
 {
-       CfEntryInfo *ce, *last;
-       ConfigOCs **colst;
-       Attribute *a, *oc_at;
-       int i, ibase = -1, nocs, rc = 0;
-       struct berval pdn;
-       ConfigTable *ct;
-       char *ptr;
+       CfEntryInfo     *ce, *last = NULL;
+       ConfigOCs       co, *coptr, **colst;
+       Attribute       *a, *oc_at, *soc_at;
+       int             i, ibase = -1, nocs, rc = 0;
+       struct berval   pdn;
+       ConfigTable     *ct;
+       char            *ptr, *log_prefix = op ? op->o_log_prefix : "";
 
        memset( ca, 0, sizeof(ConfigArgs));
 
@@ -4173,10 +3949,15 @@ config_add_internal( CfBackInfo *cfb, Entry *e, ConfigArgs *ca, SlapReply *rs,
         */
        ce = config_find_base( cfb->cb_root, &e->e_nname, &last );
        if ( ce ) {
-               if (( op && op->o_managedsait ) ||
+               if ( ( op && op->o_managedsait ) ||
                        ( ce->ce_type != Cft_Database && ce->ce_type != Cft_Overlay &&
-                         ce->ce_type != Cft_Module ))
-               return LDAP_ALREADY_EXISTS;
+                         ce->ce_type != Cft_Module ) )
+               {
+                       Debug( LDAP_DEBUG_TRACE, "%s: config_add_internal: "
+                               "DN=\"%s\" already exists\n",
+                               log_prefix, e->e_name.bv_val, 0 );
+                       return LDAP_ALREADY_EXISTS;
+               }
        }
 
        dnParent( &e->e_nname, &pdn );
@@ -4184,23 +3965,73 @@ config_add_internal( CfBackInfo *cfb, Entry *e, ConfigArgs *ca, SlapReply *rs,
        /* If last is NULL, the new entry is the root/suffix entry, 
         * otherwise last should be the parent.
         */
-       if ( last && !dn_match( &last->ce_entry->e_nname, &pdn )) {
-               if ( rs )
+       if ( last && !dn_match( &last->ce_entry->e_nname, &pdn ) ) {
+               if ( rs ) {
                        rs->sr_matched = last->ce_entry->e_name.bv_val;
+               }
+               Debug( LDAP_DEBUG_TRACE, "%s: config_add_internal: "
+                       "DN=\"%s\" not child of DN=\"%s\"\n",
+                       log_prefix, e->e_name.bv_val,
+                       last->ce_entry->e_name.bv_val );
                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 ))
+               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 ))
+                       slap_schema.si_ad_children, NULL, ACL_WADD, NULL ) )
+               {
+                       Debug( LDAP_DEBUG_TRACE, "%s: config_add_internal: "
+                               "DN=\"%s\" no write access to \"children\" of parent\n",
+                               log_prefix, e->e_name.bv_val, 0 );
                        return LDAP_INSUFFICIENT_ACCESS;
+               }
        }
 
        oc_at = attr_find( e->e_attrs, slap_schema.si_ad_objectClass );
-       if ( !oc_at ) return LDAP_OBJECT_CLASS_VIOLATION;
+       if ( !oc_at ) {
+               Debug( LDAP_DEBUG_TRACE, "%s: config_add_internal: "
+                       "DN=\"%s\" no objectClass\n",
+                       log_prefix, e->e_name.bv_val, 0 );
+               return LDAP_OBJECT_CLASS_VIOLATION;
+       }
+
+       soc_at = attr_find( e->e_attrs, slap_schema.si_ad_structuralObjectClass );
+       if ( !soc_at ) {
+               ObjectClass     *soc = NULL;
+               char            textbuf[ SLAP_TEXT_BUFLEN ];
+               const char      *text = textbuf;
+
+               /* FIXME: check result */
+               rc = structural_class( oc_at->a_nvals, &soc, NULL,
+                       &text, textbuf, sizeof(textbuf), NULL );
+               if ( rc != LDAP_SUCCESS ) {
+                       Debug( LDAP_DEBUG_TRACE, "%s: config_add_internal: "
+                               "DN=\"%s\" no structural objectClass (%s)\n",
+                               log_prefix, e->e_name.bv_val, text );
+                       return rc;
+               }
+               attr_merge_one( e, slap_schema.si_ad_structuralObjectClass, &soc->soc_cname, NULL );
+               soc_at = attr_find( e->e_attrs, slap_schema.si_ad_structuralObjectClass );
+               if ( soc_at == NULL ) {
+                       Debug( LDAP_DEBUG_TRACE, "%s: config_add_internal: "
+                               "DN=\"%s\" no structural objectClass; "
+                               "unable to merge computed class %s\n",
+                               log_prefix, e->e_name.bv_val,
+                               soc->soc_cname.bv_val );
+                       return LDAP_OBJECT_CLASS_VIOLATION;
+               }
+
+               Debug( LDAP_DEBUG_TRACE, "%s: config_add_internal: "
+                       "DN=\"%s\" no structural objectClass; "
+                       "computed objectClass %s merged\n",
+                       log_prefix, e->e_name.bv_val,
+                       soc->soc_cname.bv_val );
+       }
 
        /* Fake the coordinates based on whether we're part of an
         * LDAP Add or if reading the config dir
@@ -4214,13 +4045,20 @@ config_add_internal( CfBackInfo *cfb, Entry *e, ConfigArgs *ca, SlapReply *rs,
        }
        ca->ca_op = op;
 
-       colst = count_ocs( oc_at, &nocs );
+       co.co_name = &soc_at->a_nvals[0];
+       coptr = avl_find( CfOcTree, &co, CfOc_cmp );
+       if ( coptr == NULL ) {
+               Debug( LDAP_DEBUG_TRACE, "%s: config_add_internal: "
+                       "DN=\"%s\" no structural objectClass in configuration table\n",
+                       log_prefix, e->e_name.bv_val, 0 );
+               return LDAP_OBJECT_CLASS_VIOLATION;
+       }
 
        /* Only the root can be Cft_Global, everything else must
         * have a parent. Only limited nesting arrangements are allowed.
         */
        rc = LDAP_CONSTRAINT_VIOLATION;
-       if ( colst[0]->co_type == Cft_Global && !last ) {
+       if ( coptr->co_type == Cft_Global && !last ) {
                cfn = cfb->cb_config;
                ca->private = cfn;
                ca->be = frontendDB;    /* just to get past check_vals */
@@ -4231,15 +4069,17 @@ config_add_internal( CfBackInfo *cfb, Entry *e, ConfigArgs *ca, SlapReply *rs,
         * any necessary arg setup
         */
        if ( last ) {
-               for ( i=0; i<nocs; i++ ) {
-                       if ( colst[i]->co_ldadd &&
-                               ( rc = colst[i]->co_ldadd( last, e, ca ))
-                                       != LDAP_CONSTRAINT_VIOLATION ) {
-                               break;
-                       }
+               rc = config_add_oc( &coptr, last, e, ca );
+               if ( rc == LDAP_CONSTRAINT_VIOLATION ) {
+                       Debug( LDAP_DEBUG_TRACE, "%s: config_add_internal: "
+                               "DN=\"%s\" no structural objectClass add function\n",
+                               log_prefix, e->e_name.bv_val, 0 );
+                       return LDAP_OBJECT_CLASS_VIOLATION;
                }
        }
 
+       colst = count_ocs( oc_at, &nocs );
+
        /* Add the entry but don't parse it, we already have its contents */
        if ( rc == LDAP_COMPARE_TRUE ) {
                rc = LDAP_SUCCESS;
@@ -4266,14 +4106,15 @@ config_add_internal( CfBackInfo *cfb, Entry *e, ConfigArgs *ca, SlapReply *rs,
         * but only the other types support auto-renumbering of siblings.
         */
        {
-               rc = check_name_index( last, colst[0]->co_type, e, rs, renum,
+               rc = check_name_index( last, coptr->co_type, e, rs, renum,
                        &ibase );
                if ( rc ) {
                        goto done_noop;
                }
-               if ( renum && *renum && colst[0]->co_type != Cft_Database &&
-                       colst[0]->co_type != Cft_Overlay ) {
-                       snprintf( ca->msg, sizeof( ca->msg ),
+               if ( renum && *renum && coptr->co_type != Cft_Database &&
+                       coptr->co_type != Cft_Overlay )
+               {
+                       snprintf( ca->cr_msg, sizeof( ca->cr_msg ),
                                "operation requires sibling renumbering" );
                        rc = LDAP_UNWILLING_TO_PERFORM;
                        goto done_noop;
@@ -4285,9 +4126,9 @@ config_add_internal( CfBackInfo *cfb, Entry *e, ConfigArgs *ca, SlapReply *rs,
        /* Make sure we process attrs in the required order */
        sort_attrs( e, colst, nocs );
 
-       for ( a=e->e_attrs; a; a=a->a_next ) {
+       for ( a = e->e_attrs; a; a = a->a_next ) {
                if ( a == oc_at ) continue;
-               ct = config_find_table( colst, nocs, a->a_desc );
+               ct = config_find_table( colst, nocs, a->a_desc, ca );
                if ( !ct ) continue;    /* user data? */
                rc = check_vals( ct, ca, a, 1 );
                if ( rc ) goto done_noop;
@@ -4296,7 +4137,7 @@ config_add_internal( CfBackInfo *cfb, Entry *e, ConfigArgs *ca, SlapReply *rs,
        /* Basic syntax checks are OK. Do the actual settings. */
        for ( a=e->e_attrs; a; a=a->a_next ) {
                if ( a == oc_at ) continue;
-               ct = config_find_table( colst, nocs, a->a_desc );
+               ct = config_find_table( colst, nocs, a->a_desc, ca );
                if ( !ct ) continue;    /* user data? */
                for (i=0; a->a_vals[i].bv_val; i++) {
                        char *iptr = NULL;
@@ -4328,20 +4169,22 @@ ok:
        /* Newly added databases and overlays need to be started up */
        if ( CONFIG_ONLINE_ADD( ca )) {
                if ( colst[0]->co_type == Cft_Database ) {
-                       rc = backend_startup_one( ca->be );
+                       rc = backend_startup_one( ca->be, &ca->reply );
 
                } else if ( colst[0]->co_type == Cft_Overlay ) {
                        if ( ca->bi->bi_db_open ) {
                                BackendInfo *bi_orig = ca->be->bd_info;
                                ca->be->bd_info = ca->bi;
-                               rc = ca->bi->bi_db_open( ca->be );
+                               rc = ca->bi->bi_db_open( ca->be, &ca->reply );
                                ca->be->bd_info = bi_orig;
                        }
                }
                if ( rc ) {
-                       snprintf( ca->msg, sizeof( ca->msg ), "<%s> failed startup", ca->argv[0] );
+                       if (ca->cr_msg[0] == '\0')
+                               snprintf( ca->cr_msg, sizeof( ca->cr_msg ), "<%s> failed startup", ca->argv[0] );
+
                        Debug(LDAP_DEBUG_ANY, "%s: %s (%s)!\n",
-                               ca->log, ca->msg, ca->argv[1] );
+                               ca->log, ca->cr_msg, ca->argv[1] );
                        rc = LDAP_OTHER;
                        goto done;
                }
@@ -4529,7 +4372,7 @@ config_back_add( Operation *op, SlapReply *rs )
         */
        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;
+               rs->sr_text = ca.cr_msg;
                goto out2;
        }
 
@@ -4645,7 +4488,7 @@ config_modify_internal( CfEntryInfo *ce, Operation *op, SlapReply *rs,
        strcpy( ca->log, "back-config" );
 
        for (ml = op->orm_modlist; ml; ml=ml->sml_next) {
-               ct = config_find_table( colst, nocs, ml->sml_desc );
+               ct = config_find_table( colst, nocs, ml->sml_desc, ca );
                switch (ml->sml_op) {
                case LDAP_MOD_DELETE:
                case LDAP_MOD_REPLACE: {
@@ -4653,7 +4496,7 @@ config_modify_internal( CfEntryInfo *ce, Operation *op, SlapReply *rs,
                        int *idx = NULL;
                        if ( ct && ( ct->arg_type & ARG_NO_DELETE )) {
                                rc = LDAP_OTHER;
-                               snprintf(ca->msg, sizeof(ca->msg), "cannot delete %s",
+                               snprintf(ca->cr_msg, sizeof(ca->cr_msg), "cannot delete %s",
                                        ml->sml_desc->ad_cname.bv_val );
                                goto out_noop;
                        }
@@ -4682,7 +4525,7 @@ config_modify_internal( CfEntryInfo *ce, Operation *op, SlapReply *rs,
                        }
                        rc = modify_delete_vindex(e, &ml->sml_mod,
                                get_permissiveModify(op),
-                               &rs->sr_text, ca->msg, sizeof(ca->msg), idx );
+                               &rs->sr_text, ca->cr_msg, sizeof(ca->cr_msg), idx );
                        if ( ml->sml_op == LDAP_MOD_REPLACE ) {
                                ml->sml_values = vals;
                                ml->sml_nvalues = nvals;
@@ -4715,7 +4558,7 @@ config_modify_internal( CfEntryInfo *ce, Operation *op, SlapReply *rs,
                                                j = strtol( val, &next, 0 );
                                                if ( next == val || next[ 0 ] != '}' || j < navals ) {
                                                        rc = LDAP_OTHER;
-                                                       snprintf(ca->msg, sizeof(ca->msg), "cannot insert %s",
+                                                       snprintf(ca->cr_msg, sizeof(ca->cr_msg), "cannot insert %s",
                                                                ml->sml_desc->ad_cname.bv_val );
                                                        goto out_noop;
                                                }
@@ -4726,7 +4569,7 @@ config_modify_internal( CfEntryInfo *ce, Operation *op, SlapReply *rs,
                        }
                        rc = modify_add_values(e, &ml->sml_mod,
                                   get_permissiveModify(op),
-                                  &rs->sr_text, ca->msg, sizeof(ca->msg) );
+                                  &rs->sr_text, ca->cr_msg, sizeof(ca->cr_msg) );
 
                        /* If value already exists, show success here
                         * and ignore this operation down below.
@@ -4753,12 +4596,12 @@ config_modify_internal( CfEntryInfo *ce, Operation *op, SlapReply *rs,
        if ( rc == LDAP_SUCCESS) {
                /* check that the entry still obeys the schema */
                rc = entry_schema_check(op, e, NULL, 0, 0,
-                       &rs->sr_text, ca->msg, sizeof(ca->msg) );
+                       &rs->sr_text, ca->cr_msg, sizeof(ca->cr_msg) );
                if ( rc ) goto out_noop;
        }
        /* Basic syntax checks are OK. Do the actual settings. */
        for ( ml = op->orm_modlist; ml; ml = ml->sml_next ) {
-               ct = config_find_table( colst, nocs, ml->sml_desc );
+               ct = config_find_table( colst, nocs, ml->sml_desc, ca );
                if ( !ct ) continue;
 
                s = attr_find( save_attrs, ml->sml_desc );
@@ -4850,7 +4693,7 @@ out:
                for ( s = save_attrs; s; s = s->a_next ) {
                        if ( s->a_flags & SLAP_ATTR_IXDEL ) {
                                s->a_flags &= ~(SLAP_ATTR_IXDEL|SLAP_ATTR_IXADD);
-                               ct = config_find_table( colst, nocs, s->a_desc );
+                               ct = config_find_table( colst, nocs, s->a_desc, ca );
                                a = attr_find( e->e_attrs, s->a_desc );
                                if ( a ) {
                                        /* clear the flag so the add check below will skip it */
@@ -4868,7 +4711,7 @@ out:
                }
                for ( a = e->e_attrs; a; a = a->a_next ) {
                        if ( a->a_flags & SLAP_ATTR_IXADD ) {
-                               ct = config_find_table( colst, nocs, a->a_desc );
+                               ct = config_find_table( colst, nocs, a->a_desc, ca );
                                ca->valx = -1;
                                ca->line = NULL;
                                config_del_vals( ct, ca );
@@ -4960,7 +4803,7 @@ config_back_modify( Operation *op, SlapReply *rs )
         */
        rs->sr_err = config_modify_internal( ce, op, rs, &ca );
        if ( rs->sr_err ) {
-               rs->sr_text = ca.msg;
+               rs->sr_text = ca.cr_msg;
        } else if ( cfb->cb_use_ldif ) {
                BackendDB *be = op->o_bd;
                slap_callback sc = { NULL, slap_null_cb, NULL, NULL }, *scp;
@@ -5364,6 +5207,7 @@ config_build_entry( Operation *op, SlapReply *rs, CfEntryInfo *parent,
        attr_merge_normalize_one(e, ad, &val, NULL );
 
        oc = main->co_oc;
+       c->table = main->co_type;
        if ( oc->soc_required )
                config_build_attrs( e, oc->soc_required, ad, main->co_table, c );
 
@@ -5372,6 +5216,7 @@ config_build_entry( Operation *op, SlapReply *rs, CfEntryInfo *parent,
 
        if ( extra ) {
                oc = extra->co_oc;
+               c->table = extra->co_type;
                if ( oc->soc_required )
                        config_build_attrs( e, oc->soc_required, ad, extra->co_table, c );
 
@@ -5380,8 +5225,8 @@ config_build_entry( Operation *op, SlapReply *rs, CfEntryInfo *parent,
        }
 
        oc_at = attr_find( e->e_attrs, slap_schema.si_ad_objectClass );
-       rc = structural_class(oc_at->a_vals, &oc, NULL, &text, c->msg,
-               sizeof(c->msg), op ? op->o_tmpmemctx : NULL );
+       rc = structural_class(oc_at->a_vals, &oc, NULL, &text, c->cr_msg,
+               sizeof(c->cr_msg), op ? op->o_tmpmemctx : NULL );
        attr_merge_normalize_one(e, slap_schema.si_ad_structuralObjectClass, &oc->soc_cname, NULL );
        if ( op && !op->o_noop ) {
                op->ora_e = e;
@@ -5413,7 +5258,10 @@ config_build_schema_inc( ConfigArgs *c, CfEntryInfo *ceparent,
        struct berval bv;
 
        for (; cf; cf=cf->c_sibs, c->depth++) {
+               if ( !cf->c_at_head && !cf->c_cr_head && !cf->c_oc_head &&
+                       !cf->c_om_head ) continue;
                c->value_dn.bv_val = c->log;
+               LUTIL_SLASHPATH( cf->c_file.bv_val );
                bv.bv_val = strrchr(cf->c_file.bv_val, LDAP_DIRSEP[0]);
                if ( !bv.bv_val ) {
                        bv = cf->c_file;
@@ -5559,7 +5407,7 @@ static const char *defacl[] = {
 };
 
 static int
-config_back_db_open( BackendDB *be )
+config_back_db_open( BackendDB *be, ConfigReply *cr )
 {
        CfBackInfo *cfb = be->be_private;
        struct berval rdn;
@@ -5585,8 +5433,8 @@ config_back_db_open( BackendDB *be )
        }
 
        thrctx = ldap_pvt_thread_pool_context();
-       op = (Operation *) &opbuf;
-       connection_fake_init( &conn, op, thrctx );
+       connection_fake_init( &conn, &opbuf, thrctx );
+       op = &opbuf.ob_op;
 
        op->o_tag = LDAP_REQ_ADD;
        op->o_callback = &cb;
@@ -5797,7 +5645,7 @@ cfb_free_entries( CfEntryInfo *ce )
 }
 
 static int
-config_back_db_close( BackendDB *be )
+config_back_db_close( BackendDB *be, ConfigReply *cr )
 {
        CfBackInfo *cfb = be->be_private;
 
@@ -5812,7 +5660,7 @@ config_back_db_close( BackendDB *be )
 }
 
 static int
-config_back_db_destroy( BackendDB *be )
+config_back_db_destroy( BackendDB *be, ConfigReply *cr )
 {
        CfBackInfo *cfb = be->be_private;
 
@@ -5837,7 +5685,7 @@ config_back_db_destroy( BackendDB *be )
 }
 
 static int
-config_back_db_init( BackendDB *be )
+config_back_db_init( BackendDB *be, ConfigReply* cr )
 {
        struct berval dn;
        CfBackInfo *cfb;
@@ -5928,13 +5776,124 @@ config_tool_entry_get( BackendDB *be, ID id )
                return NULL;
 }
 
+static int entry_put_got_frontend=0;
+static int entry_put_got_config=0;
 static ID
 config_tool_entry_put( BackendDB *be, Entry *e, struct berval *text )
 {
        CfBackInfo *cfb = be->be_private;
        BackendInfo *bi = cfb->cb_db.bd_info;
+       int rc;
+       struct berval rdn, vals[ 2 ];
        ConfigArgs ca;
+       OperationBuffer opbuf;
+       Entry *ce;
+       Connection conn = {0};
+       Operation *op = NULL;
+       void *thrctx;
+
+       /* Create entry for frontend database if it does not exist already */
+       if ( !entry_put_got_frontend ) {
+               if ( !strncmp( e->e_nname.bv_val, "olcDatabase", 
+                               STRLENOF( "olcDatabase" ))) {
+                       if ( strncmp( e->e_nname.bv_val + 
+                                       STRLENOF( "olcDatabase" ), "={-1}frontend",
+                                       STRLENOF( "={-1}frontend" )) && 
+                                       strncmp( e->e_nname.bv_val + 
+                                       STRLENOF( "olcDatabase" ), "=frontend",
+                                       STRLENOF( "=frontend" ))) {
+                               vals[1].bv_len = 0;
+                               vals[1].bv_val = NULL;
+                               memset( &ca, 0, sizeof(ConfigArgs));
+                               ca.be = frontendDB;
+                               ca.bi = frontendDB->bd_info;
+                               ca.be->be_cf_ocs = &CFOC_FRONTEND;
+                               rdn.bv_val = ca.log;
+                               rdn.bv_len = snprintf(rdn.bv_val, sizeof( ca.log ),
+                                       "%s=" SLAP_X_ORDERED_FMT "%s",
+                                       cfAd_database->ad_cname.bv_val, -1,
+                                       ca.bi->bi_type);
+                               ce = config_build_entry( NULL, NULL, cfb->cb_root, &ca, &rdn,
+                                               &CFOC_DATABASE, ca.be->be_cf_ocs );
+                               thrctx = ldap_pvt_thread_pool_context();
+                               connection_fake_init2( &conn, &opbuf, thrctx,0 );
+                               op = &opbuf.ob_op;
+                               op->o_bd = &cfb->cb_db;
+                               op->o_tag = LDAP_REQ_ADD;
+                               op->ora_e = ce;
+                               op->o_dn = be->be_rootdn;
+                               op->o_ndn = be->be_rootndn;
+                               rc = slap_add_opattrs(op, NULL, NULL, 0, 0);
+                               if ( rc != LDAP_SUCCESS ) {
+                                       text->bv_val = "autocreation of \"olcDatabase={-1}frontend\" failed";
+                                       text->bv_len = STRLENOF("autocreation of \"olcDatabase={-1}frontend\" failed");
+                                       return NOID;
+                               }
 
+                               if ( ce && bi && bi->bi_tool_entry_put && 
+                                               bi->bi_tool_entry_put( &cfb->cb_db, ce, text ) != NOID ) {
+                                       entry_put_got_frontend++;
+                               } else {
+                                       text->bv_val = "autocreation of \"olcDatabase={-1}frontend\" failed";
+                                       text->bv_len = STRLENOF("autocreation of \"olcDatabase={-1}frontend\" failed");
+                                       return NOID;
+                               }
+                       } else {
+                               entry_put_got_frontend++;
+                       }
+               }
+       }
+       /* Create entry for config database if it does not exist already */
+       if ( !entry_put_got_config ) {
+               if ( !strncmp( e->e_nname.bv_val, "olcDatabase",
+                               STRLENOF( "olcDatabase" ))) {
+                       if ( strncmp( e->e_nname.bv_val +
+                                       STRLENOF( "olcDatabase" ), "={0}config",
+                                       STRLENOF( "={0}config" )) &&
+                                       strncmp( e->e_nname.bv_val +
+                                       STRLENOF( "olcDatabase" ), "=config",
+                                       STRLENOF( "=config" )) ) {
+                               vals[1].bv_len = 0;
+                               vals[1].bv_val = NULL;
+                               memset( &ca, 0, sizeof(ConfigArgs));
+                               ca.be = LDAP_STAILQ_FIRST( &backendDB );
+                               ca.bi = ca.be->bd_info;
+                               rdn.bv_val = ca.log;
+                               rdn.bv_len = snprintf(rdn.bv_val, sizeof( ca.log ),
+                                       "%s=" SLAP_X_ORDERED_FMT "%s",
+                                       cfAd_database->ad_cname.bv_val, 0,
+                                       ca.bi->bi_type);
+                               ce = config_build_entry( NULL, NULL, cfb->cb_root, &ca, &rdn, &CFOC_DATABASE,
+                                               ca.be->be_cf_ocs );
+                               if ( ! op ) {
+                                       thrctx = ldap_pvt_thread_pool_context();
+                                       connection_fake_init2( &conn, &opbuf, thrctx,0 );
+                                       op = &opbuf.ob_op;
+                                       op->o_bd = &cfb->cb_db;
+                                       op->o_tag = LDAP_REQ_ADD;
+                                       op->o_dn = be->be_rootdn;
+                                       op->o_ndn = be->be_rootndn;
+                               }
+                               op->ora_e = ce;
+                               rc = slap_add_opattrs(op, NULL, NULL, 0, 0);
+                               if ( rc != LDAP_SUCCESS ) {
+                                       text->bv_val = "autocreation of \"olcDatabase={0}config\" failed";
+                                       text->bv_len = STRLENOF("autocreation of \"olcDatabase={0}config\" failed");
+                                       return NOID;
+                               }
+                               if (ce && bi && bi->bi_tool_entry_put &&
+                                               bi->bi_tool_entry_put( &cfb->cb_db, ce, text ) != NOID ) {
+                                       entry_put_got_config++;
+                               } else {
+                                       text->bv_val = "autocreation of \"olcDatabase={0}config\" failed";
+                                       text->bv_len = STRLENOF("autocreation of \"olcDatabase={0}config\" failed");
+                                       return NOID;
+                               }
+                       } else {
+                               entry_put_got_config++;
+                       }
+               }
+       }
        if ( bi && bi->bi_tool_entry_put &&
                config_add_internal( cfb, e, &ca, NULL, NULL, NULL ) == 0 )
                return bi->bi_tool_entry_put( &cfb->cb_db, e, text );
index 706cc43559b06ff9718c91c1080ff75e0a8642dd..6b76332a5c547cad19a691899ac06b515e693933 100644 (file)
@@ -46,10 +46,11 @@ do_bind(
        ber_tag_t tag;
        Backend *be = NULL;
 
-       Debug( LDAP_DEBUG_TRACE, "do_bind\n", 0, 0, 0 );
+       Debug( LDAP_DEBUG_TRACE, "%s do_bind\n",
+               op->o_log_prefix, 0, 0 );
 
        /*
-        * Force to connection to "anonymous" until bind succeeds.
+        * Force the connection to "anonymous" until bind succeeds.
         */
        ldap_pvt_thread_mutex_lock( &op->o_conn->c_mutex );
        if ( op->o_conn->c_sasl_bind_in_progress ) {
@@ -101,7 +102,8 @@ do_bind(
        tag = ber_scanf( ber, "{imt" /*}*/, &version, &dn, &method );
 
        if ( tag == LBER_ERROR ) {
-               Debug( LDAP_DEBUG_ANY, "bind: ber_scanf failed\n", 0, 0, 0 );
+               Debug( LDAP_DEBUG_ANY, "%s do_bind: ber_scanf failed\n",
+                       op->o_log_prefix, 0, 0 );
                send_ldap_discon( op, rs, LDAP_PROTOCOL_ERROR, "decoding error" );
                rs->sr_err = SLAPD_DISCONNECT;
                goto cleanup;
@@ -134,13 +136,16 @@ do_bind(
        }
 
        if ( tag == LBER_ERROR ) {
+               Debug( LDAP_DEBUG_ANY, "%s do_bind: ber_scanf failed\n",
+                       op->o_log_prefix, 0, 0 );
                send_ldap_discon( op, rs, LDAP_PROTOCOL_ERROR, "decoding error" );
                rs->sr_err = SLAPD_DISCONNECT;
                goto cleanup;
        }
 
        if( get_ctrls( op, rs, 1 ) != LDAP_SUCCESS ) {
-               Debug( LDAP_DEBUG_ANY, "do_bind: get_ctrls failed\n", 0, 0, 0 );
+               Debug( LDAP_DEBUG_ANY, "%s do_bind: get_ctrls failed\n",
+                       op->o_log_prefix, 0, 0 );
                goto cleanup;
        } 
 
@@ -151,14 +156,18 @@ do_bind(
        rs->sr_err = dnPrettyNormal( NULL, &dn, &op->o_req_dn, &op->o_req_ndn,
                op->o_tmpmemctx );
        if ( rs->sr_err != LDAP_SUCCESS ) {
-               Debug( LDAP_DEBUG_ANY, "bind: invalid dn (%s)\n",
-                       dn.bv_val, 0, 0 );
+               Debug( LDAP_DEBUG_ANY, "%s do_bind: invalid dn (%s)\n",
+                       op->o_log_prefix, dn.bv_val, 0 );
                send_ldap_error( op, rs, LDAP_INVALID_DN_SYNTAX, "invalid DN" );
                goto cleanup;
        }
 
+       Statslog( LDAP_DEBUG_STATS, "%s BIND dn=\"%s\" method=%ld\n",
+           op->o_log_prefix, op->o_req_dn.bv_val,
+               (unsigned long) op->orb_method, 0, 0 );
+
        if( op->orb_method == LDAP_AUTH_SASL ) {
-               Debug( LDAP_DEBUG_TRACE, "do_sasl_bind: dn (%s) mech %s\n",
+               Debug( LDAP_DEBUG_TRACE, "do_bind: dn (%s) SASL mech %s\n",
                        op->o_req_dn.bv_val, mech.bv_val, NULL );
 
        } else {
@@ -168,13 +177,9 @@ do_bind(
                        (unsigned long) op->orb_method );
        }
 
-       Statslog( LDAP_DEBUG_STATS, "%s BIND dn=\"%s\" method=%ld\n",
-           op->o_log_prefix, op->o_req_dn.bv_val,
-               (unsigned long) op->orb_method, 0, 0 );
-
        if ( version < LDAP_VERSION_MIN || version > LDAP_VERSION_MAX ) {
-               Debug( LDAP_DEBUG_ANY, "do_bind: unknown version=%ld\n",
-                       (unsigned long) version, 0, 0 );
+               Debug( LDAP_DEBUG_ANY, "%s do_bind: unknown version=%ld\n",
+                       op->o_log_prefix, (unsigned long) version, 0 );
                send_ldap_error( op, rs, LDAP_PROTOCOL_ERROR,
                        "requested protocol version not supported" );
                goto cleanup;
@@ -194,7 +199,7 @@ do_bind(
        op->o_conn->c_protocol = version;
        ldap_pvt_thread_mutex_unlock( &op->o_conn->c_mutex );
 
-       op->orb_tmp_mech = mech;
+       op->orb_mech = mech;
 
        op->o_bd = frontendDB;
        rs->sr_err = frontendDB->be_bind( op, rs );
@@ -242,7 +247,7 @@ fe_op_bind( Operation *op, SlapReply *rs )
                        goto cleanup;
                }
 
-               if( BER_BVISNULL( &op->orb_tmp_mech ) || BER_BVISEMPTY( &op->orb_tmp_mech ) ) {
+               if( BER_BVISNULL( &op->orb_mech ) || BER_BVISEMPTY( &op->orb_mech ) ) {
                        Debug( LDAP_DEBUG_ANY,
                                "do_bind: no sasl mechanism provided\n",
                                0, 0, 0 );
@@ -252,19 +257,19 @@ fe_op_bind( Operation *op, SlapReply *rs )
                }
 
                /* check restrictions */
-               if( backend_check_restrictions( op, rs, &op->orb_tmp_mech ) != LDAP_SUCCESS ) {
+               if( backend_check_restrictions( op, rs, &op->orb_mech ) != LDAP_SUCCESS ) {
                        send_ldap_result( op, rs );
                        goto cleanup;
                }
 
                ldap_pvt_thread_mutex_lock( &op->o_conn->c_mutex );
                if ( op->o_conn->c_sasl_bind_in_progress ) {
-                       if( !bvmatch( &op->o_conn->c_sasl_bind_mech, &op->orb_tmp_mech ) ) {
+                       if( !bvmatch( &op->o_conn->c_sasl_bind_mech, &op->orb_mech ) ) {
                                /* mechanism changed between bind steps */
                                slap_sasl_reset(op->o_conn);
                        }
                } else {
-                       ber_dupbv(&op->o_conn->c_sasl_bind_mech, &op->orb_tmp_mech);
+                       ber_dupbv(&op->o_conn->c_sasl_bind_mech, &op->orb_mech);
                }
 
                /* Set the bindop for the benefit of in-directory SASL lookups */
@@ -291,7 +296,7 @@ fe_op_bind( Operation *op, SlapReply *rs )
        }
 
        if ( op->orb_method == LDAP_AUTH_SIMPLE ) {
-               BER_BVSTR( &op->orb_tmp_mech, "SIMPLE" );
+               BER_BVSTR( &op->orb_mech, "SIMPLE" );
                /* accept "anonymous" binds */
                if ( BER_BVISEMPTY( &op->orb_cred ) || BER_BVISEMPTY( &op->o_req_ndn ) ) {
                        rs->sr_err = LDAP_SUCCESS;
@@ -316,7 +321,7 @@ fe_op_bind( Operation *op, SlapReply *rs )
                                rs->sr_text = "anonymous bind disallowed";
 
                        } else {
-                               backend_check_restrictions( op, rs, &op->orb_tmp_mech );
+                               backend_check_restrictions( op, rs, &op->orb_mech );
                        }
 
                        /*
@@ -357,7 +362,7 @@ fe_op_bind( Operation *op, SlapReply *rs )
         * if we don't hold it.
         */
 
-       if ( (op->o_bd = select_backend( &op->o_req_ndn, 0, 0 )) == NULL ) {
+       if ( (op->o_bd = select_backend( &op->o_req_ndn, 0 )) == NULL ) {
                /* don't return referral for bind requests */
                /* noSuchObject is not allowed to be returned by bind */
                rs->sr_err = LDAP_INVALID_CREDENTIALS;
@@ -423,7 +428,7 @@ fe_op_bind_success( Operation *op, SlapReply *rs )
        Statslog( LDAP_DEBUG_STATS,
                "%s BIND dn=\"%s\" mech=%s ssf=0\n",
                op->o_log_prefix,
-               op->o_conn->c_dn.bv_val, op->orb_tmp_mech.bv_val, 0, 0 );
+               op->o_conn->c_dn.bv_val, op->orb_mech.bv_val, 0, 0 );
 
        Debug( LDAP_DEBUG_TRACE,
                "do_bind: v%d bind: \"%s\" to \"%s\"\n",
index 08115f45eda2bdc5b78fd1664db12c8eb2011e28..dd4c79730cd86f505eb0cbaf9694686dff4c5cef 100644 (file)
@@ -56,18 +56,18 @@ int cancel_extop( Operation *op, SlapReply *rs )
 
        (void) ber_free( ber, 1 );
 
+       Statslog( LDAP_DEBUG_STATS, "%s CANCEL msg=%d\n",
+               op->o_log_prefix, opid, 0, 0, 0 );
+
        if ( opid < 0 ) {
                rs->sr_text = "message ID invalid";
                return LDAP_PROTOCOL_ERROR;
        }
 
-       Statslog( LDAP_DEBUG_STATS, "%s CANCEL msg=%d\n",
-               op->o_log_prefix, opid, 0, 0, 0 );
-
        ldap_pvt_thread_mutex_lock( &op->o_conn->c_mutex );
        LDAP_STAILQ_FOREACH( o, &op->o_conn->c_pending_ops, o_next ) {
                if ( o->o_msgid == opid ) {
-                       LDAP_STAILQ_REMOVE( &op->o_conn->c_pending_ops, o, slap_op, o_next );
+                       LDAP_STAILQ_REMOVE( &op->o_conn->c_pending_ops, o, Operation, o_next );
                        LDAP_STAILQ_NEXT(o, o_next) = NULL;
                        op->o_conn->c_n_ops_pending--;
                        slap_op_free( o );
index 230602895a597849c61e6b39106d69634bd71e2e..900f585fa4a8d2031f6ac4ed84060cc7b4f4fcba 100644 (file)
@@ -44,15 +44,10 @@ do_compare(
        struct berval dn = BER_BVNULL;
        struct berval desc = BER_BVNULL;
        struct berval value = BER_BVNULL;
-#ifdef LDAP_COMP_MATCH
-       AttributeAssertion ava = { NULL, BER_BVNULL, NULL };
-#else
-       AttributeAssertion ava = { NULL, BER_BVNULL };
-#endif
+       AttributeAssertion ava = { 0 };
 
-       ava.aa_desc = NULL;
-
-       Debug( LDAP_DEBUG_TRACE, "do_compare\n", 0, 0, 0 );
+       Debug( LDAP_DEBUG_TRACE, "%s do_compare\n",
+               op->o_log_prefix, 0, 0 );
        /*
         * Parse the compare request.  It looks like this:
         *
@@ -66,37 +61,46 @@ do_compare(
         */
 
        if ( ber_scanf( op->o_ber, "{m" /*}*/, &dn ) == LBER_ERROR ) {
-               Debug( LDAP_DEBUG_ANY, "ber_scanf failed\n", 0, 0, 0 );
+               Debug( LDAP_DEBUG_ANY, "%s do_compare: ber_scanf failed\n",
+                       op->o_log_prefix, 0, 0 );
                send_ldap_discon( op, rs, LDAP_PROTOCOL_ERROR, "decoding error" );
                return SLAPD_DISCONNECT;
        }
 
        if ( ber_scanf( op->o_ber, "{mm}", &desc, &value ) == LBER_ERROR ) {
-               Debug( LDAP_DEBUG_ANY, "do_compare: get ava failed\n", 0, 0, 0 );
+               Debug( LDAP_DEBUG_ANY, "%s do_compare: get ava failed\n",
+                       op->o_log_prefix, 0, 0 );
                send_ldap_discon( op, rs, LDAP_PROTOCOL_ERROR, "decoding error" );
                return SLAPD_DISCONNECT;
        }
 
        if ( ber_scanf( op->o_ber, /*{*/ "}" ) == LBER_ERROR ) {
-               Debug( LDAP_DEBUG_ANY, "ber_scanf failed\n", 0, 0, 0 );
+               Debug( LDAP_DEBUG_ANY, "%s do_compare: ber_scanf failed\n",
+                       op->o_log_prefix, 0, 0 );
                send_ldap_discon( op, rs, LDAP_PROTOCOL_ERROR, "decoding error" );
                return SLAPD_DISCONNECT;
        }
 
        if( get_ctrls( op, rs, 1 ) != LDAP_SUCCESS ) {
-               Debug( LDAP_DEBUG_ANY, "do_compare: get_ctrls failed\n", 0, 0, 0 );
+               Debug( LDAP_DEBUG_ANY, "%s do_compare: get_ctrls failed\n",
+                       op->o_log_prefix, 0, 0 );
                goto cleanup;
        } 
 
        rs->sr_err = dnPrettyNormal( NULL, &dn, &op->o_req_dn, &op->o_req_ndn,
                op->o_tmpmemctx );
        if( rs->sr_err != LDAP_SUCCESS ) {
-               Debug( LDAP_DEBUG_ANY,
-                       "do_compare: invalid dn (%s)\n", dn.bv_val, 0, 0 );
+               Debug( LDAP_DEBUG_ANY, "%s do_compare: invalid dn (%s)\n",
+                       op->o_log_prefix, dn.bv_val, 0 );
                send_ldap_error( op, rs, LDAP_INVALID_DN_SYNTAX, "invalid DN" );
                goto cleanup;
        }
 
+       Statslog( LDAP_DEBUG_STATS,
+               "%s CMP dn=\"%s\" attr=\"%s\"\n",
+               op->o_log_prefix, op->o_req_dn.bv_val,
+               desc.bv_val, 0, 0 );
+
        rs->sr_err = slap_bv2ad( &desc, &ava.aa_desc, &rs->sr_text );
        if( rs->sr_err != LDAP_SUCCESS ) {
                rs->sr_err = slap_bv2undef_ad( &desc, &ava.aa_desc,
@@ -119,6 +123,11 @@ do_compare(
 
        op->orc_ava = &ava;
 
+       Debug( LDAP_DEBUG_ARGS,
+               "do_compare: dn (%s) attr (%s) value (%s)\n",
+               op->o_req_dn.bv_val,
+               ava.aa_desc->ad_cname.bv_val, ava.aa_value.bv_val );
+
        op->o_bd = frontendDB;
        rs->sr_err = frontendDB->be_compare( op, rs );
 
@@ -136,21 +145,10 @@ int
 fe_op_compare( Operation *op, SlapReply *rs )
 {
        Entry                   *entry = NULL;
-       int                     manageDSAit;
-       AttributeAssertion      ava = *op->orc_ava;
+       AttributeAssertion      *ava = op->orc_ava;
        BackendDB               *bd = op->o_bd;
 
        if( strcasecmp( op->o_req_ndn.bv_val, LDAP_ROOT_DSE ) == 0 ) {
-               Debug( LDAP_DEBUG_ARGS,
-                       "do_compare: dn (%s) attr (%s) value (%s)\n",
-                       op->o_req_dn.bv_val,
-                       ava.aa_desc->ad_cname.bv_val, ava.aa_value.bv_val );
-
-               Statslog( LDAP_DEBUG_STATS,
-                       "%s CMP dn=\"%s\" attr=\"%s\"\n",
-                       op->o_log_prefix, op->o_req_dn.bv_val,
-                       ava.aa_desc->ad_cname.bv_val, 0, 0 );
-
                if( backend_check_restrictions( op, rs, NULL ) != LDAP_SUCCESS ) {
                        send_ldap_result( op, rs );
                        goto cleanup;
@@ -163,15 +161,6 @@ fe_op_compare( Operation *op, SlapReply *rs )
                }
 
        } else if ( bvmatch( &op->o_req_ndn, &frontendDB->be_schemandn ) ) {
-               Debug( LDAP_DEBUG_ARGS, "do_compare: dn (%s) attr (%s) value (%s)\n",
-                       op->o_req_dn.bv_val,
-                       ava.aa_desc->ad_cname.bv_val, ava.aa_value.bv_val );
-
-               Statslog( LDAP_DEBUG_STATS,
-                       "%s CMP dn=\"%s\" attr=\"%s\"\n",
-                       op->o_log_prefix, op->o_req_dn.bv_val,
-                       ava.aa_desc->ad_cname.bv_val, 0, 0 );
-
                if( backend_check_restrictions( op, rs, NULL ) != LDAP_SUCCESS ) {
                        send_ldap_result( op, rs );
                        rs->sr_err = 0;
@@ -187,7 +176,7 @@ fe_op_compare( Operation *op, SlapReply *rs )
        }
 
        if( entry ) {
-               rs->sr_err = compare_entry( op, entry, &ava );
+               rs->sr_err = compare_entry( op, entry, ava );
                entry_free( entry );
 
                send_ldap_result( op, rs );
@@ -201,14 +190,12 @@ fe_op_compare( Operation *op, SlapReply *rs )
                goto cleanup;
        }
 
-       manageDSAit = get_manageDSAit( op );
-
        /*
         * We could be serving multiple database backends.  Select the
         * appropriate one, or send a referral to our "referral server"
         * if we don't hold it.
         */
-       op->o_bd = select_backend( &op->o_req_ndn, manageDSAit, 0 );
+       op->o_bd = select_backend( &op->o_req_ndn, 0 );
        if ( op->o_bd == NULL ) {
                rs->sr_ref = referral_rewrite( default_referral,
                        NULL, &op->o_req_dn, LDAP_SCOPE_DEFAULT );
@@ -234,31 +221,21 @@ fe_op_compare( Operation *op, SlapReply *rs )
                goto cleanup;
        }
 
-       Debug( LDAP_DEBUG_ARGS, "do_compare: dn (%s) attr (%s) value (%s)\n",
-           op->o_req_dn.bv_val,
-               ava.aa_desc->ad_cname.bv_val, ava.aa_value.bv_val );
-
-       Statslog( LDAP_DEBUG_STATS, "%s CMP dn=\"%s\" attr=\"%s\"\n",
-               op->o_log_prefix, op->o_req_dn.bv_val,
-               ava.aa_desc->ad_cname.bv_val, 0, 0 );
-
-       op->orc_ava = &ava;
-
        if ( SLAP_SHADOW(op->o_bd) && get_dontUseCopy(op) ) {
                /* don't use shadow copy */
                send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
                        "copy not used" );
 
-       } else if ( ava.aa_desc == slap_schema.si_ad_entryDN ) {
+       } else if ( ava->aa_desc == slap_schema.si_ad_entryDN ) {
                send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
                        "entryDN compare not supported" );
 
-       } else if ( ava.aa_desc == slap_schema.si_ad_subschemaSubentry ) {
+       } else if ( ava->aa_desc == slap_schema.si_ad_subschemaSubentry ) {
                send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
                        "subschemaSubentry compare not supported" );
 
 #ifndef SLAP_COMPARE_IN_FRONTEND
-       } else if ( ava.aa_desc == slap_schema.si_ad_hasSubordinates
+       } else if ( ava->aa_desc == slap_schema.si_ad_hasSubordinates
                && op->o_bd->be_has_subordinates )
        {
                int     rc, hasSubordinates = LDAP_SUCCESS;
@@ -266,7 +243,7 @@ fe_op_compare( Operation *op, SlapReply *rs )
                rc = be_entry_get_rw( op, &op->o_req_ndn, NULL, NULL, 0, &entry );
                if ( rc == 0 && entry ) {
                        if ( ! access_allowed( op, entry,
-                               ava.aa_desc, &ava.aa_value, ACL_COMPARE, NULL ) )
+                               ava->aa_desc, &ava->aa_value, ACL_COMPARE, NULL ) )
                        {       
                                rc = rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
                                
@@ -280,7 +257,7 @@ fe_op_compare( Operation *op, SlapReply *rs )
                if ( rc == 0 ) {
                        int     asserted;
 
-                       asserted = bvmatch( &ava.aa_value, &slap_true_bv )
+                       asserted = bvmatch( &ava->aa_value, &slap_true_bv )
                                ? LDAP_COMPARE_TRUE : LDAP_COMPARE_FALSE;
                        if ( hasSubordinates == asserted ) {
                                rs->sr_err = LDAP_COMPARE_TRUE;
@@ -329,7 +306,7 @@ fe_op_compare( Operation *op, SlapReply *rs )
                int             rc = LDAP_OTHER;
 
                rs->sr_err = backend_attribute( op, NULL, &op->o_req_ndn,
-                               ava.aa_desc, &vals, ACL_COMPARE );
+                               ava->aa_desc, &vals, ACL_COMPARE );
                switch ( rs->sr_err ) {
                default:
                        /* return error only if "disclose"
@@ -347,7 +324,7 @@ fe_op_compare( Operation *op, SlapReply *rs )
                        if ( value_find_ex( op->oq_compare.rs_ava->aa_desc,
                                SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH |
                                        SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH,
-                               vals, &ava.aa_value, op->o_tmpmemctx ) == 0 )
+                               vals, &ava->aa_value, op->o_tmpmemctx ) == 0 )
                        {
                                rs->sr_err = LDAP_COMPARE_TRUE;
                                break;
index 54dcf2d571eb86deeb9a8709c9d3cb26dff9ebde..d6655a78a01eda9113da6bec7324067e48a03e77 100644 (file)
@@ -41,7 +41,7 @@
 #define        S_ISREG(m)      (((m) & _S_IFMT) == _S_IFREG)
 #endif
 
-#if HAVE_UNISTD_H
+#ifdef HAVE_UNISTD_H
 #include <unistd.h>
 #endif
 
 #include "lutil_ldap.h"
 #include "config.h"
 
-#ifdef HAVE_TLS
-#include <openssl/ssl.h>
-#endif
-
 #define ARGS_STEP      512
 
 /*
@@ -145,54 +141,54 @@ int config_check_vals(ConfigTable *Conf, ConfigArgs *c, int check_only ) {
                c->argv[1] = "";
        }
        if(Conf->min_args && (c->argc < Conf->min_args)) {
-               snprintf( c->msg, sizeof( c->msg ), "<%s> missing <%s> argument",
+               snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> missing <%s> argument",
                        c->argv[0], Conf->what );
-               Debug(LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, "%s: keyword %s\n", c->log, c->msg, 0 );
+               Debug(LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, "%s: keyword %s\n", c->log, c->cr_msg, 0 );
                return(ARG_BAD_CONF);
        }
        if(Conf->max_args && (c->argc > Conf->max_args)) {
                char    *ignored = " ignored";
 
-               snprintf( c->msg, sizeof( c->msg ), "<%s> extra cruft after <%s>",
+               snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> extra cruft after <%s>",
                        c->argv[0], Conf->what );
 
                ignored = "";
                Debug(LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, "%s: %s%s.\n",
-                               c->log, c->msg, ignored );
+                               c->log, c->cr_msg, ignored );
                return(ARG_BAD_CONF);
        }
        if((arg_syn & ARG_DB) && !c->be) {
-               snprintf( c->msg, sizeof( c->msg ), "<%s> only allowed within database declaration",
+               snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> only allowed within database declaration",
                        c->argv[0] );
                Debug(LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, "%s: keyword %s\n",
-                       c->log, c->msg, 0);
+                       c->log, c->cr_msg, 0);
                return(ARG_BAD_CONF);
        }
        if((arg_syn & ARG_PRE_BI) && c->bi) {
-               snprintf( c->msg, sizeof( c->msg ), "<%s> must occur before any backend %sdeclaration",
+               snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> must occur before any backend %sdeclaration",
                        c->argv[0], (arg_syn & ARG_PRE_DB) ? "or database " : "" );
                Debug(LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, "%s: keyword %s\n",
-                       c->log, c->msg, 0 );
+                       c->log, c->cr_msg, 0 );
                return(ARG_BAD_CONF);
        }
        if((arg_syn & ARG_PRE_DB) && c->be && c->be != frontendDB) {
-               snprintf( c->msg, sizeof( c->msg ), "<%s> must occur before any database declaration",
+               snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> must occur before any database declaration",
                        c->argv[0] );
                Debug(LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, "%s: keyword %s\n",
-                       c->log, c->msg, 0);
+                       c->log, c->cr_msg, 0);
                return(ARG_BAD_CONF);
        }
        if((arg_syn & ARG_PAREN) && *c->argv[1] != '(' /*')'*/) {
-               snprintf( c->msg, sizeof( c->msg ), "<%s> old format not supported", c->argv[0] );
+               snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> old format not supported", c->argv[0] );
                Debug(LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, "%s: %s\n",
-                       c->log, c->msg, 0);
+                       c->log, c->cr_msg, 0);
                return(ARG_BAD_CONF);
        }
        if(arg_type && !Conf->arg_item && !(arg_syn & ARG_OFFSET)) {
-               snprintf( c->msg, sizeof( c->msg ), "<%s> invalid config_table, arg_item is NULL",
+               snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> invalid config_table, arg_item is NULL",
                        c->argv[0] );
                Debug(LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, "%s: %s\n",
-                       c->log, c->msg, 0);
+                       c->log, c->cr_msg, 0);
                return(ARG_BAD_CONF);
        }
        c->type = arg_user;
@@ -208,9 +204,9 @@ int config_check_vals(ConfigTable *Conf, ConfigArgs *c, int check_only ) {
                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)",
+                       snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> invalid DN %d (%s)",
                                c->argv[0], rc, ldap_err2string( rc ));
-                       Debug(LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, "%s: %s\n" , c->log, c->msg, 0);
+                       Debug(LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, "%s: %s\n" , c->log, c->cr_msg, 0);
                        return(ARG_BAD_CONF);
                }
                if ( check_only ) {
@@ -223,32 +219,32 @@ int config_check_vals(ConfigTable *Conf, ConfigArgs *c, int check_only ) {
                switch(arg_type) {
                        case ARG_INT:
                                if ( lutil_atoix( &iarg, c->argv[1], 0 ) != 0 ) {
-                                       snprintf( c->msg, sizeof( c->msg ),
+                                       snprintf( c->cr_msg, sizeof( c->cr_msg ),
                                                "<%s> unable to parse \"%s\" as int",
                                                c->argv[0], c->argv[1] );
                                        Debug(LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, "%s: %s\n",
-                                               c->log, c->msg, 0);
+                                               c->log, c->cr_msg, 0);
                                        return(ARG_BAD_CONF);
                                }
                                break;
                        case ARG_LONG:
                                if ( lutil_atolx( &larg, c->argv[1], 0 ) != 0 ) {
-                                       snprintf( c->msg, sizeof( c->msg ),
+                                       snprintf( c->cr_msg, sizeof( c->cr_msg ),
                                                "<%s> unable to parse \"%s\" as long",
                                                c->argv[0], c->argv[1] );
                                        Debug(LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, "%s: %s\n",
-                                               c->log, c->msg, 0);
+                                               c->log, c->cr_msg, 0);
                                        return(ARG_BAD_CONF);
                                }
                                break;
                        case ARG_BER_LEN_T: {
                                unsigned long   l;
                                if ( lutil_atoulx( &l, c->argv[1], 0 ) != 0 ) {
-                                       snprintf( c->msg, sizeof( c->msg ),
+                                       snprintf( c->cr_msg, sizeof( c->cr_msg ),
                                                "<%s> unable to parse \"%s\" as ber_len_t",
                                                c->argv[0], c->argv[1] );
                                        Debug(LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, "%s: %s\n",
-                                               c->log, c->msg, 0);
+                                               c->log, c->cr_msg, 0);
                                        return(ARG_BAD_CONF);
                                }
                                barg = (ber_len_t)l;
@@ -267,10 +263,10 @@ int config_check_vals(ConfigTable *Conf, ConfigArgs *c, int check_only ) {
                                {
                                        iarg = 0;
                                } else {
-                                       snprintf( c->msg, sizeof( c->msg ), "<%s> invalid value",
+                                       snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> invalid value",
                                                c->argv[0] );
                                        Debug(LDAP_DEBUG_ANY|LDAP_DEBUG_NONE, "%s: %s\n",
-                                               c->log, c->msg, 0 );
+                                               c->log, c->cr_msg, 0 );
                                        return(ARG_BAD_CONF);
                                }
                                break;
@@ -278,10 +274,10 @@ int config_check_vals(ConfigTable *Conf, ConfigArgs *c, int check_only ) {
                j = (arg_type & ARG_NONZERO) ? 1 : 0;
                if(iarg < j && larg < j && barg < j ) {
                        larg = larg ? larg : (barg ? barg : iarg);
-                       snprintf( c->msg, sizeof( c->msg ), "<%s> invalid value",
+                       snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> invalid value",
                                c->argv[0] );
                        Debug(LDAP_DEBUG_ANY|LDAP_DEBUG_NONE, "%s: %s\n",
-                               c->log, c->msg, 0 );
+                               c->log, c->cr_msg, 0 );
                        return(ARG_BAD_CONF);
                }
                switch(arg_type) {
@@ -301,33 +297,32 @@ int config_set_vals(ConfigTable *Conf, ConfigArgs *c) {
        arg_type = Conf->arg_type;
        if(arg_type & ARG_MAGIC) {
                if(!c->be) c->be = frontendDB;
-               c->msg[0] = '\0';
+               c->cr_msg[0] = '\0';
                rc = (*((ConfigDriver*)Conf->arg_item))(c);
 #if 0
                if(c->be == frontendDB) c->be = NULL;
 #endif
                if(rc) {
-                       if ( !c->msg[0] ) {
-                               snprintf( c->msg, sizeof( c->msg ), "<%s> handler exited with %d",
+                       if ( !c->cr_msg[0] ) {
+                               snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> handler exited with %d",
                                        c->argv[0], rc );
                                Debug(LDAP_DEBUG_CONFIG, "%s: %s!\n",
-                                       c->log, c->msg, 0 );
+                                       c->log, c->cr_msg, 0 );
                        }
                        return(ARG_BAD_CONF);
                }
                return(0);
        }
        if(arg_type & ARG_OFFSET) {
-               if (c->be && (!overlay_is_over(c->be) || 
-                       ((slap_overinfo *)c->be->bd_info)->oi_orig == c->bi))
+               if (c->be && c->table == Cft_Database)
                        ptr = c->be->be_private;
                else if (c->bi)
                        ptr = c->bi->bi_private;
                else {
-                       snprintf( c->msg, sizeof( c->msg ), "<%s> offset is missing base pointer",
+                       snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> offset is missing base pointer",
                                c->argv[0] );
                        Debug(LDAP_DEBUG_CONFIG, "%s: %s!\n",
-                               c->log, c->msg, 0);
+                               c->log, c->cr_msg, 0);
                        return(ARG_BAD_CONF);
                }
                ptr = (void *)((char *)ptr + (long)Conf->arg_item);
@@ -410,8 +405,7 @@ config_get_vals(ConfigTable *cf, ConfigArgs *c)
                if ( rc ) return rc;
        } else {
                if ( cf->arg_type & ARG_OFFSET ) {
-                       if (c->be && (!overlay_is_over(c->be) || 
-                               ((slap_overinfo *)c->be->bd_info)->oi_orig == c->bi))
+                       if (c->be && c->table == Cft_Database)
                                ptr = c->be->be_private;
                        else if ( c->bi )
                                ptr = c->bi->bi_private;
@@ -728,6 +722,7 @@ read_config_file(const char *fname, int depth, ConfigArgs *cf, ConfigTable *cft)
 
                ct = config_find_keyword( cft, c );
                if ( ct ) {
+                       c->table = Cft_Global;
                        rc = config_add_vals( ct, c );
                        if ( !rc ) continue;
 
@@ -748,6 +743,7 @@ read_config_file(const char *fname, int depth, ConfigArgs *cf, ConfigTable *cft)
                        if ( c->bi->bi_cf_ocs ) {
                                ct = config_find_keyword( c->bi->bi_cf_ocs->co_table, c );
                                if ( ct ) {
+                                       c->table = c->bi->bi_cf_ocs->co_type;
                                        rc = config_add_vals( ct, c );
                                }
                        }
@@ -772,6 +768,7 @@ read_config_file(const char *fname, int depth, ConfigArgs *cf, ConfigTable *cft)
                        if ( c->be->be_cf_ocs ) {
                                ct = config_find_keyword( c->be->be_cf_ocs->co_table, c );
                                if ( ct ) {
+                                       c->table = c->be->be_cf_ocs->co_type;
                                        rc = config_add_vals( ct, c );
                                }
                        }
@@ -1040,7 +1037,7 @@ static slap_cf_aux_table bindkey[] = {
        { BER_BVC("saslmech="), offsetof(slap_bindconf, sb_saslmech), 'b', 0, NULL },
        { BER_BVC("secprops="), offsetof(slap_bindconf, sb_secprops), 's', 0, NULL },
        { BER_BVC("realm="), offsetof(slap_bindconf, sb_realm), 'b', 0, NULL },
-       { BER_BVC("authcID="), offsetof(slap_bindconf, sb_authcId), 'b', 0, (slap_verbmasks *)authzNormalize },
+       { BER_BVC("authcID="), offsetof(slap_bindconf, sb_authcId), 'b', 1, NULL },
        { BER_BVC("authzID="), offsetof(slap_bindconf, sb_authzId), 'b', 1, (slap_verbmasks *)authzNormalize },
 #ifdef HAVE_TLS
        { BER_BVC("starttls="), offsetof(slap_bindconf, sb_tls), 'i', 0, tlskey },
@@ -1350,12 +1347,6 @@ void bindconf_free( slap_bindconf *bc ) {
                BER_BVZERO( &bc->sb_authzId );
        }
 #ifdef HAVE_TLS
-#if 0
-       if ( bc->sb_tls_ctx ) {
-               SSL_CTX_free( bc->sb_tls_ctx );
-               bc->sb_tls_ctx = NULL;
-       }
-#endif
        if ( bc->sb_tls_cert ) {
                ch_free( bc->sb_tls_cert );
                bc->sb_tls_cert = NULL;
@@ -1482,7 +1473,7 @@ int bindconf_tls_set( slap_bindconf *bc, LDAP *ld )
                int opt = 0;
 
                if ( bc->sb_tls_ctx ) {
-                       SSL_CTX_free( bc->sb_tls_ctx );
+                       ldap_pvt_tls_ctx_free( bc->sb_tls_ctx );
                        bc->sb_tls_ctx = NULL;
                }
                rc = ldap_set_option( ld, LDAP_OPT_X_TLS_NEWCTX, &opt );
@@ -1593,6 +1584,10 @@ slap_client_connect( LDAP **ldp, slap_bindconf *sb )
                        sb->sb_authcId.bv_val,
                        sb->sb_cred.bv_val,
                        sb->sb_authzId.bv_val );
+               if ( defaults == NULL ) {
+                       rc = LDAP_OTHER;
+                       goto done;
+               }
 
                rc = ldap_sasl_interactive_bind_s( ld,
                                sb->sb_binddn.bv_val,
@@ -1914,7 +1909,9 @@ int config_generic_wrapper( Backend *be, const char *fname, int lineno,
 
        rc = SLAP_CONF_UNKNOWN;
        ct = config_find_keyword( be->be_cf_ocs->co_table, &c );
-       if ( ct )
+       if ( ct ) {
+               c.table = be->be_cf_ocs->co_type;
                rc = config_add_vals( ct, &c );
+       }
        return rc;
 }
index eac44942e9ecb44175b9a36f80547ecfb5184168..be5e2925a8ddce6b9fafd463f817004f124d6865 100644 (file)
@@ -17,6 +17,8 @@
 #ifndef CONFIG_H
 #define CONFIG_H
 
+#include<ac/string.h>
+
 typedef struct ConfigTable {
        char *name;
        char *what;
@@ -105,6 +107,11 @@ typedef struct ConfigOCs {
 
 typedef int (ConfigDriver)(struct config_args_s *c);
 
+typedef struct config_reply_s {
+       int err;
+       char msg[SLAP_TEXT_BUFLEN];
+} ConfigReply;
+
 typedef struct config_args_s {
        int argc;
        char **argv;
@@ -114,7 +121,8 @@ typedef struct config_args_s {
        const char *fname;
        int lineno;
        char log[MAXPATHLEN + STRLENOF(": line 18446744073709551615") + 1];
-       char msg[SLAP_TEXT_BUFLEN];
+#define cr_msg reply.msg
+       ConfigReply reply;
        int depth;
        int valx;       /* multi-valued value index */
        /* parsed first val for simple cases */
@@ -142,6 +150,7 @@ typedef struct config_args_s {
        Entry *ca_entry;        /* entry being modified */
        void *private;  /* anything */
        ConfigDriver *cleanup;
+       ConfigType table;       /* which config table did we come from */
 } ConfigArgs;
 
 /* If lineno is zero, we have an actual LDAP Add request from a client.
index 062734c449a27fcad000d355bca39f6b60e179cf..9ec67f503a6d049ee48eec22e6e75089100234c6 100644 (file)
@@ -359,14 +359,15 @@ static void connection_return( Connection *c )
        ldap_pvt_thread_mutex_unlock( &c->c_mutex );
 }
 
-long connection_init(
+Connection * connection_init(
        ber_socket_t s,
        Listener *listener,
        const char* dnsname,
        const char* peername,
        int flags,
        slap_ssf_t ssf,
-       struct berval *authid )
+       struct berval *authid
+       LDAP_PF_LOCAL_SENDMSG_ARG(struct berval *peerbv))
 {
        unsigned long id;
        Connection *c;
@@ -379,13 +380,13 @@ long connection_init(
        assert( peername != NULL );
 
 #ifndef HAVE_TLS
-       assert( flags != CONN_IS_TLS );
+       assert( !( flags & CONN_IS_TLS ));
 #endif
 
        if( s == AC_SOCKET_INVALID ) {
                Debug( LDAP_DEBUG_ANY,
                        "connection_init: init of socket %ld invalid.\n", (long)s, 0, 0 );
-               return -1;
+               return NULL;
        }
 
        assert( s >= 0 );
@@ -442,7 +443,7 @@ long connection_init(
                        Debug( LDAP_DEBUG_ANY,
                                "connection_init(%d): connection table full "
                                "(%d/%d)\n", s, i, dtblsize);
-                       return -1;
+                       return NULL;
                }
        }
 #endif
@@ -525,14 +526,15 @@ long connection_init(
 
        c->c_listener = listener;
 
-       if ( flags == CONN_IS_CLIENT ) {
+       if ( flags & CONN_IS_CLIENT ) {
+               c->c_connid = 0;
                c->c_conn_state = SLAP_C_CLIENT;
                c->c_struct_state = SLAP_C_USED;
                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 );
 
-               return 0;
+               return c;
        }
 
        ber_str2bv( dnsname, 0, 1, &c->c_peer_domain );
@@ -559,7 +561,7 @@ long connection_init(
 
 #ifdef LDAP_CONNECTIONLESS
        c->c_is_udp = 0;
-       if( flags == CONN_IS_UDP ) {
+       if( flags & CONN_IS_UDP ) {
                c->c_is_udp = 1;
 #ifdef LDAP_DEBUG
                ber_sockbuf_add_io( c->c_sb, &ber_sockbuf_io_debug,
@@ -570,7 +572,21 @@ long connection_init(
                ber_sockbuf_add_io( c->c_sb, &ber_sockbuf_io_readahead,
                        LBER_SBIOD_LEVEL_PROVIDER, NULL );
        } else
+#endif /* LDAP_CONNECTIONLESS */
+#ifdef LDAP_PF_LOCAL
+       if ( flags & CONN_IS_IPC ) {
+#ifdef LDAP_DEBUG
+               ber_sockbuf_add_io( c->c_sb, &ber_sockbuf_io_debug,
+                       LBER_SBIOD_LEVEL_PROVIDER, (void*)"ipc_" );
 #endif
+               ber_sockbuf_add_io( c->c_sb, &ber_sockbuf_io_fd,
+                       LBER_SBIOD_LEVEL_PROVIDER, (void *)&s );
+#ifdef LDAP_PF_LOCAL_SENDMSG
+               if ( !BER_BVISEMPTY( peerbv ))
+                       ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_UNGET_BUF, peerbv );
+#endif
+       } else
+#endif /* LDAP_PF_LOCAL */
        {
 #ifdef LDAP_DEBUG
                ber_sockbuf_add_io( c->c_sb, &ber_sockbuf_io_debug,
@@ -605,7 +621,7 @@ long connection_init(
        c->c_tls_ssf = 0;
 
 #ifdef HAVE_TLS
-       if ( flags == CONN_IS_TLS ) {
+       if ( flags & CONN_IS_TLS ) {
                c->c_is_tls = 1;
                c->c_needs_tls_accept = 1;
        } else {
@@ -622,7 +638,7 @@ long connection_init(
 
        backend_connection_init(c);
 
-       return id;
+       return c;
 }
 
 void connection2anonymous( Connection *c )
@@ -1022,12 +1038,12 @@ void connection_done( Connection *c )
 static BI_op_func *opfun[] = {
        do_bind,
        do_unbind,
+       do_search,
+       do_compare,
+       do_modify,
+       do_modrdn,
        do_add,
        do_delete,
-       do_modrdn,
-       do_modify,
-       do_compare,
-       do_search,
        do_abandon,
        do_extended,
        NULL
@@ -1157,7 +1173,7 @@ operations_error:
 
        ber_set_option( op->o_ber, LBER_OPT_BER_MEMCTX, &memctx_null );
 
-       LDAP_STAILQ_REMOVE( &conn->c_ops, op, slap_op, o_next);
+       LDAP_STAILQ_REMOVE( &conn->c_ops, op, Operation, o_next);
        LDAP_STAILQ_NEXT(op, o_next) = NULL;
        slap_op_free( op );
        conn->c_n_ops_executing--;
@@ -1184,20 +1200,18 @@ int connection_client_setup(
        ldap_pvt_thread_start_t *func,
        void *arg )
 {
-       int rc;
        Connection *c;
 
-       rc = connection_init( s, (Listener *)&dummy_list, "", "",
-               CONN_IS_CLIENT, 0, NULL );
-       if ( rc < 0 ) return -1;
+       c = connection_init( s, (Listener *)&dummy_list, "", "",
+               CONN_IS_CLIENT, 0, NULL
+               LDAP_PF_LOCAL_SENDMSG_ARG(NULL));
+       if ( !c ) return -1;
 
-       c = connection_get( s );
        c->c_clientfunc = func;
        c->c_clientarg = arg;
 
        slapd_add_internal( s, 0 );
        slapd_set_read( s, 1 );
-       connection_return( c );
        return 0;
 }
 
@@ -1438,7 +1452,7 @@ int connection_read(ber_socket_t s)
        }
 #ifdef DATA_READY_LOOP
        while( !rc && ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_DATA_READY, NULL ));
-#elif CONNECTION_INPUT_LOOP
+#elif defined CONNECTION_INPUT_LOOP
        while(!rc);
 #else
        while(0);
@@ -1801,13 +1815,14 @@ static int connection_bind_cb( Operation *op, SlapReply *rs )
 
                        /* log authorization identity */
                        Statslog( LDAP_DEBUG_STATS,
-                               "%s BIND dn=\"%s\" mech=%s ssf=%d\n",
+                               "%s BIND dn=\"%s\" mech=%s sasl_ssf=%d ssf=%d\n",
                                op->o_log_prefix,
                                BER_BVISNULL( &op->o_conn->c_dn ) ? "<empty>" : op->o_conn->c_dn.bv_val,
-                               op->o_conn->c_authmech.bv_val, op->orb_ssf, 0 );
+                               op->o_conn->c_authmech.bv_val,
+                               op->orb_ssf, op->o_conn->c_ssf );
 
                        Debug( LDAP_DEBUG_TRACE,
-                               "do_bind: SASL/%s bind: dn=\"%s\" ssf=%d\n",
+                               "do_bind: SASL/%s bind: dn=\"%s\" sasl_ssf=%d\n",
                                op->o_conn->c_authmech.bv_val,
                                BER_BVISNULL( &op->o_conn->c_dn ) ? "<empty>" : op->o_conn->c_dn.bv_val,
                                op->orb_ssf );
@@ -1979,19 +1994,21 @@ connection_fake_destroy(
 void
 connection_fake_init(
        Connection *conn,
-       Operation *op,
+       OperationBuffer *opbuf,
        void *ctx )
 {
-       connection_fake_init2( conn, op, ctx, 1 );
+       connection_fake_init2( conn, opbuf, ctx, 1 );
 }
 
 void
 connection_fake_init2(
        Connection *conn,
-       Operation *op,
+       OperationBuffer *opbuf,
        void *ctx,
        int newmem )
 {
+       Operation *op = (Operation *) opbuf;
+
        conn->c_connid = -1;
        conn->c_send_ldap_result = slap_send_ldap_result;
        conn->c_send_search_entry = slap_send_search_entry;
@@ -2000,9 +2017,10 @@ connection_fake_init2(
        conn->c_peer_domain = slap_empty_bv;
        conn->c_peer_name = slap_empty_bv;
 
-       memset(op, 0, OPERATION_BUFFER_SIZE);
-       op->o_hdr = (Opheader *)(op+1);
-       op->o_controls = (void **)(op->o_hdr+1);
+       memset( opbuf, 0, sizeof( *opbuf ));
+       op->o_hdr = &opbuf->ob_hdr;
+       op->o_controls = opbuf->ob_controls;
+
        /* set memory context */
        op->o_tmpmemctx = slap_sl_mem_create(SLAP_SLAB_SIZE, SLAP_SLAB_STACK, ctx,
                newmem );
@@ -2016,10 +2034,11 @@ connection_fake_init2(
 
 #ifdef LDAP_SLAPI
        if ( slapi_plugins_used ) {
-               conn_fake_extblock *eb = NULL;
+               conn_fake_extblock *eb;
+               void *ebx = NULL;
 
                /* Use thread keys to make sure these eventually get cleaned up */
-               if ( ldap_pvt_thread_pool_getkey( ctx, connection_fake_init, &eb,
+               if ( ldap_pvt_thread_pool_getkey( ctx, connection_fake_init, &ebx,
                        NULL )) {
                        eb = ch_malloc( sizeof( *eb ));
                        slapi_int_create_object_extensions( SLAPI_X_EXT_CONNECTION, conn );
@@ -2029,6 +2048,7 @@ connection_fake_init2(
                        ldap_pvt_thread_pool_setkey( ctx, connection_fake_init, eb,
                                connection_fake_destroy );
                } else {
+                       eb = ebx;
                        conn->c_extensions = eb->eb_conn;
                        op->o_hdr->oh_extensions = eb->eb_op;
                }
index f9e9b9b076fafb20c3d4ecc418f81c53628de850..ed887e5f1a4b27ced92bc7ca4e43c8112720d5df 100644 (file)
@@ -21,6 +21,8 @@
 #include <ac/socket.h>
 
 #include "slap.h"
+#include "ldif.h"
+#include "lutil.h"
 
 #include "../../libraries/liblber/lber-int.h"
 
@@ -35,7 +37,7 @@ static SLAP_CTRL_PARSE_FN parsePreRead, parsePostRead;
 static SLAP_CTRL_PARSE_FN parseProxyAuthz;
 static SLAP_CTRL_PARSE_FN parseRelax;
 static SLAP_CTRL_PARSE_FN parseSearchOptions;
-#ifdef SLAP_SORTEDRESULTS
+#ifdef SLAP_CONTROL_X_SORTEDRESULTS
 static SLAP_CTRL_PARSE_FN parseSortedResults;
 #endif
 static SLAP_CTRL_PARSE_FN parseSubentries;
@@ -43,6 +45,9 @@ static SLAP_CTRL_PARSE_FN parseSubentries;
 static SLAP_CTRL_PARSE_FN parseTreeDelete;
 #endif
 static SLAP_CTRL_PARSE_FN parseValuesReturnFilter;
+#ifdef SLAP_CONTROL_X_SESSION_TRACKING
+static SLAP_CTRL_PARSE_FN parseSessionTracking;
+#endif
 
 #undef sc_mask /* avoid conflict with Irix 6.5 <sys/signal.h> */
 
@@ -103,6 +108,15 @@ static char *manageDSAit_extops[] = {
        NULL
 };
 
+#ifdef SLAP_CONTROL_X_SESSION_TRACKING
+static char *session_tracking_extops[] = {
+       LDAP_EXOP_MODIFY_PASSWD,
+       LDAP_EXOP_WHO_AM_I,
+       LDAP_EXOP_REFRESH,
+       NULL
+};
+#endif
+
 static struct slap_control control_defs[] = {
        {  LDAP_CONTROL_ASSERT,
                (int)offsetof(struct slap_control_ids, sc_assert),
@@ -130,7 +144,7 @@ static struct slap_control control_defs[] = {
                SLAP_CTRL_SEARCH,
                NULL, NULL,
                parsePagedResults, LDAP_SLIST_ENTRY_INITIALIZER(next) },
-#ifdef SLAP_SORTEDRESULTS
+#ifdef SLAP_CONTROL_X_SORTEDRESULTS
        { LDAP_CONTROL_SORTREQUEST,
                (int)offsetof(struct slap_control_ids, sc_sortedResults),
                SLAP_CTRL_GLOBAL|SLAP_CTRL_SEARCH|SLAP_CTRL_HIDE,
@@ -196,6 +210,13 @@ static struct slap_control control_defs[] = {
                SLAP_CTRL_GLOBAL|SLAP_CTRL_ACCESS,
                proxy_authz_extops, NULL,
                parseProxyAuthz, LDAP_SLIST_ENTRY_INITIALIZER(next) },
+#ifdef SLAP_CONTROL_X_SESSION_TRACKING
+       { LDAP_CONTROL_X_SESSION_TRACKING,
+               (int)offsetof(struct slap_control_ids, sc_sessionTracking),
+               SLAP_CTRL_GLOBAL|SLAP_CTRL_ACCESS|SLAP_CTRL_BIND|SLAP_CTRL_HIDE,
+               session_tracking_extops, NULL,
+               parseSessionTracking, LDAP_SLIST_ENTRY_INITIALIZER(next) },
+#endif
        { NULL, 0, 0, NULL, 0, NULL, LDAP_SLIST_ENTRY_INITIALIZER(next) }
 };
 
@@ -849,8 +870,8 @@ static int parseDontUseCopy (
                return LDAP_PROTOCOL_ERROR;
        }
 
-       if ( ctrl->ldctl_value.bv_len ) {
-               rs->sr_text = "dontUseCopy control value not empty";
+       if ( !BER_BVISNULL( &ctrl->ldctl_value )) {
+               rs->sr_text = "dontUseCopy control value not absent";
                return LDAP_PROTOCOL_ERROR;
        }
 
@@ -873,8 +894,8 @@ static int parseRelax (
                return LDAP_PROTOCOL_ERROR;
        }
 
-       if ( ctrl->ldctl_value.bv_len ) {
-               rs->sr_text = "relax control value not empty";
+       if ( !BER_BVISNULL( &ctrl->ldctl_value )) {
+               rs->sr_text = "relax control value not absent";
                return LDAP_PROTOCOL_ERROR;
        }
 
@@ -895,8 +916,8 @@ static int parseManageDSAit (
                return LDAP_PROTOCOL_ERROR;
        }
 
-       if ( ctrl->ldctl_value.bv_len ) {
-               rs->sr_text = "manageDSAit control value not empty";
+       if ( !BER_BVISNULL( &ctrl->ldctl_value )) {
+               rs->sr_text = "manageDSAit control value not absent";
                return LDAP_PROTOCOL_ERROR;
        }
 
@@ -920,6 +941,11 @@ static int parseProxyAuthz (
                return LDAP_PROTOCOL_ERROR;
        }
 
+       if ( BER_BVISNULL( &ctrl->ldctl_value )) {
+               rs->sr_text = "proxy authorization control value absent";
+               return LDAP_PROTOCOL_ERROR;
+       }
+
        if ( !( global_allows & SLAP_ALLOW_PROXY_AUTHZ_ANON )
                && BER_BVISEMPTY( &op->o_ndn ) )
        {
@@ -937,7 +963,7 @@ static int parseProxyAuthz (
                ctrl->ldctl_value.bv_len ?  ctrl->ldctl_value.bv_val : "anonymous",
                0 );
 
-       if ( ctrl->ldctl_value.bv_len == 0 ) {
+       if ( BER_BVISEMPTY( &ctrl->ldctl_value )) {
                Debug( LDAP_DEBUG_TRACE,
                        "parseProxyAuthz: conn=%lu anonymous\n", 
                        op->o_connid, 0, 0 );
@@ -1007,7 +1033,7 @@ static int parseNoOp (
                return LDAP_PROTOCOL_ERROR;
        }
 
-       if ( ctrl->ldctl_value.bv_len ) {
+       if ( !BER_BVISNULL( &ctrl->ldctl_value ) ) {
                rs->sr_text = "noop control value not empty";
                return LDAP_PROTOCOL_ERROR;
        }
@@ -1036,8 +1062,13 @@ static int parsePagedResults (
                return LDAP_PROTOCOL_ERROR;
        }
 
+       if ( BER_BVISNULL( &ctrl->ldctl_value ) ) {
+               rs->sr_text = "paged results control value is absent";
+               return LDAP_PROTOCOL_ERROR;
+       }
+
        if ( BER_BVISEMPTY( &ctrl->ldctl_value ) ) {
-               rs->sr_text = "paged results control value is empty (or absent)";
+               rs->sr_text = "paged results control value is empty";
                return LDAP_PROTOCOL_ERROR;
        }
 
@@ -1099,7 +1130,7 @@ done:;
        return rc;
 }
 
-#ifdef SLAP_SORTEDRESULTS
+#ifdef SLAP_CONTROL_X_SORTEDRESULTS
 static int parseSortedResults (
        Operation *op,
        SlapReply *rs,
@@ -1112,8 +1143,13 @@ static int parseSortedResults (
                return LDAP_PROTOCOL_ERROR;
        }
 
+       if ( BER_BVISNULL( &ctrl->ldctl_value ) ) {
+               rs->sr_text = "sorted results control value is absent";
+               return LDAP_PROTOCOL_ERROR;
+       }
+
        if ( BER_BVISEMPTY( &ctrl->ldctl_value ) ) {
-               rs->sr_text = "sorted results control value is empty (or absent)";
+               rs->sr_text = "sorted results control value is empty";
                return LDAP_PROTOCOL_ERROR;
        }
 
@@ -1140,8 +1176,13 @@ static int parseAssert (
                return LDAP_PROTOCOL_ERROR;
        }
 
-       if ( ctrl->ldctl_value.bv_len == 0 ) {
-               rs->sr_text = "assert control value is empty (or absent)";
+       if ( BER_BVISNULL( &ctrl->ldctl_value )) {
+               rs->sr_text = "assert control value is absent";
+               return LDAP_PROTOCOL_ERROR;
+       }
+
+       if ( BER_BVISEMPTY( &ctrl->ldctl_value )) {
+               rs->sr_text = "assert control value is empty";
                return LDAP_PROTOCOL_ERROR;
        }
 
@@ -1198,8 +1239,13 @@ static int parsePreRead (
                return LDAP_PROTOCOL_ERROR;
        }
 
-       if ( ctrl->ldctl_value.bv_len == 0 ) {
-               rs->sr_text = "preread control value is empty (or absent)";
+       if ( BER_BVISNULL( &ctrl->ldctl_value )) {
+               rs->sr_text = "preread control value is absent";
+               return LDAP_PROTOCOL_ERROR;
+       }
+
+       if ( BER_BVISEMPTY( &ctrl->ldctl_value )) {
+               rs->sr_text = "preread control value is empty";
                return LDAP_PROTOCOL_ERROR;
        }
 
@@ -1266,8 +1312,13 @@ static int parsePostRead (
                return LDAP_PROTOCOL_ERROR;
        }
 
-       if ( ctrl->ldctl_value.bv_len == 0 ) {
-               rs->sr_text = "postread control value is empty (or absent)";
+       if ( BER_BVISNULL( &ctrl->ldctl_value )) {
+               rs->sr_text = "postread control value is absent";
+               return LDAP_PROTOCOL_ERROR;
+       }
+
+       if ( BER_BVISEMPTY( &ctrl->ldctl_value )) {
+               rs->sr_text = "postread control value is empty";
                return LDAP_PROTOCOL_ERROR;
        }
 
@@ -1351,8 +1402,13 @@ static int parseValuesReturnFilter (
                return LDAP_PROTOCOL_ERROR;
        }
 
-       if ( ctrl->ldctl_value.bv_len == 0 ) {
-               rs->sr_text = "valuesReturnFilter control value is empty (or absent)";
+       if ( BER_BVISNULL( &ctrl->ldctl_value )) {
+               rs->sr_text = "valuesReturnFilter control value is absent";
+               return LDAP_PROTOCOL_ERROR;
+       }
+
+       if ( BER_BVISEMPTY( &ctrl->ldctl_value )) {
+               rs->sr_text = "valuesReturnFilter control value is empty";
                return LDAP_PROTOCOL_ERROR;
        }
 
@@ -1435,8 +1491,8 @@ static int parsePermissiveModify (
                return LDAP_PROTOCOL_ERROR;
        }
 
-       if ( ctrl->ldctl_value.bv_len ) {
-               rs->sr_text = "permissiveModify control value not empty";
+       if ( BER_BVISNULL( &ctrl->ldctl_value )) {
+               rs->sr_text = "permissiveModify control value not absent";
                return LDAP_PROTOCOL_ERROR;
        }
 
@@ -1457,7 +1513,7 @@ static int parseDomainScope (
                return LDAP_PROTOCOL_ERROR;
        }
 
-       if ( ctrl->ldctl_value.bv_len ) {
+       if ( BER_BVISNULL( &ctrl->ldctl_value )) {
                rs->sr_text = "domainScope control value not empty";
                return LDAP_PROTOCOL_ERROR;
        }
@@ -1480,8 +1536,8 @@ static int parseTreeDelete (
                return LDAP_PROTOCOL_ERROR;
        }
 
-       if ( ctrl->ldctl_value.bv_len ) {
-               rs->sr_text = "treeDelete control value not empty";
+       if ( !BER_BVISNULL( &ctrl->ldctl_value )) {
+               rs->sr_text = "treeDelete control value not absent";
                return LDAP_PROTOCOL_ERROR;
        }
 
@@ -1502,8 +1558,13 @@ static int parseSearchOptions (
        ber_int_t search_flags;
        ber_tag_t tag;
 
-       if ( ctrl->ldctl_value.bv_len == 0 ) {
-               rs->sr_text = "searchOptions control value is empty (or absent)";
+       if ( BER_BVISNULL( &ctrl->ldctl_value )) {
+               rs->sr_text = "searchOptions control value is absent";
+               return LDAP_PROTOCOL_ERROR;
+       }
+
+       if ( BER_BVISEMPTY( &ctrl->ldctl_value )) {
+               rs->sr_text = "searchOptions control value is empty";
                return LDAP_PROTOCOL_ERROR;
        }
 
@@ -1545,3 +1606,299 @@ static int parseSearchOptions (
        return LDAP_SUCCESS;
 }
 
+#ifdef SLAP_CONTROL_X_SESSION_TRACKING
+struct berval session_tracking_formats[] = {
+       BER_BVC( LDAP_CONTROL_X_SESSION_TRACKING_RADIUS_ACCT_SESSION_ID ),
+               BER_BVC( "RADIUS-Acct-Session-Id" ),
+       BER_BVC( LDAP_CONTROL_X_SESSION_TRACKING_RADIUS_ACCT_MULTI_SESSION_ID ),
+               BER_BVC( "RADIUS-Acct-Multi-Session-Id" ),
+       BER_BVC( LDAP_CONTROL_X_SESSION_TRACKING_USERNAME ),
+               BER_BVC( "USERNAME" ),
+
+       BER_BVNULL
+};
+
+static int parseSessionTracking(
+       Operation *op,
+       SlapReply *rs,
+       LDAPControl *ctrl )
+{
+       BerElement              *ber;
+       ber_tag_t               tag;
+       ber_len_t               len;
+       int                     i, rc;
+
+       struct berval           sessionSourceIp = BER_BVNULL,
+                               sessionSourceName = BER_BVNULL,
+                               formatOID = BER_BVNULL,
+                               sessionTrackingIdentifier = BER_BVNULL;
+
+       size_t                  st_len, st_pos;
+
+       if ( ctrl->ldctl_iscritical ) {
+               rs->sr_text = "sessionTracking criticality is TRUE";
+               return LDAP_PROTOCOL_ERROR;
+       }
+
+       if ( BER_BVISNULL( &ctrl->ldctl_value ) ) {
+               rs->sr_text = "sessionTracking control value is absent";
+               return LDAP_PROTOCOL_ERROR;
+       }
+
+       if ( BER_BVISEMPTY( &ctrl->ldctl_value ) ) {
+               rs->sr_text = "sessionTracking control value is empty";
+               return LDAP_PROTOCOL_ERROR;
+       }
+
+       ber = ber_init( &ctrl->ldctl_value );
+       if ( ber == NULL ) {
+               rs->sr_text = "internal error";
+               return LDAP_OTHER;
+       }
+
+       tag = ber_skip_tag( ber, &len );
+       if ( tag != LBER_SEQUENCE ) {
+               tag = LBER_ERROR;
+               goto error;
+       }
+
+       /* sessionSourceIp */
+       tag = ber_peek_tag( ber, &len );
+       if ( tag == LBER_DEFAULT ) {
+               tag = LBER_ERROR;
+               goto error;
+       }
+
+       if ( len == 0 ) {
+               tag = ber_skip_tag( ber, &len );
+
+       } else if ( len > 128 ) {
+               rs->sr_text = "sessionTracking.sessionSourceIp too long";
+               rs->sr_err = LDAP_PROTOCOL_ERROR;
+               goto error;
+
+       } else {
+               tag = ber_scanf( ber, "m", &sessionSourceIp );
+       }
+
+       if ( ldif_is_not_printable( sessionSourceIp.bv_val, sessionSourceIp.bv_len ) ) {
+               BER_BVZERO( &sessionSourceIp );
+       }
+
+       /* sessionSourceName */
+       tag = ber_peek_tag( ber, &len );
+       if ( tag == LBER_DEFAULT ) {
+               tag = LBER_ERROR;
+               goto error;
+       }
+
+       if ( len == 0 ) {
+               tag = ber_skip_tag( ber, &len );
+
+       } else if ( len > 65536 ) {
+               rs->sr_text = "sessionTracking.sessionSourceName too long";
+               rs->sr_err = LDAP_PROTOCOL_ERROR;
+               goto error;
+
+       } else {
+               tag = ber_scanf( ber, "m", &sessionSourceName );
+       }
+
+       if ( ldif_is_not_printable( sessionSourceName.bv_val, sessionSourceName.bv_len ) ) {
+               BER_BVZERO( &sessionSourceName );
+       }
+
+       /* formatOID */
+       tag = ber_peek_tag( ber, &len );
+       if ( tag == LBER_DEFAULT ) {
+               tag = LBER_ERROR;
+               goto error;
+       }
+
+       if ( len == 0 ) {
+               rs->sr_text = "sessionTracking.formatOID empty";
+               rs->sr_err = LDAP_PROTOCOL_ERROR;
+               goto error;
+
+       } else if ( len > 1024 ) {
+               rs->sr_text = "sessionTracking.formatOID too long";
+               rs->sr_err = LDAP_PROTOCOL_ERROR;
+               goto error;
+
+       } else {
+               tag = ber_scanf( ber, "m", &formatOID );
+       }
+
+       rc = numericoidValidate( NULL, &formatOID );
+       if ( rc != LDAP_SUCCESS ) {
+               rs->sr_text = "sessionTracking.formatOID invalid";
+               goto error;
+       }
+
+       for ( i = 0; !BER_BVISNULL( &session_tracking_formats[ i ] ); i += 2 )
+       {
+               if ( bvmatch( &formatOID, &session_tracking_formats[ i ] ) ) {
+                       formatOID = session_tracking_formats[ i + 1 ];
+                       break;
+               }
+       }
+
+       /* sessionTrackingIdentifier */
+       tag = ber_peek_tag( ber, &len );
+       if ( tag == LBER_DEFAULT ) {
+               tag = LBER_ERROR;
+               goto error;
+       }
+
+       if ( len == 0 ) {
+               tag = ber_skip_tag( ber, &len );
+
+       } else {
+               /* note: should not be more than 65536... */
+               tag = ber_scanf( ber, "m", &sessionTrackingIdentifier );
+               if ( ldif_is_not_printable( sessionTrackingIdentifier.bv_val, sessionTrackingIdentifier.bv_len ) ) {
+                       /* we want the OID printed, at least */
+                       BER_BVSTR( &sessionTrackingIdentifier, "" );
+               }
+       }
+
+       /* closure */
+       tag = ber_skip_tag( ber, &len );
+       if ( tag != LBER_DEFAULT || len != 0 ) {
+               tag = LBER_ERROR;
+               goto error;
+       }
+       tag = 0;
+
+       st_len = 0;
+       if ( !BER_BVISNULL( &sessionSourceIp ) ) {
+               st_len += STRLENOF( "IP=" ) + sessionSourceIp.bv_len;
+       }
+       if ( !BER_BVISNULL( &sessionSourceName ) ) {
+               if ( st_len ) st_len++;
+               st_len += STRLENOF( "NAME=" ) + sessionSourceName.bv_len;
+       }
+       if ( !BER_BVISNULL( &sessionTrackingIdentifier ) ) {
+               if ( st_len ) st_len++;
+               st_len += formatOID.bv_len + STRLENOF( "=" )
+                       + sessionTrackingIdentifier.bv_len;
+       }
+
+       if ( st_len == 0 ) {
+               goto error;
+       }
+
+       st_len += STRLENOF( " []" );
+       st_pos = strlen( op->o_log_prefix );
+
+       if ( sizeof( op->o_log_prefix ) - st_pos > st_len ) {
+               char    *ptr = &op->o_log_prefix[ st_pos ];
+
+               ptr = lutil_strcopy( ptr, " [" /*]*/ );
+
+               st_len = 0;
+               if ( !BER_BVISNULL( &sessionSourceIp ) ) {
+                       ptr = lutil_strcopy( ptr, "IP=" );
+                       ptr = lutil_strcopy( ptr, sessionSourceIp.bv_val );
+                       st_len++;
+               }
+
+               if ( !BER_BVISNULL( &sessionSourceName ) ) {
+                       if ( st_len ) *ptr++ = ' ';
+                       ptr = lutil_strcopy( ptr, "NAME=" );
+                       ptr = lutil_strcopy( ptr, sessionSourceName.bv_val );
+                       st_len++;
+               }
+
+               if ( !BER_BVISNULL( &sessionTrackingIdentifier ) ) {
+                       if ( st_len ) *ptr++ = ' ';
+                       ptr = lutil_strcopy( ptr, formatOID.bv_val );
+                       *ptr++ = '=';
+                       ptr = lutil_strcopy( ptr, sessionTrackingIdentifier.bv_val );
+               }
+
+               *ptr++ = /*[*/ ']';
+               *ptr = '\0';
+       }
+
+error:;
+       (void)ber_free( ber, 1 );
+
+       if ( tag == LBER_ERROR ) {
+               rs->sr_text = "sessionTracking control decoding error";
+               return LDAP_PROTOCOL_ERROR;
+       }
+
+
+       return rs->sr_err;
+}
+
+int
+slap_ctrl_session_tracking_add(
+       Operation *op,
+       SlapReply *rs,
+       struct berval *ip,
+       struct berval *name,
+       struct berval *id,
+       LDAPControl *ctrl )
+{
+       BerElementBuffer berbuf;
+       BerElement      *ber = (BerElement *)&berbuf;
+
+       static struct berval    oid = BER_BVC( LDAP_CONTROL_X_SESSION_TRACKING_USERNAME );
+
+       assert( ctrl != NULL );
+
+       ber_init2( ber, NULL, LBER_USE_DER );
+
+       ber_printf( ber, "{OOOO}", ip, name, &oid, id ); 
+
+       if ( ber_flatten2( ber, &ctrl->ldctl_value, 0 ) == -1 ) {
+               rs->sr_err = LDAP_OTHER;
+               goto done;
+       }
+
+       ctrl->ldctl_oid = LDAP_CONTROL_X_SESSION_TRACKING;
+       ctrl->ldctl_iscritical = 0;
+
+       rs->sr_err = LDAP_SUCCESS;
+
+done:;
+       return rs->sr_err;
+}
+
+int
+slap_ctrl_session_tracking_request_add( Operation *op, SlapReply *rs, LDAPControl *ctrl )
+{
+       static struct berval    bv_unknown = BER_BVC( SLAP_STRING_UNKNOWN );
+       struct berval           ip = BER_BVNULL,
+                               name = BER_BVNULL,
+                               id = BER_BVNULL;
+
+       if ( !BER_BVISNULL( &op->o_conn->c_peer_name ) &&
+               memcmp( op->o_conn->c_peer_name.bv_val, "IP=", STRLENOF( "IP=" ) ) == 0 )
+       {
+               char    *ptr;
+
+               ip.bv_val = op->o_conn->c_peer_name.bv_val + STRLENOF( "IP=" );
+               ip.bv_len = op->o_conn->c_peer_name.bv_len - STRLENOF( "IP=" );
+
+               ptr = ber_bvchr( &ip, ':' );
+               if ( ptr ) {
+                       ip.bv_len = ptr - ip.bv_val;
+               }
+       }
+
+       if ( !BER_BVISNULL( &op->o_conn->c_peer_domain ) &&
+               !bvmatch( &op->o_conn->c_peer_domain, &bv_unknown ) )
+       {
+               name = op->o_conn->c_peer_domain;
+       }
+
+       if ( !BER_BVISNULL( &op->o_dn ) && !BER_BVISEMPTY( &op->o_dn ) ) {
+               id = op->o_dn;
+       }
+
+       return slap_ctrl_session_tracking_add( op, rs, &ip, &name, &id, ctrl );
+}
+#endif
index 5e40ce202b86a25109274e63ca3469e6aecbbb4c..e18c0125af70d58cc8d2db369d20fc5437c0924f 100644 (file)
@@ -30,7 +30,7 @@ struct cindexrec {
 };
 
 static Avlnode *cr_index = NULL;
-static LDAP_STAILQ_HEAD(CRList, slap_content_rule) cr_list
+static LDAP_STAILQ_HEAD(CRList, ContentRule) cr_list
        = LDAP_STAILQ_HEAD_INITIALIZER(cr_list);
 
 static int
index 9f86d3d13035d64fe8cf4aec1f7afd065ed3627e..5949e543d732d4b177689720dcaf5778d0fdcae5 100644 (file)
 #endif /* ! epoll && ! /dev/poll */
 
 #ifdef HAVE_TCPD
-# include <tcpd.h>
 int allow_severity = LOG_INFO;
 int deny_severity = LOG_NOTICE;
-
-# define SLAP_STRING_UNKNOWN   STRING_UNKNOWN
-#else /* ! TCP Wrappers */
-# define SLAP_STRING_UNKNOWN   "unknown"
-#endif /* ! TCP Wrappers */
+#endif /* TCP Wrappers */
 
 #ifdef LDAP_PF_LOCAL
 # include <sys/stat.h>
@@ -227,7 +222,8 @@ static struct slap_daemon {
        (int *)(ptr) <= &slap_daemon.sd_index[dtblsize]) ? 0 : 1 )
 
 # define SLAP_EPOLL_EV_PTRFD(ptr)              (SLAP_EPOLL_EV_LISTENER(ptr) ? \
-       ((Listener *)ptr)->sl_sd : (int *)(ptr) - slap_daemon.sd_index)
+       ((Listener *)ptr)->sl_sd : \
+       (ber_socket_t) ((int *)(ptr) - slap_daemon.sd_index))
 
 # define SLAP_SOCK_DEL(s)              do { \
        int fd, rc, index = SLAP_EPOLL_SOCK_IX((s)); \
@@ -1434,7 +1430,7 @@ slapd_daemon_init( const char *urls )
 
 #ifdef HAVE_SYSCONF
        dtblsize = sysconf( _SC_OPEN_MAX );
-#elif HAVE_GETDTABLESIZE
+#elif defined(HAVE_GETDTABLESIZE)
        dtblsize = getdtablesize();
 #else /* ! HAVE_SYSCONF && ! HAVE_GETDTABLESIZE */
        dtblsize = FD_SETSIZE;
@@ -1571,8 +1567,8 @@ slap_listener(
        Sockaddr                from;
 
        ber_socket_t s;
-       socklen_t len = sizeof(from);
-       long id;
+       ber_socklen_t len = sizeof(from);
+       Connection *c;
        slap_ssf_t ssf = 0;
        struct berval authid = BER_BVNULL;
 #ifdef SLAPD_RLOOKUPS
@@ -1583,11 +1579,16 @@ slap_listener(
        char    *peeraddr = NULL;
 #ifdef LDAP_PF_LOCAL
        char peername[MAXPATHLEN + sizeof("PATH=")];
+#ifdef LDAP_PF_LOCAL_SENDMSG
+       char peerbuf[8];
+       struct berval peerbv = BER_BVNULL;
+#endif
 #elif defined(LDAP_PF_INET6)
        char peername[sizeof("IP=[ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff]:65535")];
 #else /* ! LDAP_PF_LOCAL && ! LDAP_PF_INET6 */
        char peername[sizeof("IP=255.255.255.255:65336")];
 #endif /* LDAP_PF_LOCAL */
+       int cflag;
 
        Debug( LDAP_DEBUG_TRACE,
                ">>> slap_listener(%s)\n",
@@ -1700,9 +1701,12 @@ slap_listener(
                "daemon: listen=%ld, new connection on %ld\n",
                (long) sl->sl_sd, (long) s, 0 );
 
+       cflag = 0;
        switch ( from.sa_addr.sa_family ) {
 #  ifdef LDAP_PF_LOCAL
        case AF_LOCAL:
+               cflag |= CONN_IS_IPC;
+
                /* FIXME: apparently accept doesn't fill
                 * the sun_path sun_path member */
                if ( from.sa_un_addr.sun_path[0] == '\0' ) {
@@ -1717,7 +1721,11 @@ slap_listener(
                        uid_t uid;
                        gid_t gid;
 
-                       if( getpeereid( s, &uid, &gid ) == 0 ) {
+#ifdef LDAP_PF_LOCAL_SENDMSG
+                       peerbv.bv_val = peerbuf;
+                       peerbv.bv_len = sizeof( peerbuf );
+#endif
+                       if( LUTIL_GETPEEREID( s, &uid, &gid, &peerbv ) == 0 ) {
                                authid.bv_val = ch_malloc(
                                        STRLENOF( "gidNumber=4294967295+uidNumber=4294967295,"
                                        "cn=peercred,cn=external,cn=auth" ) + 1 );
@@ -1809,20 +1817,18 @@ slap_listener(
 #endif /* HAVE_TCPD */
        }
 
-       id = connection_init(s, sl,
-               dnsname != NULL ? dnsname : SLAP_STRING_UNKNOWN,
-               peername,
 #ifdef HAVE_TLS
-               sl->sl_is_tls ? CONN_IS_TLS : 0,
-#else /* ! HAVE_TLS */
-               0,
-#endif /* ! HAVE_TLS */
-               ssf,
-               authid.bv_val ? &authid : NULL );
+       if ( sl->sl_is_tls ) cflag |= CONN_IS_TLS;
+#endif
+       c = connection_init(s, sl,
+               dnsname != NULL ? dnsname : SLAP_STRING_UNKNOWN,
+               peername, cflag, ssf,
+               authid.bv_val ? &authid : NULL
+               LDAP_PF_LOCAL_SENDMSG_ARG(&peerbv));
 
        if( authid.bv_val ) ch_free(authid.bv_val);
 
-       if( id < 0 ) {
+       if( !c ) {
                Debug( LDAP_DEBUG_ANY,
                        "daemon: connection_init(%ld, %s, %s) failed.\n",
                        (long) s, peername, sl->sl_name.bv_val );
@@ -1832,7 +1838,7 @@ slap_listener(
 
        Statslog( LDAP_DEBUG_STATS,
                "conn=%ld fd=%ld ACCEPT from %s (%s)\n",
-               id, (long) s, peername, sl->sl_name.bv_val,
+               c->c_connid, (long) s, peername, sl->sl_name.bv_val,
                0 );
 
        return 0;
@@ -1986,15 +1992,6 @@ slapd_daemon_task(
        }
 #endif /* HAVE_NT_SERVICE_MANAGER */
 
-#ifdef SLAP_SEM_LOAD_CONTROL
-       /*
-        * initialize count and lazyness of a semaphore
-        */
-       (void) ldap_lazy_sem_init(
-               SLAP_MAX_WORKER_THREADS + 4 /* max workers + margin */,
-               4 /* lazyness */ );
-#endif /* SLAP_SEM_LOAD_CONTROL */
-
        /* initialization complete. Here comes the loop. */
 
        while ( !slapd_shutdown ) {
@@ -2113,8 +2110,14 @@ slapd_daemon_task(
                ldap_pvt_thread_mutex_unlock( &slapd_rq.rq_mutex );
 
                if ( rtask && cat.tv_sec ) {
-                       time_t diff = difftime( cat.tv_sec, now );
-                       if ( diff == 0 ) diff = tdelta;
+                       /* NOTE: diff __should__ always be >= 0,
+                        * AFAI understand; however (ITS#4872),
+                        * time_t might be unsigned in some systems,
+                        * while difftime() returns a double */
+                       double diff = difftime( cat.tv_sec, now );
+                       if ( diff <= 0 ) {
+                               diff = tdelta;
+                       }
                        if ( tvp == NULL || diff < tv.tv_sec ) {
                                tv.tv_sec = diff;
                                tv.tv_usec = 0;
@@ -2510,16 +2513,17 @@ connectionless_init( void )
 
        for ( l = 0; slap_listeners[l] != NULL; l++ ) {
                Listener *lr = slap_listeners[l];
-               long id;
+               Connection *c;
 
                if ( !lr->sl_is_udp ) {
                        continue;
                }
 
-               id = connection_init( lr->sl_sd, lr, "", "",
-                       CONN_IS_UDP, (slap_ssf_t) 0, NULL );
+               c = connection_init( lr->sl_sd, lr, "", "",
+                       CONN_IS_UDP, (slap_ssf_t) 0, NULL
+                       LDAP_PF_LOCAL_SENDMSG_ARG(NULL));
 
-               if ( id < 0 ) {
+               if ( !c ) {
                        Debug( LDAP_DEBUG_TRACE,
                                "connectionless_init: failed on %s (%d)\n",
                                lr->sl_url, lr->sl_sd, 0 );
@@ -2633,7 +2637,7 @@ slap_sig_shutdown( int sig )
         * SIGBREAK is generated when a user logs out.
         */
 
-#if HAVE_NT_SERVICE_MANAGER && SIGBREAK
+#if defined(HAVE_NT_SERVICE_MANAGER) && defined(SIGBREAK)
        if (is_NT_Service && sig == SIGBREAK) {
                /* empty */;
        } else
index e31c51bbdb79b7b263f7cd044a0207a34080c171..eecc72445cc8fa20987e2299753eca61c9faa44e 100644 (file)
@@ -41,8 +41,8 @@ do_delete(
 {
        struct berval dn = BER_BVNULL;
 
-       Debug( LDAP_DEBUG_TRACE, "do_delete\n", 0, 0, 0 );
-
+       Debug( LDAP_DEBUG_TRACE, "%s do_delete\n",
+               op->o_log_prefix, 0, 0 );
        /*
         * Parse the delete request.  It looks like this:
         *
@@ -50,43 +50,47 @@ do_delete(
         */
 
        if ( ber_scanf( op->o_ber, "m", &dn ) == LBER_ERROR ) {
-               Debug( LDAP_DEBUG_ANY, "ber_scanf failed\n", 0, 0, 0 );
+               Debug( LDAP_DEBUG_ANY, "%s do_delete: ber_scanf failed\n",
+                       op->o_log_prefix, 0, 0 );
                send_ldap_discon( op, rs, LDAP_PROTOCOL_ERROR, "decoding error" );
                return SLAPD_DISCONNECT;
        }
 
        if( get_ctrls( op, rs, 1 ) != LDAP_SUCCESS ) {
-               Debug( LDAP_DEBUG_ANY, "do_delete: get_ctrls failed\n", 0, 0, 0 );
+               Debug( LDAP_DEBUG_ANY, "%s do_delete: get_ctrls failed\n",
+                       op->o_log_prefix, 0, 0 );
                goto cleanup;
        } 
 
        rs->sr_err = dnPrettyNormal( NULL, &dn, &op->o_req_dn, &op->o_req_ndn,
                op->o_tmpmemctx );
        if( rs->sr_err != LDAP_SUCCESS ) {
-               Debug( LDAP_DEBUG_ANY,
-                       "do_delete: invalid dn (%s)\n", dn.bv_val, 0, 0 );
+               Debug( LDAP_DEBUG_ANY, "%s do_delete: invalid dn (%s)\n",
+                       op->o_log_prefix, dn.bv_val, 0 );
                send_ldap_error( op, rs, LDAP_INVALID_DN_SYNTAX, "invalid DN" );
                goto cleanup;
        }
 
+       Statslog( LDAP_DEBUG_STATS, "%s DEL dn=\"%s\"\n",
+               op->o_log_prefix, op->o_req_dn.bv_val, 0, 0, 0 );
+
        if( op->o_req_ndn.bv_len == 0 ) {
-               Debug( LDAP_DEBUG_ANY, "do_delete: root dse!\n", 0, 0, 0 );
+               Debug( LDAP_DEBUG_ANY, "%s do_delete: root dse!\n",
+                       op->o_log_prefix, 0, 0 );
                /* protocolError would likely be a more appropriate error */
                send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
                        "cannot delete the root DSE" );
                goto cleanup;
 
        } else if ( bvmatch( &op->o_req_ndn, &frontendDB->be_schemandn ) ) {
-               Debug( LDAP_DEBUG_ANY, "do_delete: subschema subentry!\n", 0, 0, 0 );
+               Debug( LDAP_DEBUG_ANY, "%s do_delete: subschema subentry!\n",
+                       op->o_log_prefix, 0, 0 );
                /* protocolError would likely be a more appropriate error */
                send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
                        "cannot delete the root DSE" );
                goto cleanup;
        }
 
-       Statslog( LDAP_DEBUG_STATS, "%s DEL dn=\"%s\"\n",
-               op->o_log_prefix, op->o_req_dn.bv_val, 0, 0, 0 );
-
        op->o_bd = frontendDB;
        rs->sr_err = frontendDB->be_delete( op, rs );
 
@@ -107,17 +111,14 @@ int
 fe_op_delete( Operation *op, SlapReply *rs )
 {
        struct berval   pdn = BER_BVNULL;
-       int             manageDSAit;
        BackendDB       *op_be, *bd = op->o_bd;
        
-       manageDSAit = get_manageDSAit( op );
-
        /*
         * We could be serving multiple database backends.  Select the
         * appropriate one, or send a referral to our "referral server"
         * if we don't hold it.
         */
-       op->o_bd = select_backend( &op->o_req_ndn, manageDSAit, 1 );
+       op->o_bd = select_backend( &op->o_req_ndn, 1 );
        if ( op->o_bd == NULL ) {
                op->o_bd = bd;
                rs->sr_ref = referral_rewrite( default_referral,
@@ -139,7 +140,7 @@ fe_op_delete( Operation *op, SlapReply *rs )
        /* If we've got a glued backend, check the real backend */
        op_be = op->o_bd;
        if ( SLAP_GLUE_INSTANCE( op->o_bd )) {
-               op->o_bd = select_backend( &op->o_req_ndn, manageDSAit, 0 );
+               op->o_bd = select_backend( &op->o_req_ndn, 0 );
        }
 
        /* check restrictions */
@@ -168,15 +169,8 @@ fe_op_delete( Operation *op, SlapReply *rs )
                        struct berval   org_dn = BER_BVNULL;
                        struct berval   org_ndn = BER_BVNULL;
                        int             org_managedsait;
-                       slap_callback   cb = { NULL, slap_replog_cb, NULL, NULL };
 
                        op->o_bd = op_be;
-
-                       if ( !op->o_bd->be_update_ndn.bv_len || !repl_user ) {
-                               cb.sc_next = op->o_callback;
-                               op->o_callback = &cb;
-                       }
-
                        op->o_bd->be_delete( op, rs );
 
                        org_req_dn = op->o_req_dn;
index 509adb76e3ac3272a8c6bfda8706b6bdcda4a01f..b71dfc95f618cabf591dce774030e5e0938392bb 100644 (file)
@@ -228,81 +228,62 @@ rdnValidate(
  * Note: the sorting can be slightly improved by sorting first
  * by attribute type length, then by alphabetical order.
  *
- * uses a linear search; should be fine since the number of AVAs in
+ * uses an insertion sort; should be fine since the number of AVAs in
  * a RDN should be limited.
  */
-static void
-AVA_Sort( LDAPRDN rdn, int iAVA )
+static int
+AVA_Sort( LDAPRDN rdn, int nAVAs )
 {
+       LDAPAVA *ava_i;
        int             i;
-       LDAPAVA         *ava_in = rdn[ iAVA ];
 
        assert( rdn != NULL );
-       assert( ava_in != NULL );
-       
-       for ( i = 0; i < iAVA; i++ ) {
-               LDAPAVA         *ava = rdn[ i ];
-               int             a, j;
 
-               assert( ava != NULL );
+       for ( i = 1; i < nAVAs; i++ ) {
+               LDAPAVA *ava_j;
+               int j;
 
-               a = strcmp( ava_in->la_attr.bv_val, ava->la_attr.bv_val );
+               ava_i = rdn[ i ];
+               for ( j = i-1; j >=0; j-- ) {
+                       int a;
 
-               if ( a > 0 ) {
-                       break;
-               }
+                       ava_j = rdn[ j ];
+                       a = strcmp( ava_i->la_attr.bv_val, ava_j->la_attr.bv_val );
 
-               while ( a == 0 ) {
-                       int             v, d;
+                       if ( a == 0 ) {
+                               int             d;
 
-                       d = ava_in->la_value.bv_len - ava->la_value.bv_len;
+                               d = ava_i->la_value.bv_len - ava_j->la_value.bv_len;
 
-                       v = memcmp( ava_in->la_value.bv_val, 
-                                       ava->la_value.bv_val,
-                                       d <= 0 ? ava_in->la_value.bv_len 
-                                               : ava->la_value.bv_len );
+                               a = memcmp( ava_i->la_value.bv_val, 
+                                               ava_j->la_value.bv_val,
+                                               d <= 0 ? ava_i->la_value.bv_len 
+                                                       : ava_j->la_value.bv_len );
 
-                       if ( v == 0 && d != 0 ) {
-                               v = d;
+                               if ( a == 0 ) {
+                                       a = d;
+                               }
                        }
+                       /* Duplicates are not allowed */
+                       if ( a == 0 )
+                               return LDAP_INVALID_DN_SYNTAX;
 
-                       if ( v <= 0 ) {
-                               /* 
-                                * got it!
-                                */
+                       if ( a > 0 )
                                break;
-                       }
 
-                       if ( ++i == iAVA ) {
-                               /*
-                                * already sorted
-                                */
-                               return;
-                       }
-
-                       ava = rdn[ i ];
-                       a = strcmp( ava_in->la_attr.bv_val, 
-                                       ava->la_attr.bv_val );
-               }
-
-               /*
-                * move ahead
-                */
-               for ( j = iAVA; j > i; j-- ) {
-                       rdn[ j ] = rdn[ j - 1 ];
+                       rdn[ j+1 ] = rdn[ j ];
                }
-               rdn[ i ] = ava_in;
-
-               return;
+               rdn[ j+1 ] = ava_i;
        }
+       return LDAP_SUCCESS;
 }
 
 static int
 LDAPRDN_rewrite( LDAPRDN rdn, unsigned flags, void *ctx )
 {
 
-       int rc;
-       int             iAVA;
+       int rc, iAVA, do_sort = 0;
+
        for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) {
                LDAPAVA                 *ava = rdn[ iAVA ];
                AttributeDescription    *ad;
@@ -311,7 +292,6 @@ LDAPRDN_rewrite( LDAPRDN rdn, unsigned flags, void *ctx )
                slap_syntax_transform_func *transf = NULL;
                MatchingRule *mr = NULL;
                struct berval           bv = BER_BVNULL;
-               int                     do_sort = 0;
 
                assert( ava != NULL );
 
@@ -415,10 +395,14 @@ LDAPRDN_rewrite( LDAPRDN rdn, unsigned flags, void *ctx )
                        ava->la_value = bv;
                        ava->la_flags |= LDAP_AVA_FREE_VALUE;
                }
+       }
+       rc = LDAP_SUCCESS;
 
-               if( do_sort ) AVA_Sort( rdn, iAVA );
+       if ( do_sort ) {
+               rc = AVA_Sort( rdn, iAVA );
        }
-       return LDAP_SUCCESS;
+
+       return rc;
 }
 
 /*
@@ -1257,7 +1241,6 @@ int register_certificate_map_function(SLAP_CERT_MAP_FN *fn)
        return -1;
 }
 
-#ifdef HAVE_TLS
 /*
  * Convert an X.509 DN into a normalized LDAP DN
  */
@@ -1274,6 +1257,7 @@ dnX509normalize( void *x509_name, struct berval *out )
        return rc;
 }
 
+#ifdef HAVE_TLS
 /*
  * Get the TLS session's peer's DN into a normalized LDAP DN
  */
index dda4e185023f86f3a4f92125f5d595eba0397611..660bcb676b7ba680b3b2aa6f7cb28b2a1e63f914 100644 (file)
@@ -100,6 +100,8 @@ str2entry( char *s )
        return str2entry2( s, 1 );
 }
 
+#define bvcasematch(bv1, bv2)  (ber_bvstrcasecmp(bv1, bv2) == 0)
+
 Entry *
 str2entry2( char *s, int checkvals )
 {
@@ -166,6 +168,11 @@ str2entry2( char *s, int checkvals )
                        break;
                }
                i++;
+               if (i >= lines) {
+                       Debug( LDAP_DEBUG_TRACE,
+                               "<= str2entry ran past end of entry\n", 0, 0, 0 );
+                       goto fail;
+               }
 
                rc = ldif_parse_line2( s, type+i, vals+i, &freev );
                freeval[i] = freev;
@@ -175,9 +182,7 @@ str2entry2( char *s, int checkvals )
                        continue;
                }
 
-               if ( type[i].bv_len == dn_bv.bv_len &&
-                       strcasecmp( type[i].bv_val, dn_bv.bv_val ) == 0 ) {
-
+               if ( bvcasematch( &type[i], &dn_bv ) ) {
                        if ( e->e_dn != NULL ) {
                                Debug( LDAP_DEBUG_ANY, "str2entry: "
                                        "entry %ld has multiple DNs \"%s\" and \"%s\"\n",
@@ -207,8 +212,6 @@ str2entry2( char *s, int checkvals )
                goto fail;
        }
 
-#define bvcasematch(bv1, bv2)  ( ((bv1)->bv_len == (bv2)->bv_len) && (strncasecmp((bv1)->bv_val, (bv2)->bv_val, (bv1)->bv_len) == 0) )
-
        /* Make sure all attributes with multiple values are contiguous */
        if ( checkvals ) {
                int j, k;
@@ -260,6 +263,16 @@ str2entry2( char *s, int checkvals )
                                        goto fail;
                                }
                        }
+
+                       /* require ';binary' when appropriate (ITS#5071) */
+                       if ( slap_syntax_is_binary( ad->ad_type->sat_syntax ) && !slap_ad_is_binary( ad ) ) {
+                               Debug( LDAP_DEBUG_ANY,
+                                       "str2entry: attributeType %s #%d: "
+                                       "needs ';binary' transfer as per syntax %s\n", 
+                                       ad->ad_cname.bv_val, 0,
+                                       ad->ad_type->sat_syntax->ssyn_oid );
+                               goto fail;
+                       }
                }
 
                if (( ad_prev && ad != ad_prev ) || ( i == lines )) {
@@ -297,6 +310,14 @@ str2entry2( char *s, int checkvals )
                        if ( i == lines ) break;
                }
 
+               if ( BER_BVISNULL( &vals[i] ) ) {
+                       Debug( LDAP_DEBUG_ANY,
+                               "str2entry: attributeType %s #%d: "
+                               "no value\n", 
+                               ad->ad_cname.bv_val, attr_cnt, 0 );
+                       goto fail;
+               }
+
                if( slapMode & SLAP_TOOL_MODE ) {
                        struct berval pval;
                        slap_syntax_validate_func *validate =
index 38bb96c14734df866407e4b8faafe8b8fa9a6af4..2338b215f52b653a6b38b6f15bcefa471da54744 100644 (file)
@@ -123,19 +123,20 @@ do_extended(
        ber_tag_t tag;
        ber_len_t len;
 
-       Debug( LDAP_DEBUG_TRACE, "do_extended\n", 0, 0, 0 );
+       Debug( LDAP_DEBUG_TRACE, "%s do_extended\n",
+               op->o_log_prefix, 0, 0 );
 
        if( op->o_protocol < LDAP_VERSION3 ) {
-               Debug( LDAP_DEBUG_ANY,
-                       "do_extended: protocol version (%d) too low\n",
-                       op->o_protocol, 0 ,0 );
+               Debug( LDAP_DEBUG_ANY, "%s do_extended: protocol version (%d) too low\n",
+                       op->o_log_prefix, op->o_protocol, 0 );
                send_ldap_discon( op, rs, LDAP_PROTOCOL_ERROR, "requires LDAPv3" );
                rs->sr_err = SLAPD_DISCONNECT;
                goto done;
        }
 
        if ( ber_scanf( op->o_ber, "{m" /*}*/, &op->ore_reqoid ) == LBER_ERROR ) {
-               Debug( LDAP_DEBUG_ANY, "do_extended: ber_scanf failed\n", 0, 0 ,0 );
+               Debug( LDAP_DEBUG_ANY, "%s do_extended: ber_scanf failed\n",
+                       op->o_log_prefix, 0, 0 );
                send_ldap_discon( op, rs, LDAP_PROTOCOL_ERROR, "decoding error" );
                rs->sr_err = SLAPD_DISCONNECT;
                goto done;
@@ -145,7 +146,8 @@ do_extended(
        
        if( ber_peek_tag( op->o_ber, &len ) == LDAP_TAG_EXOP_REQ_VALUE ) {
                if( ber_scanf( op->o_ber, "m", &reqdata ) == LBER_ERROR ) {
-                       Debug( LDAP_DEBUG_ANY, "do_extended: ber_scanf failed\n", 0, 0 ,0 );
+                       Debug( LDAP_DEBUG_ANY, "%s do_extended: ber_scanf failed\n",
+                               op->o_log_prefix, 0, 0 );
                        send_ldap_discon( op, rs, LDAP_PROTOCOL_ERROR, "decoding error" );
                        rs->sr_err = SLAPD_DISCONNECT;
                        goto done;
@@ -153,14 +155,16 @@ do_extended(
        }
 
        if( get_ctrls( op, rs, 1 ) != LDAP_SUCCESS ) {
-               Debug( LDAP_DEBUG_ANY, "do_extended: get_ctrls failed\n", 0, 0 ,0 );
+               Debug( LDAP_DEBUG_ANY, "%s do_extended: get_ctrls failed\n",
+                       op->o_log_prefix, 0, 0 );
                return rs->sr_err;
        } 
 
+       Statslog( LDAP_DEBUG_STATS, "%s EXT oid=%s\n",
+           op->o_log_prefix, op->ore_reqoid.bv_val, 0, 0, 0 );
+
        /* check for controls inappropriate for all extended operations */
        if( get_manageDSAit( op ) == SLAP_CONTROL_CRITICAL ) {
-               Statslog( LDAP_DEBUG_STATS, "%s EXT oid=%s\n",
-                   op->o_log_prefix, op->ore_reqoid.bv_val, 0, 0, 0 );
                send_ldap_error( op, rs,
                        LDAP_UNAVAILABLE_CRITICAL_EXTENSION,
                        "manageDSAit control inappropriate" );
@@ -203,10 +207,8 @@ fe_extended( Operation *op, SlapReply *rs )
 
        ext = find_extop(supp_ext_list, &op->ore_reqoid );
        if ( ext == NULL ) {
-               Statslog( LDAP_DEBUG_STATS, "%s EXT oid=%s\n",
-                   op->o_log_prefix, op->ore_reqoid.bv_val, 0, 0, 0 );
-               Debug( LDAP_DEBUG_ANY, "do_extended: unsupported operation \"%s\"\n",
-                       op->ore_reqoid.bv_val, 0 ,0 );
+               Debug( LDAP_DEBUG_ANY, "%s do_extended: unsupported operation \"%s\"\n",
+                       op->o_log_prefix, op->ore_reqoid.bv_val, 0 );
                send_ldap_error( op, rs, LDAP_PROTOCOL_ERROR,
                        "unsupported extended operation" );
                goto done;
index f7b6821482337d12bce556412bbb8b67c2cdd592..d3ceb0b8a8c78d43e9db15c133e6f509daf2d4d4 100644 (file)
@@ -618,16 +618,16 @@ simple:
                        len = fstr->bv_len;
 
                        filter_escape_value_x( &f->f_sub_initial, &tmp, op->o_tmpmemctx );
-                       tmplen = tmp.bv_len ? tmp.bv_len : STRLENOF( "(null)" );
+                       tmplen = tmp.bv_len;
 
                        fstr->bv_len += tmplen;
                        fstr->bv_val = op->o_tmprealloc( fstr->bv_val,
                                fstr->bv_len + 1, op->o_tmpmemctx );
 
-                       snprintf( &fstr->bv_val[len-2],
+                       snprintf( &fstr->bv_val[len - 2],
                                tmplen + STRLENOF( /*(*/ "*)" ) + 1,
                                /* "(attr=" */ "%s*)",
-                               tmp.bv_len ? tmp.bv_val : "(null)");
+                               tmp.bv_len ? tmp.bv_val : "");
 
                        ber_memfree_x( tmp.bv_val, op->o_tmpmemctx );
                }
@@ -639,16 +639,16 @@ simple:
                                len = fstr->bv_len;
                                filter_escape_value_x( &f->f_sub_any[i],
                                        &tmp, op->o_tmpmemctx );
-                               tmplen = tmp.bv_len ? tmp.bv_len : STRLENOF( "(null)" );
+                               tmplen = tmp.bv_len;
 
                                fstr->bv_len += tmplen + STRLENOF( /*(*/ ")" );
                                fstr->bv_val = op->o_tmprealloc( fstr->bv_val,
                                        fstr->bv_len + 1, op->o_tmpmemctx );
 
-                               snprintf( &fstr->bv_val[len-1],
+                               snprintf( &fstr->bv_val[len - 1],
                                        tmplen + STRLENOF( /*(*/ "*)" ) + 1,
                                        /* "(attr=[init]*[any*]" */ "%s*)",
-                                       tmp.bv_len ? tmp.bv_val : "(null)");
+                                       tmp.bv_len ? tmp.bv_val : "");
                                ber_memfree_x( tmp.bv_val, op->o_tmpmemctx );
                        }
                }
@@ -659,16 +659,16 @@ simple:
                        len = fstr->bv_len;
 
                        filter_escape_value_x( &f->f_sub_final, &tmp, op->o_tmpmemctx );
-                       tmplen = tmp.bv_len ? tmp.bv_len : STRLENOF( "(null)" );
+                       tmplen = tmp.bv_len;
 
                        fstr->bv_len += tmplen;
                        fstr->bv_val = op->o_tmprealloc( fstr->bv_val,
                                fstr->bv_len + 1, op->o_tmpmemctx );
 
-                       snprintf( &fstr->bv_val[len-1],
+                       snprintf( &fstr->bv_val[len - 1],
                                tmplen + STRLENOF( /*(*/ ")" ) + 1,
                                /* "(attr=[init*][any*]" */ "%s)",
-                               tmp.bv_len ? tmp.bv_val : "(null)");
+                               tmp.bv_len ? tmp.bv_val : "");
 
                        ber_memfree_x( tmp.bv_val, op->o_tmpmemctx );
                }
index 336476a8fd39d9a8f624b706e95a91a1607aee71..d1fb4856e30cf5bb8162656713bebaa912e3a9dc 100644 (file)
@@ -583,7 +583,7 @@ test_ava_filter(
 
        if ( ava->aa_desc == slap_schema.si_ad_entryDN ) {
                MatchingRule *mr;
-               int rc, match;
+               int match;
                const char *text;
 
                if( type != LDAP_FILTER_EQUALITY &&
@@ -729,7 +729,7 @@ test_ava_filter(
                        } else 
 #endif
                        {
-                               ret = value_match( &match, a->a_desc, mr, use,
+                               ret = ordered_value_match( &match, a->a_desc, mr, use,
                                        bv, &ava->aa_value, &text );
                        }
 
index 3cff69e3e63765e010dc5d6537c2b74684a983b8..5666a49b992bbeb4cf802fc0ff2742ddee95fd16 100644 (file)
@@ -69,8 +69,6 @@ ldap_pvt_thread_mutex_t       gmtime_mutex;
 
 slap_counters_t                        slap_counters;
 
-ldap_pvt_thread_mutex_t        replog_mutex;
-
 static const char* slap_name = NULL;
 int slapMode = SLAP_UNDEFINED_MODE;
 
@@ -94,6 +92,8 @@ slap_init( int mode, const char *name )
 
        slapMode = mode;
 
+       slap_op_init();
+
 #ifdef SLAPD_MODULES
        if ( module_init() != 0 ) {
                slap_debug |= LDAP_DEBUG_NONE;
@@ -135,7 +135,6 @@ slap_init( int mode, const char *name )
 
                ldap_pvt_thread_pool_init( &connection_pool,
                                connection_pool_max, 0);
-               ldap_pvt_thread_mutex_init( &replog_mutex );
 
                ldap_pvt_thread_mutex_init( &slap_counters.sc_sent_mutex );
                ldap_pvt_thread_mutex_init( &slap_counters.sc_ops_mutex );
@@ -310,8 +309,10 @@ int slap_destroy(void)
 
        }
 
+       slap_op_destroy();
+
        ldap_pvt_thread_destroy();
 
-       /* should destory the above mutex */
+       /* should destroy the above mutex */
        return rc;
 }
index 16abf885b0e599ac1a2618f940539a0a44f719dd..99905ac67718307073724ce3ad902d686fc1ad65 100644 (file)
@@ -120,20 +120,37 @@ slap_sync_cookie_free(
 }
 
 int
-slap_parse_csn_sid( struct berval *csn )
+slap_parse_csn_sid( struct berval *csnp )
 {
        char *p, *q;
+       struct berval csn = *csnp;
        int i;
 
-       p = memchr( csn->bv_val, '#', csn->bv_len );
-       if ( p )
-               p = strchr( p+1, '#' );
+       p = ber_bvchr( &csn, '#' );
        if ( !p )
                return -1;
        p++;
-       i = strtoul( p, &q, 10 );
-       if ( p == q || i > SLAP_SYNC_SID_MAX )
+       csn.bv_len -= p - csn.bv_val;
+       csn.bv_val = p;
+
+       p = ber_bvchr( &csn, '#' );
+       if ( !p )
+               return -1;
+       p++;
+       csn.bv_len -= p - csn.bv_val;
+       csn.bv_val = p;
+
+       q = ber_bvchr( &csn, '#' );
+       if ( !q )
+               return -1;
+
+       csn.bv_len = q - p;
+
+       i = (int)strtoul( p, &q, 16 );
+       if ( p == q || q != p + csn.bv_len || i > SLAP_SYNC_SID_MAX ) {
                i = -1;
+       }
+
        return i;
 }
 
@@ -141,7 +158,6 @@ int *
 slap_parse_csn_sids( BerVarray csns, int numcsns, void *memctx )
 {
        int i, *ret;
-       char *p, *q;
 
        ret = slap_sl_malloc( numcsns * sizeof(int), memctx );
        for ( i=0; i<numcsns; i++ ) {
@@ -158,7 +174,6 @@ slap_parse_sync_cookie(
 {
        char *csn_ptr;
        char *csn_str;
-       int csn_str_len;
        char *rid_ptr;
        char *cval;
        char *next, *end;
@@ -182,7 +197,10 @@ slap_parse_sync_cookie(
                if ( !strncmp( next, "rid=", STRLENOF("rid=") )) {
                        rid_ptr = next;
                        cookie->rid = strtoul( &rid_ptr[ STRLENOF( "rid=" ) ], &next, 10 );
-                       if ( next == rid_ptr || next > end || *next != ',' ) {
+                       if ( next == rid_ptr ||
+                               next > end ||
+                               ( *next && *next != ',' ) )
+                       {
                                return -1;
                        }
                        if ( *next == ',' ) {
@@ -196,7 +214,10 @@ slap_parse_sync_cookie(
                if ( !strncmp( next, "sid=", STRLENOF("sid=") )) {
                        rid_ptr = next;
                        cookie->sid = strtoul( &rid_ptr[ STRLENOF( "sid=" ) ], &next, 16 );
-                       if ( next == rid_ptr || next > end || *next != ',' ) {
+                       if ( next == rid_ptr ||
+                               next > end ||
+                               ( *next && *next != ',' ) )
+                       {
                                return -1;
                        }
                        if ( *next == ',' ) {
index 70ba3029a3fc0555a8f90a9be545f90833ae32cd..81f4027de36dceb52a2510dfacb0c4da98b6b0ed 100644 (file)
@@ -502,7 +502,6 @@ limits_parse(
                        ad.bv_val = strchr( oc.bv_val, '/' );
                        if ( ad.bv_val != NULL ) {
                                const char      *text = NULL;
-                               int             rc;
 
                                oc.bv_len = ad.bv_val - oc.bv_val;
 
@@ -533,7 +532,6 @@ no_oc:;
 
                if ( group_ad == NULL ) {
                        const char      *text = NULL;
-                       int             rc;
                        
                        rc = slap_str2ad( SLAPD_GROUP_ATTR, &group_ad, &text );
 
index b18b8e0e07fd1c11cfff66556160bab076c48ea5..8c890e506de3f189891d61ee6c0b00c03c76842e 100644 (file)
@@ -305,7 +305,7 @@ usage( char *name )
                "\t-g group\tGroup (id or name) to run as\n"
 #endif
                "\t-h URLs\t\tList of URLs to serve\n"
-#ifdef LOG_LOCAL4
+#ifdef SLAP_DEFAULT_SYSLOG_USER
                "\t-l facility\tSyslog facility (default: LOCAL4)\n"
 #endif
                "\t-n serverName\tService name\n"
@@ -348,7 +348,7 @@ int main( int argc, char **argv )
 #if defined(HAVE_CHROOT)
        char *sandbox = NULL;
 #endif
-#ifdef LOG_LOCAL4
+#ifdef SLAP_DEFAULT_SYSLOG_USER
        int syslogUser = SLAP_DEFAULT_SYSLOG_USER;
 #endif
        
@@ -396,7 +396,7 @@ int main( int argc, char **argv )
 
 #ifdef HAVE_NT_SERVICE_MANAGER
        {
-               int *i;
+               int *ip;
                char *newConfigFile;
                char *newConfigDir;
                char *newUrls;
@@ -408,9 +408,9 @@ int main( int argc, char **argv )
                            regService = serverName;
                }
 
-               i = (int*)lutil_getRegParam( regService, "DebugLevel" );
-               if ( i != NULL ) {
-                       slap_debug = *i;
+               ip = (int*)lutil_getRegParam( regService, "DebugLevel" );
+               if ( ip != NULL ) {
+                       slap_debug = *ip;
                        Debug( LDAP_DEBUG_ANY,
                                "new debug level from registry is: %d\n", slap_debug, 0, 0 );
                }
@@ -441,7 +441,7 @@ int main( int argc, char **argv )
 
        while ( (i = getopt( argc, argv,
                             "c:d:f:F:h:n:o:s:tT:V"
-#if LDAP_PF_INET6
+#ifdef LDAP_PF_INET6
                                "46"
 #endif
 #ifdef HAVE_CHROOT
@@ -532,7 +532,6 @@ int main( int argc, char **argv )
                case 'o': {
                        char            *val = strchr( optarg, '=' );
                        struct berval   opt;
-                       int             i;
 
                        opt.bv_val = optarg;
                        
@@ -676,6 +675,7 @@ unhandled_option:;
                if ( version > 1 ) goto stop;
        }
 
+#if defined(LDAP_DEBUG) && defined(LDAP_SYSLOG)
        {
                char *logName;
 #ifdef HAVE_EBCDIC
@@ -687,13 +687,14 @@ unhandled_option:;
 
 #ifdef LOG_LOCAL4
                openlog( logName, OPENLOG_OPTIONS, syslogUser );
-#elif LOG_DEBUG
+#elif defined LOG_DEBUG
                openlog( logName, OPENLOG_OPTIONS );
 #endif
 #ifdef HAVE_EBCDIC
                free( logName );
 #endif
        }
+#endif /* LDAP_DEBUG && LDAP_SYSLOG */
 
        Debug( LDAP_DEBUG_ANY, "%s", Versionstr, 0, 0 );
 
@@ -728,7 +729,6 @@ unhandled_option:;
 
        extops_init();
        lutil_passwd_init();
-       slap_op_init();
 
 #ifdef HAVE_TLS
        rc = ldap_create( &slap_tls_ld );
@@ -959,8 +959,6 @@ destroy:
        module_kill();
 #endif
 
-       slap_op_destroy();
-
        extops_kill();
 
        supported_feature_destroy();
@@ -992,7 +990,7 @@ stop:
 
 #ifdef HAVE_TLS
        if ( slap_tls_ld ) {
-               SSL_CTX_free( slap_tls_ctx );
+               ldap_pvt_tls_ctx_free( slap_tls_ctx );
                ldap_unbind_ext( slap_tls_ld, NULL, NULL );
        }
        ldap_pvt_tls_destroy();
index 0cd1d039ab85b9bafd28040c07d578db28de7483..4a0a87eb9099115c101636f063e5c51fb138cd58 100644 (file)
@@ -41,14 +41,14 @@ do_modify(
     SlapReply  *rs )
 {
        struct berval dn = BER_BVNULL;
-       char            *last;
-       ber_tag_t       tag;
-       ber_len_t       len;
        char            textbuf[ SLAP_TEXT_BUFLEN ];
        size_t          textlen = sizeof( textbuf );
+#ifdef LDAP_DEBUG
+       Modifications   *tmp;
+#endif
 
-       Debug( LDAP_DEBUG_TRACE, "do_modify\n", 0, 0, 0 );
-
+       Debug( LDAP_DEBUG_TRACE, "%s do_modify\n",
+               op->o_log_prefix, 0, 0 );
        /*
         * Parse the modify request.  It looks like this:
         *
@@ -69,89 +69,42 @@ do_modify(
         */
 
        if ( ber_scanf( op->o_ber, "{m" /*}*/, &dn ) == LBER_ERROR ) {
-               Debug( LDAP_DEBUG_ANY, "do_modify: ber_scanf failed\n", 0, 0, 0 );
-
+               Debug( LDAP_DEBUG_ANY, "%s do_modify: ber_scanf failed\n",
+                       op->o_log_prefix, 0, 0 );
                send_ldap_discon( op, rs, LDAP_PROTOCOL_ERROR, "decoding error" );
                return SLAPD_DISCONNECT;
        }
 
-       Debug( LDAP_DEBUG_ARGS, "do_modify: dn (%s)\n", dn.bv_val, 0, 0 );
+       Debug( LDAP_DEBUG_ARGS, "%s do_modify: dn (%s)\n",
+               op->o_log_prefix, dn.bv_val, 0 );
 
        rs->sr_err = slap_parse_modlist( op, rs, op->o_ber, &op->oq_modify );
        if ( rs->sr_err != LDAP_SUCCESS ) {
-               Debug( LDAP_DEBUG_ANY, "do_modify: slap_parse_modlist failed err=%d msg=%s\n",
-                       rs->sr_err, rs->sr_text, 0 );
+               Debug( LDAP_DEBUG_ANY, "%s do_modify: slap_parse_modlist failed err=%d msg=%s\n",
+                       op->o_log_prefix, rs->sr_err, rs->sr_text );
                goto cleanup;
        }
 
        if( get_ctrls( op, rs, 1 ) != LDAP_SUCCESS ) {
-               Debug( LDAP_DEBUG_ANY, "do_modify: get_ctrls failed\n", 0, 0, 0 );
+               Debug( LDAP_DEBUG_ANY, "%s do_modify: get_ctrls failed\n",
+                       op->o_log_prefix, 0, 0 );
                goto cleanup;
        }
 
        rs->sr_err = dnPrettyNormal( NULL, &dn, &op->o_req_dn, &op->o_req_ndn,
                op->o_tmpmemctx );
        if( rs->sr_err != LDAP_SUCCESS ) {
-               Debug( LDAP_DEBUG_ANY,
-                       "do_modify: invalid dn (%s)\n", dn.bv_val, 0, 0 );
+               Debug( LDAP_DEBUG_ANY, "%s do_modify: invalid dn (%s)\n",
+                       op->o_log_prefix, dn.bv_val, 0 );
                send_ldap_error( op, rs, LDAP_INVALID_DN_SYNTAX, "invalid DN" );
                goto cleanup;
        }
 
-       rs->sr_err = slap_mods_check( op, op->orm_modlist,
-               &rs->sr_text, textbuf, textlen, NULL );
+       op->orm_no_opattrs = 0;
 
-       if ( rs->sr_err != LDAP_SUCCESS ) {
-               send_ldap_result( op, rs );
-               goto cleanup;
-       }
-
-       op->o_bd = frontendDB;
-       rs->sr_err = frontendDB->be_modify( op, rs );
-
-#ifdef LDAP_X_TXN
-       if( rs->sr_err == LDAP_X_TXN_SPECIFY_OKAY ) {
-               /* skip cleanup */
-               return rs->sr_err;
-       }
-#endif
-
-cleanup:
-       op->o_tmpfree( op->o_req_dn.bv_val, op->o_tmpmemctx );
-       op->o_tmpfree( op->o_req_ndn.bv_val, op->o_tmpmemctx );
-       if ( op->orm_modlist != NULL ) slap_mods_free( op->orm_modlist, 1 );
-
-       return rs->sr_err;
-}
-
-int
-fe_op_modify( Operation *op, SlapReply *rs )
-{
 #ifdef LDAP_DEBUG
-       Modifications   *tmp;
-#endif
-       int             manageDSAit;
-       BackendDB       *op_be, *bd = op->o_bd;
-       char            textbuf[ SLAP_TEXT_BUFLEN ];
-       size_t          textlen = sizeof( textbuf );
-       
-       if ( BER_BVISEMPTY( &op->o_req_ndn ) ) {
-               Debug( LDAP_DEBUG_ANY, "do_modify: root dse!\n", 0, 0, 0 );
-
-               send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
-                       "modify upon the root DSE not supported" );
-               goto cleanup;
-
-       } else if ( bvmatch( &op->o_req_ndn, &frontendDB->be_schemandn ) ) {
-               Debug( LDAP_DEBUG_ANY, "do_modify: subschema subentry!\n", 0, 0, 0 );
-
-               send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
-                       "modification of subschema subentry not supported" );
-               goto cleanup;
-       }
-
-#ifdef LDAP_DEBUG
-       Debug( LDAP_DEBUG_ARGS, "modifications:\n", 0, 0, 0 );
+       Debug( LDAP_DEBUG_ARGS, "%s modifications:\n",
+                       op->o_log_prefix, 0, 0 );
 
        for ( tmp = op->orm_modlist; tmp != NULL; tmp = tmp->sml_next ) {
                Debug( LDAP_DEBUG_ARGS, "\t%s: %s\n",
@@ -210,14 +163,60 @@ fe_op_modify( Operation *op, SlapReply *rs )
        }
 #endif /* LDAP_DEBUG */
 
-       manageDSAit = get_manageDSAit( op );
+       rs->sr_err = slap_mods_check( op, op->orm_modlist,
+               &rs->sr_text, textbuf, textlen, NULL );
+
+       if ( rs->sr_err != LDAP_SUCCESS ) {
+               send_ldap_result( op, rs );
+               goto cleanup;
+       }
+
+       op->o_bd = frontendDB;
+       rs->sr_err = frontendDB->be_modify( op, rs );
+
+#ifdef LDAP_X_TXN
+       if( rs->sr_err == LDAP_X_TXN_SPECIFY_OKAY ) {
+               /* skip cleanup */
+               return rs->sr_err;
+       }
+#endif
+
+cleanup:
+       op->o_tmpfree( op->o_req_dn.bv_val, op->o_tmpmemctx );
+       op->o_tmpfree( op->o_req_ndn.bv_val, op->o_tmpmemctx );
+       if ( op->orm_modlist != NULL ) slap_mods_free( op->orm_modlist, 1 );
+
+       return rs->sr_err;
+}
+
+int
+fe_op_modify( Operation *op, SlapReply *rs )
+{
+       BackendDB       *op_be, *bd = op->o_bd;
+       char            textbuf[ SLAP_TEXT_BUFLEN ];
+       size_t          textlen = sizeof( textbuf );
+       
+       if ( BER_BVISEMPTY( &op->o_req_ndn ) ) {
+               Debug( LDAP_DEBUG_ANY, "%s do_modify: root dse!\n",
+                       op->o_log_prefix, 0, 0 );
+               send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
+                       "modify upon the root DSE not supported" );
+               goto cleanup;
+
+       } else if ( bvmatch( &op->o_req_ndn, &frontendDB->be_schemandn ) ) {
+               Debug( LDAP_DEBUG_ANY, "%s do_modify: subschema subentry!\n",
+                       op->o_log_prefix, 0, 0 );
+               send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
+                       "modification of subschema subentry not supported" );
+               goto cleanup;
+       }
 
        /*
         * We could be serving multiple database backends.  Select the
         * appropriate one, or send a referral to our "referral server"
         * if we don't hold it.
         */
-       op->o_bd = select_backend( &op->o_req_ndn, manageDSAit, 1 );
+       op->o_bd = select_backend( &op->o_req_ndn, 1 );
        if ( op->o_bd == NULL ) {
                op->o_bd = bd;
                rs->sr_ref = referral_rewrite( default_referral,
@@ -244,7 +243,7 @@ fe_op_modify( Operation *op, SlapReply *rs )
        /* If we've got a glued backend, check the real backend */
        op_be = op->o_bd;
        if ( SLAP_GLUE_INSTANCE( op->o_bd )) {
-               op->o_bd = select_backend( &op->o_req_ndn, manageDSAit, 0 );
+               op->o_bd = select_backend( &op->o_req_ndn, 0 );
        }
 
        /* check restrictions */
@@ -287,7 +286,6 @@ fe_op_modify( Operation *op, SlapReply *rs )
                 */
                if ( !SLAP_SINGLE_SHADOW(op->o_bd) || repl_user ) {
                        int update = !BER_BVISEMPTY( &op->o_bd->be_update_ndn );
-                       slap_callback cb = { NULL, slap_replog_cb, NULL, NULL };
 
                        op->o_bd = op_be;
 
@@ -299,13 +297,6 @@ fe_op_modify( Operation *op, SlapReply *rs )
                                        goto cleanup;
                                }
                        }
-
-                       if ( !repl_user ) {
-                               /* but multimaster slapd logs only the ones 
-                                * not from a replicator user */
-                               cb.sc_next = op->o_callback;
-                               op->o_callback = &cb;
-                       }
                        op->o_bd->be_modify( op, rs );
 
                } else { /* send a referral */
@@ -695,7 +686,7 @@ int slap_mods_check(
 
                                        MatchingRule *mr = ad->ad_type->sat_equality;
                                        int istack[sizeof(int)*16];
-                                       int i,j,k,l,ir,jstack, rc, match, *ix, itmp;
+                                       int i, j, k, l, ir, jstack, match, *ix, itmp;
                                        struct berval a, *cv;
 
 /* If PRESERVE_ORDER is defined only the index array is sorted; the
@@ -886,6 +877,7 @@ void slap_mods_opattrs(
                timestamp.bv_val = timebuf;
                for ( modtail = modsp; *modtail; modtail = &(*modtail)->sml_next ) {
                        if ( (*modtail)->sml_op != LDAP_MOD_ADD &&
+                               (*modtail)->sml_op != SLAP_MOD_SOFTADD &&
                                (*modtail)->sml_op != LDAP_MOD_REPLACE )
                        {
                                continue;
@@ -1011,9 +1003,9 @@ slap_parse_modlist(
        ber_tag_t       tag;
        ber_len_t       len;
        char            *last;
-       Modifications   **modtail = &ms->rs_modlist;
+       Modifications   **modtail = &ms->rs_mods.rs_modlist;
 
-       ms->rs_modlist = NULL;
+       ms->rs_mods.rs_modlist = NULL;
        ms->rs_increment = 0;
 
        rs->sr_err = LDAP_SUCCESS;
@@ -1049,10 +1041,6 @@ slap_parse_modlist(
                switch( mop ) {
                case LDAP_MOD_ADD:
                        if ( mod->sml_values == NULL ) {
-                               Debug( LDAP_DEBUG_ANY, "slap_parse_modlist: "
-                                       "modify/add operation (%ld) requires values\n",
-                                       (long) mop, 0, 0 );
-
                                rs->sr_text = "modify/add operation requires values";
                                rs->sr_err = LDAP_PROTOCOL_ERROR;
                                goto done;
@@ -1068,20 +1056,12 @@ slap_parse_modlist(
                        if( op->o_protocol >= LDAP_VERSION3 ) {
                                ms->rs_increment++;
                                if ( mod->sml_values == NULL ) {
-                                       Debug( LDAP_DEBUG_ANY, "slap_parse_modlist: "
-                                               "modify/increment operation (%ld) requires value\n",
-                                               (long) mop, 0, 0 );
-
                                        rs->sr_text = "modify/increment operation requires value";
                                        rs->sr_err = LDAP_PROTOCOL_ERROR;
                                        goto done;
                                }
 
                                if ( !BER_BVISNULL( &mod->sml_values[ 1 ] ) ) {
-                                       Debug( LDAP_DEBUG_ANY,  "slap_parse_modlist: modify/increment "
-                                               "operation (%ld) requires single value\n",
-                                               (long) mop, 0, 0 );
-
                                        rs->sr_text = "modify/increment operation requires single value";
                                        rs->sr_err = LDAP_PROTOCOL_ERROR;
                                        goto done;
@@ -1092,10 +1072,6 @@ slap_parse_modlist(
                        /* fall thru */
 
                default:
-                       Debug( LDAP_DEBUG_ANY, "slap_parse_modlist: "
-                               "unrecognized modify operation (%ld)\n",
-                               (long) mop, 0, 0 );
-
                        rs->sr_text = "unrecognized modify operation";
                        rs->sr_err = LDAP_PROTOCOL_ERROR;
                        goto done;
@@ -1107,8 +1083,8 @@ slap_parse_modlist(
 
 done:
        if ( rs->sr_err != LDAP_SUCCESS ) {
-               slap_mods_free( ms->rs_modlist, 1 );
-               ms->rs_modlist = NULL;
+               slap_mods_free( ms->rs_mods.rs_modlist, 1 );
+               ms->rs_mods.rs_modlist = NULL;
                ms->rs_increment = 0;
        }
 
index 0e511a761e6d2a8a2d06520c78932e874b6a4e1f..3aae6ac4448c7733197577d195e6069ab2d196e9 100644 (file)
@@ -57,9 +57,8 @@ do_modrdn(
 
        ber_len_t       length;
 
-       Debug( LDAP_DEBUG_TRACE, "do_modrdn\n", 0, 0, 0 );
-
-
+       Debug( LDAP_DEBUG_TRACE, "%s do_modrdn\n",
+                       op->o_log_prefix, 0, 0 );
        /*
         * Parse the modrdn request.  It looks like this:
         *
@@ -74,8 +73,8 @@ do_modrdn(
        if ( ber_scanf( op->o_ber, "{mmb", &dn, &newrdn, &deloldrdn )
            == LBER_ERROR )
        {
-               Debug( LDAP_DEBUG_ANY, "ber_scanf failed\n", 0, 0, 0 );
-
+               Debug( LDAP_DEBUG_ANY, "%s do_modrdn: ber_scanf failed\n",
+                       op->o_log_prefix, 0, 0 );
                send_ldap_discon( op, rs, LDAP_PROTOCOL_ERROR, "decoding error" );
                return SLAPD_DISCONNECT;
        }
@@ -84,12 +83,12 @@ do_modrdn(
 
        if ( ber_peek_tag( op->o_ber, &length ) == LDAP_TAG_NEWSUPERIOR ) {
                if ( op->o_protocol < LDAP_VERSION3 ) {
-                       /* Conection record indicates v2 but field 
+                       /* Connection record indicates v2 but field 
                         * newSuperior is present: report error.
                         */
                        Debug( LDAP_DEBUG_ANY,
-                           "modrdn(v2): invalid field newSuperior!\n",
-                           0, 0, 0 );
+                               "%s do_modrdn: newSuperior requires LDAPv3\n",
+                               op->o_log_prefix, 0, 0 );
 
                        send_ldap_discon( op, rs,
                                LDAP_PROTOCOL_ERROR, "newSuperior requires LDAPv3" );
@@ -100,8 +99,8 @@ do_modrdn(
                if ( ber_scanf( op->o_ber, "m", &newSuperior ) 
                     == LBER_ERROR ) {
 
-                       Debug( LDAP_DEBUG_ANY, "ber_scanf(\"m\") failed\n",
-                               0, 0, 0 );
+                       Debug( LDAP_DEBUG_ANY, "%s do_modrdn: ber_scanf(\"m\") failed\n",
+                               op->o_log_prefix, 0, 0 );
 
                        send_ldap_discon( op, rs,
                                LDAP_PROTOCOL_ERROR, "decoding error" );
@@ -118,8 +117,8 @@ do_modrdn(
                newSuperior.bv_len ? newSuperior.bv_val : "" );
 
        if ( ber_scanf( op->o_ber, /*{*/ "}") == LBER_ERROR ) {
-               Debug( LDAP_DEBUG_ANY, "do_modrdn: ber_scanf failed\n", 0, 0, 0 );
-
+               Debug( LDAP_DEBUG_ANY, "%s do_modrdn: ber_scanf failed\n",
+                       op->o_log_prefix, 0, 0 );
                send_ldap_discon( op, rs,
                        LDAP_PROTOCOL_ERROR, "decoding error" );
                rs->sr_err = SLAPD_DISCONNECT;
@@ -127,16 +126,16 @@ do_modrdn(
        }
 
        if( get_ctrls( op, rs, 1 ) != LDAP_SUCCESS ) {
-               Debug( LDAP_DEBUG_ANY, "do_modrdn: get_ctrls failed\n", 0, 0, 0 );
-
+               Debug( LDAP_DEBUG_ANY, "%s do_modrdn: get_ctrls failed\n",
+                       op->o_log_prefix, 0, 0 );
                /* get_ctrls has sent results.  Now clean up. */
                goto cleanup;
        } 
 
        rs->sr_err = dnPrettyNormal( NULL, &dn, &op->o_req_dn, &op->o_req_ndn, op->o_tmpmemctx );
        if( rs->sr_err != LDAP_SUCCESS ) {
-               Debug( LDAP_DEBUG_ANY,
-                       "do_modrdn: invalid dn (%s)\n", dn.bv_val, 0, 0 );
+               Debug( LDAP_DEBUG_ANY, "%s do_modrdn: invalid dn (%s)\n",
+                       op->o_log_prefix, dn.bv_val, 0 );
                send_ldap_error( op, rs, LDAP_INVALID_DN_SYNTAX, "invalid DN" );
                goto cleanup;
        }
@@ -145,16 +144,15 @@ do_modrdn(
 
        rs->sr_err = dnPrettyNormal( NULL, &newrdn, &op->orr_newrdn, &op->orr_nnewrdn, op->o_tmpmemctx );
        if( rs->sr_err != LDAP_SUCCESS ) {
-               Debug( LDAP_DEBUG_ANY,
-                       "do_modrdn: invalid newrdn (%s)\n", newrdn.bv_val, 0, 0 );
+               Debug( LDAP_DEBUG_ANY, "%s do_modrdn: invalid newrdn (%s)\n",
+                       op->o_log_prefix, newrdn.bv_val, 0 );
                send_ldap_error( op, rs, LDAP_INVALID_DN_SYNTAX, "invalid new RDN" );
                goto cleanup;
        }
 
        if( rdn_validate( &op->orr_newrdn ) != LDAP_SUCCESS ) {
-               Debug( LDAP_DEBUG_ANY, "do_modrdn: invalid rdn (%s)\n",
-                       op->orr_newrdn.bv_val, 0, 0 );
-
+               Debug( LDAP_DEBUG_ANY, "%s do_modrdn: invalid rdn (%s)\n",
+                       op->o_log_prefix, op->orr_newrdn.bv_val, 0 );
                send_ldap_error( op, rs, LDAP_INVALID_DN_SYNTAX, "invalid new RDN" );
                goto cleanup;
        }
@@ -164,13 +162,16 @@ do_modrdn(
                        &nnewSuperior, op->o_tmpmemctx );
                if( rs->sr_err != LDAP_SUCCESS ) {
                        Debug( LDAP_DEBUG_ANY,
-                               "do_modrdn: invalid newSuperior (%s)\n",
-                               newSuperior.bv_val, 0, 0 );
+                               "%s do_modrdn: invalid newSuperior (%s)\n",
+                               op->o_log_prefix, newSuperior.bv_val, 0 );
                        send_ldap_error( op, rs, LDAP_INVALID_DN_SYNTAX, "invalid newSuperior" );
                        goto cleanup;
                }
        }
 
+       Statslog( LDAP_DEBUG_STATS, "%s MODRDN dn=\"%s\"\n",
+           op->o_log_prefix, op->o_req_dn.bv_val, 0, 0, 0 );
+
        op->orr_deleteoldrdn = deloldrdn;
        op->orr_modlist = NULL;
 
@@ -214,37 +215,31 @@ int
 fe_op_modrdn( Operation *op, SlapReply *rs )
 {
        Backend         *newSuperior_be = NULL;
-       int             manageDSAit;
        struct berval   pdn = BER_BVNULL;
        BackendDB       *op_be, *bd = op->o_bd;
        
        if( op->o_req_ndn.bv_len == 0 ) {
-               Debug( LDAP_DEBUG_ANY, "do_modrdn: root dse!\n", 0, 0, 0 );
-
+               Debug( LDAP_DEBUG_ANY, "%s do_modrdn: root dse!\n",
+                       op->o_log_prefix, 0, 0 );
                send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
                        "cannot rename the root DSE" );
                goto cleanup;
 
        } else if ( bvmatch( &op->o_req_ndn, &frontendDB->be_schemandn ) ) {
-               Debug( LDAP_DEBUG_ANY, "do_modrdn: subschema subentry: %s (%ld)\n",
-                       frontendDB->be_schemandn.bv_val, (long)frontendDB->be_schemandn.bv_len, 0 );
+               Debug( LDAP_DEBUG_ANY, "%s do_modrdn: subschema subentry: %s (%ld)\n",
+                       op->o_log_prefix, frontendDB->be_schemandn.bv_val, (long)frontendDB->be_schemandn.bv_len );
 
                send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
                        "cannot rename subschema subentry" );
                goto cleanup;
        }
 
-       Statslog( LDAP_DEBUG_STATS, "%s MODRDN dn=\"%s\"\n",
-           op->o_log_prefix, op->o_req_dn.bv_val, 0, 0, 0 );
-
-       manageDSAit = get_manageDSAit( op );
-
        /*
         * We could be serving multiple database backends.  Select the
         * appropriate one, or send a referral to our "referral server"
         * if we don't hold it.
         */
-       op->o_bd = select_backend( &op->o_req_ndn, manageDSAit, 1 );
+       op->o_bd = select_backend( &op->o_req_ndn, 1 );
        if ( op->o_bd == NULL ) {
                op->o_bd = bd;
                rs->sr_ref = referral_rewrite( default_referral,
@@ -266,7 +261,7 @@ fe_op_modrdn( Operation *op, SlapReply *rs )
        /* If we've got a glued backend, check the real backend */
        op_be = op->o_bd;
        if ( SLAP_GLUE_INSTANCE( op->o_bd )) {
-               op->o_bd = select_backend( &op->o_req_ndn, manageDSAit, 0 );
+               op->o_bd = select_backend( &op->o_req_ndn, 0 );
        }
 
        /* check restrictions */
@@ -284,7 +279,7 @@ fe_op_modrdn( Operation *op, SlapReply *rs )
         * the same backend, otherwise we return an error.
         */
        if( op->orr_newSup ) {
-               newSuperior_be = select_backend( op->orr_nnewSup, 0, 0 );
+               newSuperior_be = select_backend( op->orr_nnewSup, 0 );
 
                if ( newSuperior_be != op->o_bd ) {
                        /* newSuperior is in different backend */
@@ -306,15 +301,7 @@ fe_op_modrdn( Operation *op, SlapReply *rs )
                int repl_user = be_isupdate( op );
                if ( !SLAP_SINGLE_SHADOW(op->o_bd) || repl_user )
                {
-                       slap_callback cb = { NULL, slap_replog_cb, NULL, NULL };
-
                        op->o_bd = op_be;
-
-                       if ( !op->o_bd->be_update_ndn.bv_len || !repl_user )
-                       {
-                               cb.sc_next = op->o_callback;
-                               op->o_callback = &cb;
-                       }
                        op->o_bd->be_modrdn( op, rs );
 
                        if ( op->o_bd->be_delete ) {
@@ -349,7 +336,7 @@ fe_op_modrdn( Operation *op, SlapReply *rs )
                                        }
                                }
                                op->o_managedsait = org_managedsait;
-                               op->o_dn = org_dn;
+                               op->o_dn = org_dn;
                                op->o_ndn = org_ndn;
                                op->o_req_dn = org_req_dn;
                                op->o_req_ndn = org_req_ndn;
@@ -399,8 +386,9 @@ slap_modrdn2mods(
        if ( ldap_bv2rdn_x( &op->oq_modrdn.rs_newrdn, &new_rdn,
                (char **)&rs->sr_text, LDAP_DN_FORMAT_LDAP, op->o_tmpmemctx ) ) {
                Debug( LDAP_DEBUG_TRACE,
-                       "slap_modrdn2mods: can't figure out "
-                       "type(s)/value(s) of newrdn\n", 0, 0, 0 );
+                       "%s slap_modrdn2mods: can't figure out "
+                       "type(s)/value(s) of newrdn\n",
+                       op->o_log_prefix, 0, 0 );
                rs->sr_err = LDAP_INVALID_DN_SYNTAX;
                rs->sr_text = "unknown type(s) used in RDN";
                goto done;
@@ -410,8 +398,9 @@ slap_modrdn2mods(
                if ( ldap_bv2rdn_x( &op->o_req_dn, &old_rdn,
                        (char **)&rs->sr_text, LDAP_DN_FORMAT_LDAP, op->o_tmpmemctx ) ) {
                        Debug( LDAP_DEBUG_TRACE,
-                               "slap_modrdn2mods: can't figure out "
-                               "type(s)/value(s) of oldrdn\n", 0, 0, 0 );
+                               "%s slap_modrdn2mods: can't figure out "
+                               "type(s)/value(s) of oldrdn\n",
+                               op->o_log_prefix, 0, 0 );
                        rs->sr_err = LDAP_OTHER;
                        rs->sr_text = "cannot parse RDN from old DN";
                        goto done;
@@ -428,9 +417,10 @@ slap_modrdn2mods(
 
                if ( rs->sr_err != LDAP_SUCCESS ) {
                        Debug( LDAP_DEBUG_TRACE,
-                               "slap_modrdn2mods: %s: %s (new)\n",
+                               "%s slap_modrdn2mods: %s: %s (new)\n",
+                               op->o_log_prefix,
                                rs->sr_text, 
-                               new_rdn[ a_cnt ]->la_attr.bv_val, 0 );
+                               new_rdn[ a_cnt ]->la_attr.bv_val );
                        goto done;              
                }
 
@@ -468,10 +458,10 @@ slap_modrdn2mods(
                        rs->sr_err = slap_bv2ad( &old_rdn[d_cnt]->la_attr, &desc, &rs->sr_text );
                        if ( rs->sr_err != LDAP_SUCCESS ) {
                                Debug( LDAP_DEBUG_TRACE,
-                                       "slap_modrdn2mods: %s: %s (old)\n",
+                                       "%s slap_modrdn2mods: %s: %s (old)\n",
+                                       op->o_log_prefix,
                                        rs->sr_text, 
-                                       old_rdn[d_cnt]->la_attr.bv_val, 
-                                       0 );
+                                       old_rdn[d_cnt]->la_attr.bv_val );
                                goto done;              
                        }
 
index ebeb50b6e748d8f1e741f103260589a1f741ba17..71e1b22200ff62c12c154455787722b29e9b7d79 100644 (file)
@@ -68,7 +68,8 @@ int module_init (void)
 
                return -1;
        }
-       return 0;
+
+       return module_path( LDAP_MODULEDIR );
 }
 
 int module_kill (void)
index 85d60bf62c47f6498ad17455c799ef8752cecd89..f85c08af06476220366f3b56f9cc2c8213dc4493 100644 (file)
@@ -30,9 +30,9 @@ struct mindexrec {
 };
 
 static Avlnode *mr_index = NULL;
-static LDAP_SLIST_HEAD(MRList, slap_matching_rule) mr_list
+static LDAP_SLIST_HEAD(MRList, MatchingRule) mr_list
        = LDAP_SLIST_HEAD_INITIALIZER(&mr_list);
-static LDAP_SLIST_HEAD(MRUList, slap_matching_rule_use) mru_list
+static LDAP_SLIST_HEAD(MRUList, MatchingRuleUse) mru_list
        = LDAP_SLIST_HEAD_INITIALIZER(&mru_list);
 
 static int
@@ -145,6 +145,67 @@ mr_insert(
        return 0;
 }
 
+int
+mr_make_syntax_compat_with_mr(
+       Syntax          *syn,
+       MatchingRule    *mr )
+{
+       int             n = 0;
+
+       assert( syn != NULL );
+       assert( mr != NULL );
+
+       if ( mr->smr_compat_syntaxes ) {
+               /* count esisting */
+               for ( n = 0;
+                       mr->smr_compat_syntaxes[ n ];
+                       n++ )
+               {
+                       if ( mr->smr_compat_syntaxes[ n ] == syn ) {
+                               /* already compatible; mmmmh... */
+                               return 1;
+                       }
+               }
+       }
+
+       mr->smr_compat_syntaxes = ch_realloc(
+               mr->smr_compat_syntaxes,
+               sizeof( Syntax * )*(n + 2) );
+       mr->smr_compat_syntaxes[ n ] = syn;
+       mr->smr_compat_syntaxes[ n + 1 ] = NULL;
+
+       return 0;
+}
+
+int
+mr_make_syntax_compat_with_mrs(
+       const char *syntax,
+       char *const *mrs )
+{
+       int     r, rc = 0;
+       Syntax  *syn;
+
+       assert( syntax != NULL );
+       assert( mrs != NULL );
+
+       syn = syn_find( syntax );
+       if ( syn == NULL ) {
+               return -1;
+       }
+
+       for ( r = 0; mrs[ r ] != NULL; r++ ) {
+               MatchingRule    *mr = mr_find( mrs[ r ] );
+               if ( mr == NULL ) {
+                       /* matchingRule not found -- ignore by now */
+                       continue;
+               }
+
+               rc += mr_make_syntax_compat_with_mr( syn, mr );
+       }
+
+       return rc;
+}
+
 int
 mr_add(
     LDAPMatchingRule           *mr,
@@ -316,7 +377,8 @@ matching_rule_use_init( void )
 
        LDAP_SLIST_FOREACH( mr, &mr_list, smr_next ) {
                AttributeType   *at;
-               MatchingRuleUse mru_storage, *mru = &mru_storage;
+               MatchingRuleUse mru_storage = { 0 },
+                               *mru = &mru_storage;
 
                char            **applies_oids = NULL;
 
@@ -341,8 +403,6 @@ matching_rule_use_init( void )
                        continue;
                }
 
-               memset( mru, 0, sizeof( MatchingRuleUse ) );
-
                /*
                 * Note: we're using the same values of the corresponding 
                 * MatchingRule structure; maybe we'd copy them ...
@@ -396,13 +456,16 @@ matching_rule_use_init( void )
        return( 0 );
 }
 
-int mr_usable_with_at(
-       MatchingRule *mr,
-       AttributeType *at )
+int
+mr_usable_with_at(
+       MatchingRule    *mr,
+       AttributeType   *at )
 {
-       if( mr->smr_usage & SLAP_MR_EXT && ( 
+       if ( ( mr->smr_usage & SLAP_MR_EXT ) && (
                mr->smr_syntax == at->sat_syntax ||
-               mr == at->sat_equality || mr == at->sat_approx ) )
+               mr == at->sat_equality ||
+               mr == at->sat_approx ||
+               syn_is_sup( at->sat_syntax, mr->smr_syntax ) ) )
        {
                return 1;
        }
index ef52fc869585909492cb384eda46dde365cf6814..42879ee76e362aebbf22a2afd96e386a9d045e67 100644 (file)
@@ -37,16 +37,16 @@ int is_object_subclass(
                sup->soc_oid, sub->soc_oid, sup == sub );
 #endif
 
-       if( sup == sub ) {
+       if ( sup == sub ) {
                return 1;
        }
 
-       if( sub->soc_sups == NULL ) {
+       if ( sub->soc_sups == NULL ) {
                return 0;
        }
 
-       for( i=0; sub->soc_sups[i] != NULL; i++ ) {
-               if( is_object_subclass( sup, sub->soc_sups[i] ) ) {
+       for ( i = 0; sub->soc_sups[i] != NULL; i++ ) {
+               if ( is_object_subclass( sup, sub->soc_sups[i] ) ) {
                        return 1;
                }
        }
@@ -71,11 +71,11 @@ int is_entry_objectclass(
        assert( !( e == NULL || oc == NULL ) );
        assert( ( flags & SLAP_OCF_MASK ) != SLAP_OCF_MASK );
 
-       if( e == NULL || oc == NULL ) {
+       if ( e == NULL || oc == NULL ) {
                return 0;
        }
 
-       if( flags == SLAP_OCF_SET_FLAGS && ( e->e_ocflags & SLAP_OC__END ) )
+       if ( flags == SLAP_OCF_SET_FLAGS && ( e->e_ocflags & SLAP_OC__END ) )
        {
                /* flags are set, use them */
                return (e->e_ocflags & oc->soc_flags & SLAP_OC__MASK) != 0;
@@ -85,7 +85,7 @@ int is_entry_objectclass(
         * find objectClass attribute
         */
        attr = attr_find( e->e_attrs, slap_schema.si_ad_objectClass );
-       if( attr == NULL ) {
+       if ( attr == NULL ) {
                /* no objectClass attribute */
                Debug( LDAP_DEBUG_ANY, "is_entry_objectclass(\"%s\", \"%s\") "
                        "no objectClass attribute\n",
@@ -95,7 +95,7 @@ int is_entry_objectclass(
                return 0;
        }
 
-       for( bv=attr->a_vals; bv->bv_val; bv++ ) {
+       for ( bv = attr->a_vals; bv->bv_val; bv++ ) {
                ObjectClass *objectClass = oc_bvfind( bv );
 
                if ( objectClass == NULL ) {
@@ -132,7 +132,7 @@ struct oindexrec {
 
 static Avlnode *oc_index = NULL;
 static Avlnode *oc_cache = NULL;
-static LDAP_STAILQ_HEAD(OCList, slap_object_class) oc_list
+static LDAP_STAILQ_HEAD(OCList, ObjectClass) oc_list
        = LDAP_STAILQ_HEAD_INITIALIZER(oc_list);
 
 ObjectClass *oc_sys_tail;
@@ -193,7 +193,7 @@ oc_bvfind( struct berval *ocname )
        return( NULL );
 }
 
-static LDAP_STAILQ_HEAD(OCUList, slap_object_class) oc_undef_list
+static LDAP_STAILQ_HEAD(OCUList, ObjectClass) oc_undef_list
        = LDAP_STAILQ_HEAD_INITIALIZER(oc_undef_list);
 
 ObjectClass *
@@ -414,7 +414,7 @@ oc_delete( ObjectClass *oc )
 {
        oc->soc_flags |= SLAP_OC_DELETED;
 
-       LDAP_STAILQ_REMOVE(&oc_list,oc,slap_object_class,soc_next);
+       LDAP_STAILQ_REMOVE(&oc_list, oc, ObjectClass, soc_next);
 
        oc_delete_names( oc );
 }
index 646574a378a7f603aa3a70048569ca1af427099a..287937f03c3d1a8cb53c0765fae50d4dee84ed60 100644 (file)
@@ -26,7 +26,7 @@
 #include "lutil.h"
 #include "config.h"
 
-static LDAP_STAILQ_HEAD(OidMacroList, slap_oid_macro) om_list
+static LDAP_STAILQ_HEAD(OidMacroList, OidMacro) om_list
        = LDAP_STAILQ_HEAD_INITIALIZER(om_list);
 
 OidMacro *om_sys_tail;
@@ -105,22 +105,22 @@ parse_oidm(
 
        oidv = oidm_find( c->argv[2] );
        if( !oidv ) {
-               snprintf( c->msg, sizeof( c->msg ),
+               snprintf( c->cr_msg, sizeof( c->cr_msg ),
                        "%s: OID %s not recognized",
                        c->argv[0], c->argv[2] );
                Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
-                       "%s %s\n", c->log, c->msg, 0 );
+                       "%s %s\n", c->log, c->cr_msg, 0 );
                return 1;
        }
 
        oid = oidm_find( c->argv[1] );
        if( oid != NULL ) {
                int rc;
-               snprintf( c->msg, sizeof( c->msg ),
+               snprintf( c->cr_msg, sizeof( c->cr_msg ),
                        "%s: \"%s\" previously defined \"%s\"",
                        c->argv[0], c->argv[1], oid );
                Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
-                       "%s %s\n", c->log, c->msg, 0 );
+                       "%s %s\n", c->log, c->cr_msg, 0 );
                /* Allow duplicate if the definition is identical */
                rc = strcmp( oid, oidv ) != 0;
                SLAP_FREE( oid );
@@ -131,10 +131,10 @@ parse_oidm(
 
        om = (OidMacro *) SLAP_CALLOC( sizeof(OidMacro), 1 );
        if( om == NULL ) {
-               snprintf( c->msg, sizeof( c->msg ),
+               snprintf( c->cr_msg, sizeof( c->cr_msg ),
                        "%s: SLAP_CALLOC failed", c->argv[0] );
                Debug( LDAP_DEBUG_ANY,
-                       "%s %s\n", c->log, c->msg, 0 );
+                       "%s %s\n", c->log, c->cr_msg, 0 );
                if ( oidv != c->argv[2] )
                        SLAP_FREE( oidv );
                return 1;
index 601ab81259ef01970ae0ec6b8060e361a8a74fc9..b5b2f3d1e661b180962917607614e7a74be17893 100644 (file)
@@ -38,7 +38,7 @@
 #endif
 
 static ldap_pvt_thread_mutex_t slap_op_mutex;
-static LDAP_STAILQ_HEAD(s_o, slap_op)  slap_free_ops;
+static LDAP_STAILQ_HEAD(s_o, Operation)        slap_free_ops;
 static time_t last_time;
 static int last_incr;
 
@@ -74,6 +74,8 @@ slap_op_groups_free( Operation *op )
 void
 slap_op_free( Operation *op )
 {
+       OperationBuffer *opbuf;
+
        assert( LDAP_STAILQ_NEXT(op, o_next) == NULL );
 
        if ( op->o_ber != NULL ) {
@@ -109,9 +111,10 @@ slap_op_free( Operation *op )
 #endif /* defined( LDAP_SLAPI ) */
 
 
-       memset( op, 0, sizeof(Operation) + sizeof(Opheader) + SLAP_MAX_CIDS * sizeof(void *) );
-       op->o_hdr = (Opheader *)(op+1);
-       op->o_controls = (void **)(op->o_hdr+1);
+       opbuf = (OperationBuffer *) op;
+       memset( opbuf, 0, sizeof(*opbuf) );
+       op->o_hdr = &opbuf->ob_hdr;
+       op->o_controls = opbuf->ob_controls;
 
        ldap_pvt_thread_mutex_lock( &slap_op_mutex );
        LDAP_STAILQ_INSERT_HEAD( &slap_free_ops, op, o_next );
@@ -149,10 +152,9 @@ slap_op_alloc(
        ldap_pvt_thread_mutex_unlock( &slap_op_mutex );
 
        if (!op) {
-               op = (Operation *) ch_calloc( 1, sizeof(Operation)
-                       + sizeof(Opheader) + SLAP_MAX_CIDS * sizeof(void *) );
-               op->o_hdr = (Opheader *)(op + 1);
-               op->o_controls = (void **)(op->o_hdr+1);
+               op = (Operation *) ch_calloc( 1, sizeof(OperationBuffer) );
+               op->o_hdr = &((OperationBuffer *) op)->ob_hdr;
+               op->o_controls = ((OperationBuffer *) op)->ob_controls;
        }
 
        op->o_ber = ber;
index a6d04ee1d983ed3b2a07c72dfedb8e95f2559b92..3321f968a46ca270f4465cd2df6b5b5483be5f16 100644 (file)
@@ -20,6 +20,7 @@ SRCS = overlays.c \
        dds.c \
        dyngroup.c \
        dynlist.c \
+       memberof.c \
        pcache.c \
        ppolicy.c \
        refint.c \
@@ -30,9 +31,9 @@ SRCS = overlays.c \
        translucent.c \
        unique.c \
        valsort.c
-OBJS = overlays.o \
-       statover.o \
-       @SLAPD_STATIC_OVERLAYS@
+OBJS = statover.o \
+       @SLAPD_STATIC_OVERLAYS@ \
+       overlays.o
 
 # Add here the objs that are needed by overlays, but do not make it
 # into SLAPD_STATIC_OVERLAYS...
@@ -76,6 +77,9 @@ dyngroup.la : dyngroup.lo
 dynlist.la : dynlist.lo
        $(LTLINK_MOD) -module -o $@ dynlist.lo version.lo $(LINK_LIBS)
 
+memberof.la : memberof.lo
+       $(LTLINK_MOD) -module -o $@ memberof.lo version.lo $(LINK_LIBS)
+
 pcache.la : pcache.lo
        $(LTLINK_MOD) -module -o $@ pcache.lo version.lo $(LINK_LIBS)
 
index b23c421f1e9fd2630f69357140de7b0409f02fce..51813e6a8c95f7ccef1bc2c190d8b3c443d0df1d 100644 (file)
@@ -168,6 +168,7 @@ static ObjectClass *log_ocs[LOG_EN__COUNT], *log_container;
 
 #define LOG_SCHEMA_AT LOG_SCHEMA_ROOT ".1"
 #define LOG_SCHEMA_OC LOG_SCHEMA_ROOT ".2"
+#define LOG_SCHEMA_SYN LOG_SCHEMA_ROOT ".3"
 
 static AttributeDescription *ad_reqDN, *ad_reqStart, *ad_reqEnd, *ad_reqType,
        *ad_reqSession, *ad_reqResult, *ad_reqAuthzID, *ad_reqControls,
@@ -178,6 +179,31 @@ static AttributeDescription *ad_reqDN, *ad_reqStart, *ad_reqEnd, *ad_reqType,
        *ad_reqId, *ad_reqMessage, *ad_reqVersion, *ad_reqDerefAliases,
        *ad_reqReferral, *ad_reqOld, *ad_auditContext;
 
+static int
+logSchemaControlValidate(
+       Syntax          *syntax,
+       struct berval   *val );
+
+char   *mrControl[] = {
+       "objectIdentifierFirstComponentMatch",
+       NULL
+};
+
+static struct {
+       char                    *oid;
+       slap_syntax_defs_rec    syn;
+       char                    **mrs;
+} lsyntaxes[] = {
+       { LOG_SCHEMA_SYN ".1" ,
+               { "( " LOG_SCHEMA_SYN ".1 DESC 'Control' )",
+                       SLAP_SYNTAX_HIDE,
+                       NULL,
+                       logSchemaControlValidate,
+                       NULL },
+               mrControl },
+       { NULL }
+};
+
 static struct {
        char *at;
        AttributeDescription **ad;
@@ -231,10 +257,14 @@ static struct {
                "SUP labeledURI )", &ad_reqReferral },
        { "( " LOG_SCHEMA_AT ".10 NAME 'reqControls' "
                "DESC 'Request controls' "
-               "SYNTAX OMsOctetString )", &ad_reqControls },
+               "EQUALITY objectIdentifierFirstComponentMatch "
+               "SYNTAX " LOG_SCHEMA_SYN ".1 "
+               "X-ORDERED 'VALUES' )", &ad_reqControls },
        { "( " LOG_SCHEMA_AT ".11 NAME 'reqRespControls' "
                "DESC 'Response controls of request' "
-               "SYNTAX OMsOctetString )", &ad_reqRespControls },
+               "EQUALITY objectIdentifierFirstComponentMatch "
+               "SYNTAX " LOG_SCHEMA_SYN ".1 "
+               "X-ORDERED 'VALUES' )", &ad_reqRespControls },
        { "( " LOG_SCHEMA_AT ".12 NAME 'reqId' "
                "DESC 'ID of Request to Abandon' "
                "EQUALITY integerMatch "
@@ -561,7 +591,7 @@ accesslog_purge( void *ctx, void *arg )
 
        Connection conn = {0};
        OperationBuffer opbuf;
-       Operation *op = (Operation *) &opbuf;
+       Operation *op;
        SlapReply rs = {REP_RESULT};
        slap_callback cb = { NULL, log_old_lookup, NULL, NULL };
        Filter f;
@@ -571,7 +601,8 @@ accesslog_purge( void *ctx, void *arg )
        char csnbuf[LDAP_LUTIL_CSNSTR_BUFSIZE];
        time_t old = slap_get_time();
 
-       connection_fake_init( &conn, op, ctx );
+       connection_fake_init( &conn, &opbuf, ctx );
+       op = &opbuf.ob_op;
 
        f.f_choice = LDAP_FILTER_LE;
        f.f_ava = &ava;
@@ -655,10 +686,10 @@ log_cf_gen(ConfigArgs *c)
                                value_add_one( &c->rvalue_vals, li->li_db->be_suffix );
                                value_add_one( &c->rvalue_nvals, li->li_db->be_nsuffix );
                        } else {
-                               snprintf( c->msg, sizeof( c->msg ),
+                               snprintf( c->cr_msg, sizeof( c->cr_msg ),
                                        "accesslog: \"logdb <suffix>\" must be specified" );
                                Debug( LDAP_DEBUG_ANY, "%s: %s \"%s\"\n",
-                                       c->log, c->msg, c->value_dn.bv_val );
+                                       c->log, c->cr_msg, c->value_dn.bv_val );
                                rc = 1;
                                break;
                        }
@@ -766,13 +797,13 @@ log_cf_gen(ConfigArgs *c)
                switch( c->type ) {
                case LOG_DB:
                        if ( CONFIG_ONLINE_ADD( c )) {
-                               li->li_db = select_backend( &c->value_ndn, 0, 0 );
+                               li->li_db = select_backend( &c->value_ndn, 0 );
                                if ( !li->li_db ) {
-                                       snprintf( c->msg, sizeof( c->msg ),
+                                       snprintf( c->cr_msg, sizeof( c->cr_msg ),
                                                "<%s> no matching backend found for suffix",
                                                c->argv[0] );
                                        Debug( LDAP_DEBUG_ANY, "%s: %s \"%s\"\n",
-                                               c->log, c->msg, c->value_dn.bv_val );
+                                               c->log, c->cr_msg, c->value_dn.bv_val );
                                        rc = 1;
                                }
                                ch_free( c->value_ndn.bv_val );
@@ -813,7 +844,7 @@ log_cf_gen(ConfigArgs *c)
                case LOG_OLD:
                        li->li_oldf = str2filter( c->argv[1] );
                        if ( !li->li_oldf ) {
-                               sprintf( c->msg, "bad filter!" );
+                               sprintf( c->cr_msg, "bad filter!" );
                                rc = 1;
                        }
                        break;
@@ -830,10 +861,10 @@ log_cf_gen(ConfigArgs *c)
                                        la->next = li->li_oldattrs;
                                        li->li_oldattrs = la;
                                } else {
-                                       snprintf( c->msg, sizeof( c->msg ), "%s <%s>: %s",
+                                       snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s <%s>: %s",
                                                c->argv[0], c->argv[i], text );
                                        Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
-                                               "%s: %s\n", c->log, c->msg, 0 );
+                                               "%s: %s\n", c->log, c->cr_msg, 0 );
                                        rc = ARG_BAD_CONF;
                                        break;
                                }
@@ -846,7 +877,273 @@ log_cf_gen(ConfigArgs *c)
        return rc;
 }
 
-static Entry *accesslog_entry( Operation *op, int logop,
+static int
+logSchemaControlValidate(
+       Syntax          *syntax,
+       struct berval   *valp )
+{
+       struct berval   val, bv;
+       int             i;
+       int             rc = LDAP_SUCCESS;
+
+       assert( valp != NULL );
+
+       val = *valp;
+
+       /* check minimal size */
+       if ( val.bv_len < STRLENOF( "{*}" ) ) {
+               return LDAP_INVALID_SYNTAX;
+       }
+
+       val.bv_len--;
+
+       /* check SEQUENCE boundaries */
+       if ( val.bv_val[ 0 ] != '{' /*}*/ ||
+               val.bv_val[ val.bv_len ] != /*{*/ '}' )
+       {
+               return LDAP_INVALID_SYNTAX;
+       }
+
+       /* extract and check OID */
+       for ( i = 1; i < val.bv_len; i++ ) {
+               if ( !ASCII_SPACE( val.bv_val[ i ] ) ) {
+                       break;
+               }
+       }
+
+       bv.bv_val = &val.bv_val[ i ];
+
+       for ( i++; i < val.bv_len; i++ ) {
+               if ( ASCII_SPACE( val.bv_val[ i ] ) )
+               {
+                       break;
+               }
+       }
+
+       bv.bv_len = &val.bv_val[ i ] - bv.bv_val;
+
+       rc = numericoidValidate( NULL, &bv );
+       if ( rc != LDAP_SUCCESS ) {
+               return rc;
+       }
+
+       if ( i == val.bv_len ) {
+               return LDAP_SUCCESS;
+       }
+
+       if ( val.bv_val[ i ] != ' ' ) {
+               return LDAP_INVALID_SYNTAX;
+       }
+
+       for ( i++; i < val.bv_len; i++ ) {
+               if ( !ASCII_SPACE( val.bv_val[ i ] ) ) {
+                       break;
+               }
+       }
+
+       if ( i == val.bv_len ) {
+               return LDAP_SUCCESS;
+       }
+
+       /* extract and check criticality */
+       if ( strncasecmp( &val.bv_val[ i ], "criticality ", STRLENOF( "criticality " ) ) == 0 )
+       {
+               i += STRLENOF( "criticality " );
+               for ( ; i < val.bv_len; i++ ) {
+                       if ( !ASCII_SPACE( val.bv_val[ i ] ) ) {
+                               break;
+                       }
+               }
+
+               if ( i == val.bv_len ) {
+                       return LDAP_INVALID_SYNTAX;
+               }
+
+               bv.bv_val = &val.bv_val[ i ];
+
+               for ( ; i < val.bv_len; i++ ) {
+                       if ( ASCII_SPACE( val.bv_val[ i ] ) ) {
+                               break;
+                       }
+               }
+
+               bv.bv_len = &val.bv_val[ i ] - bv.bv_val;
+
+               if ( !bvmatch( &bv, &slap_true_bv ) && !bvmatch( &bv, &slap_false_bv ) ) 
+               {
+                       return LDAP_INVALID_SYNTAX;
+               }
+
+               if ( i == val.bv_len ) {
+                       return LDAP_SUCCESS;
+               }
+
+               if ( val.bv_val[ i ] != ' ' ) {
+                       return LDAP_INVALID_SYNTAX;
+               }
+
+               for ( i++; i < val.bv_len; i++ ) {
+                       if ( !ASCII_SPACE( val.bv_val[ i ] ) ) {
+                               break;
+                       }
+               }
+
+               if ( i == val.bv_len ) {
+                       return LDAP_SUCCESS;
+               }
+       }
+
+       /* extract and check controlValue */
+       if ( strncasecmp( &val.bv_val[ i ], "controlValue ", STRLENOF( "controlValue " ) ) == 0 )
+       {
+               i += STRLENOF( "controlValue " );
+               for ( ; i < val.bv_len; i++ ) {
+                       if ( !ASCII_SPACE( val.bv_val[ i ] ) ) {
+                               break;
+                       }
+               }
+
+               if ( i == val.bv_len ) {
+                       return LDAP_INVALID_SYNTAX;
+               }
+
+               if ( val.bv_val[ i ] != '"' ) {
+                       return LDAP_INVALID_SYNTAX;
+               }
+
+               for ( ; i < val.bv_len; i++ ) {
+                       if ( val.bv_val[ i ] == '"' ) {
+                               break;
+                       }
+
+                       if ( !ASCII_HEX( val.bv_val[ i ] ) ) {
+                               return LDAP_INVALID_SYNTAX;
+                       }
+               }
+
+               if ( val.bv_val[ i ] != '"' ) {
+                       return LDAP_INVALID_SYNTAX;
+               }
+
+               for ( ; i < val.bv_len; i++ ) {
+                       if ( !ASCII_SPACE( val.bv_val[ i ] ) ) {
+                               break;
+                       }
+               }
+
+               if ( i == val.bv_len ) {
+                       return LDAP_SUCCESS;
+               }
+       }
+
+       return LDAP_INVALID_SYNTAX;
+}
+
+static int
+accesslog_ctrls(
+       LDAPControl **ctrls,
+       BerVarray *valsp,
+       BerVarray *nvalsp,
+       void *memctx )
+{
+       long            i, rc = 0;
+
+       assert( valsp != NULL );
+       assert( ctrls != NULL );
+
+       *valsp = NULL;
+       *nvalsp = NULL;
+
+       for ( i = 0; ctrls[ i ] != NULL; i++ ) {
+               struct berval   idx,
+                               oid,
+                               noid,
+                               bv;
+               char            *ptr,
+                               buf[ 32 ];
+
+               if ( ctrls[ i ]->ldctl_oid == NULL ) {
+                       return LDAP_PROTOCOL_ERROR;
+               }
+
+               idx.bv_len = snprintf( buf, sizeof( buf ), "{%ld}", i );
+               idx.bv_val = buf;
+
+               ber_str2bv( ctrls[ i ]->ldctl_oid, 0, 0, &oid );
+               noid.bv_len = idx.bv_len + oid.bv_len;
+               ptr = noid.bv_val = ber_memalloc_x( noid.bv_len + 1, memctx );
+               ptr = lutil_strcopy( ptr, idx.bv_val );
+               ptr = lutil_strcopy( ptr, oid.bv_val );
+
+               bv.bv_len = idx.bv_len + STRLENOF( "{}" ) + oid.bv_len;
+
+               if ( ctrls[ i ]->ldctl_iscritical ) {
+                       bv.bv_len += STRLENOF( " criticality TRUE" );
+               }
+
+               if ( !BER_BVISNULL( &ctrls[ i ]->ldctl_value ) ) {
+                       bv.bv_len += STRLENOF( " controlValue \"\"" )
+                               + 2 * ctrls[ i ]->ldctl_value.bv_len;
+               }
+
+               ptr = bv.bv_val = ber_memalloc_x( bv.bv_len + 1, memctx );
+               if ( ptr == NULL ) {
+                       ber_bvarray_free( *valsp );
+                       *valsp = NULL;
+                       ber_bvarray_free( *nvalsp );
+                       *nvalsp = NULL;
+                       return LDAP_OTHER;
+               }
+
+               ptr = lutil_strcopy( ptr, idx.bv_val );
+
+               *ptr++ = '{' /*}*/ ;
+               ptr = lutil_strcopy( ptr, oid.bv_val );
+
+               if ( ctrls[ i ]->ldctl_iscritical ) {
+                       ptr = lutil_strcopy( ptr, " criticality TRUE" );
+               }
+               
+               if ( !BER_BVISNULL( &ctrls[ i ]->ldctl_value ) ) {
+                       int     j;
+
+                       ptr = lutil_strcopy( ptr, " controlValue \"" );
+                       for ( j = 0; j < ctrls[ i ]->ldctl_value.bv_len; j++ )
+                       {
+                               unsigned char   o;
+
+                               o = ( ( ctrls[ i ]->ldctl_value.bv_val[ j ] >> 4 ) & 0xF );
+                               if ( o < 10 ) {
+                                       *ptr++ = '0' + o;
+
+                               } else {
+                                       *ptr++ = 'A' + o;
+                               }
+
+                               o = ( ctrls[ i ]->ldctl_value.bv_val[ j ] & 0xF );
+                               if ( o < 10 ) {
+                                       *ptr++ = '0' + o;
+
+                               } else {
+                                       *ptr++ = 'A' + o;
+                               }
+                       }
+
+                       *ptr++ = '"';
+               }
+
+               *ptr++ = '}';
+               *ptr = '\0';
+
+               ber_bvarray_add_x( valsp, &bv, memctx );
+               ber_bvarray_add_x( nvalsp, &noid, memctx );
+       }
+
+       return rc;
+       
+}
+
+static Entry *accesslog_entry( Operation *op, SlapReply *rs, int logop,
        Operation *op2 ) {
        slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
        log_info *li = on->on_bi.bi_private;
@@ -915,13 +1212,40 @@ static Entry *accesslog_entry( Operation *op, int logop,
        rdn.bv_len = sprintf( rdn.bv_val, "%lu", op->o_connid );
        attr_merge_one( e, ad_reqSession, &rdn, NULL );
 
-       if ( BER_BVISNULL( &op->o_dn )
+       if ( BER_BVISNULL( &op->o_dn ) ) {
                attr_merge_one( e, ad_reqAuthzID, (struct berval *)&slap_empty_bv,
                        (struct berval *)&slap_empty_bv );
-       else
+       } else {
                attr_merge_one( e, ad_reqAuthzID, &op->o_dn, &op->o_ndn );
+       }
 
        /* FIXME: need to add reqControls and reqRespControls */
+       if ( op->o_ctrls ) {
+               BerVarray       vals = NULL,
+                               nvals = NULL;
+
+               if ( accesslog_ctrls( op->o_ctrls, &vals, &nvals,
+                       op->o_tmpmemctx ) == LDAP_SUCCESS && vals )
+               {
+                       attr_merge( e, ad_reqControls, vals, nvals );
+                       ber_bvarray_free_x( vals, op->o_tmpmemctx );
+                       ber_bvarray_free_x( nvals, op->o_tmpmemctx );
+               }
+       }
+
+       if ( rs->sr_ctrls ) {
+               BerVarray       vals = NULL,
+                               nvals = NULL;
+
+               if ( accesslog_ctrls( rs->sr_ctrls, &vals, &nvals,
+                       op->o_tmpmemctx ) == LDAP_SUCCESS && vals )
+               {
+                       attr_merge( e, ad_reqRespControls, vals, nvals );
+                       ber_bvarray_free_x( vals, op->o_tmpmemctx );
+                       ber_bvarray_free_x( nvals, op->o_tmpmemctx );
+               }
+
+       }
 
        return e;
 }
@@ -1007,7 +1331,7 @@ static int accesslog_response(Operation *op, SlapReply *rs) {
        if ( li->li_success && rs->sr_err != LDAP_SUCCESS )
                goto done;
 
-       e = accesslog_entry( op, logop, &op2 );
+       e = accesslog_entry( op, rs, logop, &op2 );
 
        attr_merge_one( e, ad_reqDN, &op->o_req_dn, &op->o_req_ndn );
 
@@ -1253,10 +1577,10 @@ static int accesslog_response(Operation *op, SlapReply *rs) {
                if ( op->orb_method == LDAP_AUTH_SIMPLE ) {
                        attr_merge_one( e, ad_reqMethod, &simple, NULL );
                } else {
-                       bv.bv_len = STRLENOF("SASL()") + op->orb_tmp_mech.bv_len;
+                       bv.bv_len = STRLENOF("SASL()") + op->orb_mech.bv_len;
                        bv.bv_val = op->o_tmpalloc( bv.bv_len + 1, op->o_tmpmemctx );
                        ptr = lutil_strcopy( bv.bv_val, "SASL(" );
-                       ptr = lutil_strcopy( ptr, op->orb_tmp_mech.bv_val );
+                       ptr = lutil_strcopy( ptr, op->orb_mech.bv_val );
                        *ptr++ = ')';
                        *ptr = '\0';
                        attr_merge_one( e, ad_reqMethod, &bv, NULL );
@@ -1386,7 +1710,7 @@ accesslog_unbind( Operation *op, SlapReply *rs )
                if ( !( li->li_ops & LOG_OP_UNBIND ))
                        return SLAP_CB_CONTINUE;
 
-               e = accesslog_entry( op, LOG_EN_UNBIND, &op2 );
+               e = accesslog_entry( op, rs, LOG_EN_UNBIND, &op2 );
                op2.o_hdr = op->o_hdr;
                op2.o_tag = LDAP_REQ_ADD;
                op2.o_bd = li->li_db;
@@ -1421,7 +1745,7 @@ accesslog_abandon( Operation *op, SlapReply *rs )
        if ( !op->o_time || !( li->li_ops & LOG_OP_ABANDON ))
                return SLAP_CB_CONTINUE;
 
-       e = accesslog_entry( op, LOG_EN_ABANDON, &op2 );
+       e = accesslog_entry( op, rs, LOG_EN_ABANDON, &op2 );
        bv.bv_val = buf;
        bv.bv_len = sprintf( buf, "%d", op->orn_msgid );
        attr_merge_one( e, ad_reqId, &bv, NULL );
@@ -1477,7 +1801,8 @@ static slap_overinst accesslog;
 
 static int
 accesslog_db_init(
-       BackendDB *be
+       BackendDB *be,
+       ConfigReply *cr
 )
 {
        slap_overinst *on = (slap_overinst *)be->bd_info;
@@ -1491,7 +1816,8 @@ accesslog_db_init(
 
 static int
 accesslog_db_destroy(
-       BackendDB *be
+       BackendDB *be,
+       ConfigReply *cr
 )
 {
        slap_overinst *on = (slap_overinst *)be->bd_info;
@@ -1522,12 +1848,13 @@ accesslog_db_root(
 
        Connection conn = {0};
        OperationBuffer opbuf;
-       Operation *op = (Operation *) &opbuf;
+       Operation *op;
 
        Entry *e;
        int rc;
 
-       connection_fake_init( &conn, op, ctx );
+       connection_fake_init( &conn, &opbuf, ctx );
+       op = &opbuf.ob_op;
        op->o_bd = li->li_db;
        op->o_dn = li->li_db->be_rootdn;
        op->o_ndn = li->li_db->be_rootndn;
@@ -1579,8 +1906,11 @@ accesslog_db_root(
 
                        a = attr_find( e_ctx->e_attrs, slap_schema.si_ad_contextCSN );
                        if ( a ) {
-                               attr_merge( e, slap_schema.si_ad_entryCSN, a->a_vals, NULL );
-                               attr_merge( e, a->a_desc, a->a_vals, NULL );
+                               /* FIXME: contextCSN could have multiple values!
+                                * should select the one with the server's SID */
+                               attr_merge_one( e, slap_schema.si_ad_entryCSN,
+                                       &a->a_vals[0], &a->a_nvals[0] );
+                               attr_merge( e, a->a_desc, a->a_vals, a->a_nvals );
                        }
                        be_entry_release_rw( op, e_ctx, 0 );
                }
@@ -1606,7 +1936,8 @@ accesslog_db_root(
 
 static int
 accesslog_db_open(
-       BackendDB *be
+       BackendDB *be,
+       ConfigReply *cr
 )
 {
        slap_overinst *on = (slap_overinst *)be->bd_info;
@@ -1614,7 +1945,7 @@ accesslog_db_open(
 
 
        if ( !BER_BVISEMPTY( &li->li_db_suffix )) {
-               li->li_db = select_backend( &li->li_db_suffix, 0, 0 );
+               li->li_db = select_backend( &li->li_db_suffix, 0 );
                ch_free( li->li_db_suffix.bv_val );
                BER_BVZERO( &li->li_db_suffix );
        }
@@ -1666,23 +1997,51 @@ int accesslog_initialize()
        if ( rc ) return rc;
 
        /* log schema integration */
+       for ( i=0; lsyntaxes[i].oid; i++ ) {
+               int code;
+
+               code = register_syntax( &lsyntaxes[ i ].syn );
+               if ( code != 0 ) {
+                       Debug( LDAP_DEBUG_ANY,
+                               "accesslog_init: register_syntax failed\n",
+                               0, 0, 0 );
+                       return code;
+               }
+
+               if ( lsyntaxes[i].mrs != NULL ) {
+                       code = mr_make_syntax_compat_with_mrs(
+                               lsyntaxes[i].oid, lsyntaxes[i].mrs );
+                       if ( code < 0 ) {
+                               Debug( LDAP_DEBUG_ANY,
+                                       "accesslog_init: "
+                                       "mr_make_syntax_compat_with_mrs "
+                                       "failed\n",
+                                       0, 0, 0 );
+                               return code;
+                       }
+               }
+       }
+
        for ( i=0; lattrs[i].at; i++ ) {
                int code;
 
                code = register_at( lattrs[i].at, lattrs[i].ad, 0 );
                if ( code ) {
                        Debug( LDAP_DEBUG_ANY,
-                               "accesslog_init: register_at failed\n", 0, 0, 0 );
+                               "accesslog_init: register_at failed\n",
+                               0, 0, 0 );
                        return -1;
                }
        }
+
        for ( i=0; locs[i].ot; i++ ) {
                int code;
 
                code = register_oc( locs[i].ot, locs[i].oc, 0 );
                if ( code ) {
                        Debug( LDAP_DEBUG_ANY,
-                               "accesslog_init: register_oc failed\n", 0, 0, 0 );
+                               "accesslog_init: register_oc failed\n",
+                               0, 0, 0 );
                        return -1;
                }
        }
index 601c733efd6769a1a653eaec8dc82e59718a0734..8879ee39f409df138061db0efde52dab2e503513 100644 (file)
@@ -184,7 +184,8 @@ static slap_overinst auditlog;
 
 static int
 auditlog_db_init(
-       BackendDB *be
+       BackendDB *be,
+       ConfigReply *cr
 )
 {
        slap_overinst *on = (slap_overinst *)be->bd_info;
@@ -197,7 +198,8 @@ auditlog_db_init(
 
 static int
 auditlog_db_close(
-       BackendDB *be
+       BackendDB *be,
+       ConfigReply *cr
 )
 {
        slap_overinst *on = (slap_overinst *)be->bd_info;
@@ -210,7 +212,8 @@ auditlog_db_close(
 
 static int
 auditlog_db_destroy(
-       BackendDB *be
+       BackendDB *be,
+       ConfigReply *cr
 )
 {
        slap_overinst *on = (slap_overinst *)be->bd_info;
index 5fd2cb8325cd47b0148a52db5706594fc2147053..d78f32b54a447b7594d787cb6660ba1a62680484 100644 (file)
@@ -29,7 +29,7 @@
 #include <ac/socket.h>
 
 #include "slap.h"
-
+#include "config.h"
 
 /* This is a cheap hack to implement a collective attribute.
  *
@@ -46,6 +46,124 @@ typedef struct collect_info {
        AttributeDescription *ci_ad;
 } collect_info;
 
+static int
+collect_cf( ConfigArgs *c )
+{
+       slap_overinst *on = (slap_overinst *)c->bi;
+       int rc = 1;
+
+       switch( c->op ) {
+       case SLAP_CONFIG_EMIT:
+               {
+               collect_info *ci;
+               for ( ci = on->on_bi.bi_private; ci; ci = ci->ci_next ) {
+                       struct berval bv;
+
+                       bv.bv_len = ci->ci_dn.bv_len + 3 +
+                               ci->ci_ad->ad_cname.bv_len;
+                       bv.bv_val = ch_malloc( bv.bv_len + 1 );
+                       sprintf( bv.bv_val, "\"%s\" %s", ci->ci_dn.bv_val,
+                               ci->ci_ad->ad_cname.bv_val );
+                       ber_bvarray_add( &c->rvalue_vals, &bv );
+                       rc = 0;
+               }
+               }
+               break;
+       case LDAP_MOD_DELETE:
+               if ( c->valx == -1 ) {
+               /* Delete entire attribute */
+                       collect_info *ci;
+                       while (( ci = on->on_bi.bi_private )) {
+                               on->on_bi.bi_private = ci->ci_next;
+                               ch_free( ci->ci_dn.bv_val );
+                               ch_free( ci );
+                       }
+               } else {
+               /* Delete just one value */
+                       collect_info **cip, *ci;
+                       int i;
+                       cip = (collect_info **)&on->on_bi.bi_private;
+                       for ( i=0; i <= c->valx; i++, cip = &ci->ci_next ) ci = *cip;
+                       *cip = ci->ci_next;
+                       ch_free( ci->ci_dn.bv_val );
+                       ch_free( ci );
+               }
+               rc = 0;
+               break;
+       case SLAP_CONFIG_ADD:
+       case LDAP_MOD_ADD:
+               {
+               collect_info *ci;
+               struct berval bv, dn;
+               const char *text;
+               AttributeDescription *ad = NULL;
+
+               ber_str2bv( c->argv[1], 0, 0, &bv );
+               if ( dnNormalize( 0, NULL, NULL, &bv, &dn, NULL ) ) {
+                       snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s invalid DN: \"%s\"",
+                               c->argv[0], c->argv[1] );
+                       Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
+                               "%s: %s\n", c->log, c->cr_msg, 0 );
+                       return ARG_BAD_CONF;
+               }
+               if ( slap_str2ad( c->argv[2], &ad, &text ) ) {
+                       snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s attribute description unknown: \"%s\"",
+                               c->argv[0], c->argv[2] );
+                       Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
+                               "%s: %s\n", c->log, c->cr_msg, 0 );
+                       return ARG_BAD_CONF;
+               }
+
+               /* The on->on_bi.bi_private pointer can be used for
+                * anything this instance of the overlay needs.
+                */
+               ci = ch_malloc( sizeof( collect_info ));
+               ci->ci_ad = ad;
+               ci->ci_dn = dn;
+               ci->ci_next = on->on_bi.bi_private;
+               on->on_bi.bi_private = ci;
+               rc = 0;
+               }
+       }
+       return rc;
+}
+
+static ConfigTable collectcfg[] = {
+       { "collectinfo", "dn> <attribute", 3, 3, 0,
+         ARG_MAGIC, collect_cf,
+         "( OLcfgOvAt:19.1 NAME 'olcCollectInfo' "
+         "DESC 'DN of entry and attribute to distribute' "
+         "SYNTAX OMsDirectoryString )", NULL, NULL },
+       { NULL, NULL, 0, 0, 0, ARG_IGNORED }
+};
+
+static ConfigOCs collectocs[] = {
+       { "( OLcfgOvOc:19.1 "
+         "NAME 'olcCollectConfig' "
+         "DESC 'Collective Attribute configuration' "
+         "SUP olcOverlayConfig "
+         "MAY olcCollectInfo )",
+         Cft_Overlay, collectcfg },
+       { NULL, 0, NULL }
+};
+
+static int
+collect_destroy(
+       BackendDB *be,
+       ConfigReply *cr
+)
+{
+       slap_overinst *on = (slap_overinst *)be->bd_info;
+       collect_info *ci;
+
+       while (( ci = on->on_bi.bi_private )) {
+               on->on_bi.bi_private = ci->ci_next;
+               ch_free( ci->ci_dn.bv_val );
+               ch_free( ci );
+       }
+       return 0;
+}
+
 static int
 collect_response( Operation *op, SlapReply *rs )
 {
@@ -56,7 +174,6 @@ collect_response( Operation *op, SlapReply *rs )
         * a search entry
         */
        if ( ci && rs->sr_type == REP_SEARCH ) {
-               Entry *new = NULL;
                int rc;
 
                op->o_bd->bd_info = (BackendInfo *)on->on_info;
@@ -65,9 +182,8 @@ collect_response( Operation *op, SlapReply *rs )
                        BerVarray vals = NULL;
 
                        /* Is our configured entry an ancestor of this one? */
-                       rc = rs->sr_entry->e_nname.bv_len - ci->ci_dn.bv_len;
-                       if ( rc < 1 || strcmp( rs->sr_entry->e_nname.bv_val + rc,
-                               ci->ci_dn.bv_val )) continue;
+                       if ( !dnIsSuffix( &rs->sr_entry->e_nname, &ci->ci_dn ))
+                               continue;
 
                        /* Extract the values of the desired attribute from
                         * the ancestor entry
@@ -82,82 +198,33 @@ collect_response( Operation *op, SlapReply *rs )
                                 * don't modify it directly. Make a copy and
                                 * work with that instead.
                                 */
-                               if ( !new ) {
-                                       new = entry_dup( rs->sr_entry );
+                               if ( !( rs->sr_flags & REP_ENTRY_MODIFIABLE )) {
+                                       rs->sr_entry = entry_dup( rs->sr_entry );
+                                       rs->sr_flags |= REP_ENTRY_MODIFIABLE |
+                                               REP_ENTRY_MUSTBEFREED;
                                }
-                               attr_merge( new, ci->ci_ad, vals, NULL );
+                               attr_merge( rs->sr_entry, ci->ci_ad, vals, NULL );
                                ber_bvarray_free_x( vals, op->o_tmpmemctx );
                        }
                }
-
-               if ( new ) {
-                       rs->sr_entry = new;
-                       rs->sr_flags |= REP_ENTRY_MUSTBEFREED;
-               }
        }
        /* Default is to just fall through to the normal processing */
        return SLAP_CB_CONTINUE;
 }
 
-static int collect_config(
-    BackendDB  *be,
-    const char *fname,
-    int                lineno,
-    int                argc,
-    char       **argv
-)
-{
-       slap_overinst *on = (slap_overinst *) be->bd_info;
-       AttributeDescription *ad = NULL;
-
-       /* The config syntax is "collectinfo <dn> <attribute-description>"
-        * and only one directive may be specified per overlay instance.
-        */
-
-       if ( strcasecmp( argv[0], "collectinfo" ) == 0 ) {
-               collect_info *ci;
-               struct berval bv, dn;
-               const char *text;
-               if ( argc != 3 ) {
-                       Debug( LDAP_DEBUG_ANY,
-               "%s: line %d: argument missing in \"collectinfo <dn> <attribute-description>\" line.\n",
-                       fname, lineno, 0 );
-                       return( 1 );
-               }
-               ber_str2bv( argv[1], 0, 0, &bv );
-               if ( dnNormalize( 0, NULL, NULL, &bv, &dn, NULL ) ) {
-                       Debug( LDAP_DEBUG_ANY,
-               "%s: line %d: invalid DN in \"collectinfo\" line: %s.\n",
-                       fname, lineno, text );
-                       return( 1 );
-               }
-               if ( slap_str2ad( argv[2], &ad, &text ) ) {
-                       Debug( LDAP_DEBUG_ANY,
-               "%s: line %d: attribute description unknown in \"collectinfo\" line: %s.\n",
-                       fname, lineno, text );
-                       return( 1 );
-               }
-
-               /* The on->on_bi.bi_private pointer can be used for
-                * anything this instance of the overlay needs.
-                */
-               ci = ch_malloc( sizeof( collect_info ));
-               ci->ci_ad = ad;
-               ci->ci_dn = dn;
-               ci->ci_next = on->on_bi.bi_private;
-               on->on_bi.bi_private = ci;
-               return 0;
-       }
-       return SLAP_CONF_UNKNOWN;
-}
-
 static slap_overinst collect;
 
 int collect_initialize() {
+       int code;
+
        collect.on_bi.bi_type = "collect";
-       collect.on_bi.bi_db_config = collect_config;
+       collect.on_bi.bi_db_destroy = collect_destroy;
        collect.on_response = collect_response;
 
+       collect.on_bi.bi_cf_ocs = collectocs;
+       code = config_register_schema( collectcfg, collectocs );
+       if ( code ) return code;
+
        return overlay_register( &collect );
 }
 
index c86c11a53a2e141698e1d8c0a5666c747696674e..aed82a66208e7b0352df91480926311baee2de35 100644 (file)
@@ -168,10 +168,10 @@ constraint_cf_gen( ConfigArgs *c )
             switch (c->type) {
                 case CONSTRAINT_ATTRIBUTE:
                     if ( slap_str2ad( c->argv[1], &ap.ap, &text ) ) {
-                                               snprintf( c->msg, sizeof( c->msg ),
+                                               snprintf( c->cr_msg, sizeof( c->cr_msg ),
                                                        "%s <%s>: %s\n", c->argv[0], c->argv[1], text );
                         Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
-                               "%s: %s\n", c->log, c->msg, 0 );
+                               "%s: %s\n", c->log, c->cr_msg, 0 );
                         return( ARG_BAD_CONF );
                     }
 
@@ -185,21 +185,21 @@ constraint_cf_gen( ConfigArgs *c )
                             
                             regerror( err, ap.re, errmsg, sizeof(errmsg) );
                             ch_free(ap.re);
-                                                       snprintf( c->msg, sizeof( c->msg ),
+                                                       snprintf( c->cr_msg, sizeof( c->cr_msg ),
                                    "%s %s: Illegal regular expression \"%s\": Error %s",
                                    c->argv[0], c->argv[1], c->argv[3], errmsg);
                             Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
-                                                                       "%s: %s\n", c->log, c->msg, 0 );
+                                                                       "%s: %s\n", c->log, c->cr_msg, 0 );
                             ap.re = NULL;
                             return( ARG_BAD_CONF );
                         }
                         ap.re_str = ch_strdup( c->argv[3] );
                     } else {
-                                               snprintf( c->msg, sizeof( c->msg ),
+                                               snprintf( c->cr_msg, sizeof( c->cr_msg ),
                                "%s %s: Unknown constraint type: %s",
                                c->argv[0], c->argv[1], c->argv[2] );
                         Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
-                               "%s: %s\n", c->log, c->msg, 0 );
+                               "%s: %s\n", c->log, c->cr_msg, 0 );
                         return ( ARG_BAD_CONF );
                     }
                     
@@ -237,14 +237,14 @@ constraint_violation( constraint *c, struct berval *bv )
 }
 
 static char *
-print_message( const char *fmt, AttributeDescription *a )
+print_message( const char *errtext, AttributeDescription *a )
 {
     char *ret;
     int sz;
     
-    sz = strlen(fmt) + a->ad_cname.bv_len + 1;
+    sz = strlen(errtext) + sizeof(" on ") + a->ad_cname.bv_len;
     ret = ch_malloc(sz);
-    snprintf( ret, sz, fmt, a->ad_cname.bv_val );
+    snprintf( ret, sz, "%s on %s", errtext, a->ad_cname.bv_val );
     return ret;
 }
 
@@ -256,7 +256,7 @@ constraint_add( Operation *op, SlapReply *rs )
     constraint *c = on->on_bi.bi_private, *cp;
     BerVarray b = NULL;
     int i;
-    const char *rsv = "add breaks regular expression constraint on %s";
+    const char *rsv = "add breaks regular expression constraint";
     char *msg;
     
     if ((a = op->ora_e->e_attrs) == NULL) {
@@ -301,7 +301,7 @@ constraint_modify( Operation *op, SlapReply *rs )
     Modifications *m;
     BerVarray b = NULL;
     int i;
-    const char *rsv = "modify breaks regular expression constraint on %s";
+    const char *rsv = "modify breaks regular expression constraint";
     char *msg;
     
     if ((m = op->orm_modlist) == NULL) {
@@ -343,8 +343,8 @@ constraint_modify( Operation *op, SlapReply *rs )
 
 static int
 constraint_close(
-    BackendDB *be
-    )
+       BackendDB *be,
+       ConfigReply *cr )
 {
     slap_overinst *on = (slap_overinst *) be->bd_info;
     constraint *ap, *a2;
index 80999f6381fc9a816ba9a20aaf6ed30c19f17ae9..278658eb58f93c214c7efad0aa77d2507effee16 100644 (file)
@@ -123,7 +123,7 @@ dds_expire( void *ctx, dds_info_t *di )
        Connection      conn = { 0 };
        OperationBuffer opbuf;
        Operation       *op;
-       slap_callback   sc = { 0 }, sc2 = { 0 };
+       slap_callback   sc = { 0 };
        dds_cb_t        dc = { 0 };
        dds_expire_t    *de = NULL, **dep;
        SlapReply       rs = { REP_RESULT };
@@ -134,13 +134,13 @@ dds_expire( void *ctx, dds_info_t *di )
 
        int             ndeletes, ntotdeletes;
 
-       op = (Operation *)&opbuf;
-       connection_fake_init( &conn, op, ctx );
+       connection_fake_init( &conn, &opbuf, ctx );
+       op = &opbuf.ob_op;
 
        op->o_tag = LDAP_REQ_SEARCH;
        memset( &op->oq_search, 0, sizeof( op->oq_search ) );
 
-       op->o_bd = select_backend( &di->di_nsuffix[ 0 ], 0, 0 );
+       op->o_bd = select_backend( &di->di_nsuffix[ 0 ], 0 );
 
        op->o_req_dn = op->o_bd->be_suffix[ 0 ];
        op->o_req_ndn = op->o_bd->be_nsuffix[ 0 ];
@@ -193,10 +193,8 @@ done_search:;
 
        op->o_tag = LDAP_REQ_DELETE;
        op->o_callback = &sc;
-       sc.sc_response = slap_replog_cb;
+       sc.sc_response = slap_null_cb;
        sc.sc_private = NULL;
-       sc.sc_next = &sc2;
-       sc2.sc_response = slap_null_cb;
 
        for ( ntotdeletes = 0, ndeletes = 1; dc.dc_ndnlist != NULL  && ndeletes > 0; ) {
                ndeletes = 0;
@@ -950,7 +948,7 @@ slap_parse_refresh(
 
        tag = ber_peek_tag( ber, &len );
 
-       if ( len != 0 ) {
+       if ( tag != LBER_DEFAULT || len != 0 ) {
 decoding_error:;
                Log1( LDAP_DEBUG_TRACE, LDAP_LEVEL_ERR,
                        "slap_parse_refresh: decoding error, len=%ld\n",
@@ -989,7 +987,6 @@ dds_op_extended( Operation *op, SlapReply *rs )
                SlapReply       rs2 = { REP_RESULT };
                Operation       op2 = *op;
                slap_callback   sc = { 0 };
-               slap_callback   sc2 = { 0 };
                Modifications   ttlmod = { { 0 } };
                struct berval   ttlvalues[ 2 ];
                char            ttlbuf[] = "31557600";
@@ -1082,9 +1079,7 @@ dds_op_extended( Operation *op, SlapReply *rs )
                op2.o_bd = &db;
                db.bd_info = (BackendInfo *)on->on_info;
                op2.o_callback = &sc;
-               sc.sc_response = slap_replog_cb;
-               sc.sc_next = &sc2;
-               sc2.sc_response = slap_null_cb;
+               sc.sc_response = slap_null_cb;
                op2.o_relax = SLAP_CONTROL_CRITICAL;
                op2.orm_modlist = &ttlmod;
 
@@ -1368,20 +1363,20 @@ dds_cfgen( ConfigArgs *c )
 
        case DDS_MAXTTL:
                if ( lutil_parse_time( c->argv[ 1 ], &t ) != 0 ) {
-                       snprintf( c->msg, sizeof( c->msg),
+                       snprintf( c->cr_msg, sizeof( c->cr_msg),
                                "DDS unable to parse dds-max-ttl \"%s\"",
                                c->argv[ 1 ] );
                        Log2( LDAP_DEBUG_ANY, LDAP_LEVEL_ERR,
-                               "%s: %s.\n", c->log, c->msg );
+                               "%s: %s.\n", c->log, c->cr_msg );
                        return 1;
                }
 
                if ( t < DDS_RF2589_DEFAULT_TTL || t > DDS_RF2589_MAX_TTL ) {
-                       snprintf( c->msg, sizeof( c->msg ),
+                       snprintf( c->cr_msg, sizeof( c->cr_msg ),
                                "DDS invalid dds-max-ttl=%ld; must be between %d and %d",
                                t, DDS_RF2589_DEFAULT_TTL, DDS_RF2589_MAX_TTL );
                        Log2( LDAP_DEBUG_ANY, LDAP_LEVEL_ERR,
-                               "%s: %s.\n", c->log, c->msg );
+                               "%s: %s.\n", c->log, c->cr_msg );
                        return 1;
                }
 
@@ -1390,20 +1385,20 @@ dds_cfgen( ConfigArgs *c )
 
        case DDS_MINTTL:
                if ( lutil_parse_time( c->argv[ 1 ], &t ) != 0 ) {
-                       snprintf( c->msg, sizeof( c->msg),
+                       snprintf( c->cr_msg, sizeof( c->cr_msg),
                                "DDS unable to parse dds-min-ttl \"%s\"",
                                c->argv[ 1 ] );
                        Log2( LDAP_DEBUG_ANY, LDAP_LEVEL_ERR,
-                               "%s: %s.\n", c->log, c->msg );
+                               "%s: %s.\n", c->log, c->cr_msg );
                        return 1;
                }
 
                if ( t < 0 || t > DDS_RF2589_MAX_TTL ) {
-                       snprintf( c->msg, sizeof( c->msg ),
+                       snprintf( c->cr_msg, sizeof( c->cr_msg ),
                                "DDS invalid dds-min-ttl=%ld",
                                t );
                        Log2( LDAP_DEBUG_ANY, LDAP_LEVEL_ERR,
-                               "%s: %s.\n", c->log, c->msg );
+                               "%s: %s.\n", c->log, c->cr_msg );
                        return 1;
                }
 
@@ -1417,20 +1412,20 @@ dds_cfgen( ConfigArgs *c )
 
        case DDS_DEFAULTTTL:
                if ( lutil_parse_time( c->argv[ 1 ], &t ) != 0 ) {
-                       snprintf( c->msg, sizeof( c->msg),
+                       snprintf( c->cr_msg, sizeof( c->cr_msg),
                                "DDS unable to parse dds-default-ttl \"%s\"",
                                c->argv[ 1 ] );
                        Log2( LDAP_DEBUG_ANY, LDAP_LEVEL_ERR,
-                               "%s: %s.\n", c->log, c->msg );
+                               "%s: %s.\n", c->log, c->cr_msg );
                        return 1;
                }
 
                if ( t < 0 || t > DDS_RF2589_MAX_TTL ) {
-                       snprintf( c->msg, sizeof( c->msg ),
+                       snprintf( c->cr_msg, sizeof( c->cr_msg ),
                                "DDS invalid dds-default-ttl=%ld",
                                t );
                        Log2( LDAP_DEBUG_ANY, LDAP_LEVEL_ERR,
-                               "%s: %s.\n", c->log, c->msg );
+                               "%s: %s.\n", c->log, c->cr_msg );
                        return 1;
                }
 
@@ -1444,20 +1439,20 @@ dds_cfgen( ConfigArgs *c )
 
        case DDS_INTERVAL:
                if ( lutil_parse_time( c->argv[ 1 ], &t ) != 0 ) {
-                       snprintf( c->msg, sizeof( c->msg),
+                       snprintf( c->cr_msg, sizeof( c->cr_msg),
                                "DDS unable to parse dds-interval \"%s\"",
                                c->argv[ 1 ] );
                        Log2( LDAP_DEBUG_ANY, LDAP_LEVEL_ERR,
-                               "%s: %s.\n", c->log, c->msg );
+                               "%s: %s.\n", c->log, c->cr_msg );
                        return 1;
                }
 
                if ( t <= 0 ) {
-                       snprintf( c->msg, sizeof( c->msg ),
+                       snprintf( c->cr_msg, sizeof( c->cr_msg ),
                                "DDS invalid dds-interval=%ld",
                                t );
                        Log2( LDAP_DEBUG_ANY, LDAP_LEVEL_ERR,
-                               "%s: %s.\n", c->log, c->msg );
+                               "%s: %s.\n", c->log, c->cr_msg );
                        return 1;
                }
 
@@ -1481,20 +1476,20 @@ dds_cfgen( ConfigArgs *c )
 
        case DDS_TOLERANCE:
                if ( lutil_parse_time( c->argv[ 1 ], &t ) != 0 ) {
-                       snprintf( c->msg, sizeof( c->msg),
+                       snprintf( c->cr_msg, sizeof( c->cr_msg),
                                "DDS unable to parse dds-tolerance \"%s\"",
                                c->argv[ 1 ] );
                        Log2( LDAP_DEBUG_ANY, LDAP_LEVEL_ERR,
-                               "%s: %s.\n", c->log, c->msg );
+                               "%s: %s.\n", c->log, c->cr_msg );
                        return 1;
                }
 
                if ( t < 0 || t > DDS_RF2589_MAX_TTL ) {
-                       snprintf( c->msg, sizeof( c->msg ),
+                       snprintf( c->cr_msg, sizeof( c->cr_msg ),
                                "DDS invalid dds-tolerance=%ld",
                                t );
                        Log2( LDAP_DEBUG_ANY, LDAP_LEVEL_ERR,
-                               "%s: %s.\n", c->log, c->msg );
+                               "%s: %s.\n", c->log, c->cr_msg );
                        return 1;
                }
 
@@ -1503,10 +1498,10 @@ dds_cfgen( ConfigArgs *c )
 
        case DDS_MAXDYNAMICOBJS:
                if ( c->value_int < 0 ) {
-                       snprintf( c->msg, sizeof( c->msg ),
+                       snprintf( c->cr_msg, sizeof( c->cr_msg ),
                                "DDS invalid dds-max-dynamicObjects=%d", c->value_int );
                        Log2( LDAP_DEBUG_ANY, LDAP_LEVEL_ERR,
-                               "%s: %s.\n", c->log, c->msg );
+                               "%s: %s.\n", c->log, c->cr_msg );
                        return 1;
                }
                di->di_max_dynamicObjects = c->value_int;
@@ -1522,7 +1517,8 @@ dds_cfgen( ConfigArgs *c )
 
 static int
 dds_db_init(
-       BackendDB       *be )
+       BackendDB       *be,
+       ConfigReply     *cr)
 {
        slap_overinst   *on = (slap_overinst *)be->bd_info;
        dds_info_t      *di;
@@ -1611,8 +1607,8 @@ dds_count( void *ctx, BackendDB *be )
        slap_callback   sc = { 0 };
        SlapReply       rs = { REP_RESULT };
 
-       op = (Operation *)&opbuf;
-       connection_fake_init( &conn, op, ctx );
+       connection_fake_init( &conn, &opbuf, ctx );
+       op = &opbuf.ob_op;
 
        op->o_tag = LDAP_REQ_SEARCH;
        memset( &op->oq_search, 0, sizeof( op->oq_search ) );
@@ -1671,7 +1667,8 @@ done_search:;
 
 static int
 dds_db_open(
-       BackendDB       *be )
+       BackendDB       *be,
+       ConfigReply     *cr )
 {
        slap_overinst   *on = (slap_overinst *)be->bd_info;
        dds_info_t      *di = on->on_bi.bi_private;
@@ -1736,7 +1733,8 @@ done:;
 
 static int
 dds_db_close(
-       BackendDB       *be )
+       BackendDB       *be,
+       ConfigReply     *cr )
 {
        slap_overinst   *on = (slap_overinst *)be->bd_info;
        dds_info_t      *di = on->on_bi.bi_private;
@@ -1758,7 +1756,8 @@ dds_db_close(
 
 static int
 dds_db_destroy(
-       BackendDB       *be )
+       BackendDB       *be,
+       ConfigReply     *cr )
 {
        slap_overinst   *on = (slap_overinst *)be->bd_info;
        dds_info_t      *di = on->on_bi.bi_private;
@@ -1790,7 +1789,7 @@ slap_exop_refresh(
                op->o_log_prefix, op->o_req_ndn.bv_val );
        op->o_req_dn = op->o_req_ndn;
 
-       op->o_bd = select_backend( &op->o_req_ndn, 0, 0 );
+       op->o_bd = select_backend( &op->o_req_ndn, 0 );
        if ( !SLAP_DYNAMIC( op->o_bd ) ) {
                send_ldap_error( op, rs, LDAP_UNAVAILABLE_CRITICAL_EXTENSION,
                        "backend does not support dynamic directory services" );
index 6b28ecc8c5590aa9ae2adb1b80fe3ed7c966479a..fdc8d70d9b0cf0da1d0e9d906879605fc24377fe 100644 (file)
@@ -28,7 +28,9 @@
 #include <ac/string.h>
 #include <ac/socket.h>
 
+#include "lutil.h"
 #include "slap.h"
+#include "config.h"
 
 /* This overlay extends the Compare operation to detect members of a
  * dynamic group. It has no effect on any other operations. It must
@@ -43,6 +45,100 @@ typedef struct adpair {
        AttributeDescription *ap_uri;
 } adpair;
 
+static int dgroup_cf( ConfigArgs *c )
+{
+       slap_overinst *on = (slap_overinst *)c->bi;
+       int rc = 1;
+
+       switch( c->op ) {
+       case SLAP_CONFIG_EMIT:
+               {
+               adpair *ap;
+               for ( ap = on->on_bi.bi_private; ap; ap = ap->ap_next ) {
+                       struct berval bv;
+                       char *ptr;
+                       bv.bv_len = ap->ap_mem->ad_cname.bv_len + 1 +
+                               ap->ap_uri->ad_cname.bv_len;
+                       bv.bv_val = ch_malloc( bv.bv_len + 1 );
+                       ptr = lutil_strcopy( bv.bv_val, ap->ap_mem->ad_cname.bv_val );
+                       *ptr++ = ' ';
+                       strcpy( ptr, ap->ap_uri->ad_cname.bv_val );
+                       ber_bvarray_add( &c->rvalue_vals, &bv );
+                       rc = 0;
+               }
+               }
+               break;
+       case LDAP_MOD_DELETE:
+               if ( c->valx == -1 ) {
+                       adpair *ap;
+                       while (( ap = on->on_bi.bi_private )) {
+                               on->on_bi.bi_private = ap->ap_next;
+                               ch_free( ap );
+                       }
+               } else {
+                       adpair **app, *ap;
+                       int i;
+                       app = (adpair **)&on->on_bi.bi_private;
+                       for (i=0; i<=c->valx; i++, app = &ap->ap_next) {
+                               ap = *app;
+                       }
+                       *app = ap->ap_next;
+                       ch_free( ap );
+               }
+               rc = 0;
+               break;
+       case SLAP_CONFIG_ADD:
+       case LDAP_MOD_ADD:
+               {
+               adpair ap = { NULL, NULL, NULL }, *a2;
+               const char *text;
+               if ( slap_str2ad( c->argv[1], &ap.ap_mem, &text ) ) {
+                       snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s attribute description unknown: \"%s\"",
+                               c->argv[0], c->argv[1] );
+                       Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
+                               "%s: %s\n", c->log, c->cr_msg, 0 );
+                       return ARG_BAD_CONF;
+               }
+               if ( slap_str2ad( c->argv[2], &ap.ap_uri, &text ) ) {
+                       snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s attribute description unknown: \"%s\"",
+                               c->argv[0], c->argv[2] );
+                       Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
+                               "%s: %s\n", c->log, c->cr_msg, 0 );
+                       return ARG_BAD_CONF;
+               }
+               /* The on->on_bi.bi_private pointer can be used for
+                * anything this instance of the overlay needs.
+                */
+               a2 = ch_malloc( sizeof(adpair) );
+               a2->ap_next = on->on_bi.bi_private;
+               a2->ap_mem = ap.ap_mem;
+               a2->ap_uri = ap.ap_uri;
+               on->on_bi.bi_private = a2;
+               rc = 0;
+               }
+       }
+       return rc;
+}
+
+static ConfigTable dgroupcfg[] = {
+       { "attrpair", "member-attribute> <URL-attribute", 3, 3, 0,
+         ARG_MAGIC, dgroup_cf,
+         "( OLcfgOvAt:17.1 NAME 'olcDGAttrPair' "
+         "DESC 'Member and MemberURL attribute pair' "
+         "SYNTAX OMsDirectoryString )", NULL, NULL },
+       { NULL, NULL, 0, 0, 0, ARG_IGNORED }
+};
+
+static ConfigOCs dgroupocs[] = {
+       { "( OLcfgOvOc:17.1 "
+         "NAME 'olcDGConfig' "
+         "DESC 'Dynamic Group configuration' "
+         "SUP olcOverlayConfig "
+         "MAY olcDGAttrPair )",
+         Cft_Overlay, dgroupcfg },
+       { NULL, 0, NULL }
+};
+
 static int
 dyngroup_response( Operation *op, SlapReply *rs )
 {
@@ -84,56 +180,10 @@ dyngroup_response( Operation *op, SlapReply *rs )
        return SLAP_CB_CONTINUE;
 }
 
-static int dyngroup_config(
-    BackendDB  *be,
-    const char *fname,
-    int                lineno,
-    int                argc,
-    char       **argv
-)
-{
-       slap_overinst *on = (slap_overinst *) be->bd_info;
-       adpair ap = { NULL, NULL, NULL }, *a2;
-
-       if ( strcasecmp( argv[0], "attrpair" ) == 0 ) {
-               const char *text;
-               if ( argc != 3 ) {
-                       Debug( LDAP_DEBUG_ANY, "%s: line %d: "
-                               "attribute description missing in "
-                               "\"attrpair <member-attribute> <URL-attribute>\" line.\n",
-                               fname, lineno, 0 );
-               return( 1 );
-               }
-               if ( slap_str2ad( argv[1], &ap.ap_mem, &text ) ) {
-                       Debug( LDAP_DEBUG_ANY, "%s: line %d: "
-                               "attribute description unknown \"attrpair\" line: %s.\n",
-                               fname, lineno, text );
-                       return( 1 );
-               }
-               if ( slap_str2ad( argv[2], &ap.ap_uri, &text ) ) {
-                       Debug( LDAP_DEBUG_ANY, "%s: line %d: "
-                               "attribute description unknown \"attrpair\" line: %s.\n",
-                               fname, lineno, text );
-                       return( 1 );
-               }
-               /* The on->on_bi.bi_private pointer can be used for
-                * anything this instance of the overlay needs.
-                */
-
-               a2 = ch_malloc( sizeof(adpair) );
-               a2->ap_next = on->on_bi.bi_private;
-               a2->ap_mem = ap.ap_mem;
-               a2->ap_uri = ap.ap_uri;
-               on->on_bi.bi_private = a2;
-       } else {
-               return SLAP_CONF_UNKNOWN;
-       }
-       return 0;
-}
-
 static int
 dyngroup_close(
-       BackendDB *be
+       BackendDB *be,
+       ConfigReply *cr
 )
 {
        slap_overinst *on = (slap_overinst *) be->bd_info;
@@ -154,11 +204,16 @@ static slap_overinst dyngroup;
  */
 
 int dyngroup_initialize() {
+       int code;
+
        dyngroup.on_bi.bi_type = "dyngroup";
-       dyngroup.on_bi.bi_db_config = dyngroup_config;
        dyngroup.on_bi.bi_db_close = dyngroup_close;
        dyngroup.on_response = dyngroup_response;
 
+       dyngroup.on_bi.bi_cf_ocs = dgroupocs;
+       code = config_register_schema( dgroupcfg, dgroupocs );
+       if ( code ) return code;
+
        return overlay_register( &dyngroup );
 }
 
index ff2d80b6e72a2ad6dd5f5bfe56c0a9611ebcaa66..50119eb7a16e393d690615d03b67daebcc4efdfb 100644 (file)
@@ -58,6 +58,8 @@ static AttributeName anlist_no_attrs[] = {
 static AttributeName *slap_anlist_no_attrs = anlist_no_attrs;
 #endif
 
+static AttributeDescription *ad_dgIdentity;
+
 typedef struct dynlist_info_t {
        ObjectClass             *dli_oc;
        AttributeDescription    *dli_ad;
@@ -67,13 +69,20 @@ typedef struct dynlist_info_t {
 } dynlist_info_t;
 
 static dynlist_info_t *
-dynlist_is_dynlist( Operation *op, SlapReply *rs )
+dynlist_is_dynlist_next( Operation *op, SlapReply *rs, dynlist_info_t *old_dli )
 {
        slap_overinst   *on = (slap_overinst *)op->o_bd->bd_info;
-       dynlist_info_t  *dli = (dynlist_info_t *)on->on_bi.bi_private;
+       dynlist_info_t  *dli;
 
        Attribute       *a;
 
+       if ( old_dli == NULL ) {
+               dli = (dynlist_info_t *)on->on_bi.bi_private;
+
+       } else {
+               dli = old_dli->dli_next;
+       }
+
        a = attrs_find( rs->sr_entry->e_attrs, slap_schema.si_ad_objectClass );
        if ( a == NULL ) {
                /* FIXME: objectClass must be present; for non-storage
@@ -306,9 +315,9 @@ done:;
 }
        
 static int
-dynlist_send_entry( Operation *op, SlapReply *rs, dynlist_info_t *dli )
+dynlist_prepare_entry( Operation *op, SlapReply *rs, dynlist_info_t *dli )
 {
-       Attribute       *a;
+       Attribute       *a, *id = NULL;
        slap_callback   cb;
        Operation       o = *op;
        SlapReply       r = { REP_SEARCH };
@@ -325,9 +334,19 @@ dynlist_send_entry( Operation *op, SlapReply *rs, dynlist_info_t *dli )
                return SLAP_CB_CONTINUE;
        }
 
-       e = entry_dup( rs->sr_entry );
+       if ( !( rs->sr_flags & REP_ENTRY_MODIFIABLE ) ) {
+               e = entry_dup( rs->sr_entry );
+       } else {
+               e = rs->sr_entry;
+       }
        e_flags = rs->sr_flags | ( REP_ENTRY_MODIFIABLE | REP_ENTRY_MUSTBEFREED );
 
+       if ( ad_dgIdentity && ( id = attrs_find( e->e_attrs, ad_dgIdentity ))) {
+               o.o_dn = id->a_vals[0];
+               o.o_ndn = id->a_nvals[0];
+               o.o_groups = NULL;
+       }
+
        dlc.dlc_e = e;
        dlc.dlc_dli = dli;
        cb.sc_private = &dlc;
@@ -368,7 +387,7 @@ dynlist_send_entry( Operation *op, SlapReply *rs, dynlist_info_t *dli )
 
                if ( lud->lud_host != NULL ) {
                        /* FIXME: host not allowed; reject as illegal? */
-                       Debug( LDAP_DEBUG_ANY, "dynlist_send_entry(\"%s\"): "
+                       Debug( LDAP_DEBUG_ANY, "dynlist_prepare_entry(\"%s\"): "
                                "illegal URI \"%s\"\n",
                                e->e_name.bv_val, url->bv_val, 0 );
                        goto cleanup;
@@ -466,7 +485,7 @@ dynlist_send_entry( Operation *op, SlapReply *rs, dynlist_info_t *dli )
                        goto cleanup;
                }
                
-               o.o_bd = select_backend( &o.o_req_ndn, 0, 1 );
+               o.o_bd = select_backend( &o.o_req_ndn, 1 );
                if ( o.o_bd && o.o_bd->be_search ) {
 #ifdef SLAP_OPATTRS
                        r.sr_attr_flags = slap_attr_flags( o.ors_attrs );
@@ -475,6 +494,9 @@ dynlist_send_entry( Operation *op, SlapReply *rs, dynlist_info_t *dli )
                }
 
 cleanup:;
+               if ( id ) {
+                       slap_op_groups_free( &o );
+               }
                if ( o.ors_filter ) {
                        filter_free_x( &o, o.ors_filter );
                }
@@ -489,7 +511,8 @@ cleanup:;
                if ( !BER_BVISNULL( &o.o_req_ndn ) ) {
                        op->o_tmpfree( o.o_req_ndn.bv_val, op->o_tmpmemctx );
                }
-               assert( o.ors_filterstr.bv_val != lud->lud_filter );
+               assert( BER_BVISNULL( &o.ors_filterstr )
+                       || o.ors_filterstr.bv_val != lud->lud_filter );
                op->o_tmpfree( o.ors_filterstr.bv_val, op->o_tmpmemctx );
                ldap_free_urldesc( lud );
        }
@@ -519,6 +542,8 @@ dynlist_compare( Operation *op, SlapReply *rs )
 {
        slap_overinst   *on = (slap_overinst *)op->o_bd->bd_info;
        dynlist_info_t  *dli = (dynlist_info_t *)on->on_bi.bi_private;
+       Operation o = *op;
+       Entry *e;
 
        for ( ; dli != NULL; dli = dli->dli_next ) {
                if ( op->oq_compare.rs_ava->aa_desc == dli->dli_member_ad ) {
@@ -526,12 +551,18 @@ dynlist_compare( Operation *op, SlapReply *rs )
                         * interested in. We'll use slapd's existing dyngroup
                         * evaluator to get the answer we want.
                         */
-                       int cache = op->o_do_not_cache;
-                               
-                       op->o_do_not_cache = 1;
-                       rs->sr_err = backend_group( op, NULL, &op->o_req_ndn,
-                               &op->oq_compare.rs_ava->aa_value, dli->dli_oc, dli->dli_ad );
-                       op->o_do_not_cache = cache;
+                       struct berval *id = NULL;
+
+                       o.o_do_not_cache = 1;
+
+                       if ( ad_dgIdentity && backend_attribute( &o, NULL, &o.o_req_ndn,
+                               ad_dgIdentity, &id, ACL_READ ) == LDAP_SUCCESS ) {
+                               o.o_dn = *id;
+                               o.o_ndn = *id;
+                               o.o_groups = NULL; /* authz changed, invalidate cached groups */
+                       }
+                       rs->sr_err = backend_group( &o, NULL, &o.o_req_ndn,
+                               &o.oq_compare.rs_ava->aa_value, dli->dli_oc, dli->dli_ad );
                        switch ( rs->sr_err ) {
                        case LDAP_SUCCESS:
                                rs->sr_err = LDAP_COMPARE_TRUE;
@@ -549,45 +580,35 @@ dynlist_compare( Operation *op, SlapReply *rs )
                                break;
                        }
 
+                       if ( id ) ber_bvarray_free_x( id, o.o_tmpmemctx );
+
                        return SLAP_CB_CONTINUE;
                }
        }
 
+       if ( overlay_entry_get_ov( &o, &o.o_req_ndn, NULL, NULL, 0, &e, on ) !=
+               LDAP_SUCCESS || e == NULL ) {
+               return SLAP_CB_CONTINUE;
+       }
+       if ( ad_dgIdentity ) {
+               Attribute *id = attrs_find( e->e_attrs, ad_dgIdentity );
+               if ( id ) {
+                       o.o_dn = id->a_vals[0];
+                       o.o_ndn = id->a_nvals[0];
+                       o.o_groups = NULL;
+               }
+       }
        dli = (dynlist_info_t *)on->on_bi.bi_private;
        for ( ; dli != NULL && rs->sr_err != LDAP_COMPARE_TRUE; dli = dli->dli_next ) {
                Attribute       *a;
                slap_callback   cb;
-               Operation       o = *op;
                SlapReply       r = { REP_SEARCH };
                AttributeName   an[2];
                int             rc;
                dynlist_sc_t    dlc = { 0 };
-               Entry           *e;
-
-               int cache = op->o_do_not_cache;
-               struct berval   op_dn = op->o_dn,
-                               op_ndn = op->o_ndn;
-               BackendDB       *op_bd = op->o_bd;
-
-               /* fetch the entry as rootdn (a hack to see if it exists
-                * and if it has the right objectClass) */
-               op->o_do_not_cache = 1;
-               op->o_dn = op->o_bd->be_rootdn;
-               op->o_ndn = op->o_bd->be_rootndn;
-               op->o_bd = select_backend( &op->o_req_ndn, 0, 0 );
-
-               r.sr_err = be_entry_get_rw( op, &op->o_req_ndn,
-                       dli->dli_oc, NULL, 0, &e );
-               if ( e != NULL ) {
-                       be_entry_release_r( op, e );
-               }
-               op->o_do_not_cache = cache;
-               op->o_dn = op_dn;
-               op->o_ndn = op_ndn;
-               op->o_bd = op_bd;
-               if ( r.sr_err != LDAP_SUCCESS ) {
+
+               if ( !is_entry_objectclass_or_sub( e, dli->dli_oc ))
                        continue;
-               }
 
                /* if the entry has the right objectClass, generate
                 * the dynamic list and compare */
@@ -603,7 +624,7 @@ dynlist_compare( Operation *op, SlapReply *rs )
                o.ors_tlimit = SLAP_NO_LIMIT;
                o.ors_slimit = SLAP_NO_LIMIT;
 
-               o.o_bd = select_backend( &o.o_req_ndn, 0, 1 );
+               o.o_bd = select_backend( &o.o_req_ndn, 1 );
                if ( !o.o_bd || !o.o_bd->be_search ) {
                        return SLAP_CB_CONTINUE;
                }
@@ -628,6 +649,10 @@ dynlist_compare( Operation *op, SlapReply *rs )
                rc = o.o_bd->be_search( &o, &r );
                filter_free_x( &o, o.ors_filter );
 
+               if ( o.o_dn.bv_val != op->o_dn.bv_val ) {
+                       slap_op_groups_free( &o );
+               }
+
                if ( rc != 0 ) {
                        return rc;
                }
@@ -675,9 +700,17 @@ dynlist_response( Operation *op, SlapReply *rs )
        case LDAP_REQ_SEARCH:
                if ( rs->sr_type == REP_SEARCH && !get_manageDSAit( op ) )
                {
-                       dli = dynlist_is_dynlist( op, rs );
-                       if ( dli != NULL ) {
-                               return dynlist_send_entry( op, rs, dli );
+                       int     rc = LDAP_OTHER;
+
+                       for ( dli = dynlist_is_dynlist_next( op, rs, NULL );
+                               dli;
+                               dli = dynlist_is_dynlist_next( op, rs, dli ) )
+                       {
+                               rc = dynlist_prepare_entry( op, rs, dli );
+                       }
+
+                       if ( rc != LDAP_OTHER ) {
+                               return rc;
                        }
                }
                break;
@@ -797,31 +830,17 @@ dynlist_db_config(
                for ( dlip = (dynlist_info_t **)&on->on_bi.bi_private;
                        *dlip; dlip = &(*dlip)->dli_next )
                {
-                       /* The check on objectClass may be relaxed */
-#if 0
-                       if ( (*dlip)->dli_oc == oc ) {
-                               Debug( LDAP_DEBUG_ANY, "%s: line %d: "
-                                       "\"dynlist-attrset <oc> <URL-ad> [<member-ad>]\": "
-                                       "objectClass \"%s\" already mapped.\n",
-                                       fname, lineno, oc->soc_cname.bv_val );
-                               return 1;
-                       }
-#endif
-
-                       if ( (*dlip)->dli_ad == ad ) {
+                       /* The same URL attribute / member attribute pair
+                        * cannot be repeated */
+                       if ( (*dlip)->dli_ad == ad && (*dlip)->dli_member_ad == member_ad ) {
                                Debug( LDAP_DEBUG_ANY, "%s: line %d: "
                                        "\"dynlist-attrset <oc> <URL-ad> [<member-ad>]\": "
                                        "URL attributeDescription \"%s\" already mapped.\n",
                                        fname, lineno, ad->ad_cname.bv_val );
+#if 0
+                               /* make it a warning... */
                                return 1;
-                       }
-
-                       if ( member_ad != NULL && (*dlip)->dli_member_ad == member_ad ) {
-                               Debug( LDAP_DEBUG_ANY, "%s: line %d: "
-                                       "\"dynlist-attrset <oc> <URL-ad> [<member-ad>]\": "
-                                       "member attributeDescription \"%s\" already mapped.\n",
-                                       fname, lineno, member_ad->ad_cname.bv_val );
-                               return 1;
+#endif
                        }
                }
 
@@ -888,35 +907,20 @@ dynlist_db_config(
                        return 1;
                }
 
-
                for ( dlip = (dynlist_info_t **)&on->on_bi.bi_private;
                        *dlip; dlip = &(*dlip)->dli_next )
                {
-#if 0
-                       /* The check on objectClass may be relaxed */
-                       if ( (*dlip)->dli_oc == oc ) {
-                               Debug( LDAP_DEBUG_ANY, "%s: line %d: "
-                                       "\"dynlist-attrpair <member-ad> <URL-ad>\": "
-                                       "objectClass \"%s\" already mapped.\n",
-                                       fname, lineno, oc->soc_cname.bv_val );
-                               return 1;
-                       }
-#endif
-
-                       if ( (*dlip)->dli_ad == ad ) {
+                       /* The same URL attribute / member attribute pair
+                        * cannot be repeated */
+                       if ( (*dlip)->dli_ad == ad && (*dlip)->dli_member_ad == member_ad ) {
                                Debug( LDAP_DEBUG_ANY, "%s: line %d: "
                                        "\"dynlist-attrpair <member-ad> <URL-ad>\": "
                                        "URL attributeDescription \"%s\" already mapped.\n",
                                        fname, lineno, ad->ad_cname.bv_val );
+#if 0
+                               /* make it a warning... */
                                return 1;
-                       }
-
-                       if ( member_ad != NULL && (*dlip)->dli_member_ad == member_ad ) {
-                               Debug( LDAP_DEBUG_ANY, "%s: line %d: "
-                                       "\"dynlist-attrpair <member-ad> <URL-ad>\": "
-                                       "member attributeDescription \"%s\" already mapped.\n",
-                                       fname, lineno, member_ad->ad_cname.bv_val );
-                               return 1;
+#endif
                        }
                }
 
@@ -991,12 +995,12 @@ dl_cfgen( ConfigArgs *c )
                case DL_ATTRSET:
                        for ( i = 0; dli; i++, dli = dli->dli_next ) {
                                struct berval   bv;
-                               char            *ptr = c->msg;
+                               char            *ptr = c->cr_msg;
 
                                assert( dli->dli_oc != NULL );
                                assert( dli->dli_ad != NULL );
 
-                               ptr += snprintf( c->msg, sizeof( c->msg ),
+                               ptr += snprintf( c->cr_msg, sizeof( c->cr_msg ),
                                        SLAP_X_ORDERED_FMT "%s %s", i,
                                        dli->dli_oc->soc_cname.bv_val,
                                        dli->dli_ad->ad_cname.bv_val );
@@ -1007,7 +1011,7 @@ dl_cfgen( ConfigArgs *c )
                                        ptr = lutil_strcopy( ptr, dli->dli_member_ad->ad_cname.bv_val );
                                }
 
-                               bv.bv_val = c->msg;
+                               bv.bv_val = c->cr_msg;
                                bv.bv_len = ptr - bv.bv_val;
                                value_add_one( &c->rvalue_vals, &bv );
                        }
@@ -1071,7 +1075,7 @@ dl_cfgen( ConfigArgs *c )
                        break;
                }
 
-               return 1;       /* FIXME */
+               return rc;
        }
 
        switch( c->type ) {
@@ -1085,46 +1089,46 @@ dl_cfgen( ConfigArgs *c )
 
                oc = oc_find( c->argv[ 1 ] );
                if ( oc == NULL ) {
-                       snprintf( c->msg, sizeof( c->msg ),
+                       snprintf( c->cr_msg, sizeof( c->cr_msg ),
                                "\"dynlist-attrset <oc> <URL-ad> [<member-ad>]\": "
                                "unable to find ObjectClass \"%s\"",
                                c->argv[ 1 ] );
                        Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
-                               c->log, c->msg, 0 );
+                               c->log, c->cr_msg, 0 );
                        return 1;
                }
 
                rc = slap_str2ad( c->argv[ 2 ], &ad, &text );
                if ( rc != LDAP_SUCCESS ) {
-                       snprintf( c->msg, sizeof( c->msg ),
+                       snprintf( c->cr_msg, sizeof( c->cr_msg ),
                                "\"dynlist-attrset <oc> <URL-ad> [<member-ad>]\": "
                                "unable to find AttributeDescription \"%s\"",
                                c->argv[ 2 ] );
                        Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
-                               c->log, c->msg, 0 );
+                               c->log, c->cr_msg, 0 );
                        return 1;
                }
 
                if ( !is_at_subtype( ad->ad_type, slap_schema.si_ad_labeledURI->ad_type ) ) {
-                       snprintf( c->msg, sizeof( c->msg ),
+                       snprintf( c->cr_msg, sizeof( c->cr_msg ),
                                "\"dynlist-attrset <oc> <URL-ad> [<member-ad>]\": "
                                "AttributeDescription \"%s\" "
                                "must be a subtype of \"labeledURI\"",
                                c->argv[ 2 ] );
                        Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
-                               c->log, c->msg, 0 );
+                               c->log, c->cr_msg, 0 );
                        return 1;
                }
 
                if ( c->argc == 4 ) {
                        rc = slap_str2ad( c->argv[ 3 ], &member_ad, &text );
                        if ( rc != LDAP_SUCCESS ) {
-                               snprintf( c->msg, sizeof( c->msg ),
+                               snprintf( c->cr_msg, sizeof( c->cr_msg ),
                                        "\"dynlist-attrset <oc> <URL-ad> [<member-ad>]\": "
                                        "unable to find AttributeDescription \"%s\"\n",
                                        c->argv[ 3 ] );
                                Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
-                                       c->log, c->msg, 0 );
+                                       c->log, c->cr_msg, 0 );
                                return 1;
                        }
                }
@@ -1132,37 +1136,19 @@ dl_cfgen( ConfigArgs *c )
                for ( dlip = (dynlist_info_t **)&on->on_bi.bi_private;
                        *dlip; dlip = &(*dlip)->dli_next )
                {
-                       /* The check on objectClass may be relaxed */
-#if 0
-                       if ( (*dlip)->dli_oc == oc ) {
-                               snprintf( c->msg, sizeof( c->msg ),
-                                       "\"dynlist-attrset <oc> <URL-ad> [<member-ad>]\": "
-                                       "objectClass \"%s\" already mapped.\n",
-                                       oc->soc_cname.bv_val );
-                               Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
-                                       c->log, c->msg, 0 );
-                               return 1;
-                       }
-#endif
-
-                       if ( (*dlip)->dli_ad == ad ) {
-                               snprintf( c->msg, sizeof( c->msg ),
+                       /* The same URL attribute / member attribute pair
+                        * cannot be repeated */
+                       if ( (*dlip)->dli_ad == ad && (*dlip)->dli_member_ad == member_ad ) {
+                               snprintf( c->cr_msg, sizeof( c->cr_msg ),
                                        "\"dynlist-attrset <oc> <URL-ad> [<member-ad>]\": "
                                        "URL attributeDescription \"%s\" already mapped.\n",
                                        ad->ad_cname.bv_val );
                                Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
-                                       c->log, c->msg, 0 );
-                               return 1;
-                       }
-
-                       if ( member_ad != NULL && (*dlip)->dli_member_ad == member_ad ) {
-                               snprintf( c->msg, sizeof( c->msg ),
-                                       "\"dynlist-attrset <oc> <URL-ad> [<member-ad>]\": "
-                                       "member attributeDescription \"%s\" already mapped.\n",
-                                       member_ad->ad_cname.bv_val );
-                               Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
-                                       c->log, c->msg, 0 );
+                                       c->log, c->cr_msg, 0 );
+#if 0
+                               /* make it a warning... */
                                return 1;
+#endif
                        }
                }
 
@@ -1173,12 +1159,12 @@ dl_cfgen( ConfigArgs *c )
                                i < c->valx; i++ )
                        {
                                if ( *dlip == NULL ) {
-                                       snprintf( c->msg, sizeof( c->msg ),
+                                       snprintf( c->cr_msg, sizeof( c->cr_msg ),
                                                "\"dynlist-attrset <oc> <URL-ad> [<member-ad>]\": "
                                                "invalid index {%d}\n",
                                                c->valx );
                                        Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
-                                               c->log, c->msg, 0 );
+                                               c->log, c->cr_msg, 0 );
                                        return 1;
                                }
                                dlip = &(*dlip)->dli_next;
@@ -1203,10 +1189,10 @@ dl_cfgen( ConfigArgs *c )
                } break;
 
        case DL_ATTRPAIR_COMPAT:
-               snprintf( c->msg, sizeof( c->msg ),
+               snprintf( c->cr_msg, sizeof( c->cr_msg ),
                        "warning: \"attrpair\" only supported for limited "
                        "backward compatibility with overlay \"dyngroup\"" );
-               Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+               Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
                /* fallthru */
 
        case DL_ATTRPAIR: {
@@ -1218,81 +1204,63 @@ dl_cfgen( ConfigArgs *c )
 
                oc = oc_find( "groupOfURLs" );
                if ( oc == NULL ) {
-                       snprintf( c->msg, sizeof( c->msg ),
+                       snprintf( c->cr_msg, sizeof( c->cr_msg ),
                                "\"dynlist-attrpair <member-ad> <URL-ad>\": "
                                "unable to find default ObjectClass \"groupOfURLs\"" );
                        Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
-                               c->log, c->msg, 0 );
+                               c->log, c->cr_msg, 0 );
                        return 1;
                }
 
                rc = slap_str2ad( c->argv[ 1 ], &member_ad, &text );
                if ( rc != LDAP_SUCCESS ) {
-                       snprintf( c->msg, sizeof( c->msg ),
+                       snprintf( c->cr_msg, sizeof( c->cr_msg ),
                                "\"dynlist-attrpair <member-ad> <URL-ad>\": "
                                "unable to find AttributeDescription \"%s\"",
                                c->argv[ 1 ] );
                        Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
-                               c->log, c->msg, 0 );
+                               c->log, c->cr_msg, 0 );
                        return 1;
                }
 
                rc = slap_str2ad( c->argv[ 2 ], &ad, &text );
                if ( rc != LDAP_SUCCESS ) {
-                       snprintf( c->msg, sizeof( c->msg ),
+                       snprintf( c->cr_msg, sizeof( c->cr_msg ),
                                "\"dynlist-attrpair <member-ad> <URL-ad>\": "
                                "unable to find AttributeDescription \"%s\"\n",
                                c->argv[ 2 ] );
                        Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
-                               c->log, c->msg, 0 );
+                               c->log, c->cr_msg, 0 );
                        return 1;
                }
 
                if ( !is_at_subtype( ad->ad_type, slap_schema.si_ad_labeledURI->ad_type ) ) {
-                       snprintf( c->msg, sizeof( c->msg ),
+                       snprintf( c->cr_msg, sizeof( c->cr_msg ),
                                "\"dynlist-attrset <oc> <URL-ad> [<member-ad>]\": "
                                "AttributeDescription \"%s\" "
                                "must be a subtype of \"labeledURI\"",
                                c->argv[ 2 ] );
                        Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
-                               c->log, c->msg, 0 );
+                               c->log, c->cr_msg, 0 );
                        return 1;
                }
 
                for ( dlip = (dynlist_info_t **)&on->on_bi.bi_private;
                        *dlip; dlip = &(*dlip)->dli_next )
                {
-                       /* The check on objectClass may be relaxed */
-#if 0
-                       if ( (*dlip)->dli_oc == oc ) {
-                               snprintf( c->msg, sizeof( c->msg ),
-                                       "\"dynlist-attrpair <member-ad> <URL-ad>\": "
-                                       "objectClass \"%s\" already mapped.\n",
-                                       oc->soc_cname.bv_val );
-                               Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
-                                       c->log, c->msg, 0 );
-                               return 1;
-                       }
-#endif
-
-                       if ( (*dlip)->dli_ad == ad ) {
-                               snprintf( c->msg, sizeof( c->msg ),
+                       /* The same URL attribute / member attribute pair
+                        * cannot be repeated */
+                       if ( (*dlip)->dli_ad == ad && (*dlip)->dli_member_ad == member_ad ) {
+                               snprintf( c->cr_msg, sizeof( c->cr_msg ),
                                        "\"dynlist-attrpair <member-ad> <URL-ad>\": "
                                        "URL attributeDescription \"%s\" already mapped.\n",
                                        ad->ad_cname.bv_val );
                                Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
-                                       c->log, c->msg, 0 );
-                               return 1;
-                       }
-
-                       if ( member_ad != NULL && (*dlip)->dli_member_ad == member_ad ) {
-                               snprintf( c->msg, sizeof( c->msg ),
-                                       "\"dynlist-attrpair <member-ad> <URL-ad>\": "
-                                       "member attributeDescription \"%s\" already mapped.\n",
-                                       member_ad->ad_cname.bv_val );
-                               Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
-                                       c->log, c->msg, 0 );
+                                       c->log, c->cr_msg, 0 );
+#if 0
+                               /* make it a warning... */
                                return 1;
+#endif
                        }
                }
 
@@ -1317,12 +1285,15 @@ dl_cfgen( ConfigArgs *c )
 
 static int
 dynlist_db_open(
-       BackendDB       *be )
+       BackendDB       *be,
+       ConfigReply     *cr )
 {
        slap_overinst           *on = (slap_overinst *) be->bd_info;
        dynlist_info_t          *dli = (dynlist_info_t *)on->on_bi.bi_private;
        ObjectClass             *oc = NULL;
        AttributeDescription    *ad = NULL;
+       const char      *text;
+       int rc;
 
        if ( dli == NULL ) {
                dli = ch_calloc( 1, sizeof( dynlist_info_t ) );
@@ -1330,16 +1301,12 @@ dynlist_db_open(
        }
 
        for ( ; dli; dli = dli->dli_next ) {
-               const char      *text;
-               int             rc;
-
                if ( dli->dli_oc == NULL ) {
                        if ( oc == NULL ) {
                                oc = oc_find( "groupOfURLs" );
                                if ( oc == NULL ) {
-                                       Debug( LDAP_DEBUG_ANY, "dynlist_db_open: "
-                                               "unable to fetch objectClass \"groupOfURLs\".\n",
-                                               0, 0, 0 );
+                                       sprintf( cr->msg, "unable to fetch objectClass \"groupOfURLs\"" );
+                                       Debug( LDAP_DEBUG_ANY, "dynlist_db_open: %s.\n", cr->msg, 0, 0 );
                                        return 1;
                                }
                        }
@@ -1351,9 +1318,9 @@ dynlist_db_open(
                        if ( ad == NULL ) {
                                rc = slap_str2ad( "memberURL", &ad, &text );
                                if ( rc != LDAP_SUCCESS ) {
-                                       Debug( LDAP_DEBUG_ANY, "dynlist_db_open: "
-                                               "unable to fetch attributeDescription \"memberURL\": %d (%s).\n",
-                                               rc, text, 0 );
+                                       sprintf( cr->msg, "unable to fetch attributeDescription \"memberURL\": %d (%s)",
+                                               rc, text );
+                                       Debug( LDAP_DEBUG_ANY, "dynlist_db_open: %s.\n", cr->msg, 0, 0 );
                                        return 1;
                                }
                        }
@@ -1369,12 +1336,21 @@ dynlist_db_open(
                }
        }
 
+       rc = slap_str2ad( "dgIdentity", &ad_dgIdentity, &text );
+       if ( rc != LDAP_SUCCESS ) {
+               sprintf( cr->msg, "unable to fetch attributeDescription \"dgIdentity\": %d (%s)",
+                       rc, text );
+               Debug( LDAP_DEBUG_ANY, "dynlist_db_open: %s\n", cr->msg, 0, 0 );
+               /* Just a warning */
+       }
+
        return 0;
 }
 
 static int
 dynlist_db_destroy(
-       BackendDB       *be )
+       BackendDB       *be,
+       ConfigReply     *cr )
 {
        slap_overinst   *on = (slap_overinst *) be->bd_info;
 
diff --git a/servers/slapd/overlays/memberof.c b/servers/slapd/overlays/memberof.c
new file mode 100644 (file)
index 0000000..8e282e9
--- /dev/null
@@ -0,0 +1,1947 @@
+/* memberof.c - back-reference for group membership */
+/* $OpenLDAP$ */
+/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
+ *
+ * Copyright 2005-2007 Pierangelo Masarati <ando@sys-net.it>
+ * 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>.
+ */
+/* ACKNOWLEDGMENTS:
+ * This work was initially developed by Pierangelo Masarati for inclusion
+ * in OpenLDAP Software, sponsored by SysNet s.r.l.
+ */
+
+#include "portable.h"
+
+#ifdef SLAPD_OVER_MEMBEROF
+
+#include <stdio.h>
+
+#include "ac/string.h"
+#include "ac/socket.h"
+
+#include "slap.h"
+#include "config.h"
+#include "lutil.h"
+
+/*
+ *     Glossary:
+ *
+ *             GROUP           a group object (an entry with GROUP_OC
+ *                             objectClass)
+ *             MEMBER          a member object (an entry whose DN is
+ *                             listed as MEMBER_AT value of a GROUP)
+ *             GROUP_OC        the objectClass of the group object
+ *                             (default: groupOfNames)
+ *             MEMBER_AT       the membership attribute, DN-valued;
+ *                             note: nameAndOptionalUID is tolerated
+ *                             as soon as the optionalUID is absent
+ *                             (default: member)
+ *             MEMBER_OF       reverse membership attribute
+ *                             (default: memberOf)
+ *
+ *     - add:
+ *             - if the entry that is being added is a GROUP,
+ *               the MEMBER_AT defined as values of the add operation
+ *               get the MEMBER_OF value directly from the request.
+ *
+ *               if configured to do so, the MEMBER objects do not exist,
+ *               and no relax control is issued, either:
+ *                     - fail
+ *                     - drop non-existing members
+ *               (by default: don't muck with values)
+ *
+ *             - if (configured to do so,) the referenced GROUP exists,
+ *               the relax control is set and the user has
+ *               "manage" privileges, allow to add MEMBER_OF values to
+ *               generic entries.
+ *
+ *     - modify:
+ *             - if the entry being modified is a GROUP_OC and the 
+ *               MEMBER_AT attribute is modified, the MEMBER_OF value
+ *               of the (existing) MEMBER_AT entries that are affected
+ *               is modified according to the request:
+ *                     - if a MEMBER is removed from the group,
+ *                       delete the corresponding MEMBER_OF
+ *                     - if a MEMBER is added to a group,
+ *                       add the corresponding MEMBER_OF
+ *
+ *               We need to determine, from the database, if it is
+ *               a GROUP_OC, and we need to check, from the
+ *               modification list, if the MEMBER_AT attribute is being
+ *               affected, and what MEMBER_AT values are affected.
+ *
+ *               if configured to do so, the entries corresponding to
+ *               the MEMBER_AT values do not exist, and no relax control
+ *               is issued, either:
+ *                     - fail
+ *                     - drop non-existing members
+ *               (by default: don't muck with values)
+ *
+ *             - if configured to do so, the referenced GROUP exists,
+ *               (the relax control is set) and the user has
+ *               "manage" privileges, allow to add MEMBER_OF values to
+ *               generic entries; the change is NOT automatically reflected
+ *               in the MEMBER attribute of the GROUP referenced
+ *               by the value of MEMBER_OF; a separate modification,
+ *               with or without relax control, needs to be performed.
+ *
+ *     - modrdn:
+ *             - if the entry being renamed is a GROUP, the MEMBER_OF
+ *               value of the (existing) MEMBER objects is modified
+ *               accordingly based on the newDN of the GROUP.
+ *
+ *               We need to determine, from the database, if it is
+ *               a GROUP; the list of MEMBER objects is obtained from
+ *               the database.
+ *
+ *               Non-existing MEMBER objects are ignored, since the
+ *               MEMBER_AT is not being addressed by the operation.
+ *
+ *             - if the entry being renamed has the MEMBER_OF attribute,
+ *               the corresponding MEMBER value must be modified in the
+ *               respective group entries.
+ *             
+ *
+ *     - delete:
+ *             - if the entry being deleted is a GROUP, the (existing)
+ *               MEMBER objects are modified accordingly; a copy of the 
+ *               values of the MEMBER_AT is saved and, if the delete 
+ *               succeeds, the MEMBER_OF value of the (existing) MEMBER
+ *               objects is deleted.
+ *
+ *               We need to determine, from the database, if it is
+ *               a GROUP.
+ *
+ *               Non-existing MEMBER objects are ignored, since the entry
+ *               is being deleted.
+ *
+ *             - if the entry being deleted has the MEMBER_OF attribute,
+ *               the corresponding value of the MEMBER_AT must be deleted
+ *               from the respective GROUP entries.
+ */
+
+#define        SLAPD_MEMBEROF_ATTR     "memberOf"
+
+static slap_overinst           memberof;
+
+typedef struct memberof_t {
+       struct berval           mo_dn;
+       struct berval           mo_ndn;
+
+       ObjectClass             *mo_oc_group;
+       AttributeDescription    *mo_ad_member;
+       AttributeDescription    *mo_ad_memberof;
+       
+       struct berval           mo_groupFilterstr;
+       AttributeAssertion      mo_groupAVA;
+       Filter                  mo_groupFilter;
+
+       struct berval           mo_memberFilterstr;
+       Filter                  mo_memberFilter;
+
+       unsigned                mo_flags;
+#define        MEMBEROF_NONE           0x00U
+#define        MEMBEROF_FDANGLING_DROP 0x01U
+#define        MEMBEROF_FDANGLING_ERROR        0x02U
+#define        MEMBEROF_FDANGLING_MASK (MEMBEROF_FDANGLING_DROP|MEMBEROF_FDANGLING_ERROR)
+#define        MEMBEROF_FREFINT        0x04U
+#define        MEMBEROF_FREVERSE       0x08U
+
+#define MEMBEROF_CHK(mo,f) \
+       (((mo)->mo_flags & (f)) == (f))
+#define MEMBEROF_DANGLING_CHECK(mo) \
+       ((mo)->mo_flags & MEMBEROF_FDANGLING_MASK)
+#define MEMBEROF_DANGLING_DROP(mo) \
+       MEMBEROF_CHK((mo),MEMBEROF_FDANGLING_DROP)
+#define MEMBEROF_DANGLING_ERROR(mo) \
+       MEMBEROF_CHK((mo),MEMBEROF_FDANGLING_ERROR)
+#define MEMBEROF_REFINT(mo) \
+       MEMBEROF_CHK((mo),MEMBEROF_FREFINT)
+#define MEMBEROF_REVERSE(mo) \
+       MEMBEROF_CHK((mo),MEMBEROF_FREVERSE)
+} memberof_t;
+
+typedef enum memberof_is_t {
+       MEMBEROF_IS_NONE = 0x00,
+       MEMBEROF_IS_GROUP = 0x01,
+       MEMBEROF_IS_MEMBER = 0x02,
+       MEMBEROF_IS_BOTH = (MEMBEROF_IS_GROUP|MEMBEROF_IS_MEMBER)
+} memberof_is_t;
+
+/*
+ * failover storage for member attribute values of groups being deleted
+ * handles [no]thread cases.
+ */
+static BerVarray       saved_member_vals;
+static BerVarray       saved_memberof_vals;
+
+static void
+memberof_saved_member_free( void *key, void *data )
+{
+       ber_bvarray_free( (BerVarray)data );
+}
+
+static BerVarray
+memberof_saved_member_get( Operation *op, void *keyp )
+{
+       BerVarray       vals;
+       BerVarray       *key = (BerVarray *)keyp;
+
+       assert( op );
+
+       if ( op->o_threadctx == NULL ) {
+               vals = *key;
+               *key = NULL;
+
+       } else {
+               ldap_pvt_thread_pool_getkey( op->o_threadctx,
+                               key, (void **)&vals, NULL );
+               ldap_pvt_thread_pool_setkey( op->o_threadctx,
+                               key, NULL, NULL );
+       }
+
+       return vals;
+}
+
+static void
+memberof_saved_member_set( Operation *op, void *keyp, BerVarray vals )
+{
+       BerVarray       saved_vals = NULL;
+       BerVarray       *key = (BerVarray*)keyp;
+
+       assert( op );
+
+       if ( vals ) {
+               ber_bvarray_dup_x( &saved_vals, vals, NULL );
+       }
+
+       if ( op->o_threadctx == NULL ) {
+               if ( *key ) {
+                       ber_bvarray_free( *key );
+               }
+               *key = saved_vals;
+
+       } else {
+               ldap_pvt_thread_pool_setkey( op->o_threadctx, key,
+                               saved_vals, memberof_saved_member_free );
+       }
+}
+
+typedef struct memberof_cookie_t {
+       AttributeDescription    *ad;
+       void                    *key;
+       int                     foundit;
+} memberof_cookie_t;
+
+static int
+memberof_isGroupOrMember_cb( Operation *op, SlapReply *rs )
+{
+       if ( rs->sr_type == REP_SEARCH ) {
+               memberof_cookie_t       *mc;
+
+               mc = (memberof_cookie_t *)op->o_callback->sc_private;
+               mc->foundit = 1;
+       }
+
+       return 0;
+}
+
+/*
+ * callback for internal search that saves the member attribute values
+ * of groups being deleted.
+ */
+static int
+memberof_saveMember_cb( Operation *op, SlapReply *rs )
+{
+       if ( rs->sr_type == REP_SEARCH ) {
+               memberof_cookie_t       *mc;
+               Attribute               *a;
+
+               mc = (memberof_cookie_t *)op->o_callback->sc_private;
+               mc->foundit = 1;
+
+               assert( rs->sr_entry );
+               assert( rs->sr_entry->e_attrs );
+
+               a = attr_find( rs->sr_entry->e_attrs, mc->ad );
+
+               assert( a != NULL );
+
+               memberof_saved_member_set( op, mc->key, a->a_nvals );
+
+               if ( attr_find( a->a_next, mc->ad ) != NULL ) {
+                       Debug( LDAP_DEBUG_ANY,
+                               "%s: memberof_saveMember_cb(\"%s\"): "
+                               "more than one occurrence of \"%s\" "
+                               "attribute.\n",
+                               op->o_log_prefix,
+                               rs->sr_entry->e_name.bv_val,
+                               mc->ad->ad_cname.bv_val );
+               }
+       }
+
+       return 0;
+}
+
+/*
+ * the delete hook performs an internal search that saves the member
+ * attribute values of groups being deleted.
+ */
+static int
+memberof_isGroupOrMember( Operation *op, memberof_is_t *iswhatp )
+{
+       slap_overinst           *on = (slap_overinst *)op->o_bd->bd_info;
+       memberof_t              *mo = (memberof_t *)on->on_bi.bi_private;
+
+       Operation               op2 = *op;
+       SlapReply               rs2 = { REP_RESULT };
+       slap_callback           cb = { 0 };
+       memberof_cookie_t       mc;
+       AttributeName           an[ 2 ];
+
+       memberof_is_t           iswhat = MEMBEROF_IS_NONE;
+
+       assert( iswhatp != NULL );
+       assert( *iswhatp != MEMBEROF_IS_NONE );
+
+       cb.sc_private = &mc;
+       if ( op->o_tag == LDAP_REQ_DELETE ) {
+               cb.sc_response = memberof_saveMember_cb;
+
+       } else {
+               cb.sc_response = memberof_isGroupOrMember_cb;
+       }
+
+       op2.o_tag = LDAP_REQ_SEARCH;
+       op2.o_callback = &cb;
+       op2.o_dn = op->o_bd->be_rootdn;
+       op2.o_ndn = op->o_bd->be_rootndn;
+
+       op2.ors_scope = LDAP_SCOPE_BASE;
+       op2.ors_deref = LDAP_DEREF_NEVER;
+       BER_BVZERO( &an[ 1 ].an_name );
+       op2.ors_attrs = an;
+       op2.ors_attrsonly = 0;
+       op2.ors_limit = NULL;
+       op2.ors_slimit = 1;
+       op2.ors_tlimit = SLAP_NO_LIMIT;
+
+       if ( *iswhatp & MEMBEROF_IS_GROUP ) {
+               mc.ad = mo->mo_ad_member;
+               mc.key = &saved_member_vals;
+               mc.foundit = 0;
+               an[ 0 ].an_desc = mo->mo_ad_member;
+               an[ 0 ].an_name = an[ 0 ].an_desc->ad_cname;
+               op2.ors_filterstr = mo->mo_groupFilterstr;
+               op2.ors_filter = &mo->mo_groupFilter;
+
+               op2.o_bd->bd_info = (BackendInfo *)on->on_info;
+               (void)op->o_bd->be_search( &op2, &rs2 );
+               op2.o_bd->bd_info = (BackendInfo *)on;
+
+               if ( mc.foundit ) {
+                       iswhat |= MEMBEROF_IS_GROUP;
+
+               } else {
+                       memberof_saved_member_set( op, mc.key, NULL );
+               }
+       }
+
+       if ( *iswhatp & MEMBEROF_IS_MEMBER ) {
+               mc.ad = mo->mo_ad_memberof;
+               mc.key = &saved_memberof_vals;
+               mc.foundit = 0;
+               an[ 0 ].an_desc = mo->mo_ad_memberof;
+               an[ 0 ].an_name = an[ 0 ].an_desc->ad_cname;
+               op2.ors_filterstr = mo->mo_memberFilterstr;
+               op2.ors_filter = &mo->mo_memberFilter;
+
+               op2.o_bd->bd_info = (BackendInfo *)on->on_info;
+               (void)op->o_bd->be_search( &op2, &rs2 );
+               op2.o_bd->bd_info = (BackendInfo *)on;
+
+               if ( mc.foundit ) {
+                       iswhat |= MEMBEROF_IS_MEMBER;
+
+               } else {
+                       memberof_saved_member_set( op, mc.key, NULL );
+               }
+       }
+
+       *iswhatp = iswhat;
+
+       return LDAP_SUCCESS;
+}
+
+/*
+ * response callback that adds memberof values when a group is modified.
+ */
+static int
+memberof_value_modify(
+       Operation               *op,
+       SlapReply               *rs,
+       struct berval           *ndn,
+       AttributeDescription    *ad,
+       struct berval           *old_dn,
+       struct berval           *old_ndn,
+       struct berval           *new_dn,
+       struct berval           *new_ndn )
+{
+       slap_overinst   *on = (slap_overinst *)op->o_bd->bd_info;
+       memberof_t      *mo = (memberof_t *)on->on_bi.bi_private;
+
+       Operation       op2 = *op;
+       SlapReply       rs2 = { REP_RESULT };
+       slap_callback   cb = { NULL, slap_null_cb, NULL, NULL };
+       Modifications   mod[ 2 ] = { { { 0 } } }, *ml;
+       struct berval   values[ 4 ], nvalues[ 4 ];
+
+       op2.o_tag = LDAP_REQ_MODIFY;
+
+       op2.o_req_dn = *ndn;
+       op2.o_req_ndn = *ndn;
+
+       op2.o_bd->bd_info = (BackendInfo *)on->on_info;
+
+       op2.o_callback = &cb;
+       op2.o_dn = op->o_bd->be_rootdn;
+       op2.o_ndn = op->o_bd->be_rootndn;
+
+       ml = &mod[ 0 ];
+       ml->sml_values = &values[ 0 ];
+       ml->sml_values[ 0 ] = mo->mo_dn;
+       BER_BVZERO( &ml->sml_values[ 1 ] );
+       ml->sml_nvalues = &nvalues[ 0 ];
+       ml->sml_nvalues[ 0 ] = mo->mo_ndn;
+       BER_BVZERO( &ml->sml_nvalues[ 1 ] );
+       ml->sml_desc = slap_schema.si_ad_modifiersName;
+       ml->sml_type = ml->sml_desc->ad_cname;
+       ml->sml_op = LDAP_MOD_REPLACE;
+       ml->sml_flags = SLAP_MOD_INTERNAL;
+       ml->sml_next = NULL;
+       op2.orm_modlist = ml;
+
+       ml = &mod[ 1 ];
+       ml->sml_values = &values[ 2 ];
+       BER_BVZERO( &ml->sml_values[ 1 ] );
+       ml->sml_nvalues = &nvalues[ 2 ];
+       BER_BVZERO( &ml->sml_nvalues[ 1 ] );
+       ml->sml_desc = ad;
+       ml->sml_type = ml->sml_desc->ad_cname;
+       ml->sml_flags = SLAP_MOD_INTERNAL;
+       ml->sml_next = NULL;
+       op2.orm_modlist->sml_next = ml;
+
+       if ( new_ndn != NULL ) {
+               assert( !BER_BVISNULL( new_dn ) );
+               assert( !BER_BVISNULL( new_ndn ) );
+
+               ml->sml_op = LDAP_MOD_ADD;
+
+               ml->sml_values[ 0 ] = *new_dn;
+               ml->sml_nvalues[ 0 ] = *new_ndn;
+
+               (void)op->o_bd->be_modify( &op2, &rs2 );
+
+               assert( op2.orm_modlist == &mod[ 0 ] );
+               assert( op2.orm_modlist->sml_next == &mod[ 1 ] );
+               ml = op2.orm_modlist->sml_next->sml_next;
+               if ( ml != NULL ) {
+                       slap_mods_free( ml, 1 );
+               }
+       }
+
+       if ( old_ndn != NULL ) {
+               assert( !BER_BVISNULL( old_dn ) );
+               assert( !BER_BVISNULL( old_ndn ) );
+
+               ml->sml_op = LDAP_MOD_DELETE;
+
+               ml->sml_values[ 0 ] = *old_dn;
+               ml->sml_nvalues[ 0 ] = *old_ndn;
+
+               (void)op->o_bd->be_modify( &op2, &rs2 );
+
+               assert( op2.orm_modlist == &mod[ 0 ] );
+               assert( op2.orm_modlist->sml_next == &mod[ 1 ] );
+               ml = op2.orm_modlist->sml_next->sml_next;
+               if ( ml != NULL ) {
+                       slap_mods_free( ml, 1 );
+               }
+       }
+
+       /* FIXME: if old_group_ndn doesn't exist, both delete __and__
+        * add will fail; better split in two operations, although
+        * not optimal in terms of performance.  At least it would
+        * move towards self-repairing capabilities. */
+
+       op2.o_bd->bd_info = (BackendInfo *)on;
+
+       return rs2.sr_err;
+}
+
+static int
+memberof_op_add( Operation *op, SlapReply *rs )
+{
+       slap_overinst   *on = (slap_overinst *)op->o_bd->bd_info;
+       memberof_t      *mo = (memberof_t *)on->on_bi.bi_private;
+
+       Attribute       **ap, **map = NULL;
+       int             rc = SLAP_CB_CONTINUE;
+       int             i;
+       struct berval   save_dn, save_ndn;
+
+       if ( op->ora_e->e_attrs == NULL ) {
+               /* FIXME: global overlay; need to deal with */
+               Debug( LDAP_DEBUG_ANY, "%s: memberof_op_add(\"%s\"): "
+                       "consistency checks not implemented when overlay "
+                       "is instantiated as global.\n",
+                       op->o_log_prefix, op->o_req_dn.bv_val, 0 );
+               return SLAP_CB_CONTINUE;
+       }
+
+       if ( MEMBEROF_REVERSE( mo ) ) {
+               for ( ap = &op->ora_e->e_attrs; *ap; ap = &(*ap)->a_next ) {
+                       Attribute       *a = *ap;
+
+                       if ( a->a_desc == mo->mo_ad_memberof ) {
+                               map = ap;
+                               break;
+                       }
+               }
+       }
+
+       save_dn = op->o_dn;
+       save_ndn = op->o_ndn;
+
+       if ( MEMBEROF_DANGLING_CHECK( mo )
+                       && !get_relax( op )
+                       && is_entry_objectclass( op->ora_e, mo->mo_oc_group, 0 ) )
+       {
+               op->o_dn = op->o_bd->be_rootdn;
+               op->o_dn = op->o_bd->be_rootndn;
+               op->o_bd->bd_info = (BackendInfo *)on->on_info;
+
+               for ( ap = &op->ora_e->e_attrs; *ap; ) {
+                       Attribute       *a = *ap;
+
+                       if ( !is_ad_subtype( a->a_desc, mo->mo_ad_member ) ) {
+                               ap = &a->a_next;
+                               continue;
+                       }
+
+                       assert( a->a_nvals != NULL );
+
+                       for ( i = 0; !BER_BVISNULL( &a->a_nvals[ i ] ); i++ ) {
+                               Entry           *e;
+
+                               /* FIXME: entry_get_rw does not pass
+                                * thru overlays yet; when it does, we
+                                * might need to make a copy of the DN */
+
+                               rc = be_entry_get_rw( op, &a->a_nvals[ i ],
+                                               NULL, NULL, 0, &e );
+                               if ( rc == LDAP_SUCCESS ) {
+                                       be_entry_release_r( op, e );
+                                       continue;
+                               }
+
+                               if ( MEMBEROF_DANGLING_ERROR( mo ) ) {
+                                       rc = rs->sr_err = LDAP_CONSTRAINT_VIOLATION;
+                                       rs->sr_text = "adding non-existing object "
+                                               "as group member";
+                                       send_ldap_result( op, rs );
+                                       goto done;
+                               }
+
+                               if ( MEMBEROF_DANGLING_DROP( mo ) ) {
+                                       int     j;
+       
+                                       Debug( LDAP_DEBUG_ANY, "%s: memberof_op_add(\"%s\"): "
+                                               "member=\"%s\" does not exist (stripping...)\n",
+                                               op->o_log_prefix, op->ora_e->e_name.bv_val,
+                                               a->a_vals[ i ].bv_val );
+       
+                                       for ( j = i + 1; !BER_BVISNULL( &a->a_nvals[ j ] ); j++ );
+                                       ber_memfree( a->a_vals[ i ].bv_val );
+                                       BER_BVZERO( &a->a_vals[ i ] );
+                                       if ( a->a_nvals != a->a_vals ) {
+                                               ber_memfree( a->a_nvals[ i ].bv_val );
+                                               BER_BVZERO( &a->a_nvals[ i ] );
+                                       }
+                                       if ( j - i == 1 ) {
+                                               break;
+                                       }
+               
+                                       AC_MEMCPY( &a->a_vals[ i ], &a->a_vals[ i + 1 ],
+                                               sizeof( struct berval ) * ( j - i ) );
+                                       if ( a->a_nvals != a->a_vals ) {
+                                               AC_MEMCPY( &a->a_nvals[ i ], &a->a_nvals[ i + 1 ],
+                                                       sizeof( struct berval ) * ( j - i ) );
+                                       }
+                                       i--;
+                               }
+                       }
+
+                       /* If all values have been removed,
+                        * remove the attribute itself. */
+                       if ( BER_BVISNULL( &a->a_nvals[ 0 ] ) ) {
+                               *ap = a->a_next;
+                               attr_free( a );
+       
+                       } else {
+                               ap = &a->a_next;
+                       }
+               }
+               op->o_dn = save_dn;
+               op->o_ndn = save_ndn;
+               op->o_bd->bd_info = (BackendInfo *)on;
+       }
+
+       if ( map != NULL ) {
+               Attribute               *a = *map;
+               AccessControlState      acl_state = ACL_STATE_INIT;
+
+               for ( i = 0; !BER_BVISNULL( &a->a_nvals[ i ] ); i++ ) {
+                       Entry           *e;
+
+                       op->o_bd->bd_info = (BackendInfo *)on->on_info;
+                       /* access is checked with the original identity */
+                       rc = access_allowed( op, op->ora_e, mo->mo_ad_memberof,
+                                       &a->a_nvals[ i ], ACL_WADD,
+                                       &acl_state );
+                       if ( rc == 0 ) {
+                               rc = rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
+                               rs->sr_text = NULL;
+                               send_ldap_result( op, rs );
+                               goto done;
+                       }
+                       rc = be_entry_get_rw( op, &a->a_nvals[ i ],
+                                       NULL, NULL, 0, &e );
+                       op->o_bd->bd_info = (BackendInfo *)on;
+                       if ( rc != LDAP_SUCCESS ) {
+                               if ( get_relax( op ) ) {
+                                       continue;
+                               }
+
+                               if ( MEMBEROF_DANGLING_ERROR( mo ) ) {
+                                       rc = rs->sr_err = LDAP_CONSTRAINT_VIOLATION;
+                                       rs->sr_text = "adding non-existing object "
+                                               "as memberof";
+                                       send_ldap_result( op, rs );
+                                       goto done;
+                               }
+
+                               if ( MEMBEROF_DANGLING_DROP( mo ) ) {
+                                       int     j;
+       
+                                       Debug( LDAP_DEBUG_ANY, "%s: memberof_op_add(\"%s\"): "
+                                               "memberof=\"%s\" does not exist (stripping...)\n",
+                                               op->o_log_prefix, op->ora_e->e_name.bv_val,
+                                               a->a_nvals[ i ].bv_val );
+       
+                                       for ( j = i + 1; !BER_BVISNULL( &a->a_nvals[ j ] ); j++ );
+                                       ber_memfree( a->a_vals[ i ].bv_val );
+                                       BER_BVZERO( &a->a_vals[ i ] );
+                                       if ( a->a_nvals != a->a_vals ) {
+                                               ber_memfree( a->a_nvals[ i ].bv_val );
+                                               BER_BVZERO( &a->a_nvals[ i ] );
+                                       }
+                                       if ( j - i == 1 ) {
+                                               break;
+                                       }
+               
+                                       AC_MEMCPY( &a->a_vals[ i ], &a->a_vals[ i + 1 ],
+                                               sizeof( struct berval ) * ( j - i ) );
+                                       if ( a->a_nvals != a->a_vals ) {
+                                               AC_MEMCPY( &a->a_nvals[ i ], &a->a_nvals[ i + 1 ],
+                                                       sizeof( struct berval ) * ( j - i ) );
+                                       }
+                                       i--;
+                               }
+                               
+                               continue;
+                       }
+
+                       /* access is checked with the original identity */
+                       op->o_bd->bd_info = (BackendInfo *)on->on_info;
+                       rc = access_allowed( op, e, mo->mo_ad_member,
+                                       &op->o_req_ndn, ACL_WADD, NULL );
+                       be_entry_release_r( op, e );
+                       op->o_bd->bd_info = (BackendInfo *)on;
+
+                       if ( !rc ) {
+                               rc = rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
+                               rs->sr_text = "insufficient access to object referenced by memberof";
+                               send_ldap_result( op, rs );
+                               goto done;
+                       }
+               }
+
+               if ( BER_BVISNULL( &a->a_nvals[ 0 ] ) ) {
+                       *map = a->a_next;
+                       attr_free( a );
+               }
+       }
+
+       rc = SLAP_CB_CONTINUE;
+       
+done:;
+       op->o_dn = save_dn;
+       op->o_ndn = save_ndn;
+       op->o_bd->bd_info = (BackendInfo *)on;
+
+       return rc;
+}
+
+static int
+memberof_op_delete( Operation *op, SlapReply *rs )
+{
+       slap_overinst   *on = (slap_overinst *)op->o_bd->bd_info;
+       memberof_t      *mo = (memberof_t *)on->on_bi.bi_private;
+
+       memberof_is_t   iswhat = MEMBEROF_IS_GROUP;
+
+       if ( MEMBEROF_REFINT( mo ) ) {
+               iswhat = MEMBEROF_IS_BOTH;
+       }
+
+       memberof_isGroupOrMember( op, &iswhat );
+
+       return SLAP_CB_CONTINUE;
+}
+
+static int
+memberof_op_modify( Operation *op, SlapReply *rs )
+{
+       slap_overinst   *on = (slap_overinst *)op->o_bd->bd_info;
+       memberof_t      *mo = (memberof_t *)on->on_bi.bi_private;
+
+       Modifications   **mlp, **mmlp = NULL;
+       int             rc = SLAP_CB_CONTINUE;
+       struct berval   save_dn, save_ndn;
+       memberof_is_t   iswhat = MEMBEROF_IS_GROUP;
+
+       if ( MEMBEROF_REVERSE( mo ) ) {
+               for ( mlp = &op->orm_modlist; *mlp; mlp = &(*mlp)->sml_next ) {
+                       Modifications   *ml = *mlp;
+
+                       if ( ml->sml_desc == mo->mo_ad_memberof ) {
+                               mmlp = mlp;
+                               break;
+                       }
+               }
+       }
+
+       save_dn = op->o_dn;
+       save_ndn = op->o_ndn;
+
+       if ( MEMBEROF_DANGLING_CHECK( mo )
+                       && !get_relax( op )
+                       && memberof_isGroupOrMember( op, &iswhat ) == LDAP_SUCCESS
+                       && ( iswhat & MEMBEROF_IS_GROUP ) )
+       {
+               op->o_dn = op->o_bd->be_rootdn;
+               op->o_dn = op->o_bd->be_rootndn;
+               op->o_bd->bd_info = (BackendInfo *)on->on_info;
+       
+               assert( op->orm_modlist != NULL );
+       
+               for ( mlp = &op->orm_modlist; *mlp; ) {
+                       Modifications   *ml = *mlp;
+                       int             i;
+       
+                       if ( !is_ad_subtype( ml->sml_desc, mo->mo_ad_member ) ) {
+                               mlp = &ml->sml_next;
+                               continue;
+                       }
+       
+                       switch ( ml->sml_op ) {
+                       case LDAP_MOD_DELETE:
+                               /* we don't care about cancellations: if the value
+                                * exists, fine; if it doesn't, we let the underlying
+                                * database fail as appropriate; */
+                               mlp = &ml->sml_next;
+                               break;
+       
+                       case LDAP_MOD_REPLACE:
+                       case LDAP_MOD_ADD:
+                               /* NOTE: right now, the attributeType we use
+                                * for member must have a normalized value */
+                               assert( ml->sml_nvalues );
+       
+                               for ( i = 0; !BER_BVISNULL( &ml->sml_nvalues[ i ] ); i++ ) {
+                                       int             rc;
+                                       Entry           *e;
+       
+                                       if ( be_entry_get_rw( op, &ml->sml_nvalues[ i ],
+                                                       NULL, NULL, 0, &e ) == LDAP_SUCCESS )
+                                       {
+                                               be_entry_release_r( op, e );
+                                               continue;
+                                       }
+       
+                                       if ( MEMBEROF_DANGLING_ERROR( mo ) ) {
+                                               rc = rs->sr_err = LDAP_CONSTRAINT_VIOLATION;
+                                               rs->sr_text = "adding non-existing object "
+                                                       "as group member";
+                                               send_ldap_result( op, rs );
+                                               goto done;
+                                       }
+       
+                                       if ( MEMBEROF_DANGLING_DROP( mo ) ) {
+                                               int     j;
+       
+                                               Debug( LDAP_DEBUG_ANY, "%s: memberof_op_modify(\"%s\"): "
+                                                       "member=\"%s\" does not exist (stripping...)\n",
+                                                       op->o_log_prefix, op->o_req_dn.bv_val,
+                                                       ml->sml_nvalues[ i ].bv_val );
+       
+                                               for ( j = i + 1; !BER_BVISNULL( &ml->sml_nvalues[ j ] ); j++ );
+                                               ber_memfree( ml->sml_values[ i ].bv_val );
+                                               BER_BVZERO( &ml->sml_values[ i ] );
+                                               ber_memfree( ml->sml_nvalues[ i ].bv_val );
+                                               BER_BVZERO( &ml->sml_nvalues[ i ] );
+                                               if ( j - i == 1 ) {
+                                                       break;
+                                               }
+       
+                                               AC_MEMCPY( &ml->sml_values[ i ], &ml->sml_values[ i + 1 ],
+                                                       sizeof( struct berval ) * ( j - i ) );
+                                               AC_MEMCPY( &ml->sml_nvalues[ i ], &ml->sml_nvalues[ i + 1 ],
+                                                       sizeof( struct berval ) * ( j - i ) );
+                                               i--;
+                                       }
+                               }
+       
+                               if ( BER_BVISNULL( &ml->sml_nvalues[ 0 ] ) ) {
+                                       *mlp = ml->sml_next;
+                                       slap_mod_free( &ml->sml_mod, 0 );
+                                       free( ml );
+       
+                               } else {
+                                       mlp = &ml->sml_next;
+                               }
+       
+                               break;
+       
+                       default:
+                               assert( 0 );
+                       }
+               }
+       }
+
+       if ( mmlp != NULL ) {
+               Modifications   *ml = *mmlp;
+               int             i;
+               Entry           *target;
+
+               op->o_bd->bd_info = (BackendInfo *)on->on_info;
+               rc = be_entry_get_rw( op, &op->o_req_ndn,
+                               NULL, NULL, 0, &target );
+               op->o_bd->bd_info = (BackendInfo *)on;
+               if ( rc != LDAP_SUCCESS ) {
+                       rc = rs->sr_err = LDAP_NO_SUCH_OBJECT;
+                       send_ldap_result( op, rs );
+                       goto done;
+               }
+
+               switch ( ml->sml_op ) {
+               case LDAP_MOD_DELETE:
+                       if ( ml->sml_nvalues != NULL ) {
+                               AccessControlState      acl_state = ACL_STATE_INIT;
+
+                               for ( i = 0; !BER_BVISNULL( &ml->sml_nvalues[ i ] ); i++ ) {
+                                       Entry           *e;
+
+                                       op->o_bd->bd_info = (BackendInfo *)on->on_info;
+                                       /* access is checked with the original identity */
+                                       rc = access_allowed( op, target,
+                                                       mo->mo_ad_memberof,
+                                                       &ml->sml_nvalues[ i ],
+                                                       ACL_WDEL,
+                                                       &acl_state );
+                                       if ( rc == 0 ) {
+                                               rc = rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
+                                               rs->sr_text = NULL;
+                                               send_ldap_result( op, rs );
+                                               goto done2;
+                                       }
+
+                                       rc = be_entry_get_rw( op, &ml->sml_nvalues[ i ],
+                                                       NULL, NULL, 0, &e );
+                                       op->o_bd->bd_info = (BackendInfo *)on;
+                                       if ( rc != LDAP_SUCCESS ) {
+                                               if ( get_relax( op ) ) {
+                                                       continue;
+                                               }
+
+                                               if ( MEMBEROF_DANGLING_ERROR( mo ) ) {
+                                                       rc = rs->sr_err = LDAP_CONSTRAINT_VIOLATION;
+                                                       rs->sr_text = "deleting non-existing object "
+                                                               "as memberof";
+                                                       send_ldap_result( op, rs );
+                                                       goto done2;
+                                               }
+
+                                               if ( MEMBEROF_DANGLING_DROP( mo ) ) {
+                                                       int     j;
+       
+                                                       Debug( LDAP_DEBUG_ANY, "%s: memberof_op_modify(\"%s\"): "
+                                                               "memberof=\"%s\" does not exist (stripping...)\n",
+                                                               op->o_log_prefix, op->o_req_ndn.bv_val,
+                                                               ml->sml_nvalues[ i ].bv_val );
+       
+                                                       for ( j = i + 1; !BER_BVISNULL( &ml->sml_nvalues[ j ] ); j++ );
+                                                       ber_memfree( ml->sml_values[ i ].bv_val );
+                                                       BER_BVZERO( &ml->sml_values[ i ] );
+                                                       if ( ml->sml_nvalues != ml->sml_values ) {
+                                                               ber_memfree( ml->sml_nvalues[ i ].bv_val );
+                                                               BER_BVZERO( &ml->sml_nvalues[ i ] );
+                                                       }
+                                                       if ( j - i == 1 ) {
+                                                               break;
+                                                       }
+               
+                                                       AC_MEMCPY( &ml->sml_values[ i ], &ml->sml_values[ i + 1 ],
+                                                               sizeof( struct berval ) * ( j - i ) );
+                                                       if ( ml->sml_nvalues != ml->sml_values ) {
+                                                               AC_MEMCPY( &ml->sml_nvalues[ i ], &ml->sml_nvalues[ i + 1 ],
+                                                                       sizeof( struct berval ) * ( j - i ) );
+                                                       }
+                                                       i--;
+                                               }
+
+                                               continue;
+                                       }
+
+                                       /* access is checked with the original identity */
+                                       op->o_bd->bd_info = (BackendInfo *)on->on_info;
+                                       rc = access_allowed( op, e, mo->mo_ad_member,
+                                                       &op->o_req_ndn,
+                                                       ACL_WDEL, NULL );
+                                       be_entry_release_r( op, e );
+                                       op->o_bd->bd_info = (BackendInfo *)on;
+
+                                       if ( !rc ) {
+                                               rc = rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
+                                               rs->sr_text = "insufficient access to object referenced by memberof";
+                                               send_ldap_result( op, rs );
+                                               goto done;
+                                       }
+                               }
+
+                               if ( BER_BVISNULL( &ml->sml_nvalues[ 0 ] ) ) {
+                                       *mmlp = ml->sml_next;
+                                       slap_mod_free( &ml->sml_mod, 0 );
+                                       free( ml );
+                               }
+
+                               break;
+                       }
+                       /* fall thru */
+
+               case LDAP_MOD_REPLACE:
+
+                       op->o_bd->bd_info = (BackendInfo *)on->on_info;
+                       /* access is checked with the original identity */
+                       rc = access_allowed( op, target,
+                                       mo->mo_ad_memberof,
+                                       NULL,
+                                       ACL_WDEL, NULL );
+                       op->o_bd->bd_info = (BackendInfo *)on;
+                       if ( rc == 0 ) {
+                               rc = rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
+                               rs->sr_text = NULL;
+                               send_ldap_result( op, rs );
+                               goto done2;
+                       }
+
+                       if ( ml->sml_op == LDAP_MOD_DELETE ) {
+                               break;
+                       }
+                       /* fall thru */
+
+               case LDAP_MOD_ADD: {
+                       AccessControlState      acl_state = ACL_STATE_INIT;
+
+                       for ( i = 0; !BER_BVISNULL( &ml->sml_nvalues[ i ] ); i++ ) {
+                               Entry           *e;
+
+                               op->o_bd->bd_info = (BackendInfo *)on->on_info;
+                               /* access is checked with the original identity */
+                               rc = access_allowed( op, target,
+                                               mo->mo_ad_memberof,
+                                               &ml->sml_nvalues[ i ],
+                                               ACL_WADD,
+                                               &acl_state );
+                               if ( rc == 0 ) {
+                                       rc = rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
+                                       rs->sr_text = NULL;
+                                       send_ldap_result( op, rs );
+                                       goto done2;
+                               }
+
+                               rc = be_entry_get_rw( op, &ml->sml_nvalues[ i ],
+                                               NULL, NULL, 0, &e );
+                               op->o_bd->bd_info = (BackendInfo *)on;
+                               if ( rc != LDAP_SUCCESS ) {
+                                       if ( MEMBEROF_DANGLING_ERROR( mo ) ) {
+                                               rc = rs->sr_err = LDAP_CONSTRAINT_VIOLATION;
+                                               rs->sr_text = "adding non-existing object "
+                                                       "as memberof";
+                                               send_ldap_result( op, rs );
+                                               goto done2;
+                                       }
+
+                                       if ( MEMBEROF_DANGLING_DROP( mo ) ) {
+                                               int     j;
+
+                                               Debug( LDAP_DEBUG_ANY, "%s: memberof_op_modify(\"%s\"): "
+                                                       "memberof=\"%s\" does not exist (stripping...)\n",
+                                                       op->o_log_prefix, op->o_req_ndn.bv_val,
+                                                       ml->sml_nvalues[ i ].bv_val );
+
+                                               for ( j = i + 1; !BER_BVISNULL( &ml->sml_nvalues[ j ] ); j++ );
+                                               ber_memfree( ml->sml_values[ i ].bv_val );
+                                               BER_BVZERO( &ml->sml_values[ i ] );
+                                               if ( ml->sml_nvalues != ml->sml_values ) {
+                                                       ber_memfree( ml->sml_nvalues[ i ].bv_val );
+                                                       BER_BVZERO( &ml->sml_nvalues[ i ] );
+                                               }
+                                               if ( j - i == 1 ) {
+                                                       break;
+                                               }
+       
+                                               AC_MEMCPY( &ml->sml_values[ i ], &ml->sml_values[ i + 1 ],
+                                                       sizeof( struct berval ) * ( j - i ) );
+                                               if ( ml->sml_nvalues != ml->sml_values ) {
+                                                       AC_MEMCPY( &ml->sml_nvalues[ i ], &ml->sml_nvalues[ i + 1 ],
+                                                               sizeof( struct berval ) * ( j - i ) );
+                                               }
+                                               i--;
+                                       }
+
+                                       continue;
+                               }
+
+                               /* access is checked with the original identity */
+                               op->o_bd->bd_info = (BackendInfo *)on->on_info;
+                               rc = access_allowed( op, e, mo->mo_ad_member,
+                                               &op->o_req_ndn,
+                                               ACL_WDEL, NULL );
+                               be_entry_release_r( op, e );
+                               op->o_bd->bd_info = (BackendInfo *)on;
+
+                               if ( !rc ) {
+                                       rc = rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
+                                       rs->sr_text = "insufficient access to object referenced by memberof";
+                                       send_ldap_result( op, rs );
+                                       goto done;
+                               }
+                       }
+
+                       if ( BER_BVISNULL( &ml->sml_nvalues[ 0 ] ) ) {
+                               *mmlp = ml->sml_next;
+                               slap_mod_free( &ml->sml_mod, 0 );
+                               free( ml );
+                       }
+
+                       } break;
+
+               default:
+                       assert( 0 );
+               }
+
+done2:;
+               op->o_bd->bd_info = (BackendInfo *)on->on_info;
+               be_entry_release_r( op, target );
+               op->o_bd->bd_info = (BackendInfo *)on;
+       }
+
+       rc = SLAP_CB_CONTINUE;
+
+done:;
+       op->o_dn = save_dn;
+       op->o_ndn = save_ndn;
+       op->o_bd->bd_info = (BackendInfo *)on;
+
+       return rc;
+}
+
+/*
+ * response callback that adds memberof values when a group is added.
+ */
+static int
+memberof_res_add( Operation *op, SlapReply *rs )
+{
+       slap_overinst   *on = (slap_overinst *)op->o_bd->bd_info;
+       memberof_t      *mo = (memberof_t *)on->on_bi.bi_private;
+
+       int             i;
+
+       if ( MEMBEROF_REVERSE( mo ) ) {
+               Attribute       *ma;
+
+               ma = attr_find( op->ora_e->e_attrs, mo->mo_ad_memberof );
+               if ( ma != NULL ) {
+                       Operation       op2 = *op;
+                       SlapReply       rs2 = { 0 };
+
+                       /* relax is required to allow to add
+                        * a non-existing member */
+                       op2.o_relax = SLAP_CONTROL_CRITICAL;
+
+                       for ( i = 0; !BER_BVISNULL( &ma->a_nvals[ i ] ); i++ ) {
+               
+                               /* the modification is attempted
+                                * with the original identity */
+                               (void)memberof_value_modify( &op2, &rs2,
+                                       &ma->a_nvals[ i ], mo->mo_ad_member,
+                                       NULL, NULL, &op->o_req_dn, &op->o_req_ndn );
+                       }
+               }
+       }
+
+       if ( is_entry_objectclass( op->ora_e, mo->mo_oc_group, 0 ) ) {
+               Attribute       *a;
+
+               for ( a = attrs_find( op->ora_e->e_attrs, mo->mo_ad_member );
+                               a != NULL;
+                               a = attrs_find( a->a_next, mo->mo_ad_member ) )
+               {
+                       for ( i = 0; !BER_BVISNULL( &a->a_nvals[ i ] ); i++ ) {
+                               (void)memberof_value_modify( op, rs,
+                                               &a->a_nvals[ i ],
+                                               mo->mo_ad_memberof,
+                                               NULL, NULL,
+                                               &op->o_req_dn,
+                                               &op->o_req_ndn );
+                       }
+               }
+       }
+
+       return SLAP_CB_CONTINUE;
+}
+
+/*
+ * response callback that deletes memberof values when a group is deleted.
+ */
+static int
+memberof_res_delete( Operation *op, SlapReply *rs )
+{
+       slap_overinst   *on = (slap_overinst *)op->o_bd->bd_info;
+       memberof_t      *mo = (memberof_t *)on->on_bi.bi_private;
+
+       BerVarray       vals;
+       int             i;
+
+       vals = memberof_saved_member_get( op, &saved_member_vals );
+       if ( vals != NULL ) {
+               for ( i = 0; !BER_BVISNULL( &vals[ i ] ); i++ ) {
+                       (void)memberof_value_modify( op, rs,
+                                       &vals[ i ], mo->mo_ad_memberof,
+                                       &op->o_req_dn, &op->o_req_ndn,
+                                       NULL, NULL );
+               }
+
+               ber_bvarray_free( vals );
+       }
+
+       if ( MEMBEROF_REFINT( mo ) ) {
+               vals = memberof_saved_member_get( op, &saved_memberof_vals );
+               if ( vals != NULL ) {
+                       for ( i = 0; !BER_BVISNULL( &vals[ i ] ); i++ ) {
+                               (void)memberof_value_modify( op, rs,
+                                               &vals[ i ], mo->mo_ad_member,
+                                               &op->o_req_dn, &op->o_req_ndn,
+                                               NULL, NULL );
+                       }
+
+                       ber_bvarray_free( vals );
+               }
+       }
+
+       return SLAP_CB_CONTINUE;
+}
+
+/*
+ * response callback that adds/deletes memberof values when a group
+ * is modified.
+ */
+static int
+memberof_res_modify( Operation *op, SlapReply *rs )
+{
+       slap_overinst   *on = (slap_overinst *)op->o_bd->bd_info;
+       memberof_t      *mo = (memberof_t *)on->on_bi.bi_private;
+
+       int             i, rc;
+       Modifications   *ml, *mml = NULL;
+       BerVarray       vals;
+       memberof_is_t   iswhat = MEMBEROF_IS_GROUP;
+
+       if ( MEMBEROF_REVERSE( mo ) ) {
+               for ( ml = op->orm_modlist; ml; ml = ml->sml_next ) {
+                       if ( ml->sml_desc == mo->mo_ad_memberof ) {
+                               mml = ml;
+                               break;
+                       }
+               }
+       }
+
+       if ( mml != NULL ) {
+               BerVarray       vals = mml->sml_nvalues;
+
+               switch ( mml->sml_op ) {
+               case LDAP_MOD_DELETE:
+                       if ( vals != NULL ) {
+                               for ( i = 0; !BER_BVISNULL( &vals[ i ] ); i++ ) {
+                                       memberof_value_modify( op, rs,
+                                                       &vals[ i ], mo->mo_ad_member,
+                                                       &op->o_req_dn, &op->o_req_ndn,
+                                                       NULL, NULL );
+                               }
+                               break;
+                       }
+                       /* fall thru */
+
+               case LDAP_MOD_REPLACE:
+                       /* delete all ... */
+                       op->o_bd->bd_info = (BackendInfo *)on->on_info;
+                       rc = backend_attribute( op, NULL, &op->o_req_ndn,
+                                       mo->mo_ad_memberof, &vals, ACL_READ );
+                       op->o_bd->bd_info = (BackendInfo *)on;
+                       if ( rc == LDAP_SUCCESS ) {
+                               for ( i = 0; !BER_BVISNULL( &vals[ i ] ); i++ ) {
+                                       (void)memberof_value_modify( op, rs,
+                                                       &vals[ i ], mo->mo_ad_member,
+                                                       &op->o_req_dn, &op->o_req_ndn,
+                                                       NULL, NULL );
+                               }
+                               ber_bvarray_free_x( vals, op->o_tmpmemctx );
+                       }
+
+                       if ( ml->sml_op == LDAP_MOD_DELETE ) {
+                               break;
+                       }
+                       /* fall thru */
+
+               case LDAP_MOD_ADD:
+                       assert( vals != NULL );
+
+                       for ( i = 0; !BER_BVISNULL( &vals[ i ] ); i++ ) {
+                               memberof_value_modify( op, rs,
+                                               &vals[ i ], mo->mo_ad_member,
+                                               NULL, NULL,
+                                               &op->o_req_dn, &op->o_req_ndn );
+                       }
+                       break;
+
+               default:
+                       assert( 0 );
+               }
+       }
+
+       if ( memberof_isGroupOrMember( op, &iswhat ) == LDAP_SUCCESS
+                       && ( iswhat & MEMBEROF_IS_GROUP ) )
+       {
+               for ( ml = op->orm_modlist; ml; ml = ml->sml_next ) {
+                       if ( ml->sml_desc != mo->mo_ad_member ) {
+                               continue;
+                       }
+
+                       switch ( ml->sml_op ) {
+                       case LDAP_MOD_DELETE:
+                               vals = ml->sml_nvalues;
+                               if ( vals != NULL ) {
+                                       for ( i = 0; !BER_BVISNULL( &vals[ i ] ); i++ ) {
+                                               memberof_value_modify( op, rs,
+                                                               &vals[ i ], mo->mo_ad_memberof,
+                                                               &op->o_req_dn, &op->o_req_ndn,
+                                                               NULL, NULL );
+                                       }
+                                       break;
+                               }
+                               /* fall thru */
+       
+                       case LDAP_MOD_REPLACE:
+                               /* delete all ... */
+                               op->o_bd->bd_info = (BackendInfo *)on->on_info;
+                               rc = backend_attribute( op, NULL, &op->o_req_ndn,
+                                               mo->mo_ad_member, &vals, ACL_READ );
+                               op->o_bd->bd_info = (BackendInfo *)on;
+                               if ( rc == LDAP_SUCCESS ) {
+                                       for ( i = 0; !BER_BVISNULL( &vals[ i ] ); i++ ) {
+                                               (void)memberof_value_modify( op, rs,
+                                                               &vals[ i ], mo->mo_ad_memberof,
+                                                               &op->o_req_dn, &op->o_req_ndn,
+                                                               NULL, NULL );
+                                       }
+                                       ber_bvarray_free_x( vals, op->o_tmpmemctx );
+                               }
+       
+                               if ( ml->sml_op == LDAP_MOD_DELETE ) {
+                                       break;
+                               }
+                               /* fall thru */
+       
+                       case LDAP_MOD_ADD:
+                               assert( ml->sml_nvalues != NULL );
+                               vals = ml->sml_nvalues;
+                               for ( i = 0; !BER_BVISNULL( &vals[ i ] ); i++ ) {
+                                       memberof_value_modify( op, rs,
+                                                       &vals[ i ], mo->mo_ad_memberof,
+                                                       NULL, NULL,
+                                                       &op->o_req_dn, &op->o_req_ndn );
+                               }
+                               break;
+       
+                       default:
+                               assert( 0 );
+                       }
+               }
+       }
+
+       return SLAP_CB_CONTINUE;
+}
+
+/*
+ * response callback that adds/deletes member values when a group member
+ * is modified.
+ */
+static int
+memberof_res_rename( Operation *op, SlapReply *rs )
+{
+       slap_overinst   *on = (slap_overinst *)op->o_bd->bd_info;
+       memberof_t      *mo = (memberof_t *)on->on_bi.bi_private;
+
+       struct berval   newPDN, newDN = BER_BVNULL, newPNDN, newNDN;
+       int             i, rc;
+       BerVarray       vals;
+
+       struct berval   save_dn, save_ndn;
+       memberof_is_t   iswhat = MEMBEROF_IS_GROUP;
+
+       if ( MEMBEROF_REFINT( mo ) ) {
+               iswhat |= MEMBEROF_IS_MEMBER;
+       }
+
+       if ( op->orr_nnewSup ) {
+               newPNDN = *op->orr_nnewSup;
+
+       } else {
+               dnParent( &op->o_req_ndn, &newPNDN );
+       }
+
+       build_new_dn( &newNDN, &newPNDN, &op->orr_nnewrdn, op->o_tmpmemctx ); 
+
+       save_dn = op->o_req_dn;
+       save_ndn = op->o_req_ndn;
+
+       op->o_req_dn = newNDN;
+       op->o_req_ndn = newNDN;
+       rc = memberof_isGroupOrMember( op, &iswhat );
+       op->o_req_dn = save_dn;
+       op->o_req_ndn = save_ndn;
+
+       if ( rc != LDAP_SUCCESS || iswhat == MEMBEROF_IS_NONE ) {
+               goto done;
+       }
+
+       if ( op->orr_newSup ) {
+               newPDN = *op->orr_newSup;
+
+       } else {
+               dnParent( &op->o_req_dn, &newPDN );
+       }
+
+       build_new_dn( &newDN, &newPDN, &op->orr_newrdn, op->o_tmpmemctx ); 
+
+       if ( iswhat & MEMBEROF_IS_GROUP ) {
+               op->o_bd->bd_info = (BackendInfo *)on->on_info;
+               rc = backend_attribute( op, NULL, &newNDN,
+                               mo->mo_ad_member, &vals, ACL_READ );
+               op->o_bd->bd_info = (BackendInfo *)on;
+
+               if ( rc == LDAP_SUCCESS ) {
+                       for ( i = 0; !BER_BVISNULL( &vals[ i ] ); i++ ) {
+                               (void)memberof_value_modify( op, rs,
+                                               &vals[ i ], mo->mo_ad_memberof,
+                                               &op->o_req_dn, &op->o_req_ndn,
+                                               &newDN, &newNDN );
+                       }
+                       ber_bvarray_free_x( vals, op->o_tmpmemctx );
+               }
+       }
+
+       if ( MEMBEROF_REFINT( mo ) && ( iswhat & MEMBEROF_IS_MEMBER ) ) {
+               op->o_bd->bd_info = (BackendInfo *)on->on_info;
+               rc = backend_attribute( op, NULL, &newNDN,
+                               mo->mo_ad_memberof, &vals, ACL_READ );
+               op->o_bd->bd_info = (BackendInfo *)on;
+
+               if ( rc == LDAP_SUCCESS ) {
+                       for ( i = 0; !BER_BVISNULL( &vals[ i ] ); i++ ) {
+                               (void)memberof_value_modify( op, rs,
+                                               &vals[ i ], mo->mo_ad_member,
+                                               &op->o_req_dn, &op->o_req_ndn,
+                                               &newDN, &newNDN );
+                       }
+                       ber_bvarray_free_x( vals, op->o_tmpmemctx );
+               }
+       }
+
+done:;
+       if ( !BER_BVISNULL( &newDN ) ) {
+               op->o_tmpfree( newDN.bv_val, op->o_tmpmemctx );
+       }
+       op->o_tmpfree( newNDN.bv_val, op->o_tmpmemctx );
+
+       return SLAP_CB_CONTINUE;
+}
+
+static int
+memberof_response( Operation *op, SlapReply *rs )
+{
+       if ( rs->sr_err != LDAP_SUCCESS ) {
+               return SLAP_CB_CONTINUE;
+       }
+
+       switch ( op->o_tag ) {
+       case LDAP_REQ_ADD:
+               return memberof_res_add( op, rs );
+
+       case LDAP_REQ_DELETE:
+               return memberof_res_delete( op, rs );
+
+       case LDAP_REQ_MODIFY:
+               return memberof_res_modify( op, rs );
+
+       case LDAP_REQ_MODDN:
+               return memberof_res_rename( op, rs );
+
+       default:
+               return SLAP_CB_CONTINUE;
+       }
+}
+
+static int
+memberof_db_init(
+       BackendDB       *be,
+       ConfigReply     *cr )
+{
+       slap_overinst   *on = (slap_overinst *)be->bd_info;
+       memberof_t      *mo;
+
+       int             rc;
+       const char      *text = NULL;
+
+       mo = (memberof_t *)ch_calloc( 1, sizeof( memberof_t ) );
+
+       rc = slap_str2ad( SLAPD_MEMBEROF_ATTR, &mo->mo_ad_memberof, &text );
+       if ( rc != LDAP_SUCCESS ) {
+               Debug( LDAP_DEBUG_ANY,
+                       "memberof_db_init: "
+                       "unable to find attribute=\"%s\": %s (%d)\n",
+                       SLAPD_MEMBEROF_ATTR, text, rc );
+               return rc;
+       }
+
+       rc = slap_str2ad( SLAPD_GROUP_ATTR, &mo->mo_ad_member, &text );
+       if ( rc != LDAP_SUCCESS ) {
+               Debug( LDAP_DEBUG_ANY,
+                       "memberof_db_init: "
+                       "unable to find attribute=\"%s\": %s (%d)\n",
+                       SLAPD_GROUP_ATTR, text, rc );
+               return rc;
+       }
+
+       mo->mo_oc_group = oc_find( SLAPD_GROUP_CLASS );
+       if ( mo->mo_oc_group == NULL ) {
+               Debug( LDAP_DEBUG_ANY,
+                       "memberof_db_init: "
+                       "unable to find objectClass=\"%s\"\n",
+                       SLAPD_GROUP_CLASS, 0, 0 );
+               return 1;
+       }
+
+       on->on_bi.bi_private = (void *)mo;
+
+       return 0;
+}
+
+enum {
+       MO_DN = 1,
+       MO_DANGLING,
+       MO_REFINT,
+#if 0
+       MO_REVERSE,
+#endif
+       MO_GROUP_OC,
+       MO_MEMBER_AD,
+       MO_MEMBER_OF_AD
+};
+
+static ConfigDriver mo_cf_gen;
+
+#define OID            "1.3.6.1.4.1.7136.2.666.4"
+#define        OIDAT           OID ".1.1"
+#define        OIDCFGAT        OID ".1.2"
+#define        OIDOC           OID ".2.1"
+#define        OIDCFGOC        OID ".2.2"
+
+
+static ConfigTable mo_cfg[] = {
+       { "memberof-dn", "modifiersName",
+               2, 2, 0, ARG_MAGIC|ARG_DN|MO_DN, mo_cf_gen,
+               "( OLcfgOvAt:18.0 NAME 'olcMemberOfDN' "
+                       "DESC 'DN to be used as modifiersName' "
+                       "SYNTAX OMsDN SINGLE-VALUE )",
+               NULL, NULL },
+
+       { "memberof-dangling", "ignore|drop|error",
+               2, 2, 0, ARG_MAGIC|MO_DANGLING, mo_cf_gen,
+               "( OLcfgOvAt:18.1 NAME 'olcMemberOfDangling' "
+                       "DESC 'Behavior with respect to dangling members, "
+                               "constrained to ignore, drop, error' "
+                       "SYNTAX OMsDirectoryString SINGLE-VALUE )",
+               NULL, NULL },
+
+       { "memberof-refint", "true|FALSE",
+               2, 2, 0, ARG_MAGIC|ARG_ON_OFF|MO_REFINT, mo_cf_gen,
+               "( OLcfgOvAt:18.2 NAME 'olcMemberOfRefInt' "
+                       "DESC 'Take care of referential integrity' "
+                       "SYNTAX OMsBoolean SINGLE-VALUE )",
+               NULL, NULL },
+
+       { "memberof-group-oc", "objectClass",
+               2, 2, 0, ARG_MAGIC|MO_GROUP_OC, mo_cf_gen,
+               "( OLcfgOvAt:18.3 NAME 'olcMemberOfGroupOC' "
+                       "DESC 'Group objectClass' "
+                       "SYNTAX OMsDirectoryString SINGLE-VALUE )",
+               NULL, NULL },
+
+       { "memberof-member-ad", "member attribute",
+               2, 2, 0, ARG_MAGIC|MO_MEMBER_AD, mo_cf_gen,
+               "( OLcfgOvAt:18.4 NAME 'olcMemberOfMemberAD' "
+                       "DESC 'member attribute' "
+                       "SYNTAX OMsDirectoryString SINGLE-VALUE )",
+               NULL, NULL },
+
+       { "memberof-memberof-ad", "memberOf attribute",
+               2, 2, 0, ARG_MAGIC|MO_MEMBER_OF_AD, mo_cf_gen,
+               "( OLcfgOvAt:18.5 NAME 'olcMemberOfMemberOfAD' "
+                       "DESC 'memberOf attribute' "
+                       "SYNTAX OMsDirectoryString SINGLE-VALUE )",
+               NULL, NULL },
+
+#if 0
+       { "memberof-reverse", "true|FALSE",
+               2, 2, 0, ARG_MAGIC|ARG_ON_OFF|MO_REVERSE, mo_cf_gen,
+               "( OLcfgOvAt:18.6 NAME 'olcMemberOfReverse' "
+                       "DESC 'Take care of referential integrity "
+                               "also when directly modifying memberOf' "
+                       "SYNTAX OMsBoolean SINGLE-VALUE )",
+               NULL, NULL },
+#endif
+
+       { NULL, NULL, 0, 0, 0, ARG_IGNORED }
+};
+
+static ConfigOCs mo_ocs[] = {
+       { "( OLcfgOvOc:18.1 "
+               "NAME 'olcMemberOf' "
+               "DESC 'Member-of configuration' "
+               "SUP olcOverlayConfig "
+               "MAY ( "
+                       "olcMemberOfDN "
+                       "$ olcMemberOfDangling "
+                       "$ olcMemberOfRefInt "
+                       "$ olcMemberOfGroupOC "
+                       "$ olcMemberOfMemberAD "
+                       "$ olcMemberOfMemberOfAD "
+#if 0
+                       "$ olcMemberOfReverse "
+#endif
+                       ") "
+               ")",
+               Cft_Overlay, mo_cfg, NULL, NULL },
+       { NULL, 0, NULL }
+};
+
+static slap_verbmasks dangling_mode[] = {
+       { BER_BVC( "ignore" ),          MEMBEROF_NONE },
+       { BER_BVC( "drop" ),            MEMBEROF_FDANGLING_DROP },
+       { BER_BVC( "error" ),           MEMBEROF_FDANGLING_ERROR },
+       { BER_BVNULL,                   0 }
+};
+
+static int
+memberof_make_group_filter( memberof_t *mo )
+{
+       char            *ptr;
+
+       if ( !BER_BVISNULL( &mo->mo_groupFilterstr ) ) {
+               ch_free( mo->mo_groupFilterstr.bv_val );
+       }
+
+       mo->mo_groupFilter.f_choice = LDAP_FILTER_EQUALITY;
+       mo->mo_groupFilter.f_ava = &mo->mo_groupAVA;
+       
+       mo->mo_groupFilter.f_av_desc = slap_schema.si_ad_objectClass;
+       mo->mo_groupFilter.f_av_value = mo->mo_oc_group->soc_cname;
+
+       mo->mo_groupFilterstr.bv_len = STRLENOF( "(=)" )
+               + slap_schema.si_ad_objectClass->ad_cname.bv_len
+               + mo->mo_oc_group->soc_cname.bv_len;
+       ptr = mo->mo_groupFilterstr.bv_val = ch_malloc( mo->mo_groupFilterstr.bv_len + 1 );
+       *ptr++ = '(';
+       ptr = lutil_strcopy( ptr, slap_schema.si_ad_objectClass->ad_cname.bv_val );
+       *ptr++ = '=';
+       ptr = lutil_strcopy( ptr, mo->mo_oc_group->soc_cname.bv_val );
+       *ptr++ = ')';
+       *ptr = '\0';
+
+       return 0;
+}
+
+static int
+memberof_make_member_filter( memberof_t *mo )
+{
+       char            *ptr;
+
+       if ( !BER_BVISNULL( &mo->mo_memberFilterstr ) ) {
+               ch_free( mo->mo_memberFilterstr.bv_val );
+       }
+
+       mo->mo_memberFilter.f_choice = LDAP_FILTER_PRESENT;
+       mo->mo_memberFilter.f_desc = mo->mo_ad_memberof;
+
+       mo->mo_memberFilterstr.bv_len = STRLENOF( "(=*)" )
+               + mo->mo_ad_memberof->ad_cname.bv_len;
+       ptr = mo->mo_memberFilterstr.bv_val = ch_malloc( mo->mo_memberFilterstr.bv_len + 1 );
+       *ptr++ = '(';
+       ptr = lutil_strcopy( ptr, mo->mo_ad_memberof->ad_cname.bv_val );
+       ptr = lutil_strcopy( ptr, "=*)" );
+
+       return 0;
+}
+
+static int
+mo_cf_gen( ConfigArgs *c )
+{
+       slap_overinst   *on = (slap_overinst *)c->bi;
+       memberof_t      *mo = (memberof_t *)on->on_bi.bi_private;
+
+       int             i, rc = 0;
+
+       if ( c->op == SLAP_CONFIG_EMIT ) {
+               struct berval bv = BER_BVNULL;
+
+               switch( c->type ) {
+               case MO_DN:
+                       value_add_one( &c->rvalue_vals, &mo->mo_dn );
+                       value_add_one( &c->rvalue_nvals, &mo->mo_ndn );
+                       break;
+
+               case MO_DANGLING:
+                       enum_to_verb( dangling_mode, (mo->mo_flags & MEMBEROF_FDANGLING_MASK), &bv );
+                       if ( BER_BVISNULL( &bv ) ) {
+                               /* there's something wrong... */
+                               assert( 0 );
+                               rc = 1;
+
+                       } else {
+                               value_add_one( &c->rvalue_vals, &bv );
+                       }
+                       break;
+
+               case MO_REFINT:
+                       c->value_int = MEMBEROF_REFINT( mo );
+                       break;
+
+#if 0
+               case MO_REVERSE:
+                       c->value_int = MEMBEROF_REVERSE( mo );
+                       break;
+#endif
+
+               case MO_GROUP_OC:
+                       assert( mo->mo_oc_group != NULL );
+                       value_add_one( &c->rvalue_vals, &mo->mo_oc_group->soc_cname );
+                       break;
+
+               case MO_MEMBER_AD:
+                       assert( mo->mo_ad_member != NULL );
+                       value_add_one( &c->rvalue_vals, &mo->mo_ad_member->ad_cname );
+                       break;
+
+               case MO_MEMBER_OF_AD:
+                       assert( mo->mo_ad_memberof != NULL );
+                       value_add_one( &c->rvalue_vals, &mo->mo_ad_memberof->ad_cname );
+                       break;
+
+               default:
+                       assert( 0 );
+                       return 1;
+               }
+
+               return rc;
+
+       } else if ( c->op == LDAP_MOD_DELETE ) {
+               return 1;       /* FIXME */
+
+       } else {
+               switch( c->type ) {
+               case MO_DN:
+                       if ( !BER_BVISNULL( &mo->mo_dn ) ) {
+                               ber_memfree( mo->mo_dn.bv_val );
+                               ber_memfree( mo->mo_ndn.bv_val );
+                       }
+                       mo->mo_dn = c->value_dn;
+                       mo->mo_ndn = c->value_ndn;
+                       break;
+
+               case MO_DANGLING:
+                       i = verb_to_mask( c->argv[ 1 ], dangling_mode );
+                       if ( BER_BVISNULL( &dangling_mode[ i ].word ) ) {
+                               return 1;
+                       }
+
+                       mo->mo_flags &= ~MEMBEROF_FDANGLING_MASK;
+                       mo->mo_flags |= dangling_mode[ i ].mask;
+                       break;
+
+               case MO_REFINT:
+                       if ( c->value_int ) {
+                               mo->mo_flags |= MEMBEROF_FREFINT;
+
+                       } else {
+                               mo->mo_flags &= ~MEMBEROF_FREFINT;
+                       }
+                       break;
+
+#if 0
+               case MO_REVERSE:
+                       if ( c->value_int ) {
+                               mo->mo_flags |= MEMBEROF_FREVERSE;
+
+                       } else {
+                               mo->mo_flags &= ~MEMBEROF_FREVERSE;
+                       }
+                       break;
+#endif
+
+               case MO_GROUP_OC: {
+                       ObjectClass     *oc = NULL;
+
+                       oc = oc_find( c->argv[ 1 ] );
+                       if ( oc == NULL ) {
+                               snprintf( c->cr_msg, sizeof( c->cr_msg ),
+                                       "unable to find group objectClass=\"%s\"",
+                                       c->argv[ 1 ] );
+                               Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n",
+                                       c->log, c->cr_msg, 0 );
+                               return 1;
+                       }
+
+                       mo->mo_oc_group = oc;
+                       memberof_make_group_filter( mo );
+                       } break;
+
+               case MO_MEMBER_AD: {
+                       AttributeDescription    *ad = NULL;
+                       const char              *text = NULL;
+
+
+                       rc = slap_str2ad( c->argv[ 1 ], &ad, &text );
+                       if ( rc != LDAP_SUCCESS ) {
+                               snprintf( c->cr_msg, sizeof( c->cr_msg ),
+                                       "unable to find member attribute=\"%s\": %s (%d)",
+                                       c->argv[ 1 ], text, rc );
+                               Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n",
+                                       c->log, c->cr_msg, 0 );
+                               return 1;
+                       }
+
+                       if ( !is_at_syntax( ad->ad_type, SLAPD_DN_SYNTAX )              /* e.g. "member" */
+                               && !is_at_syntax( ad->ad_type, SLAPD_NAMEUID_SYNTAX ) ) /* e.g. "uniqueMember" */
+                       {
+                               snprintf( c->cr_msg, sizeof( c->cr_msg ),
+                                       "member attribute=\"%s\" must either "
+                                       "have DN (%s) or nameUID (%s) syntax",
+                                       c->argv[ 1 ], SLAPD_DN_SYNTAX, SLAPD_NAMEUID_SYNTAX );
+                               Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n",
+                                       c->log, c->cr_msg, 0 );
+                               return 1;
+                       }
+
+                       mo->mo_ad_member = ad;
+                       } break;
+
+               case MO_MEMBER_OF_AD: {
+                       AttributeDescription    *ad = NULL;
+                       const char              *text = NULL;
+
+
+                       rc = slap_str2ad( c->argv[ 1 ], &ad, &text );
+                       if ( rc != LDAP_SUCCESS ) {
+                               snprintf( c->cr_msg, sizeof( c->cr_msg ),
+                                       "unable to find memberof attribute=\"%s\": %s (%d)",
+                                       c->argv[ 1 ], text, rc );
+                               Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n",
+                                       c->log, c->cr_msg, 0 );
+                               return 1;
+                       }
+
+                       if ( !is_at_syntax( ad->ad_type, SLAPD_DN_SYNTAX )              /* e.g. "member" */
+                               && !is_at_syntax( ad->ad_type, SLAPD_NAMEUID_SYNTAX ) ) /* e.g. "uniqueMember" */
+                       {
+                               snprintf( c->cr_msg, sizeof( c->cr_msg ),
+                                       "memberof attribute=\"%s\" must either "
+                                       "have DN (%s) or nameUID (%s) syntax",
+                                       c->argv[ 1 ], SLAPD_DN_SYNTAX, SLAPD_NAMEUID_SYNTAX );
+                               Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n",
+                                       c->log, c->cr_msg, 0 );
+                               return 1;
+                       }
+
+                       mo->mo_ad_memberof = ad;
+                       memberof_make_member_filter( mo );
+                       } break;
+
+               default:
+                       assert( 0 );
+                       return 1;
+               }
+       }
+
+       return 0;
+}
+
+static int
+memberof_db_open(
+       BackendDB       *be,
+       ConfigReply     *cr )
+{
+       slap_overinst   *on = (slap_overinst *)be->bd_info;
+       memberof_t      *mo = (memberof_t *)on->on_bi.bi_private;
+
+       if ( BER_BVISNULL( &mo->mo_dn ) ) {
+               ber_dupbv( &mo->mo_dn, &be->be_rootdn );
+               ber_dupbv( &mo->mo_ndn, &be->be_rootndn );
+       }
+
+       if ( BER_BVISNULL( &mo->mo_groupFilterstr ) ) {
+               memberof_make_group_filter( mo );
+       }
+
+       if ( BER_BVISNULL( &mo->mo_memberFilterstr ) ) {
+               memberof_make_member_filter( mo );
+       }
+
+       return 0;
+}
+
+static int
+memberof_db_destroy(
+       BackendDB       *be,
+       ConfigReply     *cr )
+{
+       slap_overinst   *on = (slap_overinst *)be->bd_info;
+       memberof_t      *mo = (memberof_t *)on->on_bi.bi_private;
+
+       if ( mo ) {
+               if ( !BER_BVISNULL( &mo->mo_dn ) ) {
+                       ber_memfree( mo->mo_dn.bv_val );
+                       ber_memfree( mo->mo_ndn.bv_val );
+               }
+
+               if ( !BER_BVISNULL( &mo->mo_groupFilterstr ) ) {
+                       ber_memfree( mo->mo_groupFilterstr.bv_val );
+               }
+
+               if ( !BER_BVISNULL( &mo->mo_memberFilterstr ) ) {
+                       ber_memfree( mo->mo_memberFilterstr.bv_val );
+               }
+
+               ber_memfree( mo );
+       }
+
+       return 0;
+}
+
+/* unused */
+static AttributeDescription    *ad_memberOf;
+
+static struct {
+       char    *desc;
+       AttributeDescription **adp;
+} as[] = {
+       { "( 1.2.840.113556.1.2.102 "
+               "NAME 'memberOf' "
+               "DESC 'Group that the entry belongs to' "
+               "SYNTAX '1.3.6.1.4.1.1466.115.121.1.12' "
+               "EQUALITY distinguishedNameMatch "      /* added */
+               "USAGE dSAOperation "                   /* added; questioned */
+               /* "NO-USER-MODIFICATION " */           /* add? */
+               "X-ORIGIN 'iPlanet Delegated Administrator' )",
+               &ad_memberOf },
+       { NULL }
+};
+
+#if SLAPD_OVER_MEMBEROF == SLAPD_MOD_DYNAMIC
+static
+#endif /* SLAPD_OVER_MEMBEROF == SLAPD_MOD_DYNAMIC */
+int
+memberof_initialize( void )
+{
+       int                     code, i;
+
+       for ( i = 0; as[ i ].desc != NULL; i++ ) {
+               code = register_at( as[ i ].desc, as[ i ].adp, 0 );
+               if ( code ) {
+                       Debug( LDAP_DEBUG_ANY,
+                               "memberof_initialize: register_at #%d failed\n",
+                               i, 0, 0 );
+                       return code;
+               }
+       }
+
+       memberof.on_bi.bi_type = "memberof";
+
+       memberof.on_bi.bi_db_init = memberof_db_init;
+       memberof.on_bi.bi_db_open = memberof_db_open;
+       memberof.on_bi.bi_db_destroy = memberof_db_destroy;
+
+       memberof.on_bi.bi_op_add = memberof_op_add;
+       memberof.on_bi.bi_op_delete = memberof_op_delete;
+       memberof.on_bi.bi_op_modify = memberof_op_modify;
+
+       memberof.on_response = memberof_response;
+
+       memberof.on_bi.bi_cf_ocs = mo_ocs;
+
+       code = config_register_schema( mo_cfg, mo_ocs );
+       if ( code ) return code;
+
+       return overlay_register( &memberof );
+}
+
+#if SLAPD_OVER_MEMBEROF == SLAPD_MOD_DYNAMIC
+int
+init_module( int argc, char *argv[] )
+{
+       return memberof_initialize();
+}
+#endif /* SLAPD_OVER_MEMBEROF == SLAPD_MOD_DYNAMIC */
+
+#endif /* SLAPD_OVER_MEMBEROF */
index 56bf2a29b21bdf7d51abf6d18dca544022268a49..ae3690c652df3aceda51945b3524b8da4d868f8b 100644 (file)
 
 #include "config.h"
 
+#ifdef LDAP_DEVEL
+/*
+ * Control that allows to access the private DB
+ * instead of the public one
+ */
+#define        PCACHE_CONTROL_PRIVDB           "1.3.6.1.4.1.4203.666.11.9.5.1"
+
+/*
+ * Extended Operation that allows to remove a query from the cache
+ */
+#define PCACHE_EXOP_QUERY_DELETE       "1.3.6.1.4.1.4203.666.11.9.6.1"
+#endif
+
 /* query cache structs */
 /* query */
 
@@ -59,7 +72,7 @@ typedef struct cached_query_s {
        Qbase                                   *qbase;
        int                                             scope;
        struct berval                   q_uuid;         /* query identifier */
-       struct query_template_s *qtemp; /* template of the query */
+       struct query_template_s         *qtemp; /* template of the query */
        time_t                          expiry_time;    /* time till the query is considered valid */
        struct cached_query_s           *next;          /* next query in the template */
        struct cached_query_s           *prev;          /* previous query in the template */
@@ -67,6 +80,22 @@ typedef struct cached_query_s {
        struct cached_query_s           *lru_down;      /* next query in the LRU list */
 } CachedQuery;
 
+/*
+ * URL representation:
+ *
+ * ldap:///<base>??<scope>?<filter>?x-uuid=<uid>,x-template=<template>,x-attrset=<attrset>,x-expiry=<expiry>
+ *
+ * <base> ::= CachedQuery.qbase->base
+ * <scope> ::= CachedQuery.scope
+ * <filter> ::= filter2bv(CachedQuery.filter)
+ * <uuid> ::= CachedQuery.q_uuid
+ * <attrset> ::= CachedQuery.qtemp->attr_set_index
+ * <expiry> ::= CachedQuery.expiry_time
+ *
+ * quick hack: parse URI, call add_query() and then fix
+ * CachedQuery.expiry_time and CachedQuery.q_uuid
+ */
+
 /*
  * Represents a set of projected attributes.
  */
@@ -131,6 +160,7 @@ typedef struct cache_manager_s {
        BackendDB       db;     /* underlying database */
        unsigned long   num_cached_queries;             /* total number of cached queries */
        unsigned long   max_queries;                    /* upper bound on # of cached queries */
+       int             save_queries;                   /* save cached queries across restarts */
        int     numattrsets;                    /* number of attribute sets */
        int     cur_entries;                    /* current number of entries cached */
        int     max_entries;                    /* max number of entries cached */
@@ -152,12 +182,299 @@ typedef struct cache_manager_s {
 
 static int pcache_debug;
 
-static AttributeDescription *ad_queryid;
-static char *queryid_schema = "( 1.3.6.1.4.1.4203.666.1.12 NAME 'queryid' "
-                       "DESC 'list of queries the entry belongs to' "
-                       "EQUALITY octetStringMatch "
-                       "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40{64} "
-                       "NO-USER-MODIFICATION USAGE directoryOperation )";
+#ifdef PCACHE_CONTROL_PRIVDB
+static int privDB_cid;
+#endif /* PCACHE_CONTROL_PRIVDB */
+
+static AttributeDescription *ad_queryId, *ad_cachedQueryURL;
+static struct {
+       char    *desc;
+       AttributeDescription **adp;
+} as[] = {
+       { "( 1.3.6.1.4.1.4203.666.11.9.1.1 "
+               "NAME 'queryId' "
+               "DESC 'ID of query the entry belongs to, formatted as a UUID' "
+               "EQUALITY octetStringMatch "
+               "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40{64} "
+               "NO-USER-MODIFICATION "
+               "USAGE directoryOperation )",
+               &ad_queryId },
+       { "( 1.3.6.1.4.1.4203.666.11.9.1.2 "
+               "NAME 'cachedQueryURL' "
+               "DESC 'URI describing a cached query' "
+               "EQUALITY caseExactMatch "
+               "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 "
+               "NO-USER-MODIFICATION "
+               "USAGE directoryOperation )",
+               &ad_cachedQueryURL },
+       { NULL }
+};
+
+static int
+filter2template(
+       Operation               *op,
+       Filter                  *f,
+       struct                  berval *fstr,
+       AttributeName**         filter_attrs,
+       int*                    filter_cnt,
+       int*                    filter_got_oc );
+
+static CachedQuery *
+add_query(
+       Operation *op,
+       query_manager* qm,
+       Query* query,
+       QueryTemplate *templ,
+       int positive);
+
+static int
+remove_query_data(
+       Operation       *op,
+       SlapReply       *rs,
+       struct berval   *query_uuid );
+
+/*
+ * Turn a cached query into its URL representation
+ */
+static int
+query2url( Operation *op, CachedQuery *q, struct berval *urlbv )
+{
+       struct berval   bv_scope,
+                       bv_filter;
+       char            attrset_buf[ 32 ],
+                       expiry_buf[ 32 ],
+                       *ptr;
+       ber_len_t       attrset_len,
+                       expiry_len;
+
+       ldap_pvt_scope2bv( q->scope, &bv_scope );
+       filter2bv_x( op, q->filter, &bv_filter );
+       attrset_len = snprintf( attrset_buf, sizeof( attrset_buf ),
+               "%lu", (unsigned long)q->qtemp->attr_set_index );
+       expiry_len = snprintf( expiry_buf, sizeof( expiry_buf ),
+               "%lu", (unsigned long)q->expiry_time );
+
+       urlbv->bv_len = STRLENOF( "ldap:///" )
+               + q->qbase->base.bv_len
+               + STRLENOF( "??" )
+               + bv_scope.bv_len
+               + STRLENOF( "?" )
+               + bv_filter.bv_len
+               + STRLENOF( "?x-uuid=" )
+               + q->q_uuid.bv_len
+               + STRLENOF( ",x-attrset=" )
+               + attrset_len
+               + STRLENOF( ",x-expiry=" )
+               + expiry_len;
+       ptr = urlbv->bv_val = ber_memalloc_x( urlbv->bv_len + 1, op->o_tmpmemctx );
+       ptr = lutil_strcopy( ptr, "ldap:///" );
+       ptr = lutil_strcopy( ptr, q->qbase->base.bv_val );
+       ptr = lutil_strcopy( ptr, "??" );
+       ptr = lutil_strcopy( ptr, bv_scope.bv_val );
+       ptr = lutil_strcopy( ptr, "?" );
+       ptr = lutil_strcopy( ptr, bv_filter.bv_val );
+       ptr = lutil_strcopy( ptr, "?x-uuid=" );
+       ptr = lutil_strcopy( ptr, q->q_uuid.bv_val );
+       ptr = lutil_strcopy( ptr, ",x-attrset=" );
+       ptr = lutil_strcopy( ptr, attrset_buf );
+       ptr = lutil_strcopy( ptr, ",x-expiry=" );
+       ptr = lutil_strcopy( ptr, expiry_buf );
+
+       ber_memfree_x( bv_filter.bv_val, op->o_tmpmemctx );
+
+       return 0;
+}
+
+/*
+ * Turn an URL representing a formerly cached query into a cached query,
+ * and try to cache it
+ */
+static int
+url2query(
+       char            *url,
+       Operation       *op,
+       query_manager   *qm )
+{
+       Query           query = { 0 };
+       QueryTemplate   *qt;
+       CachedQuery     *cq;
+       LDAPURLDesc     *lud = NULL;
+       struct berval   base,
+                       tempstr = BER_BVNULL,
+                       uuid;
+       int             attrset;
+       time_t          expiry_time;
+       int             i,
+                       got_uuid = 0,
+                       got_attrset = 0,
+                       got_expiry = 0,
+                       rc = 0;
+
+       rc = ldap_url_parse( url, &lud );
+       if ( rc != LDAP_URL_SUCCESS ) {
+               return -1;
+       }
+
+       /* non-allowed fields */
+       if ( lud->lud_host != NULL ) {
+               rc = 1;
+               goto error;
+       }
+
+       if ( lud->lud_attrs != NULL ) {
+               rc = 1;
+               goto error;
+       }
+
+       /* be pedantic */
+       if ( strcmp( lud->lud_scheme, "ldap" ) != 0 ) {
+               rc = 1;
+               goto error;
+       }
+
+       /* required fields */
+       if ( lud->lud_dn == NULL || lud->lud_dn[ 0 ] == '\0' ) {
+               rc = 1;
+               goto error;
+       }
+
+       switch ( lud->lud_scope ) {
+       case LDAP_SCOPE_BASE:
+       case LDAP_SCOPE_ONELEVEL:
+       case LDAP_SCOPE_SUBTREE:
+       case LDAP_SCOPE_SUBORDINATE:
+               break;
+
+       default:
+               rc = 1;
+               goto error;
+       }
+
+       if ( lud->lud_filter == NULL || lud->lud_filter[ 0 ] == '\0' ) {
+               rc = 1;
+               goto error;
+       }
+
+       if ( lud->lud_exts == NULL ) {
+               rc = 1;
+               goto error;
+       }
+
+       for ( i = 0; lud->lud_exts[ i ] != NULL; i++ ) {
+               if ( strncmp( lud->lud_exts[ i ], "x-uuid=", STRLENOF( "x-uuid=" ) ) == 0 ) {
+                       struct berval   tmpUUID;
+                       Syntax          *syn_UUID = slap_schema.si_ad_entryUUID->ad_type->sat_syntax;
+
+                       ber_str2bv( &lud->lud_exts[ i ][ STRLENOF( "x-uuid=" ) ], 0, 0, &tmpUUID );
+                       rc = syn_UUID->ssyn_pretty( syn_UUID, &tmpUUID, &uuid, NULL );
+                       if ( rc != LDAP_SUCCESS ) {
+                               goto error;
+                       }
+                       got_uuid = 1;
+
+               } else if ( strncmp( lud->lud_exts[ i ], "x-attrset=", STRLENOF( "x-attrset=" ) ) == 0 ) {
+                       rc = lutil_atoi( &attrset, &lud->lud_exts[ i ][ STRLENOF( "x-attrset=" ) ] );
+                       if ( rc ) {
+                               goto error;
+                       }
+                       got_attrset = 1;
+
+               } else if ( strncmp( lud->lud_exts[ i ], "x-expiry=", STRLENOF( "x-expiry=" ) ) == 0 ) {
+                       unsigned long l;
+
+                       rc = lutil_atoul( &l, &lud->lud_exts[ i ][ STRLENOF( "x-expiry=" ) ] );
+                       if ( rc ) {
+                               goto error;
+                       }
+                       expiry_time = (time_t)l;
+                       got_expiry = 1;
+
+               } else {
+                       rc = -1;
+                       goto error;
+               }
+       }
+
+       if ( !got_uuid ) {
+               rc = 1;
+               goto error;
+       }
+
+       if ( !got_attrset ) {
+               rc = 1;
+               goto error;
+       }
+
+       if ( !got_expiry ) {
+               rc = 1;
+               goto error;
+       }
+
+       /* ignore expired queries */
+       if ( expiry_time <= slap_get_time()) {
+               Operation       op2 = *op;
+               SlapReply       rs2 = { 0 };
+
+               memset( &op2.oq_search, 0, sizeof( op2.oq_search ) );
+
+               (void)remove_query_data( &op2, &rs2, &uuid );
+
+               rc = 0;
+
+       } else {
+               ber_str2bv( lud->lud_dn, 0, 0, &base );
+               rc = dnNormalize( 0, NULL, NULL, &base, &query.base, NULL );
+               if ( rc != LDAP_SUCCESS ) {
+                       goto error;
+               }
+               query.scope = lud->lud_scope;
+               query.filter = str2filter( lud->lud_filter );
+
+               tempstr.bv_val = ch_malloc( strlen( lud->lud_filter ) + 1 );
+               tempstr.bv_len = 0;
+               if ( filter2template( op, query.filter, &tempstr, NULL, NULL, NULL ) ) {
+                       ch_free( tempstr.bv_val );
+                       rc = -1;
+                       goto error;
+               }
+
+               /* check for query containment */
+               qt = qm->attr_sets[attrset].templates;
+               for ( ; qt; qt = qt->qtnext ) {
+                       /* find if template i can potentially answer tempstr */
+                       if ( bvmatch( &qt->querystr, &tempstr ) ) {
+                               break;
+                       }
+               }
+
+               if ( qt == NULL ) {
+                       rc = 1;
+                       goto error;
+               }
+
+               cq = add_query( op, qm, &query, qt, 1 );
+               if ( cq != NULL ) {
+                       cq->expiry_time = expiry_time;
+                       cq->q_uuid = uuid;
+
+                       /* it's now into cq->filter */
+                       BER_BVZERO( &uuid );
+                       query.filter = NULL;
+
+               } else {
+                       rc = 1;
+               }
+       }
+
+error:;
+       if ( query.filter != NULL ) filter_free( query.filter );
+       if ( !BER_BVISNULL( &tempstr ) ) ch_free( tempstr.bv_val );
+       if ( !BER_BVISNULL( &query.base ) ) ch_free( query.base.bv_val );
+       if ( !BER_BVISNULL( &uuid ) ) ch_free( uuid.bv_val );
+       if ( lud != NULL ) ldap_free_urldesc( lud );
+
+       return rc;
+}
 
 /* Return 1 for an added entry, else 0 */
 static int
@@ -180,8 +497,8 @@ merge_entry(
        attr = e->e_attrs;
        e->e_attrs = NULL;
 
-       /* add queryid attribute */
-       attr_merge_one( e, ad_queryid, query_uuid, NULL );
+       /* add queryId attribute */
+       attr_merge_one( e, ad_queryId, query_uuid, NULL );
 
        /* append the attribute list from the fetched entry */
        e->e_attrs->a_next = attr;
@@ -812,7 +1129,8 @@ free_query (CachedQuery* qc)
 
 
 /* Add query to query cache */
-static CachedQuery * add_query(
+static CachedQuery *
+add_query(
        Operation *op,
        query_manager* qm,
        Query* query,
@@ -849,7 +1167,7 @@ static CachedQuery * add_query(
        qbase = avl_find( templ->qbase, &qb, pcache_dn_cmp );
        if ( !qbase ) {
                qbase = ch_calloc( 1, sizeof(Qbase) + qb.base.bv_len + 1 );
-               qbase->base.bv_len =qb.base.bv_len;
+               qbase->base.bv_len = qb.base.bv_len;
                qbase->base.bv_val = (char *)(qbase+1);
                memcpy( qbase->base.bv_val, qb.base.bv_val, qb.base.bv_len );
                qbase->base.bv_val[qbase->base.bv_len] = '\0';
@@ -917,23 +1235,50 @@ remove_from_template (CachedQuery* qc, QueryTemplate* template)
 }
 
 /* remove bottom query of LRU list from the query cache */
-static void cache_replacement(query_manager* qm, struct berval *result)
+/*
+ * NOTE: slight change in functionality.
+ *
+ * - if result->bv_val is NULL, the query at the bottom of the LRU
+ *   is removed
+ * - otherwise, the query whose UUID is *result is removed
+ *     - if not found, result->bv_val is zeroed
+ */
+static void
+cache_replacement(query_manager* qm, struct berval *result)
 {
        CachedQuery* bottom;
        QueryTemplate *temp;
 
        ldap_pvt_thread_mutex_lock(&qm->lru_mutex);
-       bottom = qm->lru_bottom;
+       if ( BER_BVISNULL( result ) ) {
+               bottom = qm->lru_bottom;
+
+               if (!bottom) {
+                       Debug ( pcache_debug,
+                               "Cache replacement invoked without "
+                               "any query in LRU list\n", 0, 0, 0 );
+                       ldap_pvt_thread_mutex_unlock(&qm->lru_mutex);
+                       return;
+               }
 
-       result->bv_val = NULL;
-       result->bv_len = 0;
+       } else {
+               for ( bottom = qm->lru_bottom;
+                       bottom != NULL;
+                       bottom = bottom->lru_up )
+               {
+                       if ( bvmatch( result, &bottom->q_uuid ) ) {
+                               break;
+                       }
+               }
 
-       if (!bottom) {
-               Debug ( pcache_debug,
-                       "Cache replacement invoked without "
-                       "any query in LRU list\n", 0, 0, 0 );
-               ldap_pvt_thread_mutex_unlock(&qm->lru_mutex);
-               return;
+               if ( !bottom ) {
+                       Debug ( pcache_debug,
+                               "Could not find query with uuid=\"%s\""
+                               "in LRU list\n", result->bv_val, 0, 0 );
+                       ldap_pvt_thread_mutex_unlock(&qm->lru_mutex);
+                       BER_BVZERO( result );
+                       return;
+               }
        }
 
        temp = bottom->qtemp;
@@ -971,14 +1316,12 @@ remove_func (
 
        if ( rs->sr_type != REP_SEARCH ) return 0;
 
-       for (attr = rs->sr_entry->e_attrs; attr!= NULL; attr = attr->a_next) {
-               if (attr->a_desc == ad_queryid) {
-                       for (count=0; attr->a_vals[count].bv_val; count++)
-                               ;
-                       break;
-               }
-       }
-       if ( count == 0 ) return 0;
+       attr = attr_find( rs->sr_entry->e_attrs,  ad_queryId );
+       if ( attr == NULL ) return 0;
+
+       for ( count = 0; !BER_BVISNULL( &attr->a_vals[count] ); count++ )
+               ;
+       assert( count > 0 );
        qi = op->o_tmpalloc( sizeof( struct query_info ), op->o_tmpmemctx );
        qi->next = op->o_callback->sc_private;
        op->o_callback->sc_private = qi;
@@ -989,13 +1332,13 @@ remove_func (
 }
 
 static int
-remove_query_data (
+remove_query_data(
        Operation       *op,
        SlapReply       *rs,
-       struct berval* query_uuid)
+       struct berval   *query_uuid )
 {
        struct query_info       *qi, *qnext;
-       char                    filter_str[64];
+       char                    filter_str[ LDAP_LUTIL_UUIDSTR_BUFSIZE + STRLENOF( "(queryId=)" ) ];
 #ifdef LDAP_COMP_MATCH
        AttributeAssertion      ava = { NULL, BER_BVNULL, NULL };
 #else
@@ -1009,9 +1352,9 @@ remove_query_data (
        sreply.sr_entry = NULL;
        sreply.sr_nentries = 0;
        op->ors_filterstr.bv_len = snprintf(filter_str, sizeof(filter_str),
-               "(%s=%s)", ad_queryid->ad_cname.bv_val, query_uuid->bv_val);
+               "(%s=%s)", ad_queryId->ad_cname.bv_val, query_uuid->bv_val);
        filter.f_ava = &ava;
-       filter.f_av_desc = ad_queryid;
+       filter.f_av_desc = ad_queryId;
        filter.f_av_value = *query_uuid;
 
        op->o_tag = LDAP_REQ_SEARCH;
@@ -1040,7 +1383,7 @@ remove_query_data (
                op->o_req_dn = qi->xdn;
                op->o_req_ndn = qi->xdn;
 
-               if ( qi->del) {
+               if ( qi->del ) {
                        Debug( pcache_debug, "DELETING ENTRY TEMPLATE=%s\n",
                                query_uuid->bv_val, 0, 0 );
 
@@ -1049,6 +1392,7 @@ remove_query_data (
                        if (op->o_bd->be_delete(op, &sreply) == LDAP_SUCCESS) {
                                deleted++;
                        }
+
                } else {
                        Modifications mod;
                        struct berval vals[2];
@@ -1058,8 +1402,8 @@ remove_query_data (
                        vals[1].bv_len = 0;
                        mod.sml_op = LDAP_MOD_DELETE;
                        mod.sml_flags = 0;
-                       mod.sml_desc = ad_queryid;
-                       mod.sml_type = ad_queryid->ad_cname;
+                       mod.sml_desc = ad_queryId;
+                       mod.sml_type = ad_queryId->ad_cname;
                        mod.sml_values = vals;
                        mod.sml_nvalues = NULL;
                        mod.sml_next = NULL;
@@ -1158,17 +1502,20 @@ filter2template(
                return -1;
        }
 
-       *filter_attrs = (AttributeName *)op->o_tmprealloc(*filter_attrs,
+       if ( filter_attrs != NULL ) {
+               *filter_attrs = (AttributeName *)op->o_tmprealloc(*filter_attrs,
                                (*filter_cnt + 2)*sizeof(AttributeName), op->o_tmpmemctx);
 
-       (*filter_attrs)[*filter_cnt].an_desc = ad;
-       (*filter_attrs)[*filter_cnt].an_name = ad->ad_cname;
-       (*filter_attrs)[*filter_cnt].an_oc = NULL;
-       (*filter_attrs)[*filter_cnt].an_oc_exclude = 0;
-       BER_BVZERO( &(*filter_attrs)[*filter_cnt+1].an_name );
-       (*filter_cnt)++;
-       if ( ad == slap_schema.si_ad_objectClass )
-               *filter_got_oc = 1;
+               (*filter_attrs)[*filter_cnt].an_desc = ad;
+               (*filter_attrs)[*filter_cnt].an_name = ad->ad_cname;
+               (*filter_attrs)[*filter_cnt].an_oc = NULL;
+               (*filter_attrs)[*filter_cnt].an_oc_exclude = 0;
+               BER_BVZERO( &(*filter_attrs)[*filter_cnt+1].an_name );
+               (*filter_cnt)++;
+               if ( ad == slap_schema.si_ad_objectClass )
+                       *filter_got_oc = 1;
+       }
+
        return 0;
 }
 
@@ -1183,124 +1530,411 @@ struct search_info {
        Entry *head, *tail;
 };
 
-static int
-cache_entries(
+static void
+remove_query_and_data(
        Operation       *op,
        SlapReply       *rs,
-       struct berval *query_uuid)
+       cache_manager   *cm,
+       struct berval   *uuid )
 {
-       struct search_info *si = op->o_callback->sc_private;
-       slap_overinst *on = si->on;
-       cache_manager *cm = on->on_bi.bi_private;
        query_manager*          qm = cm->qm;
-       int             return_val = 0;
-       Entry           *e;
-       struct berval   crp_uuid;
-       char            uuidbuf[ LDAP_LUTIL_UUIDSTR_BUFSIZE ];
-       Operation op_tmp = *op;
 
-       query_uuid->bv_len = lutil_uuidstr(uuidbuf, sizeof(uuidbuf));
-       ber_str2bv(uuidbuf, query_uuid->bv_len, 1, query_uuid);
+       qm->crfunc( qm, uuid );
+       if ( !BER_BVISNULL( uuid ) ) {
+               int     return_val;
 
-       op_tmp.o_bd = &cm->db;
-       op_tmp.o_dn = cm->db.be_rootdn;
-       op_tmp.o_ndn = cm->db.be_rootndn;
+               Debug( pcache_debug,
+                       "Removing query UUID %s\n",
+                       uuid->bv_val, 0, 0 );
+               return_val = remove_query_data( op, rs, uuid );
+               Debug( pcache_debug,
+                       "QUERY REMOVED, SIZE=%d\n",
+                       return_val, 0, 0);
+               ldap_pvt_thread_mutex_lock( &cm->cache_mutex );
+               cm->cur_entries -= return_val;
+               cm->num_cached_queries--;
+               Debug( pcache_debug,
+                       "STORED QUERIES = %lu\n",
+                       cm->num_cached_queries, 0, 0 );
+               ldap_pvt_thread_mutex_unlock( &cm->cache_mutex );
+               Debug( pcache_debug,
+                       "QUERY REMOVED, CACHE ="
+                       "%d entries\n",
+                       cm->cur_entries, 0, 0 );
+       }
+}
 
-       Debug( pcache_debug, "UUID for query being added = %s\n",
-                       uuidbuf, 0, 0 );
+/*
+ * Callback used to fetch queryId values based on entryUUID;
+ * used by pcache_remove_entries_from_cache()
+ */
+static int
+fetch_queryId_cb( Operation *op, SlapReply *rs )
+{
+       int             rc = 0;
 
-       for ( e=si->head; e; e=si->head ) {
-               si->head = e->e_private;
-               e->e_private = NULL;
-               while ( cm->cur_entries > (cm->max_entries) ) {
-                               qm->crfunc(qm, &crp_uuid);
-                               if (crp_uuid.bv_val) {
-                                       Debug( pcache_debug,
-                                               "Removing query UUID %s\n",
-                                               crp_uuid.bv_val, 0, 0 );
-                                       return_val = remove_query_data(&op_tmp, rs, &crp_uuid);
-                                       Debug( pcache_debug,
-                                               "QUERY REMOVED, SIZE=%d\n",
-                                               return_val, 0, 0);
-                                       ldap_pvt_thread_mutex_lock(
-                                                       &cm->cache_mutex );
-                                       cm->cur_entries -= return_val;
-                                       cm->num_cached_queries--;
-                                       Debug( pcache_debug,
-                                               "STORED QUERIES = %lu\n",
-                                               cm->num_cached_queries, 0, 0 );
-                                       ldap_pvt_thread_mutex_unlock(
-                                                       &cm->cache_mutex );
-                                       Debug( pcache_debug,
-                                               "QUERY REMOVED, CACHE ="
-                                               "%d entries\n",
-                                               cm->cur_entries, 0, 0 );
-                               }
+       /* only care about searchEntry responses */
+       if ( rs->sr_type != REP_SEARCH ) {
+               return 0;
+       }
+
+       /* allow only one response per entryUUID */
+       if ( op->o_callback->sc_private != NULL ) {
+               rc = 1;
+
+       } else {
+               Attribute       *a;
+
+               /* copy all queryId values into callback's private data */
+               a = attr_find( rs->sr_entry->e_attrs, ad_queryId );
+               if ( a != NULL ) {
+                       BerVarray       vals = NULL;
+
+                       ber_bvarray_dup_x( &vals, a->a_nvals, op->o_tmpmemctx );
+                       op->o_callback->sc_private = (void *)vals;
                }
+       }
 
-               return_val = merge_entry(&op_tmp, e, query_uuid);
-               ldap_pvt_thread_mutex_lock(&cm->cache_mutex);
-               cm->cur_entries += return_val;
-               Debug( pcache_debug,
-                       "ENTRY ADDED/MERGED, CACHED ENTRIES=%d\n",
-                       cm->cur_entries, 0, 0 );
-               return_val = 0;
-               ldap_pvt_thread_mutex_unlock(&cm->cache_mutex);
+       /* clear entry if required */
+       if ( rs->sr_flags & REP_ENTRY_MUSTBEFREED ) {
+               entry_free( rs->sr_entry );
+               rs->sr_entry = NULL;
+               rs->sr_flags ^= REP_ENTRY_MUSTBEFREED;
        }
 
-       return return_val;
+       return rc;
 }
 
-static int
-pcache_response(
+/*
+ * Call that allows to remove a set of entries from the cache,
+ * by forcing the removal of all the related queries.
+ */
+int
+pcache_remove_entries_from_cache(
        Operation       *op,
-       SlapReply       *rs )
+       cache_manager   *cm,
+       BerVarray       entryUUIDs )
 {
-       struct search_info *si = op->o_callback->sc_private;
-       slap_overinst *on = si->on;
-       cache_manager *cm = on->on_bi.bi_private;
-       query_manager*          qm = cm->qm;
+       Connection      conn = { 0 };
+       OperationBuffer opbuf;
+       Operation       op2;
+       slap_callback   sc = { 0 };
+       SlapReply       rs = { REP_RESULT };
+       Filter          f = { 0 };
+       char            filtbuf[ LDAP_LUTIL_UUIDSTR_BUFSIZE + STRLENOF( "(entryUUID=)" ) ];
+#ifdef LDAP_COMP_MATCH
+       AttributeAssertion ava = { NULL, BER_BVNULL, NULL };
+#else
+       AttributeAssertion ava = { NULL, BER_BVNULL };
+#endif
+       AttributeName   attrs[ 2 ] = { 0 };
+       int             s, rc;
 
-       if ( si->save_attrs != NULL ) {
-               rs->sr_attrs = si->save_attrs;
-               op->ors_attrs = si->save_attrs;
-               si->save_attrs = NULL;
+       if ( op == NULL ) {
+               void    *thrctx = ldap_pvt_thread_pool_context();
+
+               connection_fake_init( &conn, &opbuf, thrctx );
+               op = &opbuf.ob_op;
+
+       } else {
+               op2 = *op;
+               op = &op2;
        }
 
-       if ( rs->sr_type == REP_SEARCH ) {
-               Entry *e;
-               /* If we haven't exceeded the limit for this query,
-                * build a chain of answers to store. If we hit the
-                * limit, empty the chain and ignore the rest.
-                */
-               if ( !si->over ) {
-                       if ( si->count < si->max ) {
-                               si->count++;
-                               e = entry_dup( rs->sr_entry );
-                               if ( !si->head ) si->head = e;
-                               if ( si->tail ) si->tail->e_private = e;
-                               si->tail = e;
-                       } else {
-                               si->over = 1;
-                               si->count = 0;
-                               for (;si->head; si->head=e) {
-                                       e = si->head->e_private;
-                                       si->head->e_private = NULL;
-                                       entry_free(si->head);
-                               }
-                               si->tail = NULL;
-                       }
-               }
+       memset( &op->oq_search, 0, sizeof( op->oq_search ) );
+       op->ors_scope = LDAP_SCOPE_SUBTREE;
+       op->ors_deref = LDAP_DEREF_NEVER;
+       f.f_choice = LDAP_FILTER_EQUALITY;
+       f.f_ava = &ava;
+       ava.aa_desc = slap_schema.si_ad_entryUUID;
+       op->ors_filter = &f;
+       op->ors_slimit = 1;
+       op->ors_tlimit = SLAP_NO_LIMIT;
+       attrs[ 0 ].an_desc = ad_queryId;
+       attrs[ 0 ].an_name = ad_queryId->ad_cname;
+       op->ors_attrs = attrs;
+       op->ors_attrsonly = 0;
 
-       } else if ( rs->sr_type == REP_RESULT ) {
-               if ( si->count ||
-                       ( si->qtemp->negttl && !si->count && !si->over &&
-                               rs->sr_err == LDAP_SUCCESS )) {
-                       CachedQuery *qc = qm->addfunc(op, qm, &si->query, si->qtemp,
-                               si->count);
+       op->o_req_dn = cm->db.be_suffix[ 0 ];
+       op->o_req_ndn = cm->db.be_nsuffix[ 0 ];
 
-                       if ( qc != NULL ) {
-                               if ( si->count )
+       op->o_tag = LDAP_REQ_SEARCH;
+       op->o_protocol = LDAP_VERSION3;
+       op->o_managedsait = SLAP_CONTROL_CRITICAL;
+       op->o_bd = &cm->db;
+       op->o_dn = op->o_bd->be_rootdn;
+       op->o_ndn = op->o_bd->be_rootndn;
+       sc.sc_response = fetch_queryId_cb;
+       op->o_callback = &sc;
+
+       for ( s = 0; !BER_BVISNULL( &entryUUIDs[ s ] ); s++ ) {
+               BerVarray       vals = NULL;
+
+               op->ors_filterstr.bv_len = snprintf( filtbuf, sizeof( filtbuf ),
+                       "(entryUUID=%s)", entryUUIDs[ s ].bv_val );
+               op->ors_filterstr.bv_val = filtbuf;
+               ava.aa_value = entryUUIDs[ s ];
+
+               rc = op->o_bd->be_search( op, &rs );
+               if ( rc != LDAP_SUCCESS ) {
+                       continue;
+               }
+
+               vals = (BerVarray)op->o_callback->sc_private;
+               if ( vals != NULL ) {
+                       int             i;
+
+                       for ( i = 0; !BER_BVISNULL( &vals[ i ] ); i++ ) {
+                               struct berval   val = vals[ i ];
+
+                               remove_query_and_data( op, &rs, cm, &val );
+
+                               if ( !BER_BVISNULL( &val ) && val.bv_val != vals[ i ].bv_val ) {
+                                       ch_free( val.bv_val );
+                               }
+                       }
+
+                       ber_bvarray_free_x( vals, op->o_tmpmemctx );
+                       op->o_callback->sc_private = NULL;
+               }
+       }
+
+       return 0;
+}
+
+/*
+ * Call that allows to remove a query from the cache.
+ */
+int
+pcache_remove_query_from_cache(
+       Operation       *op,
+       cache_manager   *cm,
+       struct berval   *queryid )
+{
+       Operation       op2 = *op;
+       SlapReply       rs2 = { 0 };
+
+       op2.o_bd = &cm->db;
+
+       /* remove the selected query */
+       remove_query_and_data( &op2, &rs2, cm, queryid );
+
+       return LDAP_SUCCESS;
+}
+
+/*
+ * Call that allows to remove a set of queries related to an entry 
+ * from the cache; if queryid is not null, the entry must belong to
+ * the query indicated by queryid.
+ */
+int
+pcache_remove_entry_queries_from_cache(
+       Operation       *op,
+       cache_manager   *cm,
+       struct berval   *ndn,
+       struct berval   *queryid )
+{
+       Connection              conn = { 0 };
+       OperationBuffer         opbuf;
+       Operation               op2;
+       slap_callback           sc = { 0 };
+       SlapReply               rs = { REP_RESULT };
+       Filter                  f = { 0 };
+       char                    filter_str[ LDAP_LUTIL_UUIDSTR_BUFSIZE + STRLENOF( "(queryId=)" ) ];
+#ifdef LDAP_COMP_MATCH
+       AttributeAssertion      ava = { NULL, BER_BVNULL, NULL };
+#else
+       AttributeAssertion      ava = { NULL, BER_BVNULL };
+#endif
+       AttributeName           attrs[ 2 ] = { 0 };
+       int                     rc;
+
+       BerVarray               vals = NULL;
+
+       if ( op == NULL ) {
+               void    *thrctx = ldap_pvt_thread_pool_context();
+
+               connection_fake_init( &conn, &opbuf, thrctx );
+               op = &opbuf.ob_op;
+
+       } else {
+               op2 = *op;
+               op = &op2;
+       }
+
+       memset( &op->oq_search, 0, sizeof( op->oq_search ) );
+       op->ors_scope = LDAP_SCOPE_BASE;
+       op->ors_deref = LDAP_DEREF_NEVER;
+       if ( queryid == NULL || BER_BVISNULL( queryid ) ) {
+               BER_BVSTR( &op->ors_filterstr, "(objectClass=*)" );
+               f.f_choice = LDAP_FILTER_PRESENT;
+               f.f_desc = slap_schema.si_ad_objectClass;
+
+       } else {
+               op->ors_filterstr.bv_len = snprintf( filter_str,
+                       sizeof( filter_str ), "(%s=%s)",
+                       ad_queryId->ad_cname.bv_val, queryid->bv_val );
+               f.f_choice = LDAP_FILTER_EQUALITY;
+               f.f_ava = &ava;
+               f.f_av_desc = ad_queryId;
+               f.f_av_value = *queryid;
+       }
+       op->ors_filter = &f;
+       op->ors_slimit = 1;
+       op->ors_tlimit = SLAP_NO_LIMIT;
+       attrs[ 0 ].an_desc = ad_queryId;
+       attrs[ 0 ].an_name = ad_queryId->ad_cname;
+       op->ors_attrs = attrs;
+       op->ors_attrsonly = 0;
+
+       op->o_req_dn = *ndn;
+       op->o_req_ndn = *ndn;
+
+       op->o_tag = LDAP_REQ_SEARCH;
+       op->o_protocol = LDAP_VERSION3;
+       op->o_managedsait = SLAP_CONTROL_CRITICAL;
+       op->o_bd = &cm->db;
+       op->o_dn = op->o_bd->be_rootdn;
+       op->o_ndn = op->o_bd->be_rootndn;
+       sc.sc_response = fetch_queryId_cb;
+       op->o_callback = &sc;
+
+       rc = op->o_bd->be_search( op, &rs );
+       if ( rc != LDAP_SUCCESS ) {
+               return rc;
+       }
+
+       vals = (BerVarray)op->o_callback->sc_private;
+       if ( vals != NULL ) {
+               int             i;
+
+               for ( i = 0; !BER_BVISNULL( &vals[ i ] ); i++ ) {
+                       struct berval   val = vals[ i ];
+
+                       remove_query_and_data( op, &rs, cm, &val );
+
+                       if ( !BER_BVISNULL( &val ) && val.bv_val != vals[ i ].bv_val ) {
+                               ch_free( val.bv_val );
+                       }
+               }
+
+               ber_bvarray_free_x( vals, op->o_tmpmemctx );
+       }
+
+       return LDAP_SUCCESS;
+}
+
+static int
+cache_entries(
+       Operation       *op,
+       SlapReply       *rs,
+       struct berval *query_uuid )
+{
+       struct search_info *si = op->o_callback->sc_private;
+       slap_overinst *on = si->on;
+       cache_manager *cm = on->on_bi.bi_private;
+       int             return_val = 0;
+       Entry           *e;
+       struct berval   crp_uuid;
+       char            uuidbuf[ LDAP_LUTIL_UUIDSTR_BUFSIZE ];
+       Operation op_tmp = *op;
+
+       query_uuid->bv_len = lutil_uuidstr(uuidbuf, sizeof(uuidbuf));
+       ber_str2bv(uuidbuf, query_uuid->bv_len, 1, query_uuid);
+
+       op_tmp.o_bd = &cm->db;
+       op_tmp.o_dn = cm->db.be_rootdn;
+       op_tmp.o_ndn = cm->db.be_rootndn;
+
+       Debug( pcache_debug, "UUID for query being added = %s\n",
+                       uuidbuf, 0, 0 );
+
+       for ( e=si->head; e; e=si->head ) {
+               si->head = e->e_private;
+               e->e_private = NULL;
+               while ( cm->cur_entries > (cm->max_entries) ) {
+                       BER_BVZERO( &crp_uuid );
+                       remove_query_and_data( &op_tmp, rs, cm, &crp_uuid );
+               }
+
+               return_val = merge_entry(&op_tmp, e, query_uuid);
+               ldap_pvt_thread_mutex_lock(&cm->cache_mutex);
+               cm->cur_entries += return_val;
+               Debug( pcache_debug,
+                       "ENTRY ADDED/MERGED, CACHED ENTRIES=%d\n",
+                       cm->cur_entries, 0, 0 );
+               return_val = 0;
+               ldap_pvt_thread_mutex_unlock(&cm->cache_mutex);
+       }
+
+       return return_val;
+}
+
+static int
+pcache_op_cleanup( Operation *op, SlapReply *rs ) {
+       slap_callback   *cb = op->o_callback;
+       struct search_info *si = cb->sc_private;
+       if ( rs->sr_type == REP_RESULT || op->o_abandon || 
+                       rs->sr_err == SLAPD_ABANDON ) {
+               if ( si->save_attrs != NULL ) {
+                       rs->sr_attrs = si->save_attrs;
+                       op->ors_attrs = si->save_attrs;
+               }
+               op->o_callback = op->o_callback->sc_next;
+               op->o_tmpfree( cb, op->o_tmpmemctx );
+       }
+       return SLAP_CB_CONTINUE;
+}
+
+static int
+pcache_response(
+       Operation       *op,
+       SlapReply       *rs )
+{
+       struct search_info *si = op->o_callback->sc_private;
+       slap_overinst *on = si->on;
+       cache_manager *cm = on->on_bi.bi_private;
+       query_manager*          qm = cm->qm;
+
+       if ( si->save_attrs != NULL ) {
+               rs->sr_attrs = si->save_attrs;
+               op->ors_attrs = si->save_attrs;
+       }
+
+       if ( rs->sr_type == REP_SEARCH ) {
+               Entry *e;
+               /* If we haven't exceeded the limit for this query,
+                * build a chain of answers to store. If we hit the
+                * limit, empty the chain and ignore the rest.
+                */
+               if ( !si->over ) {
+                       if ( si->count < si->max ) {
+                               si->count++;
+                               e = entry_dup( rs->sr_entry );
+                               if ( !si->head ) si->head = e;
+                               if ( si->tail ) si->tail->e_private = e;
+                               si->tail = e;
+                       } else {
+                               si->over = 1;
+                               si->count = 0;
+                               for (;si->head; si->head=e) {
+                                       e = si->head->e_private;
+                                       si->head->e_private = NULL;
+                                       entry_free(si->head);
+                               }
+                               si->tail = NULL;
+                       }
+               }
+
+       } else if ( rs->sr_type == REP_RESULT ) {
+               if ( si->count ||
+                       ( si->qtemp->negttl && !si->count && !si->over &&
+                               rs->sr_err == LDAP_SUCCESS )) {
+                       CachedQuery *qc = qm->addfunc(op, qm, &si->query, si->qtemp,
+                               si->count);
+
+                       if ( qc != NULL ) {
+                               if ( si->count )
                                        cache_entries( op, rs, &qc->q_uuid );
                                ldap_pvt_thread_mutex_lock(&cm->cache_mutex);
                                cm->num_cached_queries++;
@@ -1331,14 +1965,11 @@ pcache_response(
                } else {
                        filter_free( si->query.filter );
                }
-
-               /* free self */
-               op->o_callback->sc_cleanup = slap_freeself_cb;
        }
        return SLAP_CB_CONTINUE;
 }
 
-static void
+static int
 add_filter_attrs(
        Operation *op,
        AttributeName** new_attrs,
@@ -1360,8 +1991,8 @@ add_filter_attrs(
                count++;
        }
 
-       *new_attrs = (AttributeName*)ch_malloc((count+1)*
-               sizeof(AttributeName));
+       *new_attrs = (AttributeName*)ch_calloc( count + 1,
+               sizeof(AttributeName) );
        for (i=0; i<attrs->count; i++) {
                (*new_attrs)[i].an_name = attrs->attrs[i].an_name;
                (*new_attrs)[i].an_desc = attrs->attrs[i].an_desc;
@@ -1372,13 +2003,16 @@ add_filter_attrs(
 
        j = i;
        for ( i=0; i<fattr_cnt; i++ ) {
-               if ( an_find(*new_attrs, &filter_attrs[i].an_name ))
+               if ( an_find(*new_attrs, &filter_attrs[i].an_name ) ) {
                        continue;
+               }
                if ( is_at_operational(filter_attrs[i].an_desc->ad_type) ) {
-                       if (allop)
+                       if ( allop ) {
                                continue;
-               } else if (alluser)
+                       }
+               } else if ( alluser ) {
                        continue;
+               }
                (*new_attrs)[j].an_name = filter_attrs[i].an_name;
                (*new_attrs)[j].an_desc = filter_attrs[i].an_desc;
                (*new_attrs)[j].an_oc = NULL;
@@ -1393,6 +2027,8 @@ add_filter_attrs(
                j++;
        }
        BER_BVZERO( &(*new_attrs)[j].an_name );
+
+       return count;
 }
 
 /* NOTE: this is a quick workaround to let pcache minimally interact
@@ -1431,6 +2067,64 @@ pcache_chk_controls(
        return rs->sr_err;
 }
 
+#ifdef PCACHE_CONTROL_PRIVDB
+static int
+pcache_op_privdb(
+       Operation               *op,
+       SlapReply               *rs )
+{
+       slap_overinst   *on = (slap_overinst *)op->o_bd->bd_info;
+       cache_manager   *cm = on->on_bi.bi_private;
+       slap_callback   *save_cb;
+       slap_op_t       type;
+
+       /* skip if control is unset */
+       if ( op->o_ctrlflag[ privDB_cid ] != SLAP_CONTROL_CRITICAL ) {
+               return SLAP_CB_CONTINUE;
+       }
+
+       /* FIXME: might be a little bit exaggerated... */
+       if ( !be_isroot( op ) ) {
+               save_cb = op->o_callback;
+               op->o_callback = NULL;
+               send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
+                       "pcachePrivDB: operation not allowed" );
+               op->o_callback = save_cb;
+
+               return rs->sr_err;
+       }
+
+       /* map tag to operation */
+       type = slap_req2op( op->o_tag );
+       if ( type != SLAP_OP_LAST ) {
+               BI_op_func      **func;
+               int             rc;
+
+               /* execute, if possible */
+               func = &cm->db.be_bind;
+               if ( func[ type ] != NULL ) {
+                       Operation       op2 = *op;
+       
+                       op2.o_bd = &cm->db;
+
+                       rc = func[ type ]( &op2, rs );
+                       if ( type == SLAP_OP_BIND && rc == LDAP_SUCCESS ) {
+                               op->o_conn->c_authz_cookie = cm->db.be_private;
+                       }
+               }
+       }
+
+       /* otherwise fall back to error */
+       save_cb = op->o_callback;
+       op->o_callback = NULL;
+       send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
+               "operation not supported with pcachePrivDB control" );
+       op->o_callback = save_cb;
+
+       return rs->sr_err;
+}
+#endif /* PCACHE_CONTROL_PRIVDB */
+
 static int
 pcache_op_search(
        Operation       *op,
@@ -1445,7 +2139,7 @@ pcache_op_search(
        AttributeName   *filter_attrs = NULL;
 
        Query           query;
-       QueryTemplate *qtemp = NULL;
+       QueryTemplate   *qtemp = NULL;
 
        int             attr_set = -1;
        CachedQuery     *answerable = NULL;
@@ -1453,7 +2147,13 @@ pcache_op_search(
        int             fattr_cnt=0;
        int             fattr_got_oc = 0;
 
-       struct berval tempstr;
+       struct berval   tempstr;
+
+#ifdef PCACHE_CONTROL_PRIVDB
+       if ( op->o_ctrlflag[ privDB_cid ] == SLAP_CONTROL_CRITICAL ) {
+               return pcache_op_privdb( op, rs );
+       }
+#endif /* PCACHE_CONTROL_PRIVDB */
 
        tempstr.bv_val = op->o_tmpalloc( op->ors_filterstr.bv_len+1, op->o_tmpmemctx );
        tempstr.bv_len = 0;
@@ -1537,15 +2237,16 @@ pcache_op_search(
                query.filter = filter_dup(op->ors_filter, NULL);
                ldap_pvt_thread_rdwr_wlock(&qtemp->t_rwlock);
                if ( !qtemp->t_attrs.count ) {
-                       add_filter_attrs(op, &qtemp->t_attrs.attrs,
+                       qtemp->t_attrs.count = add_filter_attrs(op,
+                               &qtemp->t_attrs.attrs,
                                &qm->attr_sets[attr_set],
                                filter_attrs, fattr_cnt, fattr_got_oc);
                }
                ldap_pvt_thread_rdwr_wunlock(&qtemp->t_rwlock);
 
-               cb = op->o_tmpalloc( sizeof(*cb) + sizeof(*si), op->o_tmpmemctx);
+               cb = op->o_tmpalloc( sizeof(*cb) + sizeof(*si), op->o_tmpmemctx );
                cb->sc_response = pcache_response;
-               cb->sc_cleanup = NULL;
+               cb->sc_cleanup = pcache_op_cleanup;
                cb->sc_private = (cb+1);
                si = cb->sc_private;
                si->on = on;
@@ -1598,28 +2299,47 @@ get_attr_set(
                for ( ; attrs[count].an_name.bv_val; count++ );
        }
 
-       for (i=0; i<num; i++) {
+       /* recognize a single "*" or a "1.1" */
+       if ( count == 0 ) {
+               count = 1;
+               attrs = slap_anlist_all_user_attributes;
+
+       } else if ( count == 1 && strcmp( attrs[0].an_name.bv_val, LDAP_NO_ATTRS ) == 0 ) {
+               count = 0;
+               attrs = NULL;
+       }
+
+       for ( i = 0; i < num; i++ ) {
                AttributeName *a2;
                int found = 1;
 
-               if ( count > qm->attr_sets[i].count )
+               if ( count > qm->attr_sets[i].count ) {
                        continue;
+               }
+
                if ( !count ) {
-                       if ( !qm->attr_sets[i].count )
+                       if ( !qm->attr_sets[i].count ) {
                                break;
+                       }
                        continue;
                }
+
                for ( a2 = attrs; a2->an_name.bv_val; a2++ ) {
-                       if ( !an_find( qm->attr_sets[i].attrs, &a2->an_name )) {
+                       if ( !an_find( qm->attr_sets[i].attrs, &a2->an_name ) ) {
                                found = 0;
                                break;
                        }
                }
-               if ( found )
+
+               if ( found ) {
                        break;
+               }
        }
-       if ( i == num )
+
+       if ( i == num ) {
                i = -1;
+       }
+
        return i;
 }
 
@@ -1641,8 +2361,8 @@ consistency_check(
        int return_val, pause = 1;
        QueryTemplate* templ;
 
-       op = (Operation *) &opbuf;
-       connection_fake_init( &conn, op, ctx );
+       connection_fake_init( &conn, &opbuf, ctx );
+       op = &opbuf.ob_op;
 
        op->o_bd = &cm->db;
        op->o_dn = cm->db.be_rootdn;
@@ -1749,6 +2469,11 @@ static ConfigTable pccfg[] = {
                "( OLcfgOvAt:2.5 NAME 'olcProxyCacheQueries' "
                        "DESC 'Maximum number of queries to cache' "
                        "SYNTAX OMsInteger )", NULL, NULL },
+       { "proxySaveQueries", "TRUE|FALSE",
+               2, 2, 0, ARG_ON_OFF|ARG_OFFSET, (void *)offsetof(cache_manager, save_queries),
+               "( OLcfgOvAt:2.6 NAME 'olcProxySaveQueries' "
+                       "DESC 'Save cached queries for hot restart' "
+                       "SYNTAX OMsBoolean )", NULL, NULL },
 
        { NULL, NULL, 0, 0, 0, ARG_IGNORED }
 };
@@ -1759,7 +2484,8 @@ static ConfigOCs pcocs[] = {
                "DESC 'ProxyCache configuration' "
                "SUP olcOverlayConfig "
                "MUST ( olcProxyCache $ olcProxyAttrset $ olcProxyTemplate ) "
-               "MAY ( olcProxyResponseCB $ olcProxyCacheQueries ) )", Cft_Overlay, pccfg, NULL, pc_cfadd },
+               "MAY ( olcProxyResponseCB $ olcProxyCacheQueries $ olcProxySaveQueries ) )",
+               Cft_Overlay, pccfg, NULL, pc_cfadd },
        { "( OLcfgOvOc:2.2 "
                "NAME 'olcPcacheDatabase' "
                "DESC 'Cache database configuration' "
@@ -1792,8 +2518,8 @@ pc_cfadd( Operation *op, SlapReply *rs, Entry *p, ConfigArgs *ca )
        struct berval bv;
 
        /* FIXME: should not hardcode "olcDatabase" here */
-       bv.bv_len = sprintf( ca->msg, "olcDatabase=%s", cm->db.bd_info->bi_type );
-       bv.bv_val = ca->msg;
+       bv.bv_len = sprintf( ca->cr_msg, "olcDatabase=%s", cm->db.bd_info->bi_type );
+       bv.bv_val = ca->cr_msg;
        ca->be = &cm->db;
 
        /* We can only create this entry if the database is table-driven
@@ -1823,17 +2549,17 @@ pc_cf_gen( ConfigArgs *c )
                struct berval bv;
                switch( c->type ) {
                case PC_MAIN:
-                       bv.bv_len = snprintf( c->msg, sizeof( c->msg ), "%s %d %d %d %ld",
+                       bv.bv_len = snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s %d %d %d %ld",
                                cm->db.bd_info->bi_type, cm->max_entries, cm->numattrsets,
                                cm->num_entries_limit, cm->cc_period );
-                       bv.bv_val = c->msg;
+                       bv.bv_val = c->cr_msg;
                        value_add_one( &c->rvalue_vals, &bv );
                        break;
                case PC_ATTR:
                        for (i=0; i<cm->numattrsets; i++) {
                                if ( !qm->attr_sets[i].count ) continue;
 
-                               bv.bv_len = snprintf( c->msg, sizeof( c->msg ), "%d", i );
+                               bv.bv_len = snprintf( c->cr_msg, sizeof( c->cr_msg ), "%d", i );
 
                                /* count the attr length */
                                for ( attr_name = qm->attr_sets[i].attrs;
@@ -1841,7 +2567,7 @@ pc_cf_gen( ConfigArgs *c )
                                        bv.bv_len += attr_name->an_name.bv_len + 1;
 
                                bv.bv_val = ch_malloc( bv.bv_len+1 );
-                               ptr = lutil_strcopy( bv.bv_val, c->msg );
+                               ptr = lutil_strcopy( bv.bv_val, c->cr_msg );
                                for ( attr_name = qm->attr_sets[i].attrs;
                                        attr_name->an_name.bv_val; attr_name++ ) {
                                        *ptr++ = ' ';
@@ -1855,13 +2581,13 @@ pc_cf_gen( ConfigArgs *c )
                case PC_TEMP:
                        for (temp=qm->templates; temp; temp=temp->qmnext) {
                                if ( temp->negttl ) {
-                                       bv.bv_len = snprintf( c->msg, sizeof( c->msg ),
+                                       bv.bv_len = snprintf( c->cr_msg, sizeof( c->cr_msg ),
                                                " %d %ld %ld",
                                                temp->attr_set_index,
                                                temp->ttl,
                                                temp->negttl );
                                } else {
-                                       bv.bv_len = snprintf( c->msg, sizeof( c->msg ), " %d %ld",
+                                       bv.bv_len = snprintf( c->cr_msg, sizeof( c->cr_msg ), " %d %ld",
                                                temp->attr_set_index,
                                                temp->ttl );
                                }
@@ -1871,7 +2597,7 @@ pc_cf_gen( ConfigArgs *c )
                                *ptr++ = '"';
                                ptr = lutil_strcopy( ptr, temp->querystr.bv_val );
                                *ptr++ = '"';
-                               strcpy( ptr, c->msg );
+                               strcpy( ptr, c->cr_msg );
                                ber_bvarray_add( &c->rvalue_vals, &bv );
                        }
                        if ( !c->rvalue_vals )
@@ -1904,67 +2630,67 @@ pc_cf_gen( ConfigArgs *c )
        switch( c->type ) {
        case PC_MAIN:
                if ( cm->numattrsets > 0 ) {
-                       snprintf( c->msg, sizeof( c->msg ), "\"proxycache\" directive already provided" );
-                       Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", c->log, c->msg, 0 );
+                       snprintf( c->cr_msg, sizeof( c->cr_msg ), "\"proxycache\" directive already provided" );
+                       Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", c->log, c->cr_msg, 0 );
                        return( 1 );
                }
 
                if ( lutil_atoi( &cm->numattrsets, c->argv[3] ) != 0 ) {
-                       snprintf( c->msg, sizeof( c->msg ), "unable to parse num attrsets=\"%s\" (arg #3)",
+                       snprintf( c->cr_msg, sizeof( c->cr_msg ), "unable to parse num attrsets=\"%s\" (arg #3)",
                                c->argv[3] );
-                       Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", c->log, c->msg, 0 );
+                       Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", c->log, c->cr_msg, 0 );
                        return( 1 );
                }
                if ( cm->numattrsets <= 0 ) {
-                       snprintf( c->msg, sizeof( c->msg ), "numattrsets (arg #3) must be positive" );
-                       Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", c->log, c->msg, 0 );
+                       snprintf( c->cr_msg, sizeof( c->cr_msg ), "numattrsets (arg #3) must be positive" );
+                       Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", c->log, c->cr_msg, 0 );
                        return( 1 );
                }
                if ( cm->numattrsets > MAX_ATTR_SETS ) {
-                       snprintf( c->msg, sizeof( c->msg ), "numattrsets (arg #3) must be <= %d", MAX_ATTR_SETS );
-                       Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", c->log, c->msg, 0 );
+                       snprintf( c->cr_msg, sizeof( c->cr_msg ), "numattrsets (arg #3) must be <= %d", MAX_ATTR_SETS );
+                       Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", c->log, c->cr_msg, 0 );
                        return( 1 );
                }
 
-               if ( !backend_db_init( c->argv[1], &cm->db, -1 )) {
-                       snprintf( c->msg, sizeof( c->msg ), "unknown backend type (arg #1)" );
-                       Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", c->log, c->msg, 0 );
+               if ( !backend_db_init( c->argv[1], &cm->db, -1, NULL )) {
+                       snprintf( c->cr_msg, sizeof( c->cr_msg ), "unknown backend type (arg #1)" );
+                       Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", c->log, c->cr_msg, 0 );
                        return( 1 );
                }
 
                if ( lutil_atoi( &cm->max_entries, c->argv[2] ) != 0 ) {
-                       snprintf( c->msg, sizeof( c->msg ), "unable to parse max entries=\"%s\" (arg #2)",
+                       snprintf( c->cr_msg, sizeof( c->cr_msg ), "unable to parse max entries=\"%s\" (arg #2)",
                                c->argv[2] );
-                       Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", c->log, c->msg, 0 );
+                       Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", c->log, c->cr_msg, 0 );
                        return( 1 );
                }
                if ( cm->max_entries <= 0 ) {
-                       snprintf( c->msg, sizeof( c->msg ), "max entries (arg #2) must be positive.\n" );
-                       Debug( LDAP_DEBUG_CONFIG, "%s: %s\n", c->log, c->msg, 0 );
+                       snprintf( c->cr_msg, sizeof( c->cr_msg ), "max entries (arg #2) must be positive.\n" );
+                       Debug( LDAP_DEBUG_CONFIG, "%s: %s\n", c->log, c->cr_msg, 0 );
                        return( 1 );
                }
 
                if ( lutil_atoi( &cm->num_entries_limit, c->argv[4] ) != 0 ) {
-                       snprintf( c->msg, sizeof( c->msg ), "unable to parse entry limit=\"%s\" (arg #4)",
+                       snprintf( c->cr_msg, sizeof( c->cr_msg ), "unable to parse entry limit=\"%s\" (arg #4)",
                                c->argv[4] );
-                       Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", c->log, c->msg, 0 );
+                       Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", c->log, c->cr_msg, 0 );
                        return( 1 );
                }
                if ( cm->num_entries_limit <= 0 ) {
-                       snprintf( c->msg, sizeof( c->msg ), "entry limit (arg #4) must be positive" );
-                       Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", c->log, c->msg, 0 );
+                       snprintf( c->cr_msg, sizeof( c->cr_msg ), "entry limit (arg #4) must be positive" );
+                       Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", c->log, c->cr_msg, 0 );
                        return( 1 );
                }
                if ( cm->num_entries_limit > cm->max_entries ) {
-                       snprintf( c->msg, sizeof( c->msg ), "entry limit (arg #4) must be less than max entries %d (arg #2)", cm->max_entries );
-                       Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", c->log, c->msg, 0 );
+                       snprintf( c->cr_msg, sizeof( c->cr_msg ), "entry limit (arg #4) must be less than max entries %d (arg #2)", cm->max_entries );
+                       Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", c->log, c->cr_msg, 0 );
                        return( 1 );
                }
 
                if ( lutil_parse_time( c->argv[5], &t ) != 0 ) {
-                       snprintf( c->msg, sizeof( c->msg ), "unable to parse period=\"%s\" (arg #5)",
+                       snprintf( c->cr_msg, sizeof( c->cr_msg ), "unable to parse period=\"%s\" (arg #5)",
                                c->argv[5] );
-                       Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", c->log, c->msg, 0 );
+                       Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", c->log, c->cr_msg, 0 );
                        return( 1 );
                }
                cm->cc_period = (time_t)t;
@@ -1976,42 +2702,101 @@ pc_cf_gen( ConfigArgs *c )
                break;
        case PC_ATTR:
                if ( cm->numattrsets == 0 ) {
-                       snprintf( c->msg, sizeof( c->msg ), "\"proxycache\" directive not provided yet" );
-                       Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", c->log, c->msg, 0 );
+                       snprintf( c->cr_msg, sizeof( c->cr_msg ), "\"proxycache\" directive not provided yet" );
+                       Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", c->log, c->cr_msg, 0 );
                        return( 1 );
                }
                if ( lutil_atoi( &num, c->argv[1] ) != 0 ) {
-                       snprintf( c->msg, sizeof( c->msg ), "unable to parse attrset #=\"%s\"",
+                       snprintf( c->cr_msg, sizeof( c->cr_msg ), "unable to parse attrset #=\"%s\"",
                                c->argv[1] );
-                       Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", c->log, c->msg, 0 );
+                       Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", c->log, c->cr_msg, 0 );
                        return( 1 );
                }
 
                if ( num < 0 || num >= cm->numattrsets ) {
-                       snprintf( c->msg, sizeof( c->msg ), "attrset index %d out of bounds (must be %s%d)",
+                       snprintf( c->cr_msg, sizeof( c->cr_msg ), "attrset index %d out of bounds (must be %s%d)",
                                num, cm->numattrsets > 1 ? "0->" : "", cm->numattrsets - 1 );
-                       Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", c->log, c->msg, 0 );
+                       Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", c->log, c->cr_msg, 0 );
                        return 1;
                }
                qm->attr_sets[num].flags |= PC_CONFIGURED;
-               if ( c->argc > 2 && strcmp( c->argv[2], "*" ) ) {
+               if ( c->argc == 2 ) {
+                       /* assume "1.1" */
+                       snprintf( c->cr_msg, sizeof( c->cr_msg ),
+                               "need an explicit attr in attrlist; use \"*\" to indicate all attrs" );
+                       Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", c->log, c->cr_msg, 0 );
+                       return 1;
+
+               } else if ( c->argc == 3 ) {
+                       if ( strcmp( c->argv[2], LDAP_ALL_USER_ATTRIBUTES ) == 0 ) {
+                               qm->attr_sets[num].count = 1;
+                               qm->attr_sets[num].attrs = (AttributeName*)ch_calloc( 2,
+                                       sizeof( AttributeName ) );
+                               BER_BVSTR( &qm->attr_sets[num].attrs[0].an_name, LDAP_ALL_USER_ATTRIBUTES );
+                               break;
+
+                       } else if ( strcmp( c->argv[2], LDAP_ALL_OPERATIONAL_ATTRIBUTES ) == 0 ) {
+                               qm->attr_sets[num].count = 1;
+                               qm->attr_sets[num].attrs = (AttributeName*)ch_calloc( 2,
+                                       sizeof( AttributeName ) );
+                               BER_BVSTR( &qm->attr_sets[num].attrs[0].an_name, LDAP_ALL_OPERATIONAL_ATTRIBUTES );
+                               break;
+
+                       } else if ( strcmp( c->argv[2], LDAP_NO_ATTRS ) == 0 ) {
+                               break;
+                       }
+                       /* else: fallthru */
+
+               } else if ( c->argc == 4 ) {
+                       if ( ( strcmp( c->argv[2], LDAP_ALL_USER_ATTRIBUTES ) == 0 && strcmp( c->argv[3], LDAP_ALL_OPERATIONAL_ATTRIBUTES ) == 0 )
+                               || ( strcmp( c->argv[2], LDAP_ALL_OPERATIONAL_ATTRIBUTES ) == 0 && strcmp( c->argv[3], LDAP_ALL_USER_ATTRIBUTES ) == 0 ) )
+                       {
+                               qm->attr_sets[num].count = 2;
+                               qm->attr_sets[num].attrs = (AttributeName*)ch_calloc( 3,
+                                       sizeof( AttributeName ) );
+                               BER_BVSTR( &qm->attr_sets[num].attrs[0].an_name, LDAP_ALL_USER_ATTRIBUTES );
+                               BER_BVSTR( &qm->attr_sets[num].attrs[1].an_name, LDAP_ALL_OPERATIONAL_ATTRIBUTES );
+                               break;
+                       }
+                       /* else: fallthru */
+               }
+
+               if ( c->argc > 2 ) {
+                       int all_user = 0, all_op = 0;
+
                        qm->attr_sets[num].count = c->argc - 2;
-                       qm->attr_sets[num].attrs = (AttributeName*)ch_malloc(
-                                               (c->argc-1) * sizeof( AttributeName ));
+                       qm->attr_sets[num].attrs = (AttributeName*)ch_calloc( c->argc - 1,
+                               sizeof( AttributeName ) );
                        attr_name = qm->attr_sets[num].attrs;
                        for ( i = 2; i < c->argc; i++ ) {
                                attr_name->an_desc = NULL;
-                               if ( slap_str2ad( c->argv[i], 
-                                               &attr_name->an_desc, &text ) )
-                               {
-                                       strcpy( c->msg, text );
-                                       Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", c->log, c->msg, 0 );
+                               if ( strcmp( c->argv[i], LDAP_NO_ATTRS ) == 0 ) {
+                                       snprintf( c->cr_msg, sizeof( c->cr_msg ),
+                                               "invalid attr #%d \"%s\" in attrlist",
+                                               i - 2, c->argv[i] );
+                                       Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", c->log, c->cr_msg, 0 );
                                        ch_free( qm->attr_sets[num].attrs );
                                        qm->attr_sets[num].attrs = NULL;
                                        qm->attr_sets[num].count = 0;
                                        return 1;
                                }
-                               attr_name->an_name = attr_name->an_desc->ad_cname;
+                               if ( strcmp( c->argv[i], LDAP_ALL_USER_ATTRIBUTES ) == 0 ) {
+                                       all_user = 1;
+                                       BER_BVSTR( &attr_name->an_name, LDAP_ALL_USER_ATTRIBUTES );
+                               } else if ( strcmp( c->argv[i], LDAP_ALL_OPERATIONAL_ATTRIBUTES ) == 0 ) {
+                                       all_op = 1;
+                                       BER_BVSTR( &attr_name->an_name, LDAP_ALL_OPERATIONAL_ATTRIBUTES );
+                               } else {
+                                       if ( slap_str2ad( c->argv[i], &attr_name->an_desc, &text ) ) {
+                                               strcpy( c->cr_msg, text );
+                                               Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", c->log, c->cr_msg, 0 );
+                                               ch_free( qm->attr_sets[num].attrs );
+                                               qm->attr_sets[num].attrs = NULL;
+                                               qm->attr_sets[num].count = 0;
+                                               return 1;
+                                       }
+                                       attr_name->an_name = attr_name->an_desc->ad_cname;
+                               }
                                attr_name->an_oc = NULL;
                                attr_name->an_oc_exclude = 0;
                                if ( attr_name->an_desc == slap_schema.si_ad_objectClass )
@@ -2019,26 +2804,33 @@ pc_cf_gen( ConfigArgs *c )
                                attr_name++;
                                BER_BVZERO( &attr_name->an_name );
                        }
+
+                       /* warn if list contains both "*" and "+" */
+                       if ( i > 4 && all_user && all_op ) {
+                               snprintf( c->cr_msg, sizeof( c->cr_msg ),
+                                       "warning: attribute list contains \"*\" and \"+\"" );
+                               Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", c->log, c->cr_msg, 0 );
+                       }
                }
                break;
        case PC_TEMP:
                if ( cm->numattrsets == 0 ) {
-                       snprintf( c->msg, sizeof( c->msg ), "\"proxycache\" directive not provided yet" );
-                       Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", c->log, c->msg, 0 );
+                       snprintf( c->cr_msg, sizeof( c->cr_msg ), "\"proxycache\" directive not provided yet" );
+                       Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", c->log, c->cr_msg, 0 );
                        return( 1 );
                }
                if ( lutil_atoi( &i, c->argv[2] ) != 0 ) {
-                       snprintf( c->msg, sizeof( c->msg ), "unable to parse template #=\"%s\"",
+                       snprintf( c->cr_msg, sizeof( c->cr_msg ), "unable to parse template #=\"%s\"",
                                c->argv[2] );
-                       Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", c->log, c->msg, 0 );
+                       Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", c->log, c->cr_msg, 0 );
                        return( 1 );
                }
 
                if ( i < 0 || i >= cm->numattrsets || 
                        !(qm->attr_sets[i].flags & PC_CONFIGURED )) {
-                       snprintf( c->msg, sizeof( c->msg ), "template index %d invalid (%s%d)",
+                       snprintf( c->cr_msg, sizeof( c->cr_msg ), "template index %d invalid (%s%d)",
                                i, cm->numattrsets > 1 ? "0->" : "", cm->numattrsets - 1 );
-                       Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", c->log, c->msg, 0 );
+                       Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", c->log, c->cr_msg, 0 );
                        return 1;
                }
                temp = ch_calloc( 1, sizeof( QueryTemplate ));
@@ -2047,18 +2839,18 @@ pc_cf_gen( ConfigArgs *c )
                ldap_pvt_thread_rdwr_init( &temp->t_rwlock );
                temp->query = temp->query_last = NULL;
                if ( lutil_parse_time( c->argv[3], &t ) != 0 ) {
-                       snprintf( c->msg, sizeof( c->msg ), "unable to parse template ttl=\"%s\"",
+                       snprintf( c->cr_msg, sizeof( c->cr_msg ), "unable to parse template ttl=\"%s\"",
                                c->argv[3] );
-                       Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", c->log, c->msg, 0 );
+                       Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", c->log, c->cr_msg, 0 );
                        return( 1 );
                }
                temp->ttl = (time_t)t;
                if ( c->argc == 5 ) {
                        if ( lutil_parse_time( c->argv[4], &t ) != 0 ) {
-                               snprintf( c->msg, sizeof( c->msg ),
+                               snprintf( c->cr_msg, sizeof( c->cr_msg ),
                                        "unable to parse template negttl=\"%s\"",
                                        c->argv[4] );
-                               Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", c->log, c->msg, 0 );
+                               Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", c->log, c->cr_msg, 0 );
                                        return( 1 );
                        }
                        temp->negttl = (time_t)t;
@@ -2091,15 +2883,15 @@ pc_cf_gen( ConfigArgs *c )
                        cm->response_cb = PCACHE_RESPONSE_CB_TAIL;
 
                } else {
-                       snprintf( c->msg, sizeof( c->msg ), "unknown specifier" );
-                       Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", c->log, c->msg, 0 );
+                       snprintf( c->cr_msg, sizeof( c->cr_msg ), "unknown specifier" );
+                       Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", c->log, c->cr_msg, 0 );
                        return 1;
                }
                break;
        case PC_QUERIES:
                if ( c->value_int <= 0 ) {
-                       snprintf( c->msg, sizeof( c->msg ), "max queries must be positive" );
-                       Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", c->log, c->msg, 0 );
+                       snprintf( c->cr_msg, sizeof( c->cr_msg ), "max queries must be positive" );
+                       Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", c->log, c->cr_msg, 0 );
                        return( 1 );
                }
                cm->max_queries = c->value_int;
@@ -2129,7 +2921,8 @@ pcache_db_config(
 
 static int
 pcache_db_init(
-       BackendDB *be )
+       BackendDB *be,
+       ConfigReply *cr)
 {
        slap_overinst *on = (slap_overinst *)be->bd_info;
        cache_manager *cm;
@@ -2151,6 +2944,7 @@ pcache_db_init(
        cm->max_entries = 0;
        cm->cur_entries = 0;
        cm->max_queries = 10000;
+       cm->save_queries = 0;
        cm->response_cb = PCACHE_RESPONSE_CB_TAIL;
        cm->cc_period = 1000;
        cm->cc_paused = 0;
@@ -2169,9 +2963,48 @@ pcache_db_init(
        return 0;
 }
 
+static int
+pcache_cachedquery_open_cb( Operation *op, SlapReply *rs )
+{
+       assert( op->o_tag == LDAP_REQ_SEARCH );
+
+       if ( rs->sr_type == REP_SEARCH ) {
+               Attribute       *a;
+
+               a = attr_find( rs->sr_entry->e_attrs, ad_cachedQueryURL );
+               if ( a != NULL ) {
+                       BerVarray       *valsp;
+
+                       assert( a->a_nvals != NULL );
+
+                       valsp = op->o_callback->sc_private;
+                       assert( *valsp == NULL );
+
+                       ber_bvarray_dup_x( valsp, a->a_nvals, op->o_tmpmemctx );
+               }
+       }
+
+       return 0;
+}
+
+static int
+pcache_cachedquery_count_cb( Operation *op, SlapReply *rs )
+{
+       assert( op->o_tag == LDAP_REQ_SEARCH );
+
+       if ( rs->sr_type == REP_SEARCH ) {
+               int     *countp = (int *)op->o_callback->sc_private;
+
+               (*countp)++;
+       }
+
+       return 0;
+}
+
 static int
 pcache_db_open(
-       BackendDB *be )
+       BackendDB *be,
+       ConfigReply *cr )
 {
        slap_overinst   *on = (slap_overinst *)be->bd_info;
        cache_manager   *cm = on->on_bi.bi_private;
@@ -2219,7 +3052,7 @@ pcache_db_open(
                SLAP_DBFLAGS( &cm->db ) &= ~SLAP_DBFLAG_MONITORING;
        }
 
-       rc = backend_startup_one( &cm->db );
+       rc = backend_startup_one( &cm->db, NULL );
 
        /* There is no runqueue in TOOL mode */
        if ( slapMode & SLAP_SERVER_MODE ) {
@@ -2241,6 +3074,92 @@ pcache_db_open(
                                cm->db.be_suffix[0].bv_val, 0 );
                        return 1;
                }
+
+               if ( cm->save_queries ) {
+                       void            *thrctx = ldap_pvt_thread_pool_context();
+                       Connection      conn = { 0 };
+                       OperationBuffer opbuf;
+                       Operation       *op;
+                       slap_callback   cb = { 0 };
+                       SlapReply       rs = { 0 };
+                       BerVarray       vals = NULL;
+                       Filter          f = { 0 }, f2 = { 0 };
+#ifdef LDAP_COMP_MATCH
+                       AttributeAssertion      ava = { NULL, BER_BVNULL, NULL };
+#else
+                       AttributeAssertion      ava = { NULL, BER_BVNULL };
+#endif
+                       AttributeName   attrs[ 2 ] = { 0 };
+
+                       connection_fake_init( &conn, &opbuf, thrctx );
+                       op = &opbuf.ob_op;
+
+                       op->o_bd = &cm->db;
+
+                       op->o_tag = LDAP_REQ_SEARCH;
+                       op->o_protocol = LDAP_VERSION3;
+                       cb.sc_response = pcache_cachedquery_open_cb;
+                       cb.sc_private = &vals;
+                       op->o_callback = &cb;
+                       op->o_time = slap_get_time();
+                       op->o_do_not_cache = 1;
+                       op->o_managedsait = SLAP_CONTROL_CRITICAL;
+
+                       op->o_dn = cm->db.be_rootdn;
+                       op->o_ndn = cm->db.be_rootndn;
+                       op->o_req_dn = cm->db.be_suffix[ 0 ];
+                       op->o_req_ndn = cm->db.be_nsuffix[ 0 ];
+
+                       op->ors_scope = LDAP_SCOPE_BASE;
+                       op->ors_deref = LDAP_DEREF_NEVER;
+                       op->ors_slimit = 1;
+                       op->ors_tlimit = SLAP_NO_LIMIT;
+                       ber_str2bv( "(cachedQueryURL=*)", 0, 0, &op->ors_filterstr );
+                       f.f_choice = LDAP_FILTER_PRESENT;
+                       f.f_desc = ad_cachedQueryURL;
+                       op->ors_filter = &f;
+                       attrs[ 0 ].an_desc = ad_cachedQueryURL;
+                       attrs[ 0 ].an_name = ad_cachedQueryURL->ad_cname;
+                       op->ors_attrs = attrs;
+                       op->ors_attrsonly = 0;
+
+                       rc = op->o_bd->be_search( op, &rs );
+                       if ( rc == LDAP_SUCCESS && vals != NULL ) {
+                               int     i;
+
+                               for ( i = 0; !BER_BVISNULL( &vals[ i ] ); i++ ) {
+                                       if ( url2query( vals[ i ].bv_val, op, qm ) == 0 ) {
+                                               cm->num_cached_queries++;
+                                       }
+                               }
+
+                               ber_bvarray_free_x( vals, op->o_tmpmemctx );
+                       }
+
+                       /* count cached entries */
+                       f.f_choice = LDAP_FILTER_NOT;
+                       f.f_not = &f2;
+                       f2.f_choice = LDAP_FILTER_EQUALITY;
+                       f2.f_ava = &ava;
+                       f2.f_av_desc = slap_schema.si_ad_objectClass;
+                       BER_BVSTR( &f2.f_av_value, "glue" );
+                       ber_str2bv( "(!(objectClass=glue))", 0, 0, &op->ors_filterstr );
+
+                       op->ors_slimit = SLAP_NO_LIMIT;
+                       op->ors_scope = LDAP_SCOPE_SUBTREE;
+                       op->ors_attrs = slap_anlist_no_attrs;
+
+                       op->o_callback->sc_response = pcache_cachedquery_count_cb;
+                       rs.sr_nentries = 0;
+                       op->o_callback->sc_private = &rs.sr_nentries;
+
+                       rc = op->o_bd->be_search( op, &rs );
+
+                       cm->cur_entries = rs.sr_nentries;
+
+                       /* ignore errors */
+                       rc = 0;
+               }
        }
 
        return rc;
@@ -2259,7 +3178,8 @@ pcache_free_qbase( void *v )
 
 static int
 pcache_db_close(
-       BackendDB *be
+       BackendDB *be,
+       ConfigReply *cr
 )
 {
        slap_overinst *on = (slap_overinst *)be->bd_info;
@@ -2268,12 +3188,85 @@ pcache_db_close(
        QueryTemplate *tm;
        int i, rc = 0;
 
+       if ( cm->save_queries ) {
+               CachedQuery     *qc;
+               BerVarray       vals = NULL;
+
+               void            *thrctx;
+               Connection      conn = { 0 };
+               OperationBuffer opbuf;
+               Operation       *op;
+               slap_callback   cb = { 0 };
+
+               SlapReply       rs = { REP_RESULT };
+               Modifications   mod = { 0 };
+
+               thrctx = ldap_pvt_thread_pool_context();
+
+               connection_fake_init( &conn, &opbuf, thrctx );
+               op = &opbuf.ob_op;
+
+               if ( qm->templates != NULL ) {
+                       for ( tm = qm->templates; tm != NULL; tm = tm->qmnext ) {
+                               for ( qc = tm->query; qc; qc = qc->next ) {
+                                       struct berval   bv;
+
+                                       if ( query2url( op, qc, &bv ) == 0 ) {
+                                               ber_bvarray_add_x( &vals, &bv, op->o_tmpmemctx );
+                                       }
+                               }
+                       }
+               }
+
+               op->o_bd = &cm->db;
+               op->o_dn = cm->db.be_rootdn;
+               op->o_ndn = cm->db.be_rootndn;
+
+               op->o_tag = LDAP_REQ_MODIFY;
+               op->o_protocol = LDAP_VERSION3;
+               cb.sc_response = slap_null_cb;
+               op->o_callback = &cb;
+               op->o_time = slap_get_time();
+               op->o_do_not_cache = 1;
+               op->o_managedsait = SLAP_CONTROL_CRITICAL;
+
+               op->o_req_dn = op->o_bd->be_suffix[0];
+               op->o_req_ndn = op->o_bd->be_nsuffix[0];
+
+               mod.sml_op = LDAP_MOD_REPLACE;
+               mod.sml_flags = 0;
+               mod.sml_desc = ad_cachedQueryURL;
+               mod.sml_type = ad_cachedQueryURL->ad_cname;
+               mod.sml_values = vals;
+               mod.sml_nvalues = NULL;
+               mod.sml_next = NULL;
+               Debug( pcache_debug,
+                       "%sSETTING CACHED QUERY URLS\n",
+                       vals == NULL ? "RE" : "", 0, 0 );
+
+               op->orm_modlist = &mod;
+
+               op->o_bd->be_modify( op, &rs );
+
+               ber_bvarray_free_x( vals, op->o_tmpmemctx );
+       }
+
        /* cleanup stuff inherited from the original database... */
        cm->db.be_limits = NULL;
        cm->db.be_acl = NULL;
 
+       /* stop the thread ... */
+       if ( cm->cc_arg ) {
+               ldap_pvt_thread_mutex_lock( &slapd_rq.rq_mutex );
+               if ( ldap_pvt_runqueue_isrunning( &slapd_rq, cm->cc_arg ) ) {
+                       ldap_pvt_runqueue_stoptask( &slapd_rq, cm->cc_arg );
+               }
+               ldap_pvt_runqueue_remove( &slapd_rq, cm->cc_arg );
+               ldap_pvt_thread_mutex_unlock( &slapd_rq.rq_mutex );
+       }
+
        if ( cm->db.bd_info->bi_db_close ) {
-               rc = cm->db.bd_info->bi_db_close( &cm->db );
+               rc = cm->db.bd_info->bi_db_close( &cm->db, NULL );
        }
        while ( (tm = qm->templates) != NULL ) {
                CachedQuery *qc, *qn;
@@ -2300,7 +3293,8 @@ pcache_db_close(
 
 static int
 pcache_db_destroy(
-       BackendDB *be
+       BackendDB *be,
+       ConfigReply *cr
 )
 {
        slap_overinst *on = (slap_overinst *)be->bd_info;
@@ -2319,6 +3313,368 @@ pcache_db_destroy(
        return 0;
 }
 
+#ifdef PCACHE_CONTROL_PRIVDB
+/*
+        Control ::= SEQUENCE {
+             controlType             LDAPOID,
+             criticality             BOOLEAN DEFAULT FALSE,
+             controlValue            OCTET STRING OPTIONAL }
+
+        controlType ::= 1.3.6.1.4.1.4203.666.11.9.5.1
+
+ * criticality must be TRUE; controlValue must be absent.
+ */
+static int
+parse_privdb_ctrl(
+       Operation       *op,
+       SlapReply       *rs,
+       LDAPControl     *ctrl )
+{
+       if ( op->o_ctrlflag[ privDB_cid ] != SLAP_CONTROL_NONE ) {
+               rs->sr_text = "privateDB control specified multiple times";
+               return LDAP_PROTOCOL_ERROR;
+       }
+
+       if ( !BER_BVISNULL( &ctrl->ldctl_value ) ) {
+               rs->sr_text = "privateDB control value not absent";
+               return LDAP_PROTOCOL_ERROR;
+       }
+
+       if ( !ctrl->ldctl_iscritical ) {
+               rs->sr_text = "privateDB control criticality required";
+               return LDAP_PROTOCOL_ERROR;
+       }
+
+       op->o_ctrlflag[ privDB_cid ] = SLAP_CONTROL_CRITICAL;
+
+       return LDAP_SUCCESS;
+}
+
+static char *extops[] = {
+       LDAP_EXOP_MODIFY_PASSWD,
+       NULL
+};
+#endif /* PCACHE_CONTROL_PRIVDB */
+
+#ifdef PCACHE_EXOP_QUERY_DELETE
+static struct berval pcache_exop_QUERY_DELETE = BER_BVC( PCACHE_EXOP_QUERY_DELETE );
+
+#define        LDAP_TAG_EXOP_QUERY_DELETE_BASE ((LBER_CLASS_CONTEXT|LBER_CONSTRUCTED) + 0)
+#define        LDAP_TAG_EXOP_QUERY_DELETE_DN   ((LBER_CLASS_CONTEXT|LBER_CONSTRUCTED) + 1)
+#define        LDAP_TAG_EXOP_QUERY_DELETE_UUID ((LBER_CLASS_CONTEXT|LBER_CONSTRUCTED) + 2)
+
+/*
+        ExtendedRequest ::= [APPLICATION 23] SEQUENCE {
+             requestName      [0] LDAPOID,
+             requestValue     [1] OCTET STRING OPTIONAL }
+
+        requestName ::= 1.3.6.1.4.1.4203.666.11.9.6.1
+
+        requestValue ::= SEQUENCE { CHOICE {
+                  baseDN           [0] LDAPDN
+                  entryDN          [1] LDAPDN },
+             queryID          [2] OCTET STRING (SIZE(16))
+                  -- constrained to UUID }
+
+ * Either baseDN or entryDN must be present, to allow database selection.
+ *
+ * 1. if baseDN and queryID are present, then the query corresponding
+ *    to queryID is deleted;
+ * 2. if baseDN is present and queryID is absent, then all queries
+ *    are deleted;
+ * 3. if entryDN is present and queryID is absent, then all queries
+ *    corresponding to the queryID values present in entryDN are deleted;
+ * 4. if entryDN and queryID are present, then all queries
+ *    corresponding to the queryID values present in entryDN are deleted,
+ *    but only if the value of queryID is contained in the entry;
+ *
+ * Currently, only 1, 3 and 4 are implemented.  2 can be obtained by either
+ * recursively deleting the database (ldapdelete -r) with PRIVDB control,
+ * or by removing the database files.
+
+        ExtendedResponse ::= [APPLICATION 24] SEQUENCE {
+             COMPONENTS OF LDAPResult,
+             responseName     [10] LDAPOID OPTIONAL,
+             responseValue    [11] OCTET STRING OPTIONAL }
+
+ * responseName and responseValue must be absent.
+ */
+
+/*
+ * - on success, *tagp is either LDAP_TAG_EXOP_QUERY_DELETE_BASE
+ *   or LDAP_TAG_EXOP_QUERY_DELETE_DN.
+ * - if ndn != NULL, it is set to the normalized DN in the request
+ *   corresponding to either the baseDN or the entryDN, according
+ *   to *tagp; memory is malloc'ed on the Operation's slab, and must
+ *   be freed by the caller.
+ * - if uuid != NULL, it is set to point to the normalized UUID;
+ *   memory is malloc'ed on the Operation's slab, and must
+ *   be freed by the caller.
+ */
+static int
+pcache_parse_query_delete(
+       struct berval   *in,
+       ber_tag_t       *tagp,
+       struct berval   *ndn,
+       struct berval   *uuid,
+       const char      **text,
+       void            *ctx )
+{
+       int                     rc = LDAP_SUCCESS;
+       ber_tag_t               tag;
+       ber_len_t               len = -1;
+       BerElementBuffer        berbuf;
+       BerElement              *ber = (BerElement *)&berbuf;
+       struct berval           reqdata = BER_BVNULL;
+
+       *text = NULL;
+
+       if ( ndn ) {
+               BER_BVZERO( ndn );
+       }
+
+       if ( uuid ) {
+               BER_BVZERO( uuid );
+       }
+
+       if ( in == NULL || in->bv_len == 0 ) {
+               *text = "empty request data field in queryDelete exop";
+               return LDAP_PROTOCOL_ERROR;
+       }
+
+       ber_dupbv_x( &reqdata, in, ctx );
+
+       /* ber_init2 uses reqdata directly, doesn't allocate new buffers */
+       ber_init2( ber, &reqdata, 0 );
+
+       tag = ber_scanf( ber, "{" /*}*/ );
+
+       if ( tag == LBER_ERROR ) {
+               Debug( LDAP_DEBUG_TRACE,
+                       "pcache_parse_query_delete: decoding error.\n",
+                       0, 0, 0 );
+               goto decoding_error;
+       }
+
+       tag = ber_peek_tag( ber, &len );
+       if ( tag == LDAP_TAG_EXOP_QUERY_DELETE_BASE
+               || tag == LDAP_TAG_EXOP_QUERY_DELETE_DN )
+       {
+               *tagp = tag;
+
+               if ( ndn != NULL ) {
+                       struct berval   dn;
+
+                       tag = ber_scanf( ber, "m", &dn );
+                       if ( tag == LBER_ERROR ) {
+                               Debug( LDAP_DEBUG_TRACE,
+                                       "pcache_parse_query_delete: DN parse failed.\n",
+                                       0, 0, 0 );
+                               goto decoding_error;
+                       }
+
+                       rc = dnNormalize( 0, NULL, NULL, &dn, ndn, ctx );
+                       if ( rc != LDAP_SUCCESS ) {
+                               *text = "invalid DN in queryDelete exop request data";
+                               goto done;
+                       }
+
+               } else {
+                       tag = ber_scanf( ber, "x" /* "m" */ );
+                       if ( tag == LBER_DEFAULT ) {
+                               goto decoding_error;
+                       }
+               }
+
+               tag = ber_peek_tag( ber, &len );
+       }
+
+       if ( tag == LDAP_TAG_EXOP_QUERY_DELETE_UUID ) {
+               if ( uuid != NULL ) {
+                       struct berval   bv;
+                       char            uuidbuf[ LDAP_LUTIL_UUIDSTR_BUFSIZE ];
+
+                       tag = ber_scanf( ber, "m", &bv );
+                       if ( tag == LBER_ERROR ) {
+                               Debug( LDAP_DEBUG_TRACE,
+                                       "pcache_parse_query_delete: UUID parse failed.\n",
+                                       0, 0, 0 );
+                               goto decoding_error;
+                       }
+
+                       if ( bv.bv_len != 16 ) {
+                               Debug( LDAP_DEBUG_TRACE,
+                                       "pcache_parse_query_delete: invalid UUID length %lu.\n",
+                                       (unsigned long)bv.bv_len, 0, 0 );
+                               goto decoding_error;
+                       }
+
+                       rc = lutil_uuidstr_from_normalized(
+                               bv.bv_val, bv.bv_len,
+                               uuidbuf, sizeof( uuidbuf ) );
+                       if ( rc == -1 ) {
+                               goto decoding_error;
+                       }
+                       ber_str2bv( uuidbuf, rc, 1, uuid );
+                       rc = LDAP_SUCCESS;
+
+               } else {
+                       tag = ber_skip_tag( ber, &len );
+                       if ( tag == LBER_DEFAULT ) {
+                               goto decoding_error;
+                       }
+
+                       if ( len != 16 ) {
+                               Debug( LDAP_DEBUG_TRACE,
+                                       "pcache_parse_query_delete: invalid UUID length %lu.\n",
+                                       (unsigned long)len, 0, 0 );
+                               goto decoding_error;
+                       }
+               }
+
+               tag = ber_peek_tag( ber, &len );
+       }
+
+       if ( tag != LBER_DEFAULT || len != 0 ) {
+decoding_error:;
+               Debug( LDAP_DEBUG_TRACE,
+                       "pcache_parse_query_delete: decoding error\n",
+                       0, 0, 0 );
+               rc = LDAP_PROTOCOL_ERROR;
+               *text = "queryDelete data decoding error";
+
+done:;
+               if ( ndn && !BER_BVISNULL( ndn ) ) {
+                       slap_sl_free( ndn->bv_val, ctx );
+                       BER_BVZERO( ndn );
+               }
+
+               if ( uuid && !BER_BVISNULL( uuid ) ) {
+                       slap_sl_free( uuid->bv_val, ctx );
+                       BER_BVZERO( uuid );
+               }
+       }
+
+       if ( !BER_BVISNULL( &reqdata ) ) {
+               ber_memfree_x( reqdata.bv_val, ctx );
+       }
+
+       return rc;
+}
+
+static int
+pcache_exop_query_delete(
+       Operation       *op,
+       SlapReply       *rs )
+{
+       BackendDB       *bd = op->o_bd;
+
+       struct berval   uuid = BER_BVNULL,
+                       *uuidp = NULL;
+       char            buf[ SLAP_TEXT_BUFLEN ] = { '\0' };
+       int             len = 0;
+       ber_tag_t       tag = LBER_DEFAULT;
+
+       if ( LogTest( LDAP_DEBUG_STATS ) ) {
+               uuidp = &uuid;
+       }
+
+       rs->sr_err = pcache_parse_query_delete( op->ore_reqdata,
+               &tag, &op->o_req_ndn, uuidp,
+               &rs->sr_text, op->o_tmpmemctx );
+       if ( rs->sr_err != LDAP_SUCCESS ) {
+               return rs->sr_err;
+       }
+
+       if ( LogTest( LDAP_DEBUG_STATS ) ) {
+               assert( !BER_BVISNULL( &op->o_req_ndn ) );
+               len = snprintf( buf, sizeof( buf ), " dn=\"%s\"", op->o_req_ndn.bv_val );
+
+               if ( !BER_BVISNULL( &uuid ) ) {
+                       snprintf( &buf[ len ], sizeof( buf ) - len, " queryId=\"%s\"", uuid.bv_val );
+               }
+
+               Debug( LDAP_DEBUG_STATS, "%s QUERY DELETE%s\n",
+                       op->o_log_prefix, buf, 0 );
+       }
+       op->o_req_dn = op->o_req_ndn;
+
+       op->o_bd = select_backend( &op->o_req_ndn, 0 );
+       rs->sr_err = backend_check_restrictions( op, rs,
+               (struct berval *)&pcache_exop_QUERY_DELETE );
+       if ( rs->sr_err != LDAP_SUCCESS ) {
+               goto done;
+       }
+
+       if ( op->o_bd->be_extended == NULL ) {
+               send_ldap_error( op, rs, LDAP_UNAVAILABLE_CRITICAL_EXTENSION,
+                       "backend does not support extended operations" );
+               goto done;
+       }
+
+       op->o_bd->be_extended( op, rs );
+
+done:;
+       if ( !BER_BVISNULL( &op->o_req_ndn ) ) {
+               op->o_tmpfree( op->o_req_ndn.bv_val, op->o_tmpmemctx );
+               BER_BVZERO( &op->o_req_ndn );
+               BER_BVZERO( &op->o_req_dn );
+       }
+
+       if ( !BER_BVISNULL( &uuid ) ) {
+               op->o_tmpfree( uuid.bv_val, op->o_tmpmemctx );
+       }
+
+       op->o_bd = bd;
+
+        return rs->sr_err;
+}
+
+static int
+pcache_op_extended( Operation *op, SlapReply *rs )
+{
+       slap_overinst   *on = (slap_overinst *)op->o_bd->bd_info;
+       cache_manager   *cm = on->on_bi.bi_private;
+
+#ifdef PCACHE_CONTROL_PRIVDB
+       if ( op->o_ctrlflag[ privDB_cid ] == SLAP_CONTROL_CRITICAL ) {
+               return pcache_op_privdb( op, rs );
+       }
+#endif /* PCACHE_CONTROL_PRIVDB */
+
+       if ( bvmatch( &op->ore_reqoid, &pcache_exop_QUERY_DELETE ) ) {
+               struct berval   uuid = BER_BVNULL;
+               ber_tag_t       tag = LBER_DEFAULT;
+
+               rs->sr_err = pcache_parse_query_delete( op->ore_reqdata,
+                       &tag, NULL, &uuid, &rs->sr_text, op->o_tmpmemctx );
+               assert( rs->sr_err == LDAP_SUCCESS );
+
+               if ( tag == LDAP_TAG_EXOP_QUERY_DELETE_DN ) {
+                       /* remove all queries related to the selected entry */
+                       rs->sr_err = pcache_remove_entry_queries_from_cache( op,
+                               cm, &op->o_req_ndn, &uuid );
+
+               } else if ( tag == LDAP_TAG_EXOP_QUERY_DELETE_BASE ) {
+                       if ( !BER_BVISNULL( &uuid ) ) {
+                               /* remove the selected query */
+                               rs->sr_err = pcache_remove_query_from_cache( op,
+                                       cm, &uuid );
+
+                       } else {
+                               /* TODO: remove all queries */
+                               rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
+                               rs->sr_text = "deletion of all queries not implemented";
+                       }
+               }
+
+               op->o_tmpfree( uuid.bv_val, op->o_tmpmemctx );
+       }
+
+       return rs->sr_err;
+}
+#endif /* PCACHE_EXOP_QUERY_DELETE */
+
 static slap_overinst pcache;
 
 static char *obsolete_names[] = {
@@ -2326,20 +3682,52 @@ static char *obsolete_names[] = {
        NULL
 };
 
-int pcache_initialize()
+#if SLAPD_OVER_PROXYCACHE == SLAPD_MOD_DYNAMIC
+static
+#endif /* SLAPD_OVER_PROXYCACHE == SLAPD_MOD_DYNAMIC */
+int
+pcache_initialize()
 {
-       int code;
+       int i, code;
        struct berval debugbv = BER_BVC("pcache");
 
-       if (( code = slap_loglevel_get( &debugbv, &pcache_debug )))
+       code = slap_loglevel_get( &debugbv, &pcache_debug );
+       if ( code ) {
                return code;
+       }
 
-       code = register_at( queryid_schema, &ad_queryid, 0 );
-       if ( code ) {
+#ifdef PCACHE_CONTROL_PRIVDB
+       code = register_supported_control( PCACHE_CONTROL_PRIVDB,
+               SLAP_CTRL_BIND|SLAP_CTRL_ACCESS|SLAP_CTRL_HIDE, extops,
+               parse_privdb_ctrl, &privDB_cid );
+       if ( code != LDAP_SUCCESS ) {
                Debug( LDAP_DEBUG_ANY,
-                       "pcache_initialize: register_at failed\n", 0, 0, 0 );
+                       "pcache_initialize: failed to register control %s (%d)\n",
+                       PCACHE_CONTROL_PRIVDB, code, 0 );
                return code;
        }
+#endif /* PCACHE_CONTROL_PRIVDB */
+
+#ifdef PCACHE_EXOP_QUERY_DELETE
+       code = load_extop2( (struct berval *)&pcache_exop_QUERY_DELETE,
+               SLAP_EXOP_WRITES|SLAP_EXOP_HIDE, pcache_exop_query_delete,
+               0 );
+       if ( code != LDAP_SUCCESS ) {
+               Debug( LDAP_DEBUG_ANY,
+                       "pcache_initialize: unable to register queryDelete exop: %d.\n",
+                       code, 0, 0 );
+               return code;
+       }
+#endif /* PCACHE_EXOP_QUERY_DELETE */
+
+       for ( i = 0; as[i].desc != NULL; i++ ) {
+               code = register_at( as[i].desc, as[i].adp, 0 );
+               if ( code ) {
+                       Debug( LDAP_DEBUG_ANY,
+                               "pcache_initialize: register_at #%d failed\n", i, 0, 0 );
+                       return code;
+               }
+       }
 
        pcache.on_bi.bi_type = "pcache";
        pcache.on_bi.bi_obsolete_names = obsolete_names;
@@ -2350,6 +3738,19 @@ int pcache_initialize()
        pcache.on_bi.bi_db_destroy = pcache_db_destroy;
 
        pcache.on_bi.bi_op_search = pcache_op_search;
+#ifdef PCACHE_CONTROL_PRIVDB
+       pcache.on_bi.bi_op_bind = pcache_op_privdb;
+       pcache.on_bi.bi_op_compare = pcache_op_privdb;
+       pcache.on_bi.bi_op_modrdn = pcache_op_privdb;
+       pcache.on_bi.bi_op_modify = pcache_op_privdb;
+       pcache.on_bi.bi_op_add = pcache_op_privdb;
+       pcache.on_bi.bi_op_delete = pcache_op_privdb;
+#endif /* PCACHE_CONTROL_PRIVDB */
+#ifdef PCACHE_EXOP_QUERY_DELETE
+       pcache.on_bi.bi_extended = pcache_op_extended;
+#elif defined( PCACHE_CONTROL_PRIVDB )
+       pcache.on_bi.bi_extended = pcache_op_privdb;
+#endif
 
        pcache.on_bi.bi_chk_controls = pcache_chk_controls;
 
index 48ecf6821905b65532addd5839c03fb4f7219008..2900c64c31cd0ff17301e976080d1ca26c4df9b8 100644 (file)
@@ -31,7 +31,7 @@
 #include <ldap.h>
 #include "lutil.h"
 #include "slap.h"
-#if SLAPD_MODULES
+#ifdef SLAPD_MODULES
 #define LIBLTDL_DLL_IMPORT     /* Win32: don't re-export libltdl's symbols */
 #include <ltdl.h>
 #endif
@@ -61,6 +61,7 @@ typedef struct pw_conn {
 
 static pw_conn *pwcons;
 static int ppolicy_cid;
+static int ov_count;
 
 typedef struct pass_policy {
        AttributeDescription *ad; /* attribute to which the policy applies */
@@ -358,6 +359,8 @@ account_locked( Operation *op, Entry *e,
 #define PPOLICY_EXPIRE 0x80L   /* primitive + 0 */
 #define PPOLICY_GRACE  0x81L   /* primitive + 1 */
 
+static const char ppolicy_ctrl_oid[] = LDAP_CONTROL_PASSWORDPOLICYRESPONSE;
+
 static LDAPControl *
 create_passcontrol( int exptime, int grace, LDAPPasswordPolicyError err )
 {
@@ -370,7 +373,7 @@ create_passcontrol( int exptime, int grace, LDAPPasswordPolicyError err )
        if ( c == NULL ) {
                return NULL;
        }
-       c->ldctl_oid = LDAP_CONTROL_PASSWORDPOLICYRESPONSE;
+       c->ldctl_oid = (char *)ppolicy_ctrl_oid;
        c->ldctl_iscritical = 0;
        BER_BVZERO( &c->ldctl_value );
 
@@ -618,7 +621,7 @@ check_password_quality( struct berval *cred, PassPolicy *pp, LDAPPasswordPolicyE
        rc = LDAP_SUCCESS;
 
        if (pp->pwdCheckModule[0]) {
-#if SLAPD_MODULES
+#ifdef SLAPD_MODULES
                lt_dlhandle mod;
                const char *err;
                
@@ -850,7 +853,7 @@ ctrls_cleanup( Operation *op, SlapReply *rs, LDAPControl **oldctrls )
        assert( rs->sr_ctrls[0] != NULL );
 
        for ( n = 0; rs->sr_ctrls[n]; n++ ) {
-               if ( rs->sr_ctrls[n]->ldctl_oid == LDAP_CONTROL_PASSWORDPOLICYRESPONSE ) {
+               if ( rs->sr_ctrls[n]->ldctl_oid == ppolicy_ctrl_oid ) {
                        ch_free( rs->sr_ctrls[n]->ldctl_value.bv_val );
                        ch_free( rs->sr_ctrls[n] );
                        rs->sr_ctrls[n] = (LDAPControl *)(-1);
@@ -1512,7 +1515,7 @@ ppolicy_modify( Operation *op, SlapReply *rs )
                slap_callback *sc;
 
                for ( sc = op->o_callback; sc; sc=sc->sc_next ) {
-                       if ( sc->sc_response == slap_replog_cb &&
+                       if ( sc->sc_response == slap_null_cb &&
                                sc->sc_private ) {
                                req_pwdexop_s *qpw = sc->sc_private;
                                newpw = qpw->rs_new;
@@ -1694,7 +1697,10 @@ ppolicy_modify( Operation *op, SlapReply *rs )
                goto return_results;
        }
 
-       if (pp.pwdMinAge > 0) {
+       /* Check age, but only if pwdReset is not TRUE */
+       pa = attr_find( e->e_attrs, ad_pwdReset );
+       if ((!pa || !bvmatch( &pa->a_nvals[0], &slap_true_bv )) &&
+               pp.pwdMinAge > 0) {
                time_t pwtime = (time_t)-1, now;
                int age;
 
@@ -2018,8 +2024,8 @@ ppolicy_parseCtrl(
        SlapReply *rs,
        LDAPControl *ctrl )
 {
-       if ( ctrl->ldctl_value.bv_len ) {
-               rs->sr_text = "passwordPolicyRequest control value not empty";
+       if ( !BER_BVISNULL( &ctrl->ldctl_value ) ) {
+               rs->sr_text = "passwordPolicyRequest control value not absent";
                return LDAP_PROTOCOL_ERROR;
        }
        op->o_ctrlflag[ppolicy_cid] = ctrl->ldctl_iscritical
@@ -2069,7 +2075,8 @@ attrNormalize(
 
 static int
 ppolicy_db_init(
-       BackendDB *be
+       BackendDB *be,
+       ConfigReply *cr
 )
 {
        slap_overinst *on = (slap_overinst *) be->bd_info;
@@ -2112,21 +2119,29 @@ ppolicy_db_init(
 
 static int
 ppolicy_db_open(
-    BackendDB *be
+       BackendDB *be,
+       ConfigReply *cr
 )
 {
+       ov_count++;
        return overlay_register_control( be, LDAP_CONTROL_PASSWORDPOLICYREQUEST );
 }
 
 static int
 ppolicy_close(
-       BackendDB *be
+       BackendDB *be,
+       ConfigReply *cr
 )
 {
        slap_overinst *on = (slap_overinst *) be->bd_info;
        pp_info *pi = on->on_bi.bi_private;
-       
-       free( pwcons );
+
+       /* Perhaps backover should provide bi_destroy hooks... */
+       ov_count--;
+       if ( ov_count <=0 && pwcons ) {
+               free( pwcons );
+               pwcons = NULL;
+       }
        free( pi->def_policy.bv_val );
        free( pi );
 
index 0a7c1aeb09d2decf3d8ca02dffb20f07ecd55d58..4afc7204e17ac64a878cf3797c86e25a75d2ddd8 100644 (file)
@@ -48,8 +48,12 @@ static BerValue refint_dn = BER_BVC("cn=Referential Integrity Overlay");
 static BerValue refint_ndn = BER_BVC("cn=referential integrity overlay");
 
 typedef struct refint_attrs_s {
-       struct refint_attrs_s *next;
-       AttributeDescription *attr;
+       struct refint_attrs_s   *next;
+       AttributeDescription    *attr;
+       BerVarray               old_vals;
+       BerVarray               old_nvals;
+       BerVarray               new_vals;
+       BerVarray               new_nvals;
 } refint_attrs;
 
 typedef struct dependents_s {
@@ -84,6 +88,8 @@ typedef struct refint_data_s {
 
 #define        RUNQ_INTERVAL   36000   /* a long time */
 
+static MatchingRule    *mr_dnSubtreeMatch;
+
 enum {
        REFINT_ATTRS = 1,
        REFINT_NOTHING
@@ -209,10 +215,10 @@ refint_cf_gen(ConfigArgs *c)
                                        ip->next = dd->attrs;
                                        dd->attrs = ip;
                                } else {
-                                       snprintf( c->msg, sizeof( c->msg ),
+                                       snprintf( c->cr_msg, sizeof( c->cr_msg ),
                                                "%s <%s>: %s", c->argv[0], c->argv[i], text );
                                        Debug ( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
-                                               "%s: %s\n", c->log, c->msg, 0 );
+                                               "%s: %s\n", c->log, c->cr_msg, 0 );
                                        rc = ARG_BAD_CONF;
                                }
                        }
@@ -245,7 +251,8 @@ refint_cf_gen(ConfigArgs *c)
 
 static int
 refint_db_init(
-       BackendDB       *be
+       BackendDB       *be,
+       ConfigReply     *cr
 )
 {
        slap_overinst *on = (slap_overinst *)be->bd_info;
@@ -259,7 +266,8 @@ refint_db_init(
 
 static int
 refint_db_destroy(
-       BackendDB       *be
+       BackendDB       *be,
+       ConfigReply     *cr
 )
 {
        slap_overinst *on = (slap_overinst *)be->bd_info;
@@ -280,7 +288,8 @@ refint_db_destroy(
 
 static int
 refint_open(
-       BackendDB *be
+       BackendDB *be,
+       ConfigReply *cr
 )
 {
        slap_overinst *on       = (slap_overinst *)be->bd_info;
@@ -308,7 +317,8 @@ refint_open(
 
 static int
 refint_close(
-       BackendDB *be
+       BackendDB *be,
+       ConfigReply *cr
 )
 {
        slap_overinst *on       = (slap_overinst *) be->bd_info;
@@ -373,28 +383,109 @@ refint_search_cb(
        rq->attrs = ip;
        ip->attrs = NULL;
        for(ia = da; ia; ia = ia->next) {
-           if ( (a = attr_find(rs->sr_entry->e_attrs, ia->attr) ) )
-               for(i = 0, b = a->a_nvals; b[i].bv_val; i++)
-                   if(bvmatch(&rq->oldndn, &b[i])) {
-                       na = op->o_tmpalloc(sizeof( refint_attrs ), op->o_tmpmemctx );
-                       na->next = ip->attrs;
-                       ip->attrs = na;
-                       na->attr = ia->attr;
-                       /* If this is a delete and there's only one value, and
-                        * we have a nothing DN configured, allocate the attr again.
-                        */
-                       if(!b[1].bv_val && BER_BVISEMPTY( &rq->newdn ) &&
-                               dd->nothing.bv_val) {
-                               na = op->o_tmpalloc(sizeof( refint_attrs ), op->o_tmpmemctx );
-                               na->next = ip->attrs;
-                               ip->attrs = na;
-                               na->attr = ia->attr;
+               if ( (a = attr_find(rs->sr_entry->e_attrs, ia->attr) ) ) {
+                       int             first = -1, count = 0, deleted = 0;
+
+                       na = NULL;
+
+                       for(i = 0, b = a->a_nvals; b[i].bv_val; i++) {
+                               count++;
+
+                               if(dnIsSuffix(&b[i], &rq->oldndn)) {
+                                       /* first match? create structure */
+                                       if ( na == NULL ) {
+                                               na = op->o_tmpcalloc( 1,
+                                                       sizeof( refint_attrs ),
+                                                       op->o_tmpmemctx );
+                                               na->next = ip->attrs;
+                                               ip->attrs = na;
+                                               na->attr = ia->attr;
+
+                                               /* delete, or exact match? note it's first match */
+                                               if ( BER_BVISEMPTY( &rq->newdn ) &&
+                                                       b[i].bv_len == rq->oldndn.bv_len )
+                                               {
+                                                       first = i;
+                                               }
+                                       }
+
+                                       /* if it's a rename, or a subordinate match,
+                                        * save old and build new dn */
+                                       if ( !BER_BVISEMPTY( &rq->newdn ) &&
+                                               b[i].bv_len != rq->oldndn.bv_len )
+                                       {
+                                               struct berval   newsub, newdn, olddn, oldndn;
+
+                                               /* if not first, save first as well */
+                                               if ( first != -1 ) {
+
+                                                       ber_dupbv_x( &olddn, &a->a_vals[first], op->o_tmpmemctx );
+                                                       ber_bvarray_add_x( &na->old_vals, &olddn, op->o_tmpmemctx );
+                                                       ber_dupbv_x( &oldndn, &a->a_nvals[first], op->o_tmpmemctx );
+                                                       ber_bvarray_add_x( &na->old_nvals, &oldndn, op->o_tmpmemctx );
+
+                                                       newsub = a->a_vals[first];
+                                                       newsub.bv_len -= rq->olddn.bv_len + 1;
+
+                                                       build_new_dn( &newdn, &rq->newdn, &newsub, op->o_tmpmemctx );
+
+                                                       ber_bvarray_add_x( &na->new_vals, &newdn, op->o_tmpmemctx );
+
+                                                       newsub = a->a_nvals[first];
+                                                       newsub.bv_len -= rq->oldndn.bv_len + 1;
+
+                                                       build_new_dn( &newdn, &rq->newndn, &newsub, op->o_tmpmemctx );
+
+                                                       ber_bvarray_add_x( &na->new_nvals, &newdn, op->o_tmpmemctx );
+                                                       
+                                                       first = -1;
+                                               }
+
+                                               ber_dupbv_x( &olddn, &a->a_vals[i], op->o_tmpmemctx );
+                                               ber_bvarray_add_x( &na->old_vals, &olddn, op->o_tmpmemctx );
+                                               ber_dupbv_x( &oldndn, &a->a_nvals[i], op->o_tmpmemctx );
+                                               ber_bvarray_add_x( &na->old_nvals, &oldndn, op->o_tmpmemctx );
+
+                                               newsub = a->a_vals[i];
+                                               newsub.bv_len -= rq->olddn.bv_len + 1;
+
+                                               build_new_dn( &newdn, &rq->newdn, &newsub, op->o_tmpmemctx );
+
+                                               ber_bvarray_add_x( &na->new_vals, &newdn, op->o_tmpmemctx );
+
+                                               newsub = a->a_nvals[i];
+                                               newsub.bv_len -= rq->oldndn.bv_len + 1;
+
+                                               build_new_dn( &newdn, &rq->newndn, &newsub, op->o_tmpmemctx );
+
+                                               ber_bvarray_add_x( &na->new_nvals, &newdn, op->o_tmpmemctx );
+                                       }
+
+                                       /* count deteles */
+                                       if ( BER_BVISEMPTY( &rq->newdn ) ) {
+                                               deleted++;
+                                       }
+                               }
+
+                               /* If this is a delete and no value would be left, and
+                                * we have a nothing DN configured, allocate the attr again.
+                                */
+                               if ( count == deleted && !BER_BVISNULL(&dd->nothing) )
+                               {
+                                       na = op->o_tmpcalloc( 1,
+                                               sizeof( refint_attrs ),
+                                               op->o_tmpmemctx );
+                                       na->next = ip->attrs;
+                                       ip->attrs = na;
+                                       na->attr = ia->attr;
+                               }
+
+                               Debug( LDAP_DEBUG_TRACE, "refint_search_cb: %s: %s (#%d)\n",
+                                       a->a_desc->ad_cname.bv_val, rq->olddn.bv_val, count );
                        }
-                       Debug(LDAP_DEBUG_TRACE, "refint_search_cb: %s: %s\n",
-                               a->a_desc->ad_cname.bv_val, rq->olddn.bv_val, 0);
-                       break;
-           }
+               }
        }
+
        return(0);
 }
 
@@ -410,12 +501,12 @@ refint_qtask( void *ctx, void *arg )
        slap_callback cb = { NULL, NULL, NULL, NULL };
        Filter ftop, *fptr;
        refint_q *rq;
-       dependent_data *dp;
+       dependent_data *dp, *dp_next;
        refint_attrs *ra, *ip;
        int rc;
 
-       op = (Operation *) &opbuf;
-       connection_fake_init( &conn, op, ctx );
+       connection_fake_init( &conn, &opbuf, ctx );
+       op = &opbuf.ob_op;
 
        /*
        ** build a search filter for all configured attributes;
@@ -432,11 +523,16 @@ refint_qtask( void *ctx, void *arg )
        ftop.f_or = NULL;
        op->ors_filter = &ftop;
        for(ip = id->attrs; ip; ip = ip->next) {
-               fptr = op->o_tmpalloc( sizeof(Filter) + sizeof(AttributeAssertion),
-                       op->o_tmpmemctx );
-               fptr->f_choice = LDAP_FILTER_EQUALITY;
-               fptr->f_ava = (AttributeAssertion *)(fptr+1);
-               fptr->f_ava->aa_desc = ip->attr;
+               fptr = op->o_tmpcalloc( sizeof(Filter) + sizeof(MatchingRuleAssertion),
+                       1, op->o_tmpmemctx );
+               /* Use (attr:dnSubtreeMatch:=value) to catch subtree rename
+                * and subtree delete where supported */
+               fptr->f_choice = LDAP_FILTER_EXT;
+               fptr->f_mra = (MatchingRuleAssertion *)(fptr+1);
+               fptr->f_mr_rule = mr_dnSubtreeMatch;
+               fptr->f_mr_rule_text = mr_dnSubtreeMatch->smr_str;
+               fptr->f_mr_desc = ip->attr;
+               fptr->f_mr_dnattrs = 0;
                fptr->f_next = ftop.f_or;
                ftop.f_or = fptr;
        }
@@ -455,7 +551,7 @@ refint_qtask( void *ctx, void *arg )
                        break;
 
                for (fptr = ftop.f_or; fptr; fptr=fptr->f_next )
-                       fptr->f_av_value = rq->oldndn;
+                       fptr->f_mr_value = rq->oldndn;
 
                filter2bv_x( op, op->ors_filter, &op->ors_filterstr );
 
@@ -513,14 +609,16 @@ refint_qtask( void *ctx, void *arg )
                **
                */
 
-               for(dp = rq->attrs; dp; dp = dp->next) {
+               for(dp = rq->attrs; dp; dp = dp_next) {
                        Modifications *m, *first = NULL;
 
+                       dp_next = dp->next;
+
                        op->orm_modlist = NULL;
 
                        op->o_req_dn    = dp->dn;
                        op->o_req_ndn   = dp->ndn;
-                       op->o_bd = select_backend(&dp->ndn, 0, 1);
+                       op->o_bd = select_backend(&dp->ndn, 1);
                        if(!op->o_bd) {
                                Debug( LDAP_DEBUG_TRACE,
                                        "refint_response: no backend for DN %s!\n",
@@ -529,6 +627,8 @@ refint_qtask( void *ctx, void *arg )
                        }
                        rs.sr_type      = REP_RESULT;
                        for (ra = dp->attrs; ra; ra = dp->attrs) {
+                               size_t  len;
+
                                dp->attrs = ra->next;
                                /* Set our ModifiersName */
                                if ( SLAP_LASTMOD( op->o_bd )) {
@@ -550,9 +650,15 @@ refint_qtask( void *ctx, void *arg )
                                        m->sml_nvalues[0] = refint_ndn;
                                }
                                if ( !BER_BVISEMPTY( &rq->newdn ) || ( ra->next &&
-                                       ra->attr == ra->next->attr )) {
-                                       m = op->o_tmpalloc( sizeof(Modifications) +
-                                               4*sizeof(BerValue), op->o_tmpmemctx );
+                                       ra->attr == ra->next->attr ))
+                               {
+                                       len = sizeof(Modifications);
+
+                                       if ( ra->new_vals == NULL ) {
+                                               len += 4*sizeof(BerValue);
+                                       }
+
+                                       m = op->o_tmpalloc( len, op->o_tmpmemctx );
                                        m->sml_next = op->orm_modlist;
                                        if ( !first )
                                                first = m;
@@ -561,23 +667,33 @@ refint_qtask( void *ctx, void *arg )
                                        m->sml_flags = 0;
                                        m->sml_desc = ra->attr;
                                        m->sml_type = ra->attr->ad_cname;
-                                       m->sml_values = (BerVarray)(m+1);
-                                       m->sml_nvalues = m->sml_values+2;
-                                       BER_BVZERO( &m->sml_values[1] );
-                                       BER_BVZERO( &m->sml_nvalues[1] );
-                                       if ( BER_BVISEMPTY( &rq->newdn )) {
-                                               op->o_tmpfree( ra, op->o_tmpmemctx );
-                                               ra = dp->attrs;
-                                               dp->attrs = ra->next;
-                                               m->sml_values[0] = id->nothing;
-                                               m->sml_nvalues[0] = id->nnothing;
+                                       if ( ra->new_vals == NULL ) {
+                                               m->sml_values = (BerVarray)(m+1);
+                                               m->sml_nvalues = m->sml_values+2;
+                                               BER_BVZERO( &m->sml_values[1] );
+                                               BER_BVZERO( &m->sml_nvalues[1] );
+                                               if ( BER_BVISEMPTY( &rq->newdn )) {
+                                                       op->o_tmpfree( ra, op->o_tmpmemctx );
+                                                       ra = dp->attrs;
+                                                       dp->attrs = ra->next;
+                                                       m->sml_values[0] = id->nothing;
+                                                       m->sml_nvalues[0] = id->nnothing;
+                                               } else {
+                                                       m->sml_values[0] = rq->newdn;
+                                                       m->sml_nvalues[0] = rq->newndn;
+                                               }
                                        } else {
-                                               m->sml_values[0] = rq->newdn;
-                                               m->sml_nvalues[0] = rq->newndn;
+                                               m->sml_values = ra->new_vals;
+                                               m->sml_nvalues = ra->new_nvals;
                                        }
                                }
-                               m = op->o_tmpalloc( sizeof(Modifications) + 4*sizeof(BerValue),
-                                       op->o_tmpmemctx );
+
+                               len = sizeof(Modifications);
+                               if ( ra->old_vals == NULL ) {
+                                       len += 4*sizeof(BerValue);
+                               }
+
+                               m = op->o_tmpalloc( len, op->o_tmpmemctx );
                                m->sml_next = op->orm_modlist;
                                op->orm_modlist = m;
                                if ( !first )
@@ -586,12 +702,17 @@ refint_qtask( void *ctx, void *arg )
                                m->sml_flags = 0;
                                m->sml_desc = ra->attr;
                                m->sml_type = ra->attr->ad_cname;
-                               m->sml_values = (BerVarray)(m+1);
-                               m->sml_nvalues = m->sml_values+2;
-                               m->sml_values[0] = rq->olddn;
-                               m->sml_nvalues[0] = rq->oldndn;
-                               BER_BVZERO( &m->sml_values[1] );
-                               BER_BVZERO( &m->sml_nvalues[1] );
+                               if ( ra->old_vals == NULL ) {
+                                       m->sml_values = (BerVarray)(m+1);
+                                       m->sml_nvalues = m->sml_values+2;
+                                       m->sml_values[0] = rq->olddn;
+                                       m->sml_nvalues[0] = rq->oldndn;
+                                       BER_BVZERO( &m->sml_values[1] );
+                                       BER_BVZERO( &m->sml_nvalues[1] );
+                               } else {
+                                       m->sml_values = ra->old_vals;
+                                       m->sml_nvalues = ra->old_nvals;
+                               }
                                op->o_tmpfree( ra, op->o_tmpmemctx );
                        }
 
@@ -606,6 +727,10 @@ refint_qtask( void *ctx, void *arg )
 
                        while (( m = op->orm_modlist )) {
                                op->orm_modlist = m->sml_next;
+                               if ( m->sml_values && m->sml_values != (BerVarray)(m+1) ) {
+                                       ber_bvarray_free_x( m->sml_values, op->o_tmpmemctx );
+                                       ber_bvarray_free_x( m->sml_nvalues, op->o_tmpmemctx );
+                               }
                                op->o_tmpfree( m, op->o_tmpmemctx );
                                if ( m == first ) break;
                        }
@@ -624,6 +749,13 @@ done:
                ch_free( rq );
        }
 
+       /* free filter */
+       for ( fptr = ftop.f_or; fptr; ) {
+               Filter *f_next = fptr->f_next;
+               op->o_tmpfree( fptr, op->o_tmpmemctx );
+               fptr = f_next;
+       }
+
        /* wait until we get explicitly scheduled again */
        ldap_pvt_thread_mutex_lock( &slapd_rq.rq_mutex );
        ldap_pvt_runqueue_stoptask( &slapd_rq, id->qtask );
@@ -677,7 +809,7 @@ refint_response(
        **
        */
 
-       db = select_backend(&id->dn, 0, 1);
+       db = select_backend(&id->dn, 1);
 
        if(db) {
                if (!db->be_search || !db->be_modify) {
@@ -754,6 +886,14 @@ refint_response(
 int refint_initialize() {
        int rc;
 
+       mr_dnSubtreeMatch = mr_find( "dnSubtreeMatch" );
+       if ( mr_dnSubtreeMatch == NULL ) {
+               Debug( LDAP_DEBUG_ANY, "refint_initialize: "
+                       "unable to find MatchingRule 'dnSubtreeMatch'.\n",
+                       0, 0, 0 );
+               return 1;
+       }
+
        /* statically declared just after the #includes at top */
        refint.on_bi.bi_type = "refint";
        refint.on_bi.bi_db_init = refint_db_init;
index 4c8af8898695bcc2e7c3cb3509c6e1f9ccb2da3f..76b70d7be7b88b74dccdf018169e151adacddd65 100644 (file)
@@ -31,6 +31,7 @@
 #include <ac/socket.h>
 
 #include "slap.h"
+#include "config.h"
 #include "lutil.h"
 #include "ldif.h"
 
@@ -202,11 +203,11 @@ retcode_cb_response( Operation *op, SlapReply *rs )
 {
        retcode_cb_t    *rdc = (retcode_cb_t *)op->o_callback->sc_private;
 
+       op->o_tag = rdc->rdc_tag;
        if ( rs->sr_type == REP_SEARCH ) {
                ber_tag_t       o_tag = op->o_tag;
                int             rc;
 
-               op->o_tag = rdc->rdc_tag;
                if ( op->o_tag == LDAP_REQ_SEARCH ) {
                        rs->sr_attrs = rdc->rdc_attrs;
                }
@@ -216,7 +217,11 @@ retcode_cb_response( Operation *op, SlapReply *rs )
                return rc;
        }
 
-       if ( rs->sr_err == LDAP_SUCCESS ) {
+       switch ( rs->sr_err ) {
+       case LDAP_SUCCESS:
+       case LDAP_NO_SUCH_OBJECT:
+               /* in case of noSuchObject, stop the internal search
+                * for in-directory error stuff */
                if ( !op->o_abandon ) {
                        rdc->rdc_flags = SLAP_CB_CONTINUE;
                }
@@ -300,8 +305,9 @@ retcode_op_func( Operation *op, SlapReply *rs )
 
                        case LDAP_REQ_BIND:
                                /* skip if rootdn */
+                               /* FIXME: better give the db a chance? */
                                if ( be_isroot_pw( op ) ) {
-                                       return SLAP_CB_CONTINUE;
+                                       return LDAP_SUCCESS;
                                }
                                return retcode_op_internal( op, rs );
 
@@ -721,7 +727,7 @@ retcode_response( Operation *op, SlapReply *rs )
 }
 
 static int
-retcode_db_init( BackendDB *be )
+retcode_db_init( BackendDB *be, ConfigReply *cr )
 {
        slap_overinst   *on = (slap_overinst *)be->bd_info;
        retcode_t       *rd;
@@ -1083,7 +1089,7 @@ retcode_db_config(
 }
 
 static int
-retcode_db_open( BackendDB *be )
+retcode_db_open( BackendDB *be, ConfigReply *cr)
 {
        slap_overinst   *on = (slap_overinst *)be->bd_info;
        retcode_t       *rd = (retcode_t *)on->on_bi.bi_private;
@@ -1207,7 +1213,7 @@ retcode_db_open( BackendDB *be )
 }
 
 static int
-retcode_db_destroy( BackendDB *be )
+retcode_db_destroy( BackendDB *be, ConfigReply *cr )
 {
        slap_overinst   *on = (slap_overinst *)be->bd_info;
        retcode_t       *rd = (retcode_t *)on->on_bi.bi_private;
index 4e87d36dd2b05098e299f092f6df37b6f482f5ab..031f9f5d3c22ec18a094af944d392cf81322c2a0 100644 (file)
@@ -24,6 +24,8 @@
 #include <ac/string.h>
 
 #include "slap.h"
+#include "config.h"
+#include "lutil.h"
 #include "rwm.h"
 
 typedef struct rwm_op_state {
@@ -32,11 +34,12 @@ typedef struct rwm_op_state {
        struct berval ro_ndn;
        struct berval r_dn;
        struct berval r_ndn;
+       AttributeName *mapped_attrs;
        OpRequest o_request;
 } rwm_op_state;
 
 static int
-rwm_db_destroy( BackendDB *be );
+rwm_db_destroy( BackendDB *be, ConfigReply *cr );
 
 typedef struct rwm_op_cb {
        slap_callback cb;
@@ -55,8 +58,17 @@ rwm_op_cleanup( Operation *op, SlapReply *rs )
                op->o_req_dn = ros->ro_dn;
                op->o_req_ndn = ros->ro_ndn;
 
-               if ( !BER_BVISEMPTY( &ros->r_dn )) ch_free( ros->r_dn.bv_val );
-               if ( !BER_BVISEMPTY( &ros->r_ndn )) ch_free( ros->r_ndn.bv_val );
+               if ( !BER_BVISNULL( &ros->r_dn )
+                       && ros->r_dn.bv_val != ros->r_ndn.bv_val )
+               {
+                       ch_free( ros->r_dn.bv_val );
+                       BER_BVZERO( &ros->r_dn );
+               }
+
+               if ( !BER_BVISNULL( &ros->r_ndn ) ) {
+                       ch_free( ros->r_ndn.bv_val );
+                       BER_BVZERO( &ros->r_ndn );
+               }
 
                switch( ros->r_tag ) {
                case LDAP_REQ_COMPARE:
@@ -79,7 +91,7 @@ rwm_op_cleanup( Operation *op, SlapReply *rs )
                        }
                        break;
                case LDAP_REQ_SEARCH:
-                       ch_free( op->ors_attrs );
+                       ch_free( ros->mapped_attrs );
                        filter_free_x( op, op->ors_filter );
                        ch_free( op->ors_filterstr.bv_val );
                        op->ors_attrs = ros->ors_attrs;
@@ -139,14 +151,9 @@ rwm_op_dn_massage( Operation *op, SlapReply *rs, void *cookie,
         * Rewrite the dn if needed
         */
        dc.rwmap = rwmap;
-#ifdef ENABLE_REWRITE
        dc.conn = op->o_conn;
        dc.rs = rs;
        dc.ctx = (char *)cookie;
-#else /* ! ENABLE_REWRITE */
-       dc.tofrom = ((int *)cookie)[0];
-       dc.normalized = 0;
-#endif /* ! ENABLE_REWRITE */
 
        /* NOTE: in those cases where only the ndn is available,
         * and the caller sets op->o_req_dn = op->o_req_ndn,
@@ -172,12 +179,12 @@ rwm_op_dn_massage( Operation *op, SlapReply *rs, void *cookie,
 
        if ( op->o_req_dn.bv_val != op->o_req_ndn.bv_val ) {
                op->o_req_dn = dn;
-               ros->r_dn  = dn;
+               ros->r_dn = dn;
        } else {
                op->o_req_dn = ndn;
        }
-       ros->r_ndn = ndn;
        op->o_req_ndn = ndn;
+       ros->r_ndn = ndn;
 
        return LDAP_SUCCESS;
 }
@@ -195,14 +202,9 @@ rwm_op_add( Operation *op, SlapReply *rs )
        char                    *olddn = op->o_req_dn.bv_val;
        int                     isupdate;
 
-       rwm_op_cb *roc = rwm_callback_get( op, rs );
+       rwm_op_cb               *roc = rwm_callback_get( op, rs );
 
-#ifdef ENABLE_REWRITE
        rc = rwm_op_dn_massage( op, rs, "addDN", &roc->ros );
-#else /* ! ENABLE_REWRITE */
-       rc = 1;
-       rc = rwm_op_dn_massage( op, rs, &rc, &roc->ros );
-#endif /* ! ENABLE_REWRITE */
        if ( rc != LDAP_SUCCESS ) {
                op->o_bd->bd_info = (BackendInfo *)on->on_info;
                send_ldap_error( op, rs, rc, "addDN massage error" );
@@ -275,29 +277,17 @@ rwm_op_add( Operation *op, SlapReply *rs )
                                 * FIXME: rewrite could fail; in this case
                                 * the operation should give up, right?
                                 */
-#ifdef ENABLE_REWRITE
                                rc = rwm_dnattr_rewrite( op, rs, "addAttrDN",
                                                (*ap)->a_vals,
                                                (*ap)->a_nvals ? &(*ap)->a_nvals : NULL );
-#else /* ! ENABLE_REWRITE */
-                               rc = 1;
-                               rc = rwm_dnattr_rewrite( op, rs, &rc, (*ap)->a_vals,
-                                               (*ap)->a_nvals ? &(*ap)->a_nvals : NULL );
-#endif /* ! ENABLE_REWRITE */
                                if ( rc ) {
                                        goto cleanup_attr;
                                }
 
                        } else if ( (*ap)->a_desc == slap_schema.si_ad_ref ) {
-#ifdef ENABLE_REWRITE
                                rc = rwm_referral_rewrite( op, rs, "referralAttrDN",
                                                (*ap)->a_vals,
                                                (*ap)->a_nvals ? &(*ap)->a_nvals : NULL );
-#else /* ! ENABLE_REWRITE */
-                               rc = 1;
-                               rc = rwm_referral_rewrite( op, rs, &rc, (*ap)->a_vals,
-                                               (*ap)->a_nvals ? &(*ap)->a_nvals : NULL );
-#endif /* ! ENABLE_REWRITE */
                                if ( rc != LDAP_SUCCESS ) {
                                        goto cleanup_attr;
                                }
@@ -326,7 +316,6 @@ cleanup_attr:;
        return SLAP_CB_CONTINUE;
 }
 
-#ifdef ENABLE_REWRITE
 static int
 rwm_conn_init( BackendDB *be, Connection *conn )
 {
@@ -350,7 +339,6 @@ rwm_conn_destroy( BackendDB *be, Connection *conn )
 
        return SLAP_CB_CONTINUE;
 }
-#endif /* ENABLE_REWRITE */
 
 static int
 rwm_op_bind( Operation *op, SlapReply *rs )
@@ -358,14 +346,9 @@ rwm_op_bind( Operation *op, SlapReply *rs )
        slap_overinst           *on = (slap_overinst *) op->o_bd->bd_info;
        int                     rc;
 
-       rwm_op_cb *roc = rwm_callback_get( op, rs );
+       rwm_op_cb               *roc = rwm_callback_get( op, rs );
 
-#ifdef ENABLE_REWRITE
        rc = rwm_op_dn_massage( op, rs, "bindDN", &roc->ros );
-#else /* ! ENABLE_REWRITE */
-       rc = 1;
-       rc = rwm_op_dn_massage( op, rs, &rc, &roc->ros );
-#endif /* ! ENABLE_REWRITE */
        if ( rc != LDAP_SUCCESS ) {
                op->o_bd->bd_info = (BackendInfo *)on->on_info;
                send_ldap_error( op, rs, rc, "bindDN massage error" );
@@ -384,9 +367,7 @@ rwm_op_unbind( Operation *op, SlapReply *rs )
        struct ldaprwmap        *rwmap = 
                        (struct ldaprwmap *)on->on_bi.bi_private;
 
-#ifdef ENABLE_REWRITE
        rewrite_session_delete( rwmap->rwm_rw, op->o_conn );
-#endif /* ENABLE_REWRITE */
 
        return SLAP_CB_CONTINUE;
 }
@@ -399,16 +380,11 @@ rwm_op_compare( Operation *op, SlapReply *rs )
                        (struct ldaprwmap *)on->on_bi.bi_private;
 
        int                     rc;
-       struct berval mapped_vals[2] = { BER_BVNULL, BER_BVNULL };
+       struct berval           mapped_vals[2] = { BER_BVNULL, BER_BVNULL };
 
-       rwm_op_cb *roc = rwm_callback_get( op, rs );
+       rwm_op_cb               *roc = rwm_callback_get( op, rs );
 
-#ifdef ENABLE_REWRITE
        rc = rwm_op_dn_massage( op, rs, "compareDN", &roc->ros );
-#else /* ! ENABLE_REWRITE */
-       rc = 1;
-       rc = rwm_op_dn_massage( op, rs, &rc, &roc->ros );
-#endif /* ! ENABLE_REWRITE */
        if ( rc != LDAP_SUCCESS ) {
                op->o_bd->bd_info = (BackendInfo *)on->on_info;
                send_ldap_error( op, rs, rc, "compareDN massage error" );
@@ -460,12 +436,7 @@ rwm_op_compare( Operation *op, SlapReply *rs )
 
                        mapped_vals[0] = op->orc_ava->aa_value;
 
-#ifdef ENABLE_REWRITE
                        rc = rwm_dnattr_rewrite( op, rs, "compareAttrDN", NULL, mapped_valsp );
-#else /* ! ENABLE_REWRITE */
-                       rc = 1;
-                       rc = rwm_dnattr_rewrite( op, rs, &rc, NULL, mapped_valsp );
-#endif /* ! ENABLE_REWRITE */
 
                        if ( rc != LDAP_SUCCESS ) {
                                op->o_bd->bd_info = (BackendInfo *)on->on_info;
@@ -496,14 +467,9 @@ rwm_op_delete( Operation *op, SlapReply *rs )
        slap_overinst           *on = (slap_overinst *) op->o_bd->bd_info;
        int                     rc;
 
-       rwm_op_cb *roc = rwm_callback_get( op, rs );
+       rwm_op_cb               *roc = rwm_callback_get( op, rs );
 
-#ifdef ENABLE_REWRITE
        rc = rwm_op_dn_massage( op, rs, "deleteDN", &roc->ros );
-#else /* ! ENABLE_REWRITE */
-       rc = 1;
-       rc = rwm_op_dn_massage( op, rs, &rc, &roc->ros );
-#endif /* ! ENABLE_REWRITE */
        if ( rc != LDAP_SUCCESS ) {
                op->o_bd->bd_info = (BackendInfo *)on->on_info;
                send_ldap_error( op, rs, rc, "deleteDN massage error" );
@@ -526,14 +492,9 @@ rwm_op_modify( Operation *op, SlapReply *rs )
        Modifications           **mlp;
        int                     rc;
 
-       rwm_op_cb *roc = rwm_callback_get( op, rs );
+       rwm_op_cb               *roc = rwm_callback_get( op, rs );
 
-#ifdef ENABLE_REWRITE
        rc = rwm_op_dn_massage( op, rs, "modifyDN", &roc->ros );
-#else /* ! ENABLE_REWRITE */
-       rc = 1;
-       rc = rwm_op_dn_massage( op, rs, &rc, &roc->ros );
-#endif /* ! ENABLE_REWRITE */
        if ( rc != LDAP_SUCCESS ) {
                op->o_bd->bd_info = (BackendInfo *)on->on_info;
                send_ldap_error( op, rs, rc, "modifyDN massage error" );
@@ -541,7 +502,7 @@ rwm_op_modify( Operation *op, SlapReply *rs )
        }
 
        isupdate = be_shadow_update( op );
-       for ( mlp = &op->oq_modify.rs_modlist; *mlp; ) {
+       for ( mlp = &op->orm_modlist; *mlp; ) {
                int                     is_oc = 0;
                Modifications           *ml;
                struct ldapmapping      *mapping = NULL;
@@ -628,29 +589,15 @@ rwm_op_modify( Operation *op, SlapReply *rs )
                                if ( ml->sml_desc->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName
                                                || ( mapping != NULL && mapping->m_dst_ad->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName ) )
                                {
-#ifdef ENABLE_REWRITE
                                        rc = rwm_dnattr_rewrite( op, rs, "modifyAttrDN",
                                                        ml->sml_values,
                                                        ml->sml_nvalues ? &ml->sml_nvalues : NULL );
-#else /* ! ENABLE_REWRITE */
-                                       rc = 1;
-                                       rc = rwm_dnattr_rewrite( op, rs, &rc, 
-                                                       ml->sml_values,
-                                                       ml->sml_nvalues ? &ml->sml_nvalues : NULL );
-#endif /* ! ENABLE_REWRITE */
 
                                } else if ( ml->sml_desc == slap_schema.si_ad_ref ) {
-#ifdef ENABLE_REWRITE
                                        rc = rwm_referral_rewrite( op, rs,
                                                        "referralAttrDN",
                                                        ml->sml_values,
                                                        ml->sml_nvalues ? &ml->sml_nvalues : NULL );
-#else /* ! ENABLE_REWRITE */
-                                       rc = 1;
-                                       rc = rwm_referral_rewrite( op, rs, &rc,
-                                                       ml->sml_values,
-                                                       ml->sml_nvalues ? &ml->sml_nvalues : NULL );
-#endif /* ! ENABLE_REWRITE */
                                        if ( rc != LDAP_SUCCESS ) {
                                                goto cleanup_mod;
                                        }
@@ -693,7 +640,7 @@ rwm_op_modrdn( Operation *op, SlapReply *rs )
        
        int                     rc;
 
-       rwm_op_cb *roc = rwm_callback_get( op, rs );
+       rwm_op_cb               *roc = rwm_callback_get( op, rs );
 
        if ( op->orr_newSup ) {
                dncookie        dc;
@@ -704,14 +651,9 @@ rwm_op_modrdn( Operation *op, SlapReply *rs )
                 * Rewrite the new superior, if defined and required
                 */
                dc.rwmap = rwmap;
-#ifdef ENABLE_REWRITE
                dc.conn = op->o_conn;
                dc.rs = rs;
                dc.ctx = "newSuperiorDN";
-#else /* ! ENABLE_REWRITE */
-               dc.tofrom = 0;
-               dc.normalized = 0;
-#endif /* ! ENABLE_REWRITE */
                newSup = *op->orr_newSup;
                nnewSup = *op->orr_nnewSup;
                rc = rwm_dn_massage_pretty_normalize( &dc, op->orr_newSup, &newSup, &nnewSup );
@@ -734,12 +676,7 @@ rwm_op_modrdn( Operation *op, SlapReply *rs )
        /*
         * Rewrite the dn, if needed
         */
-#ifdef ENABLE_REWRITE
        rc = rwm_op_dn_massage( op, rs, "renameDN", &roc->ros );
-#else /* ! ENABLE_REWRITE */
-       rc = 1;
-       rc = rwm_op_dn_massage( op, rs, &rc, &roc->ros );
-#endif /* ! ENABLE_REWRITE */
        if ( rc != LDAP_SUCCESS ) {
                op->o_bd->bd_info = (BackendInfo *)on->on_info;
                send_ldap_error( op, rs, rc, "renameDN massage error" );
@@ -770,6 +707,11 @@ rwm_swap_attrs( Operation *op, SlapReply *rs )
        rwm_op_state *ros = cb->sc_private;
 
        rs->sr_attrs = ros->ors_attrs;
+
+       /* other overlays might have touched op->ors_attrs, 
+        * so we restore the original version here, otherwise
+        * attribute-mapping might fail */
+       op->ors_attrs = ros->mapped_attrs; 
        
        return SLAP_CB_CONTINUE;
 }
@@ -791,17 +733,12 @@ rwm_op_search( Operation *op, SlapReply *rs )
 
        char                    *text = NULL;
 
-       rwm_op_cb *roc = rwm_callback_get( op, rs );
+       rwm_op_cb               *roc = rwm_callback_get( op, rs );
 
-#ifdef ENABLE_REWRITE
        rc = rewrite_session_var_set( rwmap->rwm_rw, op->o_conn,
                "searchFilter", op->ors_filterstr.bv_val );
        if ( rc == LDAP_SUCCESS )
                rc = rwm_op_dn_massage( op, rs, "searchDN", &roc->ros );
-#else /* ! ENABLE_REWRITE */
-       rc = 1;
-       rc = rwm_op_dn_massage( op, rs, &rc, &roc->ros );
-#endif /* ! ENABLE_REWRITE */
        if ( rc != LDAP_SUCCESS ) {
                text = "searchDN massage error";
                goto error_return;
@@ -811,14 +748,9 @@ rwm_op_search( Operation *op, SlapReply *rs )
         * Rewrite the dn if needed
         */
        dc.rwmap = rwmap;
-#ifdef ENABLE_REWRITE
        dc.conn = op->o_conn;
        dc.rs = rs;
        dc.ctx = "searchFilterAttrDN";
-#else /* ! ENABLE_REWRITE */
-       dc.tofrom = 0;
-       dc.normalized = 0;
-#endif /* ! ENABLE_REWRITE */
 
        rc = rwm_filter_map_rewrite( op, &dc, op->ors_filter, &fstr );
        if ( rc != LDAP_SUCCESS ) {
@@ -844,6 +776,9 @@ rwm_op_search( Operation *op, SlapReply *rs )
        }
 
        op->ors_attrs = an;
+       /* store the mapped Attributes for later usage, in
+        * the case that other overlays change op->ors_attrs */
+       roc->ros.mapped_attrs = an;
        roc->cb.sc_response = rwm_swap_attrs;
 
        op->o_callback = &roc->cb;
@@ -914,12 +849,7 @@ rwm_exop_passwd( Operation *op, SlapReply *rs )
 
        roc = rwm_callback_get( op, rs );
 
-#ifdef ENABLE_REWRITE
        rc = rwm_op_dn_massage( op, rs, "extendedDN", &roc->ros );
-#else /* ! ENABLE_REWRITE */
-       rc = 1;
-       rc = rwm_op_dn_massage( op, rs, &rc, &roc->ros );
-#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" );
@@ -991,12 +921,7 @@ rwm_extended( Operation *op, SlapReply *rs )
 
        roc = rwm_callback_get( op, rs );
 
-#ifdef ENABLE_REWRITE
        rc = rwm_op_dn_massage( op, rs, "extendedDN", &roc->ros );
-#else /* ! ENABLE_REWRITE */
-       rc = 1;
-       rc = rwm_op_dn_massage( op, rs, &rc, &roc->ros );
-#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" );
@@ -1025,14 +950,9 @@ rwm_matched( Operation *op, SlapReply *rs )
        }
 
        dc.rwmap = rwmap;
-#ifdef ENABLE_REWRITE
        dc.conn = op->o_conn;
        dc.rs = rs;
        dc.ctx = "matchedDN";
-#else /* ! ENABLE_REWRITE */
-       dc.tofrom = 0;
-       dc.normalized = 0;
-#endif /* ! ENABLE_REWRITE */
        ber_str2bv( rs->sr_matched, 0, 0, &dn );
        mdn = dn;
        rc = rwm_dn_massage_pretty( &dc, &dn, &mdn );
@@ -1066,18 +986,14 @@ rwm_attrs( Operation *op, SlapReply *rs, Attribute** a_first, int stripEntryDN )
        int                     rc;
        Attribute               **ap;
        int                     isupdate;
+       int                     check_duplicate_attrs = 0;
 
        /*
         * Rewrite the dn attrs, if needed
         */
        dc.rwmap = rwmap;
-#ifdef ENABLE_REWRITE
        dc.conn = op->o_conn;
        dc.rs = NULL; 
-#else /* ! ENABLE_REWRITE */
-       dc.tofrom = 0;
-       dc.normalized = 0;
-#endif /* ! ENABLE_REWRITE */
 
        /* FIXME: the entries are in the remote mapping form;
         * so we need to select those attributes we are willing
@@ -1095,7 +1011,7 @@ rwm_attrs( Operation *op, SlapReply *rs, Attribute** a_first, int stripEntryDN )
        for ( ap = a_first; *ap; ) {
                struct ldapmapping      *mapping = NULL;
                int                     drop_missing;
-               int                     last;
+               int                     last = -1;
                Attribute               *a;
 
                if ( SLAP_OPATTRS( rs->sr_attr_flags ) && is_at_operational( (*ap)->a_desc->ad_type ) )
@@ -1116,9 +1032,51 @@ rwm_attrs( Operation *op, SlapReply *rs, Attribute** a_first, int stripEntryDN )
                        {
                                goto cleanup_attr;
                        }
-
                        if ( mapping != NULL ) {
+                               assert( mapping->m_dst_ad != NULL );
+
+                               /* try to normalize mapped Attributes if the original 
+                                * AttributeType was not normalized */
+                               if ((rwmap->rwm_flags & RWM_F_NORMALIZE_MAPPED_ATTRS) && 
+                                       (!(*ap)->a_desc->ad_type->sat_equality || 
+                                       !(*ap)->a_desc->ad_type->sat_equality->smr_normalize) &&
+                                       mapping->m_dst_ad->ad_type->sat_equality &&
+                                       mapping->m_dst_ad->ad_type->sat_equality->smr_normalize )
+                               {
+                                       int i = 0;
+                                       for ( last = 0; !BER_BVISNULL( &(*ap)->a_vals[last] ); last++ )
+                                               /* just count */ ;
+
+                                       if ( last )
+                                       {
+                                               (*ap)->a_nvals = ch_malloc( (last+1) * sizeof(struct berval) );
+
+                                               for ( i = 0; !BER_BVISNULL( &(*ap)->a_vals[i]); i++ ) {
+                                                       int             rc;
+                                                       /*
+                                                        * check that each value is valid per syntax
+                                                        * and pretty if appropriate
+                                                        */
+                                                       rc = mapping->m_dst_ad->ad_type->sat_equality->smr_normalize(
+                                                               SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
+                                                               mapping->m_dst_ad->ad_type->sat_syntax,
+                                                               mapping->m_dst_ad->ad_type->sat_equality,
+                                                               &(*ap)->a_vals[i], &(*ap)->a_nvals[i],
+                                                               NULL );
+
+                                                       if ( rc != LDAP_SUCCESS ) {
+                                                               BER_BVZERO( &(*ap)->a_nvals[i] );
+                                                       }
+                                               }
+                                               BER_BVZERO( &(*ap)->a_nvals[i] );
+                                       }
+                               }
+
+                               /* rewrite the attribute description */
                                (*ap)->a_desc = mapping->m_dst_ad;
+
+                               /* will need to check for duplicate attrs */
+                               check_duplicate_attrs++;
                        }
                }
 
@@ -1136,8 +1094,10 @@ rwm_attrs( Operation *op, SlapReply *rs, Attribute** a_first, int stripEntryDN )
                        goto next_attr;
                }
 
-               for ( last = 0; !BER_BVISNULL( &(*ap)->a_vals[last] ); last++ )
-                       /* just count */ ;
+               if ( last == -1 ) { /* not yet counted */ 
+                       for ( last = 0; !BER_BVISNULL( &(*ap)->a_vals[last] ); last++ )
+                               /* just count */ ;
+               }
 
                if ( last == 0 ) {
                        /* empty? leave it in place because of attrsonly and vlv */
@@ -1155,6 +1115,7 @@ rwm_attrs( Operation *op, SlapReply *rs, Attribute** a_first, int stripEntryDN )
 
                                rwm_map( &rwmap->rwm_oc, &bv[0], &mapped, RWM_REMAP );
                                if ( BER_BVISNULL( &mapped ) || BER_BVISEMPTY( &mapped ) ) {
+remove_oc:;
                                        ch_free( bv[0].bv_val );
                                        BER_BVZERO( &bv[0] );
                                        if ( &(*ap)->a_vals[last] > &bv[0] ) {
@@ -1165,12 +1126,32 @@ rwm_attrs( Operation *op, SlapReply *rs, Attribute** a_first, int stripEntryDN )
                                        bv--;
 
                                } else if ( mapped.bv_val != bv[0].bv_val ) {
+                                       int     i;
+
+                                       for ( i = 0; !BER_BVISNULL( &(*ap)->a_vals[ i ] ); i++ ) {
+                                               if ( &(*ap)->a_vals[ i ] == bv ) {
+                                                       continue;
+                                               }
+
+                                               if ( ber_bvstrcasecmp( &mapped, &(*ap)->a_vals[ i ] ) == 0 ) {
+                                                       break;
+                                               }
+                                       }
+
+                                       if ( !BER_BVISNULL( &(*ap)->a_vals[ i ] ) ) {
+                                               goto remove_oc;
+                                       }
+
                                        /*
                                         * FIXME: after LBER_FREEing
                                         * the value is replaced by
                                         * ch_alloc'ed memory
                                         */
                                        ber_bvreplace( &bv[0], &mapped );
+
+                                       /* FIXME: will need to check
+                                        * if the structuralObjectClass
+                                        * changed */
                                }
                        }
 
@@ -1189,29 +1170,20 @@ rwm_attrs( Operation *op, SlapReply *rs, Attribute** a_first, int stripEntryDN )
                } else if ( (*ap)->a_desc->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName
                                || ( mapping != NULL && mapping->m_src_ad->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName ) )
                {
-#ifdef ENABLE_REWRITE
                        dc.ctx = "searchAttrDN";
-#endif /* ENABLE_REWRITE */
                        rc = rwm_dnattr_result_rewrite( &dc, (*ap)->a_vals );
                        if ( rc != LDAP_SUCCESS ) {
                                goto cleanup_attr;
                        }
 
                } else if ( (*ap)->a_desc == slap_schema.si_ad_ref ) {
-#ifdef ENABLE_REWRITE
                        dc.ctx = "searchAttrDN";
-#endif /* ENABLE_REWRITE */
                        rc = rwm_referral_result_rewrite( &dc, (*ap)->a_vals );
                        if ( rc != LDAP_SUCCESS ) {
                                goto cleanup_attr;
                        }
                }
 
-               if ( mapping != NULL ) {
-                       /* rewrite the attribute description */
-                       assert( mapping->m_dst_ad != NULL );
-                       (*ap)->a_desc = mapping->m_dst_ad;
-               }
 
 next_attr:;
                ap = &(*ap)->a_next;
@@ -1224,6 +1196,45 @@ cleanup_attr:;
                attr_free( a );
        }
 
+       /* only check if some mapping occurred */
+       if ( check_duplicate_attrs ) {
+               for ( ap = a_first; *ap != NULL; ap = &(*ap)->a_next ) {
+                       Attribute       **tap;
+
+                       for ( tap = &(*ap)->a_next; *tap != NULL; ) {
+                               if ( (*tap)->a_desc == (*ap)->a_desc ) {
+                                       Entry           e = { 0 };
+                                       Modification    mod = { 0 };
+                                       const char      *text = NULL;
+                                       char            textbuf[ SLAP_TEXT_BUFLEN ];
+                                       Attribute       *next = (*tap)->a_next;
+
+                                       BER_BVSTR( &e.e_name, "" );
+                                       BER_BVSTR( &e.e_nname, "" );
+                                       e.e_attrs = *ap;
+                                       mod.sm_op = LDAP_MOD_ADD;
+                                       mod.sm_desc = (*ap)->a_desc;
+                                       mod.sm_type = mod.sm_desc->ad_cname;
+                                       mod.sm_values = (*tap)->a_vals;
+                                       mod.sm_nvalues = (*tap)->a_nvals;
+
+                                       (void)modify_add_values( &e, &mod,
+                                               /* permissive */ 1,
+                                               &text, textbuf, sizeof( textbuf ) );
+
+                                       /* should not insert new attrs! */
+                                       assert( e.e_attrs == *ap );
+
+                                       attr_free( *tap );
+                                       *tap = next;
+
+                               } else {
+                                       tap = &(*tap)->a_next;
+                               }
+                       }
+               }
+       }
+
        return 0;
 }
 
@@ -1247,14 +1258,9 @@ rwm_send_entry( Operation *op, SlapReply *rs )
         * Rewrite the dn of the result, if needed
         */
        dc.rwmap = rwmap;
-#ifdef ENABLE_REWRITE
        dc.conn = op->o_conn;
        dc.rs = NULL; 
        dc.ctx = "searchEntryDN";
-#else /* ! ENABLE_REWRITE */
-       dc.tofrom = 0;
-       dc.normalized = 0;
-#endif /* ! ENABLE_REWRITE */
 
        e = rs->sr_entry;
        flags = rs->sr_flags;
@@ -1361,12 +1367,7 @@ rwm_chk_referrals( Operation *op, SlapReply *rs )
        slap_overinst           *on = (slap_overinst *) op->o_bd->bd_info;
        int                     rc;
 
-#ifdef ENABLE_REWRITE
        rc = rwm_op_dn_massage( op, rs, "referralCheckDN" );
-#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, "referralCheckDN massage error" );
@@ -1385,7 +1386,6 @@ rwm_rw_config(
        int             argc,
        char            **argv )
 {
-#ifdef ENABLE_REWRITE
        slap_overinst           *on = (slap_overinst *) be->bd_info;
        struct ldaprwmap        *rwmap = 
                        (struct ldaprwmap *)on->on_bi.bi_private;
@@ -1393,11 +1393,6 @@ rwm_rw_config(
        return rewrite_parse( rwmap->rwm_rw,
                                fname, lineno, argc, argv );
 
-#else /* !ENABLE_REWRITE */
-       fprintf( stderr, "%s: line %d: rewrite capabilities "
-                       "are not enabled\n", fname, lineno );
-#endif /* !ENABLE_REWRITE */
-               
        return 0;
 }
 
@@ -1415,9 +1410,7 @@ rwm_suffixmassage_config(
 
        struct berval           bvnc, nvnc, pvnc, brnc, nrnc, prnc;
        int                     massaged;
-#ifdef ENABLE_REWRITE
        int                     rc;
-#endif /* ENABLE_REWRITE */
                
        /*
         * syntax:
@@ -1469,7 +1462,6 @@ rwm_suffixmassage_config(
                return 1;
        }
 
-#ifdef ENABLE_REWRITE
        /*
         * The suffix massaging is emulated 
         * by means of the rewrite capabilities
@@ -1481,17 +1473,7 @@ rwm_suffixmassage_config(
        free( nrnc.bv_val );
        free( prnc.bv_val );
 
-       return( rc );
-
-#else /* !ENABLE_REWRITE */
-       ber_bvarray_add( &rwmap->rwm_suffix_massage, &pvnc );
-       ber_bvarray_add( &rwmap->rwm_suffix_massage, &nvnc );
-               
-       ber_bvarray_add( &rwmap->rwm_suffix_massage, &prnc );
-       ber_bvarray_add( &rwmap->rwm_suffix_massage, &nrnc );
-#endif /* !ENABLE_REWRITE */
-
-       return 0;
+       return rc;
 }
 
 static int
@@ -1541,14 +1523,9 @@ rwm_response( Operation *op, SlapReply *rs )
                         * Rewrite the dn of the referrals, if needed
                         */
                        dc.rwmap = rwmap;
-#ifdef ENABLE_REWRITE
                        dc.conn = op->o_conn;
                        dc.rs = NULL; 
                        dc.ctx = "referralDN";
-#else /* ! ENABLE_REWRITE */
-                       dc.tofrom = 0;
-                       dc.normalized = 0;
-#endif /* ! ENABLE_REWRITE */
                        rc = rwm_referral_result_rewrite( &dc, rs->sr_ref );
                        if ( rc != LDAP_SUCCESS ) {
                                rc = 1;
@@ -1604,7 +1581,7 @@ rwm_db_config(
                }
 
                if ( strcasecmp( argv[ 1 ], "no" ) == 0 ) {
-                       rwmap->rwm_flags &= ~(RWM_F_SUPPORT_T_F|RWM_F_SUPPORT_T_F_DISCOVER);
+                       rwmap->rwm_flags &= ~(RWM_F_SUPPORT_T_F_MASK2);
 
                } else if ( strcasecmp( argv[ 1 ], "yes" ) == 0 ) {
                        rwmap->rwm_flags |= RWM_F_SUPPORT_T_F;
@@ -1626,6 +1603,20 @@ rwm_db_config(
                                fname, lineno, argv[ 1 ] );
                        return 1;
                }
+       } else if ( strcasecmp( argv[0], "normalize-mapped-attrs" ) ==  0 ) {
+               if ( argc !=2 ) { 
+                       fprintf( stderr,
+               "%s: line %d: \"normalize-mapped-attrs {no|yes}\" needs 1 argument.\n",
+                                       fname, lineno );
+                       return( 1 );
+               }
+
+               if ( strcasecmp( argv[ 1 ], "no" ) == 0 ) {
+                       rwmap->rwm_flags &= ~(RWM_F_NORMALIZE_MAPPED_ATTRS);
+
+               } else if ( strcasecmp( argv[ 1 ], "yes" ) == 0 ) {
+                       rwmap->rwm_flags |= RWM_F_NORMALIZE_MAPPED_ATTRS;
+               }
 
        } else {
                rc = SLAP_CONF_UNKNOWN;
@@ -1638,20 +1629,357 @@ rwm_db_config(
        return rc;
 }
 
+/*
+ * dynamic configuration...
+ */
+
+enum {
+       /* rewrite */
+       RWM_CF_REWRITE = 1,
+       RWM_CF_SUFFIXMASSAGE,
+
+       /* map */
+       RWM_CF_MAP,
+       RWM_CF_T_F_SUPPORT,
+       RWM_CF_NORMALIZE_MAPPED,
+
+       RWM_CF_LAST
+};
+
+static slap_verbmasks t_f_mode[] = {
+       { BER_BVC( "yes" ),             RWM_F_SUPPORT_T_F },
+       { BER_BVC( "discover" ),        RWM_F_SUPPORT_T_F_DISCOVER },
+       { BER_BVC( "no" ),              RWM_F_NONE },
+       { BER_BVNULL,                   0 }
+};
+
+static ConfigDriver rwm_cf_gen;
+
+static ConfigTable rwmcfg[] = {
+       { "rwm-rewrite", "rewrite",
+               2, 0, STRLENOF("rwm-rewrite"),
+               ARG_MAGIC|ARG_QUOTE|RWM_CF_REWRITE, rwm_cf_gen,
+               "( OLcfgOvAt:16.1 NAME 'olcRwmRewrite' "
+                       "DESC 'Rewrites strings' "
+                       "EQUALITY caseIgnoreMatch "
+                       "SYNTAX OMsDirectoryString "
+                       "X-ORDERED 'VALUES' )",
+               NULL, NULL },
+
+       { "rwm-suffixmassage", "[virtual]> <real",
+               2, 3, 0, ARG_MAGIC|RWM_CF_SUFFIXMASSAGE, rwm_cf_gen,
+               NULL, NULL, NULL },
+               
+       { "rwm-t-f-support", "true|false|discover",
+               2, 2, 0, ARG_MAGIC|RWM_CF_T_F_SUPPORT, rwm_cf_gen,
+               "( OLcfgOvAt:16.2 NAME 'olcRwmTFSupport' "
+                       "DESC 'Absolute filters support' "
+                       "SYNTAX OMsDirectoryString "
+                       "SINGLE-VALUE )",
+               NULL, NULL },
+
+       { "rwm-map", "{objectClass|attribute}",
+               2, 4, 0, ARG_MAGIC|RWM_CF_MAP, rwm_cf_gen,
+               "( OLcfgOvAt:16.3 NAME 'olcRwmMap' "
+                       "DESC 'maps attributes/objectClasses' "
+                       "SYNTAX OMsDirectoryString "
+                       "X-ORDERED 'VALUES' )",
+               NULL, NULL },
+
+       { "rwm-normalize-mapped-attrs", "true|false",
+               2, 2, 0, ARG_MAGIC|ARG_ON_OFF|RWM_CF_NORMALIZE_MAPPED, rwm_cf_gen,
+               "( OLcfgOvAt:16.4 NAME 'olcRwmNormalizeMapped' "
+                       "DESC 'Normalize mapped attributes/objectClasses' "
+                       "SYNTAX OMsBoolean "
+                       "SINGLE-VALUE )",
+               NULL, NULL },
+
+       { NULL, NULL, 0, 0, 0, ARG_IGNORED }
+};
+
+static ConfigOCs rwmocs[] = {
+       { "( OLcfgOvOc:16.1 "
+               "NAME 'olcRwmConfig' "
+               "DESC 'Rewrite/remap configuration' "
+               "SUP olcOverlayConfig "
+               "MAY ( "
+                       "olcRwmRewrite $ "
+                       "olcRwmTFSupport $ "
+                       "olcRwmMap $ "
+                       "olcRwmNormalizeMapped "
+                       ") )",
+               Cft_Overlay, rwmcfg, NULL, NULL },
+       { NULL, 0, NULL }
+};
+
+static void
+slap_rewrite_unparse( BerVarray in, BerVarray *out )
+{
+       int             i;
+       BerVarray       bva = NULL;
+       char            ibuf[32], *ptr;
+       struct berval   idx;
+
+       assert( in != NULL );
+
+       for ( i = 0; !BER_BVISNULL( &in[i] ); i++ )
+               /* count'em */ ;
+
+       if ( i == 0 ) {
+               return;
+       }
+
+       idx.bv_val = ibuf;
+
+       bva = ch_malloc( ( i + 1 ) * sizeof(struct berval) );
+       BER_BVZERO( &bva[ 0 ] );
+
+       for ( i = 0; !BER_BVISNULL( &in[i] ); i++ ) {
+               idx.bv_len = snprintf( idx.bv_val, sizeof( ibuf ), "{%d}", i );
+               if ( idx.bv_len >= sizeof( ibuf ) ) {
+                       ber_bvarray_free( bva );
+                       return;
+               }
+
+               bva[i].bv_len = idx.bv_len + in[i].bv_len;
+               bva[i].bv_val = ch_malloc( bva[i].bv_len + 1 );
+               ptr = lutil_strcopy( bva[i].bv_val, ibuf );
+               ptr = lutil_strcopy( ptr, in[i].bv_val );
+               *ptr = '\0';
+               BER_BVZERO( &bva[ i + 1 ] );
+       }
+
+       *out = bva;
+}
+
+static int
+rwm_cf_gen( ConfigArgs *c )
+{
+       slap_overinst           *on = (slap_overinst *)c->bi;
+       struct ldaprwmap        *rwmap = 
+                       (struct ldaprwmap *)on->on_bi.bi_private;
+
+       BackendDB               db;
+       char                    *argv0;
+       int                     rc = 0;
+
+       db = *c->be;
+       db.bd_info = c->bi;
+
+       if ( c->op == SLAP_CONFIG_EMIT ) {
+               struct berval   bv = BER_BVNULL;
+
+               switch ( c->type ) {
+               case RWM_CF_REWRITE:
+                       if ( rwmap->rwm_bva_rewrite == NULL ) {
+                               rc = 1;
+
+                       } else {
+                               slap_rewrite_unparse( rwmap->rwm_bva_rewrite, &c->rvalue_vals );
+                               if ( !c->rvalue_vals ) {
+                                       rc = 1;
+                               }
+                       }
+                       break;
+
+               case RWM_CF_T_F_SUPPORT:
+                       enum_to_verb( t_f_mode, (rwmap->rwm_flags & RWM_F_SUPPORT_T_F_MASK2), &bv );
+                       if ( BER_BVISNULL( &bv ) ) {
+                               /* there's something wrong... */
+                               assert( 0 );
+                               rc = 1;
+
+                       } else {
+                               value_add_one( &c->rvalue_vals, &bv );
+                       }
+                       break;
+
+               case RWM_CF_MAP:
+                       if ( rwmap->rwm_bva_map == NULL ) {
+                               rc = 1;
+
+                       } else {
+                               value_add( &c->rvalue_vals, rwmap->rwm_bva_map );
+                       }
+                       break;
+
+               case RWM_CF_NORMALIZE_MAPPED:
+                       c->value_int = ( rwmap->rwm_flags & RWM_F_NORMALIZE_MAPPED_ATTRS );
+                       break;
+
+               default:
+                       assert( 0 );
+                       rc = 1;
+               }
+
+               return rc;
+
+       } else if ( c->op == LDAP_MOD_DELETE ) {
+               switch ( c->type ) {
+               case RWM_CF_REWRITE:
+                       if ( c->valx >= 0 ) {
+                               /* single modification is not allowed */
+                               rc = 1;
+
+                       } else if ( rwmap->rwm_rw != NULL ) {
+                               rewrite_info_delete( &rwmap->rwm_rw );
+                               assert( rwmap->rwm_rw == NULL );
+
+                               ber_bvarray_free( rwmap->rwm_bva_rewrite );
+                               rwmap->rwm_bva_rewrite = NULL;
+                       }
+                       break;
+
+               case RWM_CF_T_F_SUPPORT:
+                       rwmap->rwm_flags &= ~RWM_F_SUPPORT_T_F_MASK2;
+                       break;
+
+               case RWM_CF_MAP:
+                       if ( c->valx >= 0 ) {
+                               /* single modification is not allowed */
+                               rc = 1;
+
+                       } else {
+                               avl_free( rwmap->rwm_oc.remap, rwm_mapping_dst_free );
+                               avl_free( rwmap->rwm_oc.map, rwm_mapping_free );
+                               avl_free( rwmap->rwm_at.remap, rwm_mapping_dst_free );
+                               avl_free( rwmap->rwm_at.map, rwm_mapping_free );
+
+                               rwmap->rwm_oc.remap = NULL;
+                               rwmap->rwm_oc.map = NULL;
+                               rwmap->rwm_at.remap = NULL;
+                               rwmap->rwm_at.map = NULL;
+
+                               ber_bvarray_free( rwmap->rwm_bva_map );
+                               rwmap->rwm_bva_map = NULL;
+                       }
+                       break;
+
+               case RWM_CF_NORMALIZE_MAPPED:
+                       rwmap->rwm_flags &= ~RWM_F_NORMALIZE_MAPPED_ATTRS;
+                       break;
+
+               default:
+                       return 1;
+               }
+               return rc;
+       }
+
+       switch ( c->type ) {
+       case RWM_CF_REWRITE:
+               argv0 = c->argv[ 0 ];
+               c->argv[ 0 ] += STRLENOF( "rwm-" );
+               rc = rwm_rw_config( &db, c->fname, c->lineno, c->argc, c->argv );
+               c->argv[ 0 ] = argv0;
+               if ( rc ) {
+                       return 1;
+
+               } else {
+                       char            *line;
+                       struct berval   bv;
+
+                       line = ldap_charray2str( c->argv, "\" \"" );
+                       if ( line != NULL ) {
+                               int     len = strlen( c->argv[ 0 ] );
+
+                               ber_str2bv( line, 0, 0, &bv );
+                               AC_MEMCPY( &bv.bv_val[ len ], &bv.bv_val[ len + 1 ],
+                                       bv.bv_len - ( len + 1 ) );
+                               bv.bv_val[ bv.bv_len - 1 ] = '"';
+                               ber_bvarray_add( &rwmap->rwm_bva_rewrite, &bv );
+                       }
+               }
+               break;
+
+       case RWM_CF_SUFFIXMASSAGE:
+               argv0 = c->argv[ 0 ];
+               c->argv[ 0 ] += STRLENOF( "rwm-" );
+               rc = rwm_suffixmassage_config( &db, c->fname, c->lineno, c->argc, c->argv );
+               c->argv[ 0 ] = argv0;
+               if ( rc ) {
+                       return 1;
+
+               } else {
+                       char            *line;
+                       struct berval   bv;
+
+                       /* FIXME: not optimal; in fact, this keeps track
+                        * of the fact that a set of rules was added
+                        * using the rwm-suffixmassage shortcut, but the
+                        * rules are not clarified */
+
+                       line = ldap_charray2str( c->argv, "\" \"" );
+                       if ( line != NULL ) {
+                               int     len = strlen( c->argv[ 0 ] );
+
+                               ber_str2bv( line, 0, 0, &bv );
+                               AC_MEMCPY( &bv.bv_val[ len ], &bv.bv_val[ len + 1 ],
+                                       bv.bv_len - ( len + 1 ) );
+                               bv.bv_val[ bv.bv_len - 1 ] = '"';
+                               ber_bvarray_add( &rwmap->rwm_bva_rewrite, &bv );
+                       }
+               }
+               break;
+
+       case RWM_CF_T_F_SUPPORT:
+               rc = verb_to_mask( c->argv[ 1 ], t_f_mode );
+               if ( BER_BVISNULL( &t_f_mode[ rc ].word ) ) {
+                       return 1;
+               }
+
+               rwmap->rwm_flags &= ~RWM_F_SUPPORT_T_F_MASK2;
+               rwmap->rwm_flags |= t_f_mode[ rc ].mask;
+               rc = 0;
+               break;
+
+       case RWM_CF_MAP:
+               argv0 = c->argv[ 0 ];
+               c->argv[ 0 ] += STRLENOF( "rwm-" );
+               rc = rwm_m_config( &db, c->fname, c->lineno, c->argc, c->argv );
+               c->argv[ 0 ] = argv0;
+               if ( rc ) {
+                       return 1;
+
+               } else {
+                       char            *line;
+                       struct berval   bv;
+
+                       line = ldap_charray2str( &c->argv[ 1 ], " " );
+                       if ( line != NULL ) {
+                               ber_str2bv( line, 0, 0, &bv );
+                               ber_bvarray_add( &rwmap->rwm_bva_map, &bv );
+                       }
+               }
+               break;
+
+       case RWM_CF_NORMALIZE_MAPPED:
+               if ( c->value_int ) {
+                       rwmap->rwm_flags |= RWM_F_NORMALIZE_MAPPED_ATTRS;
+               } else {
+                       rwmap->rwm_flags &= ~RWM_F_NORMALIZE_MAPPED_ATTRS;
+               }
+               break;
+
+       default:
+               assert( 0 );
+               return 1;
+       }
+
+       return rc;
+}
+
 static int
 rwm_db_init(
-       BackendDB       *be )
+       BackendDB       *be,
+       ConfigReply     *cr )
 {
        slap_overinst           *on = (slap_overinst *) be->bd_info;
        struct ldaprwmap        *rwmap;
-#ifdef ENABLE_REWRITE
        char                    *rargv[ 3 ];
-#endif /* ENABLE_REWRITE */
        int                     rc = 0;
 
        rwmap = (struct ldaprwmap *)ch_calloc( 1, sizeof( struct ldaprwmap ) );
 
-#ifdef ENABLE_REWRITE
        rwmap->rwm_rw = rewrite_info_init( REWRITE_MODE_USE_DEFAULT );
        if ( rwmap->rwm_rw == NULL ) {
                rc = -1;
@@ -1669,13 +1997,12 @@ rwm_db_init(
        rargv[ 1 ] = "default";
        rargv[ 2 ] = NULL;
        rewrite_parse( rwmap->rwm_rw, "<suffix massage>", 2, 2, rargv );
-#endif /* ENABLE_REWRITE */
 
 error_return:;
        on->on_bi.bi_private = (void *)rwmap;
 
        if ( rc ) {
-               (void)rwm_db_destroy( be );
+               (void)rwm_db_destroy( be, NULL );
        }
 
        return rc;
@@ -1683,7 +2010,8 @@ error_return:;
 
 static int
 rwm_db_destroy(
-       BackendDB       *be )
+       BackendDB       *be,
+       ConfigReply     *cr )
 {
        slap_overinst   *on = (slap_overinst *) be->bd_info;
        int             rc = 0;
@@ -1692,20 +2020,16 @@ rwm_db_destroy(
                struct ldaprwmap        *rwmap = 
                        (struct ldaprwmap *)on->on_bi.bi_private;
 
-#ifdef ENABLE_REWRITE
                if ( rwmap->rwm_rw ) {
                        rewrite_info_delete( &rwmap->rwm_rw );
+                       ber_bvarray_free( rwmap->rwm_bva_rewrite );
                }
-#else /* !ENABLE_REWRITE */
-               if ( rwmap->rwm_suffix_massage ) {
-                       ber_bvarray_free( rwmap->rwm_suffix_massage );
-               }
-#endif /* !ENABLE_REWRITE */
 
                avl_free( rwmap->rwm_oc.remap, rwm_mapping_dst_free );
                avl_free( rwmap->rwm_oc.map, rwm_mapping_free );
                avl_free( rwmap->rwm_at.remap, rwm_mapping_dst_free );
                avl_free( rwmap->rwm_at.map, rwm_mapping_free );
+               ber_bvarray_free( rwmap->rwm_bva_map );
 
                ch_free( rwmap );
        }
@@ -1721,6 +2045,11 @@ static
 int
 rwm_initialize( void )
 {
+       int             rc;
+
+       /* Make sure we don't exceed the bits reserved for userland */
+       config_check_userland( RWM_CF_LAST );
+
        memset( &rwm, 0, sizeof( slap_overinst ) );
 
        rwm.on_bi.bi_type = "rwm";
@@ -1745,13 +2074,18 @@ rwm_initialize( void )
        rwm.on_bi.bi_operational = rwm_operational;
        rwm.on_bi.bi_chk_referrals = 0 /* rwm_chk_referrals */ ;
 
-#ifdef ENABLE_REWRITE
        rwm.on_bi.bi_connection_init = rwm_conn_init;
        rwm.on_bi.bi_connection_destroy = rwm_conn_destroy;
-#endif /* ENABLE_REWRITE */
 
        rwm.on_response = rwm_response;
 
+       rwm.on_bi.bi_cf_ocs = rwmocs;
+
+       rc = config_register_schema( rwmcfg, rwmocs );
+       if ( rc ) {
+               return rc;
+       }
+
        return overlay_register( &rwm );
 }
 
index bc349d9c4092477fde5faee7b6522033f12d1121..f2bc816a0947619c5e038bfa4e42a9175e867708 100644 (file)
 #ifndef RWM_H
 #define RWM_H
 
+#ifndef ENABLE_REWRITE
+#error "librewrite must be enabled!"
+#endif /* ENABLE_REWRITE */
+
 /* String rewrite library */
-#ifdef ENABLE_REWRITE
 #include "rewrite.h"
-#endif /* ENABLE_REWRITE */
 
 LDAP_BEGIN_DECL
 
@@ -67,23 +69,22 @@ struct ldaprwmap {
        /*
         * DN rewriting
         */
-#ifdef ENABLE_REWRITE
        struct rewrite_info *rwm_rw;
-#else /* !ENABLE_REWRITE */
-       /* some time the suffix massaging without librewrite
-        * will be disabled */
-       BerVarray rwm_suffix_massage;
-#endif /* !ENABLE_REWRITE */
+       BerVarray rwm_bva_rewrite;
 
        /*
         * Attribute/objectClass mapping
         */
        struct ldapmap rwm_oc;
        struct ldapmap rwm_at;
-
-#define        RWM_F_NONE                      0x0000U
-#define        RWM_F_SUPPORT_T_F               0x4000U
-#define        RWM_F_SUPPORT_T_F_DISCOVER      0x8000U
+       BerVarray rwm_bva_map;
+
+#define        RWM_F_NONE                      (0x0000U)
+#define        RWM_F_NORMALIZE_MAPPED_ATTRS    (0x0001U)
+#define        RWM_F_SUPPORT_T_F               (0x4000U)
+#define        RWM_F_SUPPORT_T_F_DISCOVER      (0x8000U)
+#define        RWM_F_SUPPORT_T_F_MASK          (RWM_F_SUPPORT_T_F)
+#define        RWM_F_SUPPORT_T_F_MASK2         (RWM_F_SUPPORT_T_F|RWM_F_SUPPORT_T_F_DISCOVER)
        unsigned        rwm_flags;
 };
 
@@ -91,14 +92,9 @@ struct ldaprwmap {
 typedef struct dncookie {
        struct ldaprwmap *rwmap;
 
-#ifdef ENABLE_REWRITE
        Connection *conn;
        char *ctx;
        SlapReply *rs;
-#else /* !ENABLE_REWRITE */
-       int normalized;
-       int tofrom;
-#endif /* !ENABLE_REWRITE */
 } dncookie;
 
 int rwm_dn_massage( dncookie *dc, struct berval *in, struct berval *dn );
@@ -158,18 +154,22 @@ rwm_filter_map_rewrite(
                struct berval           *fstr );
 
 /* suffix massaging by means of librewrite */
-#ifdef ENABLE_REWRITE
-extern int rwm_suffix_massage_config( struct rewrite_info *info,
-               struct berval *pvnc, struct berval *nvnc,
-               struct berval *prnc, struct berval *nrnc);
-#endif /* ENABLE_REWRITE */
-extern int rwm_dnattr_rewrite(
+extern int
+rwm_suffix_massage_config(
+       struct rewrite_info     *info,
+       struct berval           *pvnc,
+       struct berval           *nvnc,
+       struct berval           *prnc,
+       struct berval           *nrnc);
+extern int
+rwm_dnattr_rewrite(
        Operation               *op,
        SlapReply               *rs,
        void                    *cookie,
        BerVarray               a_vals,
        BerVarray               *pa_nvals );
-extern int rwm_referral_rewrite(
+extern int
+rwm_referral_rewrite(
        Operation               *op,
        SlapReply               *rs,
        void                    *cookie,
index 81e0b3b594e45a2514c57a74f59c4bde832b0866..a0856347751f1a678a659c3c269d45bba64494cb 100644 (file)
@@ -149,13 +149,6 @@ rwm_map_config(
                                        fname, lineno, dst );
                                goto error_return;
                        }
-
-#if 0
-                       mapping[0].m_dst_oc = ch_malloc( sizeof( ObjectClass ) );
-                       memset( mapping[0].m_dst_oc, 0, sizeof( ObjectClass ) );
-                       mapping[0].m_dst_oc->soc_cname = mapping[0].m_dst;
-                       mapping[0].m_flags |= RWMMAP_F_FREE_DST;
-#endif
                }
                mapping[1].m_src_oc = mapping[0].m_dst_oc;
 
@@ -247,7 +240,6 @@ error_return:;
        return 1;
 }
 
-#ifdef ENABLE_REWRITE
 static char *
 rwm_suffix_massage_regexize( const char *s )
 {
@@ -413,6 +405,5 @@ rwm_suffix_massage_config(
 
        return 0;
 }
-#endif /* ENABLE_REWRITE */
 
 #endif /* SLAPD_OVER_RWM */
index 9348c70f119ad1cfa80e1fc44af7b6ebdcc36e53..500993b3fcbfa73599fa098a78d169c823c88579 100644 (file)
@@ -142,7 +142,6 @@ rwm_dn_massage_pretty_normalize(
        return rc;
 }
 
-#ifdef ENABLE_REWRITE
 /*
  * massages "in" into "dn"
  * 
@@ -209,111 +208,4 @@ rwm_dn_massage(
        return rc;
 }
 
-#else /* ! ENABLE_REWRITE */
-/*
- * rwm_dn_massage
- * 
- * Aliases the suffix; based on suffix_alias (servers/slapd/suffixalias.c).
- */
-int
-rwm_dn_massage(
-       dncookie *dc,
-       struct berval *in,
-       struct berval *dn
-)
-{
-       int             i, src, dst;
-       struct berval   tmpin;
-
-       assert( dc != NULL );
-       assert( in != NULL );
-       assert( dn != NULL );
-
-       BER_BVZERO( dn );
-
-       if ( BER_BVISNULL( in ) ) {
-               return LDAP_SUCCESS;
-       }
-
-       if ( dc->rwmap == NULL || dc->rwmap->rwm_suffix_massage == NULL ) {
-               *dn = *in;
-               return LDAP_SUCCESS;
-       }
-
-       if ( dc->tofrom ) {
-               src = 0 + dc->normalized;
-               dst = 2 + dc->normalized;
-
-               tmpin = *in;
-
-       } else {
-               int     rc;
-
-               src = 2 + dc->normalized;
-               dst = 0 + dc->normalized;
-
-               /* DN from remote server may be in arbitrary form.
-                * Pretty it so we can parse reliably.
-                */
-               if ( dc->normalized ) {
-                       rc = dnNormalize( 0, NULL, NULL, in, &tmpin, NULL );
-
-               } else {
-                       rc = dnPretty( NULL, in, &tmpin, NULL );
-               }
-
-               if ( rc != LDAP_SUCCESS ) {
-                       return rc;
-               }
-       }
-
-       for ( i = 0;
-                       !BER_BVISNULL( &dc->rwmap->rwm_suffix_massage[i] );
-                       i += 4 )
-       {
-               int aliasLength = dc->rwmap->rwm_suffix_massage[i+src].bv_len;
-               int diff = tmpin.bv_len - aliasLength;
-
-               if ( diff < 0 ) {
-                       /* alias is longer than dn */
-                       continue;
-
-               } else if ( diff > 0 && ( !DN_SEPARATOR(tmpin.bv_val[diff-1])))
-               {
-                       /* FIXME: DN_SEPARATOR() is intended to work
-                        * on a normalized/pretty DN, so that ';'
-                        * is never used as a DN separator */
-                       continue;
-                       /* At a DN Separator */
-               }
-
-               if ( !strcmp( dc->rwmap->rwm_suffix_massage[i+src].bv_val,
-                                       &tmpin.bv_val[diff] ) )
-               {
-                       dn->bv_len = diff + dc->rwmap->rwm_suffix_massage[i+dst].bv_len;
-                       dn->bv_val = ch_malloc( dn->bv_len + 1 );
-                       strncpy( dn->bv_val, tmpin.bv_val, diff );
-                       strcpy( &dn->bv_val[diff], dc->rwmap->rwm_suffix_massage[i+dst].bv_val );
-                       Debug( LDAP_DEBUG_ARGS,
-                               "rwm_dn_massage:"
-                               " converted \"%s\" to \"%s\"\n",
-                               in->bv_val, dn->bv_val, 0 );
-
-                       break;
-               }
-       }
-
-       if ( tmpin.bv_val != in->bv_val ) {
-               ch_free( tmpin.bv_val );
-       }
-
-       /* Nothing matched, just return the original DN */
-       if ( BER_BVISNULL( dn ) ) {
-               *dn = *in;
-       }
-
-       return LDAP_SUCCESS;
-}
-#endif /* ! ENABLE_REWRITE */
-
 #endif /* SLAPD_OVER_RWM */
index c05032a36aa3cd18d30f1fd79c309c4c2834ec2e..f18d80d2716ee404bd653a8cb0967f81c2c2add3 100644 (file)
@@ -403,9 +403,7 @@ map_attr_value(
                        dncookie        fdc = *dc;
                        int             rc;
 
-#ifdef ENABLE_REWRITE
                        fdc.ctx = "searchFilterAttrDN";
-#endif /* ENABLE_REWRITE */
 
                        vtmp = *value;
                        rc = rwm_dn_massage_normalize( &fdc, value, &vtmp );
@@ -499,7 +497,7 @@ rwm_int_filter_map_rewrite(
                fstr->bv_val = ch_malloc( fstr->bv_len + 1 );
 
                snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s=%s)",
-                       atmp.bv_val, vtmp.bv_val );
+                       atmp.bv_val, vtmp.bv_len ? vtmp.bv_val : "" );
 
                ch_free( vtmp.bv_val );
                break;
@@ -516,7 +514,7 @@ rwm_int_filter_map_rewrite(
                fstr->bv_val = ch_malloc( fstr->bv_len + 1 );
 
                snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s>=%s)",
-                       atmp.bv_val, vtmp.bv_val );
+                       atmp.bv_val, vtmp.bv_len ? vtmp.bv_val : "" );
 
                ch_free( vtmp.bv_val );
                break;
@@ -533,7 +531,7 @@ rwm_int_filter_map_rewrite(
                fstr->bv_val = ch_malloc( fstr->bv_len + 1 );
 
                snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s<=%s)",
-                       atmp.bv_val, vtmp.bv_val );
+                       atmp.bv_val, vtmp.bv_len ? vtmp.bv_val : "" );
 
                ch_free( vtmp.bv_val );
                break;
@@ -550,7 +548,7 @@ rwm_int_filter_map_rewrite(
                fstr->bv_val = ch_malloc( fstr->bv_len + 1 );
 
                snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s~=%s)",
-                       atmp.bv_val, vtmp.bv_val );
+                       atmp.bv_val, vtmp.bv_len ? vtmp.bv_val : "" );
 
                ch_free( vtmp.bv_val );
                break;
@@ -581,7 +579,7 @@ rwm_int_filter_map_rewrite(
 
                        snprintf( &fstr->bv_val[len - 2], vtmp.bv_len + 3,
                                /* "(attr=" */ "%s*)",
-                               vtmp.bv_val );
+                               vtmp.bv_len ? vtmp.bv_val : "" );
 
                        ch_free( vtmp.bv_val );
                }
@@ -596,7 +594,7 @@ rwm_int_filter_map_rewrite(
 
                                snprintf( &fstr->bv_val[len - 1], vtmp.bv_len + 3,
                                        /* "(attr=[init]*[any*]" */ "%s*)",
-                                       vtmp.bv_val );
+                                       vtmp.bv_len ? vtmp.bv_val : "" );
                                ch_free( vtmp.bv_val );
                        }
                }
@@ -611,7 +609,7 @@ rwm_int_filter_map_rewrite(
 
                        snprintf( &fstr->bv_val[len - 1], vtmp.bv_len + 3,
                                /* "(attr=[init*][any*]" */ "%s)",
-                               vtmp.bv_val );
+                               vtmp.bv_len ? vtmp.bv_val : "" );
 
                        ch_free( vtmp.bv_val );
                }
@@ -657,7 +655,7 @@ rwm_int_filter_map_rewrite(
                        fstr->bv_val = ch_realloc( fstr->bv_val, fstr->bv_len + 1 );
 
                        snprintf( &fstr->bv_val[len-1], vtmp.bv_len + 2, 
-                               /*"("*/ "%s)", vtmp.bv_val );
+                               /*"("*/ "%s)", vtmp.bv_len ? vtmp.bv_val : "" );
 
                        ch_free( vtmp.bv_val );
                }
@@ -690,7 +688,7 @@ rwm_int_filter_map_rewrite(
                        f->f_mr_dnattrs ? ":dn" : "",
                        !BER_BVISEMPTY( &f->f_mr_rule_text ) ? ":" : "",
                        !BER_BVISEMPTY( &f->f_mr_rule_text ) ? f->f_mr_rule_text.bv_val : "",
-                       vtmp.bv_val );
+                       vtmp.bv_len ? vtmp.bv_val : "" );
                ch_free( vtmp.bv_val );
                break;
        }
@@ -751,7 +749,6 @@ rwm_filter_map_rewrite(
 
        rc = rwm_int_filter_map_rewrite( op, dc, f, fstr );
 
-#ifdef ENABLE_REWRITE
        if ( rc != 0 ) {
                return rc;
        }
@@ -768,7 +765,9 @@ rwm_filter_map_rewrite(
        case REWRITE_REGEXEC_OK:
                if ( !BER_BVISNULL( fstr ) ) {
                        fstr->bv_len = strlen( fstr->bv_val );
-                       ch_free( ftmp.bv_val );
+                       if ( fstr->bv_val != ftmp.bv_val ) {
+                               ch_free( ftmp.bv_val );
+                       }
 
                } else {
                        *fstr = ftmp;
@@ -796,7 +795,6 @@ rwm_filter_map_rewrite(
                rc = LDAP_OTHER;
                break;
        }
-#endif /* ENABLE_REWRITE */
 
        return rc;
 }
@@ -832,14 +830,9 @@ rwm_referral_rewrite(
         * Rewrite the dn if needed
         */
        dc.rwmap = rwmap;
-#ifdef ENABLE_REWRITE
        dc.conn = op->o_conn;
        dc.rs = rs;
        dc.ctx = (char *)cookie;
-#else /* ! ENABLE_REWRITE */
-       dc.tofrom = ((int *)cookie)[0];
-       dc.normalized = 0;
-#endif /* ! ENABLE_REWRITE */
 
        for ( last = 0; !BER_BVISNULL( &a_vals[last] ); last++ )
                ;
@@ -1005,14 +998,9 @@ rwm_dnattr_rewrite(
         * Rewrite the dn if needed
         */
        dc.rwmap = rwmap;
-#ifdef ENABLE_REWRITE
        dc.conn = op->o_conn;
        dc.rs = rs;
        dc.ctx = (char *)cookie;
-#else /* ! ENABLE_REWRITE */
-       dc.tofrom = ((int *)cookie)[0];
-       dc.normalized = 0;
-#endif /* ! ENABLE_REWRITE */
 
        for ( last = 0; !BER_BVISNULL( &in[last] ); last++ );
        last--;
index 278face56d26e3a7791e934017e4cc9778d8fbba..a871f546f158557d8231da2e23b0579d618123a4 100644 (file)
@@ -22,6 +22,7 @@
 #ifdef SLAPD_OVER_SEQMOD
 
 #include "slap.h"
+#include "config.h"
 
 /* This overlay serializes concurrent attempts to modify a single entry */
 
@@ -139,7 +140,8 @@ seqmod_op_extended(
 
 static int
 seqmod_db_open(
-       BackendDB *be
+       BackendDB *be,
+       ConfigReply *cr
 )
 {
        slap_overinst   *on = (slap_overinst *)be->bd_info;
@@ -155,7 +157,8 @@ seqmod_db_open(
 
 static int
 seqmod_db_close(
-       BackendDB *be
+       BackendDB *be,
+       ConfigReply *cr
 )
 {
        slap_overinst   *on = (slap_overinst *)be->bd_info;
index 2b4268813ae5ef7e1e735fce8fce1c65b7c22fcb..a817700622eedc180dfc723b2a0a089660e3000e 100644 (file)
@@ -659,6 +659,7 @@ again:
                } else {
                        cf.f_choice = LDAP_FILTER_LE;
                        fop.ors_limit = &fc_limits;
+                       memset( &fc_limits, 0, sizeof( fc_limits ));
                        fc_limits.lms_s_unchecked = 1;
                        fop.ors_filterstr.bv_len = sprintf( buf, "(entryCSN<=%s)",
                                cf.f_av_value.bv_val );
@@ -896,11 +897,11 @@ syncprov_qtask( void *ctx, void *arg )
        BackendDB be;
        int rc;
 
-       op = (Operation *) &opbuf;
+       op = &opbuf.ob_op;
        *op = *so->s_op;
-       op->o_hdr = (Opheader *)(op+1);
-       op->o_controls = (void **)(op->o_hdr+1);
-       memset( op->o_controls, 0, SLAP_MAX_CIDS * sizeof(void *));
+       op->o_hdr = &opbuf.ob_hdr;
+       op->o_controls = opbuf.ob_controls;
+       memset( op->o_controls, 0, sizeof(opbuf.ob_controls) );
 
        *op->o_hdr = *so->s_op->o_hdr;
 
@@ -1030,7 +1031,7 @@ syncprov_drop_psearch( syncops *so, int lock )
                        ldap_pvt_thread_mutex_lock( &so->s_op->o_conn->c_mutex );
                so->s_op->o_conn->c_n_ops_executing--;
                so->s_op->o_conn->c_n_ops_completed++;
-               LDAP_STAILQ_REMOVE( &so->s_op->o_conn->c_ops, so->s_op, slap_op,
+               LDAP_STAILQ_REMOVE( &so->s_op->o_conn->c_ops, so->s_op, Operation,
                        o_next );
                if ( lock )
                        ldap_pvt_thread_mutex_unlock( &so->s_op->o_conn->c_mutex );
@@ -1284,7 +1285,7 @@ syncprov_op_cleanup( Operation *op, SlapReply *rs )
 static void
 syncprov_checkpoint( Operation *op, SlapReply *rs, slap_overinst *on )
 {
-    syncprov_info_t *si = (syncprov_info_t *)on->on_bi.bi_private;
+       syncprov_info_t *si = (syncprov_info_t *)on->on_bi.bi_private;
        Modifications mod;
        Operation opm;
        SlapReply rsm = { 0 };
@@ -1307,10 +1308,12 @@ syncprov_checkpoint( Operation *op, SlapReply *rs, slap_overinst *on )
        opm.o_req_ndn = op->o_bd->be_nsuffix[0];
        opm.o_bd->bd_info = on->on_info->oi_orig;
        opm.o_managedsait = SLAP_CONTROL_NONCRITICAL;
+       opm.o_no_schema_check = 1;
        opm.o_bd->be_modify( &opm, &rsm );
        if ( mod.sml_next != NULL ) {
                slap_mods_free( mod.sml_next, 1 );
        }
+       opm.orm_no_opattrs = 0;
 }
 
 static void
@@ -1810,9 +1813,17 @@ syncprov_search_cleanup( Operation *op, SlapReply *rs )
        return 0;
 }
 
+typedef struct SyncOperationBuffer {
+       Operation               sob_op;
+       Opheader                sob_hdr;
+       AttributeName   sob_extra;      /* not always present */
+       /* Further data allocated here */
+} SyncOperationBuffer;
+
 static void
 syncprov_detach_op( Operation *op, syncops *so, slap_overinst *on )
 {
+       SyncOperationBuffer *sopbuf2;
        Operation *op2;
        int i, alen = 0;
        size_t size;
@@ -1824,14 +1835,15 @@ syncprov_detach_op( Operation *op, syncops *so, slap_overinst *on )
                alen += op->ors_attrs[i].an_name.bv_len + 1;
        }
        /* Make a new copy of the operation */
-       size = sizeof(Operation) + sizeof(Opheader) +
+       size = offsetof( SyncOperationBuffer, sob_extra ) +
                (i ? ( (i+1) * sizeof(AttributeName) + alen) : 0) +
                op->o_req_dn.bv_len + 1 +
                op->o_req_ndn.bv_len + 1 +
                op->o_ndn.bv_len + 1 +
                so->s_filterstr.bv_len + 1;
-       op2 = (Operation *)ch_calloc( 1, size );
-       op2->o_hdr = (Opheader *)(op2+1);
+       sopbuf2 = ch_calloc( 1, size );
+       op2 = &sopbuf2->sob_op;
+       op2->o_hdr = &sopbuf2->sob_hdr;
 
        /* Copy the fields we care about explicitly, leave the rest alone */
        *op2->o_hdr = *op->o_hdr;
@@ -1841,18 +1853,18 @@ syncprov_detach_op( Operation *op, syncops *so, slap_overinst *on )
        op2->o_request = op->o_request;
        op2->o_private = on;
 
+       ptr = (char *) sopbuf2 + offsetof( SyncOperationBuffer, sob_extra );
        if ( i ) {
-               op2->ors_attrs = (AttributeName *)(op2->o_hdr + 1);
-               ptr = (char *)(op2->ors_attrs+i+1);
+               op2->ors_attrs = (AttributeName *) ptr;
+               ptr = (char *) &op2->ors_attrs[i+1];
                for (i=0; !BER_BVISNULL( &op->ors_attrs[i].an_name ); i++) {
                        op2->ors_attrs[i] = op->ors_attrs[i];
                        op2->ors_attrs[i].an_name.bv_val = ptr;
                        ptr = lutil_strcopy( ptr, op->ors_attrs[i].an_name.bv_val ) + 1;
                }
                BER_BVZERO( &op2->ors_attrs[i].an_name );
-       } else {
-               ptr = (char *)(op2->o_hdr + 1);
        }
+
        op2->o_authz = op->o_authz;
        op2->o_ndn.bv_val = ptr;
        ptr = lutil_strcopy(ptr, op->o_ndn.bv_val) + 1;
@@ -2296,10 +2308,15 @@ syncprov_operational(
                                                a = attr_find( rs->sr_entry->e_attrs,
                                                        slap_schema.si_ad_contextCSN );
                                        }
-                                       free( a->a_vals );
+                                       if ( a->a_nvals != a->a_vals ) {
+                                               ber_bvarray_free( a->a_nvals );
+                                       }
+                                       a->a_nvals = NULL;
+                                       ber_bvarray_free( a->a_vals );
+                                       a->a_vals = NULL;
                                }
                                ber_bvarray_dup_x( &a->a_vals, si->si_ctxcsn, NULL );
-                               a->a_nvals = a->a_vals;
+                               ber_bvarray_dup_x( &a->a_nvals, si->si_ctxcsn, NULL );
                        }
                        ldap_pvt_thread_rdwr_runlock( &si->si_csn_rwlock );
                }
@@ -2358,9 +2375,9 @@ sp_cf_gen(ConfigArgs *c)
                case SP_CHKPT:
                        if ( si->si_chkops || si->si_chktime ) {
                                struct berval bv;
-                               bv.bv_len = sprintf( c->msg, "%d %d",
+                               bv.bv_len = sprintf( c->cr_msg, "%d %d",
                                        si->si_chkops, si->si_chktime );
-                               bv.bv_val = c->msg;
+                               bv.bv_val = c->cr_msg;
                                value_add_one( &c->rvalue_vals, &bv );
                        } else {
                                rc = 1;
@@ -2419,31 +2436,31 @@ sp_cf_gen(ConfigArgs *c)
        switch ( c->type ) {
        case SP_CHKPT:
                if ( lutil_atoi( &si->si_chkops, c->argv[1] ) != 0 ) {
-                       snprintf( c->msg, sizeof( c->msg ), "%s unable to parse checkpoint ops # \"%s\"",
+                       snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s unable to parse checkpoint ops # \"%s\"",
                                c->argv[0], c->argv[1] );
                        Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
-                               "%s: %s\n", c->log, c->msg, 0 );
+                               "%s: %s\n", c->log, c->cr_msg, 0 );
                        return ARG_BAD_CONF;
                }
                if ( si->si_chkops <= 0 ) {
-                       snprintf( c->msg, sizeof( c->msg ), "%s invalid checkpoint ops # \"%d\"",
+                       snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s invalid checkpoint ops # \"%d\"",
                                c->argv[0], si->si_chkops );
                        Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
-                               "%s: %s\n", c->log, c->msg, 0 );
+                               "%s: %s\n", c->log, c->cr_msg, 0 );
                        return ARG_BAD_CONF;
                }
                if ( lutil_atoi( &si->si_chktime, c->argv[2] ) != 0 ) {
-                       snprintf( c->msg, sizeof( c->msg ), "%s unable to parse checkpoint time \"%s\"",
+                       snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s unable to parse checkpoint time \"%s\"",
                                c->argv[0], c->argv[1] );
                        Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
-                               "%s: %s\n", c->log, c->msg, 0 );
+                               "%s: %s\n", c->log, c->cr_msg, 0 );
                        return ARG_BAD_CONF;
                }
                if ( si->si_chktime <= 0 ) {
-                       snprintf( c->msg, sizeof( c->msg ), "%s invalid checkpoint time \"%d\"",
+                       snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s invalid checkpoint time \"%d\"",
                                c->argv[0], si->si_chkops );
                        Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
-                               "%s: %s\n", c->log, c->msg, 0 );
+                               "%s: %s\n", c->log, c->cr_msg, 0 );
                        return ARG_BAD_CONF;
                }
                si->si_chktime *= 60;
@@ -2453,10 +2470,10 @@ sp_cf_gen(ConfigArgs *c)
                int size = c->value_int;
 
                if ( size < 0 ) {
-                       snprintf( c->msg, sizeof( c->msg ), "%s size %d is negative",
+                       snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s size %d is negative",
                                c->argv[0], size );
                        Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
-                               "%s: %s\n", c->log, c->msg, 0 );
+                               "%s: %s\n", c->log, c->cr_msg, 0 );
                        return ARG_BAD_CONF;
                }
                sl = si->si_logs;
@@ -2500,15 +2517,16 @@ syncprov_db_otask(
  */
 static int
 syncprov_db_open(
-    BackendDB *be
+       BackendDB *be,
+       ConfigReply *cr
 )
 {
        slap_overinst   *on = (slap_overinst *) be->bd_info;
        syncprov_info_t *si = (syncprov_info_t *)on->on_bi.bi_private;
 
        Connection conn = { 0 };
-       OperationBuffer opbuf = { 0 };
-       Operation *op = (Operation *) &opbuf;
+       OperationBuffer opbuf;
+       Operation *op;
        Entry *e = NULL;
        Attribute *a;
        int rc;
@@ -2530,7 +2548,8 @@ syncprov_db_open(
        }
 
        thrctx = ldap_pvt_thread_pool_context();
-       connection_fake_init( &conn, op, thrctx );
+       connection_fake_init( &conn, &opbuf, thrctx );
+       op = &opbuf.ob_op;
        op->o_bd = be;
        op->o_dn = be->be_rootdn;
        op->o_ndn = be->be_rootndn;
@@ -2592,7 +2611,8 @@ out:
  */
 static int
 syncprov_db_close(
-    BackendDB *be
+       BackendDB *be,
+       ConfigReply *cr
 )
 {
     slap_overinst   *on = (slap_overinst *) be->bd_info;
@@ -2602,14 +2622,15 @@ syncprov_db_close(
                return 0;
        }
        if ( si->si_numops ) {
-               Connection conn;
+               Connection conn = {0};
                OperationBuffer opbuf;
-               Operation *op = (Operation *) &opbuf;
+               Operation *op;
                SlapReply rs = {REP_RESULT};
                void *thrctx;
 
                thrctx = ldap_pvt_thread_pool_context();
-               connection_fake_init( &conn, op, thrctx );
+               connection_fake_init( &conn, &opbuf, thrctx );
+               op = &opbuf.ob_op;
                op->o_bd = be;
                op->o_dn = be->be_rootdn;
                op->o_ndn = be->be_rootndn;
@@ -2621,7 +2642,8 @@ syncprov_db_close(
 
 static int
 syncprov_db_init(
-       BackendDB *be
+       BackendDB *be,
+       ConfigReply *cr
 )
 {
        slap_overinst   *on = (slap_overinst *)be->bd_info;
@@ -2653,7 +2675,8 @@ syncprov_db_init(
 
 static int
 syncprov_db_destroy(
-       BackendDB *be
+       BackendDB *be,
+       ConfigReply *cr
 )
 {
        slap_overinst   *on = (slap_overinst *)be->bd_info;
@@ -2708,8 +2731,13 @@ static int syncprov_parseCtrl (
                return LDAP_PROTOCOL_ERROR;
        }
 
+       if ( BER_BVISNULL( &ctrl->ldctl_value ) ) {
+               rs->sr_text = "Sync control value is absent";
+               return LDAP_PROTOCOL_ERROR;
+       }
+
        if ( BER_BVISEMPTY( &ctrl->ldctl_value ) ) {
-               rs->sr_text = "Sync control value is empty (or absent)";
+               rs->sr_text = "Sync control value is empty";
                return LDAP_PROTOCOL_ERROR;
        }
 
@@ -2767,8 +2795,8 @@ static int syncprov_parseCtrl (
        sr->sr_rhint = rhint;
        if (!BER_BVISNULL(&cookie)) {
                ber_dupbv_x( &sr->sr_state.octet_str, &cookie, op->o_tmpmemctx );
-               slap_parse_sync_cookie( &sr->sr_state, op->o_tmpmemctx );
-               if ( sr->sr_state.rid == -1 ) {
+               if ( slap_parse_sync_cookie( &sr->sr_state, op->o_tmpmemctx ) ||
+                       sr->sr_state.rid == -1 ) {
                        rs->sr_text = "Sync control : cookie parsing error";
                        return LDAP_PROTOCOL_ERROR;
                }
index ee9bf9ebe4da59bf5700f1e47d8cfaff836ae1c5..dce035531d1d1610d374d1bad2292ec2e9263a33 100644 (file)
@@ -103,9 +103,9 @@ translucent_cfadd( Operation *op, SlapReply *rs, Entry *e, ConfigArgs *ca )
        Debug(LDAP_DEBUG_TRACE, "==> translucent_cfadd\n", 0, 0, 0);
 
        /* FIXME: should not hardcode "olcDatabase" here */
-       bv.bv_len = sprintf( ca->msg, "olcDatabase=%s",
+       bv.bv_len = sprintf( ca->cr_msg, "olcDatabase=%s",
                             ov->db.bd_info->bi_type );
-       bv.bv_val = ca->msg;
+       bv.bv_val = ca->cr_msg;
        ca->be = &ov->db;
 
        /* We can only create this entry if the database is table-driven
@@ -686,7 +686,7 @@ static int translucent_db_config(
 **
 */
 
-static int translucent_db_init(BackendDB *be) {
+static int translucent_db_init(BackendDB *be, ConfigReply *cr) {
        slap_overinst *on = (slap_overinst *) be->bd_info;
        translucent_info *ov;
 
@@ -698,7 +698,7 @@ static int translucent_db_init(BackendDB *be) {
        ov->db.be_private = NULL;
        ov->db.be_pcl_mutexp = &ov->db.be_pcl_mutex;
 
-       if ( !backend_db_init( "ldap", &ov->db, -1 )) {
+       if ( !backend_db_init( "ldap", &ov->db, -1, NULL )) {
                Debug( LDAP_DEBUG_CONFIG, "translucent: unable to open captive back-ldap\n", 0, 0, 0);
                return 1;
        }
@@ -714,7 +714,7 @@ static int translucent_db_init(BackendDB *be) {
 **
 */
 
-static int translucent_db_open(BackendDB *be) {
+static int translucent_db_open(BackendDB *be, ConfigReply *cr) {
        slap_overinst *on = (slap_overinst *) be->bd_info;
        translucent_info *ov = on->on_bi.bi_private;
        int rc;
@@ -727,7 +727,7 @@ static int translucent_db_open(BackendDB *be) {
        ov->db.be_acl = be->be_acl;
        ov->db.be_dfltaccess = be->be_dfltaccess;
 
-       rc = backend_startup_one( &ov->db );
+       rc = backend_startup_one( &ov->db, NULL );
 
        if(rc) Debug(LDAP_DEBUG_TRACE,
                "translucent: bi_db_open() returned error %d\n", rc, 0, 0);
@@ -743,7 +743,7 @@ static int translucent_db_open(BackendDB *be) {
 */
 
 static int
-translucent_db_close( BackendDB *be )
+translucent_db_close( BackendDB *be, ConfigReply *cr )
 {
        slap_overinst *on = (slap_overinst *) be->bd_info;
        translucent_info *ov = on->on_bi.bi_private;
@@ -752,7 +752,7 @@ translucent_db_close( BackendDB *be )
        Debug(LDAP_DEBUG_TRACE, "==> translucent_db_close\n", 0, 0, 0);
 
        if ( ov && ov->db.bd_info && ov->db.bd_info->bi_db_close ) {
-               rc = ov->db.bd_info->bi_db_close(&ov->db);
+               rc = ov->db.bd_info->bi_db_close(&ov->db, NULL);
        }
 
        return(rc);
@@ -765,13 +765,13 @@ translucent_db_close( BackendDB *be )
 */
 
 static int
-translucent_db_destroy( BackendDB *be )
+translucent_db_destroy( BackendDB *be, ConfigReply *cr )
 {
        slap_overinst *on = (slap_overinst *) be->bd_info;
        translucent_info *ov = on->on_bi.bi_private;
        int rc = 0;
 
-       Debug(LDAP_DEBUG_TRACE, "==> translucent_db_close\n", 0, 0, 0);
+       Debug(LDAP_DEBUG_TRACE, "==> translucent_db_destroy\n", 0, 0, 0);
 
        if ( ov ) {
                if ( ov->db.be_private != NULL ) {
index 9d6eefbdbbcf3b35c96da76b30c4b653037a47bb..68154eaec3f5a02fbf0a00bd76443c65b4bb3b63 100644 (file)
@@ -3,7 +3,7 @@
 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
  *
  * Copyright 2004-2007 The OpenLDAP Foundation.
- * Portions Copyright 2004 Symas Corporation.
+ * Portions Copyright 2004,2006-2007 Symas Corporation.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * top-level directory of the distribution or, alternatively, at
  * <http://www.OpenLDAP.org/license.html>.
  */
-/* ACKNOWLEDGEMENTS:
- * This work was initially developed by Symas Corp. for inclusion in
- * OpenLDAP Software.  This work was sponsored by Hewlett-Packard.
+/* ACKNOWLEDGEMENTS: 
+ * This work was initially developed by Symas Corporation for
+ * inclusion in OpenLDAP Software, with subsequent enhancements by
+ * Matthew Backes at Symas Corporation.  This work was sponsored by
+ * Hewlett-Packard.
  */
 
 #include "portable.h"
 #include "slap.h"
 #include "config.h"
 
+#define UNIQUE_DEFAULT_URI ("ldap:///??sub")
+
 static slap_overinst unique;
 
 typedef struct unique_attrs_s {
-       struct unique_attrs_s *next;            /* list of attrs */
+       struct unique_attrs_s *next;          /* list of attrs */
        AttributeDescription *attr;
 } unique_attrs;
 
+typedef struct unique_domain_uri_s {
+       struct unique_domain_uri_s *next;
+       struct berval *dn;
+       struct berval *ndn;
+       struct berval *filter;
+       struct unique_attrs_s *attrs;
+       int scope;
+} unique_domain_uri;
+
+typedef struct unique_domain_s {
+       struct unique_domain_s *next;
+       struct berval *domain_spec;
+       struct unique_domain_uri_s *uri;
+       char ignore;                          /* polarity of attributes */
+       char strict;                          /* null considered unique too */
+} unique_domain;
+
 typedef struct unique_data_s {
-       const char *message;                    /* breadcrumbs */
-       struct unique_attrs_s *attrs;           /* list of known attrs */
-       struct unique_attrs_s *ignore;          /* list of ignored attrs */
-       BerValue dn;                            /* base of "unique tree" */
-       char strict;                            /* null considered unique too */
+       struct unique_domain_s *domains;
+       struct unique_domain_s *legacy;
+       char legacy_strict_set;
 } unique_data;
 
 typedef struct unique_counter_s {
@@ -55,32 +74,47 @@ enum {
        UNIQUE_BASE = 1,
        UNIQUE_IGNORE,
        UNIQUE_ATTR,
-       UNIQUE_STRICT
+       UNIQUE_STRICT,
+       UNIQUE_URI
 };
 
-static ConfigDriver unique_cf_gen;
+static ConfigDriver unique_cf_base;
+static ConfigDriver unique_cf_attrs;
+static ConfigDriver unique_cf_strict;
+static ConfigDriver unique_cf_uri;
 
 static ConfigTable uniquecfg[] = {
        { "unique_base", "basedn", 2, 2, 0, ARG_DN|ARG_MAGIC|UNIQUE_BASE,
-         unique_cf_gen, "( OLcfgOvAt:10.1 NAME 'olcUniqueBase' "
+         unique_cf_base, "( OLcfgOvAt:10.1 NAME 'olcUniqueBase' "
          "DESC 'Subtree for uniqueness searches' "
+         "EQUALITY distinguishedNameMatch "
          "SYNTAX OMsDN SINGLE-VALUE )", NULL, NULL },
        { "unique_ignore", "attribute...", 2, 0, 0, ARG_MAGIC|UNIQUE_IGNORE,
-         unique_cf_gen, "( OLcfgOvAt:10.2 NAME 'olcUniqueIgnore' "
+         unique_cf_attrs, "( OLcfgOvAt:10.2 NAME 'olcUniqueIgnore' "
          "DESC 'Attributes for which uniqueness shall not be enforced' "
-         "EQUALITY caseIgnoreMatch "   /* Should use OID syntax */
+         "EQUALITY caseIgnoreMatch "
+         "ORDERING caseIgnoreOrderingMatch "
+         "SUBSTR caseIgnoreSubstringsMatch "
          "SYNTAX OMsDirectoryString )", NULL, NULL },
        { "unique_attributes", "attribute...", 2, 0, 0, ARG_MAGIC|UNIQUE_ATTR,
-         unique_cf_gen, "( OLcfgOvAt:10.3 NAME 'olcUniqueAttribute' "
+         unique_cf_attrs, "( OLcfgOvAt:10.3 NAME 'olcUniqueAttribute' "
          "DESC 'Attributes for which uniqueness shall be enforced' "
          "EQUALITY caseIgnoreMatch "
+         "ORDERING caseIgnoreOrderingMatch "
+         "SUBSTR caseIgnoreSubstringsMatch "
          "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' "
+       { "unique_strict", "on|off", 1, 2, 0, ARG_MAGIC|UNIQUE_STRICT,
+         unique_cf_strict, "( OLcfgOvAt:10.4 NAME 'olcUniqueStrict' "
          "DESC 'Enforce uniqueness of null values' "
+         "EQUALITY booleanMatch "
          "SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL },
+       { "unique_uri", "ldapuri", 2, 3, 0, ARG_MAGIC|UNIQUE_URI,
+         unique_cf_uri, "( OLcfgOvAt:10.5 NAME 'olcUniqueURI' "
+         "DESC 'List of keywords and LDAP URIs for a uniqueness domain' "
+         "EQUALITY caseExactMatch "
+         "ORDERING caseExactOrderingMatch "
+         "SUBSTR caseExactSubstringsMatch "
+         "SYNTAX OMsDirectoryString )", NULL, NULL },
        { NULL, NULL, 0, 0, 0, ARG_IGNORED }
 };
 
@@ -90,150 +124,606 @@ static ConfigOCs uniqueocs[] = {
          "DESC 'Attribute value uniqueness configuration' "
          "SUP olcOverlayConfig "
          "MAY ( olcUniqueBase $ olcUniqueIgnore $ "
-         "olcUniqueAttribute $ olcUniqueStrict ) )",
+         "olcUniqueAttribute $ olcUniqueStrict $ "
+         "olcUniqueURI ) )",
          Cft_Overlay, uniquecfg },
        { NULL, 0, NULL }
 };
 
+static void
+unique_free_domain_uri ( unique_domain_uri *uri )
+{
+       unique_domain_uri *next_uri = NULL;
+       unique_attrs *attr, *next_attr = NULL;
+
+       while ( uri ) {
+               next_uri = uri->next;
+               ber_bvfree ( uri->dn );
+               ber_bvfree ( uri->ndn );
+               ber_bvfree ( uri->filter );
+               attr = uri->attrs;
+               while ( attr ) {
+                       next_attr = attr->next;
+                       ch_free (attr);
+                       attr = next_attr;
+               }
+               ch_free ( uri );
+               uri = next_uri;
+       }
+}
+
+/* free an entire stack of domains */
+static void
+unique_free_domain ( unique_domain *domain )
+{
+       unique_domain *next_domain = NULL;
+
+       while ( domain ) {
+               next_domain = domain->next;
+               ber_bvfree ( domain->domain_spec );
+               unique_free_domain_uri ( domain->uri );
+               ch_free ( domain );
+               domain = next_domain;
+       }
+}
+
 static int
-unique_cf_gen( ConfigArgs *c )
+unique_new_domain_uri ( unique_domain_uri **urip,
+                       const LDAPURLDesc *url_desc,
+                       ConfigArgs *c )
 {
-       slap_overinst *on = (slap_overinst *)c->bi;
-       unique_data *ud = (unique_data *)on->on_bi.bi_private;
+       int i, rc = LDAP_SUCCESS;
+       unique_domain_uri *uri;
+       struct berval bv = {0, NULL};
        BackendDB *be = (BackendDB *)c->be;
-       unique_attrs *up, *pup, **pupp = NULL;
-       AttributeDescription *ad;
-       const char *text;
+       char ** attr_str;
+       AttributeDescription * ad;
+       const char * text;
+
+       uri = ch_calloc ( 1, sizeof ( unique_domain_uri ) );
+
+       if ( url_desc->lud_dn && url_desc->lud_dn[0] ) {
+               ber_str2bv( url_desc->lud_dn, 0, 1, &bv );
+               rc = dnPrettyNormal( NULL,
+                                    &bv,
+                                    uri->dn,
+                                    uri->ndn,
+                                    NULL );
+               if ( rc != LDAP_SUCCESS ) {
+                       snprintf( c->cr_msg, sizeof( c->cr_msg ),
+                                 "<%s> invalid DN %d (%s)",
+                                 url_desc->lud_dn, rc, ldap_err2string( rc ));
+                       rc = ARG_BAD_CONF;
+                       goto exit;
+               }
+
+               if ( !dnIsSuffix ( uri->ndn, &be->be_nsuffix[0] ) ) {
+                       sprintf ( c->cr_msg,
+                                 "dn <%s> is not a suffix of backend base dn <%s>",
+                                 uri->dn->bv_val,
+                                 be->be_nsuffix[0].bv_val );
+                       rc = ARG_BAD_CONF;
+                       goto exit;
+               }
+       }
+
+       attr_str = url_desc->lud_attrs;
+       if ( attr_str ) {
+               for ( i=0; attr_str[i]; ++i ) {
+                       unique_attrs * attr;
+                       ad = NULL;
+                       if ( slap_str2ad ( attr_str[i], &ad, &text )
+                            == LDAP_SUCCESS) {
+                               attr = ch_calloc ( 1,
+                                                  sizeof ( unique_attrs ) );
+                               attr->attr = ad;
+                               attr->next = uri->attrs;
+                               uri->attrs = attr;
+                       } else {
+                               snprintf( c->cr_msg, sizeof( c->cr_msg ),
+                                         "unique: attribute: %s: %s",
+                                         attr_str[i], text );
+                               rc = ARG_BAD_CONF;
+                               goto exit;
+                       }
+               }
+       }
+
+       uri->scope = url_desc->lud_scope;
+       if ( !uri->scope ) {
+               snprintf( c->cr_msg, sizeof( c->cr_msg ),
+                         "unique: uri with base scope will always be unique");
+               rc = ARG_BAD_CONF;
+               goto exit;
+       }
+
+       if (url_desc->lud_filter) {
+               Filter * f;
+               uri->filter = ber_str2bv( url_desc->lud_filter, 0, 1, NULL);
+               f = str2filter( uri->filter->bv_val );
+               if ( !f ) {
+                       snprintf( c->cr_msg, sizeof( c->cr_msg ),
+                                 "unique: bad filter");
+                       rc = ARG_BAD_CONF;
+                       goto exit;
+               }
+               filter_free( f );
+       }
+exit:
+       if ( bv.bv_val ) ber_memfree ( bv.bv_val );
+       uri->next = *urip;
+       *urip = uri;
+       if ( rc ) {
+               Debug ( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
+                       "%s: %s\n", c->log, c->cr_msg, 0 );
+               unique_free_domain_uri ( uri );
+               *urip = NULL;
+       }
+       return rc;
+}
+
+static int
+unique_new_domain_uri_basic ( unique_domain_uri **urip,
+                             ConfigArgs *c )
+{
+       LDAPURLDesc *url_desc = NULL;
+       int rc;
+
+       rc = ldap_url_parse ( UNIQUE_DEFAULT_URI, &url_desc );
+       if ( rc ) return rc;
+       rc = unique_new_domain_uri ( urip, url_desc, c );
+       ldap_free_urldesc ( url_desc );
+       return rc;
+}
+
+/* if *domain is non-null, it's pushed down the stack.
+ * note that the entire stack is freed if there is an error,
+ * so build added domains in a separate stack before adding them
+ *
+ * domain_specs look like
+ *
+ * [strict ][ignore ]uri[[ uri]...]
+ * e.g. "ldap:///ou=foo,o=bar?uid?sub ldap:///ou=baz,o=bar?uid?sub"
+ *      "strict ldap:///ou=accounts,o=bar?uid,uidNumber?one"
+ *      etc
+ *
+ * so finally strictness is per-domain
+ * but so is ignore-state, and that would be better as a per-url thing
+ */
+static int
+unique_new_domain ( unique_domain **domainp,
+                   char *domain_spec,
+                   ConfigArgs *c )
+{
+       char *uri_start;
+       int rc = LDAP_SUCCESS;
+       int uri_err = 0;
+       unique_domain * domain;
+       LDAPURLDesc *url_desc, *url_descs = NULL;
+
+       Debug(LDAP_DEBUG_TRACE, "==> unique_new_domain <%s>\n",
+             domain_spec, 0, 0);
+
+       domain = ch_calloc ( 1, sizeof (unique_domain) );
+       domain->domain_spec = ber_str2bv( domain_spec, 0, 1, NULL );
+
+       uri_start = domain_spec;
+       if ( strncasecmp ( uri_start, "ignore ",
+                          STRLENOF( "ignore " ) ) == 0 ) {
+               domain->ignore = 1;
+               uri_start += STRLENOF( "ignore " );
+       }
+       if ( strncasecmp ( uri_start, "strict ",
+                          STRLENOF( "strict " ) ) == 0 ) {
+               domain->strict = 1;
+               uri_start += STRLENOF( "strict " );
+               if ( !domain->ignore
+                    && strncasecmp ( uri_start, "ignore ",
+                                     STRLENOF( "ignore " ) ) == 0 ) {
+                       domain->ignore = 1;
+                       uri_start += STRLENOF( "ignore " );
+               }
+       }
+       rc = ldap_url_parselist_ext ( &url_descs, uri_start, " ", 0 );
+       if ( rc ) {
+               snprintf( c->cr_msg, sizeof( c->cr_msg ),
+                         "<%s> invalid ldap urilist",
+                         uri_start );
+               rc = ARG_BAD_CONF;
+               goto exit;
+       }
+
+       for ( url_desc = url_descs;
+             url_desc;
+             url_desc = url_descs->lud_next ) {
+               rc = unique_new_domain_uri ( &domain->uri,
+                                            url_desc,
+                                            c );
+               if ( rc ) {
+                       rc = ARG_BAD_CONF;
+                       uri_err = 1;
+                       goto exit;
+               }
+       }
+
+exit:
+       if ( url_descs ) ldap_free_urldesc ( url_descs );
+       domain->next = *domainp;
+       *domainp = domain;
+       if ( rc ) {
+               Debug ( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
+                       "%s: %s\n", c->log, c->cr_msg, 0 );
+               unique_free_domain ( domain );
+               *domainp = NULL;
+       }
+       return rc;
+}
+
+static int
+unique_cf_base( ConfigArgs *c )
+{
+       BackendDB *be = (BackendDB *)c->be;
+       slap_overinst *on = (slap_overinst *)c->bi;
+       unique_data *private = (unique_data *) on->on_bi.bi_private;
+       unique_domain *domains = private->domains;
+       unique_domain *legacy = private->legacy;
        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;
-                       }
+               rc = 0;
+               if ( legacy && legacy->uri && legacy->uri->dn ) {
+                       rc = value_add_one ( &c->rvalue_vals,
+                                            legacy->uri->dn );
+                       if ( rc ) return rc;
+                       rc = value_add_one ( &c->rvalue_nvals,
+                                            legacy->uri->ndn );
+                       if ( rc ) return rc;
+               }
+               break;
+       case LDAP_MOD_DELETE:
+               assert ( legacy && legacy->uri && legacy->uri->dn );
+               rc = 0;
+               ber_bvfree ( legacy->uri->dn );
+               ber_bvfree ( legacy->uri->ndn );
+               legacy->uri->dn = NULL;
+               legacy->uri->ndn = NULL;
+               if ( !legacy->uri->attrs
+                    && !legacy->uri->dn ) {
+                       unique_free_domain_uri ( legacy->uri );
+                       legacy->uri = NULL;
+               }
+               if ( !legacy->uri && !private->legacy_strict_set ) {
+                       unique_free_domain ( legacy );
+                       private->legacy = legacy = NULL;
+               }
+               break;
+       case LDAP_MOD_ADD:
+       case SLAP_CONFIG_ADD:
+               if ( domains ) {
+                       sprintf ( c->cr_msg,
+                                 "cannot set legacy attrs when URIs are present" );
+                       Debug ( LDAP_DEBUG_CONFIG, "unique config: %s\n",
+                               c->cr_msg, NULL, NULL );
+                       rc = ARG_BAD_CONF;
                        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;
+               }
+               if ( !dnIsSuffix ( &c->value_ndn,
+                                  &be->be_nsuffix[0] ) ) {
+                       sprintf ( c->cr_msg,
+                                 "dn is not a suffix of backend base" );
+                       Debug ( LDAP_DEBUG_CONFIG, "unique config: %s\n",
+                               c->cr_msg, NULL, NULL );
+                       rc = ARG_BAD_CONF;
                        break;
-               case UNIQUE_STRICT:
-                       /* handled via ARG_OFFSET */
-                       /* fallthrough to default */
-               default:
-                       abort ();
                }
+               if ( !legacy ) {
+                       unique_new_domain ( &private->legacy,
+                                           UNIQUE_DEFAULT_URI,
+                                           c );
+                       legacy = private->legacy;
+               }
+               if ( !legacy->uri )
+                       unique_new_domain_uri_basic ( &legacy->uri, c );
+               ber_bvfree ( legacy->uri->dn );
+               ber_bvfree ( legacy->uri->ndn );
+               legacy->uri->dn = ber_bvdup ( &c->value_dn );
+               legacy->uri->ndn = ber_bvdup ( &c->value_ndn );
+               rc = 0;
+               break;
+       default:
+               abort();
+       }
+
+       return rc;
+}
+
+static int
+unique_cf_attrs( ConfigArgs *c )
+{
+       slap_overinst *on = (slap_overinst *)c->bi;
+       unique_data *private = (unique_data *) on->on_bi.bi_private;
+       unique_domain *domains = private->domains;
+       unique_domain *legacy = private->legacy;
+       unique_attrs *new_attrs = NULL;
+       unique_attrs *attr, *next_attr, *reverse_attrs;
+       unique_attrs **attrp;
+       int rc = ARG_BAD_CONF;
+       int i;
+
+       switch ( c->op ) {
+       case SLAP_CONFIG_EMIT:
+               if ( legacy
+                    && (c->type == UNIQUE_IGNORE) == legacy->ignore
+                    && legacy->uri )
+                       for ( attr = legacy->uri->attrs;
+                             attr;
+                             attr = attr->next )
+                               value_add_one( &c->rvalue_vals,
+                                              &attr->attr->ad_cname );
+               rc = 0;
                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;
+               if ( legacy
+                    && (c->type == UNIQUE_IGNORE) == legacy->ignore
+                    && legacy->uri
+                    && legacy->uri->attrs) {
+                       if ( c->valx < 0 ) { /* delete all */
+                               for ( attr = legacy->uri->attrs;
+                                     attr;
+                                     attr = next_attr ) {
+                                       next_attr = attr->next;
+                                       ch_free ( attr );
+                               }
+                               legacy->uri->attrs = NULL;
+                       } else { /* delete by index */
+                               attrp = &legacy->uri->attrs;
+                               for ( i=0; i < c->valx; ++i )
+                                       attrp = &(*attrp)->next;
+                               attr = *attrp;
+                               *attrp = attr->next;
+                               ch_free (attr);
+                       }
+                       if ( !legacy->uri->attrs
+                            && !legacy->uri->dn ) {
+                               unique_free_domain_uri ( legacy->uri );
+                               legacy->uri = NULL;
+                       }
+                       if ( !legacy->uri && !private->legacy_strict_set ) {
+                               unique_free_domain ( legacy );
+                               private->legacy = legacy = NULL;
+                       }
+               }
+               rc = 0;
+               break;
+       case LDAP_MOD_ADD:
+       case SLAP_CONFIG_ADD:
+               if ( domains ) {
+                       sprintf ( c->cr_msg,
+                                 "cannot set legacy attrs when URIs are present" );
+                       Debug ( LDAP_DEBUG_CONFIG, "unique config: %s\n",
+                               c->cr_msg, NULL, NULL );
+                       rc = ARG_BAD_CONF;
+                       break;
+               }
+               if ( legacy
+                    && legacy->uri
+                    && legacy->uri->attrs
+                    && (c->type == UNIQUE_IGNORE) != legacy->ignore ) {
+                       sprintf ( c->cr_msg,
+                                 "cannot set both attrs and ignore-attrs" );
+                       Debug ( LDAP_DEBUG_CONFIG, "unique config: %s\n",
+                               c->cr_msg, NULL, NULL );
+                       rc = ARG_BAD_CONF;
                        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 );
+               }
+               if ( !legacy ) {
+                       unique_new_domain ( &private->legacy,
+                                           UNIQUE_DEFAULT_URI,
+                                           c );
+                       legacy = private->legacy;
+               }
+               if ( !legacy->uri )
+                       unique_new_domain_uri_basic ( &legacy->uri, c );
+               rc = 0;
+               for ( i=1; c->argv[i]; ++i ) {
+                       AttributeDescription * ad = NULL;
+                       const char * text;
+                       if ( slap_str2ad ( c->argv[i], &ad, &text )
+                            == LDAP_SUCCESS) {
+
+                               attr = ch_calloc ( 1,
+                                       sizeof ( unique_attrs ) );
+                               attr->attr = ad;
+                               attr->next = new_attrs;
+                               new_attrs = attr;
+                       } else {
+                               snprintf( c->cr_msg, sizeof( c->cr_msg ),
+                                         "unique: attribute: %s: %s",
+                                         c->argv[i], text );
+                               for ( attr = new_attrs;
+                                     attr;
+                                     attr=next_attr ) {
+                                       next_attr = attr->next;
+                                       ch_free ( attr );
                                }
+                               rc = ARG_BAD_CONF;
+                               break;
+                       }
+               }
+               if ( rc ) break;
+
+               /* (nconc legacy->uri->attrs (nreverse new_attrs)) */
+               reverse_attrs = NULL;
+               for ( attr = new_attrs;
+                     attr;
+                     attr = next_attr ) {
+                       next_attr = attr->next;
+                       attr->next = reverse_attrs;
+                       reverse_attrs = attr;
+               }
+               for ( attrp = &legacy->uri->attrs;
+                     *attrp;
+                     attrp = &(*attrp)->next ) ;
+               *attrp = reverse_attrs;
 
-                       } else {
+               legacy->ignore = ( c->type == UNIQUE_IGNORE );
+               break;
+       default:
+               abort();
+       }
 
-                               /* delete from linked list */
-                               for ( i=0; i < c->valx; ++i ) {
-                                       pupp = &(*pupp)->next;
-                               }
-                               up = *pupp;
-                               *pupp = (*pupp)->next;
+       if ( rc ) {
+               Debug ( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
+                       "%s: %s\n", c->log, c->cr_msg, 0 );
+       }
+       return rc;
+}
+
+static int
+unique_cf_strict( ConfigArgs *c )
+{
+       slap_overinst *on = (slap_overinst *)c->bi;
+       unique_data *private = (unique_data *) on->on_bi.bi_private;
+       unique_domain *domains = private->domains;
+       unique_domain *legacy = private->legacy;
+       int rc = ARG_BAD_CONF;
 
-                               /* AttributeDescriptions are global so
-                                * shouldn't be freed here... */
-                               ch_free ( up );
+       switch ( c->op ) {
+       case SLAP_CONFIG_EMIT:
+               /* We process the boolean manually instead of using
+                * ARG_ON_OFF so that we can three-state it;
+                * olcUniqueStrict is either TRUE, FALSE, or missing,
+                * and missing is necessary to add olcUniqueURIs...
+                */
+               if ( private->legacy_strict_set ) {
+                       struct berval bv;
+                       bv.bv_val = legacy->strict ? "TRUE" : "FALSE";
+                       bv.bv_len = legacy->strict ?
+                               STRLENOF("TRUE") :
+                               STRLENOF("FALSE");
+                       value_add_one ( &c->rvalue_vals, &bv );
+               }
+               rc = 0;
+               break;
+       case LDAP_MOD_DELETE:
+               if ( legacy ) {
+                       legacy->strict = 0;
+                       if ( ! legacy->uri ) {
+                               unique_free_domain ( legacy );
+                               private->legacy = NULL;
                        }
-                       rc = 0;
-                       break;
-               case UNIQUE_STRICT:
-                       /* handled via ARG_OFFSET */
-                       /* fallthrough to default */
-               default:
-                       abort ();
                }
+               private->legacy_strict_set = 0;
+               rc = 0;
                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, "%s dn is not a suffix of backend base",
-                                       c->argv[0] );
-                               Debug ( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
-                                       "%s: %s\n", c->log, c->msg, 0 );
-                               rc = ARG_BAD_CONF;
-                       }
-                       if ( ud->dn.bv_val ) ber_memfree ( ud->dn.bv_val );
-                       ud->dn = c->value_ndn;
-                       rc = 0;
+       case SLAP_CONFIG_ADD:
+               if ( domains ) {
+                       sprintf ( c->cr_msg,
+                                 "cannot set legacy attrs when URIs are present" );
+                       Debug ( LDAP_DEBUG_CONFIG, "unique config: %s\n",
+                               c->cr_msg, NULL, NULL );
+                       rc = ARG_BAD_CONF;
                        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 {
-                                       snprintf( c->msg, sizeof( c->msg ),
-                                               "%s <%s>: %s", c->argv[0], c->argv[i], text );
-                                       Debug ( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
-                                               "%s: %s\n", c->log, c->msg, 0 );
-                                       rc = ARG_BAD_CONF;
-                               }
-                       }
+               }
+               if ( ! legacy ) {
+                       unique_new_domain ( &private->legacy,
+                                           UNIQUE_DEFAULT_URI,
+                                           c );
+                       legacy = private->legacy;
+               }
+               /* ... not using ARG_ON_OFF makes this necessary too */
+               assert ( c->argc == 2 );
+               legacy->strict = (strcasecmp ( c->argv[1], "TRUE" ) == 0);
+               private->legacy_strict_set = 1;
+               rc = 0;
+               break;
+       default:
+               abort();
+       }
+
+       return rc;
+}
+
+static int
+unique_cf_uri( ConfigArgs *c )
+{
+       slap_overinst *on = (slap_overinst *)c->bi;
+       unique_data *private = (unique_data *) on->on_bi.bi_private;
+       unique_domain *domains = private->domains;
+       unique_domain *legacy = private->legacy;
+       unique_domain *domain = NULL, **domainp = NULL;
+       int rc = ARG_BAD_CONF;
+       int i;
+
+       switch ( c->op ) {
+       case SLAP_CONFIG_EMIT:
+               for ( domain = domains;
+                     domain;
+                     domain = domain->next ) {
+                       rc = value_add_one ( &c->rvalue_vals,
+                                            domain->domain_spec );
+                       if ( rc ) break;
+                       rc = value_add_one ( &c->rvalue_nvals,
+                                            domain->domain_spec );
+                       if ( rc ) break;
+               }
+               break;
+       case LDAP_MOD_DELETE:
+               if ( c->valx < 0 ) { /* delete them all! */
+                       unique_free_domain ( domains );
+                       private->domains = NULL;
+               } else { /* delete just one */
+                       domainp = &private->domains;
+                       for ( i=0; i < c->valx && *domainp; ++i )
+                               domainp = &(*domainp)->next;
+
+                       /* If *domainp is null, we walked off the end
+                        * of the list.  This happens when back-config
+                        * and the overlay are out-of-sync, like when
+                        * rejecting changes before ITS#4752 gets
+                        * fixed.
+                        *
+                        * This should never happen, but will appear
+                        * if you backport this version of
+                        * slapo-unique without the config-undo fixes
+                        *
+                        * test024 Will hit this case in such a
+                        * situation.
+                        */
+                       assert (*domainp != NULL);
+
+                       domain = *domainp;
+                       *domainp = domain->next;
+                       domain->next = NULL;
+                       unique_free_domain ( domain );
+               }
+               rc = 0;
+               break;
+
+       case SLAP_CONFIG_ADD: /* fallthrough */
+       case LDAP_MOD_ADD:
+               if ( legacy ) {
+                       sprintf ( c->cr_msg,
+                                 "cannot set Uri when legacy attrs are present" );
+                       Debug ( LDAP_DEBUG_CONFIG, "unique config: %s\n",
+                               c->cr_msg, NULL, NULL );
+                       rc = ARG_BAD_CONF;
                        break;
-               case UNIQUE_STRICT:
-                       /* handled via ARG_OFFSET */
-                       /* fallthrough to default */
-               default:
-                       abort ();
                }
+               rc = 0;
+               if ( c->line ) rc = unique_new_domain ( &domain, c->line, c );
+               else rc = unique_new_domain ( &domain, c->argv[1], c );
+               if ( rc ) break;
+               assert ( domain->next == NULL );
+               for ( domainp = &private->domains;
+                     *domainp;
+                     domainp = &(*domainp)->next ) ;
+               *domainp = domain;
+
                break;
+
        default:
                abort ();
        }
@@ -248,94 +738,86 @@ unique_cf_gen( ConfigArgs *c )
 **
 */
 
-static int unique_db_init(
-       BackendDB       *be
+static int
+unique_db_init(
+       BackendDB       *be,
+       ConfigReply     *cr
 )
 {
        slap_overinst *on = (slap_overinst *)be->bd_info;
-       unique_data *ud   = ch_calloc(1,sizeof(unique_data));
+       unique_data **privatep = (unique_data **) &on->on_bi.bi_private;
 
-       /* Debug(LDAP_DEBUG_TRACE, "==> unique_init\n", 0, 0, 0); */
+       Debug(LDAP_DEBUG_TRACE, "==> unique_db_init\n", 0, 0, 0);
+
+       *privatep = ch_calloc ( 1, sizeof ( unique_data ) );
 
-       ud->message     = "_init";
-       on->on_bi.bi_private = ud;
        return 0;
 }
 
-static int unique_db_destroy(
-       BackendDB       *be
+static int
+unique_db_destroy(
+       BackendDB       *be,
+       ConfigReply     *cr
 )
 {
        slap_overinst *on = (slap_overinst *)be->bd_info;
+       unique_data **privatep = (unique_data **) &on->on_bi.bi_private;
+       unique_data *private = *privatep;
+
+       Debug(LDAP_DEBUG_TRACE, "==> unique_db_destroy\n", 0, 0, 0);
+
+       if ( private ) {
+               unique_domain *domains = private->domains;
+               unique_domain *legacy = private->legacy;
 
-       if ( on->on_bi.bi_private ) {
-               ch_free( on->on_bi.bi_private );
-               on->on_bi.bi_private = NULL;
+               unique_free_domain ( domains );
+               unique_free_domain ( legacy );
+               ch_free ( private );
+               *privatep = NULL;
        }
+
        return 0;
 }
 
-/*
-** mostly, just print the init message;
-**
-*/
-
 static int
 unique_open(
-       BackendDB *be
+       BackendDB *be,
+       ConfigReply *cr
 )
 {
-       slap_overinst *on       = (slap_overinst *)be->bd_info;
-       unique_data *ud         = on->on_bi.bi_private;
-       ud->message             = "_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);
+       return 0;
 }
 
 
 /*
-** foreach configured attribute:
-**     free it;
-** free our basedn;
+** Leave unique_data but wipe out config
 **
 */
 
 static int
 unique_close(
-       BackendDB *be
+       BackendDB *be,
+       ConfigReply *cr
 )
 {
        slap_overinst *on       = (slap_overinst *) be->bd_info;
-       unique_data *ud         = on->on_bi.bi_private;
-       unique_attrs *ii, *ij;
-       ud->message             = "_close";
+       unique_data **privatep = (unique_data **) &on->on_bi.bi_private;
+       unique_data *private = *privatep;
 
        Debug(LDAP_DEBUG_TRACE, "==> unique_close\n", 0, 0, 0);
 
-       for(ii = ud->attrs; ii; ii = ij) {
-               ij = ii->next;
-               ch_free(ii);
-       }
+       if ( private ) {
+               unique_domain *domains = private->domains;
+               unique_domain *legacy = private->legacy;
 
-       for(ii = ud->ignore; ii; ii = ij) {
-               ij = ii->next;
-               ch_free(ii);
+               unique_free_domain ( domains );
+               unique_free_domain ( legacy );
+               memset ( private, 0, sizeof ( unique_data ) );
        }
 
-       ch_free(ud->dn.bv_val);
-
-       memset( ud, 0, sizeof(*ud));
-
-       return(0);
+       return ( 0 );
 }
 
 
@@ -371,34 +853,31 @@ static int count_attr_cb(
        return(0);
 }
 
-static int count_filter_len(
-       unique_data *ud,
+/* count the length of one attribute ad
+ * (and all of its values b)
+ * in the proposed filter
+ */
+static int
+count_filter_len(
+       unique_domain *domain,
+       unique_domain_uri *uri,
        AttributeDescription *ad,
-       BerVarray b,
-       int ks
+       BerVarray b
 )
 {
-       unique_attrs *up;
+       unique_attrs *attr;
        int i;
+       int ks = 0;
 
        while ( !is_at_operational( ad->ad_type ) ) {
-               if ( ud->ignore ) {
-                       for ( up = ud->ignore; up; up = up->next ) {
-                               if (ad == up->attr ) {
-                                       break;
-                               }
-                       }
-                       if ( up ) {
-                               break;
-                       }
-               }
-               if ( ud->attrs ) {
-                       for ( up = ud->attrs; up; up = up->next ) {
-                               if ( ad == up->attr ) {
+               if ( uri->attrs ) {
+                       for ( attr = uri->attrs; attr; attr = attr->next ) {
+                               if ( ad == attr->attr ) {
                                        break;
                                }
                        }
-                       if ( !up ) {
+                       if ( ( domain->ignore && attr )
+                            || (!domain->ignore && !attr )) {
                                break;
                        }
                }
@@ -407,43 +886,37 @@ static int count_filter_len(
                                /* note: make room for filter escaping... */
                                ks += ( 3 * b[i].bv_len ) + ad->ad_cname.bv_len + STRLENOF( "(=)" );
                        }
-               } else if ( ud->strict ) {
+               } else if ( domain->strict ) {
                        ks += ad->ad_cname.bv_len + STRLENOF( "(=*)" ); /* (attr=*) */
                }
                break;
        }
+
        return ks;
 }
 
-static char *build_filter(
-       unique_data *ud,
+static char *
+build_filter(
+       unique_domain *domain,
+       unique_domain_uri *uri,
        AttributeDescription *ad,
        BerVarray b,
        char *kp,
        void *ctx
 )
 {
-       unique_attrs *up;
+       unique_attrs *attr;
        int i;
 
        while ( !is_at_operational( ad->ad_type ) ) {
-               if ( ud->ignore ) {
-                       for ( up = ud->ignore; up; up = up->next ) {
-                               if ( ad == up->attr ) {
+               if ( uri->attrs ) {
+                       for ( attr = uri->attrs; attr; attr = attr->next ) {
+                               if ( ad == attr->attr ) {
                                        break;
                                }
                        }
-                       if ( up ) {
-                               break;
-                       }
-               }
-               if ( ud->attrs ) {
-                       for ( up = ud->attrs; up; up = up->next ) {
-                               if ( ad == up->attr ) {
-                                       break;
-                               }
-                       }
-                       if ( !up ) {
+                       if ( ( domain->ignore && attr )
+                            || (!domain->ignore && !attr )) {
                                break;
                        }
                }
@@ -457,7 +930,7 @@ static char *build_filter(
                                        ber_memfree_x( bv.bv_val, ctx );
                                }
                        }
-               } else if ( ud->strict ) {
+               } else if ( domain->strict ) {
                        kp += sprintf( kp, "(%s=*)", ad->ad_cname.bv_val );
                }
                break;
@@ -465,20 +938,24 @@ static char *build_filter(
        return kp;
 }
 
-static int unique_search(
+static int
+unique_search(
        Operation *op,
        Operation *nop,
+       struct berval * dn,
+       int scope,
        SlapReply *rs,
        char *key
 )
 {
        slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
-       unique_data *ud = on->on_bi.bi_private;
        SlapReply nrs = { REP_RESULT };
        slap_callback cb = { NULL, NULL, NULL, NULL }; /* XXX */
        unique_counter uq = { NULL, 0 };
        int rc;
 
+       Debug(LDAP_DEBUG_TRACE, "==> unique_search %s\n", key, 0, 0);
+
        nop->ors_filter = str2filter_x(nop, key);
        ber_str2bv(key, 0, 0, &nop->ors_filterstr);
 
@@ -486,7 +963,7 @@ static int unique_search(
        cb.sc_private   = &uq;
        nop->o_callback = &cb;
        nop->o_tag      = LDAP_REQ_SEARCH;
-       nop->ors_scope  = LDAP_SCOPE_SUBTREE;
+       nop->ors_scope  = scope;
        nop->ors_deref  = LDAP_DEREF_NEVER;
        nop->ors_limit  = NULL;
        nop->ors_slimit = SLAP_NO_LIMIT;
@@ -496,7 +973,7 @@ static int unique_search(
 
        uq.ndn = &op->o_req_ndn;
 
-       nop->o_req_ndn  = ud->dn;
+       nop->o_req_ndn = *dn;
        nop->o_ndn = op->o_bd->be_rootndn;
 
        nop->o_bd = on->on_info->oi_origdb;
@@ -522,182 +999,303 @@ static int unique_search(
        return(SLAP_CB_CONTINUE);
 }
 
-#define ALLOC_EXTRA    16      /* extra slop */
-
-static int unique_add(
+static int
+unique_add(
        Operation *op,
        SlapReply *rs
 )
 {
        slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
-       unique_data *ud = on->on_bi.bi_private;
+       unique_data *private = (unique_data *) on->on_bi.bi_private;
+       unique_domain *domains = private->domains;
+       unique_domain *legacy = private->legacy;
+       unique_domain *domain;
        Operation nop = *op;
-
        Attribute *a;
        char *key, *kp;
-       int ks = 0;
-
-       Debug(LDAP_DEBUG_TRACE, "==> unique_add <%s>\n", op->o_req_dn.bv_val, 0, 0);
-
-       if ( !dnIsSuffix( &op->o_req_ndn, &ud->dn ))
-               return SLAP_CB_CONTINUE;
-
-/*
-** count everything first;
-** allocate some memory;
-** write the search key;
-**
-*/
-
-       if(!(a = op->ora_e->e_attrs)) {
-               op->o_bd->bd_info = (BackendInfo *) on->on_info;
-               send_ldap_error(op, rs, LDAP_INVALID_SYNTAX,
-                       "unique_add() got null op.ora_e.e_attrs");
-               return(rs->sr_err);
-       } else for(; a; a = a->a_next) {
-               ks = count_filter_len(ud, a->a_desc, a->a_vals, ks);
-       }
-
-       if ( !ks )
-               return SLAP_CB_CONTINUE;
-
-       ks += ALLOC_EXTRA;
-       key = op->o_tmpalloc(ks, op->o_tmpmemctx);
+       int rc = SLAP_CB_CONTINUE;
+
+       Debug(LDAP_DEBUG_TRACE, "==> unique_add <%s>\n",
+             op->o_req_dn.bv_val, 0, 0);
+
+       for ( domain = legacy ? legacy : domains;
+             domain;
+             domain = domain->next ) {
+               unique_domain_uri *uri;
+               int ks = 0;
+
+               for ( uri = domain->uri;
+                     uri;
+                     uri = uri->next ) {
+
+                       if ( uri->ndn
+                            && !dnIsSuffix( &op->o_req_ndn, uri->ndn ))
+                               continue;
+
+                       if(!(a = op->ora_e->e_attrs)) {
+                               op->o_bd->bd_info = (BackendInfo *) on->on_info;
+                               send_ldap_error(op, rs, LDAP_INVALID_SYNTAX,
+                                               "unique_add() got null op.ora_e.e_attrs");
+                               rc = rs->sr_err;
+                               break;
 
-       kp = key + sprintf(key, "(|");
+                       } else {
+                               for(; a; a = a->a_next) {
+                                       ks += count_filter_len ( domain,
+                                                                uri,
+                                                                a->a_desc,
+                                                                a->a_vals);
+                               }
+                       }
 
-       for(a = op->ora_e->e_attrs; a; a = a->a_next) {
-               kp = build_filter(ud, a->a_desc, a->a_vals, kp, op->o_tmpmemctx);
+                       /* skip this domain-uri if it isn't involved */
+                       if ( !ks ) continue;
+
+                       if ( uri->filter && uri->filter->bv_len )
+                               ks += uri->filter->bv_len + STRLENOF ("(&)");
+                       kp = key = op->o_tmpalloc(ks, op->o_tmpmemctx);
+
+                       if ( uri->filter && uri->filter->bv_len )
+                               kp += sprintf (kp, "(&%s", uri->filter->bv_val);
+                       kp += sprintf(kp, "(|");
+
+                       for(a = op->ora_e->e_attrs; a; a = a->a_next)
+                               kp = build_filter(domain,
+                                                 uri,
+                                                 a->a_desc,
+                                                 a->a_vals,
+                                                 kp,
+                                                 op->o_tmpmemctx);
+
+                       kp += sprintf(kp, ")");
+                       if ( uri->filter && uri->filter->bv_len )
+                               kp += sprintf (kp, ")");
+
+                       rc = unique_search ( op,
+                                            &nop,
+                                            uri->ndn ?
+                                            uri->ndn :
+                                            &op->o_bd->be_nsuffix[0],
+                                            uri->scope,
+                                            rs,
+                                            key);
+
+                       if ( rc != SLAP_CB_CONTINUE ) break;
+               }
+               if ( rc != SLAP_CB_CONTINUE ) break;
        }
 
-       sprintf(kp, ")");
-
-       Debug(LDAP_DEBUG_TRACE, "=> unique_add %s\n", key, 0, 0);
-
-       return unique_search(op, &nop, rs, key);
+       return rc;
 }
 
 
-static int unique_modify(
+static int
+unique_modify(
        Operation *op,
        SlapReply *rs
 )
 {
        slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
-       unique_data *ud = on->on_bi.bi_private;
+       unique_data *private = (unique_data *) on->on_bi.bi_private;
+       unique_domain *domains = private->domains;
+       unique_domain *legacy = private->legacy;
+       unique_domain *domain;
        Operation nop = *op;
-
        Modifications *m;
        char *key, *kp;
-       int ks = 0;
-
-       Debug(LDAP_DEBUG_TRACE, "==> unique_modify <%s>\n", op->o_req_dn.bv_val, 0, 0);
-
-       if ( !dnIsSuffix( &op->o_req_ndn, &ud->dn ))
-               return SLAP_CB_CONTINUE;
-
-/*
-** count everything first;
-** allocate some memory;
-** write the search key;
-**
-*/
-
-       if(!(m = op->orm_modlist)) {
-               op->o_bd->bd_info = (BackendInfo *) on->on_info;
-               send_ldap_error(op, rs, LDAP_INVALID_SYNTAX,
-                       "unique_modify() got null op.orm_modlist");
-               return(rs->sr_err);
-       } else for(; m; m = m->sml_next) {
-               if ((m->sml_op & LDAP_MOD_OP) == LDAP_MOD_DELETE) continue;
-               ks = count_filter_len(ud, m->sml_desc, m->sml_values, ks);
-       }
-
-       if ( !ks )
-               return SLAP_CB_CONTINUE;
-
-       ks += ALLOC_EXTRA;
-       key = op->o_tmpalloc(ks, op->o_tmpmemctx);
-
-       kp = key + sprintf(key, "(|");
+       int rc = SLAP_CB_CONTINUE;
+
+       Debug(LDAP_DEBUG_TRACE, "==> unique_modify <%s>\n",
+             op->o_req_dn.bv_val, 0, 0);
+
+       for ( domain = legacy ? legacy : domains;
+             domain;
+             domain = domain->next ) {
+               unique_domain_uri *uri;
+               int ks = 0;
+
+               for ( uri = domain->uri;
+                     uri;
+                     uri = uri->next ) {
+
+                       if ( uri->ndn
+                            && !dnIsSuffix( &op->o_req_ndn, uri->ndn ))
+                               continue;
+
+                       if ( !(m = op->orm_modlist) ) {
+                               op->o_bd->bd_info = (BackendInfo *) on->on_info;
+                               send_ldap_error(op, rs, LDAP_INVALID_SYNTAX,
+                                               "unique_modify() got null op.orm_modlist");
+                               rc = rs->sr_err;
+                               break;
 
-       for(m = op->orm_modlist; m; m = m->sml_next) {
-               if ((m->sml_op & LDAP_MOD_OP) == LDAP_MOD_DELETE) continue;
-               kp = build_filter(ud, m->sml_desc, m->sml_values, kp, op->o_tmpmemctx);
+                       } else
+                               for ( ; m; m = m->sml_next)
+                                       if ( (m->sml_op & LDAP_MOD_OP)
+                                            != LDAP_MOD_DELETE )
+                                               ks += count_filter_len
+                                                       ( domain,
+                                                         uri,
+                                                         m->sml_desc,
+                                                         m->sml_values);
+
+                       /* skip this domain-uri if it isn't involved */
+                       if ( !ks ) continue;
+
+                       if ( uri->filter && uri->filter->bv_len )
+                               ks += uri->filter->bv_len + STRLENOF ("(&)");
+                       kp = key = op->o_tmpalloc(ks, op->o_tmpmemctx);
+
+                       if ( uri->filter && uri->filter->bv_len )
+                               kp += sprintf (kp, "(&%s", uri->filter->bv_val);
+                       kp += sprintf(kp, "(|");
+
+                       for(m = op->orm_modlist; m; m = m->sml_next)
+                               if ( (m->sml_op & LDAP_MOD_OP)
+                                    != LDAP_MOD_DELETE )
+                                       kp = build_filter ( domain,
+                                                           uri,
+                                                           m->sml_desc,
+                                                           m->sml_values,
+                                                           kp,
+                                                           op->o_tmpmemctx );
+
+                       kp += sprintf (kp, ")");
+                       if ( uri->filter && uri->filter->bv_len )
+                               kp += sprintf (kp, ")");
+
+                       rc = unique_search ( op,
+                                            &nop,
+                                            uri->ndn ?
+                                            uri->ndn :
+                                            &op->o_bd->be_nsuffix[0],
+                                            uri->scope,
+                                            rs,
+                                            key);
+
+                       if ( rc != SLAP_CB_CONTINUE ) break;
+               }
+               if ( rc != SLAP_CB_CONTINUE ) break;
        }
 
-       sprintf(kp, ")");
-
-       Debug(LDAP_DEBUG_TRACE, "=> unique_modify %s\n", key, 0, 0);
-
-       return unique_search(op, &nop, rs, key);
+       return rc;
 }
 
 
-static int unique_modrdn(
+static int
+unique_modrdn(
        Operation *op,
        SlapReply *rs
 )
 {
        slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
-       unique_data *ud = on->on_bi.bi_private;
+       unique_data *private = (unique_data *) on->on_bi.bi_private;
+       unique_domain *domains = private->domains;
+       unique_domain *legacy = private->legacy;
+       unique_domain *domain;
        Operation nop = *op;
-
        char *key, *kp;
-       int i, ks = 0;
        LDAPRDN newrdn;
        struct berval bv[2];
+       int rc = SLAP_CB_CONTINUE;
 
        Debug(LDAP_DEBUG_TRACE, "==> unique_modrdn <%s> <%s>\n",
                op->o_req_dn.bv_val, op->orr_newrdn.bv_val, 0);
 
-       if ( !dnIsSuffix( &op->o_req_ndn, &ud->dn ) && 
-               (!op->orr_nnewSup || !dnIsSuffix( op->orr_nnewSup, &ud->dn )))
-               return SLAP_CB_CONTINUE;
-
-       if(ldap_bv2rdn_x(&op->oq_modrdn.rs_newrdn, &newrdn,
-               (char **)&rs->sr_text, LDAP_DN_FORMAT_LDAP, op->o_tmpmemctx )) {
-               op->o_bd->bd_info = (BackendInfo *) on->on_info;
-               send_ldap_error(op, rs, LDAP_INVALID_SYNTAX,
-                       "unknown type(s) used in RDN");
-               return(rs->sr_err);
-       }
-       for(i = 0; newrdn[i]; i++) {
-               AttributeDescription *ad = NULL;
-               if ( slap_bv2ad( &newrdn[i]->la_attr, &ad, &rs->sr_text )) {
-                       ldap_rdnfree_x( newrdn, op->o_tmpmemctx );
-                       rs->sr_err = LDAP_INVALID_SYNTAX;
-                       send_ldap_result( op, rs );
-                       return(rs->sr_err);
-               }
-               newrdn[i]->la_private = ad;
-       }
+       for ( domain = legacy ? legacy : domains;
+             domain;
+             domain = domain->next ) {
+               unique_domain_uri *uri;
+               int ks = 0;
+
+               for ( uri = domain->uri;
+                     uri;
+                     uri = uri->next ) {
+                       int i;
+
+                       if ( uri->ndn
+                            && !dnIsSuffix( &op->o_req_ndn, uri->ndn )
+                            && (!op->orr_nnewSup
+                                || !dnIsSuffix( op->orr_nnewSup, uri->ndn )))
+                               continue;
+
+                       if ( ldap_bv2rdn_x ( &op->oq_modrdn.rs_newrdn,
+                                            &newrdn,
+                                            (char **)&rs->sr_text,
+                                            LDAP_DN_FORMAT_LDAP,
+                                            op->o_tmpmemctx ) ) {
+                               op->o_bd->bd_info = (BackendInfo *) on->on_info;
+                               send_ldap_error(op, rs, LDAP_INVALID_SYNTAX,
+                                               "unknown type(s) used in RDN");
+                               rc = rs->sr_err;
+                               break;
+                       }
 
-       bv[1].bv_val = NULL;
-       bv[1].bv_len = 0;
+                       rc = SLAP_CB_CONTINUE;
+                       for ( i=0; newrdn[i]; i++) {
+                               AttributeDescription *ad = NULL;
+                               if ( slap_bv2ad( &newrdn[i]->la_attr, &ad, &rs->sr_text )) {
+                                       ldap_rdnfree_x( newrdn, op->o_tmpmemctx );
+                                       rs->sr_err = LDAP_INVALID_SYNTAX;
+                                       send_ldap_result( op, rs );
+                                       rc = rs->sr_err;
+                                       break;
+                               }
+                               newrdn[i]->la_private = ad;
+                       }
+                       if ( rc != SLAP_CB_CONTINUE ) break;
 
-       for(i = 0; newrdn[i]; i++) {
-               bv[0] = newrdn[i]->la_value;
-               ks = count_filter_len(ud, newrdn[i]->la_private, bv, ks);
-       }
+                       bv[1].bv_val = NULL;
+                       bv[1].bv_len = 0;
 
-       if ( !ks )
-               return SLAP_CB_CONTINUE;
+                       for ( i=0; newrdn[i]; i++ ) {
+                               bv[0] = newrdn[i]->la_value;
+                               ks += count_filter_len ( domain,
+                                                        uri,
+                                                        newrdn[i]->la_private,
+                                                        bv);
+                       }
 
-       ks += ALLOC_EXTRA;
-       key = op->o_tmpalloc(ks, op->o_tmpmemctx);
-       kp = key + sprintf(key, "(|");
+                       /* skip this domain if it isn't involved */
+                       if ( !ks ) continue;
+
+                       if ( uri->filter && uri->filter->bv_len )
+                               ks += uri->filter->bv_len + STRLENOF ("(&)");
+                       kp = key = op->o_tmpalloc(ks, op->o_tmpmemctx);
+
+                       if ( uri->filter && uri->filter->bv_len )
+                               kp += sprintf (kp, "(&%s", uri->filter->bv_val);
+                       kp += sprintf(kp, "(|");
+
+                       for ( i=0; newrdn[i]; i++) {
+                               bv[0] = newrdn[i]->la_value;
+                               kp = build_filter ( domain,
+                                                   uri,
+                                                   newrdn[i]->la_private,
+                                                   bv,
+                                                   kp,
+                                                   op->o_tmpmemctx);
+                       }
 
-       for(i = 0; newrdn[i]; i++) {
-               bv[0] = newrdn[i]->la_value;
-               kp = build_filter(ud, newrdn[i]->la_private, bv, kp, op->o_tmpmemctx);
-       }
+                       kp += sprintf(kp, ")");
+                       if ( uri->filter && uri->filter->bv_len )
+                               kp += sprintf (kp, ")");
 
-       sprintf(kp, ")");
+                       rc = unique_search ( op,
+                                            &nop,
+                                            uri->ndn ?
+                                            uri->ndn :
+                                            &op->o_bd->be_nsuffix[0],
+                                            uri->scope,
+                                            rs,
+                                            key);
 
-       Debug(LDAP_DEBUG_TRACE, "=> unique_modrdn %s\n", key, 0, 0);
+                       if ( rc != SLAP_CB_CONTINUE ) break;
+               }
+               if ( rc != SLAP_CB_CONTINUE ) break;
+       }
 
-       return unique_search(op, &nop, rs, key);
+       return rc;
 }
 
 /*
@@ -705,10 +1303,14 @@ static int unique_modrdn(
 ** it expects to be called automagically during dynamic module initialization
 */
 
-int unique_initialize() {
+int
+unique_initialize()
+{
        int rc;
 
        /* statically declared just after the #includes at top */
+       memset (&unique, 0, sizeof(unique));
+
        unique.on_bi.bi_type = "unique";
        unique.on_bi.bi_db_init = unique_db_init;
        unique.on_bi.bi_db_destroy = unique_db_destroy;
@@ -717,7 +1319,6 @@ int unique_initialize() {
        unique.on_bi.bi_op_add = unique_add;
        unique.on_bi.bi_op_modify = unique_modify;
        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 );
index b089a7189974e2cfd50423de36ea7c217811a488..5950a208c40b4e09a960901f360fcddbf3ddc2ee 100644 (file)
@@ -152,16 +152,16 @@ valsort_cf_func(ConfigArgs *c) {
        vitmp.vi_ad = NULL;
        i = slap_str2ad( c->argv[1], &vitmp.vi_ad, &text );
        if ( i ) {
-               sprintf( c->msg, "<%s> %s", c->argv[0], text );
+               sprintf( c->cr_msg, "<%s> %s", c->argv[0], text );
                Debug( LDAP_DEBUG_ANY, "%s: %s (%s)!\n",
-                       c->log, c->msg, c->argv[1] );
+                       c->log, c->cr_msg, c->argv[1] );
                return(1);
        }
        if ( is_at_single_value( vitmp.vi_ad->ad_type )) {
-               sprintf( c->msg, "<%s> %s is single-valued, ignoring", c->argv[0],
+               sprintf( c->cr_msg, "<%s> %s is single-valued, ignoring", c->argv[0],
                        vitmp.vi_ad->ad_cname.bv_val );
                Debug( LDAP_DEBUG_ANY, "%s: %s (%s)!\n",
-                       c->log, c->msg, c->argv[1] );
+                       c->log, c->cr_msg, c->argv[1] );
                return(0);
        }
        is_numeric = ( vitmp.vi_ad->ad_type->sat_syntax == syn_numericString ||
@@ -170,34 +170,34 @@ valsort_cf_func(ConfigArgs *c) {
        ber_str2bv( c->argv[2], 0, 0, &bv );
        i = dnNormalize( 0, NULL, NULL, &bv, &vitmp.vi_dn, NULL );
        if ( i ) {
-               sprintf( c->msg, "<%s> unable to normalize DN", c->argv[0] );
+               sprintf( c->cr_msg, "<%s> unable to normalize DN", c->argv[0] );
                Debug( LDAP_DEBUG_ANY, "%s: %s (%s)!\n",
-                       c->log, c->msg, c->argv[2] );
+                       c->log, c->cr_msg, c->argv[2] );
                return(1);
        }
        i = verb_to_mask( c->argv[3], sorts );
        if ( BER_BVISNULL( &sorts[i].word )) {
-               sprintf( c->msg, "<%s> unrecognized sort type", c->argv[0] );
+               sprintf( c->cr_msg, "<%s> unrecognized sort type", c->argv[0] );
                Debug( LDAP_DEBUG_ANY, "%s: %s (%s)!\n",
-                       c->log, c->msg, c->argv[3] );
+                       c->log, c->cr_msg, c->argv[3] );
                return(1);
        }
        vitmp.vi_sort = sorts[i].mask;
        if ( sorts[i].mask == VALSORT_WEIGHTED && c->argc == 5 ) {
                i = verb_to_mask( c->argv[4], sorts );
                if ( BER_BVISNULL( &sorts[i].word )) {
-                       sprintf( c->msg, "<%s> unrecognized sort type", c->argv[0] );
+                       sprintf( c->cr_msg, "<%s> unrecognized sort type", c->argv[0] );
                        Debug( LDAP_DEBUG_ANY, "%s: %s (%s)!\n",
-                               c->log, c->msg, c->argv[4] );
+                               c->log, c->cr_msg, c->argv[4] );
                        return(1);
                }
                vitmp.vi_sort |= sorts[i].mask;
        }
        if (( vitmp.vi_sort & VALSORT_NUMERIC ) && !is_numeric ) {
-               sprintf( c->msg, "<%s> numeric sort specified for non-numeric syntax",
+               sprintf( c->cr_msg, "<%s> numeric sort specified for non-numeric syntax",
                        c->argv[0] );
                Debug( LDAP_DEBUG_ANY, "%s: %s (%s)!\n",
-                       c->log, c->msg, c->argv[1] );
+                       c->log, c->cr_msg, c->argv[1] );
                return(1);
        }
        vi = ch_malloc( sizeof(valsort_info) );
@@ -447,6 +447,9 @@ valsort_modify( Operation *op, SlapReply *rs )
                if ( !(vi->vi_sort & VALSORT_WEIGHTED ))
                        continue;
                for (ml = op->orm_modlist; ml; ml=ml->sml_next ) {
+                       /* Must be a Delete Attr op, so no values to consider */
+                       if ( !ml->sml_values )
+                               continue;
                        if ( ml->sml_desc == vi->vi_ad )
                                break;
                }
@@ -476,7 +479,8 @@ valsort_modify( Operation *op, SlapReply *rs )
 
 static int
 valsort_db_open(
-       BackendDB *be
+       BackendDB *be,
+       ConfigReply *cr
 )
 {
        return overlay_register_control( be, LDAP_CONTROL_VALSORT );
@@ -484,7 +488,8 @@ valsort_db_open(
 
 static int
 valsort_destroy(
-       BackendDB *be
+       BackendDB *be,
+       ConfigReply *cr
 )
 {
        slap_overinst *on = (slap_overinst *)be->bd_info;
@@ -510,8 +515,13 @@ valsort_parseCtrl(
        BerElement *ber = (BerElement *)&berbuf;
        ber_int_t flag = 0;
 
-       if ( ctrl->ldctl_value.bv_len == 0 ) {
-               rs->sr_text = "valSort control value is empty (or absent)";
+       if ( BER_BVISNULL( &ctrl->ldctl_value )) {
+               rs->sr_text = "valSort control value is absent";
+               return LDAP_PROTOCOL_ERROR;
+       }
+
+       if ( BER_BVISEMPTY( &ctrl->ldctl_value )) {
+               rs->sr_text = "valSort control value is empty";
                return LDAP_PROTOCOL_ERROR;
        }
 
index 327de020e045e2217832e45791be01459a74ce83..a08bbba4b21f08e5107d4924d193569564ca29fa 100644 (file)
@@ -52,15 +52,12 @@ int passwd_extop(
        req_extended_s qext = op->oq_extended;
        Modifications *ml;
        slap_callback cb = { NULL, slap_null_cb, NULL, NULL };
-       slap_callback cb2 = { NULL, slap_replog_cb, NULL, NULL };
        int i, nhash;
        char **hashes;
        int rc;
        BackendDB *op_be;
        int freenewpw = 0;
 
-       cb2.sc_next = &cb;
-
        assert( ber_bvcmp( &slap_EXOP_MODIFY_PASSWD, &op->ore_reqoid ) == 0 );
 
        if( op->o_dn.bv_len == 0 ) {
@@ -104,7 +101,7 @@ int passwd_extop(
                        rc = rs->sr_err;
                        goto error_return;
                }
-               op->o_bd = select_backend( &op->o_req_ndn, 0, 1 );
+               op->o_bd = select_backend( &op->o_req_ndn, 1 );
 
        } else {
                ber_dupbv_x( &op->o_req_dn, &op->o_dn, op->o_tmpmemctx );
@@ -139,7 +136,7 @@ int passwd_extop(
        /* If we've got a glued backend, check the real backend */
        op_be = op->o_bd;
        if ( SLAP_GLUE_INSTANCE( op->o_bd )) {
-               op->o_bd = select_backend( &op->o_req_ndn, 0, 0 );
+               op->o_bd = select_backend( &op->o_req_ndn, 0 );
        }
 
        if (backend_check_restrictions( op, rs,
@@ -275,9 +272,11 @@ old_good:
                slap_callback *sc = op->o_callback;
 
                op->o_tag = LDAP_REQ_MODIFY;
-               op->o_callback = &cb2;
+               op->o_callback = &cb;
                op->orm_modlist = qpw->rs_mods;
-               cb2.sc_private = qpw;   /* let Modify know this was pwdMod,
+               op->orm_no_opattrs = 0;
+               
+               cb.sc_private = qpw;    /* let Modify know this was pwdMod,
                                         * if it cares... */
 
                rs->sr_err = op->o_bd->be_modify( op, rs );
index eb1d6d795d2b0e02050b21f57c1171b11db53d40..e3fae5ded0462e31926b9080827a54058f1be69b 100644 (file)
@@ -32,6 +32,7 @@
 LDAP_BEGIN_DECL
 
 struct config_args_s;  /* config.h */
+struct config_reply_s; /* config.h */
 
 /*
  * aci.c
@@ -167,6 +168,9 @@ LDAP_SLAPD_F (AttributeDescription *) ad_find_tags LDAP_P((
 
 LDAP_SLAPD_F (AttributeName *) str2anlist LDAP_P(( AttributeName *an,
        char *str, const char *brkstr ));
+LDAP_SLAPD_F (void) anlist_free LDAP_P(( AttributeName *an,
+       int freename, void *ctx ));
+
 LDAP_SLAPD_F (char **) anlist2charray_x LDAP_P((
                                                                        AttributeName *an, int dup, void *ctx ));
 LDAP_SLAPD_F (char **) anlist2charray LDAP_P(( AttributeName *an, int dup ));
@@ -320,7 +324,7 @@ LDAP_SLAPD_F (int) backend_init LDAP_P((void));
 LDAP_SLAPD_F (int) backend_add LDAP_P((BackendInfo *aBackendInfo));
 LDAP_SLAPD_F (int) backend_num LDAP_P((Backend *be));
 LDAP_SLAPD_F (int) backend_startup LDAP_P((Backend *be));
-LDAP_SLAPD_F (int) backend_startup_one LDAP_P((Backend *be));
+LDAP_SLAPD_F (int) backend_startup_one LDAP_P((Backend *be, struct config_reply_s *cr));
 LDAP_SLAPD_F (int) backend_sync LDAP_P((Backend *be));
 LDAP_SLAPD_F (int) backend_shutdown LDAP_P((Backend *be));
 LDAP_SLAPD_F (int) backend_destroy LDAP_P((void));
@@ -329,26 +333,28 @@ LDAP_SLAPD_F (void) backend_destroy_one LDAP_P((BackendDB *bd, int dynamic));
 
 LDAP_SLAPD_F (BackendInfo *) backend_info LDAP_P(( const char *type ));
 LDAP_SLAPD_F (BackendDB *) backend_db_init LDAP_P(( const char *type,
-       BackendDB *be, int idx ));
+       BackendDB *be, int idx, struct config_reply_s *cr ));
 LDAP_SLAPD_F (void) backend_db_insert LDAP_P((BackendDB *bd, int idx));
 LDAP_SLAPD_F (void) backend_db_move LDAP_P((BackendDB *bd, int idx));
 
 LDAP_SLAPD_F (BackendDB *) select_backend LDAP_P((
        struct berval * dn,
-       int manageDSAit,
        int noSubordinates ));
 
 LDAP_SLAPD_F (int) be_issuffix LDAP_P(( Backend *be,
        struct berval *suffix ));
+LDAP_SLAPD_F (int) be_issubordinate LDAP_P(( Backend *be,
+       struct berval *subordinate ));
 LDAP_SLAPD_F (int) be_isroot LDAP_P(( Operation *op ));
 LDAP_SLAPD_F (int) be_isroot_dn LDAP_P(( Backend *be, struct berval *ndn ));
 LDAP_SLAPD_F (int) be_isroot_pw LDAP_P(( Operation *op ));
+LDAP_SLAPD_F (int) be_rootdn_bind LDAP_P(( Operation *op, SlapReply *rs ));
 LDAP_SLAPD_F (int) be_slurp_update LDAP_P(( Operation *op ));
 #define be_isupdate( op ) be_slurp_update( (op) )
 LDAP_SLAPD_F (int) be_shadow_update LDAP_P(( Operation *op ));
 LDAP_SLAPD_F (int) be_isupdate_dn LDAP_P(( Backend *be, struct berval *ndn ));
 LDAP_SLAPD_F (struct berval *) be_root_dn LDAP_P(( Backend *be ));
-LDAP_SLAPD_F (int) be_entry_get_rw LDAP_P(( struct slap_op *o,
+LDAP_SLAPD_F (int) be_entry_get_rw LDAP_P(( Operation *o,
                struct berval *ndn, ObjectClass *oc,
                AttributeDescription *at, int rw, Entry **e ));
 LDAP_SLAPD_F (int) be_entry_release_rw LDAP_P((
@@ -626,6 +632,20 @@ LDAP_SLAPD_F (int) slap_remove_control LDAP_P((
        int             ctrl,
        BI_chk_controls fnc ));
 
+#ifdef SLAP_CONTROL_X_SESSION_TRACKING
+LDAP_SLAPD_F (int)
+slap_ctrl_session_tracking_add LDAP_P((
+       Operation *op,
+       SlapReply *rs,
+       struct berval *ip,
+       struct berval *name,
+       struct berval *id,
+       LDAPControl *ctrl ));
+LDAP_SLAPD_F (int)
+slap_ctrl_session_tracking_request_add LDAP_P((
+       Operation *op, SlapReply *rs, LDAPControl *ctrl ));
+#endif /* SLAP_CONTROL_X_SESSION_TRACKING */
+
 /*
  * config.c
  */
@@ -685,15 +705,21 @@ LDAP_SLAPD_F (int) connection_client_setup LDAP_P((
 LDAP_SLAPD_F (void) connection_client_enable LDAP_P(( ber_socket_t s ));
 LDAP_SLAPD_F (void) connection_client_stop LDAP_P(( ber_socket_t s ));
 
+#ifdef LDAP_PF_LOCAL_SENDMSG
+#define LDAP_PF_LOCAL_SENDMSG_ARG(arg) , arg
+#else
+#define LDAP_PF_LOCAL_SENDMSG_ARG(arg)
+#endif
 
-LDAP_SLAPD_F (long) connection_init LDAP_P((
+LDAP_SLAPD_F (Connection *) connection_init LDAP_P((
        ber_socket_t s,
        Listener* url,
        const char* dnsname,
        const char* peername,
        int use_tls,
        slap_ssf_t ssf,
-       struct berval *id ));
+       struct berval *id
+       LDAP_PF_LOCAL_SENDMSG_ARG(struct berval *peerbv)));
 
 LDAP_SLAPD_F (void) connection_closing LDAP_P((
        Connection *c, const char *why ));
@@ -718,11 +744,11 @@ LDAP_SLAPD_F (void) connection_done LDAP_P((Connection *));
 LDAP_SLAPD_F (void) connection2anonymous LDAP_P((Connection *));
 LDAP_SLAPD_F (void) connection_fake_init LDAP_P((
        Connection *conn,
-       Operation *op,
+       OperationBuffer *opbuf,
        void *threadctx ));
 LDAP_SLAPD_F (void) connection_fake_init2 LDAP_P((
        Connection *conn,
-       Operation *op,
+       OperationBuffer *opbuf,
        void *threadctx,
        int newmem ));
 LDAP_SLAPD_F (void) connection_assign_nextid LDAP_P((Connection *));
@@ -772,8 +798,8 @@ LDAP_SLAPD_F (int) slapd_daemon(void);
 LDAP_SLAPD_F (Listener **)     slapd_get_listeners LDAP_P((void));
 LDAP_SLAPD_F (void) slapd_remove LDAP_P((ber_socket_t s, Sockbuf *sb,
        int wasactive, int wake, int locked ));
-LDAP_SLAPD_F (void) slapd_sd_lock();
-LDAP_SLAPD_F (void) slapd_sd_unlock();
+LDAP_SLAPD_F (void) slapd_sd_lock LDAP_P((void));
+LDAP_SLAPD_F (void) slapd_sd_unlock LDAP_P((void));
 
 LDAP_SLAPD_F (RETSIGTYPE) slap_sig_shutdown LDAP_P((int sig));
 LDAP_SLAPD_F (RETSIGTYPE) slap_sig_wake LDAP_P((int sig));
@@ -1215,11 +1241,17 @@ LDAP_SLAPD_F (int) register_matching_rule LDAP_P((
 LDAP_SLAPD_F (void) mru_destroy LDAP_P(( void ));
 LDAP_SLAPD_F (int) matching_rule_use_init LDAP_P(( void ));
 
-LDAP_SLAPD_F (int) mr_schema_info( Entry *e );
-LDAP_SLAPD_F (int) mru_schema_info( Entry *e );
+LDAP_SLAPD_F (int) mr_schema_info LDAP_P(( Entry *e ));
+LDAP_SLAPD_F (int) mru_schema_info LDAP_P(( Entry *e ));
 
-LDAP_SLAPD_F (int) mr_usable_with_at( MatchingRule *mr,
-       AttributeType *at );
+LDAP_SLAPD_F (int) mr_usable_with_at LDAP_P(( MatchingRule *mr,
+       AttributeType *at ));
+LDAP_SLAPD_F (int) mr_make_syntax_compat_with_mr LDAP_P((
+       Syntax          *syn,
+       MatchingRule    *mr ));
+LDAP_SLAPD_F (int) mr_make_syntax_compat_with_mrs LDAP_P((
+       const char *syntax,
+       char *const *mrs ));
 
 /*
  * mra.c
@@ -1406,18 +1438,6 @@ LDAP_SLAPD_F (int) get_alias_dn LDAP_P((
        int *err,
        const char **text ));
 
-/*
- * repl.c
- */
-LDAP_SLAPD_F (int) add_replica_info LDAP_P(( Backend *be,
-       const char *uri, const char *host ));
-LDAP_SLAPD_F (int) destroy_replica_info LDAP_P (( Backend *be ));
-LDAP_SLAPD_F (int) add_replica_suffix LDAP_P(( Backend *be,
-       int nr, const char *suffix ));
-LDAP_SLAPD_F (int) add_replica_attrs LDAP_P(( Backend *be,
-       int nr, char *attrs, int exclude ));
-LDAP_SLAPD_F (void) replog LDAP_P(( Operation *op ));
-
 /*
  * result.c
  */
@@ -1431,7 +1451,6 @@ LDAP_SLAPD_F (int) slap_send_search_reference LDAP_P(( Operation *op, SlapReply
 LDAP_SLAPD_F (int) slap_send_search_entry LDAP_P(( Operation *op, SlapReply *rs ));
 LDAP_SLAPD_F (int) slap_null_cb LDAP_P(( Operation *op, SlapReply *rs ));
 LDAP_SLAPD_F (int) slap_freeself_cb LDAP_P(( Operation *op, SlapReply *rs ));
-LDAP_SLAPD_F (int) slap_replog_cb LDAP_P(( Operation *op, SlapReply *rs ));
 
 LDAP_SLAPD_V( const struct berval ) slap_pre_read_bv;
 LDAP_SLAPD_V( const struct berval ) slap_post_read_bv;
@@ -1600,8 +1619,11 @@ LDAP_SLAPD_F( slap_mr_indexer_func ) octetStringIndexer;
 LDAP_SLAPD_F( slap_mr_filter_func ) octetStringFilter;
 
 LDAP_SLAPD_F( int ) numericoidValidate LDAP_P((
-       struct slap_syntax *syntax,
+       Syntax *syntax,
         struct berval *in ));
+LDAP_SLAPD_F( int ) numericStringValidate LDAP_P((
+       Syntax *syntax,
+       struct berval *in ));
 LDAP_SLAPD_F( int ) octetStringMatch LDAP_P((
        int *matchp,
        slap_mask_t flags,
@@ -1609,6 +1631,13 @@ LDAP_SLAPD_F( int ) octetStringMatch LDAP_P((
        MatchingRule *mr,
        struct berval *value,
        void *assertedValue ));
+LDAP_SLAPD_F( int ) octetStringOrderingMatch LDAP_P((
+       int *matchp,
+       slap_mask_t flags,
+       Syntax *syntax,
+       MatchingRule *mr,
+       struct berval *value,
+       void *assertedValue ));
 
 /*
  * schema_prep.c
@@ -1681,6 +1710,9 @@ LDAP_SLAPD_F (int)  syncrepl_add_glue LDAP_P((
 LDAP_SLAPD_F (void) syncinfo_free LDAP_P(( struct syncinfo_s *, int all ));
 
 /* syntax.c */
+LDAP_SLAPD_F (int) syn_is_sup LDAP_P((
+       Syntax *syn,
+       Syntax *sup ));
 LDAP_SLAPD_F (Syntax *) syn_find LDAP_P((
        const char *synname ));
 LDAP_SLAPD_F (Syntax *) syn_find_desc LDAP_P((
@@ -1850,7 +1882,6 @@ LDAP_SLAPD_V (int)                        connection_pool_max;
 LDAP_SLAPD_V (int)                     slap_tool_thread_max;
 
 LDAP_SLAPD_V (ldap_pvt_thread_mutex_t) entry2str_mutex;
-LDAP_SLAPD_V (ldap_pvt_thread_mutex_t) replog_mutex;
 
 LDAP_SLAPD_V (ldap_pvt_thread_mutex_t) gmtime_mutex;
 
@@ -1960,11 +1991,11 @@ LDAP_SLAPD_F (int) fe_access_allowed LDAP_P((
        } while ( 0 )
 
 #else
-# if USE_MP_LONG_LONG
+# ifdef USE_MP_LONG_LONG
 #  define UI2BV_FORMAT "%llu"
-# elif USE_MP_LONG
+# elif defined USE_MP_LONG
 #  define UI2BV_FORMAT "%lu"
-# elif HAVE_LONG_LONG
+# elif defined HAVE_LONG_LONG
 #  define UI2BV_FORMAT "%llu"
 # else
 #  define UI2BV_FORMAT "%lu"
diff --git a/servers/slapd/repl.c b/servers/slapd/repl.c
deleted file mode 100644 (file)
index 2809772..0000000
+++ /dev/null
@@ -1,555 +0,0 @@
-/* repl.c - log modifications for replication purposes */
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 1998-2007 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>.
- */
-/* Portions Copyright (c) 1995 Regents of the University of Michigan.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that this notice is preserved and that due credit is given
- * to the University of Michigan at Ann Arbor. The name of the University
- * may not be used to endorse or promote products derived from this
- * software without specific prior written permission. This software
- * is provided ``as is'' without express or implied warranty.
- */
-
-#include "portable.h"
-
-#include <stdio.h>
-
-#include <ac/string.h>
-#include <ac/ctype.h>
-#include <ac/socket.h>
-
-#ifdef HAVE_SYS_FILE_H
-#include <sys/file.h>
-#endif
-
-#include "slap.h"
-#include "ldif.h"
-
-int
-add_replica_info(
-       Backend         *be,
-       const char      *uri, 
-       const char      *host )
-{
-       int i = 0;
-
-       assert( be != NULL );
-       assert( host != NULL );
-
-       if ( be->be_replica != NULL ) {
-               for ( ; be->be_replica[ i ] != NULL; i++ );
-       }
-               
-       be->be_replica = ch_realloc( be->be_replica, 
-               sizeof( struct slap_replica_info * )*( i + 2 ) );
-
-       be->be_replica[ i ] 
-               = ch_calloc( sizeof( struct slap_replica_info ), 1 );
-       ber_str2bv( uri, 0, 0, &be->be_replica[ i ]->ri_bindconf.sb_uri );
-       be->be_replica[ i ]->ri_host = host;
-       be->be_replica[ i ]->ri_nsuffix = NULL;
-       be->be_replica[ i ]->ri_attrs = NULL;
-       be->be_replica[ i + 1 ] = NULL;
-
-       return( i );
-}
-
-int
-destroy_replica_info(
-       Backend         *be )
-{
-       int i = 0;
-
-       assert( be != NULL );
-
-       if ( be->be_replica == NULL ) {
-               return 0;
-       }
-
-       for ( ; be->be_replica[ i ] != NULL; i++ ) {
-               ber_bvarray_free( be->be_replica[ i ]->ri_nsuffix );
-
-               if ( be->be_replica[ i ]->ri_attrs ) {
-                       AttributeName   *an = be->be_replica[ i ]->ri_attrs;
-                       int             j;
-
-                       for ( j = 0; !BER_BVISNULL( &an[ j ].an_name ); j++ )
-                       {
-                               ch_free( an[ j ].an_name.bv_val );
-                       }
-                       ch_free( an );
-               }
-
-               bindconf_free( &be->be_replica[ i ]->ri_bindconf );
-
-               ch_free( be->be_replica[ i ] );
-       }
-
-       ch_free( be->be_replica );
-
-       return 0;
-}
-
-int
-add_replica_suffix(
-    Backend     *be,
-    int                nr,
-    const char  *suffix
-)
-{
-       struct berval dn, ndn;
-       int rc;
-
-       dn.bv_val = (char *) suffix;
-       dn.bv_len = strlen( dn.bv_val );
-
-       rc = dnNormalize( 0, NULL, NULL, &dn, &ndn, NULL );
-       if( rc != LDAP_SUCCESS ) {
-               return 2;
-       }
-
-       if ( select_backend( &ndn, 0, 0 ) != be ) {
-               free( ndn.bv_val );
-               return 1;
-       }
-
-       ber_bvarray_add( &be->be_replica[nr]->ri_nsuffix, &ndn );
-       return 0;
-}
-
-int
-add_replica_attrs(
-       Backend *be,
-       int     nr,
-       char    *attrs,
-       int     exclude
-)
-{
-       if ( be->be_replica[nr]->ri_attrs != NULL ) {
-               if ( be->be_replica[nr]->ri_exclude != exclude ) {
-                       fprintf( stderr, "attr selective replication directive '%s' conflicts with previous one (discarded)\n", attrs );
-                       ch_free( be->be_replica[nr]->ri_attrs );
-                       be->be_replica[nr]->ri_attrs = NULL;
-               }
-       }
-
-       be->be_replica[nr]->ri_exclude = exclude;
-       be->be_replica[nr]->ri_attrs = str2anlist( be->be_replica[nr]->ri_attrs,
-               attrs, "," );
-       return ( be->be_replica[nr]->ri_attrs == NULL );
-}
-   
-static void
-print_vals( FILE *fp, struct berval *type, struct berval *bv );
-static void
-replog1( struct slap_replica_info *ri, Operation *op, FILE *fp, long now);
-
-void
-replog( Operation *op )
-{
-       FILE    *fp, *lfp;
-       int     i;
-/* undef NO_LOG_WHEN_NO_REPLICAS */
-#ifdef NO_LOG_WHEN_NO_REPLICAS
-       int     count = 0;
-#endif /* NO_LOG_WHEN_NO_REPLICAS */
-       int     subsets = 0;
-       long    now = slap_get_time();
-       char    *replogfile;
-
-       replogfile = op->o_bd->be_replogfile ? op->o_bd->be_replogfile :
-               frontendDB->be_replogfile;
-       if ( !replogfile ) {
-               return;
-       }
-
-       ldap_pvt_thread_mutex_lock( &replog_mutex );
-       if ( (fp = lock_fopen( replogfile, "a", &lfp )) == NULL ) {
-               ldap_pvt_thread_mutex_unlock( &replog_mutex );
-               return;
-       }
-
-       for ( i = 0; op->o_bd->be_replica != NULL && op->o_bd->be_replica[i] != NULL; i++ ) {
-               /* check if dn's suffix matches legal suffixes, if any */
-               if ( op->o_bd->be_replica[i]->ri_nsuffix != NULL ) {
-                       int j;
-
-                       for ( j = 0; op->o_bd->be_replica[i]->ri_nsuffix[j].bv_val; j++ ) {
-                               if ( dnIsSuffix( &op->o_req_ndn, &op->o_bd->be_replica[i]->ri_nsuffix[j] ) ) {
-                                       break;
-                               }
-                       }
-
-                       if ( !op->o_bd->be_replica[i]->ri_nsuffix[j].bv_val ) {
-                               /* do not add "replica:" line */
-                               continue;
-                       }
-               }
-               /* See if we only want a subset of attributes */
-               if ( op->o_bd->be_replica[i]->ri_attrs != NULL &&
-                       ( op->o_tag == LDAP_REQ_MODIFY || op->o_tag == LDAP_REQ_ADD || op->o_tag == LDAP_REQ_EXTENDED ) ) {
-                       if ( !subsets ) {
-                               subsets = i + 1;
-                       }
-                       /* Do attribute subsets by themselves in a second pass */
-                       continue;
-               }
-
-               fprintf( fp, "replica: %s\n", op->o_bd->be_replica[i]->ri_host );
-#ifdef NO_LOG_WHEN_NO_REPLICAS
-               ++count;
-#endif /* NO_LOG_WHEN_NO_REPLICAS */
-       }
-
-#ifdef NO_LOG_WHEN_NO_REPLICAS
-       if ( count == 0 && subsets == 0 ) {
-               /* if no replicas matched, drop the log 
-                * (should we log it anyway?) */
-               lock_fclose( fp, lfp );
-               ldap_pvt_thread_mutex_unlock( &replog_mutex );
-
-               return;
-       }
-#endif /* NO_LOG_WHEN_NO_REPLICAS */
-
-       replog1( NULL, op, fp, now );
-
-       if ( subsets > 0 ) {
-               for ( i = subsets - 1; op->o_bd->be_replica[i] != NULL; i++ ) {
-
-                       /* If no attrs, we already did this above */
-                       if ( op->o_bd->be_replica[i]->ri_attrs == NULL ) {
-                               continue;
-                       }
-
-                       /* check if dn's suffix matches legal suffixes, if any */
-                       if ( op->o_bd->be_replica[i]->ri_nsuffix != NULL ) {
-                               int j;
-
-                               for ( j = 0; op->o_bd->be_replica[i]->ri_nsuffix[j].bv_val; j++ ) {
-                                       if ( dnIsSuffix( &op->o_req_ndn, &op->o_bd->be_replica[i]->ri_nsuffix[j] ) ) {
-                                               break;
-                                       }
-                               }
-
-                               if ( !op->o_bd->be_replica[i]->ri_nsuffix[j].bv_val ) {
-                                       /* no matching suffix found, skip it */
-                                       continue;
-                               }
-                       }
-                       switch( op->o_tag ) {
-                       case LDAP_REQ_EXTENDED:
-                               /* quick hack for extended operations */
-                               /* assume change parameter is a Modifications* */
-                               /* fall thru */
-                       case LDAP_REQ_MODIFY:
-                       case LDAP_REQ_ADD:
-                               break;
-                       default:
-                               /* Other operations were logged in the first pass */
-                               continue;
-                       }
-                       replog1( op->o_bd->be_replica[i], op, fp, now );
-               }
-       }
-
-       lock_fclose( fp, lfp );
-       ldap_pvt_thread_mutex_unlock( &replog_mutex );
-}
-
-static void
-rephdr(
-       struct slap_replica_info *ri,
-       Operation *op,
-       FILE *fp,
-       long now
-)
-{
-       if ( ri ) {
-               fprintf( fp, "replica: %s\n", ri->ri_host );
-       }
-       fprintf( fp, "time: %ld\n", now );
-       fprintf( fp, "dn: %s\n", op->o_req_dn.bv_val );
-}
-
-static void
-replog1(
-       struct slap_replica_info *ri,
-       Operation *op,
-       FILE    *fp,
-       long    now
-)
-{
-       Modifications   *ml;
-       Attribute       *a;
-       AttributeName   *an;
-       int             dohdr = 1, ocs = -1;
-       struct berval vals[2];
-
-       vals[1].bv_val = NULL;
-       vals[1].bv_len = 0;
-
-       switch ( op->o_tag ) {
-       case LDAP_REQ_EXTENDED:
-               /* quick hack for extended operations */
-               /* assume change parameter is a Modifications* */
-               /* fall thru */
-
-       case LDAP_REQ_MODIFY:
-               for ( ml = op->orm_modlist; ml != NULL; ml = ml->sml_next ) {
-                       char *did = NULL, *type = ml->sml_desc->ad_cname.bv_val;
-                       switch ( ml->sml_op ) {
-                       case LDAP_MOD_ADD:
-                               did = "add"; break;
-
-                       case LDAP_MOD_DELETE:
-                               did = "delete"; break;
-
-                       case LDAP_MOD_REPLACE:
-                               did = "replace"; break;
-
-                       case LDAP_MOD_INCREMENT:
-                               did = "increment"; break;
-                       }
-                       if ( ri && ri->ri_attrs ) {
-                               int is_in = ad_inlist( ml->sml_desc, ri->ri_attrs );
-
-                               /* skip if:
-                                *   1) the attribute is not in the list,
-                                *      and it's not an exclusion list
-                                *   2) the attribute is in the list
-                                *      and it's an exclusion list,
-                                *      and either the objectClass attribute
-                                *      has already been dealt with or
-                                *      this is not the objectClass attr
-                                */
-                               if ( ( !is_in && !ri->ri_exclude )
-                                       || ( ( is_in && ri->ri_exclude )
-                                               && ( !ocs || ml->sml_desc != slap_schema.si_ad_objectClass ) ) )
-                               {
-                                       continue;
-                               }
-
-                               /* If this is objectClass, see if the value is included
-                                * in any subset, otherwise drop it.
-                                */
-                               if ( ocs && ml->sml_desc == slap_schema.si_ad_objectClass
-                                       && ml->sml_values )
-                               {
-                                       int i, first = 1;
-
-                                       if ( ocs == -1 ) ocs = 0;
-
-                                       for ( i=0; ml->sml_values[i].bv_val; i++ ) {
-                                               int match = 0;
-                                               for ( an = ri->ri_attrs; an->an_name.bv_val; an++ ) {
-                                                       if ( an->an_oc ) {
-                                                               struct berval   bv = an->an_name;
-
-                                                               ocs = 1;
-                                                               match |= an->an_oc_exclude;
-
-                                                               switch ( bv.bv_val[ 0 ] ) {
-                                                               case '@':
-                                                               case '+':
-                                                               case '!':
-                                                                       bv.bv_val++;
-                                                                       bv.bv_len--;
-                                                                       break;
-                                                               }
-
-                                                               if ( ml->sml_values[i].bv_len == bv.bv_len
-                                                                       && !strcasecmp(ml->sml_values[i].bv_val,
-                                                                               bv.bv_val ) )
-                                                               {
-                                                                       match = !an->an_oc_exclude;
-                                                                       break;
-                                                               }
-                                                       }
-                                               }
-                                               /* Objectclasses need no special treatment, drop into
-                                                * regular processing
-                                                */
-                                               if ( !ocs ) break;
-
-                                               match ^= ri->ri_exclude;
-                                               /* Found a match, log it */
-                                               if ( match ) {
-                                                       if ( dohdr ) {
-                                                               rephdr( ri, op, fp, now );
-                                                               fprintf( fp, "changetype: modify\n" );
-                                                               dohdr = 0;
-                                                       }
-                                                       if ( first ) {
-                                                               fprintf( fp, "%s: %s\n", did, type );
-                                                               first = 0;
-                                                       }
-                                                       vals[0] = ml->sml_values[i];
-                                                       print_vals( fp, &ml->sml_desc->ad_cname, vals );
-                                                       ocs = 2;
-                                               }
-
-                                       }
-                                       /* Explicit objectclasses have been handled already */
-                                       if ( ocs ) {
-                                               if ( ocs == 2 ) {
-                                                       fprintf( fp, "-\n" );
-                                               }
-                                               continue;
-                                       }
-                               }
-                       }
-                       if ( dohdr ) {
-                               rephdr( ri, op, fp, now );
-                               fprintf( fp, "changetype: modify\n" );
-                               dohdr = 0;
-                       }
-                       fprintf( fp, "%s: %s\n", did, type );
-                       if ( ml->sml_values ) {
-                               print_vals( fp, &ml->sml_desc->ad_cname, ml->sml_values );
-                       }
-                       fprintf( fp, "-\n" );
-               }
-               break;
-
-       case LDAP_REQ_ADD:
-               for ( a = op->ora_e->e_attrs ; a != NULL; a=a->a_next ) {
-                       if ( ri && ri->ri_attrs ) {
-                               int is_in = ad_inlist( a->a_desc, ri->ri_attrs );
-
-                               /* skip if:
-                                *   1) the attribute is not in the list,
-                                *      and it's not an exclusion list
-                                *   2) the attribute is in the list
-                                *      and it's an exclusion list,
-                                *      and either the objectClass attribute
-                                *      has already been dealt with or
-                                *      this is not the objectClass attr
-                                */
-                               if ( ( !is_in && !ri->ri_exclude )
-                                       || ( ( is_in && ri->ri_exclude )
-                                               && ( !ocs || a->a_desc != slap_schema.si_ad_objectClass ) ) )
-                               {
-                                       continue;
-                               }
-
-                               /* If the list includes objectClass names,
-                                * only include those classes in the
-                                * objectClass attribute
-                                */
-                               if ( ocs && a->a_desc == slap_schema.si_ad_objectClass ) {
-                                       int i;
-
-                                       if ( ocs == -1 ) ocs = 0;
-
-                                       for ( i=0; a->a_vals[i].bv_val; i++ ) {
-                                               int match = 0;
-                                               for ( an = ri->ri_attrs; an->an_name.bv_val; an++ ) {
-                                                       if ( an->an_oc ) {
-                                                               struct berval   bv = an->an_name;
-
-                                                               ocs = 1;
-                                                               match |= an->an_oc_exclude;
-
-                                                               switch ( bv.bv_val[ 0 ] ) {
-                                                               case '@':
-                                                               case '+':
-                                                               case '!':
-                                                                       bv.bv_val++;
-                                                                       bv.bv_len--;
-                                                                       break;
-                                                               }
-
-                                                               if ( a->a_vals[i].bv_len == bv.bv_len
-                                                                       && !strcasecmp(a->a_vals[i].bv_val,
-                                                                               bv.bv_val ) )
-                                                               {
-                                                                       match = !an->an_oc_exclude;
-                                                                       break;
-                                                               }
-                                                       }
-                                               }
-                                               if ( !ocs ) break;
-
-                                               match ^= ri->ri_exclude;
-                                               if ( match ) {
-                                                       if ( dohdr ) {
-                                                               rephdr( ri, op, fp, now );
-                                                               fprintf( fp, "changetype: add\n" );
-                                                               dohdr = 0;
-                                                       }
-                                                       vals[0] = a->a_nvals[i];
-                                                       print_vals( fp, &a->a_desc->ad_cname, vals );
-                                               }
-                                       }
-                                       if ( ocs ) continue;
-                               }
-                       }
-                       if ( dohdr ) {
-                               rephdr( ri, op, fp, now );
-                               fprintf( fp, "changetype: add\n" );
-                               dohdr = 0;
-                       }
-                       print_vals( fp, &a->a_desc->ad_cname, a->a_vals );
-               }
-               break;
-
-       case LDAP_REQ_DELETE:
-               rephdr( ri, op, fp, now );
-               fprintf( fp, "changetype: delete\n" );
-               break;
-
-       case LDAP_REQ_MODRDN:
-               rephdr( ri, op, fp, now );
-               fprintf( fp, "changetype: modrdn\n" );
-               fprintf( fp, "newrdn: %s\n", op->orr_newrdn.bv_val );
-               fprintf( fp, "deleteoldrdn: %d\n", op->orr_deleteoldrdn ? 1 : 0 );
-               if( op->orr_newSup != NULL ) {
-                       fprintf( fp, "newsuperior: %s\n", op->orr_newSup->bv_val );
-               }
-       }
-       fprintf( fp, "\n" );
-}
-
-static void
-print_vals(
-       FILE *fp,
-       struct berval *type,
-       struct berval *bv )
-{
-       ber_len_t i, len;
-       char    *buf, *bufp;
-
-       for ( i = 0, len = 0; bv && bv[i].bv_val; i++ ) {
-               if ( bv[i].bv_len > len )
-                       len = bv[i].bv_len;
-       }
-
-       len = LDIF_SIZE_NEEDED( type->bv_len, len ) + 1;
-       buf = (char *) ch_malloc( len );
-
-       for ( ; bv && bv->bv_val; bv++ ) {
-               bufp = buf;
-               ldif_sput( &bufp, LDIF_PUT_VALUE, type->bv_val,
-                                   bv->bv_val, bv->bv_len );
-               *bufp = '\0';
-
-               fputs( buf, fp );
-
-       }
-       free( buf );
-}
index ae6a42dd0f5cd61cdcf04eefb0b5683b02046e60..4368bf8e4ae170eabfd2032827cf0b0908622185 100644 (file)
@@ -54,14 +54,6 @@ int slap_freeself_cb( Operation *op, SlapReply *rs )
        return SLAP_CB_CONTINUE;
 }
 
-int slap_replog_cb( Operation *op, SlapReply *rs )
-{
-       if ( rs->sr_err == LDAP_SUCCESS ) {
-               replog( op );
-       }
-       return SLAP_CB_CONTINUE;
-}
-
 static char *v2ref( BerVarray ref, const char *text )
 {
        size_t len = 0, i = 0;
@@ -247,7 +239,7 @@ send_ldap_controls( Operation *o, BerElement *ber, LDAPControl **c )
                if( rc == -1 ) return rc;
        }
 
-#ifdef SLAP_SORTED_RESULTS
+#ifdef SLAP_CONTROL_X_SORTEDRESULTS
        /* this is a hack to avoid having to modify op->s_ctrls */
        if( o->o_sortedresults ) {
                BerElementBuffer berbuf;
@@ -570,7 +562,7 @@ send_ldap_disconnect( Operation     *op, SlapReply *rs )
        } else {
                rs->sr_rspoid = LDAP_NOTICE_DISCONNECT;
                rs->sr_tag = LDAP_RES_EXTENDED;
-               rs->sr_msgid = 0;
+               rs->sr_msgid = LDAP_RES_UNSOLICITED;
        }
 
        if ( send_ldap_response( op, rs ) == SLAP_CB_CONTINUE ) {
index 7c02247dd6234710efbfaffa41f207a25b55cafc..9e019fdec0bc91a64c34d6d965b8f12528c6c02a 100644 (file)
@@ -326,7 +326,7 @@ slap_auxprop_lookup(
 
                cb.sc_private = &sl;
 
-               op.o_bd = select_backend( &op.o_req_ndn, 0, 1 );
+               op.o_bd = select_backend( &op.o_req_ndn, 1 );
 
                if ( op.o_bd ) {
                        /* For rootdn, see if we can use the rootpw */
@@ -440,7 +440,7 @@ slap_auxprop_store(
        }
        if (!conn || !op.o_req_ndn.bv_val) return SASL_BADPARAM;
 
-       op.o_bd = select_backend( &op.o_req_ndn, 0, 1 );
+       op.o_bd = select_backend( &op.o_req_ndn, 1 );
 
        if ( !op.o_bd || !op.o_bd->be_modify ) return SASL_FAIL;
                
@@ -610,6 +610,7 @@ slap_sasl_canonicalize(
         */
        if ( flags == SASL_CU_AUTHID && !auxvals[SLAP_SASL_PROP_AUTHZ].values ) {
                conn->c_sasl_dn.bv_val = (char *) in;
+               conn->c_sasl_dn.bv_len = 0;
        } else if ( flags == SASL_CU_AUTHZID && conn->c_sasl_dn.bv_val ) {
                rc = strcmp( in, conn->c_sasl_dn.bv_val );
                conn->c_sasl_dn.bv_val = NULL;
@@ -624,13 +625,13 @@ slap_sasl_canonicalize(
        if ( rc != LDAP_SUCCESS ) {
                sasl_seterror( sconn, 0, ldap_err2string( rc ) );
                return SASL_NOAUTHZ;
-       }               
+       }
 
        names[0] = slap_propnames[which];
        names[1] = NULL;
 
        prop_set( props, names[0], (char *)&dn, sizeof( dn ) );
-               
+
        Debug( LDAP_DEBUG_ARGS, "SASL Canonicalize [conn=%ld]: %s=\"%s\"\n",
                conn ? conn->c_connid : -1, names[0]+1,
                dn.bv_val ? dn.bv_val : "<EMPTY>" );
@@ -721,9 +722,9 @@ slap_sasl_authorize(
 ok:
        if (conn->c_sasl_bindop) {
                Statslog( LDAP_DEBUG_STATS,
-                       "conn=%lu op=%lu BIND authcid=\"%s\" authzid=\"%s\"\n",
-                       conn->c_connid, conn->c_sasl_bindop->o_opid
-                       auth_identity, requested_user, 0);
+                       "%s BIND authcid=\"%s\" authzid=\"%s\"\n",
+                       conn->c_sasl_bindop->o_log_prefix
+                       auth_identity, requested_user, 0, 0 );
        }
 
        Debug( LDAP_DEBUG_TRACE, "SASL Authorize [conn=%ld]: "
@@ -825,9 +826,9 @@ ok:
 
        if ( conn->c_sasl_bindop ) {
                Statslog( LDAP_DEBUG_STATS,
-                       "conn=%lu op=%lu BIND authcid=\"%s\" authzid=\"%s\"\n",
-                       conn->c_connid, conn->c_sasl_bindop->o_opid
-                       authcid, authzid ? authzid : "", 0);
+                       "%s BIND authcid=\"%s\" authzid=\"%s\"\n",
+                       conn->c_sasl_bindop->o_log_prefix
+                       authcid, authzid ? authzid : "", 0, 0 );
        }
 
        *errstr = NULL;
@@ -1092,12 +1093,12 @@ slapd_rw_apply( void *private, const char *filter, struct berval *val )
        int rc;
 
        thrctx = ldap_pvt_thread_pool_context();
-       op = (Operation *)&opbuf;
-       connection_fake_init2( &conn, op, thrctx, 0 );
+       connection_fake_init2( &conn, &opbuf, thrctx, 0 );
+       op = &opbuf.ob_op;
 
        op->o_tag = LDAP_REQ_SEARCH;
        op->o_req_dn = op->o_req_ndn = sl->base;
-       op->o_bd = select_backend( &op->o_req_ndn, 0, 1 );
+       op->o_bd = select_backend( &op->o_req_ndn, 1 );
        if ( !op->o_bd ) {
                return REWRITE_ERR;
        }
@@ -1121,8 +1122,12 @@ slapd_rw_apply( void *private, const char *filter, struct berval *val )
        ptr = op->ors_filterstr.bv_val = op->o_tmpalloc( rc + 1, op->o_tmpmemctx );
        if ( sl->filter.bv_len ) {
                ptr = lutil_strcopy( ptr, sl->filter.bv_val );
+       } else {
+               *ptr = '\0';
+       }
+       if ( filter ) {
+               strcpy( ptr, filter );
        }
-       strcpy( ptr, filter );
        op->ors_filter = str2filter_x( op, op->ors_filterstr.bv_val );
        if ( !op->ors_filter ) {
                op->o_tmpfree( op->ors_filterstr.bv_val, op->o_tmpmemctx );
@@ -1205,8 +1210,8 @@ int slap_sasl_init( void )
                sprintf( version, "%u.%d.%d", (unsigned)rc >> 24, (rc >> 16) & 0xff,
                        rc & 0xffff );
                Debug( LDAP_DEBUG_ANY, "slap_sasl_init: SASL library version mismatch:"
-                       " expected " SASL_VERSION_STRING ","
-                       " got %s\n", version, 0, 0 );
+                       " expected %s, got %s\n",
+                       SASL_VERSION_STRING, version, 0 );
                return -1;
        }
 #endif
@@ -1706,6 +1711,9 @@ int slap_sasl_bind( Operation *op, SlapReply *rs )
                send_ldap_sasl( op, rs );
 
        } else {
+               if ( op->o_conn->c_sasl_dn.bv_len )
+                       ch_free( op->o_conn->c_sasl_dn.bv_val );
+               BER_BVZERO( &op->o_conn->c_sasl_dn );
 #if SASL_VERSION_MAJOR >= 2
                rs->sr_text = sasl_errdetail( ctx );
 #endif
index 2f6fd33d48aa4e5d6fcf374afd933e9767a9da6b..f591668961df64011816cb8b8518f5880fe09b8e 100644 (file)
@@ -1820,7 +1820,7 @@ exact_match:
           "slap_sasl_match: performing internal search (base=%s, scope=%d)\n",
           op.o_req_ndn.bv_val, op.ors_scope, 0 );
 
-       op.o_bd = select_backend( &op.o_req_ndn, 0, 1 );
+       op.o_bd = select_backend( &op.o_req_ndn, 1 );
        if(( op.o_bd == NULL ) || ( op.o_bd->be_search == NULL)) {
                rc = LDAP_INAPPROPRIATE_AUTH;
                goto CONCLUDED;
@@ -1953,7 +1953,7 @@ slap_sasl2dn(
        }
 
        /* Must do an internal search */
-       op.o_bd = select_backend( &op.o_req_ndn, 0, 1 );
+       op.o_bd = select_backend( &op.o_req_ndn, 1 );
 
        switch ( op.ors_scope ) {
        case LDAP_X_SCOPE_EXACT:
index 5f8cba5679ad81f1c7b5b4a3ae9b7e372f86b1db..fd75166d4d6a73dcb158266678f89a4fd9772cac 100644 (file)
@@ -92,9 +92,18 @@ attributetype ( 2.5.4.5 NAME 'serialNumber'
        SUBSTR caseIgnoreSubstringsMatch
        SYNTAX 1.3.6.1.4.1.1466.115.121.1.44{64} )
 
-attributetype ( 2.5.4.6 NAME ( 'c' 'countryName' )
+# RFC 4519 definition (cannot be loaded because SYNTAX conflicts
+# with that of name).
+#
+attributetype ( 2.5.4.6 NAME 'c'
        DESC 'RFC2256: ISO-3166 country 2-letter code'
-       SUP name SINGLE-VALUE )
+       SUP name
+       SYNTAX 1.3.6.1.4.1.1466.115.121.1.11
+       SINGLE-VALUE )
+
+#attributetype ( 2.5.4.6 NAME ( 'c' 'countryName' )
+#      DESC 'RFC2256: ISO-3166 country 2-letter code'
+#      SUP name SINGLE-VALUE )
 
 attributetype ( 2.5.4.7 NAME ( 'l' 'localityName' )
        DESC 'RFC2256: locality which this object resides in'
index 1650cb4965b90f0fd54cf9be6902f7cfb3c98ed8..aa07b6e2957cad7a550f31b50c78f55ad31e5cbd 100644 (file)
 # between structural and auxiliary classes. This fact is noted here:
 # http://forum.java.sun.com/thread.jspa?threadID=5016864&messageID=9034636
 #
-# In accordance with the actual usage in practice, we define it as an
-# auxiliary class.
+# In accordance with other existing implementations, we define it as a
+# structural class.
 #
 # Our definition of memberURL also does not match theirs but again
 # their published definition and what works in practice do not agree.
 # In other words, the Netscape definitions are broken and interoperability
 # is not guaranteed.
 #
+# Also see the new DynGroup proposed spec at
+# http://tools.ietf.org/html/draft-haripriya-dynamicgroup-02
 
 objectIdentifier NetscapeRoot 2.16.840.1.113730
 
@@ -50,14 +52,31 @@ objectIdentifier NetscapeLDAP NetscapeRoot:3
 objectIdentifier NetscapeLDAPattributeType NetscapeLDAP:1
 objectIdentifier NetscapeLDAPobjectClass NetscapeLDAP:2
 
+objectIdentifier OpenLDAPExp11 1.3.6.1.4.1.4203.666.11
+objectIdentifier DynGroupBase  OpenLDAPExp11:8
+objectIdentifier DynGroupAttr  DynGroupBase:1
+objectIdentifier DynGroupOC    DynGroupBase:2
+
 attributetype ( NetscapeLDAPattributeType:198
        NAME 'memberURL'
        DESC 'Identifies an URL associated with each member of a group. Any type of labeled URL can be used.'
        SUP labeledURI )
 
+attributetype ( DynGroupAttr:1
+       NAME 'dgIdentity'
+       DESC 'Identity to use when processing the memberURL'
+       SUP distinguishedName SINGLE-VALUE )
+
 objectClass ( NetscapeLDAPobjectClass:33
        NAME 'groupOfURLs'
        SUP top STRUCTURAL
        MUST cn
        MAY ( memberURL $ businessCategory $ description $ o $ ou $
                owner $ seeAlso ) )
+
+# The Haripriya dyngroup schema still needs a lot of work.
+# We're just adding support for the dgIdentity attribute for now...
+objectClass ( DynGroupOC:1
+       NAME 'dgIdentityAux'
+       SUP top AUXILIARY
+       MAY dgIdentity )
index 19bed5b3bbcf03133ed0b5bc94de560842d0f4a2..a5860d7dc9fd9b0128fc562f2484962e665b4df8 100644 (file)
@@ -172,7 +172,7 @@ entry_schema_check(
                        e->e_dn, textbuf, 0 );
 
                rc = LDAP_OBJECT_CLASS_VIOLATION;
-               goto leave;
+               goto done;
        }
 
        if( sc->soc_kind != LDAP_SCHEMA_STRUCTURAL ) {
@@ -185,7 +185,7 @@ entry_schema_check(
                        e->e_dn, textbuf, 0 );
 
                rc = LDAP_OTHER;
-               goto leave;
+               goto done;
        }
 
 got_soc:
@@ -199,7 +199,7 @@ got_soc:
                        e->e_dn, textbuf, 0 );
 
                rc = LDAP_OBJECT_CLASS_VIOLATION;
-               goto leave;
+               goto done;
        }
 
        *text = textbuf;
@@ -209,7 +209,7 @@ got_soc:
                        "unrecognized objectClass '%s'",
                        aoc->a_vals[0].bv_val );
                rc = LDAP_OBJECT_CLASS_VIOLATION;
-               goto leave;
+               goto done;
 
        } else if ( sc != slap_schema.si_oc_glue && sc != oc ) {
                snprintf( textbuf, textlen, 
@@ -217,7 +217,7 @@ got_soc:
                        "from '%s' to '%s' not allowed",
                        asc->a_vals[0].bv_val, oc->soc_cname.bv_val );
                rc = LDAP_NO_OBJECT_CLASS_MODS;
-               goto leave;
+               goto done;
        } else if ( sc == slap_schema.si_oc_glue ) {
                sc = oc;
        }
@@ -226,7 +226,7 @@ got_soc:
        if ( !is_entry_glue ( e ) ) {
                rc = entry_naming_check( e, manage, text, textbuf, textlen );
                if( rc != LDAP_SUCCESS ) {
-                       goto leave;
+                       goto done;
                }
        } else {
                /* Glue Entry */
@@ -250,7 +250,7 @@ got_soc:
                                e->e_dn, textbuf, 0 );
 
                        rc = LDAP_OBJECT_CLASS_VIOLATION;
-                       goto leave;
+                       goto done;
                }
 
                if( cr->scr_required ) for( i=0; cr->scr_required[i]; i++ ) {
@@ -274,7 +274,7 @@ got_soc:
                                        e->e_dn, textbuf, 0 );
 
                                rc = LDAP_OBJECT_CLASS_VIOLATION;
-                               goto leave;
+                               goto done;
                        }
                }
 
@@ -299,7 +299,7 @@ got_soc:
                                        e->e_dn, textbuf, 0 );
 
                                rc = LDAP_OBJECT_CLASS_VIOLATION;
-                               goto leave;
+                               goto done;
                        }
                }
        }
@@ -318,14 +318,14 @@ got_soc:
                                e->e_dn, textbuf, 0 );
 
                        rc = LDAP_OBJECT_CLASS_VIOLATION;
-                       goto leave;
+                       goto done;
                }
 
                if ( oc->soc_check ) {
                        rc = (oc->soc_check)( op->o_bd, e, oc,
                                text, textbuf, textlen );
                        if( rc != LDAP_SUCCESS ) {
-                               goto leave;
+                               goto done;
                        }
                }
 
@@ -365,7 +365,7 @@ got_soc:
                                                e->e_dn, textbuf, 0 );
 
                                        rc = LDAP_OBJECT_CLASS_VIOLATION;
-                                       goto leave;
+                                       goto done;
                                }
                        }
 
@@ -408,7 +408,7 @@ got_soc:
                                                e->e_dn, textbuf, 0 );
 
                                        rc = LDAP_OBJECT_CLASS_VIOLATION;
-                                       goto leave;
+                                       goto done;
                                }
                        }
 
@@ -423,7 +423,7 @@ got_soc:
                                        e->e_dn, textbuf, 0 );
 
                                rc = LDAP_OBJECT_CLASS_VIOLATION;
-                               goto leave;
+                               goto done;
                        }
 
                        if( oc == slap_schema.si_oc_extensibleObject ) {
@@ -435,7 +435,7 @@ got_soc:
        if( extensible ) {
                *text = NULL;
                rc = LDAP_SUCCESS;
-               goto leave;
+               goto done;
        }
 
        /* check that each attr in the entry is allowed by some oc */
@@ -476,12 +476,12 @@ got_soc:
                            "Entry (%s), %s\n",
                            e->e_dn, textbuf, 0 );
 
-                       goto leave;
+                       goto done;
                }
        }
 
        *text = NULL;
-leave:
+done:
        slap_sl_free( socs, op->o_tmpmemctx );
        return rc;
 }
@@ -572,6 +572,10 @@ int oc_check_allowed(
        for ( i = 0; socs[i]; i++ ) {
                /* if we know about the oc */
                ObjectClass     *oc = socs[i];
+               /* extensibleObject allows all */
+               if ( oc == slap_schema.si_oc_extensibleObject ) {
+                       return LDAP_SUCCESS;
+               }
                if ( oc != NULL && oc->soc_kind != LDAP_SCHEMA_ABSTRACT &&
                        ( sc == NULL || oc->soc_kind == LDAP_SCHEMA_AUXILIARY ))
                {
index 616d9703842915b381cccaf56eea1facf464339e..2cb1ce23494604c82dd0dcc5f3e82ccb30558885 100644 (file)
 #include <ac/socket.h>
 
 #include "slap.h"
+#include "../../libraries/liblber/lber-int.h" /* get ber_ptrlen() */
 
 #include "ldap_utf8.h"
 
-#ifdef HAVE_TLS
-#include <openssl/x509.h>
-#include <openssl/err.h>
-#include <openssl/rsa.h>
-#include <openssl/crypto.h>
-#include <openssl/pem.h>
-#include <openssl/bio.h>
-#include <openssl/asn1.h>
-#include <openssl/x509v3.h>
-#include <openssl/ssl.h>
-#endif
-
 #include "lutil.h"
 #include "lutil_hash.h"
 #define HASH_BYTES                             LUTIL_HASH_BYTES
@@ -61,7 +50,6 @@
 #define IA5StringApproxFilter                  approxFilter
 
 /* Change Sequence Number (CSN) - much of this will change */
-#define csnValidate                            blobValidate
 #define csnMatch                               octetStringMatch
 #define csnOrderingMatch               octetStringOrderingMatch
 #define csnIndexer                             generalizedTimeIndexer
@@ -78,6 +66,11 @@ unsigned int index_substr_any_step = SLAP_INDEX_SUBSTR_ANY_STEP_DEFAULT;
 ldap_pvt_thread_mutex_t        ad_undef_mutex;
 ldap_pvt_thread_mutex_t        oc_undef_mutex;
 
+static int
+generalizedTimeValidate(
+       Syntax *syntax,
+       struct berval *in );
+
 static int
 inValidate(
        Syntax *syntax,
@@ -109,21 +102,163 @@ sequenceValidate(
        return LDAP_SUCCESS;
 }
 
+/* X.509 related stuff */
+
+enum {
+       SLAP_X509_V1            = 0,
+       SLAP_X509_V2            = 1,
+       SLAP_X509_V3            = 2
+};
 
-#ifdef HAVE_TLS
+#define        SLAP_X509_OPTION        (LBER_CLASS_CONTEXT|LBER_CONSTRUCTED)
+
+enum {
+       SLAP_X509_OPT_C_VERSION         = SLAP_X509_OPTION + 0,
+       SLAP_X509_OPT_C_ISSUERUNIQUEID  = SLAP_X509_OPTION + 1,
+       SLAP_X509_OPT_C_SUBJECTUNIQUEID = SLAP_X509_OPTION + 2,
+       SLAP_X509_OPT_C_EXTENSIONS      = SLAP_X509_OPTION + 3
+};
+
+enum {
+       SLAP_X509_OPT_CL_CRLEXTENSIONS  = SLAP_X509_OPTION + 0
+};
+
+/* X.509 certificate validation */
 static int certificateValidate( Syntax *syntax, struct berval *in )
 {
-       X509 *xcert=NULL;
-       unsigned char *p = (unsigned char *)in->bv_val;
-       xcert = d2i_X509(NULL, &p, in->bv_len);
-       if ( !xcert ) return LDAP_INVALID_SYNTAX;
-       X509_free(xcert);
+       BerElementBuffer berbuf;
+       BerElement *ber = (BerElement *)&berbuf;
+       ber_tag_t tag;
+       ber_len_t len;
+       ber_int_t version = SLAP_X509_V1;
+
+       ber_init2( ber, in, LBER_USE_DER );
+       tag = ber_skip_tag( ber, &len );        /* Signed wrapper */
+       if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
+       tag = ber_skip_tag( ber, &len );        /* Sequence */
+       if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
+       tag = ber_peek_tag( ber, &len );
+       /* Optional version */
+       if ( tag == SLAP_X509_OPT_C_VERSION ) {
+               tag = ber_skip_tag( ber, &len );
+               tag = ber_get_int( ber, &version );
+               if ( tag != LBER_INTEGER ) return LDAP_INVALID_SYNTAX;
+       }
+       /* NOTE: don't try to parse Serial, because it might be longer
+        * than sizeof(ber_int_t); deferred to certificateExactNormalize() */
+       tag = ber_skip_tag( ber, &len );        /* Serial */
+       if ( tag != LBER_INTEGER ) return LDAP_INVALID_SYNTAX;
+       ber_skip_data( ber, len );
+       tag = ber_skip_tag( ber, &len );        /* Signature Algorithm */
+       if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
+       ber_skip_data( ber, len );
+       tag = ber_skip_tag( ber, &len );        /* Issuer DN */
+       if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
+       ber_skip_data( ber, len );
+       tag = ber_skip_tag( ber, &len );        /* Validity */
+       if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
+       ber_skip_data( ber, len );
+       tag = ber_skip_tag( ber, &len );        /* Subject DN */
+       if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
+       ber_skip_data( ber, len );
+       tag = ber_skip_tag( ber, &len );        /* Subject PublicKeyInfo */
+       if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
+       ber_skip_data( ber, len );
+       tag = ber_skip_tag( ber, &len );
+       if ( tag == SLAP_X509_OPT_C_ISSUERUNIQUEID ) {  /* issuerUniqueID */
+               if ( version < SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX;
+               ber_skip_data( ber, len );
+               tag = ber_skip_tag( ber, &len );
+       }
+       if ( tag == SLAP_X509_OPT_C_SUBJECTUNIQUEID ) { /* subjectUniqueID */
+               if ( version < SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX;
+               ber_skip_data( ber, len );
+               tag = ber_skip_tag( ber, &len );
+       }
+       if ( tag == SLAP_X509_OPT_C_EXTENSIONS ) {      /* Extensions */
+               if ( version < SLAP_X509_V3 ) return LDAP_INVALID_SYNTAX;
+               tag = ber_skip_tag( ber, &len );
+               if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
+               ber_skip_data( ber, len );
+               tag = ber_skip_tag( ber, &len );
+       }
+       /* signatureAlgorithm */
+       if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
+       ber_skip_data( ber, len );
+       tag = ber_skip_tag( ber, &len );
+       /* Signature */
+       if ( tag != LBER_BITSTRING ) return LDAP_INVALID_SYNTAX; 
+       ber_skip_data( ber, len );
+       tag = ber_skip_tag( ber, &len );
+       /* Must be at end now */
+       if ( len || tag != LBER_DEFAULT ) return LDAP_INVALID_SYNTAX;
+       return LDAP_SUCCESS;
+}
+
+/* X.509 certificate list validation */
+static int certificateListValidate( Syntax *syntax, struct berval *in )
+{
+       BerElementBuffer berbuf;
+       BerElement *ber = (BerElement *)&berbuf;
+       ber_tag_t tag;
+       ber_len_t len;
+       ber_int_t version = SLAP_X509_V1;
+
+       ber_init2( ber, in, LBER_USE_DER );
+       tag = ber_skip_tag( ber, &len );        /* Signed wrapper */
+       if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
+       tag = ber_skip_tag( ber, &len );        /* Sequence */
+       if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
+       tag = ber_peek_tag( ber, &len );
+       /* Optional version */
+       if ( tag == LBER_INTEGER ) {
+               tag = ber_get_int( ber, &version );
+               assert( tag == LBER_INTEGER );
+               if ( version != SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX;
+       }
+       tag = ber_skip_tag( ber, &len );        /* Signature Algorithm */
+       if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
+       ber_skip_data( ber, len );
+       tag = ber_skip_tag( ber, &len );        /* Issuer DN */
+       if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
+       ber_skip_data( ber, len );
+       tag = ber_skip_tag( ber, &len );        /* thisUpdate */
+       /* NOTE: in the certificates I'm playing with, the time is UTC.
+        * maybe the tag is different from 0x17U for generalizedTime? */
+       if ( tag != 0x17U ) return LDAP_INVALID_SYNTAX;
+       ber_skip_data( ber, len );
+       /* Optional nextUpdate */
+       tag = ber_skip_tag( ber, &len );
+       if ( tag == 0x17U ) {
+               ber_skip_data( ber, len );
+               tag = ber_skip_tag( ber, &len );
+       }
+       /* Optional revokedCertificates */
+       if ( tag == LBER_SEQUENCE ) {
+               /* Should NOT be empty */
+               ber_skip_data( ber, len );
+               tag = ber_skip_tag( ber, &len );
+       }
+       /* Optional Extensions */
+       if ( tag == SLAP_X509_OPT_CL_CRLEXTENSIONS ) { /* ? */
+               if ( version != SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX;
+               tag = ber_skip_tag( ber, &len );
+               if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
+               ber_skip_data( ber, len );
+               tag = ber_skip_tag( ber, &len );
+       }
+       /* signatureAlgorithm */
+       if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
+       ber_skip_data( ber, len );
+       tag = ber_skip_tag( ber, &len );
+       /* Signature */
+       if ( tag != LBER_BITSTRING ) return LDAP_INVALID_SYNTAX; 
+       ber_skip_data( ber, len );
+       tag = ber_skip_tag( ber, &len );
+       /* Must be at end now */
+       if ( len || tag != LBER_DEFAULT ) return LDAP_INVALID_SYNTAX;
        return LDAP_SUCCESS;
 }
-#else
-#define certificateValidate sequenceValidate
-#endif
 
 int
 octetStringMatch(
@@ -145,7 +280,7 @@ octetStringMatch(
        return LDAP_SUCCESS;
 }
 
-static int
+int
 octetStringOrderingMatch(
        int *matchp,
        slap_mask_t flags,
@@ -2078,7 +2213,11 @@ IA5StringNormalize(
        /* Ignore initial whitespace */
        while ( ASCII_SPACE( *p ) ) p++;
 
-       normalized->bv_val = ber_strdup_x( p, ctx );
+       normalized->bv_len = val->bv_len - ( p - val->bv_val );
+       normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
+       AC_MEMCPY( normalized->bv_val, p, normalized->bv_len );
+       normalized->bv_val[normalized->bv_len] = '\0';
+
        p = q = normalized->bv_val;
 
        while ( *p ) {
@@ -2246,7 +2385,7 @@ UUIDNormalize(
 
 
 
-static int
+int
 numericStringValidate(
        Syntax *syntax,
        struct berval *in )
@@ -2292,7 +2431,7 @@ numericStringNormalize(
                }
        }
 
-       /* we should have copied no more then is in val */
+       /* we should have copied no more than is in val */
        assert( (q - normalized->bv_val) <= (p - val->bv_val) );
 
        /* null terminate */
@@ -2618,7 +2757,7 @@ serialNumberAndIssuerValidate(
        if( rc ) return LDAP_INVALID_SYNTAX;
 
        Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerValidate: OKAY\n",
-               in->bv_val, 0, 0 );
+               0, 0, 0 );
        return LDAP_SUCCESS;
 }
 
@@ -3202,7 +3341,6 @@ serialNumberAndIssuerNormalize(
        return LDAP_SUCCESS;
 }
 
-#ifdef HAVE_TLS
 static int
 certificateExactNormalize(
        slap_mask_t usage,
@@ -3212,14 +3350,16 @@ certificateExactNormalize(
        struct berval *normalized,
        void *ctx )
 {
-       int rc = LDAP_INVALID_SYNTAX;
-       unsigned char *p;
-       char *serial = NULL;
+       BerElementBuffer berbuf;
+       BerElement *ber = (BerElement *)&berbuf;
+       ber_tag_t tag;
+       ber_len_t len;
+       ber_int_t i;
+       char serialbuf[64], *serial = serialbuf;
        ber_len_t seriallen;
-       struct berval issuer_dn = BER_BVNULL;
-       X509_NAME *name = NULL;
-       ASN1_INTEGER *sn = NULL;
-       X509 *xcert = NULL;
+       struct berval issuer_dn = BER_BVNULL, bvdn;
+       unsigned char *p;
+       int rc = LDAP_INVALID_SYNTAX;
 
        if( BER_BVISEMPTY( val ) ) goto done;
 
@@ -3229,19 +3369,78 @@ certificateExactNormalize(
 
        assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
 
-       p = (unsigned char *)val->bv_val;
-       xcert = d2i_X509( NULL, &p, val->bv_len);
-       if( xcert == NULL ) goto done;
+       ber_init2( ber, val, LBER_USE_DER );
+       tag = ber_skip_tag( ber, &len );        /* Signed Sequence */
+       tag = ber_skip_tag( ber, &len );        /* Sequence */
+       tag = ber_peek_tag( ber, &len );        /* Optional version? */
+       if ( tag == SLAP_X509_OPT_C_VERSION ) {
+               tag = ber_skip_tag( ber, &len );
+               tag = ber_get_int( ber, &i );   /* version */
+       }
+
+       /* NOTE: move the test here from certificateNormalize,
+        * so that we can validate certs with serial longer
+        * than sizeof(ber_int_t) */
+       tag = ber_peek_tag( ber, &len );        /* serial */
+       if ( len > sizeof(ber_int_t) ) {
+               unsigned char *ptr;
+               
+               tag = ber_skip_tag( ber, &len );
+               ptr = (unsigned char *)ber->ber_ptr;
+               ber_skip_data( ber, len );
+
+               while ( ptr[0] == '\0' && len > 0 ) {
+                       ptr++;
+                       len--;
+               }
+
+#if defined(USE_MP_BIGNUM)
+               /* TODO */
+
+#elif defined(USE_MP_GMP)
+               /* TODO */
+               /* hint: use mpz_import(), mpz_get_str() */
+
+#elif defined(USE_MP_LONG_LONG)
+               if ( len <= sizeof( unsigned long long ) ) {
+                       unsigned long long      sn = 0;
+                       int                     i;
 
-       sn=X509_get_serialNumber(xcert);
-       if ( sn == NULL ) goto done;
-       serial=i2s_ASN1_INTEGER(0, sn );
-       if( serial == NULL ) goto done;
-       seriallen=strlen(serial);
+                       sn = ptr[0];
 
-       name=X509_get_issuer_name(xcert);
-       if( name == NULL ) goto done;
-       rc = dnX509normalize( name, &issuer_dn );
+                       for ( i = 1; i < len; i++ ) {
+                               sn <<= 8;
+                               sn += ptr[i];
+                       }
+
+                       seriallen = snprintf( serialbuf, sizeof(serialbuf), "%llu", sn );
+
+               } else {
+                       /* do not accept serialNumber that requires
+                        * more than long long */
+                       rc = LDAP_INVALID_SYNTAX;
+                       goto done;
+               }
+
+#else
+               /* do not accept serialNumber that requires
+                * more than long */
+               rc = LDAP_INVALID_SYNTAX;
+               goto done;
+#endif
+
+       } else {
+               tag = ber_get_int( ber, &i );   /* serial */
+               seriallen = snprintf( serialbuf, sizeof(serialbuf), "%d", i );
+       }
+       tag = ber_skip_tag( ber, &len );        /* SignatureAlg */
+       ber_skip_data( ber, len );
+       tag = ber_peek_tag( ber, &len );        /* IssuerDN */
+       len = ber_ptrlen( ber );
+       bvdn.bv_val = val->bv_val + len;
+       bvdn.bv_len = val->bv_len - len;
+
+       rc = dnX509normalize( &bvdn, &issuer_dn );
        if( rc != LDAP_SUCCESS ) goto done;
 
        normalized->bv_len = STRLENOF( "{ serialNumber , issuer \"\" }" )
@@ -3273,14 +3472,407 @@ certificateExactNormalize(
        rc = LDAP_SUCCESS;
 
 done:
-       if (xcert) X509_free(xcert);
-       if (serial) ch_free(serial);
-       if (issuer_dn.bv_val) ber_memfree(issuer_dn.bv_val);
+       if ( issuer_dn.bv_val ) ber_memfree( issuer_dn.bv_val );
+       if ( serial != serialbuf ) ber_memfree_x( serial, ctx );
 
        return rc;
 }
-#endif /* HAVE_TLS */
 
+static int
+hexValidate(
+       Syntax *syntax,
+       struct berval *in )
+{
+       int     i;
+
+       assert( in != NULL );
+       assert( !BER_BVISNULL( in ) );
+
+       for ( i = 0; i < in->bv_len; i++ ) {
+               if ( !ASCII_HEX( in->bv_val[ i ] ) ) {
+                       return LDAP_INVALID_SYNTAX;
+               }
+       }
+
+       return LDAP_SUCCESS;
+}
+
+/* Normalize a SID as used inside a CSN:
+ * three-digit numeric string */
+static int
+hexNormalize(
+       slap_mask_t usage,
+       Syntax *syntax,
+       MatchingRule *mr,
+       struct berval *val,
+       struct berval *normalized,
+       void *ctx )
+{
+       int     i;
+
+       ber_dupbv_x( normalized, val, ctx );
+
+       for ( i = 0; i < normalized->bv_len; i++ ) {
+               if ( !ASCII_HEX( normalized->bv_val[ i ] ) ) {
+                       ber_memfree_x( normalized->bv_val, ctx );
+                       BER_BVZERO( normalized );
+                       return LDAP_INVALID_SYNTAX;
+               }
+
+               normalized->bv_val[ i ] = TOLOWER( normalized->bv_val[ i ] );
+       }
+
+       return LDAP_SUCCESS;
+}
+
+static int
+sidValidate (
+       Syntax *syntax,
+       struct berval *in )
+{
+       assert( in != NULL );
+       assert( !BER_BVISNULL( in ) );
+
+       if ( in->bv_len != 3 ) {
+               return LDAP_INVALID_SYNTAX;
+       }
+
+       return hexValidate( NULL, in );
+}
+
+/* Normalize a SID as used inside a CSN:
+ * three-digit numeric string */
+static int
+sidNormalize(
+       slap_mask_t usage,
+       Syntax *syntax,
+       MatchingRule *mr,
+       struct berval *val,
+       struct berval *normalized,
+       void *ctx )
+{
+       if ( val->bv_len != 3 ) {
+               return LDAP_INVALID_SYNTAX;
+       }
+
+       return hexNormalize( 0, NULL, NULL, val, normalized, ctx );
+}
+
+static int
+sidPretty(
+       Syntax *syntax,
+       struct berval *val,
+       struct berval *out,
+       void *ctx )
+{
+       return sidNormalize( SLAP_MR_VALUE_OF_SYNTAX, NULL, NULL, val, out, ctx );
+}
+
+/* Normalize a SID as used inside a CSN, either as-is
+ * (assertion value) or extracted from the CSN
+ * (attribute value) */
+static int
+csnSidNormalize(
+       slap_mask_t usage,
+       Syntax *syntax,
+       MatchingRule *mr,
+       struct berval *val,
+       struct berval *normalized,
+       void *ctx )
+{
+       struct berval   bv;
+       char            *ptr,
+                       buf[ 4 ];
+
+
+       if ( BER_BVISEMPTY( val ) ) {
+               return LDAP_INVALID_SYNTAX;
+       }
+
+       if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
+               return sidNormalize( 0, NULL, NULL, val, normalized, ctx );
+       }
+
+       assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
+
+       ptr = ber_bvchr( val, '#' );
+       if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
+               return LDAP_INVALID_SYNTAX;
+       }
+
+       bv.bv_val = ptr + 1;
+       bv.bv_len = val->bv_len - ( ptr + 1 - val->bv_val );
+
+       ptr = ber_bvchr( &bv, '#' );
+       if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
+               return LDAP_INVALID_SYNTAX;
+       }
+
+       bv.bv_val = ptr + 1;
+       bv.bv_len = val->bv_len - ( ptr + 1 - val->bv_val );
+               
+       ptr = ber_bvchr( &bv, '#' );
+       if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
+               return LDAP_INVALID_SYNTAX;
+       }
+
+       bv.bv_len = ptr - bv.bv_val;
+
+       if ( bv.bv_len == 2 ) {
+               /* OpenLDAP 2.3 SID */
+               buf[ 0 ] = '0';
+               buf[ 1 ] = bv.bv_val[ 0 ];
+               buf[ 2 ] = bv.bv_val[ 1 ];
+               buf[ 3 ] = '\0';
+
+               bv.bv_val = buf;
+               bv.bv_len = 3;
+       }
+
+       return sidNormalize( 0, NULL, NULL, &bv, normalized, ctx );
+}
+
+static int
+csnValidate(
+       Syntax *syntax,
+       struct berval *in )
+{
+       struct berval   bv;
+       char            *ptr;
+       int             rc;
+
+       assert( in != NULL );
+       assert( !BER_BVISNULL( in ) );
+
+       if ( BER_BVISEMPTY( in ) ) {
+               return LDAP_INVALID_SYNTAX;
+       }
+
+       bv = *in;
+
+       ptr = ber_bvchr( &bv, '#' );
+       if ( ptr == NULL || ptr - bv.bv_val == bv.bv_len ) {
+               return LDAP_INVALID_SYNTAX;
+       }
+
+       bv.bv_len = ptr - bv.bv_val;
+       if ( bv.bv_len != STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ" ) &&
+               bv.bv_len != STRLENOF( "YYYYmmddHHMMSSZ" ) )
+       {
+               return LDAP_INVALID_SYNTAX;
+       }
+
+       rc = generalizedTimeValidate( NULL, &bv );
+       if ( rc != LDAP_SUCCESS ) {
+               return rc;
+       }
+
+       bv.bv_val = ptr + 1;
+       bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
+
+       ptr = ber_bvchr( &bv, '#' );
+       if ( ptr == NULL || ptr - in->bv_val == in->bv_len ) {
+               return LDAP_INVALID_SYNTAX;
+       }
+
+       bv.bv_len = ptr - bv.bv_val;
+       if ( bv.bv_len != 6 ) {
+               return LDAP_INVALID_SYNTAX;
+       }
+
+       rc = hexValidate( NULL, &bv );
+       if ( rc != LDAP_SUCCESS ) {
+               return rc;
+       }
+
+       bv.bv_val = ptr + 1;
+       bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
+
+       ptr = ber_bvchr( &bv, '#' );
+       if ( ptr == NULL || ptr - in->bv_val == in->bv_len ) {
+               return LDAP_INVALID_SYNTAX;
+       }
+
+       bv.bv_len = ptr - bv.bv_val;
+       if ( bv.bv_len == 2 ) {
+               /* tolerate old 2-digit replica-id */
+               rc = hexValidate( NULL, &bv );
+
+       } else {
+               rc = sidValidate( NULL, &bv );
+       }
+       if ( rc != LDAP_SUCCESS ) {
+               return rc;
+       }
+
+       bv.bv_val = ptr + 1;
+       bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
+
+       if ( bv.bv_len != 6 ) {
+               return LDAP_INVALID_SYNTAX;
+       }
+
+       return hexValidate( NULL, &bv );
+}
+
+/* Normalize a CSN in OpenLDAP 2.3 format */
+static int
+csnNormalize23(
+       slap_mask_t usage,
+       Syntax *syntax,
+       MatchingRule *mr,
+       struct berval *val,
+       struct berval *normalized,
+       void *ctx )
+{
+       struct berval   gt, cnt, sid, mod;
+       char            *ptr;
+       int             i;
+
+       assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
+       assert( !BER_BVISEMPTY( val ) );
+
+       gt = *val;
+
+       ptr = ber_bvchr( &gt, '#' );
+       if ( ptr == NULL || ptr - gt.bv_val == gt.bv_len ) {
+               return LDAP_INVALID_SYNTAX;
+       }
+
+       gt.bv_len = ptr - gt.bv_val;
+       assert( gt.bv_len == STRLENOF( "YYYYmmddHHMMSSZ" ) );
+
+       cnt.bv_val = ptr + 1;
+       cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val );
+
+       ptr = ber_bvchr( &cnt, '#' );
+       if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
+               return LDAP_INVALID_SYNTAX;
+       }
+
+       cnt.bv_len = ptr - cnt.bv_val;
+       assert( cnt.bv_len == STRLENOF( "000000" ) );
+
+       sid.bv_val = ptr + 1;
+       sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val );
+               
+       ptr = ber_bvchr( &sid, '#' );
+       if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
+               return LDAP_INVALID_SYNTAX;
+       }
+
+       sid.bv_len = ptr - sid.bv_val;
+       assert( sid.bv_len == STRLENOF( "00" ) );
+
+       mod.bv_val = ptr + 1;
+       mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val );
+       assert( mod.bv_len == STRLENOF( "000000" ) );
+
+       normalized->bv_len = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" );
+       normalized->bv_val = ber_memalloc_x( normalized->bv_len + 1, ctx );
+
+       ptr = normalized->bv_val;
+       ptr = lutil_strncopy( ptr, gt.bv_val, gt.bv_len - 1 );
+       ptr = lutil_strcopy( ptr, ".000000Z#" );
+       ptr = lutil_strncopy( ptr, cnt.bv_val, cnt.bv_len );
+       *ptr++ = '#';
+       *ptr++ = '0';
+       for ( i = 0; i < sid.bv_len; i++ ) {
+               *ptr++ = TOLOWER( sid.bv_val[ i ] );
+       }
+       *ptr++ = '#';
+       for ( i = 0; i < mod.bv_len; i++ ) {
+               *ptr++ = TOLOWER( mod.bv_val[ i ] );
+       }
+       *ptr = '\0';
+
+       assert( ptr - normalized->bv_val == normalized->bv_len );
+
+       return LDAP_SUCCESS;
+}
+
+/* Normalize a CSN */
+static int
+csnNormalize(
+       slap_mask_t usage,
+       Syntax *syntax,
+       MatchingRule *mr,
+       struct berval *val,
+       struct berval *normalized,
+       void *ctx )
+{
+       struct berval   cnt, sid, mod;
+       char            *ptr;
+       int             i;
+
+       assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
+
+       if ( BER_BVISEMPTY( val ) ) {
+               return LDAP_INVALID_SYNTAX;
+       }
+
+       if ( val->bv_len == STRLENOF( "YYYYmmddHHMMSSZ#SSSSSS#ID#ssssss" ) ) {
+               /* Openldap <= 2.3 */
+
+               return csnNormalize23( usage, syntax, mr, val, normalized, ctx );
+       }
+
+       assert( val->bv_len == STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ) );
+
+       ptr = ber_bvchr( val, '#' );
+       if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
+               return LDAP_INVALID_SYNTAX;
+       }
+
+       assert( ptr - val->bv_val == STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ" ) );
+
+       cnt.bv_val = ptr + 1;
+       cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val );
+
+       ptr = ber_bvchr( &cnt, '#' );
+       if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
+               return LDAP_INVALID_SYNTAX;
+       }
+
+       assert( ptr - cnt.bv_val == STRLENOF( "000000" ) );
+
+       sid.bv_val = ptr + 1;
+       sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val );
+               
+       ptr = ber_bvchr( &sid, '#' );
+       if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
+               return LDAP_INVALID_SYNTAX;
+       }
+
+       sid.bv_len = ptr - sid.bv_val;
+       assert( sid.bv_len == STRLENOF( "000" ) );
+
+       mod.bv_val = ptr + 1;
+       mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val );
+
+       assert( mod.bv_len == STRLENOF( "000000" ) );
+
+       ber_dupbv_x( normalized, val, ctx );
+
+       for ( i = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#" );
+               i < normalized->bv_len; i++ )
+       {
+               /* assume it's already validated that's all hex digits */
+               normalized->bv_val[ i ] = TOLOWER( normalized->bv_val[ i ] );
+       }
+
+       return LDAP_SUCCESS;
+}
+
+static int
+csnPretty(
+       Syntax *syntax,
+       struct berval *val,
+       struct berval *out,
+       void *ctx )
+{
+       return csnNormalize( SLAP_MR_VALUE_OF_SYNTAX, NULL, NULL, val, out, ctx );
+}
 
 #ifndef SUPPORT_OBSOLETE_UTC_SYNTAX
 /* slight optimization - does not need the start parameter */
@@ -3960,6 +4552,12 @@ firstComponentNormalize(
        return rc;
 }
 
+static char *country_gen_syn[] = {
+       "1.3.6.1.4.1.1466.115.121.1.15",
+       "1.3.6.1.4.1.1466.115.121.1.26",
+       "1.3.6.1.4.1.1466.115.121.1.44",
+       NULL
+};
 
 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
@@ -3967,178 +4565,195 @@ firstComponentNormalize(
 static slap_syntax_defs_rec syntax_defs[] = {
        {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' "
                X_BINARY X_NOT_H_R ")",
-               SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL},
+               SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL, NULL},
        {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
-               0, NULL, NULL},
+               0, NULL, NULL, NULL},
        {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
-               0, NULL, NULL},
+               0, NULL, NULL, NULL},
        {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' "
                X_NOT_H_R ")",
-               SLAP_SYNTAX_BLOB, blobValidate, NULL},
+               SLAP_SYNTAX_BLOB, NULL, blobValidate, NULL},
        {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' "
                X_NOT_H_R ")",
-               SLAP_SYNTAX_BER, berValidate, NULL},
+               SLAP_SYNTAX_BER, NULL, berValidate, NULL},
        {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
-               0, bitStringValidate, NULL },
+               0, NULL, bitStringValidate, NULL },
        {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
-               0, booleanValidate, NULL},
+               0, NULL, booleanValidate, NULL},
        {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
                X_BINARY X_NOT_H_R ")",
-               SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, certificateValidate, NULL},
+               SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
+               NULL, certificateValidate, NULL},
        {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
                X_BINARY X_NOT_H_R ")",
-               SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, sequenceValidate, NULL},
+               SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
+               NULL, certificateListValidate, NULL},
        {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
                X_BINARY X_NOT_H_R ")",
-               SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, sequenceValidate, NULL},
+               SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
+               NULL, sequenceValidate, NULL},
+#if 0  /* need to go __after__ printableString */
        {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
-               0, countryStringValidate, NULL},
+               0, "1.3.6.1.4.1.1466.115.121.1.44",
+               countryStringValidate, NULL},
+#endif
        {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
-               0, dnValidate, dnPretty},
+               0, NULL, dnValidate, dnPretty},
        {"( 1.2.36.79672281.1.5.0 DESC 'RDN' )",
-               0, rdnValidate, rdnPretty},
+               0, NULL, rdnValidate, rdnPretty},
 #ifdef LDAP_COMP_MATCH
        {"( 1.2.36.79672281.1.5.3 DESC 'allComponents' )",
-               0, allComponentsValidate, NULL},
+               0, NULL, allComponentsValidate, NULL},
        {"( 1.2.36.79672281.1.5.2 DESC 'componentFilterMatch assertion') ",
-               0, componentFilterValidate, NULL},
+               0, NULL, componentFilterValidate, NULL},
 #endif
        {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
-               0, NULL, NULL},
+               0, NULL, NULL, NULL},
        {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
-               0, deliveryMethodValidate, NULL},
+               0, NULL, deliveryMethodValidate, NULL},
        {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
-               0, UTF8StringValidate, NULL},
+               0, NULL, UTF8StringValidate, NULL},
        {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
-               0, NULL, NULL},
+               0, NULL, NULL, NULL},
        {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
-               0, NULL, NULL},
+               0, NULL, NULL, NULL},
        {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
-               0, NULL, NULL},
+               0, NULL, NULL, NULL},
        {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
-               0, NULL, NULL},
+               0, NULL, NULL, NULL},
        {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
-               0, NULL, NULL},
+               0, NULL, NULL, NULL},
        {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
-               0, printablesStringValidate, NULL},
+               0, NULL, printablesStringValidate, NULL},
        {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
-               SLAP_SYNTAX_BLOB, NULL, NULL},
+               SLAP_SYNTAX_BLOB, NULL, NULL, NULL},
        {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
-               0, generalizedTimeValidate, NULL},
+               0, NULL, generalizedTimeValidate, NULL},
        {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
-               0, NULL, NULL},
+               0, NULL, NULL, NULL},
        {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
-               0, IA5StringValidate, NULL},
+               0, NULL, IA5StringValidate, NULL},
        {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
-               0, integerValidate, NULL},
+               0, NULL, integerValidate, NULL},
        {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
-               SLAP_SYNTAX_BLOB, blobValidate, NULL},
+               SLAP_SYNTAX_BLOB, NULL, blobValidate, NULL},
        {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
-               0, NULL, NULL},
+               0, NULL, NULL, NULL},
        {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
-               0, NULL, NULL},
+               0, NULL, NULL, NULL},
        {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
-               0, NULL, NULL},
+               0, NULL, NULL, NULL},
        {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
-               0, NULL, NULL},
+               0, NULL, NULL, NULL},
        {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
-               0, NULL, NULL},
+               0, NULL, NULL, NULL},
        {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
-               0, nameUIDValidate, nameUIDPretty },
+               0, NULL, nameUIDValidate, nameUIDPretty },
        {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
-               0, NULL, NULL},
+               0, NULL, NULL, NULL},
        {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
-               0, numericStringValidate, NULL},
+               0, NULL, numericStringValidate, NULL},
        {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
-               0, NULL, NULL},
+               0, NULL, NULL, NULL},
        {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
-               0, numericoidValidate, NULL},
+               0, NULL, numericoidValidate, NULL},
        {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
-               0, IA5StringValidate, NULL},
+               0, NULL, IA5StringValidate, NULL},
        {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
-               0, blobValidate, NULL},
+               0, NULL, blobValidate, NULL},
        {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
-               0, UTF8StringValidate, NULL},
+               0, NULL, UTF8StringValidate, NULL},
        {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
-               0, NULL, NULL},
+               0, NULL, NULL, NULL},
        {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
-               0, NULL, NULL},
+               0, NULL, NULL, NULL},
        {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
-               0, printableStringValidate, NULL},
+               0, NULL, printableStringValidate, NULL},
+       /* moved here because now depends on Directory String, IA5 String 
+        * and Printable String */
+       {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
+               0, country_gen_syn, countryStringValidate, NULL},
        {"( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' )",
 #define subtreeSpecificationValidate UTF8StringValidate /* FIXME */
-               0, subtreeSpecificationValidate, NULL},
+               0, NULL, subtreeSpecificationValidate, NULL},
        {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
                X_BINARY X_NOT_H_R ")",
-               SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL},
+               SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, berValidate, NULL},
        {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
-               0, printableStringValidate, NULL},
+               0, NULL, printableStringValidate, NULL},
        {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
-               0, NULL, NULL},
+               0, NULL, NULL, NULL},
        {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
-               0, printablesStringValidate, NULL},
+               0, NULL, printablesStringValidate, NULL},
 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
        {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
-               0, utcTimeValidate, NULL},
+               0, NULL, utcTimeValidate, NULL},
 #endif
        {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
-               0, NULL, NULL},
+               0, NULL, NULL, NULL},
        {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
-               0, NULL, NULL},
+               0, NULL, NULL, NULL},
        {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
-               0, NULL, NULL},
+               0, NULL, NULL, NULL},
        {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
-               0, NULL, NULL},
+               0, NULL, NULL, NULL},
        {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
-               0, NULL, NULL},
+               0, NULL, NULL, NULL},
 
        /* RFC 2307 NIS Syntaxes */
        {"( 1.3.6.1.1.1.0.0  DESC 'RFC2307 NIS Netgroup Triple' )",
-               0, nisNetgroupTripleValidate, NULL},
+               0, NULL, nisNetgroupTripleValidate, NULL},
        {"( 1.3.6.1.1.1.0.1  DESC 'RFC2307 Boot Parameter' )",
-               0, bootParameterValidate, NULL},
+               0, NULL, bootParameterValidate, NULL},
 
        /* draft-zeilenga-ldap-x509 */
        {"( 1.3.6.1.1.15.1 DESC 'Certificate Exact Assertion' )",
-               SLAP_SYNTAX_HIDE,
+               SLAP_SYNTAX_HIDE, NULL,
                serialNumberAndIssuerValidate,
                serialNumberAndIssuerPretty},
        {"( 1.3.6.1.1.15.2 DESC 'Certificate Assertion' )",
-               SLAP_SYNTAX_HIDE, NULL, NULL},
+               SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
        {"( 1.3.6.1.1.15.3 DESC 'Certificate Pair Exact Assertion' )",
-               SLAP_SYNTAX_HIDE, NULL, NULL},
+               SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
        {"( 1.3.6.1.1.15.4 DESC 'Certificate Pair Assertion' )",
-               SLAP_SYNTAX_HIDE, NULL, NULL},
+               SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
        {"( 1.3.6.1.1.15.5 DESC 'Certificate List Exact Assertion' )",
-               SLAP_SYNTAX_HIDE, NULL, NULL},
+               SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
        {"( 1.3.6.1.1.15.6 DESC 'Certificate List Assertion' )",
-               SLAP_SYNTAX_HIDE, NULL, NULL},
+               SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
        {"( 1.3.6.1.1.15.7 DESC 'Algorithm Identifier' )",
-               SLAP_SYNTAX_HIDE, NULL, NULL},
+               SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
 
 #ifdef SLAPD_AUTHPASSWD
        /* needs updating */
        {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
-               SLAP_SYNTAX_HIDE, NULL, NULL},
+               SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
 #endif
 
        {"( 1.3.6.1.1.16.1 DESC 'UUID' )",
-               0, UUIDValidate, UUIDPretty},
+               0, NULL, UUIDValidate, UUIDPretty},
 
        {"( 1.3.6.1.4.1.4203.666.11.2.1 DESC 'CSN' )",
-               SLAP_SYNTAX_HIDE, csnValidate, NULL},
+               SLAP_SYNTAX_HIDE, NULL, csnValidate, csnPretty },
+
+       {"( 1.3.6.1.4.1.4203.666.11.2.4 DESC 'CSN SID' )",
+               SLAP_SYNTAX_HIDE, NULL, sidValidate, sidPretty },
 
        /* OpenLDAP Void Syntax */
        {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
-               SLAP_SYNTAX_HIDE, inValidate, NULL},
+               SLAP_SYNTAX_HIDE, NULL, inValidate, NULL},
 
        /* FIXME: OID is unused, but not registered yet */
        {"( 1.3.6.1.4.1.4203.666.2.7 DESC 'OpenLDAP authz' )",
-               SLAP_SYNTAX_HIDE, authzValidate, authzPretty},
+               SLAP_SYNTAX_HIDE, NULL, authzValidate, authzPretty},
 
-       {NULL, 0, NULL, NULL}
+       {NULL, 0, NULL, NULL, NULL}
 };
 
+char *csnSIDMatchSyntaxes[] = {
+       "1.3.6.1.4.1.4203.666.11.2.1" /* csn */,
+       NULL
+};
 char *certificateExactMatchSyntaxes[] = {
        "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
        NULL
@@ -4474,12 +5089,8 @@ static slap_mrule_defs_rec mrule_defs[] = {
        {"( 2.5.13.34 NAME 'certificateExactMatch' "
                "SYNTAX 1.3.6.1.1.15.1 )",
                SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateExactMatchSyntaxes,
-#ifdef HAVE_TLS
                NULL, certificateExactNormalize, octetStringMatch,
                octetStringIndexer, octetStringFilter,
-#else
-               NULL, NULL, NULL, NULL, NULL,
-#endif
                NULL },
 
        {"( 2.5.13.35 NAME 'certificateMatch' "
@@ -4557,7 +5168,7 @@ static slap_mrule_defs_rec mrule_defs[] = {
        {"( 1.3.6.1.4.1.4203.666.11.2.2 NAME 'CSNMatch' "
                "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
                SLAP_MR_HIDE | SLAP_MR_EQUALITY | SLAP_MR_ORDERED_INDEX, NULL,
-               NULL, NULL, csnMatch,
+               NULL, csnNormalize, csnMatch,
                csnIndexer, csnFilter,
                NULL},
 
@@ -4568,6 +5179,13 @@ static slap_mrule_defs_rec mrule_defs[] = {
                NULL, NULL,
                "CSNMatch" },
 
+       {"( 1.3.6.1.4.1.4203.666.11.2.5 NAME 'CSNSIDMatch' "
+               "SYNTAX 1.3.6.1.4.1.4203.666.11.2.4 )",
+               SLAP_MR_EQUALITY | SLAP_MR_EXT, csnSIDMatchSyntaxes,
+               NULL, csnSidNormalize, octetStringMatch,
+               octetStringIndexer, octetStringFilter,
+               NULL },
+
        /* FIXME: OID is unused, but not registered yet */
        {"( 1.3.6.1.4.1.4203.666.4.12 NAME 'authzMatch' "
                "SYNTAX 1.3.6.1.4.1.4203.666.2.7 )",
index 43eb1be76687933f097de5ac0881260e74ef5ead..b4999b958b75090bd9baf0e1ff18ef1655482643 100644 (file)
@@ -85,9 +85,9 @@ oidValidate(
 
 
 static int objectClassPretty(
-       struct slap_syntax *syntax,
-       struct berval * in,
-       struct berval * out,
+       Syntax *syntax,
+       struct berval *in,
+       struct berval *out,
        void *ctx )
 {
        ObjectClass *oc;
@@ -241,8 +241,8 @@ objectSubClassMatch(
 static int objectSubClassIndexer( 
        slap_mask_t use,
        slap_mask_t mask,
-       struct slap_syntax *syntax,
-       struct slap_matching_rule *mr,
+       Syntax *syntax,
+       MatchingRule *mr,
        struct berval *prefix,
        BerVarray values,
        BerVarray *keysp,
@@ -532,12 +532,12 @@ static struct slap_schema_ad_map {
                offsetof(struct slap_internal_schema, si_ad_collectiveExclusions) },
 #endif
 
-       { "entryDN", "( 1.3.6.1.4.1.4203.666.1.33 NAME 'entryDN' "   
+       { "entryDN", "( 1.3.6.1.1.20 NAME 'entryDN' "   
                        "DESC 'DN of the entry' "
                        "EQUALITY distinguishedNameMatch "
                        "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 "
                        "SINGLE-VALUE NO-USER-MODIFICATION USAGE directoryOperation )",
-               NULL, SLAP_AT_HIDE|SLAP_AT_DYNAMIC,
+               NULL, SLAP_AT_DYNAMIC,
                NULL, NULL,
                NULL, NULL, NULL, NULL, NULL,
                offsetof(struct slap_internal_schema, si_ad_entryDN) },
index 05535257b48e217c19b762361cffd5cefb0db3cf..80f44f5044940d90f37fc4472b189ef4d554b467 100644 (file)
@@ -49,6 +49,7 @@ static char *const err2text[] = {
        "Duplicate matchingRule",
        "Syntax not found",
        "Duplicate ldapSyntax",
+       "Superior syntax not found",
        "OID or name required",
        "Qualifier not supported",
        "Invalid NAME",
@@ -135,19 +136,19 @@ parse_cr(
 
        cr = ldap_str2contentrule( line, &code, &err, LDAP_SCHEMA_ALLOW_ALL );
        if ( !cr ) {
-               snprintf( c->msg, sizeof( c->msg ), "%s: %s before %s",
+               snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s: %s before %s",
                        c->argv[0], ldap_scherr2str( code ), err );
                Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
-                       "%s %s\n", c->log, c->msg, 0 );
+                       "%s %s\n", c->log, c->cr_msg, 0 );
                cr_usage();
                return 1;
        }
 
        if ( cr->cr_oid == NULL ) {
-               snprintf( c->msg, sizeof( c->msg ), "%s: OID is missing",
+               snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s: OID is missing",
                        c->argv[0] );
                Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
-                       "%s %s\n", c->log, c->msg, 0 );
+                       "%s %s\n", c->log, c->cr_msg, 0 );
                cr_usage();
                code = 1;
                goto done;
@@ -155,10 +156,10 @@ parse_cr(
 
        code = cr_add( cr, 1, scr, &err );
        if ( code ) {
-               snprintf( c->msg, sizeof( c->msg ), "%s: %s: \"%s\"",
+               snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s: %s: \"%s\"",
                        c->argv[0], scherr2str(code), err);
                Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
-                       "%s %s\n", c->log, c->msg, 0 );
+                       "%s %s\n", c->log, c->cr_msg, 0 );
                code = 1;
                goto done;
        }
@@ -187,19 +188,19 @@ parse_oc(
 
        oc = ldap_str2objectclass(line, &code, &err, LDAP_SCHEMA_ALLOW_ALL );
        if ( !oc ) {
-               snprintf( c->msg, sizeof( c->msg ), "%s: %s before %s",
+               snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s: %s before %s",
                        c->argv[0], ldap_scherr2str( code ), err );
                Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
-                       "%s %s\n", c->log, c->msg, 0 );
+                       "%s %s\n", c->log, c->cr_msg, 0 );
                oc_usage();
                return 1;
        }
 
        if ( oc->oc_oid == NULL ) {
-               snprintf( c->msg, sizeof( c->msg ), "%s: OID is missing",
+               snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s: OID is missing",
                        c->argv[0] );
                Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
-                       "%s %s\n", c->log, c->msg, 0 );
+                       "%s %s\n", c->log, c->cr_msg, 0 );
                oc_usage();
                code = 1;
                goto done;
@@ -207,10 +208,10 @@ parse_oc(
 
        code = oc_add( oc, 1, soc, prev, &err );
        if ( code ) {
-               snprintf( c->msg, sizeof( c->msg ), "%s: %s: \"%s\"",
+               snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s: %s: \"%s\"",
                        c->argv[0], scherr2str(code), err);
                Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
-                       "%s %s\n", c->log, c->msg, 0 );
+                       "%s %s\n", c->log, c->cr_msg, 0 );
                code = 1;
                goto done;
        }
@@ -282,19 +283,19 @@ parse_at(
 
        at = ldap_str2attributetype( line, &code, &err, LDAP_SCHEMA_ALLOW_ALL );
        if ( !at ) {
-               snprintf( c->msg, sizeof( c->msg ), "%s: %s before %s",
+               snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s: %s before %s",
                        c->argv[0], ldap_scherr2str(code), err );
                Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
-                       "%s %s\n", c->log, c->msg, 0 );
+                       "%s %s\n", c->log, c->cr_msg, 0 );
                at_usage();
                return 1;
        }
 
        if ( at->at_oid == NULL ) {
-               snprintf( c->msg, sizeof( c->msg ), "%s: OID is missing",
+               snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s: OID is missing",
                        c->argv[0] );
                Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
-                       "%s %s\n", c->log, c->msg, 0 );
+                       "%s %s\n", c->log, c->cr_msg, 0 );
                at_usage();
                code = 1;
                goto done;
@@ -302,20 +303,20 @@ parse_at(
 
        /* operational attributes should be defined internally */
        if ( at->at_usage ) {
-               snprintf( c->msg, sizeof( c->msg ), "%s: \"%s\" is operational",
+               snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s: \"%s\" is operational",
                        c->argv[0], at->at_oid );
                Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
-                       "%s %s\n", c->log, c->msg, 0 );
+                       "%s %s\n", c->log, c->cr_msg, 0 );
                code = 1;
                goto done;
        }
 
        code = at_add( at, 1, sat, prev, &err);
        if ( code ) {
-               snprintf( c->msg, sizeof( c->msg ), "%s: %s: \"%s\"",
+               snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s: %s: \"%s\"",
                        c->argv[0], scherr2str(code), err);
                Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
-                       "%s %s\n", c->log, c->msg, 0 );
+                       "%s %s\n", c->log, c->cr_msg, 0 );
                code = 1;
                goto done;
        }
index f53584a9e88003fc62232b36f96f3b7a40b2fc80..0c1d525f8b91c9e253a00c13b533ed4f11ea3bbb 100644 (file)
@@ -41,8 +41,8 @@ do_search(
        struct berval base = BER_BVNULL;
        ber_len_t       siz, off, i;
 
-       Debug( LDAP_DEBUG_TRACE, "do_search\n", 0, 0, 0 );
-
+       Debug( LDAP_DEBUG_TRACE, "%s do_search\n",
+               op->o_log_prefix, 0, 0 );
        /*
         * Parse the search request.  It looks like this:
         *
@@ -112,8 +112,8 @@ do_search(
 
        rs->sr_err = dnPrettyNormal( NULL, &base, &op->o_req_dn, &op->o_req_ndn, op->o_tmpmemctx );
        if( rs->sr_err != LDAP_SUCCESS ) {
-               Debug( LDAP_DEBUG_ANY,
-                       "do_search: invalid dn (%s)\n", base.bv_val, 0, 0 );
+               Debug( LDAP_DEBUG_ANY, "%s do_search: invalid dn (%s)\n",
+                       op->o_log_prefix, base.bv_val, 0 );
                send_ldap_error( op, rs, LDAP_INVALID_DN_SYNTAX, "invalid DN" );
                goto return_results;
        }
@@ -163,8 +163,8 @@ do_search(
        }
 
        if( get_ctrls( op, rs, 1 ) != LDAP_SUCCESS ) {
-               Debug( LDAP_DEBUG_ANY, "do_search: get_ctrls failed\n", 0, 0, 0 );
-
+               Debug( LDAP_DEBUG_ANY, "%s do_search: get_ctrls failed\n",
+                       op->o_log_prefix, 0, 0 );
                goto return_results;
        }
 
@@ -239,12 +239,8 @@ return_results:;
 int
 fe_op_search( Operation *op, SlapReply *rs )
 {
-       int                     manageDSAit;
-       int                     be_manageDSAit;
        BackendDB               *bd = op->o_bd;
 
-       manageDSAit = get_manageDSAit( op );
-
        /* fake while loop to allow breaking out */
        while ( op->ors_scope == LDAP_SCOPE_BASE ) {
                Entry *entry = NULL;
@@ -320,9 +316,7 @@ fe_op_search( Operation *op, SlapReply *rs )
         * if we don't hold it.
         */
 
-       be_manageDSAit = manageDSAit;
-
-       op->o_bd = select_backend( &op->o_req_ndn, be_manageDSAit, 1 );
+       op->o_bd = select_backend( &op->o_req_ndn, 1 );
        if ( op->o_bd == NULL ) {
                rs->sr_ref = referral_rewrite( default_referral,
                        NULL, &op->o_req_dn, op->ors_scope );
index c63361432b042e6643a832acb6bd8309554a7297..c42d8f4277f72ee562f80cb902322836af69c0ec 100644 (file)
@@ -21,7 +21,7 @@
 LDAP_BEGIN_DECL
 
 typedef struct slap_set_cookie {
-       struct slap_op *set_op;
+       Operation *set_op;
 } SetCookie;
 
 /* this routine needs to return the bervals instead of
index e60faf24398139020a65ce7bf043451504ee27a3..4feab16e2b2438f02943fe1a892db05ece729aa9 100644 (file)
@@ -266,7 +266,7 @@ slap_sl_malloc(
        int i, j;
 
 #ifdef SLAP_NO_SL_MALLOC
-       return ber_malloc_x( size, NULL );
+       return ber_memalloc_x( size, NULL );
 #endif
 
        /* ber_set_option calls us like this */
index f4c1cf7d1d99f32796b03ab0d7f4f0149a257d24..75aa25d1a92b32aa292b047133e3796b19988f88 100644 (file)
 LDAP_BEGIN_DECL
 
 #define SLAP_LIGHTWEIGHT_DISPATCHER /* experimental slapd architecture */
-#ifdef LDAP_PVT_THREAD_POOL_SEM_LOAD_CONTROL
-#define SLAP_SEM_LOAD_CONTROL
-#endif
 
 #ifdef LDAP_DEVEL
 #define LDAP_COLLECTIVE_ATTRIBUTES
 #define LDAP_COMP_MATCH
 #define LDAP_SYNC_TIMESTAMP
-#define SLAP_SORTEDRESULTS
+#define SLAP_CONTROL_X_SORTEDRESULTS
+#define SLAP_CONTROL_X_SESSION_TRACKING
 #endif
 
 #define LDAP_DYNAMIC_OBJECTS
@@ -103,6 +101,13 @@ LDAP_BEGIN_DECL
 #define SERVICE_NAME  OPENLDAP_PACKAGE "-slapd"
 #define SLAPD_ANONYMOUS ""
 
+#ifdef HAVE_TCPD
+# include <tcpd.h>
+# define SLAP_STRING_UNKNOWN   STRING_UNKNOWN
+#else /* ! TCP Wrappers */
+# define SLAP_STRING_UNKNOWN   "unknown"
+#endif /* ! TCP Wrappers */
+
 /* LDAPMod.mod_op value ===> Must be kept in sync with ldap.h!
  * This is a value used internally by the backends. It is needed to allow
  * adding values that already exist without getting an error as required by
@@ -268,7 +273,7 @@ typedef struct slap_ssf_set {
 #define SLAP_SYNTAX_ATTRIBUTETYPES_OID  "1.3.6.1.4.1.1466.115.121.1.3"
 #define SLAP_SYNTAX_OBJECTCLASSES_OID   "1.3.6.1.4.1.1466.115.121.1.37"
 #define SLAP_SYNTAX_MATCHINGRULEUSES_OID "1.3.6.1.4.1.1466.115.121.1.31"
-#define SLAP_SYNTAX_CONTENTRULE_OID             "1.3.6.1.4.1.1466.115.121.1.16"
+#define SLAP_SYNTAX_CONTENTRULE_OID     "1.3.6.1.4.1.1466.115.121.1.16"
 
 /*
  * represents schema information for a database
@@ -292,6 +297,7 @@ enum {
        SLAP_SCHERR_MR_DUP,
        SLAP_SCHERR_SYN_NOT_FOUND,
        SLAP_SCHERR_SYN_DUP,
+       SLAP_SCHERR_SYN_SUP_NOT_FOUND,
        SLAP_SCHERR_NO_NAME,
        SLAP_SCHERR_NOT_SUPPORTED,
        SLAP_SCHERR_BAD_DESCR,
@@ -304,7 +310,42 @@ enum {
        SLAP_SCHERR_LAST
 };
 
-typedef union slap_sockaddr {
+/* forward declarations */
+typedef struct Syntax Syntax;
+typedef struct MatchingRule MatchingRule;
+typedef struct MatchingRuleUse MatchingRuleUse;
+typedef struct MatchingRuleAssertion MatchingRuleAssertion;
+typedef struct OidMacro OidMacro;
+typedef struct ObjectClass ObjectClass;
+typedef struct AttributeType AttributeType;
+typedef struct AttributeDescription AttributeDescription;
+typedef struct AttributeName AttributeName;
+typedef struct ContentRule ContentRule;
+
+typedef struct AttributeAssertion AttributeAssertion;
+typedef struct SubstringsAssertion SubstringsAssertion;
+typedef struct Filter Filter;
+typedef struct ValuesReturnFilter ValuesReturnFilter;
+typedef struct Attribute Attribute;
+#ifdef LDAP_COMP_MATCH
+typedef struct ComponentData ComponentData;
+typedef struct ComponentFilter ComponentFilter;
+#endif
+
+typedef struct Entry Entry;
+typedef struct Modification Modification;
+typedef struct Modifications Modifications;
+typedef struct LDAPModList LDAPModList;
+
+typedef struct BackendInfo BackendInfo;                /* per backend type */
+typedef struct BackendDB BackendDB;            /* per backend database */
+
+typedef struct Connection Connection;
+typedef struct Operation Operation;
+typedef struct SlapReply SlapReply;
+/* end of forward declarations */
+
+typedef union Sockaddr {
        struct sockaddr sa_addr;
        struct sockaddr_in sa_in_addr;
 #ifdef LDAP_PF_INET6
@@ -320,25 +361,21 @@ typedef union slap_sockaddr {
 extern int slap_inet4or6;
 #endif
 
-typedef struct slap_oid_macro {
+struct OidMacro {
        struct berval som_oid;
        BerVarray som_names;
        BerVarray som_subs;
 #define        SLAP_OM_HARDCODE        0x10000U        /* This is hardcoded schema */
        int som_flags;
-       LDAP_STAILQ_ENTRY(slap_oid_macro) som_next;
-} OidMacro;
-
-/* forward declarations */
-struct slap_syntax;
-struct slap_matching_rule;
+       LDAP_STAILQ_ENTRY(OidMacro) som_next;
+};
 
 typedef int slap_syntax_validate_func LDAP_P((
-       struct slap_syntax *syntax,
+       Syntax *syntax,
        struct berval * in));
 
 typedef int slap_syntax_transform_func LDAP_P((
-       struct slap_syntax *syntax,
+       Syntax *syntax,
        struct berval * in,
        struct berval * out,
        void *memctx));
@@ -349,7 +386,7 @@ typedef void* slap_component_transform_func LDAP_P((
 struct ComponentDesc;
 #endif
 
-typedef struct slap_syntax {
+struct Syntax {
        LDAPSyntax                      ssyn_syn;
 #define ssyn_oid               ssyn_syn.syn_oid
 #define ssyn_desc              ssyn_syn.syn_desc
@@ -377,6 +414,8 @@ typedef struct slap_syntax {
 #define SLAP_SYNTAX_HIDE       0x8000U /* hide (do not publish) */
 #endif
 
+       Syntax                          **ssyn_sups;
+
        slap_syntax_validate_func       *ssyn_validate;
        slap_syntax_transform_func      *ssyn_pretty;
 
@@ -390,8 +429,8 @@ typedef struct slap_syntax {
        struct ComponentDesc* ssync_comp_syntax;
 #endif
 
-       LDAP_SLIST_ENTRY(slap_syntax) ssyn_next;
-} Syntax;
+       LDAP_SLIST_ENTRY(Syntax)        ssyn_next;
+};
 
 #define slap_syntax_is_flag(s,flag) ((int)((s)->ssyn_flags & (flag)) ? 1 : 0)
 #define slap_syntax_is_blob(s)         slap_syntax_is_flag((s),SLAP_SYNTAX_BLOB)
@@ -402,6 +441,7 @@ typedef struct slap_syntax {
 typedef struct slap_syntax_defs_rec {
        char *sd_desc;
        int sd_flags;
+       char **sd_sups;
        slap_syntax_validate_func *sd_validate;
        slap_syntax_transform_func *sd_pretty;
 #ifdef SLAPD_BINARY_CONVERSION
@@ -419,27 +459,27 @@ typedef int slap_mr_convert_func LDAP_P((
 /* Normalizer */
 typedef int slap_mr_normalize_func LDAP_P((
        slap_mask_t use,
-       struct slap_syntax *syntax, /* NULL if in is asserted value */
-       struct slap_matching_rule *mr,
-       struct berval * in,
-       struct berval * out,
+       Syntax *syntax, /* NULL if in is asserted value */
+       MatchingRule *mr,
+       struct berval *in,
+       struct berval *out,
        void *memctx ));
 
 /* Match (compare) function */
 typedef int slap_mr_match_func LDAP_P((
        int *match,
        slap_mask_t use,
-       struct slap_syntax *syntax,     /* syntax of stored value */
-       struct slap_matching_rule *mr,
-       struct berval * value,
-       void * assertValue ));
+       Syntax *syntax, /* syntax of stored value */
+       MatchingRule *mr,
+       struct berval *value,
+       void *assertValue ));
 
 /* Index generation function */
 typedef int slap_mr_indexer_func LDAP_P((
        slap_mask_t use,
        slap_mask_t mask,
-       struct slap_syntax *syntax,     /* syntax of stored value */
-       struct slap_matching_rule *mr,
+       Syntax *syntax, /* syntax of stored value */
+       MatchingRule *mr,
        struct berval *prefix,
        BerVarray values,
        BerVarray *keys,
@@ -449,16 +489,14 @@ typedef int slap_mr_indexer_func LDAP_P((
 typedef int slap_mr_filter_func LDAP_P((
        slap_mask_t use,
        slap_mask_t mask,
-       struct slap_syntax *syntax,     /* syntax of stored value */
-       struct slap_matching_rule *mr,
+       Syntax *syntax, /* syntax of stored value */
+       MatchingRule *mr,
        struct berval *prefix,
-       void * assertValue,
+       void *assertValue,
        BerVarray *keys,
        void *memctx ));
 
-typedef struct slap_matching_rule_use MatchingRuleUse;
-
-typedef struct slap_matching_rule {
+struct MatchingRule {
        LDAPMatchingRule                smr_mrule;
        MatchingRuleUse                 *smr_mru;
        /* RFC 4512 string representation */
@@ -474,7 +512,7 @@ typedef struct slap_matching_rule {
        struct berval                   smr_bvoid;
 #define        smr_oidlen                      smr_bvoid.bv_len
 
-       slap_mask_t                             smr_usage;
+       slap_mask_t                     smr_usage;
 
 #ifdef LDAP_DEVEL
 #define SLAP_MR_HIDE                   0x0000U
@@ -482,18 +520,18 @@ typedef struct slap_matching_rule {
 #define SLAP_MR_HIDE                   0x8000U
 #endif
 
-#define SLAP_MR_MUTATION_NORMALIZER 0x4000U
+#define SLAP_MR_MUTATION_NORMALIZER    0x4000U
 
 #define SLAP_MR_TYPE_MASK              0x0F00U
-#define SLAP_MR_SUBTYPE_MASK   0x00F0U
+#define SLAP_MR_SUBTYPE_MASK           0x00F0U
 #define SLAP_MR_USAGE                  0x000FU
 
 #define SLAP_MR_NONE                   0x0000U
 #define SLAP_MR_EQUALITY               0x0100U
 #define SLAP_MR_ORDERING               0x0200U
 #define SLAP_MR_SUBSTR                 0x0400U
-#define SLAP_MR_EXT                            0x0800U /* implicitly extensible */
-#define        SLAP_MR_ORDERED_INDEX   0x1000U
+#define SLAP_MR_EXT                    0x0800U /* implicitly extensible */
+#define        SLAP_MR_ORDERED_INDEX           0x1000U
 #ifdef LDAP_COMP_MATCH
 #define SLAP_MR_COMPONENT              0x2000U
 #endif
@@ -501,7 +539,7 @@ typedef struct slap_matching_rule {
 #define SLAP_MR_EQUALITY_APPROX        ( SLAP_MR_EQUALITY | 0x0010U )
 
 #define SLAP_MR_SUBSTR_INITIAL ( SLAP_MR_SUBSTR | 0x0010U )
-#define SLAP_MR_SUBSTR_ANY             ( SLAP_MR_SUBSTR | 0x0020U )
+#define SLAP_MR_SUBSTR_ANY     ( SLAP_MR_SUBSTR | 0x0020U )
 #define SLAP_MR_SUBSTR_FINAL   ( SLAP_MR_SUBSTR | 0x0040U )
 
 
@@ -518,7 +556,7 @@ typedef struct slap_matching_rule {
  */
 #define SLAP_MR_VALUE_OF_ASSERTION_SYNTAX      0x0001U
 #define SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX      0x0002U
-#define SLAP_MR_VALUE_OF_SYNTAX                                0x0003U
+#define SLAP_MR_VALUE_OF_SYNTAX                        0x0003U
 
 #define SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX( usage ) \
        ((usage) & SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX )
@@ -554,30 +592,30 @@ typedef struct slap_matching_rule {
 #define SLAP_IS_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH( usage ) \
        ((usage) & SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH )
 
-       Syntax                                  *smr_syntax;
+       Syntax                  *smr_syntax;
        slap_mr_convert_func    *smr_convert;
        slap_mr_normalize_func  *smr_normalize;
-       slap_mr_match_func              *smr_match;
+       slap_mr_match_func      *smr_match;
        slap_mr_indexer_func    *smr_indexer;
-       slap_mr_filter_func             *smr_filter;
+       slap_mr_filter_func     *smr_filter;
 
        /*
         * null terminated array of syntaxes compatible with this syntax
         * note: when MS_EXT is set, this MUST NOT contain the assertion
         * syntax of the rule.  When MS_EXT is not set, it MAY.
         */
-       Syntax                                  **smr_compat_syntaxes;
+       Syntax                  **smr_compat_syntaxes;
 
        /*
         * For equality rules, refers to an associated approximate rule.
         * For non-equality rules, refers to an associated equality rule.
         */
-       struct slap_matching_rule       *smr_associated;
+       MatchingRule    *smr_associated;
 
 #define SLAP_MR_ASSOCIATED(mr,amr)     \
        (((mr) == (amr)) || ((mr)->smr_associated == (amr)))
 
-       LDAP_SLIST_ENTRY(slap_matching_rule)smr_next;
+       LDAP_SLIST_ENTRY(MatchingRule)  smr_next;
 
 #define smr_oid                                smr_mrule.mr_oid
 #define smr_names                      smr_mrule.mr_names
@@ -585,15 +623,15 @@ typedef struct slap_matching_rule {
 #define smr_obsolete           smr_mrule.mr_obsolete
 #define smr_syntax_oid         smr_mrule.mr_syntax_oid
 #define smr_extensions         smr_mrule.mr_extensions
-} MatchingRule;
+};
 
-struct slap_matching_rule_use {
+struct MatchingRuleUse {
        LDAPMatchingRuleUse             smru_mruleuse;
        MatchingRule                    *smru_mr;
        /* RFC 4512 string representation */
        struct berval                   smru_str;
 
-       LDAP_SLIST_ENTRY(slap_matching_rule_use) smru_next;
+       LDAP_SLIST_ENTRY(MatchingRuleUse) smru_next;
 
 #define smru_oid                       smru_mruleuse.mru_oid
 #define smru_names                     smru_mruleuse.mru_names
@@ -619,30 +657,26 @@ typedef struct slap_mrule_defs_rec {
        char *                                          mrd_associated;
 } slap_mrule_defs_rec;
 
-struct slap_backend_db;
-struct slap_entry;
-struct slap_attr;
-
 typedef int (AttributeTypeSchemaCheckFN)(
-       struct slap_backend_db *be,
-       struct slap_entry *e,
-       struct slap_attr *attr,
+       BackendDB *be,
+       Entry *e,
+       Attribute *attr,
        const char** text,
        char *textbuf, size_t textlen );
 
-typedef struct slap_attribute_type {
+struct AttributeType {
        LDAPAttributeType               sat_atype;
        struct berval                   sat_cname;
-       struct slap_attribute_type      *sat_sup;
-       struct slap_attribute_type      **sat_subtypes;
+       AttributeType                   *sat_sup;
+       AttributeType                   **sat_subtypes;
        MatchingRule                    *sat_equality;
        MatchingRule                    *sat_approx;
        MatchingRule                    *sat_ordering;
        MatchingRule                    *sat_substr;
-       Syntax                                  *sat_syntax;
+       Syntax                          *sat_syntax;
 
        AttributeTypeSchemaCheckFN      *sat_check;
-       char                                    *sat_oidmacro;
+       char                            *sat_oidmacro;
 
 #define SLAP_AT_NONE                   0x0000U
 #define SLAP_AT_ABSTRACT               0x0100U /* cannot be instantiated */
@@ -660,31 +694,31 @@ typedef struct slap_attribute_type {
 #define        SLAP_AT_ORDERED_SIB             0x0002U /* siblings are ordered */
 #define        SLAP_AT_ORDERED                 0x0003U /* value has order index */
 
-#define        SLAP_AT_HARDCODE        0x10000U        /* hardcoded schema */
-#define        SLAP_AT_DELETED         0x20000U
+#define        SLAP_AT_HARDCODE                0x10000U        /* hardcoded schema */
+#define        SLAP_AT_DELETED                 0x20000U
 
-       slap_mask_t                                     sat_flags;
+       slap_mask_t                     sat_flags;
 
-       LDAP_STAILQ_ENTRY(slap_attribute_type) sat_next;
+       LDAP_STAILQ_ENTRY(AttributeType) sat_next;
 
 #define sat_oid                                sat_atype.at_oid
 #define sat_names                      sat_atype.at_names
 #define sat_desc                       sat_atype.at_desc
-#define sat_obsolete           sat_atype.at_obsolete
+#define sat_obsolete                   sat_atype.at_obsolete
 #define sat_sup_oid                    sat_atype.at_sup_oid
-#define sat_equality_oid       sat_atype.at_equality_oid
-#define sat_ordering_oid       sat_atype.at_ordering_oid
-#define sat_substr_oid         sat_atype.at_substr_oid
-#define sat_syntax_oid         sat_atype.at_syntax_oid
-#define sat_single_value       sat_atype.at_single_value
-#define sat_collective         sat_atype.at_collective
-#define sat_no_user_mod                sat_atype.at_no_user_mod
+#define sat_equality_oid               sat_atype.at_equality_oid
+#define sat_ordering_oid               sat_atype.at_ordering_oid
+#define sat_substr_oid                 sat_atype.at_substr_oid
+#define sat_syntax_oid                 sat_atype.at_syntax_oid
+#define sat_single_value               sat_atype.at_single_value
+#define sat_collective                 sat_atype.at_collective
+#define sat_no_user_mod                        sat_atype.at_no_user_mod
 #define sat_usage                      sat_atype.at_usage
-#define sat_extensions         sat_atype.at_extensions
+#define sat_extensions                 sat_atype.at_extensions
 
-       struct slap_attr_desc           *sat_ad;
+       AttributeDescription            *sat_ad;
        ldap_pvt_thread_mutex_t         sat_ad_mutex;
-} AttributeType;
+};
 
 #define is_at_operational(at)  ((at)->sat_usage)
 #define is_at_single_value(at) ((at)->sat_single_value)
@@ -692,36 +726,34 @@ typedef struct slap_attribute_type {
 #define is_at_obsolete(at)             ((at)->sat_obsolete)
 #define is_at_no_user_mod(at)  ((at)->sat_no_user_mod)
 
-struct slap_object_class;
-
 typedef int (ObjectClassSchemaCheckFN)(
-       struct slap_backend_db *be,
-       struct slap_entry *e,
-       struct slap_object_class *oc,
+       BackendDB *be,
+       Entry *e,
+       ObjectClass *oc,
        const char** text,
        char *textbuf, size_t textlen );
 
-typedef struct slap_object_class {
+struct ObjectClass {
        LDAPObjectClass                 soc_oclass;
        struct berval                   soc_cname;
-       struct slap_object_class        **soc_sups;
-       AttributeType                           **soc_required;
-       AttributeType                           **soc_allowed;
+       ObjectClass                     **soc_sups;
+       AttributeType                   **soc_required;
+       AttributeType                   **soc_allowed;
        ObjectClassSchemaCheckFN        *soc_check;
-       char                                    *soc_oidmacro;
-       slap_mask_t                                     soc_flags;
+       char                            *soc_oidmacro;
+       slap_mask_t                     soc_flags;
 #define soc_oid                                soc_oclass.oc_oid
 #define soc_names                      soc_oclass.oc_names
 #define soc_desc                       soc_oclass.oc_desc
-#define soc_obsolete           soc_oclass.oc_obsolete
-#define soc_sup_oids           soc_oclass.oc_sup_oids
+#define soc_obsolete                   soc_oclass.oc_obsolete
+#define soc_sup_oids                   soc_oclass.oc_sup_oids
 #define soc_kind                       soc_oclass.oc_kind
-#define soc_at_oids_must       soc_oclass.oc_at_oids_must
-#define soc_at_oids_may                soc_oclass.oc_at_oids_may
-#define soc_extensions         soc_oclass.oc_extensions
+#define soc_at_oids_must               soc_oclass.oc_at_oids_must
+#define soc_at_oids_may                        soc_oclass.oc_at_oids_may
+#define soc_extensions                 soc_oclass.oc_extensions
 
-       LDAP_STAILQ_ENTRY(slap_object_class) soc_next;
-} ObjectClass;
+       LDAP_STAILQ_ENTRY(ObjectClass)  soc_next;
+};
 
 #define        SLAP_OCF_SET_FLAGS      0x1
 #define        SLAP_OCF_CHECK_SUP      0x2
@@ -749,55 +781,55 @@ typedef struct slap_object_class {
 /*
  * DIT content rule
  */
-typedef struct slap_content_rule {
+struct ContentRule {
        LDAPContentRule         scr_crule;
-       ObjectClass                     *scr_sclass;
-       ObjectClass                     **scr_auxiliaries;      /* optional */
+       ObjectClass             *scr_sclass;
+       ObjectClass             **scr_auxiliaries;      /* optional */
        AttributeType           **scr_required;         /* optional */
        AttributeType           **scr_allowed;          /* optional */
        AttributeType           **scr_precluded;        /* optional */
-#define scr_oid                                scr_crule.cr_oid
-#define scr_names                      scr_crule.cr_names
-#define scr_desc                       scr_crule.cr_desc
+#define scr_oid                        scr_crule.cr_oid
+#define scr_names              scr_crule.cr_names
+#define scr_desc               scr_crule.cr_desc
 #define scr_obsolete           scr_crule.cr_obsolete
 #define scr_oc_oids_aux                scr_crule.cr_oc_oids_aux
 #define scr_at_oids_must       scr_crule.cr_at_oids_must
 #define scr_at_oids_may                scr_crule.cr_at_oids_may
 #define scr_at_oids_not                scr_crule.cr_at_oids_not
 
-       char                            *scr_oidmacro;
-#define        SLAP_CR_HARDCODE        0x10000U
-       int     scr_flags;
+       char                    *scr_oidmacro;
+#define        SLAP_CR_HARDCODE        0x10000U
+       int                     scr_flags;
 
-       LDAP_STAILQ_ENTRY( slap_content_rule ) scr_next;
-} ContentRule;
+       LDAP_STAILQ_ENTRY( ContentRule ) scr_next;
+};
 
 /* Represents a recognized attribute description ( type + options ). */
-typedef struct slap_attr_desc {
-       struct slap_attr_desc *ad_next;
-       AttributeType *ad_type;         /* attribute type, must be specified */
-       struct berval ad_cname;         /* canonical name, must be specified */
-       struct berval ad_tags;          /* empty if no tagging options */
+struct AttributeDescription {
+       AttributeDescription    *ad_next;
+       AttributeType           *ad_type;       /* attribute type, must be specified */
+       struct berval           ad_cname;       /* canonical name, must be specified */
+       struct berval           ad_tags;        /* empty if no tagging options */
        unsigned ad_flags;
-#define SLAP_DESC_NONE                 0x00U
-#define SLAP_DESC_BINARY               0x01U
-#define SLAP_DESC_TAG_RANGE            0x80U
-#define SLAP_DESC_TEMPORARY            0x1000U
-} AttributeDescription;
+#define SLAP_DESC_NONE         0x00U
+#define SLAP_DESC_BINARY       0x01U
+#define SLAP_DESC_TAG_RANGE    0x80U
+#define SLAP_DESC_TEMPORARY    0x1000U
+};
 
 /* flags to slap_*2undef_ad to register undefined (0, the default)
  * or proxied (SLAP_AD_PROXIED) AttributeDescriptions; the additional
  * SLAP_AD_NOINSERT is to lookup without insert */
-#define SLAP_AD_UNDEF                  0x00U
-#define SLAP_AD_PROXIED                        0x01U
-#define        SLAP_AD_NOINSERT                0x02U
-
-typedef struct slap_attr_name {
-       struct berval an_name;
-       AttributeDescription *an_desc;
-       int an_oc_exclude;
-       ObjectClass *an_oc;
-} AttributeName;
+#define SLAP_AD_UNDEF          0x00U
+#define SLAP_AD_PROXIED                0x01U
+#define        SLAP_AD_NOINSERT        0x02U
+
+struct AttributeName {
+       struct berval           an_name;
+       AttributeDescription    *an_desc;
+       int                     an_oc_exclude;
+       ObjectClass             *an_oc;
+};
 
 #define slap_ad_is_tagged(ad)                  ( (ad)->ad_tags.bv_len != 0 )
 #define slap_ad_is_tag_range(ad)       \
@@ -940,40 +972,36 @@ struct slap_internal_schema {
        Syntax          *si_syn_objectClassDesc;
 };
 
-typedef struct slap_attr_assertion {
+struct AttributeAssertion {
        AttributeDescription    *aa_desc;
-       struct berval aa_value;
+       struct berval           aa_value;
 #ifdef LDAP_COMP_MATCH
-       struct slap_component_filter *aa_cf;/* for attribute aliasing */
+       ComponentFilter         *aa_cf;         /* for attribute aliasing */
 #endif
-} AttributeAssertion;
+};
 
-typedef struct slap_ss_assertion {
+struct SubstringsAssertion {
        AttributeDescription    *sa_desc;
        struct berval           sa_initial;
        struct berval           *sa_any;
        struct berval           sa_final;
-} SubstringsAssertion;
-
-#ifdef LDAP_COMP_MATCH
-struct slap_component_filter;
-#endif
+};
 
-typedef struct slap_mr_assertion {
+struct MatchingRuleAssertion {
        MatchingRule            *ma_rule;       /* optional */
-       struct berval           ma_rule_text;  /* optional */
+       struct berval           ma_rule_text;   /* optional */
        AttributeDescription    *ma_desc;       /* optional */
-       int                                             ma_dnattrs; /* boolean */
+       int                     ma_dnattrs;     /* boolean */
        struct berval           ma_value;       /* required */
 #ifdef LDAP_COMP_MATCH
-       struct slap_component_filter* ma_cf; /* component filter */
+       ComponentFilter         *ma_cf; /* component filter */
 #endif
-} MatchingRuleAssertion;
+};
 
 /*
  * represents a search filter
  */
-typedef struct slap_filter {
+struct Filter {
        ber_tag_t       f_choice;       /* values taken from ldap.h, plus: */
 #define SLAPD_FILTER_COMPUTED          0
 #define SLAPD_FILTER_MASK                      0x7fff
@@ -981,19 +1009,19 @@ typedef struct slap_filter {
 
        union f_un_u {
                /* precomputed result */
-               ber_int_t f_un_result;
+               ber_int_t               f_un_result;
 
                /* present */
-               AttributeDescription *f_un_desc;
+               AttributeDescription    *f_un_desc;
 
                /* simple value assertion */
-               AttributeAssertion *f_un_ava;
+               AttributeAssertion      *f_un_ava;
 
                /* substring assertion */
-               SubstringsAssertion *f_un_ssa;
+               SubstringsAssertion     *f_un_ssa;
 
                /* matching rule assertion */
-               MatchingRuleAssertion *f_un_mra;
+               MatchingRuleAssertion   *f_un_mra;
 
 #define f_desc                 f_un.f_un_desc
 #define f_ava                  f_un.f_un_ava
@@ -1001,18 +1029,18 @@ typedef struct slap_filter {
 #define f_av_value             f_un.f_un_ava->aa_value
 #define f_sub                  f_un.f_un_ssa
 #define f_sub_desc             f_un.f_un_ssa->sa_desc
-#define f_sub_initial  f_un.f_un_ssa->sa_initial
+#define f_sub_initial          f_un.f_un_ssa->sa_initial
 #define f_sub_any              f_un.f_un_ssa->sa_any
 #define f_sub_final            f_un.f_un_ssa->sa_final
 #define f_mra                  f_un.f_un_mra
 #define f_mr_rule              f_un.f_un_mra->ma_rule
-#define f_mr_rule_text f_un.f_un_mra->ma_rule_text
+#define f_mr_rule_text         f_un.f_un_mra->ma_rule_text
 #define f_mr_desc              f_un.f_un_mra->ma_desc
 #define f_mr_value             f_un.f_un_mra->ma_value
-#define        f_mr_dnattrs    f_un.f_un_mra->ma_dnattrs
+#define        f_mr_dnattrs            f_un.f_un_mra->ma_dnattrs
 
                /* and, or, not */
-               struct slap_filter *f_un_complex;
+               Filter                  *f_un_complex;
        } f_un;
 
 #define f_result       f_un.f_un_result
@@ -1021,13 +1049,13 @@ typedef struct slap_filter {
 #define f_not          f_un.f_un_complex
 #define f_list         f_un.f_un_complex
 
-       struct slap_filter      *f_next;
-} Filter;
+       Filter          *f_next;
+};
 
 /* compare routines can return undefined */
 #define SLAPD_COMPARE_UNDEFINED        ((ber_int_t) -1)
 
-typedef struct slap_valuesreturnfilter {
+struct ValuesReturnFilter {
        ber_tag_t       vrf_choice;
 
        union vrf_un_u {
@@ -1071,34 +1099,26 @@ typedef struct slap_valuesreturnfilter {
 
        } vrf_un;
 
-       struct slap_valuesreturnfilter  *vrf_next;
-} ValuesReturnFilter;
-
-#ifdef LDAP_COMP_MATCH
-struct slap_component_syntax_info;
-typedef struct         slap_component_data {
-       void* cd_mem_op;/* nibble memory handler */
-       struct slap_component_syntax_info** cd_tree;/* component tree */
-} ComponentData;
-#endif
+       ValuesReturnFilter      *vrf_next;
+};
 
 /*
  * represents an attribute (description + values)
  */
-typedef struct slap_attr {
-       AttributeDescription *a_desc;
-       BerVarray       a_vals;         /* preserved values */
-       BerVarray       a_nvals;        /* normalized values */
+struct Attribute {
+       AttributeDescription    *a_desc;
+       BerVarray               a_vals;         /* preserved values */
+       BerVarray               a_nvals;        /* normalized values */
 #ifdef LDAP_COMP_MATCH
-       ComponentData   *a_comp_data; /* component values */
+       ComponentData           *a_comp_data;   /* component values */
 #endif
-       struct slap_attr *a_next;
-       unsigned a_flags;
-#define SLAP_ATTR_IXADD                0x1U
-#define SLAP_ATTR_IXDEL                0x2U
+       Attribute               *a_next;
+       unsigned                a_flags;
+#define SLAP_ATTR_IXADD                        0x1U
+#define SLAP_ATTR_IXDEL                        0x2U
 #define SLAP_ATTR_DONT_FREE_DATA       0x4U
 #define SLAP_ATTR_DONT_FREE_VALS       0x8U
-} Attribute;
+};
 
 
 /*
@@ -1107,7 +1127,7 @@ typedef struct slap_attr {
 typedef unsigned long  ID;
 #define NOID   ((ID)~0)
 
-typedef struct slap_entry_header {
+typedef struct EntryHeader {
        struct berval bv;
        char *data;
        int nattrs;
@@ -1117,7 +1137,7 @@ typedef struct slap_entry_header {
 /*
  * represents an entry in core
  */
-typedef struct slap_entry {
+struct Entry {
        /*
         * The ID field should only be changed before entry is
         * inserted into a cache.  The ID value is backend
@@ -1140,12 +1160,12 @@ typedef struct slap_entry {
 
        /* for use by the backend for any purpose */
        void*   e_private;
-} Entry;
+};
 
 /*
  * A list of LDAPMods
  */
-typedef struct slap_mod {
+struct Modification {
        short sm_op;
        short sm_flags;
 /* Set for internal mods, will bypass ACL checks. Only needed when
@@ -1158,31 +1178,31 @@ typedef struct slap_mod {
        struct berval sm_type;
        BerVarray sm_values;
        BerVarray sm_nvalues;
-} Modification;
+};
 
-typedef struct slap_mod_list {
-       Modification sml_mod;
+struct Modifications {
+       Modification    sml_mod;
 #define sml_op         sml_mod.sm_op
 #define sml_flags      sml_mod.sm_flags
 #define sml_desc       sml_mod.sm_desc
 #define        sml_type        sml_mod.sm_type
 #define sml_values     sml_mod.sm_values
 #define sml_nvalues    sml_mod.sm_nvalues
-       struct slap_mod_list *sml_next;
-} Modifications;
+       Modifications   *sml_next;
+};
 
-typedef struct slap_ldap_modlist {
-       LDAPMod ml_mod;
-       struct slap_ldap_modlist *ml_next;
+struct LDAPModList {
+       LDAPMod         ml_mod;
+       LDAPModList     *ml_next;
 #define ml_op          ml_mod.mod_op
 #define ml_type                ml_mod.mod_type
 #define ml_values      ml_mod.mod_values
-} LDAPModList;
+};
 
 /*
  * represents an access control list
  */
-typedef enum slap_access_e {
+typedef enum slap_access_t {
        ACL_INVALID_ACCESS = -1,
        ACL_NONE = 0,
        ACL_DISCLOSE,
@@ -1235,7 +1255,7 @@ typedef enum slap_style_e {
        ACL_STYLE_PATH
 } slap_style_t;
 
-typedef struct slap_authz_info {
+typedef struct AuthorizationInformation {
        ber_tag_t       sai_method;                     /* LDAP_AUTH_* from <ldap.h> */
        struct berval   sai_mech;               /* SASL Mechanism */
        struct berval   sai_dn;                 /* DN for reporting purposes */
@@ -1248,9 +1268,7 @@ typedef struct slap_authz_info {
        slap_ssf_t      sai_sasl_ssf;           /* SASL SSF */
 } AuthorizationInformation;
 
-
 #ifdef SLAP_DYNACL
-struct slap_op;
 
 /*
  * "dynamic" ACL infrastructure (for ACIs and more)
@@ -1260,7 +1278,7 @@ typedef int (slap_dynacl_parse) LDAP_P(( const char *fname, int lineno,
 typedef int (slap_dynacl_unparse) LDAP_P(( void *priv, struct berval *bv ));
 typedef int (slap_dynacl_mask) LDAP_P((
                void                    *priv,
-               struct slap_op          *op,
+               Operation               *op,
                Entry                   *e,
                AttributeDescription    *desc,
                struct berval           *val,
@@ -1297,7 +1315,7 @@ typedef struct slap_dn_access {
 } slap_dn_access;
 
 /* the "by" part */
-typedef struct slap_access {
+typedef struct Access {
        slap_control_t a_type;
 
 /* strip qualifiers */
@@ -1454,14 +1472,14 @@ typedef struct slap_access {
        /* ACL Groups */
        slap_style_t a_group_style;
        struct berval   a_group_pat;
-       ObjectClass                             *a_group_oc;
+       ObjectClass             *a_group_oc;
        AttributeDescription    *a_group_at;
 
-       struct slap_access      *a_next;
+       struct Access           *a_next;
 } Access;
 
 /* the "to" part */
-typedef struct slap_acl {
+typedef struct AccessControl {
        /* "to" part: the entries this acl applies to */
        Filter          *acl_filter;
        slap_style_t acl_dn_style;
@@ -1476,7 +1494,7 @@ typedef struct slap_acl {
        /* "by" part: list of who has what access to the entries */
        Access  *acl_access;
 
-       struct slap_acl *acl_next;
+       struct AccessControl    *acl_next;
 } AccessControl;
 
 typedef enum {
@@ -1486,7 +1504,7 @@ typedef enum {
        ACL_STATE_RECORDED                      = ( ACL_STATE_RECORDED_VD | ACL_STATE_RECORDED_NV )
 } slap_acl_state_t;
 
-typedef struct slap_acl_state {
+typedef struct AccessControlState {
        /* Access state */
        AccessControl *as_vi_acl;
        AccessControl *as_vd_acl;
@@ -1505,10 +1523,8 @@ typedef struct slap_acl_state {
  * represents a backend 
  */
 
-typedef struct slap_backend_info BackendInfo;  /* per backend type */
-typedef struct slap_backend_db BackendDB;              /* per backend database */
-typedef LDAP_STAILQ_HEAD(BeI, slap_backend_info) slap_bi_head;
-typedef LDAP_STAILQ_HEAD(BeDB, slap_backend_db) slap_be_head;
+typedef LDAP_STAILQ_HEAD(BeI, BackendInfo) slap_bi_head;
+typedef LDAP_STAILQ_HEAD(BeDB, BackendDB) slap_be_head;
 
 LDAP_SLAPD_V (int) nBackendInfo;
 LDAP_SLAPD_V (int) nBackendDB;
@@ -1562,14 +1578,6 @@ typedef struct slap_bindconf {
 #endif
 } slap_bindconf;
 
-struct slap_replica_info {
-       const char *ri_host;            /* points to host part of uri */
-       BerVarray ri_nsuffix;           /* array of suffixes this replica accepts */
-       AttributeName *ri_attrs;        /* attrs to replicate, NULL=all */
-       int ri_exclude;                         /* 1 => exclude ri_attrs */
-       slap_bindconf ri_bindconf;      /* for back-config */
-};
-
 typedef struct slap_verbmasks {
        struct berval word;
        const slap_mask_t mask;
@@ -1677,7 +1685,7 @@ LDAP_TAILQ_HEAD( be_pcl, slap_csn_entry );
 
 struct ConfigOCs;      /* config.h */
 
-struct slap_backend_db {
+struct BackendDB {
        BackendInfo     *bd_info;       /* pointer to shared backend info */
 
        /* fields in this structure (and routines acting on this structure)
@@ -1696,9 +1704,9 @@ struct slap_backend_db {
 #define                be_modrdn       bd_info->bi_op_modrdn
 #define                be_search       bd_info->bi_op_search
 #define                be_abandon      bd_info->bi_op_abandon
-#define                be_cancel       bd_info->bi_op_cancel
 
 #define                be_extended     bd_info->bi_extended
+#define                be_cancel       bd_info->bi_op_cancel
 
 #define                be_chk_referrals        bd_info->bi_chk_referrals
 #define                be_chk_controls         bd_info->bi_chk_controls
@@ -1727,7 +1735,6 @@ struct slap_backend_db {
 #define                be_entry_put bd_info->bi_tool_entry_put
 #define                be_sync bd_info->bi_tool_sync
 #define                be_dn2id_get bd_info->bi_tool_dn2id_get
-#define                be_id2entry_get bd_info->bi_tool_id2entry_get
 #define                be_entry_modify bd_info->bi_tool_entry_modify
 #endif
 
@@ -1850,11 +1857,6 @@ struct slap_backend_db {
        slap_access_t   be_dfltaccess;  /* access given if no acl matches          */
 
        /* Replica Information */
-       struct slap_replica_info **be_replica;  /* replicas of this backend (in master) */
-       char    *be_replogfile; /* replication log file (in master)        */
-       char    *be_replica_argsfile; /* per-replog replica args file */
-       char    *be_replica_pidfile; /* per-replog replica pid file */
-       int     be_replicationinterval; /* per-replog replicationinterval */
        struct berval be_update_ndn;    /* allowed to make changes (in replicas) */
        BerVarray       be_update_refs; /* where to refer modifying clients to */
        struct          be_pcl  *be_pending_csn_list;
@@ -1866,12 +1868,9 @@ struct slap_backend_db {
        struct ConfigOCs *be_cf_ocs;
 
        void    *be_private;    /* anything the backend database needs     */
-       LDAP_STAILQ_ENTRY(slap_backend_db) be_next;
+       LDAP_STAILQ_ENTRY(BackendDB) be_next;
 };
 
-struct slap_conn;
-struct slap_op;
-
 /* Backend function typedefs */
 typedef int (BI_bi_func) LDAP_P((BackendInfo *bi));
 typedef BI_bi_func BI_init;
@@ -1882,7 +1881,8 @@ typedef int (BI_config) LDAP_P((BackendInfo *bi,
        const char *fname, int lineno,
        int argc, char **argv));
 
-typedef int (BI_db_func) LDAP_P((Backend *bd));
+struct config_reply_s ; /* config.h */
+typedef int (BI_db_func) LDAP_P((Backend *bd, struct config_reply_s *c));
 typedef BI_db_func BI_db_init;
 typedef BI_db_func BI_db_open;
 typedef BI_db_func BI_db_close;
@@ -1896,7 +1896,7 @@ typedef struct req_bind_s {
        struct berval rb_cred;
        struct berval rb_edn;
        slap_ssf_t rb_ssf;
-       struct berval rb_tmp_mech;      /* FIXME: temporary */
+       struct berval rb_mech;
 } req_bind_s;
 
 typedef struct req_search_s {
@@ -1916,23 +1916,27 @@ typedef struct req_compare_s {
        AttributeAssertion *rs_ava;
 } req_compare_s;
 
-typedef struct req_modify_s {
+typedef struct req_modifications_s {
        Modifications *rs_modlist;
-       int rs_increment;               /* FIXME: temporary */
        char rs_no_opattrs;             /* don't att modify operational attrs */
+} req_modifications_s;
+
+typedef struct req_modify_s {
+       req_modifications_s rs_mods;    /* NOTE: must be first in req_modify_s & req_modrdn_s */
+       int rs_increment;
 } req_modify_s;
 
 typedef struct req_modrdn_s {
-       Modifications *rs_modlist;
+       req_modifications_s rs_mods;    /* NOTE: must be first in req_modify_s & req_modrdn_s */
+       int rs_deleteoldrdn;
        struct berval rs_newrdn;
        struct berval rs_nnewrdn;
        struct berval *rs_newSup;
        struct berval *rs_nnewSup;
-       int rs_deleteoldrdn;
 } req_modrdn_s;
 
 typedef struct req_add_s {
-       Modifications *rs_modlist;      /* FIXME: temporary */
+       Modifications *rs_modlist;
        Entry *rs_e;
 } req_add_s;
 
@@ -2000,7 +2004,7 @@ typedef struct rep_search_s {
        BerVarray r_v2ref;
 } rep_search_s;
 
-typedef struct slap_rep {
+struct SlapReply {
        slap_reply_t sr_type;
        ber_tag_t sr_tag;
        ber_int_t sr_msgid;
@@ -2029,7 +2033,7 @@ typedef struct slap_rep {
 #define        REP_NO_ENTRYDN          0x1000U
 #define        REP_NO_SUBSCHEMA        0x2000U
 #define        REP_NO_OPERATIONALS     (REP_NO_ENTRYDN|REP_NO_SUBSCHEMA)
-} SlapReply;
+};
 
 /* short hands for response members */
 #define        sr_attrs sr_un.sru_search.r_attrs
@@ -2042,7 +2046,7 @@ typedef struct slap_rep {
 #define        sr_rspdata sr_un.sru_extended.r_rspdata
 #define        sr_sasldata sr_un.sru_sasl.r_sasldata
 
-typedef int (BI_op_func) LDAP_P(( struct slap_op *op, struct slap_rep *rs ));
+typedef int (BI_op_func) LDAP_P(( Operation *op, SlapReply *rs ));
 typedef BI_op_func BI_op_bind;
 typedef BI_op_func BI_op_unbind;
 typedef BI_op_func BI_op_search;
@@ -2052,28 +2056,28 @@ typedef BI_op_func BI_op_modrdn;
 typedef BI_op_func BI_op_add;
 typedef BI_op_func BI_op_delete;
 typedef BI_op_func BI_op_abandon;
-typedef BI_op_func BI_op_cancel;
 typedef BI_op_func BI_op_extended;
+typedef BI_op_func BI_op_cancel;
 typedef BI_op_func BI_chk_referrals;
 typedef BI_op_func BI_chk_controls;
 typedef int (BI_entry_release_rw)
-       LDAP_P(( struct slap_op *op, Entry *e, int rw ));
-typedef int (BI_entry_get_rw) LDAP_P(( struct slap_op *op, struct berval *ndn,
+       LDAP_P(( Operation *op, Entry *e, int rw ));
+typedef int (BI_entry_get_rw) LDAP_P(( Operation *op, struct berval *ndn,
        ObjectClass *oc, AttributeDescription *at, int rw, Entry **e ));
-typedef int (BI_operational) LDAP_P(( struct slap_op *op, struct slap_rep *rs ));
-typedef int (BI_has_subordinates) LDAP_P(( struct slap_op *op,
+typedef int (BI_operational) LDAP_P(( Operation *op, SlapReply *rs ));
+typedef int (BI_has_subordinates) LDAP_P(( Operation *op,
        Entry *e, int *hasSubs ));
-typedef int (BI_access_allowed) LDAP_P(( struct slap_op *op, Entry *e,
+typedef int (BI_access_allowed) LDAP_P(( Operation *op, Entry *e,
        AttributeDescription *desc, struct berval *val, slap_access_t access,
        AccessControlState *state, slap_mask_t *maskp ));
-typedef int (BI_acl_group) LDAP_P(( struct slap_op *op, Entry *target,
+typedef int (BI_acl_group) LDAP_P(( Operation *op, Entry *target,
        struct berval *gr_ndn, struct berval *op_ndn,
        ObjectClass *group_oc, AttributeDescription *group_at ));
-typedef int (BI_acl_attribute) LDAP_P(( struct slap_op *op, Entry *target,
+typedef int (BI_acl_attribute) LDAP_P(( Operation *op, Entry *target,
        struct berval *entry_ndn, AttributeDescription *entry_at,
        BerVarray *vals, slap_access_t access ));
 
-typedef int (BI_conn_func) LDAP_P(( BackendDB *bd, struct slap_conn *c ));
+typedef int (BI_conn_func) LDAP_P(( BackendDB *bd, Connection *c ));
 typedef BI_conn_func BI_connection_init;
 typedef BI_conn_func BI_connection_destroy;
 
@@ -2087,11 +2091,10 @@ typedef ID (BI_tool_entry_put) LDAP_P(( BackendDB *be, Entry *e,
 typedef int (BI_tool_entry_reindex) LDAP_P(( BackendDB *be, ID id, AttributeDescription **adv ));
 typedef int (BI_tool_sync) LDAP_P(( BackendDB *be ));
 typedef ID (BI_tool_dn2id_get) LDAP_P(( BackendDB *be, struct berval *dn ));
-typedef int (BI_tool_id2entry_get) LDAP_P(( BackendDB *be, ID id, Entry **e ));
 typedef ID (BI_tool_entry_modify) LDAP_P(( BackendDB *be, Entry *e, 
        struct berval *text ));
 
-struct slap_backend_info {
+struct BackendInfo {
        char    *bi_type; /* type of backend */
 
        /*
@@ -2157,10 +2160,10 @@ struct slap_backend_info {
        BI_op_add       *bi_op_add;
        BI_op_delete    *bi_op_delete;
        BI_op_abandon   *bi_op_abandon;
-       BI_op_cancel    *bi_op_cancel;
 
        /* Extended Operations Helper */
        BI_op_extended  *bi_extended;
+       BI_op_cancel    *bi_op_cancel;
 
        /* Auxilary Functions */
        BI_operational          *bi_operational;
@@ -2187,7 +2190,6 @@ struct slap_backend_info {
        BI_tool_entry_reindex   *bi_tool_entry_reindex;
        BI_tool_sync            *bi_tool_sync;
        BI_tool_dn2id_get       *bi_tool_dn2id_get;
-       BI_tool_id2entry_get    *bi_tool_id2entry_get;
        BI_tool_entry_modify    *bi_tool_entry_modify;
 
 #define SLAP_INDEX_ADD_OP              0x0001
@@ -2235,28 +2237,28 @@ struct slap_backend_info {
        char    **bi_obsolete_names;
        void    *bi_extra;              /* backend type-specific APIs */
        void    *bi_private;    /* backend type-specific config data */
-       LDAP_STAILQ_ENTRY(slap_backend_info) bi_next ;
+       LDAP_STAILQ_ENTRY(BackendInfo) bi_next ;
 };
 
 #define c_authtype     c_authz.sai_method
 #define c_authmech     c_authz.sai_mech
 #define c_dn           c_authz.sai_dn
 #define c_ndn          c_authz.sai_ndn
-#define c_ssf                  c_authz.sai_ssf
+#define c_ssf          c_authz.sai_ssf
 #define c_transport_ssf        c_authz.sai_transport_ssf
-#define c_tls_ssf              c_authz.sai_tls_ssf
-#define c_sasl_ssf             c_authz.sai_sasl_ssf
+#define c_tls_ssf      c_authz.sai_tls_ssf
+#define c_sasl_ssf     c_authz.sai_sasl_ssf
 
 #define o_authtype     o_authz.sai_method
 #define o_authmech     o_authz.sai_mech
 #define o_dn           o_authz.sai_dn
 #define o_ndn          o_authz.sai_ndn
-#define o_ssf                  o_authz.sai_ssf
+#define o_ssf          o_authz.sai_ssf
 #define o_transport_ssf        o_authz.sai_transport_ssf
-#define o_tls_ssf              o_authz.sai_tls_ssf
-#define o_sasl_ssf             o_authz.sai_sasl_ssf
+#define o_tls_ssf      o_authz.sai_tls_ssf
+#define o_sasl_ssf     o_authz.sai_sasl_ssf
 
-typedef int (slap_response)( struct slap_op *, struct slap_rep * );
+typedef int (slap_response)( Operation *, SlapReply * );
 
 typedef struct slap_callback {
        struct slap_callback *sc_next;
@@ -2277,8 +2279,8 @@ typedef enum slap_operation_e {
        op_add,
        op_delete,
        op_abandon,
-       op_cancel,
        op_extended,
+       op_cancel,
        op_aux_operational,
        op_aux_chk_referrals,
        op_aux_chk_controls,
@@ -2308,7 +2310,7 @@ typedef struct slap_overinfo {
  * Paged Results state
  */
 typedef unsigned long PagedResultsCookie;
-typedef struct slap_paged_state {
+typedef struct PagedResultsState {
        Backend *ps_be;
        ber_int_t ps_size;
        PagedResultsCookie ps_cookie;
@@ -2328,8 +2330,8 @@ struct slap_csn_entry {
 /*
  * Caches the result of a backend_group check for ACL evaluation
  */
-typedef struct slap_gacl {
-       struct slap_gacl *ga_next;
+typedef struct GroupAssertion {
+       struct GroupAssertion *ga_next;
        Backend *ga_be;
        ObjectClass *ga_oc;
        AttributeDescription *ga_at;
@@ -2353,13 +2355,18 @@ struct slap_control_ids {
        int sc_proxyAuthz;
        int sc_relax;
        int sc_searchOptions;
-#ifdef SLAP_SORTEDRESULTS
+#ifdef SLAP_CONTROL_X_SORTEDRESULTS
        int sc_sortedResults;
 #endif
        int sc_subentries;
+#ifdef SLAP_CONTROL_X_TREE_DELETE
        int sc_treeDelete;
+#endif
 #ifdef LDAP_X_TXN
        int sc_txnSpec;
+#endif
+#ifdef SLAP_CONTROL_X_SESSION_TRACKING
+       int sc_sessionTracking;
 #endif
        int sc_valuesReturnFilter;
 };
@@ -2367,10 +2374,10 @@ struct slap_control_ids {
 /*
  * represents an operation pending from an ldap client
  */
-typedef struct slap_op_header {
-       unsigned long oh_opid;  /* id of this operation */
-       unsigned long oh_connid; /* id of conn initiating this op */
-       struct slap_conn *oh_conn;      /* connection spawning this op */
+typedef struct Opheader {
+       unsigned long   oh_opid;        /* id of this operation */
+       unsigned long   oh_connid;      /* id of conn initiating this op */
+       Connection      *oh_conn;       /* connection spawning this op */
 
        ber_int_t       oh_msgid;       /* msgid of the request */
        ber_int_t       oh_protocol;    /* version of the LDAP protocol used by client */
@@ -2381,14 +2388,14 @@ typedef struct slap_op_header {
        void    *oh_tmpmemctx;          /* slab malloc context */
        BerMemoryFunctions *oh_tmpmfuncs;
 
-       char            oh_log_prefix[sizeof("conn=18446744073709551615 op=18446744073709551615")];
+       char            oh_log_prefix[ /* sizeof("conn=18446744073709551615 op=18446744073709551615") */ SLAP_TEXT_BUFLEN ];
 
 #ifdef LDAP_SLAPI
        void    *oh_extensions;         /* NS-SLAPI plugin */
 #endif
 } Opheader;
 
-typedef union slap_op_request {
+typedef union OpRequest {
        req_add_s oq_add;
        req_bind_s oq_bind;
        req_compare_s oq_compare;
@@ -2401,7 +2408,7 @@ typedef union slap_op_request {
        req_pwdexop_s oq_pwdexop;
 } OpRequest;
 
-typedef struct slap_op {
+struct Operation {
        Opheader *o_hdr;
 
 #define o_opid o_hdr->oh_opid
@@ -2448,7 +2455,7 @@ typedef struct slap_op {
 #define orb_cred oq_bind.rb_cred
 #define orb_edn oq_bind.rb_edn
 #define orb_ssf oq_bind.rb_ssf
-#define orb_tmp_mech oq_bind.rb_tmp_mech
+#define orb_mech oq_bind.rb_mech
 
 #define ors_scope oq_search.rs_scope
 #define ors_deref oq_search.rs_deref
@@ -2460,20 +2467,24 @@ typedef struct slap_op {
 #define ors_filter oq_search.rs_filter
 #define ors_filterstr oq_search.rs_filterstr
 
+#define orr_modlist oq_modrdn.rs_mods.rs_modlist
+#define orr_no_opattrs oq_modrdn.rs_mods.rs_no_opattrs
+#define orr_deleteoldrdn oq_modrdn.rs_deleteoldrdn
 #define orr_newrdn oq_modrdn.rs_newrdn
 #define orr_nnewrdn oq_modrdn.rs_nnewrdn
 #define orr_newSup oq_modrdn.rs_newSup
 #define orr_nnewSup oq_modrdn.rs_nnewSup
-#define orr_deleteoldrdn oq_modrdn.rs_deleteoldrdn
-#define orr_modlist oq_modrdn.rs_modlist
 
 #define orc_ava oq_compare.rs_ava
+
 #define ora_e oq_add.rs_e
 #define ora_modlist oq_add.rs_modlist
+
 #define orn_msgid oq_abandon.rs_msgid
-#define orm_modlist oq_modify.rs_modlist
+
+#define orm_modlist oq_modify.rs_mods.rs_modlist
+#define orm_no_opattrs oq_modify.rs_mods.rs_no_opattrs
 #define orm_increment oq_modify.rs_increment
-#define orm_no_opattrs oq_modify.rs_no_opattrs
 
 #define ore_reqoid oq_extended.rs_reqoid
 #define ore_flags oq_extended.rs_flags
@@ -2548,8 +2559,10 @@ typedef struct slap_op {
 #define o_domain_scope o_ctrlflag[slap_cids.sc_domainScope]
 #define get_domainScope(op)                            ((int)(op)->o_domain_scope)
 
+#ifdef SLAP_CONTROL_X_TREE_DELETE
 #define        o_tree_delete   o_ctrlflag[slap_cids.sc_treeDelete]
 #define get_treeDelete(op)                             ((int)(op)->o_tree_delete)
+#endif
 
 #define o_preread      o_ctrlflag[slap_cids.sc_preRead]
 #define o_postread     o_ctrlflag[slap_cids.sc_postRead]
@@ -2561,7 +2574,7 @@ typedef struct slap_op {
 #define o_pagedresults_state   o_controls[slap_cids.sc_pagedResults]
 #define get_pagedresults(op)                   ((int)(op)->o_pagedresults)
 
-#ifdef SLAP_SORTEDRESULTS
+#ifdef SLAP_CONTROL_X_SORTEDRESULTS
 #define o_sortedresults                o_ctrlflag[slap_cids.sc_sortedResults]
 #endif
 
@@ -2569,6 +2582,12 @@ typedef struct slap_op {
 #define o_txnSpec              o_ctrlflag[slap_cids.sc_txnSpec]
 #endif
 
+#ifdef SLAP_CONTROL_X_SESSION_TRACKING
+#define o_session_tracking     o_ctrlflag[slap_cids.sc_sessionTracking]
+#define o_tracked_sessions     o_controls[slap_cids.sc_sessionTracking]
+#define get_sessionTracking(op)                        ((int)(op)->o_session_tracking)
+#endif
+
 #define o_sync                 o_ctrlflag[slap_cids.sc_LDAPsync]
 
        AuthorizationInformation o_authz;
@@ -2581,14 +2600,14 @@ typedef struct slap_op {
 
        void    *o_private;     /* anything the backend needs */
 
-       LDAP_STAILQ_ENTRY(slap_op)      o_next; /* next operation in list */
-} Operation;
-
-#define        OPERATION_BUFFER_SIZE   ( sizeof(Operation) + sizeof(Opheader) + \
-       SLAP_MAX_CIDS*sizeof(void *) )
+       LDAP_STAILQ_ENTRY(Operation)    o_next; /* next operation in list */
+};
 
-typedef LBER_ALIGNED_BUFFER(operation_buffer_u,OPERATION_BUFFER_SIZE)
-       OperationBuffer;
+typedef struct OperationBuffer {
+       Operation       ob_op;
+       Opheader        ob_hdr;
+       void            *ob_controls[SLAP_MAX_CIDS];
+} OperationBuffer;
 
 #define send_ldap_error( op, rs, err, text ) do { \
                (rs)->sr_err = err; (rs)->sr_text = text; \
@@ -2600,15 +2619,15 @@ typedef LBER_ALIGNED_BUFFER(operation_buffer_u,OPERATION_BUFFER_SIZE)
        } while (0)
 
 typedef void (SEND_LDAP_RESULT)(
-       struct slap_op *op, struct slap_rep *rs);
+       Operation *op, SlapReply *rs);
 typedef int (SEND_SEARCH_ENTRY)(
-       struct slap_op *op, struct slap_rep *rs);
+       Operation *op, SlapReply *rs);
 typedef int (SEND_SEARCH_REFERENCE)(
-       struct slap_op *op, struct slap_rep *rs);
+       Operation *op, SlapReply *rs);
 typedef void (SEND_LDAP_EXTENDED)(
-       struct slap_op *op, struct slap_rep *rs);
+       Operation *op, SlapReply *rs);
 typedef void (SEND_LDAP_INTERMEDIATE)(
-       struct slap_op *op, struct slap_rep *rs);
+       Operation *op, SlapReply *rs);
 
 #define send_ldap_result( op, rs ) \
        ((op)->o_conn->c_send_ldap_result)( op, rs )
@@ -2626,7 +2645,7 @@ typedef struct slap_listener Listener;
 /*
  * represents a connection from an ldap client
  */
-typedef struct slap_conn {
+struct Connection {
        int                     c_struct_state; /* structure management state */
        int                     c_conn_state;   /* connection state */
        int                     c_conn_idx;             /* slot in connections array */
@@ -2667,8 +2686,8 @@ typedef struct slap_conn {
 
        ber_int_t       c_protocol;     /* version of the LDAP protocol used by client */
 
-       LDAP_STAILQ_HEAD(c_o, slap_op) c_ops;   /* list of operations being processed */
-       LDAP_STAILQ_HEAD(c_po, slap_op) c_pending_ops;  /* list of pending operations */
+       LDAP_STAILQ_HEAD(c_o, Operation) c_ops; /* list of operations being processed */
+       LDAP_STAILQ_HEAD(c_po, Operation) c_pending_ops;        /* list of pending operations */
 
        ldap_pvt_thread_mutex_t c_write_mutex;  /* only one pdu written at a time */
        ldap_pvt_thread_cond_t  c_write_cv;             /* used to wait for sd write-ready*/
@@ -2678,7 +2697,8 @@ typedef struct slap_conn {
 
 #define        CONN_IS_TLS     1
 #define        CONN_IS_UDP     2
-#define        CONN_IS_CLIENT  3
+#define        CONN_IS_CLIENT  4
+#define        CONN_IS_IPC     8
 
 #ifdef LDAP_CONNECTIONLESS
        int     c_is_udp;               /* true if this is (C)LDAP over UDP */
@@ -2692,7 +2712,7 @@ typedef struct slap_conn {
        void    *c_sasl_authctx;        /* SASL authentication context */
        void    *c_sasl_sockctx;        /* SASL security layer context */
        void    *c_sasl_extra;          /* SASL session extra stuff */
-       struct slap_op  *c_sasl_bindop; /* set to current op if it's a bind */
+       Operation       *c_sasl_bindop; /* set to current op if it's a bind */
 
 #ifdef LDAP_X_TXN
 #define CONN_TXN_INACTIVE 0
@@ -2701,7 +2721,7 @@ typedef struct slap_conn {
        int c_txn;
 
        Backend *c_txn_backend;
-       LDAP_STAILQ_HEAD(c_to, slap_op) c_txn_ops; /* list of operations in txn */
+       LDAP_STAILQ_HEAD(c_to, Operation) c_txn_ops; /* list of operations in txn */
 #endif
 
        PagedResultsState c_pagedresults_state; /* paged result state */
@@ -2733,7 +2753,7 @@ typedef struct slap_conn {
        SEND_SEARCH_REFERENCE *c_send_search_reference;
        SEND_LDAP_EXTENDED *c_send_ldap_extended;
        SEND_LDAP_INTERMEDIATE *c_send_ldap_intermediate;
-} Connection;
+};
 
 #ifdef LDAP_DEBUG
 #ifdef LDAP_SYSLOG
@@ -2785,12 +2805,12 @@ struct slap_listener {
 typedef enum {
        SLAP_OP_BIND = 0,
        SLAP_OP_UNBIND,
+       SLAP_OP_SEARCH,
+       SLAP_OP_COMPARE,
+       SLAP_OP_MODIFY,
+       SLAP_OP_MODRDN,
        SLAP_OP_ADD,
        SLAP_OP_DELETE,
-       SLAP_OP_MODRDN,
-       SLAP_OP_MODIFY,
-       SLAP_OP_COMPARE,
-       SLAP_OP_SEARCH,
        SLAP_OP_ABANDON,
        SLAP_OP_EXTENDED,
        SLAP_OP_LAST
@@ -2903,9 +2923,21 @@ typedef int (*SLAP_ENTRY_INFO_FN) LDAP_P(( void *arg, Entry *e ));
 #define LDAP_COMP_FILTER_ITEM          ((ber_tag_t) 0xa3U)
 #define LDAP_COMP_FILTER_UNDEFINED     ((ber_tag_t) 0xa4U)
 
-typedef struct slap_component_id {
-       int     ci_type;
-       struct slap_component_id *ci_next;
+typedef struct ComponentId ComponentId;
+typedef struct ComponentReference ComponentReference;
+typedef struct ComponentAssertion ComponentAssertion;
+typedef struct ComponentAssertionValue ComponentAssertionValue;
+typedef struct ComponentSyntaxInfo ComponentSyntaxInfo;
+typedef struct ComponentDesc ComponentDesc;
+
+struct ComponentData {
+       void                    *cd_mem_op;     /* nibble memory handler */
+       ComponentSyntaxInfo**   cd_tree;        /* component tree */
+};
+
+struct ComponentId {
+       int             ci_type;
+       ComponentId     *ci_next;
 
        union comp_id_value{
                BerValue        ci_identifier;
@@ -2916,9 +2948,9 @@ typedef struct slap_component_id {
                BerValue        ci_select_value;
                char            ci_all;
        } ci_val;
-} ComponentId;
+};
 
-typedef struct slap_component_reference {
+struct ComponentReference {
        ComponentId     *cr_list;
        ComponentId     *cr_curr;
        struct berval   cr_string;
@@ -2928,25 +2960,25 @@ typedef struct slap_component_reference {
        slap_mask_t     cr_indexmask;
        AttributeDescription* cr_ad;
        BerVarray       cr_nvals;
-       struct slap_component_reference* cr_next;
-} ComponentReference;
+       ComponentReference* cr_next;
+};
 
-typedef struct slap_component_assertion {
+struct ComponentAssertion {
        ComponentReference      *ca_comp_ref;
        ber_int_t               ca_use_def;
        MatchingRule            *ca_ma_rule;
        struct berval           ca_ma_value;
        ComponentData           ca_comp_data; /* componentized assertion */
-       struct slap_component_filter    *ca_cf;
+       ComponentFilter         *ca_cf;
        MatchingRuleAssertion   *ca_mra;
-} ComponentAssertion;
+};
 
-typedef struct slap_component_filter {
-       ber_tag_t cf_choice;
+struct ComponentFilter {
+       ber_tag_t       cf_choice;
        union cf_un_u {
-               ber_int_t cf_un_result;
-               ComponentAssertion *cf_un_ca;
-               struct slap_component_filter *cf_un_complex;
+               ber_int_t               cf_un_result;
+               ComponentAssertion      *cf_un_ca;
+               ComponentFilter         *cf_un_complex;
        } cf_un;
 
 #define cf_ca          cf_un.cf_un_ca
@@ -2956,25 +2988,23 @@ typedef struct slap_component_filter {
 #define cf_not         cf_un.cf_un_complex
 #define cf_any         cf_un.cf_un_complex
        
-       struct slap_component_filter *cf_next;
-} ComponentFilter;
+       ComponentFilter *cf_next;
+};
 
-typedef struct slap_component_assertion_value {
+struct ComponentAssertionValue {
        char* cav_buf;
        char* cav_ptr;
        char* cav_end;
-} ComponentAssertionValue;
+};
 
 typedef int encoder_func LDAP_P((
        void* b,
        void* comp));
 
-struct slap_component_syntax_info;
-
 typedef int gser_decoder_func LDAP_P((
        void* mem_op,
        void* b,
-       struct slap_component_syntax_info** comp_syn_info,
+       ComponentSyntaxInfo** comp_syn_info,
        int* len,
        int mode));
 
@@ -2986,14 +3016,14 @@ typedef int ber_decoder_func LDAP_P((
        void* b,
        int tag,
        int elmtLen,
-       struct slap_component_syntax_info* comp_syn_info,
+       ComponentSyntaxInfo* comp_syn_info,
        int* len,
        int mode));
 
 typedef int ber_tag_decoder_func LDAP_P((
        void* mem_op,
        void* b,
-       struct slap_component_syntax_info* comp_syn_info,
+       ComponentSyntaxInfo* comp_syn_info,
        int* len,
        int mode));
 
@@ -3014,17 +3044,16 @@ typedef void* alloc_nibble_func LDAP_P ((
 typedef void free_nibble_func LDAP_P ((
        void* nm ));
 
-struct slap_component_syntax_info;                                                                          
 typedef void convert_assert_to_comp_func LDAP_P ((
        void *mem_op,
-        struct slap_component_syntax_info* csi_attr,
+        ComponentSyntaxInfo* csi_attr,
         struct berval* bv,
-        struct slap_component_syntax_info** csi,
+        ComponentSyntaxInfo** csi,
         int* len,
         int mode ));
                                                                           
 typedef int convert_asn_to_ldap_func LDAP_P ((
-        struct slap_component_syntax_info* csi,
+        ComponentSyntaxInfo* csi,
         struct berval *bv ));
 
 typedef void free_component_func LDAP_P ((
@@ -3033,8 +3062,8 @@ typedef void free_component_func LDAP_P ((
 typedef int test_component_func LDAP_P ((
        void* attr_mem_op,
        void* assert_mem_op,
-        struct slap_component_syntax_info* csi,
-       struct slap_component_assertion* ca));
+        ComponentSyntaxInfo* csi,
+       ComponentAssertion* ca));
 
 typedef void* test_membership_func LDAP_P ((
        void* in ));
@@ -3042,43 +3071,41 @@ typedef void* test_membership_func LDAP_P ((
 typedef void* get_component_info_func LDAP_P ((
        int in ));
 
-struct slap_component_syntax_info;
-
 typedef int component_encoder_func LDAP_P ((
        void* mem_op,
-       struct slap_component_syntax_info* csi,
+       ComponentSyntaxInfo* csi,
        struct berval* nvals ));
        
 typedef int allcomponent_matching_func LDAP_P((
        char* oid,
-       struct slap_component_syntax_info* comp1,
-       struct slap_component_syntax_info* comp));
+       ComponentSyntaxInfo* comp1,
+       ComponentSyntaxInfo* comp));
 
-typedef struct slap_component_desc {
+struct ComponentDesc {
        /* Don't change the order of following four fields */
-       int             cd_tag;
-       AttributeType   *cd_comp_type;
-       struct berval   cd_ad_type;/* ad_type, ad_cname */
-       struct berval   cd_ad_cname;/* ad_type, ad_cname */
-       unsigned        cd_flags; /*ad_flags*/
-       int             cd_type;
-       int             cd_type_id;
-       encoder_func            *cd_ldap_encoder;
-       encoder_func            *cd_gser_encoder;
-       encoder_func            *cd_ber_encoder;
-       gser_decoder_func       *cd_gser_decoder;
-       ber_decoder_func        *cd_ber_decoder;
-       comp_free_func          *cd_free;
+       int                             cd_tag;
+       AttributeType                   *cd_comp_type;
+       struct berval                   cd_ad_type;     /* ad_type, ad_cname */
+       struct berval                   cd_ad_cname;    /* ad_type, ad_cname */
+       unsigned                        cd_flags;       /* ad_flags */
+       int                             cd_type;
+       int                             cd_type_id;
+       encoder_func                    *cd_ldap_encoder;
+       encoder_func                    *cd_gser_encoder;
+       encoder_func                    *cd_ber_encoder;
+       gser_decoder_func               *cd_gser_decoder;
+       ber_decoder_func                *cd_ber_decoder;
+       comp_free_func                  *cd_free;
        extract_component_from_id_func*  cd_extract_i;
        allcomponent_matching_func      *cd_all_match;
-} ComponentDesc;
+};
 
-typedef struct slap_component_syntax_info {
-       Syntaxcsi_syntax;
-       ComponentDesccsi_comp_desc;
-} ComponentSyntaxInfo;
+struct ComponentSyntaxInfo {
+       Syntax          *csi_syntax;
+       ComponentDesc   *csi_comp_desc;
+};
 
-#endif
+#endif /* LDAP_COMP_MATCH */
 
 /* slab heap data structures */
 
index f8573b5ed5ea7369cadada8abe35d4f924a9f006..090b67e327bd6a0c72f9f6001e18974721633c30 100644 (file)
@@ -95,8 +95,8 @@ slapacl( int argc, char **argv )
        argv = &argv[ optind ];
        argc -= optind;
 
-       op = (Operation *) &opbuf;
-       connection_fake_init( &conn, op, &conn );
+       connection_fake_init( &conn, &opbuf, &conn );
+       op = &opbuf.ob_op;
 
        conn.c_listener = &listener;
        conn.c_listener_url = listener_url;
@@ -238,7 +238,7 @@ slapacl( int argc, char **argv )
                if ( !be->be_entry_open ||
                        !be->be_entry_close ||
                        !be->be_dn2id_get ||
-                       !be->be_id2entry_get )
+                       !be->be_entry_get )
                {
                        fprintf( stderr, "%s: target database "
                                "doesn't support necessary operations; "
@@ -264,7 +264,8 @@ slapacl( int argc, char **argv )
                        rc = 1;
                        goto destroy;
                }
-               if ( be->be_id2entry_get( be, id, &ep ) != 0 ) {
+               ep = be->be_entry_get( be, id );
+               if ( ep == NULL ) {
                        fprintf( stderr, "%s: unable to fetch entry \"%s\" (%lu)\n",
                                progname, e.e_nname.bv_val, id );
                        rc = 1;
@@ -384,7 +385,7 @@ destroy:;
                ber_memfree( e.e_nname.bv_val );
        }
        if ( !dryrun && be ) {
-               if ( ep != &e ) {
+               if ( ep && ep != &e ) {
                        be_entry_release_r( op, ep );
                }
                if ( doclose ) {
index 72daa638c6b8e7fd212f1841ec7f15534755008b..5f8d6be3644671f4ab2a53a43c2fcf5b89a9a42d 100644 (file)
@@ -39,7 +39,7 @@
 #include "slapcommon.h"
 
 static char csnbuf[ LDAP_LUTIL_CSNSTR_BUFSIZE ];
-static char maxcsnbuf[ LDAP_LUTIL_CSNSTR_BUFSIZE ];
+static char maxcsnbuf[ LDAP_LUTIL_CSNSTR_BUFSIZE * ( SLAP_SYNC_SID_MAX + 1 ) ];
 
 int
 slapadd( int argc, char **argv )
@@ -51,7 +51,8 @@ slapadd( int argc, char **argv )
        const char *progname = "slapadd";
 
        struct berval csn;
-       struct berval maxcsn;
+       struct berval maxcsn[ SLAP_SYNC_SID_MAX + 1 ];
+       unsigned long sid;
        struct berval bvtext;
        Attribute *attr;
        Entry *ctxcsn_e;
@@ -60,25 +61,27 @@ slapadd( int argc, char **argv )
        Operation *op;
 
        int match;
-       int ret;
        int checkvals;
        int lineno, nextline;
        int lmax;
        int rc = EXIT_SUCCESS;
        int manage = 0; 
 
+       /* default "000" */
+       csnsid = 0;
+
        slap_tool_init( progname, SLAPADD, argc, argv );
 
        memset( &opbuf, 0, sizeof(opbuf) );
-       op = (Operation *) &opbuf;
-       op->o_hdr = (Opheader *)(op+1);
+       op = &opbuf.ob_op;
+       op->o_hdr = &opbuf.ob_hdr;
 
        if( !be->be_entry_open ||
                !be->be_entry_close ||
                !be->be_entry_put ||
                (update_ctxcsn &&
                 (!be->be_dn2id_get ||
-                 !be->be_id2entry_get ||
+                 !be->be_entry_get ||
                  !be->be_entry_modify)) )
        {
                fprintf( stderr, "%s: database doesn't support necessary operations.\n",
@@ -96,6 +99,11 @@ slapadd( int argc, char **argv )
        lmax = 0;
        nextline = 0;
 
+       /* enforce schema checking unless not disabled */
+       if ( (slapMode & SLAP_TOOL_NO_SCHEMA_CHECK) == 0) {
+               SLAP_DBFLAGS(be) &= ~(SLAP_DBFLAG_NO_SCHEMA_CHECK);
+       }
+
        if( !dryrun && be->be_entry_open( be, 1 ) != 0 ) {
                fprintf( stderr, "%s: could not open database.\n",
                        progname );
@@ -103,8 +111,11 @@ slapadd( int argc, char **argv )
        }
 
        if ( update_ctxcsn ) {
-               maxcsn.bv_val = maxcsnbuf;
-               maxcsn.bv_len = 0;
+               maxcsn[ 0 ].bv_val = maxcsnbuf;
+               for ( sid = 1; sid <= SLAP_SYNC_SID_MAX; sid++ ) {
+                       maxcsn[ sid ].bv_val = maxcsn[ sid - 1 ].bv_val + LDAP_LUTIL_CSNSTR_BUFSIZE;
+                       maxcsn[ sid ].bv_len = 0;
+               }
        }
 
        /* nextline is the line number of the end of the current entry */
@@ -144,7 +155,7 @@ slapadd( int argc, char **argv )
                }
 
                /* check backend */
-               if( select_backend( &e->e_nname, is_entry_referral(e), nosubordinates )
+               if( select_backend( &e->e_nname, nosubordinates )
                        != be )
                {
                        fprintf( stderr, "%s: line %d: "
@@ -212,7 +223,7 @@ slapadd( int argc, char **argv )
                        nvals[1].bv_len = 0;
                        nvals[1].bv_val = NULL;
 
-                       csn.bv_len = lutil_csnstr( csnbuf, sizeof( csnbuf ), 0, 0 );
+                       csn.bv_len = lutil_csnstr( csnbuf, sizeof( csnbuf ), csnsid, 0 );
                        csn.bv_val = csnbuf;
 
                        timestamp.bv_val = timebuf;
@@ -274,19 +285,34 @@ slapadd( int argc, char **argv )
                        }
 
                        if ( update_ctxcsn ) {
+                               int rc_sid;
+
                                attr = attr_find( e->e_attrs, slap_schema.si_ad_entryCSN );
-                               if ( maxcsn.bv_len != 0 ) {
-                                       match = 0;
-                                       value_match( &match, slap_schema.si_ad_entryCSN,
-                                               slap_schema.si_ad_entryCSN->ad_type->sat_ordering,
-                                               SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
-                                               &maxcsn, &attr->a_nvals[0], &text );
+                               assert( attr != NULL );
+
+                               rc_sid = slap_parse_csn_sid( &attr->a_nvals[ 0 ] );
+                               if ( rc_sid < 0 ) {
+                                       Debug( LDAP_DEBUG_ANY, "%s: could not "
+                                               "extract SID from entryCSN=%s\n",
+                                               progname, attr->a_nvals[ 0 ].bv_val, 0 );
+
                                } else {
-                                       match = -1;
-                               }
-                               if ( match < 0 ) {
-                                       strcpy( maxcsn.bv_val, attr->a_nvals[0].bv_val );
-                                       maxcsn.bv_len = attr->a_nvals[0].bv_len;
+                                       assert( rc_sid <= SLAP_SYNC_SID_MAX );
+
+                                       sid = (unsigned)rc_sid;
+                                       if ( maxcsn[ sid ].bv_len != 0 ) {
+                                               match = 0;
+                                               value_match( &match, slap_schema.si_ad_entryCSN,
+                                                       slap_schema.si_ad_entryCSN->ad_type->sat_ordering,
+                                                       SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
+                                                       &maxcsn[ sid ], &attr->a_nvals[0], &text );
+                                       } else {
+                                               match = -1;
+                                       }
+                                       if ( match < 0 ) {
+                                               strcpy( maxcsn[ sid ].bv_val, attr->a_nvals[0].bv_val );
+                                               maxcsn[ sid ].bv_len = attr->a_nvals[0].bv_len;
+                                       }
                                }
                        }
                }
@@ -318,41 +344,80 @@ slapadd( int argc, char **argv )
        bvtext.bv_val = textbuf;
        bvtext.bv_val[0] = '\0';
 
-       if ( rc == EXIT_SUCCESS && update_ctxcsn && !dryrun && maxcsn.bv_len ) {
+       if ( rc == EXIT_SUCCESS && update_ctxcsn && !dryrun && sid != SLAP_SYNC_SID_MAX + 1 ) {
                ctxcsn_id = be->be_dn2id_get( be, be->be_nsuffix );
                if ( ctxcsn_id == NOID ) {
                        fprintf( stderr, "%s: context entry is missing\n", progname );
                        rc = EXIT_FAILURE;
                } else {
-                       ret = be->be_id2entry_get( be, ctxcsn_id, &ctxcsn_e );
-                       if ( ret == LDAP_SUCCESS ) {
-                               attr = attr_find( ctxcsn_e->e_attrs,
-                                                                       slap_schema.si_ad_contextCSN );
+                       ctxcsn_e = be->be_entry_get( be, ctxcsn_id );
+                       if ( ctxcsn_e != NULL ) {
+                               Entry *e = entry_dup( ctxcsn_e );
+                               attr = attr_find( e->e_attrs, slap_schema.si_ad_contextCSN );
                                if ( attr ) {
-                                       value_match( &match, slap_schema.si_ad_entryCSN,
-                                               slap_schema.si_ad_entryCSN->ad_type->sat_ordering,
-                                               SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
-                                               &maxcsn, &attr->a_nvals[0], &text );
-                                       if ( match > 0 ) {
-                                               AC_MEMCPY( attr->a_vals[0].bv_val, maxcsn.bv_val, maxcsn.bv_len );
-                                               attr->a_vals[0].bv_val[maxcsn.bv_len] = '\0';
-                                               attr->a_vals[0].bv_len = maxcsn.bv_len;
+                                       int             i;
+
+                                       for ( i = 0; !BER_BVISNULL( &attr->a_nvals[ i ] ); i++ ) {
+                                               int rc_sid;
+
+                                               rc_sid = slap_parse_csn_sid( &attr->a_nvals[ i ] );
+                                               if ( rc_sid < 0 ) {
+                                                       Debug( LDAP_DEBUG_ANY,
+                                                               "%s: unable to extract SID "
+                                                               "from #%d contextCSN=%s\n",
+                                                               progname, i,
+                                                               attr->a_nvals[ i ].bv_val );
+                                                       continue;
+                                               }
+
+                                               assert( rc_sid <= SLAP_SYNC_SID_MAX );
+
+                                               sid = (unsigned)rc_sid;
+
+                                               if ( maxcsn[ sid ].bv_len == 0 ) {
+                                                       match = -1;
+
+                                               } else {
+                                                       value_match( &match, slap_schema.si_ad_entryCSN,
+                                                               slap_schema.si_ad_entryCSN->ad_type->sat_ordering,
+                                                               SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
+                                                               &maxcsn[ sid ], &attr->a_nvals[i], &text );
+                                               }
+
+                                               if ( match < 0 ) {
+                                                       AC_MEMCPY( maxcsn[ sid ].bv_val,
+                                                               attr->a_nvals[ i ].bv_val,
+                                                               attr->a_nvals[ i ].bv_len );
+                                                       maxcsn[ sid ].bv_val[ attr->a_nvals[ i ].bv_len ] = '\0';
+                                                       maxcsn[ sid ].bv_len = attr->a_nvals[ i ].bv_len;
+                                               }
                                        }
-                               } else {
-                                       match = 1;
-                                       attr_merge_one( ctxcsn_e, slap_schema.si_ad_contextCSN, &maxcsn, NULL );
+
+                                       if ( attr->a_nvals != attr->a_nvals ) {
+                                               ber_bvarray_free( attr->a_nvals );
+                                       }
+                                       attr->a_nvals = NULL;
+                                       ber_bvarray_free( attr->a_vals );
+                                       attr->a_vals = NULL;
                                }
-                               if ( match > 0 ) {
-                                       ctxcsn_id = be->be_entry_modify( be, ctxcsn_e, &bvtext );
-                                       if( ctxcsn_id == NOID ) {
-                                               fprintf( stderr, "%s: could not modify ctxcsn\n",
-                                                                               progname);
-                                               rc = EXIT_FAILURE;
-                                       } else if ( verbose ) {
-                                               fprintf( stderr, "modified: \"%s\" (%08lx)\n",
-                                                                                ctxcsn_e->e_dn, (long) ctxcsn_id );
+
+                               for ( sid = 0; sid <= SLAP_SYNC_SID_MAX; sid++ ) {
+                                       if ( maxcsn[ sid ].bv_len ) {
+                                               attr_merge_one( e, slap_schema.si_ad_contextCSN,
+                                                       &maxcsn[ sid], NULL );
                                        }
                                }
+                       
+                               ctxcsn_id = be->be_entry_modify( be, e, &bvtext );
+                               if( ctxcsn_id == NOID ) {
+                                       fprintf( stderr, "%s: could not modify ctxcsn\n",
+                                               progname);
+                                       rc = EXIT_FAILURE;
+                               } else if ( verbose ) {
+                                       fprintf( stderr, "modified: \"%s\" (%08lx)\n",
+                                               e->e_dn, (long) ctxcsn_id );
+                               }
+                               entry_free( e );
                        }
                } 
        }
index 3a4c304ff940215166bdd4c3d5e7b21c4e5a8ffd..92799ac0c9d4c5ff06b99e3522744c93809d15fd 100644 (file)
@@ -88,8 +88,8 @@ slapauth( int argc, char **argv )
        argv = &argv[ optind ];
        argc -= optind;
 
-       op = (Operation *) &opbuf;
-       connection_fake_init( &conn, op, &conn );
+       connection_fake_init( &conn, &opbuf, &conn );
+       op = &opbuf.ob_op;
 
        conn.c_sasl_bind_mech = mech;
 
index 70843c731e9c6c2317c568974ad916eafb46de17..adf5a60323305ee1383312698c1015578109cd8b 100644 (file)
@@ -47,13 +47,13 @@ static FILE *leakfile;
 
 static LDIFFP dummy;
 
-#ifdef LDAP_SYSLOG
+#if defined(LDAP_SYSLOG) && defined(LDAP_DEBUG)
 int start_syslog;
 static char **syslog_unknowns;
 #ifdef LOG_LOCAL4
 static int syslogUser = SLAP_DEFAULT_SYSLOG_USER;
 #endif /* LOG_LOCAL4 */
-#endif /* LDAP_SYSLOG */
+#endif /* LDAP_DEBUG && LDAP_SYSLOG */
 
 static void
 usage( int tool, const char *progname )
@@ -165,7 +165,7 @@ parse_slapopt( void )
        } else if ( strncasecmp( optarg, "authzDN", len ) == 0 ) {
                ber_str2bv( p, 0, 1, &authzDN );
 
-#ifdef LDAP_SYSLOG
+#if defined(LDAP_SYSLOG) && defined(LDAP_DEBUG)
        } else if ( strncasecmp( optarg, "syslog", len ) == 0 ) {
                if ( parse_debug_level( p, &ldap_syslog, &syslog_unknowns ) ) {
                        return -1;
@@ -185,7 +185,7 @@ parse_slapopt( void )
                }
                start_syslog = 1;
 #endif /* LOG_LOCAL4 */
-#endif /* LDAP_SYSLOG */
+#endif /* LDAP_DEBUG && LDAP_SYSLOG */
 
        } else {
                return -1;
@@ -241,7 +241,7 @@ slap_tool_init(
 
        switch( tool ) {
        case SLAPADD:
-               options = "b:cd:f:F:gj:l:n:o:qstuvw";
+               options = "b:cd:f:F:gj:l:n:o:qsS:tuvw";
                break;
 
        case SLAPCAT:
@@ -255,7 +255,7 @@ slap_tool_init(
                break;
 
        case SLAPTEST:
-               options = "d:f:F:o:uv";
+               options = "d:f:F:o:Quv";
                mode |= SLAP_TOOL_READMAIN | SLAP_TOOL_READONLY;
                break;
 
@@ -371,6 +371,11 @@ slap_tool_init(
                        dn_mode = SLAP_TOOL_LDAPDN_PRETTY;
                        break;
 
+               case 'Q':
+                       quiet++;
+                       slap_debug = 0;
+                       break;
+
                case 'q':       /* turn on quick */
                        mode |= SLAP_TOOL_QUICK;
                        break;
@@ -379,6 +384,14 @@ slap_tool_init(
                        realm = optarg;
                        break;
 
+               case 'S':
+                       if ( lutil_atoul( &csnsid, optarg )
+                               || csnsid > SLAP_SYNC_SID_MAX )
+                       {
+                               usage( tool, progname );
+                       }
+                       break;
+
                case 's':       /* dump subtree */
                        if ( tool == SLAPADD )
                                mode |= SLAP_TOOL_NO_SCHEMA_CHECK;
@@ -417,7 +430,7 @@ slap_tool_init(
                }
        }
 
-#ifdef LDAP_SYSLOG
+#if defined(LDAP_SYSLOG) && defined(LDAP_DEBUG)
        if ( start_syslog ) {
                char *logName;
 #ifdef HAVE_EBCDIC
@@ -429,14 +442,14 @@ slap_tool_init(
 
 #ifdef LOG_LOCAL4
                openlog( logName, OPENLOG_OPTIONS, syslogUser );
-#elif LOG_DEBUG
+#elif defined LOG_DEBUG
                openlog( logName, OPENLOG_OPTIONS );
 #endif
 #ifdef HAVE_EBCDIC
                free( logName );
 #endif
        }
-#endif /* LDAP_SYSLOG */
+#endif /* LDAP_DEBUG && LDAP_SYSLOG */
 
        switch ( tool ) {
        case SLAPADD:
@@ -523,7 +536,7 @@ slap_tool_init(
                        exit( EXIT_FAILURE );
        }
 
-#ifdef LDAP_SYSLOG
+#if defined(LDAP_SYSLOG) && defined(LDAP_DEBUG)
        if ( syslog_unknowns ) {
                rc = parse_debug_unknowns( syslog_unknowns, &ldap_syslog );
                ldap_charray_free( syslog_unknowns );
@@ -613,7 +626,7 @@ slap_tool_init(
                        exit( EXIT_FAILURE );
                }
 
-               be = select_backend( &nbase, 0, 0 );
+               be = select_backend( &nbase, 0 );
                ber_memfree( nbase.bv_val );
 
                switch ( tool ) {
@@ -755,4 +768,8 @@ void slap_tool_destroy( void )
        if ( !BER_BVISNULL( &authcDN ) ) {
                ch_free( authcDN.bv_val );
        }
+
+       if ( ldiffp && ldiffp != &dummy ) {
+               ldif_close( ldiffp );
+       }
 }
index 8f74a029e9df5f8b680f866dc206c705d2287112..d48d2179750265273badf0a1947b8a198acf8a44 100644 (file)
@@ -35,6 +35,7 @@ enum slaptool {
 typedef struct tool_vars {
        Backend *tv_be;
        int tv_verbose;
+       int tv_quiet;
        int tv_update_ctxcsn;
        int tv_continuemode;
        int tv_nosubordinates;
@@ -59,12 +60,14 @@ typedef struct tool_vars {
        slap_ssf_t tv_tls_ssf;
        slap_ssf_t tv_sasl_ssf;
        unsigned tv_dn_mode;
+       unsigned int tv_csnsid;
 } tool_vars;
 
 extern tool_vars tool_globals;
 
 #define        be tool_globals.tv_be
 #define verbose tool_globals.tv_verbose
+#define quiet tool_globals.tv_quiet
 #define jumpline tool_globals.tv_jumpline
 #define update_ctxcsn tool_globals.tv_update_ctxcsn
 #define continuemode tool_globals.tv_continuemode
@@ -89,6 +92,7 @@ extern tool_vars tool_globals;
 #define tls_ssf tool_globals.tv_tls_ssf
 #define sasl_ssf tool_globals.tv_sasl_ssf
 #define dn_mode tool_globals.tv_dn_mode
+#define csnsid tool_globals.tv_csnsid
 #define SLAP_TOOL_LDAPDN_PRETTY                SLAP_LDAPDN_PRETTY
 #define SLAP_TOOL_LDAPDN_NORMAL                (SLAP_LDAPDN_PRETTY << 1)
 
index f4b562b6e7932512c8f3ef18428b836781af03bf..e4d198592d6b2aa87f4ad35dbdc356678bc0ffd5 100644 (file)
@@ -30,11 +30,11 @@ LDAP_BEGIN_DECL
 /*
  * Quick 'n' dirty to make struct slapi_* in slapi-plugin.h opaque
  */
-#define slapi_entry    slap_entry
-#define slapi_attr     slap_attr
+#define slapi_entry    Entry
+#define slapi_attr     Attribute
 #define slapi_value    berval
 #define slapi_valueset berval *
-#define slapi_filter   slap_filter
+#define slapi_filter   Filter
 
 LDAP_END_DECL
 
index 27374322cb156e7d1250fb999a75f3897c5646dd..fe1d2474c6a76f3c7491b99915daaebd8e8fa2e6 100644 (file)
@@ -187,9 +187,9 @@ slapi_int_connection_init_pb( Slapi_PBlock *pb, ber_tag_t tag )
 
        LDAP_STAILQ_INIT( &conn->c_pending_ops );
 
-       op = (Operation *) slapi_ch_calloc( 1, OPERATION_BUFFER_SIZE );
-       op->o_hdr = (Opheader *)(op + 1);
-       op->o_controls = (void **)(op->o_hdr + 1);
+       op = (Operation *) slapi_ch_calloc( 1, sizeof(OperationBuffer) );
+       op->o_hdr = &((OperationBuffer *) op)->ob_hdr;
+       op->o_controls = ((OperationBuffer *) op)->ob_controls;
 
        op->o_callback = (slap_callback *) slapi_ch_calloc( 1, sizeof(slap_callback) );
        op->o_callback->sc_response = slapi_int_response;
@@ -296,7 +296,7 @@ slapi_int_set_operation_dn( Slapi_PBlock *pb )
 
        if ( BER_BVISNULL( &op->o_ndn ) ) {
                /* set to root DN */
-               be = select_backend( &op->o_req_ndn, get_manageDSAit( op ), 1 );
+               be = select_backend( &op->o_req_ndn, 1 );
                if ( be != NULL ) {
                        ber_dupbv( &op->o_dn, &be->be_rootdn );
                        ber_dupbv( &op->o_ndn, &be->be_rootndn );
index fcbe435643fda766e4daf23ce4657c20fde19e36..a589a036bb6e1cbe60eab901846c9803792841b5 100644 (file)
@@ -27,6 +27,7 @@
 
 #include "slap.h"
 #include "slapi.h"
+#include "config.h"
 
 #ifdef LDAP_SLAPI
 
@@ -280,8 +281,8 @@ slapi_op_bind_callback( Operation *op, SlapReply *rs, int prc )
                                op->o_log_prefix,
                                BER_BVISNULL( &op->o_conn->c_dn )
                                        ? "<empty>" : op->o_conn->c_dn.bv_val,
-                               BER_BVISNULL( &op->orb_tmp_mech )
-                                       ? "<empty>" : op->orb_tmp_mech.bv_val, 0, 0 );
+                               BER_BVISNULL( &op->orb_mech )
+                                       ? "<empty>" : op->orb_mech.bv_val, 0, 0 );
 
                        return -1;
                }
@@ -763,7 +764,7 @@ slapi_over_acl_group(
        GroupAssertion          *g;
        SlapReply               rs = { REP_RESULT };
 
-       op->o_bd = select_backend( gr_ndn, 0, 0 );
+       op->o_bd = select_backend( gr_ndn, 0 );
 
        for ( g = op->o_groups; g; g = g->ga_next ) {
                if ( g->ga_be != op->o_bd || g->ga_oc != group_oc ||
@@ -848,7 +849,9 @@ done:
 }
 
 static int
-slapi_over_db_open( BackendDB *be )
+slapi_over_db_open(
+       BackendDB       *be,
+       ConfigReply     *cr )
 {
        Slapi_PBlock            *pb;
        int                     rc;
@@ -863,7 +866,9 @@ slapi_over_db_open( BackendDB *be )
 }
 
 static int
-slapi_over_db_close( BackendDB *be )
+slapi_over_db_close(
+       BackendDB       *be,
+       ConfigReply     *cr )
 {
        Slapi_PBlock            *pb;
        int                     rc;
index 2414ce5ed6272b7d77b969dc1fbbfd5878207765..136a5586b1c7c7424f18c8c4a5b5b17326b09f59 100644 (file)
@@ -447,7 +447,7 @@ pblock_be_call( Slapi_PBlock *pb, int (*bep)(Operation *) )
        op = pb->pb_op;
 
        be_orig = op->o_bd;
-       op->o_bd = select_backend( &op->o_req_ndn, 0, 0 );
+       op->o_bd = select_backend( &op->o_req_ndn, 0 );
        rc = (*bep)( op );
        op->o_bd = be_orig;
 
@@ -526,7 +526,7 @@ pblock_get( Slapi_PBlock *pb, int param, void **value )
                break;
        case SLAPI_BACKEND:
                PBLOCK_ASSERT_OP( pb, 0 );
-               *((BackendDB **)value) = select_backend( &pb->pb_op->o_req_ndn, 0, 0 );
+               *((BackendDB **)value) = select_backend( &pb->pb_op->o_req_ndn, 0 );
                break;
        case SLAPI_BE_TYPE:
                PBLOCK_ASSERT_OP( pb, 0 );
index 6feae2bf7b37bb84c2805d4a9aba852a32b0af50..99d5ccbc33840033df433532ba70d57f2dc75d83 100644 (file)
@@ -478,7 +478,7 @@ slapi_entry_has_children( const Slapi_Entry *e )
 
        slapi_pblock_set( pb, SLAPI_TARGET_DN, slapi_entry_get_dn( (Entry *)e ) );
 
-       pb->pb_op->o_bd = select_backend( (struct berval *)&e->e_nname, 0, 0 );
+       pb->pb_op->o_bd = select_backend( (struct berval *)&e->e_nname, 0 );
        if ( pb->pb_op->o_bd != NULL ) {
                pb->pb_op->o_bd->be_has_subordinates( pb->pb_op, (Entry *)e, &hasSubordinates );
        }
@@ -946,7 +946,7 @@ int slapi_dn_isbesuffix( Slapi_PBlock *pb, char *ldn )
        ndn.bv_len = strlen( ldn );
        ndn.bv_val = ldn;
 
-       be = select_backend( &pb->pb_op->o_req_ndn, 0, 0 );
+       be = select_backend( &pb->pb_op->o_req_ndn, 0 );
        if ( be == NULL ) {
                return 0;
        }
@@ -983,7 +983,7 @@ char *slapi_dn_beparent( Slapi_PBlock *pb, const char *ldn )
                return NULL;
        }
 
-       be = select_backend( &pb->pb_op->o_req_ndn, 0, 0 );
+       be = select_backend( &pb->pb_op->o_req_ndn, 0 );
 
        if ( be == NULL || be_issuffix( be, &normalizedDN ) == 0 ) {
                dnParent( &prettyDN, &parentDN );
@@ -3116,7 +3116,7 @@ int slapi_entry_schema_check( Slapi_PBlock *pb, Slapi_Entry *e )
 
        be_orig = pb->pb_op->o_bd;
 
-       pb->pb_op->o_bd = select_backend( &e->e_nname, 0, 0 );
+       pb->pb_op->o_bd = select_backend( &e->e_nname, 0 );
        if ( pb->pb_op->o_bd != NULL ) {
                rc = entry_schema_check( pb->pb_op, e, NULL, 0, 0,
                        &text, textbuf, textlen );
@@ -3402,7 +3402,7 @@ Slapi_Backend *slapi_be_select( const Slapi_DN *sdn )
 
        slapi_sdn_get_ndn( sdn );
 
-       be = select_backend( (struct berval *)&sdn->ndn, 0, 0 );
+       be = select_backend( (struct berval *)&sdn->ndn, 0 );
 
        return be;
 }
index ca10c7a6c7e2543192b227d47926f20158c13b87..84f87caeb5ca04cbc63565449bc9d36d768e3a20 100644 (file)
@@ -104,7 +104,9 @@ slaptest( int argc, char **argv )
                }
        }
 
-       fprintf( stderr, "config file testing succeeded\n");
+       if ( !quiet ) {
+               fprintf( stderr, "config file testing succeeded\n");
+       }
 
        slap_tool_destroy();
 
index c297650da2b359b674029c58b8360ad131f86c93..af5b81d446d2b6c8c1934271c46fbd7aab9a6709 100644 (file)
@@ -59,46 +59,46 @@ typedef struct cookie_state {
 
 typedef struct syncinfo_s {
        struct syncinfo_s       *si_next;
-       struct slap_backend_db *si_be;
-       struct slap_backend_db *si_wbe;
-       struct re_s                     *si_re;
-       int                                     si_rid;
-       char                            si_ridtxt[8];
+       BackendDB               *si_be;
+       BackendDB               *si_wbe;
+       struct re_s             *si_re;
+       int                     si_rid;
+       char                    si_ridtxt[ STRLENOF("rid=4095") + 1 ];
        slap_bindconf           si_bindconf;
        struct berval           si_base;
        struct berval           si_logbase;
        struct berval           si_filterstr;
        struct berval           si_logfilterstr;
-       int                                     si_scope;
-       int                                     si_attrsonly;
-       char                            *si_anfile;
+       int                     si_scope;
+       int                     si_attrsonly;
+       char                    *si_anfile;
        AttributeName           *si_anlist;
        AttributeName           *si_exanlist;
-       char                            **si_attrs;
-       char                            **si_exattrs;
-       int                                     si_allattrs;
-       int                                     si_allopattrs;
-       int                                     si_schemachecking;
-       int                                     si_type;        /* the active type */
-       int                                     si_ctype;       /* the configured type */
-       time_t                          si_interval;
-       time_t                          *si_retryinterval;
-       int                                     *si_retrynum_init;
-       int                                     *si_retrynum;
+       char                    **si_attrs;
+       char                    **si_exattrs;
+       int                     si_allattrs;
+       int                     si_allopattrs;
+       int                     si_schemachecking;
+       int                     si_type;        /* the active type */
+       int                     si_ctype;       /* the configured type */
+       time_t                  si_interval;
+       time_t                  *si_retryinterval;
+       int                     *si_retrynum_init;
+       int                     *si_retrynum;
        struct sync_cookie      si_syncCookie;
        cookie_state            *si_cookieState;
-       int                                     si_cookieAge;
-       int                                     si_manageDSAit;
-       int                                     si_slimit;
-       int                                     si_tlimit;
-       int                                     si_refreshDelete;
-       int                                     si_refreshPresent;
-       int                                     si_syncdata;
-       int                                     si_logstate;
-       int                                     si_conn_setup;
-       Avlnode                         *si_presentlist;
-       LDAP                            *si_ld;
-       LDAP_LIST_HEAD(np, nonpresent_entry) si_nonpresentlist;
+       int                     si_cookieAge;
+       int                     si_manageDSAit;
+       int                     si_slimit;
+       int                     si_tlimit;
+       int                     si_refreshDelete;
+       int                     si_refreshPresent;
+       int                     si_syncdata;
+       int                     si_logstate;
+       int                     si_conn_setup;
+       Avlnode                 *si_presentlist;
+       LDAP                    *si_ld;
+       LDAP_LIST_HEAD(np, nonpresent_entry)    si_nonpresentlist;
        ldap_pvt_thread_mutex_t si_mutex;
 } syncinfo_t;
 
@@ -120,12 +120,32 @@ static struct berval * slap_uuidstr_from_normalized(
                                        struct berval *, struct berval *, void * );
 
 /* callback functions */
-static int dn_callback( struct slap_op *, struct slap_rep * );
-static int nonpresent_callback( struct slap_op *, struct slap_rep * );
-static int null_callback( struct slap_op *, struct slap_rep * );
+static int dn_callback( Operation *, SlapReply * );
+static int nonpresent_callback( Operation *, SlapReply * );
+static int null_callback( Operation *, SlapReply * );
 
 static AttributeDescription *sync_descs[4];
 
+static const char *
+syncrepl_state2str( int state )
+{
+       switch ( state ) {
+       case LDAP_SYNC_PRESENT:
+               return "PRESENT";
+
+       case LDAP_SYNC_ADD:
+               return "ADD";
+
+       case LDAP_SYNC_MODIFY:
+               return "MODIFY";
+
+       case LDAP_SYNC_DELETE:
+               return "DELETE";
+       }
+
+       return "UNKNOWN";
+}
+
 static void
 init_syncrepl(syncinfo_t *si)
 {
@@ -203,10 +223,6 @@ init_syncrepl(syncinfo_t *si)
                        attrs = ( char ** ) ch_realloc( attrs, (n + 4)*sizeof( char * ) );
                }
 
-               if ( attrs == NULL ) {
-                       Debug( LDAP_DEBUG_ANY, "out of memory\n", 0, 0, 0 );
-               }
-
                /* Add Attributes */
                if ( si->si_allopattrs ) {
                        attrs[n++] = ch_strdup( sync_descs[0]->ad_cname.bv_val );
@@ -324,7 +340,6 @@ ldap_sync_search(
        BerElementBuffer berbuf;
        BerElement *ber = (BerElement *)&berbuf;
        LDAPControl c[2], *ctrls[3];
-       struct timeval timeout;
        ber_int_t       msgid;
        int rc;
        int rhint;
@@ -409,12 +424,8 @@ ldap_sync_search(
                ctrls[1] = NULL;
        }
 
-       timeout.tv_sec = si->si_tlimit;
-       timeout.tv_usec = 0;
-
        rc = ldap_search_ext( si->si_ld, base, scope, filter, attrs, attrsonly,
-               ctrls, NULL, si->si_tlimit > 0 ? &timeout : NULL,
-               si->si_slimit, &msgid );
+               ctrls, NULL, NULL, si->si_slimit, &msgid );
        ber_free_buf( ber );
        return rc;
 }
@@ -453,6 +464,8 @@ do_syncrep1(
        op->o_ssf = ( op->o_sasl_ssf > op->o_tls_ssf )
                ?  op->o_sasl_ssf : op->o_tls_ssf;
 
+       ldap_set_option( si->si_ld, LDAP_OPT_TIMELIMIT, &si->si_tlimit );
+
        /* We've just started up, or the remote server hasn't sent us
         * any meaningful state.
         */
@@ -523,7 +536,7 @@ do_syncrep1(
                        si->si_syncCookie.sid );
        } else {
                AttributeName at[2];
-               Attribute a = { slap_schema.si_ad_contextCSN };
+               Attribute a = {0};
                Entry e = {0};
                SlapReply rs = {0};
                int i, j, changed = 0;
@@ -534,6 +547,7 @@ do_syncrep1(
                 * allowed, and all changes will already be reflected in
                 * the cookieState.
                 */
+               a.a_desc = slap_schema.si_ad_contextCSN;
                e.e_attrs = &a;
                e.e_name = si->si_wbe->be_suffix[0];
                e.e_nname = si->si_wbe->be_nsuffix[0];
@@ -542,6 +556,8 @@ do_syncrep1(
                at[0].an_name = a.a_desc->ad_cname;
                at[0].an_desc = a.a_desc;
                BER_BVZERO( &at[1].an_name );
+               op->o_req_dn = e.e_name;
+               op->o_req_ndn = e.e_nname;
 
                ldap_pvt_thread_mutex_lock( &si->si_cookieState->cs_mutex );
                rc = backend_operational( op, &rs );
@@ -688,7 +704,8 @@ do_syncrep2(
        struct sync_cookie      syncCookie_req = { NULL };
        struct berval           cookie = BER_BVNULL;
 
-       int     rc, err;
+       int             rc,
+                       err = LDAP_SUCCESS;
        ber_len_t       len;
 
        struct berval   *psub;
@@ -745,10 +762,19 @@ do_syncrep2(
                                /* we can't work without the control */
                                rctrlp = NULL;
                                if ( rctrls ) {
+                                       LDAPControl **next;
                                        /* NOTE: make sure we use the right one;
                                         * a better approach would be to run thru
                                         * the whole list and take care of all */
-                                       rctrlp = ldap_find_control( LDAP_CONTROL_SYNC_STATE, rctrls );
+                                       rctrlp = ldap_control_find( LDAP_CONTROL_SYNC_STATE, rctrls, &next );
+                                       if ( next && ldap_control_find( LDAP_CONTROL_SYNC_STATE, next, NULL ) )
+                                       {
+                                               Debug( LDAP_DEBUG_ANY, "do_syncrep2: %s "
+                                                       "got search entry with multiple "
+                                                       "Sync State control\n", si->si_ridtxt, 0, 0 );
+                                               rc = -1;
+                                               goto done;
+                                       }
                                }
                                if ( rctrlp == NULL ) {
                                        Debug( LDAP_DEBUG_ANY, "do_syncrep2: %s "
@@ -763,7 +789,9 @@ do_syncrep2(
                                 * (happens with back-sql...) */
                                if ( BER_BVISEMPTY( &syncUUID ) ) {
                                        Debug( LDAP_DEBUG_ANY, "do_syncrep2: %s "
-                                               "got empty syncUUID\n", si->si_ridtxt, 0, 0 );
+                                               "got empty syncUUID with LDAP_SYNC_%s\n",
+                                               si->si_ridtxt,
+                                               syncrepl_state2str( syncstate ), 0 );
                                        ldap_controls_free( rctrls );
                                        rc = -1;
                                        goto done;
@@ -1051,16 +1079,17 @@ do_syncrep2(
        }
 
        if ( rc == -1 ) {
-               const char *errstr;
-
                ldap_get_option( si->si_ld, LDAP_OPT_ERROR_NUMBER, &rc );
-               errstr = ldap_err2string( rc );
-               
-               Debug( LDAP_DEBUG_ANY,
-                       "do_syncrep2: %s %s\n", si->si_ridtxt, errstr, 0 );
+               err = rc;
        }
 
 done:
+       if ( err != LDAP_SUCCESS ) {
+               Debug( LDAP_DEBUG_ANY,
+                       "do_syncrep2: %s (%d) %s\n",
+                       si->si_ridtxt, err, ldap_err2string( err ) );
+       }
+
        slap_sync_cookie_free( &syncCookie, 0 );
        slap_sync_cookie_free( &syncCookie_req, 0 );
 
@@ -1093,7 +1122,7 @@ do_syncrepl(
        int rc = LDAP_SUCCESS;
        int dostop = 0;
        ber_socket_t s;
-       int i, defer = 1;
+       int i, defer = 1, fail = 0;
        Backend *be;
 
        Debug( LDAP_DEBUG_TRACE, "=>do_syncrepl %s\n", si->si_ridtxt, 0, 0 );
@@ -1126,8 +1155,8 @@ do_syncrepl(
                return NULL;
        }
 
-       op = (Operation *) &opbuf;
-       connection_fake_init( &conn, op, ctx );
+       connection_fake_init( &conn, &opbuf, ctx );
+       op = &opbuf.ob_op;
 
        /* use global malloc for now */
        op->o_tmpmemctx = NULL;
@@ -1143,7 +1172,7 @@ do_syncrepl(
        /* If we're glued, send writes through the glue parent */
        if ( !si->si_wbe ) {
                if ( SLAP_GLUE_SUBORDINATE( be )) {
-                       si->si_wbe = select_backend( &be->be_nsuffix[0], 0, 1 );
+                       si->si_wbe = select_backend( &be->be_nsuffix[0], 1 );
                } else {
                        si->si_wbe = be;
                }
@@ -1231,18 +1260,36 @@ reload:
                if ( !si->si_ctype
                        || !si->si_retrynum || si->si_retrynum[i] == RETRYNUM_TAIL ) {
                        ldap_pvt_runqueue_remove( &slapd_rq, rtask );
+                       fail = RETRYNUM_TAIL;
                } else if ( RETRYNUM_VALID( si->si_retrynum[i] ) ) {
                        if ( si->si_retrynum[i] > 0 )
                                si->si_retrynum[i]--;
+                       fail = si->si_retrynum[i];
                        rtask->interval.tv_sec = si->si_retryinterval[i];
                        ldap_pvt_runqueue_resched( &slapd_rq, rtask, 0 );
                        slap_wake_listener();
                }
        }
-       
+
        ldap_pvt_thread_mutex_unlock( &slapd_rq.rq_mutex );
        ldap_pvt_thread_mutex_unlock( &si->si_mutex );
 
+       if ( rc ) {
+               if ( fail == RETRYNUM_TAIL ) {
+                       Debug( LDAP_DEBUG_ANY,
+                               "do_syncrepl: rid %03d quitting\n",
+                               si->si_rid, 0, 0 );
+               } else if ( fail > 0 ) {
+                       Debug( LDAP_DEBUG_ANY,
+                               "do_syncrepl: rid %03d retrying (%d retries left)\n",
+                               si->si_rid, fail, 0 );
+               } else {
+                       Debug( LDAP_DEBUG_ANY,
+                               "do_syncrepl: rid %03d retrying\n",
+                               si->si_rid, 0, 0 );
+               }
+       }
+
        /* Do final delete cleanup */
        if ( !si->si_ctype ) {
                cookie_state *cs = NULL;
@@ -1499,6 +1546,7 @@ syncrepl_message_to_op(
                        op->orm_modlist = modlist;
                        op->o_bd = si->si_wbe;
                        rc = op->o_bd->be_modify( op, &rs );
+                       modlist = op->orm_modlist;
                        Debug( rc ? LDAP_DEBUG_ANY : LDAP_DEBUG_SYNC,
                                "syncrepl_message_to_op: %s be_modify %s (%d)\n", 
                                si->si_ridtxt, op->o_req_dn.bv_val, rc );
@@ -1784,7 +1832,6 @@ syncrepl_entry(
        slap_callback   cb = { NULL, NULL, NULL, NULL };
        struct berval   *syncuuid_bv = NULL;
        struct berval   syncUUID_strrep = BER_BVNULL;
-       struct berval   uuid_bv = BER_BVNULL;
 
        SlapReply       rs_search = {REP_RESULT};
        SlapReply       rs_delete = {REP_RESULT};
@@ -1801,33 +1848,11 @@ syncrepl_entry(
        struct berval pdn = BER_BVNULL;
        dninfo dni = {0};
        int     retry = 1;
+       int     freecsn = 1;
 
-       switch( syncstate ) {
-       case LDAP_SYNC_PRESENT:
-               Debug( LDAP_DEBUG_SYNC, "syncrepl_entry: %s %s\n",
-                                       si->si_ridtxt,
-                                       "LDAP_RES_SEARCH_ENTRY(LDAP_SYNC_PRESENT)", 0 );
-               break;
-       case LDAP_SYNC_ADD:
-               Debug( LDAP_DEBUG_SYNC, "syncrepl_entry: %s %s\n",
-                                       si->si_ridtxt,
-                                       "LDAP_RES_SEARCH_ENTRY(LDAP_SYNC_ADD)", 0 );
-               break;
-       case LDAP_SYNC_DELETE:
-               Debug( LDAP_DEBUG_SYNC, "syncrepl_entry: %s %s\n",
-                                       si->si_ridtxt,
-                                       "LDAP_RES_SEARCH_ENTRY(LDAP_SYNC_DELETE)", 0 );
-               break;
-       case LDAP_SYNC_MODIFY:
-               Debug( LDAP_DEBUG_SYNC, "syncrepl_entry: %s %s\n",
-                                       si->si_ridtxt,
-                                       "LDAP_RES_SEARCH_ENTRY(LDAP_SYNC_MODIFY)", 0 );
-               break;
-       default:
-               Debug( LDAP_DEBUG_ANY, "syncrepl_entry: %s %s\n",
-                                       si->si_ridtxt,
-                                       "LDAP_RES_SEARCH_ENTRY(UNKNOWN syncstate)", 0 );
-       }
+       Debug( LDAP_DEBUG_SYNC,
+               "syncrepl_entry: %s LDAP_RES_SEARCH_ENTRY(LDAP_SYNC_%s)\n",
+               si->si_ridtxt, syncrepl_state2str( syncstate ), 0 );
 
        if (( syncstate == LDAP_SYNC_PRESENT || syncstate == LDAP_SYNC_ADD ) ) {
                if ( !si->si_refreshPresent ) {
@@ -1935,6 +1960,8 @@ syncrepl_entry(
                                si->si_ridtxt, dni.dn.bv_val ? dni.dn.bv_val : "(null)", 0 );
        }
 
+       assert( BER_BVISNULL( &op->o_csn ) );
+
        slap_op_time( &op->o_time, &op->o_tincr );
        switch ( syncstate ) {
        case LDAP_SYNC_ADD:
@@ -1949,6 +1976,7 @@ syncrepl_entry(
                                 */
                                assert( BER_BVISNULL( &op->o_csn ) );
                                op->o_csn = a->a_vals[0];
+                               freecsn = 0;
                        }
                }
 retry_add:;
@@ -2066,12 +2094,14 @@ retry_add:;
 
                        /* Setup opattrs too */
                        {
-                               AttributeDescription *opattrs[] = {
-                                       slap_schema.si_ad_entryCSN,
-                                       slap_schema.si_ad_modifiersName,
-                                       slap_schema.si_ad_modifyTimestamp,
-                                       NULL
+                               static AttributeDescription *nullattr = NULL;
+                               static AttributeDescription **const opattrs[] = {
+                                       &slap_schema.si_ad_entryCSN,
+                                       &slap_schema.si_ad_modifiersName,
+                                       &slap_schema.si_ad_modifyTimestamp,
+                                       &nullattr
                                };
+                               AttributeDescription *opattr;
                                Modifications *mod, **modtail, **ml;
                                int i;
 
@@ -2082,10 +2112,10 @@ retry_add:;
                                modtail = &mod->sml_next;
 
                                /* pull mod off incoming modlist, append to orr_modlist */
-                               for ( i = 0; opattrs[i]; i++ ) {
+                               for ( i = 0; (opattr = *opattrs[i]) != NULL; i++ ) {
                                        for ( ml = modlist; *ml; ml = &(*ml)->sml_next )
                                        {
-                                               if ( (*ml)->sml_desc == opattrs[i] ) {
+                                               if ( (*ml)->sml_desc == opattr ) {
                                                        mod = *ml;
                                                        *ml = mod->sml_next;
                                                        mod->sml_next = NULL;
@@ -2116,6 +2146,7 @@ retry_add:;
 
                        rc = op->o_bd->be_modify( op, &rs_modify );
                        slap_mods_free( op->orm_modlist, 1 );
+                       op->orm_no_opattrs = 0;
                        Debug( LDAP_DEBUG_SYNC,
                                        "syncrepl_entry: %s be_modify (%d)\n", 
                                        si->si_ridtxt, rc, 0 );
@@ -2178,8 +2209,12 @@ done:
        if ( !BER_BVISNULL( &dni.dn ) ) {
                op->o_tmpfree( dni.dn.bv_val, op->o_tmpmemctx );
        }
-       if ( entry )
+       if ( entry ) {
                entry_free( entry );
+       }
+       if ( !BER_BVISNULL( &op->o_csn ) && freecsn ) {
+               op->o_tmpfree( op->o_csn.bv_val, op->o_tmpmemctx );
+       }
        BER_BVZERO( &op->o_csn );
        return rc;
 }
@@ -2349,6 +2384,10 @@ syncrepl_del_nonpresent(
                        ber_bvfree( np_prev->npe_name );
                        ber_bvfree( np_prev->npe_nname );
                        ch_free( np_prev );
+
+                       if ( slapd_shutdown ) {
+                               break;
+                       }
                }
 
                slap_graduate_commit_csn( op );
@@ -2519,7 +2558,7 @@ syncrepl_updateCookie(
        Modifications mod[2];
        struct berval first = BER_BVNULL;
 
-       int rc, i, j;
+       int rc, i, j, len;
 
        slap_callback cb = { NULL };
        SlapReply       rs_modify = {REP_RESULT};
@@ -2544,8 +2583,11 @@ syncrepl_updateCookie(
                for ( j=0; j<si->si_cookieState->cs_num; j++ ) {
                        if ( syncCookie->sids[i] != si->si_cookieState->cs_sids[j] )
                                continue;
-                       if ( ber_bvcmp( &syncCookie->ctxcsn[i],
-                               &si->si_cookieState->cs_vals[j] ) > 0 ) {
+                       len = syncCookie->ctxcsn[i].bv_len;
+                       if ( len > si->si_cookieState->cs_vals[j].bv_len )
+                               len = si->si_cookieState->cs_vals[j].bv_len;
+                       if ( memcmp( syncCookie->ctxcsn[i].bv_val,
+                               si->si_cookieState->cs_vals[j].bv_val, len ) > 0 ) {
                                ber_bvarray_add_x( &mod[0].sml_values,
                                        &si->si_cookieState->cs_vals[j], op->o_tmpmemctx );
                                ber_bvarray_add_x( &mod[1].sml_values,
@@ -2563,6 +2605,11 @@ syncrepl_updateCookie(
                                first = syncCookie->ctxcsn[i];
                }
        }
+       /* Should never happen, ITS#5065 */
+       if ( BER_BVISNULL( &first )) {
+               ldap_pvt_thread_mutex_unlock( &si->si_cookieState->cs_mutex );
+               return 0;
+       }
        op->o_bd = si->si_wbe;
        slap_queue_csn( op, &first );
 
@@ -2585,6 +2632,7 @@ syncrepl_updateCookie(
 
        op->orm_no_opattrs = 1;
        rc = op->o_bd->be_modify( op, &rs_modify );
+       op->orm_no_opattrs = 0;
        op->o_msgid = 0;
 
        if ( rs_modify.sr_err == LDAP_SUCCESS ) {
@@ -2641,74 +2689,63 @@ attr_cmp( Operation *op, Attribute *old, Attribute *new,
        modtail = *mret;
 
        if ( old ) {
-               int n, o, d, a, *adds, *dels;
+               int n, o, nn, no;
+               struct berval **adds, **dels;
                /* count old and new */
                for ( o=0; old->a_vals[o].bv_val; o++ ) ;
                for ( n=0; new->a_vals[n].bv_val; n++ ) ;
 
-               adds = op->o_tmpalloc( sizeof(int) * n, op->o_tmpmemctx );
-               dels = op->o_tmpalloc( sizeof(int) * o, op->o_tmpmemctx );
-               d = 0;
-               a = 0;
-               i = 0;
-               j = 0;
+               adds = op->o_tmpalloc( sizeof(struct berval *) * n, op->o_tmpmemctx );
+               dels = op->o_tmpalloc( sizeof(struct berval *) * o, op->o_tmpmemctx );
 
-               while ( i < o && j < n ) {
-                       int k;
-                       if ( bvmatch( &old->a_vals[i], &new->a_vals[j] ) ) {
-                               i++;
-                               j++;
-                               continue;
-                       }
-                       for ( k = j + 1; k<n; k++ ) {
-                               if ( bvmatch( &old->a_vals[i], &new->a_vals[k] ) ) {
-                                       break;
-                               }
-                       }
-                       /* an old value was deleted */
-                       if ( k == n ) {
-                               dels[d++] = i++;
-                               continue;
-                       }
-                       for ( k = i + 1; k < o; k++ ) {
-                               if ( bvmatch( &old->a_vals[k], &new->a_vals[j] ) ) {
+               for ( i=0; i<o; i++ ) dels[i] = &old->a_vals[i];
+               for ( i=0; i<n; i++ ) adds[i] = &new->a_vals[i];
+
+               nn = n; no = o;
+
+               for ( i=0; i<o; i++ ) {
+                       for ( j=0; j<n; j++ ) {
+                               if ( !adds[j] )
+                                       continue;
+                               if ( bvmatch( dels[i], adds[j] ) ) {
+                                       no--;
+                                       nn--;
+                                       adds[j] = NULL;
+                                       dels[i] = NULL;
                                        break;
                                }
                        }
-                       if ( k == o ) {
-                               adds[a++] = j++;
-                       }
                }
-               while ( i < o )
-                       dels[d++] = i++;
-               while ( j < n )
-                       adds[a++] = j++;
 
+               i = j;
                /* all old values were deleted, just use the replace op */
-               if ( d == o ) {
+               if ( no == o ) {
                        i = j-1;
-               } else if ( d ) {
+               } else if ( no ) {
                /* delete some values */
                        mod = ch_malloc( sizeof( Modifications ) );
                        mod->sml_op = LDAP_MOD_DELETE;
                        mod->sml_flags = 0;
                        mod->sml_desc = old->a_desc;
                        mod->sml_type = mod->sml_desc->ad_cname;
-                       mod->sml_values = ch_malloc( ( d + 1 ) * sizeof(struct berval) );
+                       mod->sml_values = ch_malloc( ( no + 1 ) * sizeof(struct berval) );
                        if ( old->a_vals != old->a_nvals ) {
-                               mod->sml_nvalues = ch_malloc( ( d + 1 ) * sizeof(struct berval) );
+                               mod->sml_nvalues = ch_malloc( ( no + 1 ) * sizeof(struct berval) );
                        } else {
                                mod->sml_nvalues = NULL;
                        }
-                       for ( i = 0; i < d; i++ ) {
-                               ber_dupbv( &mod->sml_values[i], &old->a_vals[dels[i]] );
+                       j = 0;
+                       for ( i = 0; i < o; i++ ) {
+                               if ( !dels[i] ) continue;
+                               ber_dupbv( &mod->sml_values[j], &old->a_vals[i] );
                                if ( mod->sml_nvalues ) {
-                                       ber_dupbv( &mod->sml_nvalues[i], &old->a_nvals[dels[i]] );
+                                       ber_dupbv( &mod->sml_nvalues[j], &old->a_nvals[i] );
                                }
+                               j++;
                        }
-                       BER_BVZERO( &mod->sml_values[i] );
+                       BER_BVZERO( &mod->sml_values[j] );
                        if ( mod->sml_nvalues ) {
-                               BER_BVZERO( &mod->sml_nvalues[i] );
+                               BER_BVZERO( &mod->sml_nvalues[j] );
                        }
                        *modtail = mod;
                        modtail = &mod->sml_next;
@@ -2716,27 +2753,30 @@ attr_cmp( Operation *op, Attribute *old, Attribute *new,
                }
                op->o_tmpfree( dels, op->o_tmpmemctx );
                /* some values were added */
-               if ( a && d < o ) {
+               if ( nn && no < o ) {
                        mod = ch_malloc( sizeof( Modifications ) );
                        mod->sml_op = LDAP_MOD_ADD;
                        mod->sml_flags = 0;
                        mod->sml_desc = old->a_desc;
                        mod->sml_type = mod->sml_desc->ad_cname;
-                       mod->sml_values = ch_malloc( ( a + 1 ) * sizeof(struct berval) );
+                       mod->sml_values = ch_malloc( ( nn + 1 ) * sizeof(struct berval) );
                        if ( old->a_vals != old->a_nvals ) {
-                               mod->sml_nvalues = ch_malloc( ( a + 1 ) * sizeof(struct berval) );
+                               mod->sml_nvalues = ch_malloc( ( nn + 1 ) * sizeof(struct berval) );
                        } else {
                                mod->sml_nvalues = NULL;
                        }
-                       for ( i = 0; i < a; i++ ) {
-                               ber_dupbv( &mod->sml_values[i], &new->a_vals[adds[i]] );
+                       j = 0;
+                       for ( i = 0; i < n; i++ ) {
+                               if ( !adds[i] ) continue;
+                               ber_dupbv( &mod->sml_values[j], &new->a_vals[i] );
                                if ( mod->sml_nvalues ) {
-                                       ber_dupbv( &mod->sml_nvalues[i], &new->a_nvals[adds[i]] );
+                                       ber_dupbv( &mod->sml_nvalues[j], &new->a_nvals[i] );
                                }
+                               j++;
                        }
-                       BER_BVZERO( &mod->sml_values[i] );
+                       BER_BVZERO( &mod->sml_values[j] );
                        if ( mod->sml_nvalues ) {
-                               BER_BVZERO( &mod->sml_nvalues[i] );
+                               BER_BVZERO( &mod->sml_nvalues[j] );
                        }
                        *modtail = mod;
                        modtail = &mod->sml_next;
@@ -2784,7 +2824,7 @@ dn_callback(
                        if ( dni->new_entry ) {
                                Modifications **modtail, **ml;
                                Attribute *old, *new;
-                               int i, is_ctx;
+                               int is_ctx;
 
                                is_ctx = dn_match( &rs->sr_entry->e_nname,
                                        &op->o_bd->be_nsuffix[0] );
@@ -2827,15 +2867,29 @@ dn_callback(
                                        slap_schema.si_ad_entryCSN );
                                new = attr_find( dni->new_entry->e_attrs,
                                        slap_schema.si_ad_entryCSN );
-                               if ( new && old && ber_bvcmp( &old->a_vals[0],
-                                       &new->a_vals[0] ) >= 0 ) {
-                                       Debug( LDAP_DEBUG_SYNC,
-                                               "dn_callback : new entry is older than ours "
-                                               "%s ours %s, new %s\n",
-                                               rs->sr_entry->e_name.bv_val,
-                                               old->a_vals[0].bv_val,
-                                               new->a_vals[0].bv_val );
-                                       return LDAP_SUCCESS;
+                               if ( new && old ) {
+                                       int rc, len = old->a_vals[0].bv_len;
+                                       if ( len > new->a_vals[0].bv_len )
+                                               len = new->a_vals[0].bv_len;
+                                       rc = memcmp( old->a_vals[0].bv_val,
+                                               new->a_vals[0].bv_val, len );
+                                       if ( rc > 0 ) {
+                                               Debug( LDAP_DEBUG_SYNC,
+                                                       "dn_callback : new entry is older than ours "
+                                                       "%s ours %s, new %s\n",
+                                                       rs->sr_entry->e_name.bv_val,
+                                                       old->a_vals[0].bv_val,
+                                                       new->a_vals[0].bv_val );
+                                               return LDAP_SUCCESS;
+                                       } else if ( rc == 0 ) {
+                                               Debug( LDAP_DEBUG_SYNC,
+                                                       "dn_callback : entries have identical CSN "
+                                                       "%s ours %s, new %s\n",
+                                                       rs->sr_entry->e_name.bv_val,
+                                                       old->a_vals[0].bv_val,
+                                                       new->a_vals[0].bv_val );
+                                               return LDAP_SUCCESS;
+                                       }
                                }
 
                                /* We assume that attributes are saved in the same order
@@ -2997,6 +3051,7 @@ slap_uuidstr_from_normalized(
        struct berval* normalized,
        void *ctx )
 {
+#if 0
        struct berval *new;
        unsigned char nibble;
        int i, d = 0;
@@ -3044,6 +3099,52 @@ slap_uuidstr_from_normalized(
        }
 
        new->bv_val[new->bv_len] = '\0';
+       return new;
+#endif
+
+       struct berval   *new;
+       int             rc = 0;
+
+       if ( normalized == NULL ) return NULL;
+       if ( normalized->bv_len != 16 ) return NULL;
+
+       if ( uuidstr ) {
+               new = uuidstr;
+
+       } else {
+               new = (struct berval *)slap_sl_malloc( sizeof(struct berval), ctx );
+               if ( new == NULL ) {
+                       return NULL;
+               }
+       }
+
+       new->bv_len = 36;
+
+       if ( ( new->bv_val = slap_sl_malloc( new->bv_len + 1, ctx ) ) == NULL ) {
+               rc = 1;
+               goto done;
+       }
+
+       rc = lutil_uuidstr_from_normalized( normalized->bv_val,
+               normalized->bv_len, new->bv_val, new->bv_len + 1 );
+
+done:;
+       if ( rc == -1 ) {
+               if ( new != NULL ) {
+                       if ( new->bv_val != NULL ) {
+                               slap_sl_free( new->bv_val, ctx );
+                       }
+
+                       if ( new != uuidstr ) {
+                               slap_sl_free( new, ctx );
+                       }
+               }
+               new = NULL;
+
+       } else {
+               new->bv_len = rc;
+       }
+
        return new;
 }
 
@@ -3256,21 +3357,21 @@ parse_syncrepl_line(
                        /* '\0' string terminator accounts for '=' */
                        val = c->argv[ i ] + STRLENOF( IDSTR "=" );
                        if ( lutil_atoi( &tmp, val ) != 0 ) {
-                               snprintf( c->msg, sizeof( c->msg ),
+                               snprintf( c->cr_msg, sizeof( c->cr_msg ),
                                        "Error: parse_syncrepl_line: "
                                        "unable to parse syncrepl id \"%s\"", val );
-                               Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+                               Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
                                return -1;
                        }
-                       if ( tmp >= 1000 || tmp < 0 ) {
-                               snprintf( c->msg, sizeof( c->msg ),
+                       if ( tmp > SLAP_SYNC_SID_MAX || tmp < 0 ) {
+                               snprintf( c->cr_msg, sizeof( c->cr_msg ),
                                        "Error: parse_syncrepl_line: "
-                                       "syncrepl id %d is out of range [0..999]", tmp );
-                               Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+                                       "syncrepl id %d is out of range [0..4095]", tmp );
+                               Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
                                return -1;
                        }
                        si->si_rid = tmp;
-                       sprintf( si->si_ridtxt, IDSTR "=%03d", si->si_rid );
+                       sprintf( si->si_ridtxt, IDSTR "=%d", si->si_rid );
                        gots |= GOT_ID;
                } else if ( !strncasecmp( c->argv[ i ], PROVIDERSTR "=",
                                        STRLENOF( PROVIDERSTR "=" ) ) )
@@ -3316,10 +3417,19 @@ parse_syncrepl_line(
                        ber_str2bv( val, 0, 0, &bv );
                        rc = dnNormalize( 0, NULL, NULL, &bv, &si->si_base, NULL );
                        if ( rc != LDAP_SUCCESS ) {
-                               snprintf( c->msg, sizeof( c->msg ),
+                               snprintf( c->cr_msg, sizeof( c->cr_msg ),
                                        "Invalid base DN \"%s\": %d (%s)",
                                        val, rc, ldap_err2string( rc ) );
-                               Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+                               Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
+                               return -1;
+                       }
+                       if ( !be_issubordinate( c->be, &si->si_base ) ) {
+                               ch_free( si->si_base.bv_val );
+                               BER_BVZERO( &si->si_base );
+                               snprintf( c->cr_msg, sizeof( c->cr_msg ),
+                                       "Base DN \"%s\" is not within the database naming context",
+                                       val );
+                               Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
                                return -1;
                        }
                        gots |= GOT_BASE;
@@ -3336,10 +3446,10 @@ parse_syncrepl_line(
                        ber_str2bv( val, 0, 0, &bv );
                        rc = dnNormalize( 0, NULL, NULL, &bv, &si->si_logbase, NULL );
                        if ( rc != LDAP_SUCCESS ) {
-                               snprintf( c->msg, sizeof( c->msg ),
+                               snprintf( c->cr_msg, sizeof( c->cr_msg ),
                                        "Invalid logbase DN \"%s\": %d (%s)",
                                        val, rc, ldap_err2string( rc ) );
-                               Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+                               Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
                                return -1;
                        }
                } else if ( !strncasecmp( c->argv[ i ], SCOPESTR "=",
@@ -3354,10 +3464,10 @@ parse_syncrepl_line(
                                }
                        }
                        if ( BER_BVISNULL(&scopes[j].key) ) {
-                               snprintf( c->msg, sizeof( c->msg ),
+                               snprintf( c->cr_msg, sizeof( c->cr_msg ),
                                        "Error: parse_syncrepl_line: "
                                        "unknown scope \"%s\"", val);
-                               Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+                               Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
                                return -1;
                        }
                } else if ( !strncasecmp( c->argv[ i ], ATTRSONLYSTR,
@@ -3434,10 +3544,10 @@ parse_syncrepl_line(
                                si->si_type = si->si_ctype = LDAP_SYNC_REFRESH_AND_PERSIST;
                                si->si_interval = 60;
                        } else {
-                               snprintf( c->msg, sizeof( c->msg ),
+                               snprintf( c->cr_msg, sizeof( c->cr_msg ),
                                        "Error: parse_syncrepl_line: "
                                        "unknown sync type \"%s\"", val);
-                               Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+                               Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
                                return -1;
                        }
                } else if ( !strncasecmp( c->argv[ i ], INTERVALSTR "=",
@@ -3454,37 +3564,37 @@ parse_syncrepl_line(
                                 * should go before the call to strtoul() */
                                dd = strtoul( ptr, &next, 10 );
                                if ( ptr[ 0 ] == '-' || next == ptr || next[0] != ':' ) {
-                                       snprintf( c->msg, sizeof( c->msg ),
+                                       snprintf( c->cr_msg, sizeof( c->cr_msg ),
                                                "Error: parse_syncrepl_line: "
                                                "invalid interval \"%s\", unable to parse days", val );
-                                       Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+                                       Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
                                        return -1;
                                }
                                ptr = next + 1;
                                hh = strtoul( ptr, &next, 10 );
                                if ( ptr[ 0 ] == '-' || next == ptr || next[0] != ':' || hh > 24 ) {
-                                       snprintf( c->msg, sizeof( c->msg ),
+                                       snprintf( c->cr_msg, sizeof( c->cr_msg ),
                                                "Error: parse_syncrepl_line: "
                                                "invalid interval \"%s\", unable to parse hours", val );
-                                       Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+                                       Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
                                        return -1;
                                }
                                ptr = next + 1;
                                mm = strtoul( ptr, &next, 10 );
                                if ( ptr[ 0 ] == '-' || next == ptr || next[0] != ':' || mm > 60 ) {
-                                       snprintf( c->msg, sizeof( c->msg ),
+                                       snprintf( c->cr_msg, sizeof( c->cr_msg ),
                                                "Error: parse_syncrepl_line: "
                                                "invalid interval \"%s\", unable to parse minutes", val );
-                                       Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+                                       Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
                                        return -1;
                                }
                                ptr = next + 1;
                                ss = strtoul( ptr, &next, 10 );
                                if ( ptr[ 0 ] == '-' || next == ptr || next[0] != '\0' || ss > 60 ) {
-                                       snprintf( c->msg, sizeof( c->msg ),
+                                       snprintf( c->cr_msg, sizeof( c->cr_msg ),
                                                "Error: parse_syncrepl_line: "
                                                "invalid interval \"%s\", unable to parse seconds", val );
-                                       Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+                                       Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
                                        return -1;
                                }
                                si->si_interval = (( dd * 24 + hh ) * 60 + mm ) * 60 + ss;
@@ -3492,20 +3602,20 @@ parse_syncrepl_line(
                                unsigned long   t;
 
                                if ( lutil_parse_time( val, &t ) != 0 ) {
-                                       snprintf( c->msg, sizeof( c->msg ),
+                                       snprintf( c->cr_msg, sizeof( c->cr_msg ),
                                                "Error: parse_syncrepl_line: "
                                                "invalid interval \"%s\"", val );
-                                       Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+                                       Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
                                        return -1;
                                }
                                si->si_interval = (time_t)t;
                        }
                        if ( si->si_interval < 0 ) {
-                               snprintf( c->msg, sizeof( c->msg ),
+                               snprintf( c->cr_msg, sizeof( c->cr_msg ),
                                        "Error: parse_syncrepl_line: "
                                        "invalid interval \"%ld\"",
                                        (long) si->si_interval);
-                               Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+                               Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
                                return -1;
                        }
                } else if ( !strncasecmp( c->argv[ i ], RETRYSTR "=",
@@ -3523,9 +3633,9 @@ parse_syncrepl_line(
                        for ( k = 0; retry_list && retry_list[k]; k++ ) ;
                        n = k / 2;
                        if ( k % 2 ) {
-                               snprintf( c->msg, sizeof( c->msg ),
+                               snprintf( c->cr_msg, sizeof( c->cr_msg ),
                                        "Error: incomplete syncrepl retry list" );
-                               Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+                               Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
                                for ( k = 0; retry_list && retry_list[k]; k++ ) {
                                        ch_free( retry_list[k] );
                                }
@@ -3538,10 +3648,10 @@ parse_syncrepl_line(
                        for ( j = 0; j < n; j++ ) {
                                unsigned long   t;
                                if ( lutil_atoul( &t, retry_list[j*2] ) != 0 ) {
-                                       snprintf( c->msg, sizeof( c->msg ),
+                                       snprintf( c->cr_msg, sizeof( c->cr_msg ),
                                                "Error: invalid retry interval \"%s\" (#%d)",
                                                retry_list[j*2], j );
-                                       Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+                                       Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
                                        /* do some cleanup */
                                        return 1;
                                }
@@ -3555,20 +3665,20 @@ parse_syncrepl_line(
                                        if ( lutil_atoi( &si->si_retrynum_init[j], retry_list[j*2+1] ) != 0
                                                        || si->si_retrynum_init[j] <= 0 )
                                        {
-                                               snprintf( c->msg, sizeof( c->msg ),
+                                               snprintf( c->cr_msg, sizeof( c->cr_msg ),
                                                        "Error: invalid initial retry number \"%s\" (#%d)",
                                                        retry_list[j*2+1], j );
-                                               Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+                                               Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
                                                /* do some cleanup */
                                                return 1;
                                        }
                                        if ( lutil_atoi( &si->si_retrynum[j], retry_list[j*2+1] ) != 0
                                                        || si->si_retrynum[j] <= 0 )
                                        {
-                                               snprintf( c->msg, sizeof( c->msg ),
+                                               snprintf( c->cr_msg, sizeof( c->cr_msg ),
                                                        "Error: invalid retry number \"%s\" (#%d)",
                                                        retry_list[j*2+1], j );
-                                               Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+                                               Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
                                                /* do some cleanup */
                                                return 1;
                                        }
@@ -3589,10 +3699,10 @@ parse_syncrepl_line(
                        if ( lutil_atoi( &si->si_manageDSAit, val ) != 0
                                || si->si_manageDSAit < 0 || si->si_manageDSAit > 1 )
                        {
-                               snprintf( c->msg, sizeof( c->msg ),
+                               snprintf( c->cr_msg, sizeof( c->cr_msg ),
                                        "invalid manageDSAit value \"%s\".\n",
                                        val );
-                               Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+                               Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
                                return 1;
                        }
                } else if ( !strncasecmp( c->argv[ i ], SLIMITSTR "=",
@@ -3603,10 +3713,10 @@ parse_syncrepl_line(
                                si->si_slimit = 0;
 
                        } else if ( lutil_atoi( &si->si_slimit, val ) != 0 || si->si_slimit < 0 ) {
-                               snprintf( c->msg, sizeof( c->msg ),
+                               snprintf( c->cr_msg, sizeof( c->cr_msg ),
                                        "invalid size limit value \"%s\".\n",
                                        val );
-                               Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+                               Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
                                return 1;
                        }
                } else if ( !strncasecmp( c->argv[ i ], TLIMITSTR "=",
@@ -3617,10 +3727,10 @@ parse_syncrepl_line(
                                si->si_tlimit = 0;
 
                        } else if ( lutil_atoi( &si->si_tlimit, val ) != 0 || si->si_tlimit < 0 ) {
-                               snprintf( c->msg, sizeof( c->msg ),
+                               snprintf( c->cr_msg, sizeof( c->cr_msg ),
                                        "invalid time limit value \"%s\".\n",
                                        val );
-                               Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+                               Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
                                return 1;
                        }
                } else if ( !strncasecmp( c->argv[ i ], SYNCDATASTR "=",
@@ -3629,21 +3739,21 @@ parse_syncrepl_line(
                        val = c->argv[ i ] + STRLENOF( SYNCDATASTR "=" );
                        si->si_syncdata = verb_to_mask( val, datamodes );
                } else if ( bindconf_parse( c->argv[i], &si->si_bindconf ) ) {
-                       snprintf( c->msg, sizeof( c->msg ),
+                       snprintf( c->cr_msg, sizeof( c->cr_msg ),
                                "Error: parse_syncrepl_line: "
                                "unable to parse \"%s\"\n", c->argv[ i ] );
-                       Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+                       Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
                        return -1;
                }
        }
 
        if ( gots != GOT_ALL ) {
-               snprintf( c->msg, sizeof( c->msg ),
+               snprintf( c->cr_msg, sizeof( c->cr_msg ),
                        "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 );
+               Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
                return -1;
        }
 
@@ -3658,14 +3768,14 @@ add_syncrepl(
        int     rc = 0;
 
        if ( !( c->be->be_search && c->be->be_add && c->be->be_modify && c->be->be_delete ) ) {
-               snprintf( c->msg, sizeof(c->msg), "database %s does not support "
+               snprintf( c->cr_msg, sizeof(c->cr_msg), "database %s does not support "
                        "operations required for syncrepl", c->be->be_type );
-               Debug( LDAP_DEBUG_ANY, "%s: %s\n", c->log, c->msg, 0 );
+               Debug( LDAP_DEBUG_ANY, "%s: %s\n", c->log, c->cr_msg, 0 );
                return 1;
        }
        if ( BER_BVISEMPTY( &c->be->be_rootdn ) ) {
-               strcpy( c->msg, "rootDN must be defined before syncrepl may be used" );
-               Debug( LDAP_DEBUG_ANY, "%s: %s\n", c->log, c->msg, 0 );
+               strcpy( c->cr_msg, "rootDN must be defined before syncrepl may be used" );
+               Debug( LDAP_DEBUG_ANY, "%s: %s\n", c->log, c->cr_msg, 0 );
                return 1;
        }
        si = (syncinfo_t *) ch_calloc( 1, sizeof( syncinfo_t ) );
@@ -3753,6 +3863,9 @@ add_syncrepl(
                                else
                                        rc = -1;
                        }
+               } else {
+                       /* mirrormode still needs to see this flag in tool mode */
+                       rc = config_sync_shadow( c ) ? -1 : 0;
                }
        }
 
@@ -3804,7 +3917,8 @@ syncrepl_unparse( syncinfo_t *si, struct berval *bv )
        si->si_bindconf.sb_version = LDAP_VERSION3;
 
        ptr = buf;
-       ptr += snprintf( ptr, WHATSLEFT, IDSTR "=%03ld " PROVIDERSTR "=%s",
+       assert( si->si_rid >= 0 && si->si_rid <= SLAP_SYNC_SID_MAX );
+       ptr += snprintf( ptr, WHATSLEFT, IDSTR "=%d " PROVIDERSTR "=%s",
                si->si_rid, si->si_bindconf.sb_uri.bv_val );
        if ( ptr - buf >= sizeof( buf ) ) return;
        if ( !BER_BVISNULL( &bc ) ) {
index c5b36cfdfdeaf18ef4851e8c709d84aaa2f53583..249f3681d9449df45f56784e9dbbdd15e8c1e52e 100644 (file)
@@ -30,7 +30,7 @@ struct sindexrec {
 };
 
 static Avlnode *syn_index = NULL;
-static LDAP_SLIST_HEAD(SyntaxList, slap_syntax) syn_list
+static LDAP_SLIST_HEAD(SyntaxList, Syntax) syn_list
        = LDAP_SLIST_HEAD_INITIALIZER(&syn_list);
 
 static int
@@ -76,16 +76,48 @@ syn_find_desc( const char *syndesc, int *len )
        return( NULL );
 }
 
+int
+syn_is_sup( Syntax *syn, Syntax *sup )
+{
+       int     i;
+
+       assert( syn != NULL );
+       assert( sup != NULL );
+
+       if ( syn == sup ) {
+               return 1;
+       }
+
+       if ( syn->ssyn_sups == NULL ) {
+               return 0;
+       }
+
+       for ( i = 0; syn->ssyn_sups[i]; i++ ) {
+               if ( syn->ssyn_sups[i] == sup ) {
+                       return 1;
+               }
+
+               if ( syn_is_sup( syn->ssyn_sups[i], sup ) ) {
+                       return 1;
+               }
+       }
+
+       return 0;
+}
+
 void
 syn_destroy( void )
 {
-       Syntax *s;
-
-       avl_free(syn_index, ldap_memfree);
-       while( !LDAP_SLIST_EMPTY(&syn_list) ) {
-               s = LDAP_SLIST_FIRST(&syn_list);
-               LDAP_SLIST_REMOVE_HEAD(&syn_list, ssyn_next);
-               ldap_syntax_free((LDAPSyntax *)s);
+       Syntax  *s;
+
+       avl_free( syn_index, ldap_memfree );
+       while( !LDAP_SLIST_EMPTY( &syn_list ) ) {
+               s = LDAP_SLIST_FIRST( &syn_list );
+               LDAP_SLIST_REMOVE_HEAD( &syn_list, ssyn_next );
+               if ( s->ssyn_sups ) {
+                       SLAP_FREE( s->ssyn_sups );
+               }
+               ldap_syntax_free( (LDAPSyntax *)s );
        }
 }
 
@@ -129,12 +161,12 @@ syn_add(
 )
 {
        Syntax          *ssyn;
-       int             code;
+       int             code = 0;
 
        ssyn = (Syntax *) SLAP_CALLOC( 1, sizeof(Syntax) );
-       if( ssyn == NULL ) {
+       if ( ssyn == NULL ) {
                Debug( LDAP_DEBUG_ANY, "SLAP_CALLOC Error\n", 0, 0, 0 );
-               return LDAP_OTHER;
+               return SLAP_SCHERR_OUTOFMEM;
        }
 
        AC_MEMCPY( &ssyn->ssyn_syn, syn, sizeof(LDAPSyntax) );
@@ -151,12 +183,48 @@ syn_add(
        ssyn->ssyn_validate = def->sd_validate;
        ssyn->ssyn_pretty = def->sd_pretty;
 
+       ssyn->ssyn_sups = NULL;
+
 #ifdef SLAPD_BINARY_CONVERSION
        ssyn->ssyn_ber2str = def->sd_ber2str;
        ssyn->ssyn_str2ber = def->sd_str2ber;
 #endif
 
-       code = syn_insert(ssyn, err);
+       if ( def->sd_sups != NULL ) {
+               int     cnt;
+
+               for ( cnt = 0; def->sd_sups[cnt] != NULL; cnt++ )
+                       ;
+               
+               ssyn->ssyn_sups = (Syntax **)SLAP_CALLOC( cnt + 1,
+                       sizeof( Syntax * ) );
+               if ( ssyn->ssyn_sups == NULL ) {
+                       Debug( LDAP_DEBUG_ANY, "SLAP_CALLOC Error\n", 0, 0, 0 );
+                       code = SLAP_SCHERR_OUTOFMEM;
+
+               } else {
+                       for ( cnt = 0; def->sd_sups[cnt] != NULL; cnt++ ) {
+                               ssyn->ssyn_sups[cnt] = syn_find( def->sd_sups[cnt] );
+                               if ( ssyn->ssyn_sups[cnt] == NULL ) {
+                                       *err = def->sd_sups[cnt];
+                                       code = SLAP_SCHERR_SYN_SUP_NOT_FOUND;
+                               }
+                       }
+               }
+       }
+
+       if ( code == 0 ) {
+               code = syn_insert( ssyn, err );
+
+       }
+
+       if ( code != 0 && ssyn != NULL ) {
+               if ( ssyn->ssyn_sups != NULL ) {
+                       SLAP_FREE( ssyn->ssyn_sups );
+               }
+               SLAP_FREE( ssyn );
+       }
+
        return code;
 }
 
index 87263443a50686cfdf1889517ae5c54b59963616..0757418f4ec28717d99382c26ac57d2b5215c564 100644 (file)
@@ -36,7 +36,8 @@
 int
 do_unbind( Operation *op, SlapReply *rs )
 {
-       Debug( LDAP_DEBUG_TRACE, "do_unbind\n", 0, 0, 0 );
+       Debug( LDAP_DEBUG_TRACE, "%s do_unbind\n",
+               op->o_log_prefix, 0, 0 );
 
        /*
         * Parse the unbind request.  It looks like this:
index cd03ff97319204aadb58ad4b5baa5785438307d6..f6332eea62055ae5223a06fa6be83dc018822078 100644 (file)
@@ -430,19 +430,26 @@ ordered_value_validate(
 
                /* Skip past the assertion index */
                if ( bv.bv_val[0] == '{' ) {
-                       char    *ptr;
+                       char            *ptr;
 
                        ptr = ber_bvchr( &bv, '}' );
-                       if ( ptr == NULL ) {
-                               return LDAP_INVALID_SYNTAX;
+                       if ( ptr != NULL ) {
+                               struct berval   ns;
+
+                               ns.bv_val = bv.bv_val + 1;
+                               ns.bv_len = ptr - ns.bv_val;
+
+                               if ( numericStringValidate( NULL, &ns ) == LDAP_SUCCESS ) {
+                                       ptr++;
+                                       bv.bv_len -= ptr - bv.bv_val;
+                                       bv.bv_val = ptr;
+                                       in = &bv;
+                                       /* If deleting by index, just succeed */
+                                       if ( mop == LDAP_MOD_DELETE && BER_BVISEMPTY( &bv ) ) {
+                                               return LDAP_SUCCESS;
+                                       }
+                               }
                        }
-                       ptr++;
-                       bv.bv_len -= ptr - bv.bv_val;
-                       bv.bv_val = ptr;
-                       in = &bv;
-                       /* If deleting by index, just succeed */
-                       if ( mop == LDAP_MOD_DELETE && BER_BVISEMPTY( &bv ))
-                               return LDAP_SUCCESS;
                }
        }
 
@@ -478,18 +485,24 @@ ordered_value_pretty(
                        char    *ptr;
 
                        ptr = ber_bvchr( &bv, '}' );
-                       if ( ptr == NULL ) {
-                               return LDAP_INVALID_SYNTAX;
-                       }
-                       ptr++;
+                       if ( ptr != NULL ) {
+                               struct berval   ns;
+
+                               ns.bv_val = bv.bv_val + 1;
+                               ns.bv_len = ptr - ns.bv_val;
 
-                       idx = bv;
-                       idx.bv_len = ptr - bv.bv_val;
+                               if ( numericStringValidate( NULL, &ns ) == LDAP_SUCCESS ) {
+                                       ptr++;
 
-                       bv.bv_len -= idx.bv_len;
-                       bv.bv_val = ptr;
+                                       idx = bv;
+                                       idx.bv_len = ptr - bv.bv_val;
 
-                       val = &bv;
+                                       bv.bv_len -= idx.bv_len;
+                                       bv.bv_val = ptr;
+
+                                       val = &bv;
+                               }
+                       }
                }
        }
 
@@ -541,23 +554,29 @@ ordered_value_normalize(
                        char    *ptr;
 
                        ptr = ber_bvchr( &bv, '}' );
-                       if ( ptr == NULL ) {
-                               return LDAP_INVALID_SYNTAX;
-                       }
-                       ptr++;
+                       if ( ptr != NULL ) {
+                               struct berval   ns;
+
+                               ns.bv_val = bv.bv_val + 1;
+                               ns.bv_len = ptr - ns.bv_val;
 
-                       idx = bv;
-                       idx.bv_len = ptr - bv.bv_val;
+                               if ( numericStringValidate( NULL, &ns ) == LDAP_SUCCESS ) {
+                                       ptr++;
 
-                       bv.bv_len -= idx.bv_len;
-                       bv.bv_val = ptr;
+                                       idx = bv;
+                                       idx.bv_len = ptr - bv.bv_val;
 
-                       /* validator will already prevent this for Adds */
-                       if ( BER_BVISEMPTY( &bv )) {
-                               ber_dupbv_x( normalized, &idx, ctx );
-                               return LDAP_SUCCESS;
+                                       bv.bv_len -= idx.bv_len;
+                                       bv.bv_val = ptr;
+
+                                       /* validator will already prevent this for Adds */
+                                       if ( BER_BVISEMPTY( &bv )) {
+                                               ber_dupbv_x( normalized, &idx, ctx );
+                                               return LDAP_SUCCESS;
+                                       }
+                                       val = &bv;
+                               }
                        }
-                       val = &bv;
                }
        }
 
@@ -609,54 +628,57 @@ ordered_value_match(
         */
        if ( ad->ad_type->sat_flags & SLAP_AT_ORDERED ) {
                char *ptr;
-               struct berval iv;
+               struct berval ns1 = BER_BVNULL, ns2 = BER_BVNULL;
 
                bv1 = *v1;
                bv2 = *v2;
-               iv = bv2;
 
                /* Skip past the assertion index */
                if ( bv2.bv_val[0] == '{' ) {
                        ptr = ber_bvchr( &bv2, '}' );
-                       if ( ptr == NULL ) {
-                               return LDAP_INVALID_SYNTAX;
+                       if ( ptr != NULL ) {
+                               ns2.bv_val = bv2.bv_val + 1;
+                               ns2.bv_len = ptr - ns2.bv_val;
+
+                               if ( numericStringValidate( NULL, &ns2 ) == LDAP_SUCCESS ) {
+                                       ptr++;
+                                       bv2.bv_len -= ptr - bv2.bv_val;
+                                       bv2.bv_val = ptr;
+                                       v2 = &bv2;
+                               }
                        }
-                       ptr++;
-                       bv2.bv_len -= ptr - bv2.bv_val;
-                       bv2.bv_val = ptr;
-                       v2 = &bv2;
                }
 
-               if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX( flags )) {
-                       if ( iv.bv_val[0] == '{' && bv1.bv_val[0] == '{' ) {
-                       /* compare index values first */
-                               long l1, l2, ret;
-
-                               l1 = strtol( bv1.bv_val+1, NULL, 0 );
-                               l2 = strtol( iv.bv_val+1, &ptr, 0 );
+               /* Skip past the attribute index */
+               if ( bv1.bv_val[0] == '{' ) {
+                       ptr = ber_bvchr( &bv1, '}' );
+                       if ( ptr != NULL ) {
+                               ns1.bv_val = bv1.bv_val + 1;
+                               ns1.bv_len = ptr - ns1.bv_val;
+
+                               if ( numericStringValidate( NULL, &ns1 ) == LDAP_SUCCESS ) {
+                                       ptr++;
+                                       bv1.bv_len -= ptr - bv1.bv_val;
+                                       bv1.bv_val = ptr;
+                                       v1 = &bv1;
+                               }
+                       }
+               }
 
-                               ret = l1 - l2;
+               if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX( flags )) {
+                       if ( !BER_BVISNULL( &ns2 ) && !BER_BVISNULL( &ns1 ) ) {
+                               /* compare index values first */
+                               (void)octetStringOrderingMatch( match, 0, NULL, NULL, &ns1, &ns2 );
 
                                /* If not equal, or we're only comparing the index,
                                 * return result now.
                                 */
-                               if ( ret || ptr == iv.bv_val + iv.bv_len - 1 ) {
-                                       *match = ( ret < 0 ) ? -1 : (ret > 0 );
+                               if ( *match != 0 || BER_BVISEMPTY( &bv2 ) ) {
                                        return LDAP_SUCCESS;
                                }
                        }
                }
-               /* Skip past the attribute index */
-               if ( bv1.bv_val[0] == '{' ) {
-                       ptr = ber_bvchr( &bv1, '}' );
-                       if ( ptr == NULL ) {
-                               return LDAP_INVALID_SYNTAX;
-                       }
-                       ptr++;
-                       bv1.bv_len -= ptr - bv1.bv_val;
-                       bv1.bv_val = ptr;
-                       v1 = &bv1;
-               }
+
        }
 
        if ( !mr || !mr->smr_match ) {
@@ -712,6 +734,7 @@ ordered_value_add(
 
                k = -1;
                if ( vals[i].bv_val[0] == '{' ) {
+                       /* FIXME: strtol() could go past end... */
                        k = strtol( vals[i].bv_val + 1, &next, 0 );
                        if ( next == vals[i].bv_val + 1 ||
                                next[ 0 ] != '}' ||
diff --git a/servers/slurpd/DESIGN b/servers/slurpd/DESIGN
deleted file mode 100644 (file)
index dc5994e..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-Design Notes: slurpd
-
-This new version differs significantly from previous versions:
-
-- It uses a multithreaded, single-process model.  Previous versions forked
-  a separate process for each replica.  This new design should facilitate
-  porting to NT, and is more straightforward.
-
-- Only one copy of the replication log is made.  Previous versions made
-one copy of the replication log for each replica
-
-- This newer version is more object-oriented.  Although still written in
-  ANSI C (and compilable on k&r compilers), it encapsulates within the
-  major data structures the methods used to access "private" data.
-
-General design overview:
-
-The main data structure in slurpd is a replication queue (struct rq).
-The rq data structure is currently implemented as a linked list of 
-replication entries (struct re).  The rq structure contains member functions
-used to initialize, add to, remove, and return the next re struct.
-
-In addition to the rq structure, there is one ri (replication information)
-struct for each replica.  The ri struct encapsulates all information
-about a particular replica, e.g. hostname, port, bind dn.  The single
-public member function, ri_process, is called to begin processing
-the replication entries in the queue.
-
-There is also a status structure (struct st) which contains the timestamp
-of the last successful replication operation for each replica.  The
-contents of the st struct are flushed to disk after every successful
-operation.  This disk file is read upon startup, and is used to allow
-slapd to "pick up where it left off".
-
-Threading notes:
-
-The LDAP liblthread quasi-pthreads interface is used for threading.  At
-this point, machines which do not support pthreads, sun threads or lwp
-will probably not be able to run slurpd.  Given the current threading
-method, discussed in the next paragraph, it will probably be necessary to
-have a separate hunk of code which handles non-threaded architectures
-(or we might just not worry about it).  This needs further discussion.
-
-Upon startup, command-line arguments and the slapd configuration file
-are processed.  One thread is started for each replica.  Thread replicas,
-when no more work exists, wait on a condition variable, and the main
-thread's file manager routine broadcasts on this condition variable
-when new work is added to the queue. 
-
-Additional notes:
-       See doc/devel/replication-notes.txt
diff --git a/servers/slurpd/Makefile.in b/servers/slurpd/Makefile.in
deleted file mode 100644 (file)
index 9ce402c..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-# Makefile.in for slurpd
-# $OpenLDAP$
-## This work is part of OpenLDAP Software <http://www.openldap.org/>.
-##
-## Copyright 1998-2007 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>.
-
-PROGRAMS = slurpd
-XPROGRAMS = sslurpd
-
-XSRCS  = version.c
-
-NT_SRCS        = nt_svc.c
-NT_OBJS = nt_svc.o ../../libraries/liblutil/slapdmsg.res
-
-SRCS   =       admin.c args.c ch_malloc.c config.c \
-               fm.c globals.c ldap_op.c lock.c main.c re.c \
-               reject.c replica.c replog.c ri.c rq.c sanity.c st.c \
-               $(@PLAT@_SRCS)
-OBJS   =       admin.o args.o ch_malloc.o config.o \
-               fm.o globals.o ldap_op.o lock.o main.o re.o \
-               reject.o replica.o replog.o ri.o rq.o sanity.o st.o \
-               $(@PLAT@_OBJS)
-
-LDAP_INCDIR= ../../include       
-LDAP_LIBDIR= ../../libraries
-
-BUILD_OPT = "--enable-slurpd"
-BUILD_SRV = @BUILD_SLURPD@
-
-all-local-srv:         $(PROGRAMS)
-
-# $(LTHREAD_LIBS) must be last!
-XLIBS = $(SLURPD_L)
-XXLIBS = $(SLURPD_LIBS) $(SECURITY_LIBS) $(LUTIL_LIBS)
-XXXLIBS = $(LTHREAD_LIBS)
-
-slurpd:        version.o
-       $(LTLINK) -o $@ $(OBJS) version.o $(LIBS)
-
-sslurpd:       version.o
-       $(LTLINK) -static -o $@ $(OBJS) version.o $(LIBS)
-
-version.c: Makefile
-       @-$(RM) $@
-       $(MKVERSION) -s -n Versionstr slurpd > $@
-
-version.o: version.c $(OBJS) $(SLURPD_L)
-
-install-local-srv: FORCE
-       -$(MKDIR) $(DESTDIR)$(libexecdir)
-       @-$(INSTALL) -m 700 -d $(DESTDIR)$(localstatedir)/openldap-slurp
-       @(                                                              \
-           for prg in $(PROGRAMS); do                                  \
-               $(LTINSTALL) $(INSTALLFLAGS) $(STRIP) -m 755 $$prg$(EXEEXT)     \
-                   $(DESTDIR)$(libexecdir);                            \
-           done                                                        \
-       )
-
diff --git a/servers/slurpd/NOTES b/servers/slurpd/NOTES
deleted file mode 100644 (file)
index c8b1ae9..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-Written by Ganesan Rajagopal <rganesan@debian.org> and placed in the public
-domain.
-
-Replication in OpenLDAP
------------------------
-
-Please read "Section 10. Replication with slurpd" in the OpenLDAP guide for
-an overview and configuration of single-master replication. This document
-describes the internals of the replication mechanism.
-
-slapd/repl.c contains routines add_replica_info() and
-add_replica_suffix(). add_replica_info() adds a new host to the list of
-replicas for a backend. add_replica_info() returns a number for the
-replica. add_replica_suffix() must then be called with the replica number to
-add a suffix that is hosted on this replica. add_replica_info() and add_replica_suffix() do not lock the
-replog_mutex.
-
-Replicas are specified in the slapd.conf file. When slapd/config.c sees a
-"replica" line in slapd.conf, it calls add_replica_info() with the host
-specified in the "host=" directive and then calls add_replica_suffix() with
-the replica number and and the suffix specified in the "suffix="
-directive. 
-
-slapd writes out a replication log file containing LDIF change records for
-each configured replica for a suffix. The change records are generated for
-add, modify, delete and modrdn operations. A function called replog() is
-called at the end of the routines do_add (slapd/add.c),
-do_modify(slapd/modify.c), do_delete(slapd/delete.c) and
-do_modrdn(slapd/modrnd.c) to write out the change records.
-
-In master/slave replication, updates are not allowed on slave
-replicas. Therefore replog() is not called if the suffix is configured with
-a updatedn (which indicates that this is a slave replica), instead a
-referral is returned back to the client. If multi-master replication is
-enabled, replog() is always called whenever any of the above updates happen
-unless the dn which is making the change is the updatedn. When the dn making
-the change is the same as the updatedn, it is assumed that this entry is
-being replicated by a slurpd instance on another host. (Note: For this
-reason, the updatedn must not be a "regular" admin/user object in
-multi-master replication).
-
-The function replog() in slapd/repl.c generates the actual change
-records. Each change record is preceded by the list of replicas to which
-this change record needs to be replicated, the time when this change
-happened and the dn this change applies to. The pseudo code for replog() is
-follows
-
-1. Check that a replog exists.
-2. Lock the replog mutex.
-3. Open and lock the replog file. 
-4. Normalize the dn for the entry and write out a "replica:" entry for each
-   replica with a matching suffix. 
-5. Write out the the timestamp and the dn for the entry.
-6. Depending on the type of change, write out an appropriate changetype
-   record.
-7. Close the replication log
-8. Unlock the replog mutex
-
-slurpd has a file manager routine (function fm()) which watches for any
-change in the replication log. Whenever fm() detects a change in the
-replication log it locks the log, appends the records to slurpd's private
-copy of the replication log and truncates the log. See the slurpd/DESIGN
-file for a description of how slurpd works. 
-
-slapd can be configured to write out a replication log even if no replicas
-are configured. In this case the administrator has to truncate the
-replication log manually (under a lock!).
diff --git a/servers/slurpd/admin.c b/servers/slurpd/admin.c
deleted file mode 100644 (file)
index fa4e8f8..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 1998-2007 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>.
- */
-/* Portions Copyright (c) 1996 Regents of the University of Michigan.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that this notice is preserved and that due credit is given
- * to the University of Michigan at Ann Arbor. The name of the University
- * may not be used to endorse or promote products derived from this
- * software without specific prior written permission. This software
- * is provided ``as is'' without express or implied warranty.
- */
-/* ACKNOWLEDGEMENTS:
- * This work was originally developed by the University of Michigan
- * (as part of U-MICH LDAP).
- */
-
-/*
- * admin.c - routines for performing administrative tasks, e.g. on-the-fly
- * reconfiguration of slurpd.
- */
-
-#include "portable.h"
-
-#include <stdio.h>
-#include <ac/stdlib.h>
-
-#include <ac/signal.h>
-
-#include "slurp.h"
-#include "globals.h"
-
-
-/*
- * Eventually, do_admin will be the entry point for performing
- * administrative tasks.  General idea: put commands in a file
- * somewhere, send slurpd a USR2 signal.  The handler for
- * USR2 (this routine) reads the file and takes some action.
- *
- * For right now, this routine has been hijacked for debugging.  When
- * slurpd receives a USR2 signal, it will dump its replication 
- * queue to the disk file given by SLURPD_DUMPFILE.
- */
-RETSIGTYPE
-do_admin( int sig )
-{
-    sglob->rq->rq_dump( sglob->rq );
-    (void) SIGNAL_REINSTALL( sig, do_admin );
-}
diff --git a/servers/slurpd/args.c b/servers/slurpd/args.c
deleted file mode 100644 (file)
index c568581..0000000
+++ /dev/null
@@ -1,181 +0,0 @@
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 1998-2007 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>.
- */
-/* Portions Copyright (c) 1996 Regents of the University of Michigan.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that this notice is preserved and that due credit is given
- * to the University of Michigan at Ann Arbor. The name of the University
- * may not be used to endorse or promote products derived from this
- * software without specific prior written permission. This software
- * is provided ``as is'' without express or implied warranty.
- */
-/* ACKNOWLEDGEMENTS:
- * This work was originally developed by the University of Michigan
- * (as part of U-MICH LDAP).
- */
-
-/*
- * args.c - process command-line arguments, and set appropriate globals.
- */
-
-#include "portable.h"
-
-#include <stdio.h>
-
-#include <ac/stdlib.h>
-#include <ac/string.h>
-#include <ac/time.h>
-#include <ac/unistd.h>
-
-#include <ldap.h>
-#include <lutil.h>
-
-#include "slurp.h"
-#include "globals.h"
-
-
-static void
-usage( char *name )
-{
-    fprintf( stderr, "usage: %s\t[-d debug-level] [-s syslog-level]\n", name );
-    fprintf( stderr, "\t\t[-f slapd-config-file] [-r replication-log-file]\n" );
-    fprintf( stderr, "\t\t[-t tmp-dir] [-o]\n" );
-    fprintf( stderr, "\t\t[-n service-name]\n" );
-}
-
-
-
-/*
- * Interpret argv, and fill in any appropriate globals.
- */
-int
-doargs(
-    int                argc,
-    char       **argv,
-    Globals    *g
-)
-{
-    int                i;
-    int                rflag = 0;
-
-    g->myname = strdup( lutil_progname( "slurpd", argc, argv ));
-
-    while ( (i = getopt( argc, argv, "d:f:n:or:t:V" )) != EOF ) {
-       switch ( i ) {
-       case 'd': {     /* set debug level and 'do not detach' flag */
-           int level;
-           g->no_detach = 1;
-           if ( optarg[0] == '?' ) {
-#ifdef LDAP_DEBUG
-               printf( "Debug levels:\n" );
-               printf( "\tLDAP_DEBUG_TRACE\t%d\n",
-                       LDAP_DEBUG_TRACE );
-               printf( "\tLDAP_DEBUG_PACKETS\t%d\n",
-                       LDAP_DEBUG_PACKETS );
-               printf( "\tLDAP_DEBUG_ARGS\t\t%d\n",
-                       LDAP_DEBUG_ARGS );
-               printf( "\tLDAP_DEBUG_CONNS\t%d\n",
-                       LDAP_DEBUG_CONNS );
-               printf( "\tLDAP_DEBUG_BER\t\t%d\n",
-                       LDAP_DEBUG_BER );
-               printf( "\tLDAP_DEBUG_FILTER\t%d\n",
-                       LDAP_DEBUG_FILTER );
-               printf( "\tLDAP_DEBUG_CONFIG\t%d\n",
-                       LDAP_DEBUG_CONFIG );
-               printf( "\tLDAP_DEBUG_ACL\t\t%d\n",
-                       LDAP_DEBUG_ACL );
-               printf( "\tLDAP_DEBUG_ANY\t\t%d\n",
-                       LDAP_DEBUG_ANY );
-               puts( "\tThe -d flag also prevents slurpd from detaching." );
-#endif /* LDAP_DEBUG */
-               puts( "\tDebugging is disabled.  -d 0 prevents slurpd from detaching." );
-               return( -1 );
-           }
-#ifdef LDAP_DEBUG
-           if ( lutil_atoix( &level, optarg, 0 ) != 0 ) {
-               fprintf( stderr, "unable to parse debug flag \"%s\".\n", optarg );
-               usage( g->myname );
-               return( -1 );
-           }
-           ldap_debug |= level;
-#else /* !LDAP_DEBUG */
-           if ( lutil_atoi( &level, optarg ) != 0 || level != 0 )
-               /* can't enable debugging - not built with debug code */
-               fputs( "must compile with LDAP_DEBUG for debugging\n",
-                      stderr );
-#endif /* LDAP_DEBUG */
-           } break;
-       case 'f':       /* slapd config file */
-           LUTIL_SLASHPATH( optarg );
-           g->slapd_configfile = strdup( optarg );
-           break;
-       case 'n':       /* NT service name */
-           if ( g->serverName ) free( g->serverName );
-           g->serverName = strdup( optarg );
-           break;
-       case 'o':
-           g->one_shot_mode = 1;
-           break;
-       case 'r':       /* slapd replog file */
-           LUTIL_SLASHPATH( optarg );
-               snprintf( g->slapd_replogfile, sizeof g->slapd_replogfile,
-                       "%s", optarg );
-           rflag++;
-           break;
-       case 't': {     /* dir to use for our copies of replogs */
-               size_t sz;
-           LUTIL_SLASHPATH( optarg );
-           g->slurpd_rdir = (char *)malloc (sz = (strlen(optarg) + sizeof(LDAP_DIRSEP "replica")));
-           snprintf(g->slurpd_rdir, sz,
-                       "%s" LDAP_DIRSEP "replica", optarg);
-           } break;
-       case 'V':
-           (g->version)++;
-           break;
-       default:
-           usage( g->myname );
-           return( -1 );
-       }
-    }
-
-    if ( g->one_shot_mode && !rflag ) {
-       fprintf( stderr, "If -o flag is given, -r flag must also be given.\n" );
-       usage( g->myname );
-       return( -1 );
-    }
-
-    /* Set location/name of our private copy of the slapd replog file */
-    snprintf( g->slurpd_replogfile, sizeof g->slurpd_replogfile,
-               "%s" LDAP_DIRSEP "%s", g->slurpd_rdir,
-           DEFAULT_SLURPD_REPLOGFILE );
-
-    /* Set location/name of the slurpd status file */
-    snprintf( g->slurpd_status_file, sizeof g->slurpd_status_file,
-               "%s" LDAP_DIRSEP "%s", g->slurpd_rdir,
-           DEFAULT_SLURPD_STATUS_FILE );
-
-       ber_set_option(NULL, LBER_OPT_DEBUG_LEVEL, &ldap_debug);
-       ldap_set_option(NULL, LDAP_OPT_DEBUG_LEVEL, &ldap_debug);
-       ldif_debug = ldap_debug;
-
-#ifdef LOG_LOCAL4
-    openlog( g->myname, OPENLOG_OPTIONS, LOG_LOCAL4 );
-#elif LOG_DEBUG
-    openlog( g->myname, OPENLOG_OPTIONS );
-#endif
-
-    return 0;
-}
diff --git a/servers/slurpd/ch_malloc.c b/servers/slurpd/ch_malloc.c
deleted file mode 100644 (file)
index 7532fbe..0000000
+++ /dev/null
@@ -1,158 +0,0 @@
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 1998-2007 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>.
- */
-/* Portions Copyright (c) 1996 Regents of the University of Michigan.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that this notice is preserved and that due credit is given
- * to the University of Michigan at Ann Arbor. The name of the University
- * may not be used to endorse or promote products derived from this
- * software without specific prior written permission. This software
- * is provided ``as is'' without express or implied warranty.
- */
-/* ACKNOWLEDGEMENTS:
- * This work was originally developed by the University of Michigan
- * (as part of U-MICH LDAP).
- */
-
-#define CH_FREE 1
-
-/*
- * ch_malloc.c - malloc() and friends, with check for NULL return.
- */
-
-#include "portable.h"
-
-#include <stdio.h>
-
-#include <ac/stdlib.h>
-#include <ac/socket.h>
-
-#include "../slapd/slap.h"
-
-
-#ifndef CSRIMALLOC
-
-/*
- * Just like malloc, except we check the returned value and exit
- * if anything goes wrong.
- */
-void *
-ch_malloc(
-    ber_len_t  size
-)
-{
-       void    *new;
-
-       if ( (new = (void *) ber_memalloc( size )) == NULL ) {
-               fprintf( stderr, "malloc of %lu bytes failed\n",
-                       (long) size );
-               exit( EXIT_FAILURE );
-       }
-
-       return( new );
-}
-
-
-
-
-/*
- * Just like realloc, except we check the returned value and exit
- * if anything goes wrong.
- */
-void *
-ch_realloc(
-    void               *block,
-    ber_len_t  size
-)
-{
-       void    *new;
-
-       if ( block == NULL ) {
-               return( ch_malloc( size ) );
-       }
-
-       if ( size == 0 ) {
-               ch_free( block );
-       }
-
-       if ( (new = (void *) ber_memrealloc( block, size )) == NULL ) {
-               fprintf( stderr, "realloc of %lu bytes failed\n",
-                       (long) size );
-               exit( EXIT_FAILURE );
-       }
-
-       return( new );
-}
-
-
-
-
-/*
- * Just like calloc, except we check the returned value and exit
- * if anything goes wrong.
- */
-void *
-ch_calloc(
-    ber_len_t  nelem,
-    ber_len_t  size
-)
-{
-       void    *new;
-
-       if ( (new = (void *) ber_memcalloc( nelem, size )) == NULL ) {
-               fprintf( stderr, "calloc of %lu elems of %lu bytes failed\n",
-                   (long) nelem, (long) size );
-               exit( EXIT_FAILURE );
-       }
-
-       return( new );
-}
-
-/*
- * Just like strdup, except we check the returned value and exit
- * if anything goes wrong.
- */
-char *
-ch_strdup(
-    const char *string
-)
-{
-       char    *new;
-
-       if ( (new = ber_strdup( string )) == NULL ) {
-               fprintf( stderr, "ch_strdup: duplication of \"%s\" failed\n",
-                               string );
-               exit( EXIT_FAILURE );
-       }
-
-       return( new );
-}
-
-/*
- * Just like free, except we check to see if p is null.
- */
-void
-ch_free(
-    void *p
-)
-{
-    if ( p != NULL ) {
-               ber_memfree( p );
-    }
-    return;
-}
-
-#endif
diff --git a/servers/slurpd/config.c b/servers/slurpd/config.c
deleted file mode 100644 (file)
index 949e308..0000000
+++ /dev/null
@@ -1,675 +0,0 @@
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 1998-2007 The OpenLDAP Foundation.
- * Portions Copyright 2003 Mark Benson.
- * Portions Copyright 2002 John Morrissey.
- * 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>.
- */
-/* Portions Copyright (c) 1996 Regents of the University of Michigan.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that this notice is preserved and that due credit is given
- * to the University of Michigan at Ann Arbor. The name of the University
- * may not be used to endorse or promote products derived from this
- * software without specific prior written permission. This software
- * is provided ``as is'' without express or implied warranty.
- */
-/* ACKNOWLEDGEMENTS:
- * This work was originally developed by the University of Michigan
- * (as part of U-MICH LDAP).  Additional signficant contributors
- * include:
- *    John Morrissey
- *    Mark Benson
- */
-
-
-/*
- * config.c - configuration file handling routines
- */
-
-#include "portable.h"
-
-#include <stdio.h>
-
-#include <ac/stdlib.h>
-#include <ac/string.h>
-#include <ac/socket.h>
-#include <ac/ctype.h>
-
-#include <ldap.h>
-#include <lutil.h>
-
-#include "slurp.h"
-#include "globals.h"
-
-#define ARGS_STEP      512
-
-/* Forward declarations */
-static void    add_replica LDAP_P(( char **, int ));
-static int     parse_replica_line LDAP_P(( char **, int, Ri *));
-static void    parse_line LDAP_P(( char * ));
-static char    *slurpd_getline LDAP_P(( FILE * ));
-static char    *strtok_quote LDAP_P(( char *, char * ));
-
-int    cargc = 0, cargv_size = 0;
-char   **cargv;
-/* current config file line # */
-static int     lineno;
-
-char *slurpd_pid_file = NULL;
-char *slurpd_args_file = NULL;
-
-/*
- * Read the slapd config file, looking only for config options we're
- * interested in.  Since we haven't detached from the controlling
- * terminal yet, we just perror() and fprintf here.
- */
-int
-slurpd_read_config(
-    char       *fname
-)
-{
-       FILE    *fp;
-       char    *line;
-
-#define GOT_REPLOG_NO          (0)
-#define GOT_REPLOG_ONE         (1)
-#define GOT_REPLOG_YES         (2)     
-#define GOT_REPLOG_DONE                (3)
-#define        GOT_REPLOG_MASK         (0xF)
-#define        GOT_REPLOG(i)           ((i) & GOT_REPLOG_MASK)
-#define        GOT_REPLOG_SET(i,v)     ((i) = ((i) & ~GOT_REPLOG_MASK) | ((v) & GOT_REPLOG_MASK))
-
-#define GOT_REPLOG_PID         (0x10)
-#define GOT_REPLOG_ARGS                (0x20)
-#define GOT_REPLOG_INTERVAL    (0x40)
-       int     got_replog =    GOT_REPLOG_NO;
-
-       /*
-        * replica-pidfile and replica-argsfile can appear before any replog;
-        * in this case they're global (legacy behavior); otherwise, since
-        * each replog needs a slurpd, they can appear after a replogfile line;
-        * in that case, the replog specific values are used.
-        */
-
-       if ( cargv == NULL ) {
-               cargv = ch_calloc( ARGS_STEP + 1, sizeof(*cargv) );
-               cargv_size = ARGS_STEP + 1;
-       }
-
-       Debug( LDAP_DEBUG_CONFIG, "Config: opening config file \"%s\"\n",
-               fname, 0, 0 );
-
-       if ( (fp = fopen( fname, "r" )) == NULL ) {
-               perror( fname );
-               exit( EXIT_FAILURE );
-       }
-
-       lineno = 0;
-       while ( (line = slurpd_getline( fp )) != NULL ) {
-               /* skip comments and blank lines */
-               if ( line[0] == '#' || line[0] == '\0' ) {
-                       continue;
-               }
-
-               Debug( LDAP_DEBUG_CONFIG, "Config: (%s)\n", line, 0, 0 );
-
-               parse_line( line );
-
-               if ( cargc < 1 ) {
-                       fprintf( stderr, "line %d: bad config line (ignored)\n", lineno );
-                       continue;
-               }
-
-               /* replication log file to which changes are appended */
-               if ( strcasecmp( cargv[0], "replogfile" ) == 0 ) {
-                       /* 
-                        * if slapd_replogfile has a value, the -r option was given,
-                        * so use that value.  If slapd_replogfile has length == 0,
-                        * then we should use the value in the config file we're reading.
-                        */
-                       if ( cargc < 2 ) {
-                               fprintf( stderr,
-                                       "line %d: missing filename in \"replogfile ",
-                                       lineno );
-                               fprintf( stderr, "<filename>\" line\n" );
-                               exit( EXIT_FAILURE );
-
-                       } else if ( cargc > 2 && *cargv[2] != '#' ) {
-                               fprintf( stderr,
-                                       "line %d: extra cruft at the end of \"replogfile %s\"",
-                                       lineno, cargv[1] );
-                               fprintf( stderr, "line (ignored)\n" );
-                       }
-
-                       LUTIL_SLASHPATH( cargv[1] );
-                       if ( sglob->slapd_replogfile[0] == '\0' ) {
-                               strcpy( sglob->slapd_replogfile, cargv[1] );
-                               GOT_REPLOG_SET(got_replog, GOT_REPLOG_YES);
-
-                       } else {
-                               if ( strcmp( sglob->slapd_replogfile, cargv[1] ) == 0 ) {
-                                       GOT_REPLOG_SET(got_replog, GOT_REPLOG_YES);
-
-                               } else if ( GOT_REPLOG(got_replog) == GOT_REPLOG_YES ) {
-                                       GOT_REPLOG_SET(got_replog, GOT_REPLOG_DONE);
-
-                               } else {
-                                       GOT_REPLOG_SET(got_replog, GOT_REPLOG_ONE);
-                               }
-                       }
-
-               } else if ( strcasecmp( cargv[0], "replica" ) == 0 ) {
-                       add_replica( cargv, cargc );
-           
-               /* include another config file */
-               } else if ( strcasecmp( cargv[0], "include" ) == 0 ) {
-                       char *savefname;
-                       int savelineno;
-
-                       if ( cargc < 2 ) {
-                               Debug( LDAP_DEBUG_ANY,
-                                       "%s: line %d: missing filename in \"include <filename>\" line\n",
-                                       fname, lineno, 0 );
-               
-                               fclose( fp );
-                               return( 1 );
-                       }
-                       LUTIL_SLASHPATH( cargv[1] );
-                       savefname = strdup( cargv[1] );
-                       savelineno = lineno;
-           
-                       if ( slurpd_read_config( savefname ) != 0 ) {
-                               fclose( fp );
-                               return( 1 );
-                       }
-               
-                       free( savefname );
-                       lineno = savelineno - 1;
-
-               } else if ( strcasecmp( cargv[0], "replica-pidfile" ) == 0 ) {
-                       if ( cargc < 2 ) {
-                               Debug( LDAP_DEBUG_ANY,
-                                       "%s: line %d: missing file name in \"replica-pidfile <file>\" line\n",
-                                       fname, lineno, 0 );
-
-                               fclose( fp );
-                               return( 1 );
-                       }
-
-                       switch ( GOT_REPLOG(got_replog) ) {
-                       case GOT_REPLOG_YES:
-                               Debug( LDAP_DEBUG_CONFIG, "%s: line %d: "
-                                       "got replog specific replica-pidfile \"%s\".\n",
-                                       fname, lineno, cargv[1] );
-                       case GOT_REPLOG_NO:
-                               LUTIL_SLASHPATH( cargv[1] );
-                               if ( slurpd_pid_file != NULL ) {
-                                       ch_free( slurpd_pid_file );
-                               }
-                               slurpd_pid_file = ch_strdup( cargv[1] );
-                               got_replog |= GOT_REPLOG_PID;
-                               break;
-
-                       default:
-                               Debug( LDAP_DEBUG_CONFIG, "%s: line %d: "
-                                       "replica-pidfile \"%s\" not mine.\n",
-                                       fname, lineno, cargv[1] );
-                               break;
-                       }
-
-               } else if ( strcasecmp( cargv[0], "replica-argsfile" ) == 0 ) {
-                       if ( cargc < 2 ) {
-                               Debug( LDAP_DEBUG_ANY,
-                                       "%s: line %d: missing file name in \"argsfile <file>\" line\n",
-                                       fname, lineno, 0 );
-
-                               fclose( fp );
-                               return( 1 );
-                       }
-
-                       switch ( GOT_REPLOG(got_replog) ) {
-                       case GOT_REPLOG_YES:
-                               Debug( LDAP_DEBUG_CONFIG, "%s: line %d: "
-                                       "got replog specific replica-argsfile \"%s\".\n",
-                                       fname, lineno, cargv[1] );
-                       case GOT_REPLOG_NO:
-                               LUTIL_SLASHPATH( cargv[1] );
-                               if ( slurpd_args_file != NULL ) {
-                                       ch_free( slurpd_args_file );
-                               }
-                               slurpd_args_file = ch_strdup( cargv[1] );
-                               got_replog |= GOT_REPLOG_ARGS;
-                               break;
-
-                       default:
-                               Debug( LDAP_DEBUG_CONFIG, "%s: line %d: "
-                                       "replica-argsfile \"%s\" not mine.\n",
-                                       fname, lineno, cargv[1] );
-                               break;
-                       }
-
-               } else if ( strcasecmp( cargv[0], "replicationinterval" ) == 0 ) {
-                       int c;
-
-                       if ( cargc < 2 ) {
-                               Debug( LDAP_DEBUG_ANY, "%s: line %d: missing interval in "
-                                       "\"replicationinterval <seconds>\" line\n",
-                                       fname, lineno, 0 );
-                               fclose( fp );
-                               return( 1 );
-                       }
-
-                       if ( lutil_atoi( &c, cargv[1] ) != 0 || c < 1 ) {
-                               Debug( LDAP_DEBUG_ANY, "%s: line %d: invalid interval "
-                                       "(%d) in \"replicationinterval <seconds>\" line\n",
-                                       fname, lineno, c );
-
-                               fclose( fp );
-                               return( 1 );
-                       }
-
-                       switch ( GOT_REPLOG(got_replog) ) {
-                       case GOT_REPLOG_YES:
-                               Debug( LDAP_DEBUG_CONFIG, "%s: line %d: "
-                                       "got replog specific replicationinterval \"%s\".\n",
-                                       fname, lineno, cargv[1] );
-                       case GOT_REPLOG_NO:
-                               sglob->no_work_interval = c;
-                               got_replog |= GOT_REPLOG_INTERVAL;
-                               break;
-
-                       default:
-                               Debug( LDAP_DEBUG_CONFIG, "%s: line %d: "
-                                       "replicationinterval \"%s\" not mine.\n",
-                                       fname, lineno, cargv[1] );
-                               break;
-                       }
-               }
-       }
-
-       fclose( fp );
-       Debug( LDAP_DEBUG_CONFIG,
-               "Config: ** configuration file successfully read and parsed\n",
-               0, 0, 0 );
-       return 0;
-}
-
-
-
-
-/*
- * Parse one line of input.
- */
-static void
-parse_line(
-    char       *line
-)
-{
-    char *     token;
-
-    cargc = 0;
-    for ( token = strtok_quote( line, " \t" ); token != NULL;
-       token = strtok_quote( NULL, " \t" ) )
-    {
-        if ( cargc == cargv_size - 1 ) {
-           char **tmp;
-            tmp = ch_realloc( cargv, (cargv_size + ARGS_STEP) *
-                               sizeof(*cargv) );
-           if (tmp == NULL) {
-               cargc = 0;
-               return;
-           }
-           cargv = tmp;
-            cargv_size += ARGS_STEP;
-        }
-
-       cargv[cargc++] = token;
-    }
-    cargv[cargc] = NULL;
-}
-
-
-
-
-static char *
-strtok_quote(
-    char *line,
-    char *sep
-)
-{
-    int                inquote;
-    char       *tmp;
-    static char        *next;
-
-    if ( line != NULL ) {
-       next = line;
-    }
-    while ( *next && strchr( sep, *next ) ) {
-       next++;
-    }
-
-    if ( *next == '\0' ) {
-       next = NULL;
-       return( NULL );
-    }
-    tmp = next;
-
-    for ( inquote = 0; *next; ) {
-       switch ( *next ) {
-       case '"':
-           if ( inquote ) {
-               inquote = 0;
-           } else {
-               inquote = 1;
-           }
-           AC_MEMCPY( next, next + 1, strlen( next + 1 ) + 1 );
-           break;
-
-       case '\\':
-           if ( next[1] )
-               AC_MEMCPY( next, next + 1, strlen( next + 1 ) + 1 );
-           next++;             /* dont parse the escaped character */
-           break;
-
-       default:
-           if ( ! inquote ) {
-               if ( strchr( sep, *next ) != NULL ) {
-                   *next++ = '\0';
-                   return( tmp );
-               }
-           }
-           next++;
-           break;
-       }
-    }
-
-    return( tmp );
-}
-
-#define CATLINE( buf ) { \
-    int        len; \
-    len = strlen( buf ); \
-    while ( lcur + len + 1 > lmax ) { \
-       lmax += BUFSIZ; \
-       line = (char *) ch_realloc( line, lmax ); \
-    } \
-    strcpy( line + lcur, buf ); \
-    lcur += len; \
-}
-
-
-
-/*
- * Get a line of input.
- */
-static char *
-slurpd_getline(
-    FILE *fp
-)
-{
-    char       *p;
-    static char        buf[BUFSIZ];
-    static char        *line;
-    static int lmax, lcur;
-
-    lcur = 0;
-    CATLINE( buf );
-    while ( fgets( buf, sizeof(buf), fp ) != NULL ) {
-       if ( (p = strchr( buf, '\n' )) != NULL ) {
-               if( p > buf && p[-1] == '\r' ) --p;       
-               *p = '\0';
-       }
-       lineno++;
-       if ( ! isspace( (unsigned char) buf[0] ) ) {
-           return( line );
-       }
-
-       /* change leading whitespace to space */
-       buf[0] = ' ';
-
-       CATLINE( buf );
-    }
-    buf[0] = '\0';
-
-    return( line[0] ? line : NULL );
-}
-
-
-/*
- * Add a node to the array of replicas.
- */
-static void
-add_replica(
-    char       **cargv,
-    int                cargc
-)
-{
-    int        nr;
-
-    nr = ++sglob->num_replicas;
-    sglob->replicas = (Ri **) ch_realloc( sglob->replicas,
-           ( nr + 1 )  * sizeof( Re * ));
-    if ( sglob->replicas == NULL ) {
-       fprintf( stderr, "out of memory, add_replica\n" );
-       exit( EXIT_FAILURE );
-    }
-    sglob->replicas[ nr ] = NULL; 
-
-    if ( Ri_init( &(sglob->replicas[ nr - 1 ])) < 0 ) {
-       fprintf( stderr, "out of memory, Ri_init\n" );
-       exit( EXIT_FAILURE );
-    }
-    if ( parse_replica_line( cargv, cargc,
-           sglob->replicas[ nr - 1] ) < 0 ) {
-       /* Something bad happened - back out */
-       fprintf( stderr,
-           "Warning: failed to add replica \"%s:%d - ignoring replica\n",
-           sglob->replicas[ nr - 1 ]->ri_hostname == NULL ?
-           "(null)" : sglob->replicas[ nr - 1 ]->ri_hostname,
-           sglob->replicas[ nr - 1 ]->ri_port );
-       sglob->replicas[ nr - 1] = NULL;
-       sglob->num_replicas--;
-    } else {
-       Debug( LDAP_DEBUG_CONFIG,
-               "Config: ** successfully added replica \"%s:%d\"\n",
-               sglob->replicas[ nr - 1 ]->ri_hostname == NULL ?
-               "(null)" : sglob->replicas[ nr - 1 ]->ri_hostname,
-               sglob->replicas[ nr - 1 ]->ri_port, 0 );
-       sglob->replicas[ nr - 1]->ri_stel =
-               sglob->st->st_add( sglob->st,
-               sglob->replicas[ nr - 1 ] );
-       if ( sglob->replicas[ nr - 1]->ri_stel == NULL ) {
-           fprintf( stderr, "Failed to add status element structure\n" );
-           exit( EXIT_FAILURE );
-       }
-    }
-}
-
-
-
-/* 
- * Parse a "replica" line from the config file.  replica lines should be
- * in the following format:
- * replica    host=<hostname:portnumber> binddn=<binddn>
- *            bindmethod="simple" credentials=<creds>
- *
- * where:
- * <hostname:portnumber> describes the host name and port number where the
- * replica is running,
- *
- * <binddn> is the DN to bind to the replica slapd as,
- *
- * bindmethod is "simple", and
- *
- * <creds> are the credentials (e.g. password) for binddn.  <creds> are
- * only used for bindmethod=simple.  
- *
- * The "replica" config file line may be split across multiple lines.  If
- * a line begins with whitespace, it is considered a continuation of the
- * previous line.
- */
-#define        GOT_HOST        1
-#define        GOT_DN          2
-#define        GOT_METHOD      4
-#define        GOT_ALL         ( GOT_HOST | GOT_DN | GOT_METHOD )
-#define        GOT_MECH        8
-
-static int
-parse_replica_line( 
-    char       **cargv,
-    int                cargc,
-    Ri         *ri
-)
-{
-    int                gots = 0;
-    int                i;
-    char       *hp, *val;
-    LDAPURLDesc *ludp;
-
-    for ( i = 1; i < cargc; i++ ) {
-       if ( !strncasecmp( cargv[ i ], HOSTSTR, sizeof( HOSTSTR ) - 1 ) ) {
-               if ( gots & GOT_HOST ) {
-                       fprintf( stderr, "Error: Malformed \"replica\" line in slapd config " );
-                       fprintf( stderr, "file, too many host or uri names specified, line %d\n",
-                               lineno );
-                       return -1;
-               }       
-           val = cargv[ i ] + sizeof( HOSTSTR ); /* '\0' string terminator accounts for '=' */
-           if (( hp = strchr( val, ':' )) != NULL ) {
-               *hp = '\0';
-               hp++;
-               if ( lutil_atoi( &ri->ri_port, hp ) != 0 ) {
-                   fprintf( stderr, "unable to parse port \"%s\", line %d\n",
-                           hp, lineno );
-                   return -1;
-               }
-           }
-           if ( ri->ri_port <= 0 ) {
-               ri->ri_port = LDAP_PORT;
-           }
-           ri->ri_hostname = strdup( val );
-           gots |= GOT_HOST;
-       } else if ( !strncasecmp( cargv[ i ], URISTR, sizeof( URISTR ) - 1 ) ) {
-               if ( gots & GOT_HOST ) {
-                       fprintf( stderr, "Error: Malformed \"replica\" line in slapd config " );
-                       fprintf( stderr, "file, too many host or uri names specified, line %d\n",
-                               lineno );
-                       return -1;
-               }               
-               if ( ldap_url_parse( cargv[ i ] + sizeof( URISTR ), &ludp ) != LDAP_SUCCESS ) {
-                       fprintf( stderr, "Error: Malformed \"replica\" line in slapd config " );
-                       fprintf( stderr, "file, bad uri format specified, line %d\n",
-                               lineno );
-                       return -1;
-               }
-               if (ludp->lud_host == NULL) {
-                       fprintf( stderr, "Error: Malformed \"replica\" line in slapd config " );
-                       fprintf( stderr, "file, missing uri hostname, line %d\n",
-                               lineno );
-                       ldap_free_urldesc( ludp );                              
-                       return -1;
-               }
-               ri->ri_hostname = strdup ( ludp->lud_host );
-               ri->ri_port = ludp->lud_port;
-               ri->ri_uri = strdup ( cargv[ i ] + sizeof( URISTR ) );          
-               ldap_free_urldesc( ludp );                              
-           gots |= GOT_HOST;
-       } else if ( !strncasecmp( cargv[ i ], 
-                       ATTRSTR, sizeof( ATTRSTR ) - 1 ) ) {
-           /* ignore it */ ;
-       } else if ( !strncasecmp( cargv[ i ], 
-                       SUFFIXSTR, sizeof( SUFFIXSTR ) - 1 ) ) {
-           /* ignore it */ ;
-       } else if ( !strncasecmp( cargv[i], STARTTLSSTR, sizeof(STARTTLSSTR)-1 )) {
-           val = cargv[ i ] + sizeof( STARTTLSSTR );
-               if( !strcasecmp( val, CRITICALSTR ) ) {
-                       ri->ri_tls = TLS_CRITICAL;
-               } else {
-                       ri->ri_tls = TLS_ON;
-               }
-       } else if ( !strncasecmp( cargv[ i ], TLSSTR, sizeof( TLSSTR ) - 1 ) ) {
-           val = cargv[ i ] + sizeof( TLSSTR );
-               if( !strcasecmp( val, CRITICALSTR ) ) {
-                       ri->ri_tls = TLS_CRITICAL;
-               } else {
-                       ri->ri_tls = TLS_ON;
-               }
-       } else if ( !strncasecmp( cargv[ i ],
-                       BINDDNSTR, sizeof( BINDDNSTR ) - 1 ) ) { 
-           val = cargv[ i ] + sizeof( BINDDNSTR );
-           ri->ri_bind_dn = strdup( val );
-           gots |= GOT_DN;
-       } else if ( !strncasecmp( cargv[ i ], BINDMETHSTR,
-               sizeof( BINDMETHSTR ) - 1 ) ) {
-           val = cargv[ i ] + sizeof( BINDMETHSTR );
-           if ( !strcasecmp( val, SIMPLESTR )) {
-               ri->ri_bind_method = LDAP_AUTH_SIMPLE;
-               gots |= GOT_METHOD;
-           } else if ( !strcasecmp( val, SASLSTR )) {
-               ri->ri_bind_method = LDAP_AUTH_SASL;
-               gots |= GOT_METHOD;
-           } else {
-               ri->ri_bind_method = -1;
-           }
-       } else if ( !strncasecmp( cargv[ i ], 
-                       SASLMECHSTR, sizeof( SASLMECHSTR ) - 1 ) ) {
-           val = cargv[ i ] + sizeof( SASLMECHSTR );
-           gots |= GOT_MECH;
-           ri->ri_saslmech = strdup( val );
-       } else if ( !strncasecmp( cargv[ i ], 
-                       CREDSTR, sizeof( CREDSTR ) - 1 ) ) {
-           val = cargv[ i ] + sizeof( CREDSTR );
-           ri->ri_password = strdup( val );
-       } else if ( !strncasecmp( cargv[ i ], 
-                       SECPROPSSTR, sizeof( SECPROPSSTR ) - 1 ) ) {
-           val = cargv[ i ] + sizeof( SECPROPSSTR );
-           ri->ri_secprops = strdup( val );
-       } else if ( !strncasecmp( cargv[ i ], 
-                       REALMSTR, sizeof( REALMSTR ) - 1 ) ) {
-           val = cargv[ i ] + sizeof( REALMSTR );
-           ri->ri_realm = strdup( val );
-       } else if ( !strncasecmp( cargv[ i ], 
-                       AUTHCSTR, sizeof( AUTHCSTR ) - 1 ) ) {
-           val = cargv[ i ] + sizeof( AUTHCSTR );
-           ri->ri_authcId = strdup( val );
-       } else if ( !strncasecmp( cargv[ i ], 
-                       OLDAUTHCSTR, sizeof( OLDAUTHCSTR ) - 1 ) ) {
-           /* Old authcID is provided for some backwards compatibility */
-           val = cargv[ i ] + sizeof( OLDAUTHCSTR );
-           ri->ri_authcId = strdup( val );
-       } else if ( !strncasecmp( cargv[ i ], 
-                       AUTHZSTR, sizeof( AUTHZSTR ) - 1 ) ) {
-           val = cargv[ i ] + sizeof( AUTHZSTR );
-           ri->ri_authzId = strdup( val );
-       } else {
-           fprintf( stderr, 
-                   "Error: parse_replica_line: unknown keyword \"%s\"\n",
-                   cargv[ i ] );
-       }
-    }
-    
-       if ( ri->ri_bind_method == LDAP_AUTH_SASL) {
-               if ((gots & GOT_MECH) == 0) {
-                       fprintf( stderr, "Error: \"replica\" line needs SASLmech flag in " );
-                       fprintf( stderr, "slapd config file, line %d\n", lineno );
-                       return -1;
-               }
-       } else if ( gots != GOT_ALL ) {
-               fprintf( stderr, "Error: Malformed \"replica\" line in slapd " );
-               fprintf( stderr, "config file, line %d\n", lineno );
-               return -1;
-       }
-    return 0;
-}
-
diff --git a/servers/slurpd/fm.c b/servers/slurpd/fm.c
deleted file mode 100644 (file)
index 23d08bf..0000000
+++ /dev/null
@@ -1,274 +0,0 @@
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 1998-2007 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>.
- */
-/* Portions Copyright (c) 1996 Regents of the University of Michigan.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that this notice is preserved and that due credit is given
- * to the University of Michigan at Ann Arbor. The name of the University
- * may not be used to endorse or promote products derived from this
- * software without specific prior written permission. This software
- * is provided ``as is'' without express or implied warranty.
- */
-/* ACKNOWLEDGEMENTS:
- * This work was originally developed by the University of Michigan
- * (as part of U-MICH LDAP).
- */
-
-/*
- * fm.c - file management routines.
- */
-
-#include "portable.h"
-
-#include <stdio.h>
-
-#include <ac/stdlib.h>
-#include <ac/string.h>
-#include <ac/signal.h>
-#include <ac/socket.h>
-#include <ac/unistd.h>
-
-#include "slurp.h"
-#include "globals.h"
-#include "lutil.h"
-
-
-/*
- * Forward references
- */
-static char *get_record LDAP_P(( FILE * ));
-static void populate_queue LDAP_P(( char *f ));
-
-
-/*
- * Main file manager routine.  Watches for new data to be appended to the
- * slapd replication log.  When new data is appended, fm does the following:
- *  - appends the data to slurpd's private copy of the replication log.
- *  - truncates the slapd replog
- *  - adds items to the internal queue of replication work to do
- *  - signals the replication threads to let them know new work has arrived.
- */
-void *
-fm(
-    void *arg
-)
-{
-    int rc;
-    int i;
-    fd_set readfds;
-
-    /* Set up our signal handlers:
-     * SIG{TERM,INT,HUP} causes a shutdown
-     */
-    (void) SIGNAL( SIGTERM, slurp_set_shutdown );
-    (void) SIGNAL( SIGINT, slurp_set_shutdown );
-#ifdef SIGHUP
-    (void) SIGNAL( SIGHUP, slurp_set_shutdown );
-#endif
-#if defined(SIGBREAK)
-    (void) SIGNAL( SIGBREAK, slurp_set_shutdown );
-#endif
-
-    if ( sglob->one_shot_mode ) {
-       if ( file_nonempty( sglob->slapd_replogfile )) {
-           populate_queue( sglob->slapd_replogfile );
-       }
-       printf( "Processing in one-shot mode:\n" );
-       printf( "%d total replication records in file,\n",
-               sglob->rq->rq_getcount( sglob->rq, RQ_COUNT_ALL ));
-       printf( "%d replication records to process.\n",
-               sglob->rq->rq_getcount( sglob->rq, RQ_COUNT_NZRC ));
-       return NULL;
-    }
-    /*
-     * There may be some leftover replication records in our own
-     * copy of the replication log.  If any exist, add them to the
-     * queue.
-     */
-    if ( file_nonempty( sglob->slurpd_replogfile )) {
-       populate_queue( sglob->slurpd_replogfile );
-    }
-
-    FD_ZERO( &readfds );
-
-    while ( !sglob->slurpd_shutdown ) {
-       if ( file_nonempty( sglob->slapd_replogfile )) {
-           /* New work found - copy to slurpd replog file */
-           Debug( LDAP_DEBUG_ARGS, "new work in %s\n",
-                   sglob->slapd_replogfile, 0, 0 );
-           if (( rc = copy_replog( sglob->slapd_replogfile,
-                   sglob->slurpd_replogfile )) == 0 )  {
-               populate_queue( sglob->slurpd_replogfile );
-           } else {
-               if ( rc < 0 ) {
-                   Debug( LDAP_DEBUG_ANY,
-                           "Fatal error while copying replication log\n",
-                           0, 0, 0 );
-                   sglob->slurpd_shutdown = 1;
-               }
-           }
-       } else {
-           struct timeval tv;
-
-           FD_SET( sglob->wake_sds[0], &readfds );
-           tv.tv_sec = sglob->no_work_interval;
-           tv.tv_usec = 0;
-
-           rc = select( sglob->wake_sds[0]+1, &readfds, NULL, NULL, &tv );
-       }
-
-       /* Garbage-collect queue */
-       sglob->rq->rq_gc( sglob->rq );
-
-       /* Trim replication log file, if needed */
-       if ( sglob->rq->rq_needtrim( sglob->rq )) {
-           FILE *fp, *lfp;
-           if (( rc = acquire_lock( sglob->slurpd_replogfile, &fp,
-                   &lfp )) < 0 ) {
-               Debug( LDAP_DEBUG_ANY,
-                       "Error: cannot acquire lock on \"%s\" for trimming\n",
-                       sglob->slurpd_replogfile, 0, 0 );
-           } else {
-               sglob->rq->rq_write( sglob->rq, fp );
-               (void) relinquish_lock( sglob->slurpd_replogfile, fp, lfp );
-           }
-       }
-    }
-    sglob->rq->rq_lock( sglob->rq );                   /* lock queue */
-    ldap_pvt_thread_cond_broadcast( &(sglob->rq->rq_more) );   /* wake repl threads */
-    for ( i = 0; i < sglob->num_replicas; i++ ) {
-       (sglob->replicas[ i ])->ri_wake( sglob->replicas[ i ]);
-    }
-    sglob->rq->rq_unlock( sglob->rq );                 /* unlock queue */
-    Debug( LDAP_DEBUG_ARGS, "fm: exiting\n", 0, 0, 0 );
-    return NULL;
-}
-
-
-
-
-/*
- * Set a global flag which signals that we're shutting down.
- */
-RETSIGTYPE
-slurp_set_shutdown(int sig)
-{
-#if HAVE_NT_SERVICE_MANAGER && SIGBREAK
-    if (is_NT_Service && sig == SIGBREAK) {
-       /* empty */;
-    } else
-#endif
-    {
-    sglob->slurpd_shutdown = 1;                                /* set flag */
-    tcp_write( sglob->wake_sds[1], "0", 1);            /* wake up file mgr */
-    }
-
-    (void) SIGNAL_REINSTALL( sig, slurp_set_shutdown );        /* reinstall handlers */
-}
-
-
-
-
-/*
- * A do-nothing signal handler.
- */
-RETSIGTYPE
-do_nothing(int sig)
-{
-    (void) SIGNAL_REINSTALL( sig, do_nothing );
-}
-
-
-
-
-/*
- * Open the slurpd replication log, seek to our last known position, and
- * process any pending replication entries.
- */
-static void
-populate_queue(
-    char *f
-)
-{
-    FILE       *fp, *lfp;
-    char       *p;
-
-    if ( acquire_lock( f, &fp, &lfp ) < 0 ) {
-       Debug( LDAP_DEBUG_ANY,
-               "error: can't lock file \"%s\": %s\n",
-               f, sys_errlist[ errno ], 0 );
-       return;
-    }
-
-    /*
-     * Read replication records from fp and append them the
-     * the queue.
-     */
-    if ( fseek( fp, sglob->srpos, 0 ) < 0 ) {
-       Debug( LDAP_DEBUG_ANY,
-               "error: can't seek to offset %ld in file \"%s\"\n",
-               sglob->srpos, f, 0 );
-    } else {
-    while (( p = get_record( fp )) != NULL ) {
-       if ( sglob->rq->rq_add( sglob->rq, p ) < 0 ) {
-           char *t;
-           /* Print an error message.  Only print first line.  */
-           if (( t = strchr( p, '\n' )) != NULL ) {
-               *t = '\0';
-           }
-           Debug( LDAP_DEBUG_ANY,
-                   "error: malformed replog entry (begins with \"%s\")\n",
-                   p, 0, 0 );
-       }
-       free( p );
-       ldap_pvt_thread_yield();
-    }
-    sglob->srpos = ftell( fp );
-    }
-    (void) relinquish_lock( f, fp, lfp );
-}
-    
-
-
-
-/*
- * Get the next "record" from the file pointed to by fp.  A "record"
- * is delimited by two consecutive newlines.  Returns NULL on EOF.
- */
-static char *
-get_record(
-    FILE *fp
-)
-{
-    int                len;
-    static char        line[BUFSIZ];
-    char       *buf = NULL;
-    static int lcur, lmax;
-
-    lcur = lmax = 0;
-
-    while (( fgets( line, sizeof(line), fp ) != NULL ) &&
-           (( len = strlen( line )) > 1 )) {
-
-               while ( lcur + len + 1 > lmax ) {
-                   lmax += BUFSIZ;
-                   buf = (char *) ch_realloc( buf, lmax );
-               }
-               strcpy( buf + lcur, line );
-               lcur += len;
-    }
-    return( buf );
-}
diff --git a/servers/slurpd/globals.c b/servers/slurpd/globals.c
deleted file mode 100644 (file)
index 80e2238..0000000
+++ /dev/null
@@ -1,100 +0,0 @@
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 1998-2007 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>.
- */
-/* Portions Copyright (c) 1996 Regents of the University of Michigan.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that this notice is preserved and that due credit is given
- * to the University of Michigan at Ann Arbor. The name of the University
- * may not be used to endorse or promote products derived from this
- * software without specific prior written permission. This software
- * is provided ``as is'' without express or implied warranty.
- */
-/* ACKNOWLEDGEMENTS:
- * This work was originally developed by the University of Michigan
- * (as part of U-MICH LDAP).
- */
-
-/*
- * globals.c - initialization code for global data
- */
-
-#include "portable.h"
-
-#include <stdio.h>
-
-#include <ac/stdlib.h>
-#include <ac/string.h>
-
-#include "slurp.h"
-#include "globals.h"
-
-Globals                 *sglob;
-static Globals glob;
-
-int ldap_syslog = 0;
-#ifdef LOG_DEBUG
-int ldap_syslog_level = LOG_DEBUG;
-#else
-int ldap_syslog_level = 0;
-#endif
-int ldap_debug = 0;
-
-/*
- * Initialize the globals
- */
-Globals *
-init_globals( void )
-{
-    Globals *g;
-
-    g = &glob;
-
-       g->wake_sds[0] = -1;
-       g->wake_sds[1] = -1;
-
-#ifdef HAVE_NT_SERVICE_MANAGER
-    g->slapd_configfile = ".\\slapd.conf";
-    g->slurpd_rdir = ".\\replica";
-#else
-    g->slapd_configfile = SLAPD_DEFAULT_CONFIGFILE;
-    g->slurpd_rdir = DEFAULT_SLURPD_REPLICA_DIR "/replica";
-#endif
-
-    g->no_work_interval = DEFAULT_NO_WORK_INTERVAL;
-    g->slurpd_shutdown = 0;
-    g->num_replicas = 0;
-    g->replicas = NULL;
-    g->slapd_replogfile[ 0 ] = '\0';
-    g->slurpd_replogfile[ 0 ] = '\0';
-    g->slurpd_status_file[ 0 ] = '\0';
-    g->one_shot_mode = 0;
-    g->no_detach = 0;
-    g->myname = NULL;
-    g->serverName = NULL;
-    g->srpos = 0L;
-    g->version = 0;
-    if ( St_init( &(g->st)) < 0 ) {
-       fprintf( stderr, "Cannot initialize status data\n" );
-       exit( EXIT_FAILURE );
-    }
-    ldap_pvt_thread_mutex_init( &(g->rej_mutex) );
-    if ( Rq_init( &(g->rq)) < 0 ) {
-       fprintf( stderr, "Cannot initialize queue\n" );
-       exit( EXIT_FAILURE );
-    }
-
-    return g;
-}
diff --git a/servers/slurpd/globals.h b/servers/slurpd/globals.h
deleted file mode 100644 (file)
index 28a960b..0000000
+++ /dev/null
@@ -1,89 +0,0 @@
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 1998-2007 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>.
- */
-/* Portions Copyright (c) 1996 Regents of the University of Michigan.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that this notice is preserved and that due credit is given
- * to the University of Michigan at Ann Arbor. The name of the University
- * may not be used to endorse or promote products derived from this
- * software without specific prior written permission. This software
- * is provided ``as is'' without express or implied warranty.
- */
-/* ACKNOWLEDGEMENTS:
- * This work was originally developed by the University of Michigan
- * (as part of U-MICH LDAP).
- */
-
-#ifndef SLURPD_GLOBALS_H
-#define SLURPD_GLOBALS_H 1
-
-/*
- * globals.h - definition of structure holding global data.
- */
-
-#include "slurp.h"
-
-LDAP_BEGIN_DECL
-
-typedef struct globals {
-    /* Thread ID for file manager thread */
-    ldap_pvt_thread_t fm_tid;
-    /* pipe/socket used to wake manager from signal handler */
-    int wake_sds[2];
-    /* The name of the slapd config file (which is also our config file) */
-    char *slapd_configfile;
-    /* How long the master slurpd sleeps when there's no work to do */
-    int        no_work_interval;
-    /* We keep running until slurpd_shutdown is nonzero.  HUP signal set this */
-    sig_atomic_t slurpd_shutdown;
-    /* Number of replicas we're servicing */
-    int num_replicas;
-    /* Array of pointers to replica info */
-    Ri **replicas;
-    /* Directory where our replica files are written/read */
-    char *slurpd_rdir;
-    /* Name of slurpd status file (timestamp of last replog */
-    char slurpd_status_file[ MAXPATHLEN ];
-    /* Name of the replication log slapd is writing (and we are reading) */
-    char slapd_replogfile[ MAXPATHLEN ];
-    /* Name of local copy of replogfile we maintain */
-    char slurpd_replogfile[ MAXPATHLEN ];
-    /* Non-zero if we were given a replog file to process on command-line */
-    int        one_shot_mode;
-    /* Non-zero if we should not detach the process */
-    int no_detach;
-    /* Name of program */
-    char *myname;
-    /* NT service name */
-    char *serverName;
-    /* Current offset into slurpd replica logfile */
-    off_t srpos;
-    /* mutex to serialize access to reject file */
-    ldap_pvt_thread_mutex_t rej_mutex;
-    /* pointer to status struct */
-    St *st;
-    /* Pointer to replication queue */
-    Rq *rq;
-    /* Non-zero if we shall print the version */
-    int version;
-} Globals;
-
-
-extern Globals *sglob;
-
-LDAP_END_DECL
-
-#endif /* SLURPD_GLOBALS_H */
diff --git a/servers/slurpd/ldap_op.c b/servers/slurpd/ldap_op.c
deleted file mode 100644 (file)
index dc06b2d..0000000
+++ /dev/null
@@ -1,918 +0,0 @@
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 1998-2007 The OpenLDAP Foundation.
- * Portions Copyright 2003 Mark Benson.
- * 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>.
- */
-/* Portions Copyright (c) 1996 Regents of the University of Michigan.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that this notice is preserved and that due credit is given
- * to the University of Michigan at Ann Arbor. The name of the University
- * may not be used to endorse or promote products derived from this
- * software without specific prior written permission. This software
- * is provided ``as is'' without express or implied warranty.
- */
-/* ACKNOWLEDGEMENTS:
- * This work was originally developed by the University of Michigan
- * (as part of U-MICH LDAP).  Additional significant contributors
- * include:
- *     Mark Benson
- */
-
-/*
- * ldap_op.c - routines to perform LDAP operations
- */
-
-#include "portable.h"
-
-#include <stdio.h>
-
-#include <ac/stdlib.h>
-
-#include <ac/errno.h>
-#include <ac/string.h>
-#include <ac/ctype.h>
-#include <ac/time.h>
-#include <ac/unistd.h>
-
-#define LDAP_DEPRECATED 1
-#include <ldap.h>
-#include "lutil_ldap.h"
-#include "slurp.h"
-
-/* Forward references */
-static struct berval **make_singlevalued_berval LDAP_P(( char  *, int ));
-static int op_ldap_add LDAP_P(( Ri *, Re *, char **, int * ));
-static int op_ldap_modify LDAP_P(( Ri *, Re *, char **, int * ));
-static int op_ldap_delete LDAP_P(( Ri *, Re *, char **, int * ));
-static int op_ldap_modrdn LDAP_P(( Ri *, Re *, char **, int * ));
-static LDAPMod *alloc_ldapmod LDAP_P(( void ));
-static void free_ldapmod LDAP_P(( LDAPMod * ));
-static void free_ldmarr LDAP_P(( LDAPMod ** ));
-static int getmodtype LDAP_P(( char * ));
-#ifdef SLAPD_UNUSED
-static void dump_ldm_array LDAP_P(( LDAPMod ** ));
-#endif
-static int do_bind LDAP_P(( Ri *, int * ));
-static int do_unbind LDAP_P(( Ri * ));
-
-
-/*
- * Determine the type of ldap operation being performed and call the
- * appropriate routine.
- * - If successful, returns DO_LDAP_OK
- * - If a retryable error occurs, ERR_DO_LDAP_RETRYABLE is returned.
- *   The caller should wait a while and retry the operation.
- * - If a fatal error occurs, ERR_DO_LDAP_FATAL is returned.  The caller
- *   should reject the operation and continue with the next replication
- *   entry.
- */
-int
-do_ldap(
-       Ri              *ri,
-       Re              *re,
-       char    **errmsg,
-       int     *errfree
-)
-{
-       int     retry = 2;
-       *errmsg = NULL;
-       *errfree = 0;
-
-       do {
-               int lderr;
-               if ( ri->ri_ldp == NULL ) {
-                       lderr = do_bind( ri, &lderr );
-
-                       if ( lderr != BIND_OK ) {
-                               return DO_LDAP_ERR_RETRYABLE;
-                       }
-               }
-
-               switch ( re->re_changetype ) {
-               case T_ADDCT:
-                       lderr = op_ldap_add( ri, re, errmsg, errfree );
-                       if ( lderr != LDAP_SUCCESS ) {
-                               Debug( LDAP_DEBUG_ANY,
-                                       "Error: ldap_add_s failed adding DN \"%s\": %s\n",
-                                       re->re_dn, *errmsg && (*errmsg)[0] ?
-                                       *errmsg : ldap_err2string( lderr ), 0 );
-                       }
-                       break;
-
-               case T_MODIFYCT:
-                       lderr = op_ldap_modify( ri, re, errmsg, errfree );
-                       if ( lderr != LDAP_SUCCESS ) {
-                               Debug( LDAP_DEBUG_ANY,
-                                       "Error: ldap_modify_s failed modifying DN \"%s\": %s\n",
-                                       re->re_dn, *errmsg && (*errmsg)[0] ?
-                                       *errmsg : ldap_err2string( lderr ), 0 );
-                       }
-                       break;
-
-               case T_DELETECT:
-                       lderr = op_ldap_delete( ri, re, errmsg, errfree );
-                       if ( lderr != LDAP_SUCCESS ) {
-                               Debug( LDAP_DEBUG_ANY,
-                                       "Error: ldap_delete_s failed deleting DN \"%s\": %s\n",
-                                       re->re_dn, *errmsg && (*errmsg)[0] ?
-                                       *errmsg : ldap_err2string( lderr ), 0 );
-                       }
-                       break;
-
-               case T_MODRDNCT:
-                       lderr = op_ldap_modrdn( ri, re, errmsg, errfree );
-                       if ( lderr != LDAP_SUCCESS ) {
-                               Debug( LDAP_DEBUG_ANY,
-                                       "Error: ldap_modrdn_s failed modifying DN \"%s\": %s\n",
-                                       re->re_dn, *errmsg && (*errmsg)[0] ?
-                                       *errmsg : ldap_err2string( lderr ), 0 );
-                       }
-                       break;
-
-               default:
-                       Debug( LDAP_DEBUG_ANY,
-                               "Error: do_ldap: bad op \"%d\", DN \"%s\"\n",
-                               re->re_changetype, re->re_dn, 0 );
-                       return DO_LDAP_ERR_FATAL;
-               }
-
-               /*
-                * Analyze return code. If ok, just return. If LDAP_SERVER_DOWN,
-                * we may have been idle long enough that the remote slapd timed
-                * us out. Rebind and try again.
-                */
-               switch( lderr ) {
-               case LDAP_SUCCESS:
-                       return DO_LDAP_OK;
-       
-               default:
-                       return DO_LDAP_ERR_FATAL;
-
-               case LDAP_SERVER_DOWN: /* server went down */
-                       (void) do_unbind( ri );
-                       retry--;
-               }
-       } while ( retry > 0 );
-
-       return DO_LDAP_ERR_RETRYABLE;
-}
-
-
-
-/*
- * Perform an ldap add operation.
- */
-static int
-op_ldap_add(
-    Ri         *ri,
-    Re         *re,
-    char       **errmsg,
-    int                *errfree
-)
-{
-    Mi         *mi;
-    int                nattrs, rc = 0, i;
-    LDAPMod    *ldm, **ldmarr;
-    int                lderr = 0;
-
-    nattrs = i = 0;
-    ldmarr = NULL;
-
-    /*
-     * Construct a null-terminated array of LDAPMod structs.
-     */
-    mi = re->re_mods;
-    while ( mi[ i ].mi_type != NULL ) {
-       ldm = alloc_ldapmod();
-       ldmarr = ( LDAPMod ** ) ch_realloc( ldmarr,
-               ( nattrs + 2 ) * sizeof( LDAPMod * ));
-       ldmarr[ nattrs ] = ldm;
-       ldm->mod_op = LDAP_MOD_BVALUES;
-       ldm->mod_type = mi[ i ].mi_type;
-       ldm->mod_bvalues =
-               make_singlevalued_berval( mi[ i ].mi_val, mi[ i ].mi_len );
-       i++;
-       nattrs++;
-    }
-
-    if ( ldmarr != NULL ) {
-       ldmarr[ nattrs ] = NULL;
-
-       /* Perform the operation */
-       Debug( LDAP_DEBUG_ARGS, "replica %s:%d - add dn \"%s\"\n",
-               ri->ri_hostname, ri->ri_port, re->re_dn );
-       rc = ldap_add_s( ri->ri_ldp, re->re_dn, ldmarr );
-
-       ldap_get_option( ri->ri_ldp, LDAP_OPT_RESULT_CODE, &lderr);
-       ldap_get_option( ri->ri_ldp, LDAP_OPT_DIAGNOSTIC_MESSAGE, errmsg);
-       *errfree = 1;
-
-    } else {
-       *errmsg = "No modifications to do";
-       Debug( LDAP_DEBUG_ANY,
-              "Error: op_ldap_add: no mods to do (%s)!\n", re->re_dn, 0, 0 );
-    }
-    free_ldmarr( ldmarr );
-    return( lderr ); 
-}
-
-
-
-
-/*
- * Perform an ldap modify operation.
- */
-#define        AWAITING_OP -1
-static int
-op_ldap_modify(
-    Ri         *ri,
-    Re         *re,
-    char       **errmsg,
-    int                *errfree
-)
-{
-    Mi         *mi;
-    int                state;  /* This code is a simple-minded state machine */
-    int                nvals;  /* Number of values we're modifying */
-    int                nops;   /* Number of LDAPMod structs in ldmarr */
-    LDAPMod    *ldm = NULL, **ldmarr;
-    int                i, len;
-    char       *type, *value;
-    int                rc = 0;
-
-    state = AWAITING_OP;
-    nvals = 0;
-    nops = 0;
-    ldmarr = NULL;
-
-    if ( re->re_mods == NULL ) {
-       *errmsg = "No arguments given";
-       Debug( LDAP_DEBUG_ANY, "Error: op_ldap_modify: no arguments\n",
-               0, 0, 0 );
-           return -1;
-    }
-
-    /*
-     * Construct a null-terminated array of LDAPMod structs.
-     */
-    for ( mi = re->re_mods, i = 0; mi[ i ].mi_type != NULL; i++ ) {
-       type = mi[ i ].mi_type;
-       value = mi[ i ].mi_val;
-       len = mi[ i ].mi_len;
-       switch ( getmodtype( type )) {
-       case T_MODSEP:
-           state = T_MODSEP; /* Got a separator line "-\n" */
-           continue;
-       case T_MODOPADD:
-           state = T_MODOPADD;
-           ldmarr = ( LDAPMod ** )
-                   ch_realloc(ldmarr, (( nops + 2 ) * ( sizeof( LDAPMod * ))));
-           ldmarr[ nops ] = ldm = alloc_ldapmod();
-           ldm->mod_op = LDAP_MOD_ADD | LDAP_MOD_BVALUES;
-           ldm->mod_type = value;
-           nvals = 0;
-           nops++;
-           break;
-       case T_MODOPREPLACE:
-           state = T_MODOPREPLACE;
-           ldmarr = ( LDAPMod ** )
-                   ch_realloc(ldmarr, (( nops + 2 ) * ( sizeof( LDAPMod * ))));
-           ldmarr[ nops ] = ldm = alloc_ldapmod();
-           ldm->mod_op = LDAP_MOD_REPLACE | LDAP_MOD_BVALUES;
-           ldm->mod_type = value;
-           nvals = 0;
-           nops++;
-           break;
-       case T_MODOPDELETE:
-           state = T_MODOPDELETE;
-           ldmarr = ( LDAPMod ** )
-                   ch_realloc(ldmarr, (( nops + 2 ) * ( sizeof( LDAPMod * ))));
-           ldmarr[ nops ] = ldm = alloc_ldapmod();
-           ldm->mod_op = LDAP_MOD_DELETE | LDAP_MOD_BVALUES;
-           ldm->mod_type = value;
-           nvals = 0;
-           nops++;
-           break;
-       case T_MODOPINCREMENT:
-           state = T_MODOPINCREMENT;
-           ldmarr = ( LDAPMod ** )
-                   ch_realloc(ldmarr, (( nops + 2 ) * ( sizeof( LDAPMod * ))));
-           ldmarr[ nops ] = ldm = alloc_ldapmod();
-           ldm->mod_op = LDAP_MOD_INCREMENT | LDAP_MOD_BVALUES;
-           ldm->mod_type = value;
-           nvals = 0;
-           nops++;
-           break;
-       default:
-           if ( state == AWAITING_OP ) {
-               Debug( LDAP_DEBUG_ANY,
-                       "Error: op_ldap_modify: unknown mod type \"%s\"\n",
-                       type, 0, 0 );
-               continue;
-           }
-
-           assert( ldm != NULL );
-
-           /*
-            * We should have an attribute: value pair here.
-            * Construct the mod_bvalues part of the ldapmod struct.
-            */
-           if ( strcasecmp( type, ldm->mod_type )) {
-               Debug( LDAP_DEBUG_ANY,
-                       "Error: malformed modify op, %s: %s (expecting %s:)\n",
-                       type, value, ldm->mod_type );
-               continue;
-           }
-           ldm->mod_bvalues = ( struct berval ** )
-                   ch_realloc( ldm->mod_bvalues,
-                   ( nvals + 2 ) * sizeof( struct berval * ));
-           ldm->mod_bvalues[ nvals + 1 ] = NULL;
-           ldm->mod_bvalues[ nvals ] = ( struct berval * )
-                   ch_malloc( sizeof( struct berval ));
-           ldm->mod_bvalues[ nvals ]->bv_val = value;
-           ldm->mod_bvalues[ nvals ]->bv_len = len;
-           nvals++;
-       }
-    }
-    ldmarr[ nops ] = NULL;
-
-    if ( nops > 0 ) {
-       /* Actually perform the LDAP operation */
-       Debug( LDAP_DEBUG_ARGS, "replica %s:%d - modify dn \"%s\"\n",
-               ri->ri_hostname, ri->ri_port, re->re_dn );
-       rc = ldap_modify_s( ri->ri_ldp, re->re_dn, ldmarr );
-       ldap_get_option( ri->ri_ldp, LDAP_OPT_DIAGNOSTIC_MESSAGE, errmsg);
-       *errfree = 1;
-    }
-    free_ldmarr( ldmarr );
-    return( rc );
-}
-
-
-
-
-/*
- * Perform an ldap delete operation.
- */
-static int
-op_ldap_delete(
-    Ri         *ri,
-    Re         *re,
-    char       **errmsg,
-    int                *errfree
-)
-{
-    int                rc;
-
-    Debug( LDAP_DEBUG_ARGS, "replica %s:%d - delete dn \"%s\"\n",
-           ri->ri_hostname, ri->ri_port, re->re_dn );
-    rc = ldap_delete_s( ri->ri_ldp, re->re_dn );
-    ldap_get_option( ri->ri_ldp, LDAP_OPT_DIAGNOSTIC_MESSAGE, errmsg);
-    *errfree = 1;
-
-    return( rc );
-}
-
-
-
-
-/*
- * Perform an ldap modrdn operation.
- */
-#define        GOT_NEWRDN              0x1
-#define        GOT_DELOLDRDN   0x2
-#define GOT_NEWSUP             0x4
-
-#define GOT_MODDN_REQ  (GOT_NEWRDN|GOT_DELOLDRDN)
-#define        GOT_ALL_MODDN(f)        (((f) & GOT_MODDN_REQ) == GOT_MODDN_REQ)
-static int
-op_ldap_modrdn(
-    Ri         *ri,
-    Re         *re,
-    char       **errmsg,
-    int                *errfree
-)
-{
-    int                rc = 0;
-    Mi         *mi;
-    int                i;
-       int             lderr = 0;
-    int                state = 0;
-    int                drdnflag = -1;
-    char       *newrdn = NULL;
-       char    *newsup = NULL;
-
-    if ( re->re_mods == NULL ) {
-       *errmsg = "No arguments given";
-       Debug( LDAP_DEBUG_ANY, "Error: op_ldap_modrdn: no arguments\n",
-               0, 0, 0 );
-           return -1;
-    }
-
-    /*
-     * Get the arguments: should see newrdn: and deleteoldrdn: args.
-     */
-    for ( mi = re->re_mods, i = 0; mi[ i ].mi_type != NULL; i++ ) {
-       if ( !strcmp( mi[ i ].mi_type, T_NEWRDNSTR )) {
-               if( state & GOT_NEWRDN ) {
-               Debug( LDAP_DEBUG_ANY,
-                       "Error: op_ldap_modrdn: multiple newrdn arg \"%s\"\n",
-                       mi[ i ].mi_val, 0, 0 );
-               *errmsg = "Multiple newrdn argument";
-               return -1;
-               }
-
-           newrdn = mi[ i ].mi_val;
-           state |= GOT_NEWRDN;
-
-       } else if ( !strcmp( mi[ i ].mi_type, T_DELOLDRDNSTR )) {
-               if( state & GOT_DELOLDRDN ) {
-               Debug( LDAP_DEBUG_ANY,
-                       "Error: op_ldap_modrdn: multiple deleteoldrdn arg \"%s\"\n",
-                       mi[ i ].mi_val, 0, 0 );
-               *errmsg = "Multiple newrdn argument";
-               return -1;
-               }
-
-           state |= GOT_DELOLDRDN;
-           if ( !strcmp( mi[ i ].mi_val, "0" )) {
-               drdnflag = 0;
-           } else if ( !strcmp( mi[ i ].mi_val, "1" )) {
-               drdnflag = 1;
-           } else {
-               Debug( LDAP_DEBUG_ANY,
-                       "Error: op_ldap_modrdn: bad deleteoldrdn arg \"%s\"\n",
-                       mi[ i ].mi_val, 0, 0 );
-               *errmsg = "Incorrect argument to deleteoldrdn";
-               return -1;
-           }
-
-       } else if ( !strcmp( mi[ i ].mi_type, T_NEWSUPSTR )) {
-               if( state & GOT_NEWSUP ) {
-               Debug( LDAP_DEBUG_ANY,
-                       "Error: op_ldap_modrdn: multiple newsuperior arg \"%s\"\n",
-                       mi[ i ].mi_val, 0, 0 );
-               *errmsg = "Multiple newsuperior argument";
-               return -1;
-               }
-
-               newsup = mi[ i ].mi_val;
-           state |= GOT_NEWSUP;
-
-       } else {
-           Debug( LDAP_DEBUG_ANY, "Error: op_ldap_modrdn: bad type \"%s\"\n",
-                   mi[ i ].mi_type, 0, 0 );
-           *errmsg = "Bad value in replication log entry";
-           return -1;
-       }
-    }
-
-    /*
-     * Punt if we don't have all the args.
-     */
-    if ( !GOT_ALL_MODDN(state) ) {
-       Debug( LDAP_DEBUG_ANY, "Error: op_ldap_modrdn: missing arguments\n",
-               0, 0, 0 );
-       *errmsg = "Missing argument: requires \"newrdn\" and \"deleteoldrdn\"";
-       return -1;
-    }
-
-#ifdef LDAP_DEBUG
-    if ( ldap_debug & LDAP_DEBUG_ARGS ) {
-       char buf[ 256 ];
-       char *buf2;
-       int buf2len = strlen( re->re_dn ) + strlen( mi->mi_val ) + 11;
-
-       snprintf( buf, sizeof(buf), "%s:%d", ri->ri_hostname, ri->ri_port );
-
-       buf2 = (char *) ch_malloc( buf2len );
-       snprintf( buf2, buf2len, "(\"%s\" -> \"%s\")", re->re_dn, mi->mi_val );
-
-       Debug( LDAP_DEBUG_ARGS,
-               "replica %s - modify rdn %s (flag: %d)\n",
-               buf, buf2, drdnflag );
-       free( buf2 );
-    }
-#endif /* LDAP_DEBUG */
-
-    assert( newrdn != NULL );
-
-    /* Do the modrdn */
-    rc = ldap_rename2_s( ri->ri_ldp, re->re_dn, newrdn, newsup, drdnflag );
-
-       ldap_get_option( ri->ri_ldp, LDAP_OPT_RESULT_CODE, &lderr);
-       ldap_get_option( ri->ri_ldp, LDAP_OPT_DIAGNOSTIC_MESSAGE, errmsg);
-       *errfree = 1;
-    return( lderr );
-}
-
-
-
-/*
- * Allocate and initialize an ldapmod struct.
- */
-static LDAPMod *
-alloc_ldapmod( void )
-{
-    LDAPMod    *ldm;
-
-    ldm = ( struct ldapmod * ) ch_malloc( sizeof ( struct ldapmod ));
-    ldm->mod_type = NULL;
-    ldm->mod_bvalues = ( struct berval ** ) NULL;
-    return( ldm );
-}
-
-
-
-/*
- * Free an ldapmod struct associated mod_bvalues.  NOTE - it is assumed
- * that mod_bvalues and mod_type contain pointers to the same block of memory
- * pointed to by the repl struct.  Therefore, it's not freed here.
- */
-static void
-free_ldapmod(
-LDAPMod *ldm )
-{
-    int                i;
-
-    if ( ldm == NULL ) {
-       return;
-    }
-    if ( ldm->mod_bvalues != NULL ) {
-       for ( i = 0; ldm->mod_bvalues[ i ] != NULL; i++ ) {
-           free( ldm->mod_bvalues[ i ] );
-       }
-       free( ldm->mod_bvalues );
-    }
-    free( ldm );
-    return;
-}
-
-
-/*
- * Free an an array of LDAPMod pointers and the LDAPMod structs they point
- * to.
- */
-static void
-free_ldmarr(
-LDAPMod **ldmarr )
-{
-    int        i;
-
-    for ( i = 0; ldmarr[ i ] != NULL; i++ ) {
-       free_ldapmod( ldmarr[ i ] );
-    }
-    free( ldmarr );
-}
-
-
-/*
- * Create a berval with a single value. 
- */
-static struct berval **
-make_singlevalued_berval( 
-char   *value,
-int    len )
-{
-    struct berval **p;
-
-    p = ( struct berval ** ) ch_malloc( 2 * sizeof( struct berval * ));
-    p[ 0 ] = ( struct berval * ) ch_malloc( sizeof( struct berval ));
-    p[ 1 ] = NULL;
-    p[ 0 ]->bv_val = value;
-    p[ 0 ]->bv_len = len;
-    return( p );
-}
-
-
-/*
- * Given a modification type (string), return an enumerated type.
- * Avoids ugly copy in op_ldap_modify - lets us use a switch statement
- * there.
- */
-static int
-getmodtype( 
-char *type )
-{
-    if ( !strcmp( type, T_MODSEPSTR )) {
-       return( T_MODSEP );
-    }
-    if ( !strcmp( type, T_MODOPADDSTR )) {
-       return( T_MODOPADD );
-    }
-    if ( !strcmp( type, T_MODOPREPLACESTR )) {
-       return( T_MODOPREPLACE );
-    }
-    if ( !strcmp( type, T_MODOPDELETESTR )) {
-       return( T_MODOPDELETE );
-    }
-    if ( !strcmp( type, T_MODOPINCREMENTSTR )) {
-       return( T_MODOPINCREMENT );
-    }
-    return( T_ERR );
-}
-
-
-/*
- * Perform an LDAP unbind operation.  If replica is NULL, or the
- * repl_ldp is NULL, just return LDAP_SUCCESS.  Otherwise, unbind,
- * set the ldp to NULL, and return the result of the unbind call.
- */
-static int
-do_unbind(
-    Ri *ri
-)
-{
-    int                rc = LDAP_SUCCESS;
-
-    if (( ri != NULL ) && ( ri->ri_ldp != NULL )) {
-       rc = ldap_unbind( ri->ri_ldp );
-       if ( rc != LDAP_SUCCESS ) {
-           Debug( LDAP_DEBUG_ANY,
-                   "Error: do_unbind: ldap_unbind failed for %s:%d: %s\n",
-                   ri->ri_hostname, ri->ri_port, ldap_err2string( rc ) );
-       }
-       ri->ri_ldp = NULL;
-    }
-    return rc;
-}
-
-
-
-/*
- * Perform an LDAP bind operation to the replication site given
- * by replica.  If replica->repl_ldp is non-NULL, then we unbind
- * from the replica before rebinding.  It should be safe to call
- * this to re-connect if the replica's connection goes away
- * for some reason.
- *
- * Returns 0 on success, -1 if an LDAP error occurred, and a return
- * code > 0 if some other error occurred, e.g. invalid bind method.
- * If an LDAP error occurs, the LDAP error is returned in lderr.
- */
-static int
-do_bind( 
-    Ri *ri,
-    int        *lderr
-)
-{
-    int                ldrc;
-    int                do_tls;
-
-    *lderr = 0;
-
-    if ( ri == NULL ) {
-       Debug( LDAP_DEBUG_ANY, "Error: do_bind: null ri ptr\n", 0, 0, 0 );
-       return( BIND_ERR_BADRI );
-    }
-
-    do_tls = ri->ri_tls;
-
-retry:
-    if ( ri->ri_ldp != NULL ) {
-       ldrc = ldap_unbind( ri->ri_ldp );
-       if ( ldrc != LDAP_SUCCESS ) {
-           Debug( LDAP_DEBUG_ANY,
-                   "Error: do_bind: ldap_unbind failed: %s\n",
-                   ldap_err2string( ldrc ), 0, 0 );
-       }
-       ri->ri_ldp = NULL;
-    }
-    
-       if ( ri->ri_uri != NULL ) { /* new URI style */
-           Debug( LDAP_DEBUG_ARGS, "Initializing session to %s\n",
-                   ri->ri_uri, 0, 0 );
-
-               ldrc = ldap_initialize( &(ri->ri_ldp), ri->ri_uri);
-
-               if (ldrc != LDAP_SUCCESS) {
-               Debug( LDAP_DEBUG_ANY, "Error: ldap_initialize(0, %s) failed: %s\n",
-                       ri->ri_uri, ldap_err2string(ldrc), 0 );
-               return( BIND_ERR_OPEN );                
-               }
-       } else { /* old HOST style */
-    Debug( LDAP_DEBUG_ARGS, "Initializing session to %s:%d\n",
-           ri->ri_hostname, ri->ri_port, 0 );
-
-    ri->ri_ldp = ldap_init( ri->ri_hostname, ri->ri_port );
-    if ( ri->ri_ldp == NULL ) {
-               Debug( LDAP_DEBUG_ANY, "Error: ldap_init(%s, %d) failed: %s\n",
-                       ri->ri_hostname, ri->ri_port, sys_errlist[ errno ] );
-               return( BIND_ERR_OPEN );
-    }
-    }
-
-       {       /* set version 3 */
-               int err, version = LDAP_VERSION3;
-               err = ldap_set_option(ri->ri_ldp,
-                       LDAP_OPT_PROTOCOL_VERSION, &version);
-
-               if( err != LDAP_OPT_SUCCESS ) {
-                       Debug( LDAP_DEBUG_ANY,
-                               "Error: ldap_set_option(%s, LDAP_OPT_VERSION, 3) failed!\n",
-                               ri->ri_hostname, NULL, NULL );
-
-                       ldap_unbind( ri->ri_ldp );
-                       ri->ri_ldp = NULL;
-                       return BIND_ERR_VERSION;
-               }
-       }
-
-    /*
-     * Set ldap library options to (1) not follow referrals, and 
-     * (2) restart the select() system call.
-     */
-       {
-               int err;
-               err = ldap_set_option(ri->ri_ldp, LDAP_OPT_REFERRALS, LDAP_OPT_OFF);
-
-               if( err != LDAP_OPT_SUCCESS ) {
-                       Debug( LDAP_DEBUG_ANY,
-                               "Error: ldap_set_option(%s,REFERRALS, OFF) failed!\n",
-                               ri->ri_hostname, NULL, NULL );
-                       ldap_unbind( ri->ri_ldp );
-                       ri->ri_ldp = NULL;
-                       return BIND_ERR_REFERRALS;
-               }
-       }
-       ldap_set_option(ri->ri_ldp, LDAP_OPT_RESTART, LDAP_OPT_ON);
-
-       if( do_tls ) {
-               int err = ldap_start_tls_s(ri->ri_ldp, NULL, NULL);
-
-               if( err != LDAP_SUCCESS ) {
-                       Debug( LDAP_DEBUG_ANY,
-                               "%s: ldap_start_tls failed: %s (%d)\n",
-                               ri->ri_tls == TLS_CRITICAL ? "Error" : "Warning",
-                               ldap_err2string( err ), err );
-
-                       if( ri->ri_tls == TLS_CRITICAL ) {
-                               *lderr = err;
-                               ldap_unbind( ri->ri_ldp );
-                               ri->ri_ldp = NULL;
-                               return BIND_ERR_TLS_FAILED;
-                       }
-                       do_tls = TLS_OFF;
-                       goto retry;
-               }
-       }
-
-    switch ( ri->ri_bind_method ) {
-    case LDAP_AUTH_SIMPLE:
-       /*
-        * Bind with a plaintext password.
-        */
-       Debug( LDAP_DEBUG_ARGS, "bind to %s:%d as %s (simple)\n",
-               ri->ri_hostname, ri->ri_port, ri->ri_bind_dn );
-       ldrc = ldap_simple_bind_s( ri->ri_ldp, ri->ri_bind_dn,
-               ri->ri_password );
-       if ( ldrc != LDAP_SUCCESS ) {
-           Debug( LDAP_DEBUG_ANY,
-                   "Error: ldap_simple_bind_s for %s:%d failed: %s\n",
-                   ri->ri_hostname, ri->ri_port, ldap_err2string( ldrc ));
-           *lderr = ldrc;
-               ldap_unbind( ri->ri_ldp );
-               ri->ri_ldp = NULL;
-           return( BIND_ERR_SIMPLE_FAILED );
-       }
-       break;
-
-       case LDAP_AUTH_SASL:
-       Debug( LDAP_DEBUG_ARGS, "bind to %s as %s via %s (SASL)\n",
-               ri->ri_hostname,
-               ri->ri_authcId ? ri->ri_authcId : "-",
-               ri->ri_saslmech );
-
-#ifdef HAVE_CYRUS_SASL
-       if( ri->ri_secprops != NULL ) {
-               int err = ldap_set_option(ri->ri_ldp,
-                       LDAP_OPT_X_SASL_SECPROPS, ri->ri_secprops);
-
-               if( err != LDAP_OPT_SUCCESS ) {
-                       Debug( LDAP_DEBUG_ANY,
-                               "Error: ldap_set_option(%s,SECPROPS,\"%s\") failed!\n",
-                               ri->ri_hostname, ri->ri_secprops, NULL );
-                       ldap_unbind( ri->ri_ldp );
-                       ri->ri_ldp = NULL;
-                       return BIND_ERR_SASL_FAILED;
-               }
-       }
-
-       {
-               void *defaults = lutil_sasl_defaults( ri->ri_ldp, ri->ri_saslmech,
-                   ri->ri_realm, ri->ri_authcId, ri->ri_password, ri->ri_authzId );
-
-               ldrc = ldap_sasl_interactive_bind_s( ri->ri_ldp, ri->ri_bind_dn,
-                   ri->ri_saslmech, NULL, NULL,
-                   LDAP_SASL_QUIET, lutil_sasl_interact, defaults );
-
-               lutil_sasl_freedefs( defaults );
-               if ( ldrc != LDAP_SUCCESS ) {
-                       Debug( LDAP_DEBUG_ANY, "Error: LDAP SASL for %s:%d failed: %s\n",
-                           ri->ri_hostname, ri->ri_port, ldap_err2string( ldrc ));
-                       *lderr = ldrc;
-                       ldap_unbind( ri->ri_ldp );
-                       ri->ri_ldp = NULL;
-                       return( BIND_ERR_SASL_FAILED );
-               }
-       }
-       break;
-#else
-       Debug( LDAP_DEBUG_ANY,
-               "Error: do_bind: SASL not supported %s:%d\n",
-                ri->ri_hostname, ri->ri_port, NULL );
-       ldap_unbind( ri->ri_ldp );
-       ri->ri_ldp = NULL;
-       return( BIND_ERR_BAD_ATYPE );
-#endif
-
-    default:
-       Debug(  LDAP_DEBUG_ANY,
-               "Error: do_bind: unknown auth type \"%d\" for %s:%d\n",
-               ri->ri_bind_method, ri->ri_hostname, ri->ri_port );
-       ldap_unbind( ri->ri_ldp );
-       ri->ri_ldp = NULL;
-       return( BIND_ERR_BAD_ATYPE );
-    }
-
-       {
-               int err;
-               LDAPControl c;
-               LDAPControl *ctrls[2];
-               ctrls[0] = &c;
-               ctrls[1] = NULL;
-
-               c.ldctl_oid = LDAP_CONTROL_MANAGEDSAIT;
-               c.ldctl_value.bv_val = NULL;
-               c.ldctl_value.bv_len = 0;
-               c.ldctl_iscritical = 0;
-
-               err = ldap_set_option(ri->ri_ldp, LDAP_OPT_SERVER_CONTROLS, &ctrls);
-
-               if( err != LDAP_OPT_SUCCESS ) {
-                       Debug( LDAP_DEBUG_ANY, "Error: "
-                               "ldap_set_option(%s, SERVER_CONTROLS, ManageDSAit) failed!\n",
-                               ri->ri_hostname, NULL, NULL );
-                       ldap_unbind( ri->ri_ldp );
-                       ri->ri_ldp = NULL;
-                       return BIND_ERR_MANAGEDSAIT;
-               }
-       }
-
-       return( BIND_OK );
-}
-
-
-
-
-
-/*
- * For debugging.  Print the contents of an ldmarr array.
- */
-#ifdef SLAPD_UNUSED
-static void
-dump_ldm_array(
-    LDAPMod **ldmarr
-)
-{
-    int                         i, j;
-    LDAPMod            *ldm;
-    struct berval      *b;
-    char               *msgbuf;
-
-    for ( i = 0; ldmarr[ i ] != NULL; i++ ) {
-       ldm = ldmarr[ i ];
-       Debug( LDAP_DEBUG_TRACE,
-               "Trace (%ld): *** ldmarr[ %d ] contents:\n",
-               (long) getpid(), i, 0 );
-       Debug( LDAP_DEBUG_TRACE,
-               "Trace (%ld): *** ldm->mod_op: %d\n",
-               (long) getpid(), ldm->mod_op, 0 );
-       Debug( LDAP_DEBUG_TRACE,
-               "Trace (%ld): *** ldm->mod_type: %s\n",
-               (long) getpid(), ldm->mod_type, 0 );
-       if ( ldm->mod_bvalues != NULL ) {
-           for ( j = 0; ( b = ldm->mod_bvalues[ j ] ) != NULL; j++ ) {
-               msgbuf = ch_malloc( b->bv_len + 512 );
-               sprintf( msgbuf, "***** bv[ %d ] len = %ld, val = <%s>",
-                       j, b->bv_len, b->bv_val );
-               Debug( LDAP_DEBUG_TRACE,
-                       "Trace (%ld):%s\n", (long) getpid(), msgbuf, 0 );
-               free( msgbuf );
-           }
-       }
-    }
-}
-#endif
diff --git a/servers/slurpd/lock.c b/servers/slurpd/lock.c
deleted file mode 100644 (file)
index 7b459ab..0000000
+++ /dev/null
@@ -1,144 +0,0 @@
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 1998-2007 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>.
- */
-/* Portions Copyright (c) 1996 Regents of the University of Michigan.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that this notice is preserved and that due credit is given
- * to the University of Michigan at Ann Arbor. The name of the University
- * may not be used to endorse or promote products derived from this
- * software without specific prior written permission. This software
- * is provided ``as is'' without express or implied warranty.
- */
-/* ACKNOWLEDGEMENTS:
- * This work was originally developed by the University of Michigan
- * (as part of U-MICH LDAP).
- */
-
-/*
- * lock.c - routines to open and apply an advisory lock to a file
- */
-
-#include "portable.h"
-
-#include <stdio.h>
-
-#include <ac/param.h>
-#include <ac/string.h>
-#include <ac/socket.h>
-#include <ac/time.h>
-#include <ac/unistd.h>
-
-#ifdef HAVE_SYS_FILE_H
-#include <sys/file.h>
-#endif
-
-#include "slurp.h"
-
-
-FILE *
-lock_fopen(
-    const char *fname,
-    const char *type,
-    FILE       **lfp
-)
-{
-       FILE    *fp;
-       char    buf[MAXPATHLEN];
-
-       /* open the lock file */
-       snprintf( buf, sizeof buf, "%s.lock", fname );
-
-       if ( (*lfp = fopen( buf, "w" )) == NULL ) {
-               Debug( LDAP_DEBUG_ANY,
-                       "Error: could not open \"%s\"\n", buf, 0, 0 );
-               return( NULL );
-       }
-
-       /* acquire the lock */
-       ldap_lockf( fileno(*lfp) );
-
-       /* open the log file */
-       if ( (fp = fopen( fname, type )) == NULL ) {
-               Debug( LDAP_DEBUG_ANY,
-                       "Error: could not open \"%s\"\n", fname, 0, 0 );
-               ldap_unlockf( fileno(*lfp) );
-               fclose( *lfp );
-               *lfp = NULL;
-               return( NULL );
-       }
-
-       return( fp );
-}
-
-
-
-int
-lock_fclose(
-    FILE       *fp,
-    FILE       *lfp
-)
-{
-       int rc = fclose( fp );
-
-       /* unlock */
-       ldap_unlockf( fileno(lfp) );
-       fclose( lfp );
-
-       return( rc );
-}
-
-
-
-/*
- * Apply an advisory lock on a file.  Just calls lock_fopen()
- */
-int
-acquire_lock(
-    const char *file,
-    FILE       **rfp,
-    FILE       **lfp
-)
-{
-    if (( *rfp = lock_fopen( file, "r+", lfp )) == NULL ) {
-       Debug( LDAP_DEBUG_ANY,
-               "Error: acquire_lock(%ld): Could not acquire lock on \"%s\"\n",
-               (long) getpid(), file, 0);
-       return( -1 );
-    }
-    return( 0 );
-}
-
-
-
-/*
- * Relinquish a lock on a file.  Calls lock_fclose() and also removes the
- * lock file.
- */
-int
-relinquish_lock(
-    const char *file,
-    FILE       *rfp,
-    FILE       *lfp
-)
-{
-    if ( lock_fclose( rfp, lfp ) == EOF ) {
-       Debug( LDAP_DEBUG_ANY,
-               "Error: relinquish_lock (%ld): Error closing \"%s\"\n",
-               (long) getpid(), file, 0 );
-       return( -1 );
-    }
-    return( 0 );
-}
diff --git a/servers/slurpd/main.c b/servers/slurpd/main.c
deleted file mode 100644 (file)
index 4284c87..0000000
+++ /dev/null
@@ -1,355 +0,0 @@
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 1998-2007 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>.
- */
-/* Portions Copyright (c) 1996 Regents of the University of Michigan.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that this notice is preserved and that due credit is given
- * to the University of Michigan at Ann Arbor. The name of the University
- * may not be used to endorse or promote products derived from this
- * software without specific prior written permission. This software
- * is provided ``as is'' without express or implied warranty.
- */
-/* ACKNOWLEDGEMENTS:
- * This work was originally developed by the University of Michigan
- * (as part of U-MICH LDAP).  Additional significant contributors
- * include:
- *     Howard Chu
- */
-
-
-/* 
- * main.c - main routine for slurpd.
- */
-
-#include "portable.h"
-
-#include <stdio.h>
-#include <sys/stat.h>
-#include <ac/stdlib.h>
-#include <ac/unistd.h>
-
-#include "slurp.h"
-#include "globals.h"
-#include "lutil.h"
-
-#include <ldap_pvt.h>
-
-#ifdef HAVE_NT_SERVICE_MANAGER
-#define        MAIN_RETURN(x)  return
-#define SERVICE_EXIT( e, n )   do { \
-       if ( is_NT_Service ) { \
-               lutil_ServiceStatus.dwWin32ExitCode = (e); \
-               lutil_ServiceStatus.dwServiceSpecificExitCode = (n); \
-       } \
-} while ( 0 )
-#else
-#define SERVICE_EXIT( e, n )
-#define        MAIN_RETURN(x)  return(x)
-#endif
-
-#ifndef HAVE_MKVERSION
-const char Versionstr[] =
-       OPENLDAP_PACKAGE " " OPENLDAP_VERSION " Standalone LDAP Replicator (slurpd)";
-#endif
-
-#ifdef HAVE_NT_SERVICE_MANAGER
-void WINAPI ServiceMain( DWORD argc, LPTSTR *argv )
-#else
-int main( int argc, char **argv )
-#endif
-{
-#ifdef NO_THREADS
-    /* Haven't yet written the non-threaded version */
-    fputs( "slurpd currently requires threads support\n", stderr );
-    return( 1 );
-#else
-
-    int                        i, rc = 0;
-
-    /* initialize thread package */
-    ldap_pvt_thread_initialize();
-
-    /* 
-     * Create and initialize globals.  init_globals() also initializes
-     * the main replication queue.
-     */
-    if (( sglob = init_globals()) == NULL ) {
-       fprintf( stderr, "Out of memory initializing globals\n" );
-       SERVICE_EXIT( ERROR_NOT_ENOUGH_MEMORY, 0 );
-       rc = 1;
-       goto stop;
-    }
-
-#ifdef HAVE_NT_SERVICE_MANAGER
-       {
-               int *i;
-               char *newConfigFile;
-               char *regService = NULL;
-
-               if ( is_NT_Service ) {
-                       sglob->serverName = argv[0];
-                       lutil_CommenceStartupProcessing( sglob->serverName, slurp_set_shutdown );
-                       if ( strcmp(sglob->serverName, SERVICE_NAME) )
-                           regService = sglob->serverName;
-               }
-
-               i = (int*)lutil_getRegParam( regService, "DebugLevel" );
-               if ( i != NULL ) 
-               {
-                       ldap_debug = *i;
-                       Debug( LDAP_DEBUG_ANY, "new debug level from registry is: %d\n", ldap_debug, 0, 0 );
-               }
-
-               newConfigFile = (char*)lutil_getRegParam( regService, "ConfigFile" );
-               if ( newConfigFile != NULL ) 
-               {
-                       sglob->slapd_configfile = newConfigFile;
-                       Debug ( LDAP_DEBUG_ANY, "new config file from registry is: %s\n", sglob->slapd_configfile, 0, 0 );
-
-               }
-       }
-#endif
-
-    /*
-     * Process command-line args and fill in globals.
-     */
-    if ( doargs( argc, argv, sglob ) < 0 ) {
-       SERVICE_EXIT( ERROR_SERVICE_SPECIFIC_ERROR, 15 );
-       rc = 1;
-       goto stop;
-    }
-
-    if ( sglob->version ) {
-               fprintf(stderr, "%s\n", Versionstr);
-               if (sglob->version > 1 ) {
-                       rc = 1;
-                       goto stop;
-               }
-    }
-
-       Debug ( LDAP_DEBUG_ANY, "%s\n", Versionstr, 0, 0 );
-    
-    /*
-     * Read slapd config file and initialize Re (per-replica) structs.
-     */
-    if ( slurpd_read_config( sglob->slapd_configfile ) < 0 ) {
-       fprintf( stderr,
-               "Errors encountered while processing config file \"%s\"\n",
-               sglob->slapd_configfile );
-       SERVICE_EXIT( ERROR_SERVICE_SPECIFIC_ERROR, 19 );
-       rc = 1;
-       goto stop;
-    }
-
-#ifdef HAVE_TLS
-       if( ldap_pvt_tls_init() || ldap_pvt_tls_init_def_ctx( 0 ) ) {
-               rc = 0;
-               /* See if we actually need TLS */
-               for ( i=0; i < sglob->num_replicas; i++ ) {
-                       if ( sglob->replicas[i]->ri_tls || ( sglob->replicas[i]->ri_uri &&
-                               !strncmp( sglob->replicas[i]->ri_uri, "ldaps:", 6 ))) {
-                               rc = 1;
-                               break;
-                       }
-               }
-               if ( rc ) {
-                       fprintf( stderr, "TLS Initialization failed.\n" );
-                       SERVICE_EXIT( ERROR_SERVICE_SPECIFIC_ERROR, 20 );
-                       goto stop;
-               }
-       }
-#endif
-
-    /* 
-     * Make sure our directory exists
-     */
-    if ( mkdir(sglob->slurpd_rdir, 0755) == -1 && errno != EEXIST) {
-       perror(sglob->slurpd_rdir);
-       SERVICE_EXIT( ERROR_SERVICE_SPECIFIC_ERROR, 16 );
-       rc = 1;
-       goto stop;
-    }
-
-    /*
-     * Get any saved state information off the disk.
-     */
-    if ( sglob->st->st_read( sglob->st )) {
-       fprintf( stderr, "Malformed slurpd status file \"%s\"\n",
-               sglob->slurpd_status_file );
-       SERVICE_EXIT( ERROR_SERVICE_SPECIFIC_ERROR, 17 );
-       rc = 1;
-       goto stop;
-    }
-
-    /*
-     * All readonly data should now be initialized. 
-     * Check for any fatal error conditions before we get started
-     */
-     if ( sanity() < 0 ) {
-       SERVICE_EXIT( ERROR_SERVICE_SPECIFIC_ERROR, 18 );
-       rc = 1;
-       goto stop;
-    }
-
-
-    /*
-     * Detach from the controlling terminal
-     * unless the -d flag is given or in one-shot mode.
-     */
-#ifndef HAVE_WINSOCK
-       if ( ! (sglob->no_detach || sglob->one_shot_mode) ) {
-               lutil_detach( 0, 0 );
-       }
-#endif
-
-       /*
-        * don't open pid/args file in one-shot mode (ITS#4152)
-        *
-        * bail out if files were specified but cannot be opened (ITS#4074)
-        */
-       if ( !sglob->one_shot_mode) {
-               if ( slurpd_pid_file != NULL ) {
-                       FILE *fp = fopen( slurpd_pid_file, "w" );
-
-                       if ( fp == NULL ) {
-                               int save_errno = errno;
-
-                               fprintf( stderr, "unable to open pid file "
-                                       "\"%s\": %d (%s)\n",
-                                       slurpd_pid_file,
-                                       save_errno, strerror( save_errno ) );
-
-                               free( slurpd_pid_file );
-                               slurpd_pid_file = NULL;
-
-                               rc = 1;
-                               goto stop;
-                       }
-
-                       fprintf( fp, "%d\n", (int) getpid() );
-                       fclose( fp );
-               }
-
-               if ( slurpd_args_file != NULL ) {
-                       FILE *fp = fopen( slurpd_args_file, "w" );
-
-                       if ( fp == NULL ) {
-                               int save_errno = errno;
-
-                               fprintf( stderr, "unable to open args file "
-                                       "\"%s\": %d (%s)\n",
-                                       slurpd_args_file,
-                                       save_errno, strerror( save_errno ) );
-
-                               free( slurpd_args_file );
-                               slurpd_pid_file = NULL;
-
-                               rc = 1;
-                               goto stop;
-                       }
-
-                       for ( i = 0; i < argc; i++ ) {
-                               fprintf( fp, "%s ", argv[i] );
-                       }
-                       fprintf( fp, "\n" );
-                       fclose( fp );
-               }
-       }
-
-    if ( (rc = lutil_pair( sglob->wake_sds )) < 0 ) {
-       SERVICE_EXIT( ERROR_SERVICE_SPECIFIC_ERROR, 16 );
-       rc = 1;
-       goto stop;
-    }
-       
-#ifdef HAVE_NT_EVENT_LOG
-       if (is_NT_Service) lutil_LogStartedEvent( sglob->serverName, ldap_debug, sglob->slapd_configfile, "n/a" );
-#endif
-
-    /*
-     * Start the main file manager thread (in fm.c).
-     */
-    if ( ldap_pvt_thread_create( &(sglob->fm_tid),
-               0, fm, (void *) NULL ) != 0 )
-       {
-       Debug( LDAP_DEBUG_ANY, "file manager ldap_pvt_thread_create failed\n",
-               0, 0, 0 );
-       SERVICE_EXIT( ERROR_SERVICE_SPECIFIC_ERROR, 21 );
-       rc = 1;
-       goto stop;
-
-    }
-
-    /*
-     * wait for fm to finish if in oneshot mode
-     */
-    if ( sglob->one_shot_mode ) {
-       ldap_pvt_thread_join( sglob->fm_tid, (void *) NULL );
-    }
-
-    /*
-     * Start threads - one thread for each replica
-     */
-    for ( i = 0; sglob->replicas[ i ] != NULL; i++ ) {
-       start_replica_thread( sglob->replicas[ i ]);
-    }
-
-#ifdef HAVE_NT_SERVICE_MANAGER
-    if ( started_event ) ldap_pvt_thread_cond_signal( &started_event );
-#endif
-
-    /*
-     * Wait for the fm thread to finish.
-     */
-    if ( !sglob->one_shot_mode ) {
-       ldap_pvt_thread_join( sglob->fm_tid, (void *) NULL );
-    }
-
-    /*
-     * Wait for the replica threads to finish.
-     */
-    for ( i = 0; sglob->replicas[ i ] != NULL; i++ ) {
-       ldap_pvt_thread_join( sglob->replicas[ i ]->ri_tid, (void *) NULL );
-    }
-
-stop:
-#ifdef HAVE_NT_SERVICE_MANAGER
-       if (is_NT_Service) {
-               ldap_pvt_thread_cond_destroy( &started_event );
-               lutil_LogStoppedEvent( sglob->serverName );
-               lutil_ReportShutdownComplete();
-       }
-#endif
-    /* destroy the thread package */
-    ldap_pvt_thread_destroy();
-
-#ifdef HAVE_TLS
-    ldap_pvt_tls_destroy();
-#endif
-
-    Debug( LDAP_DEBUG_ANY, "slurpd: terminated.\n", 0, 0, 0 );
-
-    if ( slurpd_pid_file != NULL ) {
-       unlink( slurpd_pid_file );
-    }
-    if ( slurpd_args_file != NULL ) {
-       unlink( slurpd_args_file );
-    }
-
-
-       MAIN_RETURN(rc);
-#endif /* !NO_THREADS */
-}
diff --git a/servers/slurpd/nt_svc.c b/servers/slurpd/nt_svc.c
deleted file mode 100644 (file)
index e2b0f88..0000000
+++ /dev/null
@@ -1,110 +0,0 @@
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 1998-2007 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>.
- */
-
-#include "portable.h"
-#include <stdio.h>
-#include <ac/string.h>
-#include <ac/stdlib.h>
-#include "slurp.h"
-#include "lutil.h"
-
-#ifdef HAVE_NT_SERVICE_MANAGER
-
-/* in main.c */
-void WINAPI ServiceMain( DWORD argc, LPTSTR *argv );
-
-int main( int argc, LPTSTR *argv )
-{
-       int             length;
-       char    filename[MAX_PATH], *fname_start;
-
-       /*
-        * Because the service was registered as SERVICE_WIN32_OWN_PROCESS,
-        * the lpServiceName element of the SERVICE_TABLE_ENTRY will be
-        * ignored.
-        */
-
-       SERVICE_TABLE_ENTRY             DispatchTable[] = {
-               {       "",     (LPSERVICE_MAIN_FUNCTION) ServiceMain   },
-               {       NULL,                   NULL    }
-       };
-
-       /*
-        * set the service's current directory to the installation directory
-        * for the service. this way we don't have to write absolute paths
-        * in the configuration files
-        */
-       GetModuleFileName( NULL, filename, sizeof( filename ) );
-       fname_start = strrchr( filename, *LDAP_DIRSEP );
-
-       if ( argc > 1 ) {
-               if ( _stricmp( "install", argv[1] ) == 0 ) 
-               {
-                       char *svcName = SERVICE_NAME;
-                       char *displayName = "OpenLDAP Replication Service";
-                       BOOL auto_start = FALSE;
-
-                       if ( (argc > 2) && (argv[2] != NULL) )
-                               svcName = argv[2];
-
-                       if ( argc > 3 && argv[3])
-                               displayName = argv[3];
-
-                       if ( argc > 4 && stricmp(argv[4], "auto") == 0)
-                               auto_start = TRUE;
-
-                       strcat(filename, " service");
-                       if ( !lutil_srv_install(svcName, displayName, filename, auto_start) ) 
-                       {
-                               fputs( "service failed installation ...\n", stderr  );
-                               return EXIT_FAILURE;
-                       }
-                       fputs( "service has been installed ...\n", stderr  );
-                       return EXIT_SUCCESS;
-               }
-
-               if ( _stricmp( "remove", argv[1] ) == 0 ) 
-               {
-                       char *svcName = SERVICE_NAME;
-                       if ( (argc > 2) && (argv[2] != NULL) )
-                               svcName = argv[2];
-                       if ( !lutil_srv_remove(svcName, filename) ) 
-                       {
-                               fputs( "failed to remove the service ...\n", stderr  );
-                               return EXIT_FAILURE;
-                       }
-                       fputs( "service has been removed ...\n", stderr );
-                       return EXIT_SUCCESS;
-               }
-               if ( _stricmp( "service", argv[1] ) == 0 )
-               {
-                       is_NT_Service = 1;
-                       *fname_start = '\0';
-                       SetCurrentDirectory( filename );
-               }
-       }
-
-       if (is_NT_Service)
-       {
-               StartServiceCtrlDispatcher(DispatchTable);
-       } else
-       {
-               ServiceMain( argc, argv );
-       }
-
-       return EXIT_SUCCESS;
-}
-
-#endif
diff --git a/servers/slurpd/proto-slurp.h b/servers/slurpd/proto-slurp.h
deleted file mode 100644 (file)
index b213867..0000000
+++ /dev/null
@@ -1,113 +0,0 @@
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 1998-2007 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>.
- */
-/* Portions Copyright (c) 1996 Regents of the University of Michigan.  
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that this notice is preserved and that due credit is given
- * to the University of Michigan at Ann Arbor. The name of the University
- * may not be used to endorse or promote products derived from this
- * software without specific prior written permission. This software
- * is provided ``as is'' without express or implied warranty.
- */
-/* ACKNOWLEDGEMENTS:
- * This work was originally developed by the University of Michigan
- * (as part of U-MICH LDAP).
- */
-
-#ifndef _PROTO_SLURP
-#define _PROTO_SLURP
-
-#include <ldap_cdefs.h>
-
-struct globals;
-
-/* admin.c */
-RETSIGTYPE do_admin    LDAP_P((int sig));
-
-/* args.c */
-int doargs     LDAP_P((int argc, char **argv, struct globals *g));
-
-/* ch_malloc.c */
-#ifdef CSRIMALLOC
-#define ch_malloc malloc
-#define ch_realloc realloc
-#define ch_calloc calloc
-#define ch_strdup strdup
-#define ch_free free
-#else
-void *ch_malloc        LDAP_P((ber_len_t size));
-void *ch_realloc       LDAP_P((void *block, ber_len_t size));
-void *ch_calloc        LDAP_P((ber_len_t nelem, ber_len_t size));
-char *ch_strdup LDAP_P((const char *str));
-void ch_free   LDAP_P((void *p));
-#endif
-
-/* config.c */
-int slurpd_read_config LDAP_P((char *fname));
-
-extern char *slurpd_pid_file;
-extern char *slurpd_args_file;
-
-/* ch_malloc.c */
-void ch_free LDAP_P(( void *p ));
-
-/* fm.c */
-void *fm       LDAP_P((void *arg));
-RETSIGTYPE do_nothing  LDAP_P((int i));
-RETSIGTYPE slurp_set_shutdown LDAP_P((int));
-
-/* globals.c */
-extern struct globals *sglob;
-extern int ldap_syslog;
-extern int ldap_syslog_level;
-extern int ldap_debug;
-extern struct globals *init_globals    LDAP_P((void));
-
-/* ldap_op.c */
-int do_ldap    LDAP_P((Ri *ri, Re *re, char **errmsg, int *errfree));
-
-/* lock.c */
-FILE *lock_fopen       LDAP_P((const char *fname, const char *type, FILE **lfp));
-int lock_fclose        LDAP_P((FILE *fp, FILE *lfp));
-int acquire_lock       LDAP_P((const char *file, FILE **rfp, FILE **lfp));
-int relinquish_lock    LDAP_P((const char *file, FILE *rfp, FILE *lfp));
-
-/* reject.c */
-void write_reject      LDAP_P((Ri *ri, Re *re, int lderr, char *errmsg));
-
-/* replica.c */
-int start_replica_thread       LDAP_P((Ri *ri));
-
-/* replog.c */
-int copy_replog        LDAP_P((char *src, char *dst));
-int file_nonempty      LDAP_P((char *filename));
-
-/* sanity.c */
-int sanity     LDAP_P((void));
-
-/* st.c */
-int St_init    LDAP_P((St **st));
-
-/* tsleep.c */
-int tsleep     LDAP_P((time_t interval));
-#if defined( HAVE_LWP )
-void start_lwp_scheduler LDAP_P(( void ));
-#endif
-
-/*main.c */
-extern const char Versionstr[];
-
-#endif /* _PROTO_SLURP */
diff --git a/servers/slurpd/re.c b/servers/slurpd/re.c
deleted file mode 100644 (file)
index e0d4ddd..0000000
+++ /dev/null
@@ -1,793 +0,0 @@
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 1998-2007 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>.
- */
-/* Portions Copyright (c) 1996 Regents of the University of Michigan.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that this notice is preserved and that due credit is given
- * to the University of Michigan at Ann Arbor. The name of the University
- * may not be used to endorse or promote products derived from this
- * software without specific prior written permission. This software
- * is provided ``as is'' without express or implied warranty.
- */
-/* ACKNOWLEDGEMENTS:
- * This work was originally developed by the University of Michigan
- * (as part of U-MICH LDAP).
- */
-
-/* 
- * re.c - routines which deal with Re (Replication entry) structures.
- * An Re struct is an in-core representation of one replication to
- * be performed, along with member functions which are called by other
- * routines.  The Re struct is defined in slurp.h.
- */
-
-
-#include "portable.h"
-
-#include <stdio.h>
-
-#include <ac/stdlib.h>
-#include <ac/errno.h>
-#include <ac/socket.h>
-#include <ac/string.h>
-#include <ac/ctype.h>
-
-#include "../slapd/slap.h"
-
-#include "slurp.h"
-#include "globals.h"
-#include "lutil.h"
-
-/* Forward references */
-static Rh      *get_repl_hosts LDAP_P(( char *, int *, char ** ));
-static int     gettype LDAP_P(( char * ));
-static int     getchangetype LDAP_P(( char * ));
-static int     Re_parse LDAP_P(( Re *re, char *replbuf ));
-static void    Re_dump LDAP_P(( Re *re, FILE *fp ));
-static void    warn_unknown_replica LDAP_P(( char *, int port ));
-
-/* Globals, scoped within this file */
-static int     nur = 0;        /* Number of unknown replicas */
-static Rh      *ur = NULL;     /* array of unknown replica names */
-
-
-/*
- * Return the next Re in a linked list.
- */
-static Re *
-Re_getnext(
-    Re *re
-)
-{
-    return(( re == NULL ) ? NULL :  re->re_next );
-}
-
-
-
-
-/*
- * Free an Re
- * ??? Something should apparently return nonzero here, but I dont know what.
- */
-static int
-Re_free(
-    Re *re
-)
-{
-    Rh *rh;
-    Mi *mi;
-    int        i;
-
-    if ( re == NULL ) {
-       return 0;
-    }
-    if ( re->re_refcnt > 0 ) {
-       Debug( LDAP_DEBUG_ANY,
-               "Warning: freeing re (dn: %s) with nonzero refcnt\n",
-               re->re_dn, 0, 0 );
-    }
-
-    ldap_pvt_thread_mutex_destroy( &re->re_mutex );
-
-    if (( rh = re->re_replicas ) != NULL ) {
-       for ( i = 0; rh[ i ].rh_hostname != NULL; i++ ) {
-           free( rh[ i ].rh_hostname );
-       }
-       free( rh );
-    }
-    ch_free( re->re_dn );
-    if (( mi = re->re_mods ) != NULL ) {
-       for ( i = 0; mi[ i ].mi_type != NULL; i++ ) {
-           free( mi[ i ].mi_type );
-           ch_free( mi[ i ].mi_val );
-       }
-       free( mi );
-    }
-    free( re );
-    return 0;
-}
-
-
-
-
-/*
- * Read a buffer of data from a replication log file and fill in
- * an (already allocated) Re.
- */
-
-#define        BEGIN           0
-#define        GOT_DN          1
-#define        GOT_TIME        2
-#define        GOT_CHANGETYPE  4
-#define        GOT_ALL         ( GOT_DN | GOT_TIME | GOT_CHANGETYPE )
-
-static int
-Re_parse(
-    Re         *re,
-    char       *replbuf
-)
-{
-    int                        state;
-    int                        nml;
-    char               *buf, *rp, *p;
-    size_t             buflen;
-    char               *type, *value;
-    ber_len_t  len;
-    int                        nreplicas;
-
-    if ( re == NULL ) {
-       Debug( LDAP_DEBUG_ANY, "Re_parse: error: re is NULL\n", 0, 0, 0 );
-       return -1;
-    }
-    if ( replbuf == NULL ) {
-       Debug( LDAP_DEBUG_ANY, "Re_parse: error: replbuf is NULL\n", 0, 0, 0 );
-       return -1;
-    }
-
-    state = BEGIN;
-    nml = 0;   /* number of modification information entries */
-    rp = replbuf;
-
-    re->re_replicas = get_repl_hosts( replbuf, &nreplicas, &rp );
-    re->re_refcnt = sglob->num_replicas;
-
-    for (;;) {
-       if (( state == GOT_ALL ) || ( buf = ldif_getline( &rp )) == NULL ) {
-           break;
-       }
-       /*
-        * If we're processing a rejection log, then the first line
-        * of each replication record will begin with "ERROR" - just
-        * ignore it.
-        */
-       if ( strncmp( buf, ERROR_STR, strlen( ERROR_STR )) == 0 ) {
-           continue;
-       }
-       buflen = strlen( buf );
-       if ( ldif_parse_line( buf, &type, &value, &len ) < 0 ) {
-           Debug( LDAP_DEBUG_ANY,
-                   "Error: Re_parse: malformed replog file\n",
-                   0, 0, 0 );
-           return -1;
-       }
-       switch ( gettype( type )) {
-       case T_CHANGETYPE:
-           re->re_changetype = getchangetype( value );
-           state |= GOT_CHANGETYPE;
-           break;
-       case T_TIME: {
-           unsigned long       t;
-
-           if (( p = strchr( value, '.' )) != NULL ) {
-               /* there was a sequence number */
-               *p++ = '\0';
-           }
-           if ( lutil_atoul( &t, value ) != 0 ) {
-               Debug( LDAP_DEBUG_ANY,
-                       "Error: Re_parse: unable to parse timestamp \"%s\"\n",
-                       value, 0, 0 );
-               return -1;
-           }
-           re->re_timestamp = (time_t)t;
-           if ( p != NULL && isdigit( (unsigned char) *p )
-               && lutil_atoi( &re->re_seq, p ) != 0 )
-           {
-               Debug( LDAP_DEBUG_ANY,
-                       "Error: Re_parse: unable to parse sequence number \"%s\"\n",
-                       p, 0, 0 );
-               return -1;
-           }
-           state |= GOT_TIME;
-           } break;
-       case T_DN:
-           re->re_dn = ch_malloc( len + 1 );
-               AC_MEMCPY( re->re_dn, value, len );
-               re->re_dn[ len ]='\0';
-           state |= GOT_DN;
-           break;
-       default:
-           if ( !( state == GOT_ALL )) {
-               Debug( LDAP_DEBUG_ANY,
-                       "Error: Re_parse: bad type <%s>\n",
-                       type, 0, 0 );
-               free( type );
-               free( value );
-               return -1;
-           }
-       }
-       free( type );
-       free( value );
-    }
-
-    if ( state != GOT_ALL ) {
-       Debug( LDAP_DEBUG_ANY,
-               "Error: Re_parse: malformed replog file\n",
-               0, 0, 0 );
-       return -1;
-    }
-
-    for (;;) {
-       char *const dash = "-";
-
-       if (( buf = ldif_getline( &rp )) == NULL ) {
-           break;
-       }
-       buflen = strlen( buf );
-       if (( buflen == 1 ) && ( buf[ 0 ] == '-' )) {
-           type  = dash;
-           value = NULL;
-       } else {
-           if ( ldif_parse_line( buf, &type, &value, &len ) < 0 ) {
-               Debug( LDAP_DEBUG_ANY,
-                       "Error: malformed replog line \"%s\"\n",
-                       buf, 0, 0 );
-               return -1;
-           }
-       }
-       re->re_mods = ( Mi  *) ch_realloc( (char *) re->re_mods,
-           sizeof( Mi ) * ( nml + 2 ));
-       re->re_mods[ nml ].mi_type = strdup( type );
-       if ( value != NULL ) {
-           re->re_mods[ nml ].mi_val = ch_malloc( len + 1 );
-               AC_MEMCPY( re->re_mods[ nml ].mi_val, value, len );
-               re->re_mods[ nml ].mi_val[ len ] = '\0';
-           re->re_mods[ nml ].mi_len = len;
-       } else {
-           re->re_mods[ nml ].mi_val = NULL;
-           re->re_mods[ nml ].mi_len = 0;
-       }
-       re->re_mods[ nml + 1 ].mi_type = NULL;
-       re->re_mods[ nml + 1 ].mi_val = NULL;
-       nml++;
-
-       if ( type != dash )
-               free( type );
-       if ( value != NULL )
-               free( value );
-    }
-    return 0;
-}
-
-
-
-/*
- * Extract the replication hosts from a repl buf.  Check to be sure that
- * each replica host and port number are ones we know about (that is, they're
- * in the slapd config file we read at startup).  Without that information
- * from the config file, we won't have the appropriate credentials to
- * make modifications.  If there are any unknown replica names, don't
- * add them the the Re struct.  Instead, log a warning message.
- */
-static Rh *
-get_repl_hosts(
-    char       *replbuf,
-    int                *r_nreplicas,
-    char       **r_rp
-)
-{
-    char               *type, *value, *line, *p;
-    Rh                 *rh = NULL;
-    int                        nreplicas;
-       ber_len_t       len;
-    int                        port;
-    int                        repl_ok;
-    int                        i;
-
-    if ( replbuf == NULL ) {
-       return( NULL );
-    }
-
-    nreplicas = 0;
-
-    /*
-     * Get the host names of the replicas
-     */
-    *r_nreplicas = 0;
-    *r_rp = replbuf;
-    for (;;) {
-       /* If this is a reject log, we need to skip over the ERROR: line */
-       if ( !strncmp( *r_rp, ERROR_STR, strlen( ERROR_STR ))) {
-           line = ldif_getline( r_rp );
-           if ( line == NULL ) {
-               break;
-           }
-       }
-       if ( strncasecmp( *r_rp, "replica:", 7 )) {
-           break;
-       }
-       line = ldif_getline( r_rp );
-       if ( line == NULL ) {
-           break;
-       }
-       if ( ldif_parse_line( line, &type, &value, &len ) < 0 ) {
-           return( NULL );
-       }
-       port = LDAP_PORT;
-       if (( p = strchr( value, ':' )) != NULL ) {
-           *p = '\0';
-           p++;
-           if ( *p != '\0' && lutil_atoi( &port, p ) != 0 ) {
-               return( NULL );
-           }
-       }
-
-       /* Verify that we've heard of this replica before */
-       repl_ok = 0;
-       for ( i = 0; i < sglob->num_replicas; i++ ) {
-           if ( strcmp( sglob->replicas[ i ]->ri_hostname, value )) {
-               continue;
-           }
-           if ( sglob->replicas[ i ]->ri_port == port ) {
-               repl_ok = 1;
-               break;
-           }
-       }
-       free( type );
-       if ( !repl_ok ) {
-           warn_unknown_replica( value, port );
-           free( value );
-           continue;
-       }
-
-       rh = (Rh *) ch_realloc((char *) rh, ( nreplicas + 2 ) * sizeof( Rh ));
-       if ( rh == NULL ) {
-           Debug( LDAP_DEBUG_ANY, "Out of memory in get_repl_hosts\n",
-                   0, 0, 0 );
-           return NULL;
-       }
-       rh[ nreplicas ].rh_hostname = strdup( value );
-       rh[ nreplicas ].rh_port = port;
-       nreplicas++;
-
-       free( value );
-    }
-
-    if ( nreplicas == 0 ) {
-       return( NULL );
-    }
-
-    rh[ nreplicas ].rh_hostname = NULL;
-    *r_nreplicas = nreplicas;
-
-    return( rh );
-}
-
-
-
-
-
-/*
- * Convert "type" to an int.
- */
-static int
-gettype(
-    char       *type
-)
-{
-    if ( !strcmp( type, T_CHANGETYPESTR )) {
-       return( T_CHANGETYPE );
-    }
-    if ( !strcmp( type, T_TIMESTR )) {
-       return( T_TIME );
-    }
-    if ( !strcmp( type, T_DNSTR )) {
-       return( T_DN );
-    }
-    return( T_ERR );
-}
-
-
-
-/*
- * Convert "changetype" to an int.
- */
-static int
-getchangetype(
-    char       *changetype
-)
-{
-    if ( !strcmp( changetype, T_ADDCTSTR )) {
-       return( T_ADDCT );
-    }
-    if ( !strcmp( changetype, T_MODIFYCTSTR )) {
-       return( T_MODIFYCT );
-    }
-    if ( !strcmp( changetype, T_DELETECTSTR )) {
-       return( T_DELETECT );
-    }
-    if ( !strcmp( changetype, T_MODRDNCTSTR )) {
-       return( T_MODRDNCT );
-    }
-    return( T_ERR );
-}
-
-
-
-
-#if 0
-/*
- * Find the first line which is not a "replica:" line in buf.
- * Returns a pointer to the line.  Returns NULL if there are
- * only "replica:" lines in buf.
- */
-static char *
-skip_replica_lines(
-    char       *buf
-)
-{
-    char *p = buf;
-    for (;;) {
-       if ( strncasecmp( p, "replica:", 8 )) {
-           return( p );
-       }
-       while (( *p != '\0' )  && ( *p != '\n' )) {
-           p++;
-       }
-       if ( *p == '\0' ) {
-           return ( NULL );
-       } else {
-           p++;
-       }
-    }
-}
-#endif /* 0 */
-
-
-
-
-/*
- * For debugging purposes: dump the contents of a replication entry.
- * to the given stream.
- */
-static void
-Re_dump(
-    Re         *re,
-    FILE       *fp
-)
-{
-    int i;
-    Mi *mi;
-
-    if ( re == NULL ) {
-       Debug( LDAP_DEBUG_TRACE, "Re_dump: re is NULL\n", 0, 0, 0 );
-       return;
-    }
-    fprintf( fp, "Re_dump: ******\n" );
-    fprintf( fp, "re_refcnt: %d\n", re->re_refcnt );
-    fprintf( fp, "re_timestamp: %ld\n", (long) re->re_timestamp );
-    fprintf( fp, "re_seq: %d\n", re->re_seq );
-    for ( i = 0; re->re_replicas && re->re_replicas[ i ].rh_hostname != NULL;
-               i++ ) {
-       fprintf( fp, "re_replicas[%d]: %s:%d\n", 
-               i, re->re_replicas[ i ].rh_hostname,
-               re->re_replicas[ i ].rh_port );
-    }
-    fprintf( fp, "re_dn: %s\n", re->re_dn );
-    switch ( re->re_changetype ) {
-    case T_ADDCT:
-       fprintf( fp, "re_changetype: add\n" );
-       break;
-    case T_MODIFYCT:
-       fprintf( fp, "re_changetype: modify\n" );
-       break;
-    case T_DELETECT:
-       fprintf( fp, "re_changetype: delete\n" );
-       break;
-    case T_MODRDNCT:
-       fprintf( fp, "re_changetype: modrdn\n" );
-       break;
-    default:
-       fprintf( fp, "re_changetype: (unknown, type = %d\n",
-               re->re_changetype );
-    }
-    if ( re->re_mods == NULL ) {
-       fprintf( fp, "re_mods: (none)\n" );
-    } else {
-       mi = re->re_mods;
-       fprintf( fp, "re_mods:\n" );
-       for ( i = 0; mi[ i ].mi_type != NULL; i++ ) {
-           fprintf( fp, "  %s, \"%s\", (%d bytes)\n",
-                   mi[ i ].mi_type,
-                   mi[ i ].mi_val == NULL ?  "(null)" : mi[ i ].mi_val,
-                   mi[ i ].mi_len );
-       }
-    }
-    return;
-}
-
-
-/* 
- * Given an Ri, an Re, and a file pointer, write a replication record to
- * the file pointer.  If ri is NULL, then include all replicas in the
- * output.  If ri is non-NULL, then only include a single "replica:" line
- * (used when writing rejection records).  Returns 0 on success, -1
- * on failure.  Note that Re_write will not write anything out if the
- * refcnt is zero.
- */
-static int
-Re_write(
-    Ri         *ri,
-    Re         *re,
-    FILE       *fp )
-{
-    int                i;
-    char       *s;
-    int                rc = 0;
-
-    if ( re == NULL || fp == NULL ) {
-       Debug( LDAP_DEBUG_ANY, "Internal error: Re_write: NULL argument\n",
-               0, 0, 0 );
-       return -1;
-    }
-
-    if ( re->re_refcnt < 1 ) {
-       return 0;               /* this is not an error */
-    }
-
-    if ( ri != NULL ) {                /* write a single "replica:" line */
-       if ( ri->ri_port != 0 ) {
-           rc = fprintf( fp, "replica: %s:%d\n", ri->ri_hostname,
-                   ri->ri_port );
-       } else {
-           rc = fprintf( fp, "replica: %s\n", ri->ri_hostname );
-       }
-       if ( rc < 0 ) {
-           rc = -1;
-           goto bad;
-       }
-       rc = 0;
-
-    } else {                   /* write multiple "replica:" lines */
-       for ( i = 0; re->re_replicas && re->re_replicas[ i ].rh_hostname != NULL; i++ ) {
-           if ( fprintf( fp, "replica: %s:%d\n",
-                   re->re_replicas[ i ].rh_hostname,
-                   re->re_replicas[ i ].rh_port ) < 0 ) {
-               rc = -1;
-               goto bad;
-           }
-       }
-    }
-    if ( fprintf( fp, "time: %ld.%d\n", (long) re->re_timestamp, re->re_seq ) < 0 ) {
-       rc = -1;
-       goto bad;
-    }
-    if ( fprintf( fp, "dn: %s\n", re->re_dn ) < 0 ) {
-       rc = -1;
-       goto bad;
-    }
-    if ( fprintf( fp, "changetype: " ) < 0 ) {
-       rc = -1;
-       goto bad;
-    }
-    switch ( re->re_changetype ) {
-    case T_ADDCT:
-       s = T_ADDCTSTR;
-       break;
-    case T_MODIFYCT:
-       s = T_MODIFYCTSTR;
-       break;
-    case T_DELETECT:
-       s = T_DELETECTSTR;
-       break;
-    case T_MODRDNCT:
-       s = T_MODRDNCTSTR;
-       break;
-    default:
-       s = "IllegalModifyType!!!";
-    }
-    if ( fprintf( fp, "%s\n", s ) < 0 ) {
-       rc = -1;
-       goto bad;
-    }
-    for ( i = 0; (( re->re_mods != NULL ) &&
-           ( re->re_mods[ i ].mi_type != NULL )); i++ ) {
-       if ( !strcmp( re->re_mods[ i ].mi_type, T_MODSEPSTR )) {
-           if ( fprintf( fp, "%s\n", T_MODSEPSTR ) < 0 ) {
-               rc = -1;
-               goto bad;
-           }
-       } else {
-           char *obuf;
-           obuf = ldif_put( LDIF_PUT_VALUE,
-                       re->re_mods[ i ].mi_type,
-                   re->re_mods[ i ].mi_val ? re->re_mods[ i ].mi_val : "",
-                   re->re_mods[ i ].mi_len );
-           if ( fputs( obuf, fp ) < 0 ) {
-               rc = -1;
-               free( obuf );
-               goto bad;
-           } else {
-               ber_memfree( obuf );
-           }
-       }
-    }
-    if ( fprintf( fp, "\n" ) < 0 ) {
-       rc = -1;
-       goto bad;
-    }
-    if ( fflush( fp ) != 0 ) {
-       rc = -1;
-       goto bad;
-    }
-bad:
-    if ( rc != 0 ) {
-       Debug( LDAP_DEBUG_ANY, "Error while writing: %s\n",
-               sys_errlist[ errno ], 0, 0 );
-    }
-    return rc;
-}
-
-
-
-
-/*
- * Decrement the refcnt.  Locking handled internally.
- */
-static int
-Re_decrefcnt(
-    Re *re
-)
-{
-    re->re_lock( re );
-    re->re_refcnt--;
-    re->re_unlock( re );
-    return 0;
-}
-
-
-
-/*
- * Get the refcnt.  Locking handled internally.
- */
-static int
-Re_getrefcnt(
-    Re *re
-)
-{
-    int        ret;
-
-    re->re_lock( re );
-    ret = re->re_refcnt;
-    re->re_unlock( re );
-    return ret;
-}
-    
-    
-
-
-
-/*
- * Lock this replication entry
- */
-static int
-Re_lock(
-    Re *re
-)
-{
-    return( ldap_pvt_thread_mutex_lock( &re->re_mutex ));
-}
-
-
-
-
-/*
- * Unlock this replication entry
- */
-static int
-Re_unlock(
-    Re *re
-)
-{
-    return( ldap_pvt_thread_mutex_unlock( &re->re_mutex ));
-}
-
-
-
-
-/* 
- * Instantiate and initialize an Re.
- */
-int
-Re_init(
-    Re **re
-)
-{
-    /* Instantiate */
-    (*re) = (Re *) malloc( sizeof( Re ));
-    if ( *re == NULL ) {
-       return -1;
-    }
-
-    /* Fill in the member function pointers */
-    (*re)->re_free = Re_free;
-    (*re)->re_getnext = Re_getnext;
-    (*re)->re_parse = Re_parse;
-    (*re)->re_write = Re_write;
-    (*re)->re_dump = Re_dump;
-    (*re)->re_lock = Re_lock;
-    (*re)->re_unlock = Re_unlock;
-    (*re)->re_decrefcnt = Re_decrefcnt;
-    (*re)->re_getrefcnt = Re_getrefcnt;
-
-    /* Initialize private data */
-   (*re)->re_refcnt = sglob->num_replicas;
-   (*re)->re_timestamp = (time_t) 0L;
-   (*re)->re_replicas = NULL;
-   (*re)->re_dn = NULL;
-   (*re)->re_changetype = 0;
-   (*re)->re_seq = 0;
-   (*re)->re_mods = NULL;
-   (*re)->re_next = NULL;
-
-   ldap_pvt_thread_mutex_init( &((*re)->re_mutex) );
-   return 0;
-}
-
-
-
-
-/*
- * Given a host and port, generate a warning message iff we haven't already
- * generated a message for this host:port combination.
- */
-static void
-warn_unknown_replica( 
-    char       *host,
-    int                port
-)
-{
-    int        found = 0;
-    int        i;
-
-    for ( i = 0; i < nur; i++ ) {
-       if ( strcmp( ur[ i ].rh_hostname, host )) {
-           continue;
-       }
-       if ( ur[ i ].rh_port == port ) {
-           found = 1;
-           break;
-       }
-    }
-    if ( !found ) {
-       Debug( LDAP_DEBUG_ANY,
-               "Warning: unknown replica %s:%d found in replication log\n",
-               host, port, 0 );
-       nur++;
-       ur = (Rh *) ch_realloc( (char *) ur, ( nur * sizeof( Rh )));
-       ur[ nur - 1 ].rh_hostname = strdup( host );
-       ur[ nur - 1 ].rh_port = port;
-    }
-}
diff --git a/servers/slurpd/reject.c b/servers/slurpd/reject.c
deleted file mode 100644 (file)
index 9eeac4f..0000000
+++ /dev/null
@@ -1,155 +0,0 @@
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 1998-2007 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>.
- */
-/* Portions Copyright (c) 1996 Regents of the University of Michigan.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that this notice is preserved and that due credit is given
- * to the University of Michigan at Ann Arbor. The name of the University
- * may not be used to endorse or promote products derived from this
- * software without specific prior written permission. This software
- * is provided ``as is'' without express or implied warranty.
- */
-/* ACKNOWLEDGEMENTS:
- * This work was originally developed by the University of Michigan
- * (as part of U-MICH LDAP).
- */
-
-
-/*
- * reject.c - routines to write replication records to reject files.
- * An Re struct is writted to a reject file if it cannot be propagated
- * to a replica LDAP server.
- */
-
-#include "portable.h"
-
-#include <stdio.h>
-
-#include <ac/stdlib.h>
-#include <ac/string.h>
-#include <ac/errno.h>
-#include <ac/unistd.h>
-
-#include <sys/stat.h>
-#include <fcntl.h>
-
-#include "slurp.h"
-#include "globals.h"
-
-#include "lber_pvt.h"
-#include "lutil.h"
-
-#ifdef _WIN32
-#define        PORTSEP ","
-#else
-#define        PORTSEP ":"
-#endif
-
-/*
- * Write a replication record to a reject file.  The reject file has the
- * same name as the replica's private copy of the file but with ".rej"
- * appended (e.g. "/usr/tmp/<hostname>:<port>.rej")
- *
- * If errmsg is non-NULL, use that as the error message in the reject
- * file.  Otherwise, use ldap_err2string( lderr ).
- */
-void
-write_reject(
-    Ri         *ri,
-    Re         *re,
-    int                lderr,
-    char       *errmsg
-)
-{
-    char       rejfile[ MAXPATHLEN ];
-    FILE       *rfp, *lfp;
-    int                rc;
-
-    ldap_pvt_thread_mutex_lock( &sglob->rej_mutex );
-    snprintf( rejfile, sizeof rejfile, "%s" LDAP_DIRSEP "%s" PORTSEP "%d.rej",
-               sglob->slurpd_rdir, ri->ri_hostname, ri->ri_port );
-
-    if ( access( rejfile, F_OK ) < 0 ) {
-       /* Doesn't exist - try to create */
-       int rjfd;
-       if (( rjfd = open( rejfile, O_RDWR|O_APPEND|O_CREAT|O_EXCL,
-               S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP )) < 0 ) {
-           Debug( LDAP_DEBUG_ANY,
-               "Error: write_reject: Cannot create \"%s\": %s\n",
-               rejfile, sys_errlist[ errno ], 0 );
-           ldap_pvt_thread_mutex_unlock( &sglob->rej_mutex );
-           return;
-       } else {
-           close( rjfd );
-       }
-    }
-    if (( rc = acquire_lock( rejfile, &rfp, &lfp )) < 0 ) {
-       Debug( LDAP_DEBUG_ANY, "Error: cannot open reject file \"%s\"\n",
-               rejfile, 0, 0 );
-    } else {
-       struct berval   bv = BER_BVNULL,
-                       errstrbv,
-                       errmsgbv = BER_BVNULL;
-       char            *ptr;
-
-       ber_str2bv( ldap_err2string( lderr ), 0, 0, &errstrbv );
-       if ( errmsg && *errmsg ) {
-               ber_str2bv( errmsg, 0, 0, &errmsgbv );
-               bv.bv_len = errstrbv.bv_len
-                       + STRLENOF( ": " ) + errmsgbv.bv_len;
-
-               ptr = bv.bv_val = ber_memalloc( bv.bv_len + 1 );
-               ptr = lutil_strcopy( ptr, errstrbv.bv_val );
-               ptr = lutil_strcopy( ptr, ": " );
-               ptr = lutil_strcopy( ptr, errmsgbv.bv_val );
-
-       } else {
-               bv = errstrbv;
-       }
-
-       fseek( rfp, 0, 2 );
-
-       ptr = ldif_put( LDIF_PUT_VALUE, ERROR_STR, bv.bv_val, bv.bv_len );
-       if ( bv.bv_val != errstrbv.bv_val ) {
-               ber_memfree( bv.bv_val );
-       }
-       if ( ptr == NULL ) {
-               Debug( LDAP_DEBUG_ANY,
-                       "Error: cannot convert error message(s) \"%s%s%s\" "
-                       "into LDIF format\n",
-                       errstrbv.bv_val,
-                       BER_BVISNULL( &errmsgbv ) ? "" : ": ",
-                       BER_BVISNULL( &errmsgbv ) ? "" : errmsgbv.bv_val );
-               return;
-       }
-
-       fputs( ptr, rfp );
-       ber_memfree( ptr );
-
-       if ((rc = re->re_write( ri, re, rfp )) < 0 ) {
-           Debug( LDAP_DEBUG_ANY,
-                   "Error: cannot write reject file \"%s\"\n",
-                   rejfile, 0, 0 );
-       }
-       (void) relinquish_lock( rejfile, rfp, lfp );
-       Debug( LDAP_DEBUG_ANY,
-               "Error: ldap operation failed, data written to \"%s\"\n",
-               rejfile, 0, 0 );
-    }
-    ldap_pvt_thread_mutex_unlock( &sglob->rej_mutex );
-    return;
-}
-
diff --git a/servers/slurpd/replica.c b/servers/slurpd/replica.c
deleted file mode 100644 (file)
index 4702d10..0000000
+++ /dev/null
@@ -1,83 +0,0 @@
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 1998-2007 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>.
- */
-/* Portions Copyright (c) 1996 Regents of the University of Michigan.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that this notice is preserved and that due credit is given
- * to the University of Michigan at Ann Arbor. The name of the University
- * may not be used to endorse or promote products derived from this
- * software without specific prior written permission. This software
- * is provided ``as is'' without express or implied warranty.
- */
-/* ACKNOWLEDGEMENTS:
- * This work was originally developed by the University of Michigan
- * (as part of U-MICH LDAP).
- */
-
-
-/*
- * replica.c - code to start up replica threads.
- */
-
-#include "portable.h"
-
-#include <stdio.h>
-#include <ac/stdlib.h>
-
-#include "slurp.h"
-#include "globals.h"
-
-/*
- * Just invoke the Ri's process() member function, and log the start and
- * finish.
- */
-static void *
-replicate(
-    void       *ri_arg
-)
-{
-    Ri         *ri = (Ri *) ri_arg;
-
-    Debug( LDAP_DEBUG_ARGS, "begin replication thread for %s:%d\n",
-           ri->ri_hostname, ri->ri_port, 0 );
-
-    ri->ri_process( ri );
-
-    Debug( LDAP_DEBUG_ARGS, "end replication thread for %s:%d\n",
-           ri->ri_hostname, ri->ri_port, 0 );
-    return NULL;
-}
-
-
-
-/*
- * Start a detached thread for the given replica.
- */
-int
-start_replica_thread(
-    Ri *ri
-)
-{
-    /* POSIX_THREADS or compatible */
-    if ( ldap_pvt_thread_create( &(ri->ri_tid), 0, replicate,
-           (void *) ri ) != 0 ) {
-       Debug( LDAP_DEBUG_ANY, "replica \"%s:%d\" ldap_pvt_thread_create failed\n",
-               ri->ri_hostname, ri->ri_port, 0 );
-       return -1;
-    }
-
-    return 0;
-}
diff --git a/servers/slurpd/replog.c b/servers/slurpd/replog.c
deleted file mode 100644 (file)
index e4bf325..0000000
+++ /dev/null
@@ -1,169 +0,0 @@
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 1998-2007 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>.
- */
-/* Portions Copyright (c) 1996 Regents of the University of Michigan.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that this notice is preserved and that due credit is given
- * to the University of Michigan at Ann Arbor. The name of the University
- * may not be used to endorse or promote products derived from this
- * software without specific prior written permission. This software
- * is provided ``as is'' without express or implied warranty.
- */
-/* ACKNOWLEDGEMENTS:
- * This work was originally developed by the University of Michigan
- * (as part of U-MICH LDAP).
- */
-
-
-/*
- * replog.c - routines which read and write replication log files.
- */
-
-#include "portable.h"
-
-#include <stdio.h>
-
-#include <ac/stdlib.h>
-#include <ac/errno.h>
-#include <ac/param.h>
-#include <ac/string.h>
-#include <ac/syslog.h>
-#include <ac/time.h>
-#include <ac/unistd.h>
-
-#include <sys/stat.h>
-
-#include <fcntl.h>
-
-#include "slurp.h"
-#include "globals.h"
-
-/*
- * Copy the replication log.  Returns 0 on success, 1 if a temporary
- * error occurs, and -1 if a fatal error occurs.
- */
-int
-copy_replog(
-    char       *src,
-    char       *dst
-)
-{
-    int                rc = 0;
-    FILE       *rfp;   /* replog fp */
-    FILE       *lfp;   /* replog lockfile fp */
-    FILE       *dfp;   /* duplicate replog fp */
-    FILE       *dlfp;  /* duplicate replog lockfile fp */
-    static char        buf[ MAXPATHLEN ];
-    static char        rbuf[ 1024 ];
-    char       *p;
-
-    Debug( LDAP_DEBUG_ARGS,
-           "copy replog \"%s\" to \"%s\"\n", 
-           src, dst, 0 );
-
-    /*
-     * Make sure the destination directory is writable.  If not, exit
-     * with a fatal error.
-     */
-    strcpy( buf, src );
-    if (( p = strrchr( buf, LDAP_DIRSEP[0] )) == NULL ) {
-       strcpy( buf, "." );
-    } else {
-       *p = '\0';
-    }
-    if ( access( buf, W_OK ) < 0 ) {
-       Debug( LDAP_DEBUG_ANY,
-               "Error: copy_replog (%ld): Directory %s is not writable\n",
-               (long) getpid(), buf, 0 );
-       return( -1 );
-    }
-    strcpy( buf, dst );
-    if (( p = strrchr( buf, LDAP_DIRSEP[0] )) == NULL ) {
-       strcpy( buf, "." );
-    } else {
-       *p = '\0';
-    }
-    if ( access( buf, W_OK ) < 0 ) {
-       Debug( LDAP_DEBUG_ANY,
-               "Error: copy_replog (%ld): Directory %s is not writable\n",
-               (long) getpid(), buf, 0 );
-       return( -1 );
-    }
-
-    /* lock src */
-    rfp = lock_fopen( src, "r", &lfp );
-    if ( rfp == NULL ) {
-       Debug( LDAP_DEBUG_ANY,
-               "Error: copy_replog: Can't lock replog \"%s\" for read: %s\n",
-               src, sys_errlist[ errno ], 0 );
-       return( 1 );
-    }
-
-    /* lock dst */
-    dfp = lock_fopen( dst, "a", &dlfp );
-    if ( dfp == NULL ) {
-               Debug( LDAP_DEBUG_ANY,
-                       "Error: copy_replog: Can't lock replog \"%s\" for write: %s\n",
-                       dst, sys_errlist[ errno ], 0 );
-       lock_fclose( rfp, lfp );
-       return( 1 );
-    }
-
-    /*
-     * Make our own private copy of the replication log.
-     */
-    while (( p = fgets( rbuf, sizeof( rbuf ), rfp )) != NULL ) {
-       fputs( rbuf, dfp );
-    }
-    /* Only truncate the source file if we're not in one-shot mode */
-    if ( !sglob->one_shot_mode ) {
-       /* truncate replication log */
-       truncate( src, (off_t) 0 );
-    }
-
-    if ( lock_fclose( dfp, dlfp ) == EOF ) {
-               Debug( LDAP_DEBUG_ANY,
-                       "Error: copy_replog: Error closing \"%s\"\n",
-                       dst, 0, 0 );
-    }
-    if ( lock_fclose( rfp, lfp ) == EOF ) {
-       Debug( LDAP_DEBUG_ANY,
-               "Error: copy_replog: Error closing \"%s\"\n",
-               src, 0, 0 );
-    }
-    return( rc );
-}
-
-
-
-
-/*
- * Return 1 if the given file exists and has a nonzero size,
- * 0 if it is empty or nonexistent.
- */
-int
-file_nonempty(
-    char       *filename
-)
-{
-    static struct stat         stbuf;
-
-    if ( stat( filename, &stbuf ) < 0 ) {
-       return( 0 );
-    } else {
-       return( stbuf.st_size > (off_t ) 0 );
-    }
-}
diff --git a/servers/slurpd/ri.c b/servers/slurpd/ri.c
deleted file mode 100644 (file)
index 62062cc..0000000
+++ /dev/null
@@ -1,285 +0,0 @@
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 1998-2007 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>.
- */
-/* Portions Copyright (c) 1996 Regents of the University of Michigan.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that this notice is preserved and that due credit is given
- * to the University of Michigan at Ann Arbor. The name of the University
- * may not be used to endorse or promote products derived from this
- * software without specific prior written permission. This software
- * is provided ``as is'' without express or implied warranty.
- */
-/* ACKNOWLEDGEMENTS:
- * This work was originally developed by the University of Michigan
- * (as part of U-MICH LDAP).
- */
-
-/*
- * ri.c - routines used to manipulate Ri structures.  An Ri (Replica
- * information) struct contains all information about one replica
- * instance.  The Ri struct is defined in slurp.h
- */
-
-
-#include "portable.h"
-
-#include <stdio.h>
-
-#include <ac/stdlib.h>
-#include <ac/string.h>
-#include <ac/signal.h>
-
-#include "slurp.h"
-#include "globals.h"
-
-
-/* Forward references */
-static int ismine LDAP_P(( Ri  *, Re  * ));
-static int isnew LDAP_P(( Ri  *, Re  * ));
-
-
-/*
- * Process any unhandled replication entries in the queue.
- */
-static int
-Ri_process(
-    Ri *ri
-)
-{
-    Rq         *rq = sglob->rq;
-    Re         *re = NULL, *new_re = NULL;
-    int                rc ;
-    char       *errmsg;
-    int                errfree;
-
-    (void) SIGNAL( LDAP_SIGUSR1, do_nothing );
-#ifdef SIGPIPE
-    (void) SIGNAL( SIGPIPE, SIG_IGN );
-#endif
-    if ( ri == NULL ) {
-       Debug( LDAP_DEBUG_ANY, "Error: Ri_process: ri == NULL!\n", 0, 0, 0 );
-       return -1;
-    }
-
-    /*
-     * Startup code.  See if there's any work to do.  If not, wait on the
-     * rq->rq_more condition variable.
-     */
-    rq->rq_lock( rq );
-    while ( !sglob->slurpd_shutdown &&
-           (( re = rq->rq_gethead( rq )) == NULL )) {
-       /* No work */
-       if ( sglob->one_shot_mode ) {
-           /* give up if in one shot mode */
-           rq->rq_unlock( rq );
-           return 0;
-       }
-       /* wait on condition variable */
-       ldap_pvt_thread_cond_wait( &rq->rq_more, &rq->rq_mutex );
-    }
-
-    /*
-     * When we get here, there's work in the queue, and we have the
-     * queue locked.  re should be pointing to the head of the queue.
-     */
-    rq->rq_unlock( rq );
-    while ( !sglob->slurpd_shutdown ) {
-       if ( re != NULL ) {
-           if ( !ismine( ri, re )) {
-               /* The Re doesn't list my host:port */
-               Debug( LDAP_DEBUG_TRACE,
-                       "Replica %s:%d, skip repl record for %s (not mine)\n",
-                       ri->ri_hostname, ri->ri_port, re->re_dn );
-           } else if ( !isnew( ri, re )) {
-               /* This Re is older than my saved status information */
-               Debug( LDAP_DEBUG_TRACE,
-                       "Replica %s:%d, skip repl record for %s (old)\n",
-                       ri->ri_hostname, ri->ri_port, re->re_dn );
-           } else {
-               rc = do_ldap( ri, re, &errmsg, &errfree );
-               switch ( rc ) {
-               case DO_LDAP_ERR_RETRYABLE:
-                   ldap_pvt_thread_sleep( RETRY_SLEEP_TIME );
-                   Debug( LDAP_DEBUG_ANY,
-                           "Retrying operation for DN %s on replica %s:%d\n",
-                           re->re_dn, ri->ri_hostname, ri->ri_port );
-                   continue;
-                   break;
-               case DO_LDAP_ERR_FATAL: {
-                   /* Non-retryable error.  Write rejection log. */
-                       int ld_errno = 0;
-                       ldap_get_option(ri->ri_ldp, LDAP_OPT_RESULT_CODE, &ld_errno);
-                   write_reject( ri, re, ld_errno, errmsg );
-                   /* Update status ... */
-                   (void) sglob->st->st_update( sglob->st, ri->ri_stel, re );
-                   /* ... and write to disk */
-                   (void) sglob->st->st_write( sglob->st );
-                   } break;
-               default:
-                   /* LDAP op completed ok - update status... */
-                   (void) sglob->st->st_update( sglob->st, ri->ri_stel, re );
-                   /* ... and write to disk */
-                   (void) sglob->st->st_write( sglob->st );
-                   break;
-               }
-               if ( errfree && errmsg ) {
-                   ch_free( errmsg );
-               }
-           }
-       } else {
-           Debug( LDAP_DEBUG_ANY, "Error: re is null in Ri_process\n",
-                   0, 0, 0 );
-       }
-       rq->rq_lock( rq );
-       while ( !sglob->slurpd_shutdown &&
-               ((new_re = re->re_getnext( re )) == NULL )) {
-           if ( sglob->one_shot_mode ) {
-               rq->rq_unlock( rq );
-               return 0;
-           }
-           /* No work - wait on condition variable */
-           ldap_pvt_thread_cond_wait( &rq->rq_more, &rq->rq_mutex );
-       }
-       re->re_decrefcnt( re );
-       re = new_re;
-       rq->rq_unlock( rq );
-       if ( sglob->slurpd_shutdown ) {
-           if ( ri->ri_ldp ) {
-               ldap_unbind_ext( ri->ri_ldp, NULL, NULL );
-               ri->ri_ldp = NULL;
-           }
-           return 0;
-       }
-    }
-    return 0;
-}
-
-
-/*
- * Wake a replication thread which may be sleeping.
- * Send it a LDAP_SIGUSR1.
- */
-static void
-Ri_wake(
-    Ri *ri
-) 
-{
-    if ( ri == NULL ) {
-       return;
-    }
-    ldap_pvt_thread_kill( ri->ri_tid, LDAP_SIGUSR1 );
-}
-
-
-
-/* 
- * Allocate and initialize an Ri struct.
- */
-int
-Ri_init(
-    Ri **ri
-)
-{
-    (*ri) = ( Ri * ) calloc( 1, sizeof( Ri ));
-    if ( *ri == NULL ) {
-       return -1;
-    }
-
-    /* Initialize member functions */
-    (*ri)->ri_process = Ri_process;
-    (*ri)->ri_wake = Ri_wake;
-
-    /* Initialize private data */
-    (*ri)->ri_hostname = NULL;
-    (*ri)->ri_uri = NULL;
-    (*ri)->ri_ldp = NULL;
-    (*ri)->ri_bind_dn = NULL;
-    (*ri)->ri_password = NULL;
-    (*ri)->ri_authcId = NULL;
-    (*ri)->ri_curr = NULL;
-
-    return 0;
-}
-
-
-
-
-/*
- * Return 1 if the hostname and port in re match the hostname and port
- * in ri, otherwise return zero.
- */
-static int
-ismine(
-    Ri *ri,
-    Re *re
-)
-{
-    Rh *rh;
-    int        i;
-
-    if ( ri == NULL || re == NULL || ri->ri_hostname == NULL ||
-           re->re_replicas == NULL ) {
-       return 0;
-    }
-    rh = re->re_replicas;
-    for ( i = 0; rh[ i ].rh_hostname != NULL; i++ ) {
-       if ( !strcmp( rh[ i ].rh_hostname, ri->ri_hostname) &&
-               rh[ i ].rh_port == ri->ri_port ) {
-           return 1;
-       }
-    }
-    return 0;
-}
-
-
-
-
-/*
- * Return 1 if the Re's timestamp/seq combination are greater than the
- * timestamp and seq in the Ri's ri_stel member.  In other words, if we
- * find replication entries in the log which we've already processed,
- * don't process them.  If the re is "old," return 0.
- * No check for NULL pointers is done.
- */
-static int
-isnew(
-    Ri *ri,
-    Re *re
-)
-{
-    long x;
-    int        ret;
-
-    /* Lock the St struct to avoid a race */
-    sglob->st->st_lock( sglob->st );
-    x = re->re_timestamp - ri->ri_stel->last;
-    if ( x > 0 ) {
-       /* re timestamp is newer */
-       ret = 1;
-    } else if ( x < 0 ) {
-       ret = 0;
-    } else {
-       /* timestamps were equal */
-       if ( re->re_seq > ri->ri_stel->seq ) {
-           /* re seq is newer */
-           ret = 1;
-       } else {
-           ret = 0;
-       }
-    }
-    sglob->st->st_unlock( sglob->st );
-    return ret;
-}
diff --git a/servers/slurpd/rq.c b/servers/slurpd/rq.c
deleted file mode 100644 (file)
index 46010e6..0000000
+++ /dev/null
@@ -1,444 +0,0 @@
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 1998-2007 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>.
- */
-/* Portions Copyright (c) 1996 Regents of the University of Michigan.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that this notice is preserved and that due credit is given
- * to the University of Michigan at Ann Arbor. The name of the University
- * may not be used to endorse or promote products derived from this
- * software without specific prior written permission. This software
- * is provided ``as is'' without express or implied warranty.
- */
-/* ACKNOWLEDGEMENTS:
- * This work was originally developed by the University of Michigan
- * (as part of U-MICH LDAP).
- */
-
-/*
- * rq.c - routines used to manage the queue of replication entries.
- * An Rq (Replication queue) struct contains a linked list of Re
- * (Replication entry) structures.
- *
- * Routines wishing to access the replication queue should do so through
- * the Rq struct's member functions, e.g. rq->rq_gethead() and friends.
- * For example, Re structs should be added to the queue by calling 
- * the rq_add() member function.
- *
- * Access to the queue is serialized by a mutex.  Member functions which do
- * not do their own locking should only be called after locking the queue
- * using the rq_lock() member function.  The queue should be unlocked with
- * the rq_unlock() member function.
- *
- * Note that some member functions handle their own locking internally.
- * Callers should not lock the queue before calling these functions.
- * See the comment block for each function below.
- *
- */
-
-#include "portable.h"
-
-#include <stdio.h>
-#include <sys/stat.h>
-
-#include <ac/stdlib.h>
-#include <ac/string.h>
-#include <ac/unistd.h>         /* get ftruncate() */
-
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-#ifdef HAVE_FCNTL_H
-#include <fcntl.h>
-#endif
-
-#include "slurp.h"
-#include "globals.h"
-
-/*
- * Lock the replication queue.
- */
-static int
-Rq_lock(
-    Rq *rq
-)
-{
-    return( ldap_pvt_thread_mutex_lock( &rq->rq_mutex ));
-}
-
-
-/*
- * Unlock the replication queue.
- */
-static int
-Rq_unlock(
-    Rq *rq
-)
-{
-    return( ldap_pvt_thread_mutex_unlock( &rq->rq_mutex ));
-}
-
-
-
-/*
- * Return the head of the queue.  Callers should lock the queue before
- * calling this routine.
- */
-static Re *
-Rq_gethead(
-    Rq *rq
-)
-{
-    return( rq == NULL ? NULL : rq->rq_head );
-}
-
-
-/*
- * Return the next item in the queue.  Callers should lock the queue before
- * calling this routine.
- */
-static Re *
-Rq_getnext(
-    Re *re
-)
-{
-    if ( re == NULL ) {
-       return NULL;
-    } else {
-       return( re->re_getnext( re ));
-    }
-}
-
-
-/*
- * Delete the item at the head of the list.  The queue should be locked
- * by the caller before calling this routine.
- */
-static int
-Rq_delhead(
-    Rq *rq
-)
-{
-    Re *savedhead;
-    int        rc;
-
-    if ( rq == NULL ) {
-       return( -1 );
-    }
-
-    savedhead = rq->rq_head;
-    if ( savedhead == NULL ) {
-       return( 0 );
-    }
-
-    if ( savedhead->re_getrefcnt( savedhead ) != 0 ) {
-       Debug( LDAP_DEBUG_ANY, "Warning: attempt to delete when refcnt != 0\n",
-               0, 0, 0 );
-       return( -1 );
-    }
-
-    rq->rq_head = rq->rq_head->re_getnext( rq->rq_head );
-    rc = savedhead->re_free( savedhead );
-    rq->rq_nre--;      /* decrement count of Re's in queue */
-    return( rc );
-}
-
-
-/* 
- * Add an entry to the tail of the replication queue.  Locking is handled
- * internally.  When items are added to the queue, this routine wakes
- * up any threads which are waiting for more work by signaling on the
- * rq->rq_more condition variable.
- */
-static int
-Rq_add(
-    Rq         *rq,
-    char       *buf
-)
-{
-    Re *re;
-    int        wasempty = 0;
-
-    /* Lock the queue */
-    rq->rq_lock( rq );
-
-    /* Create a new Re */
-    if ( Re_init( &re ) < 0 ) {
-       rq->rq_unlock( rq );
-       return -1;
-    }
-
-    /* parse buf and fill in the re struct */
-    if ( re->re_parse( re, buf ) < 0 ) {
-       re->re_free( re );
-       rq->rq_unlock( rq );
-       return -1;
-    }
-
-    /* Insert into queue */
-    if ( rq->rq_head == NULL ) {
-       rq->rq_head = re;
-       rq->rq_tail = re;
-       wasempty = 1;
-    } else {
-       rq->rq_tail->re_next = re;
-    }
-
-    /* set the sequence number */
-    re->re_seq = 0;
-    if ( !wasempty && ( rq->rq_tail->re_timestamp == re->re_timestamp )) {
-       /*
-        * Our new re has the same timestamp as the tail's timestamp.
-        * Increment the seq number in the tail and use it as our seq number.
-        */
-       re->re_seq = rq->rq_tail->re_seq + 1;
-    }
-    rq->rq_tail = re;
-
-    /* Increment count of items in queue */
-    rq->rq_nre++;
-    /* wake up any threads waiting for more work */
-    ldap_pvt_thread_cond_broadcast( &rq->rq_more );
-
-    /* ... and unlock the queue */
-    rq->rq_unlock( rq );
-
-    return 0;
-}
-
-
-/*
- * Garbage-collect the replication queue.  Locking is handled internally.
- */
-static void
-Rq_gc(
-    Rq *rq
-)
-{
-    if ( rq == NULL ) {
-       Debug( LDAP_DEBUG_ANY, "Rq_gc: rq is NULL!\n", 0, 0, 0 );
-       return;
-    }
-    rq->rq_lock( rq ); 
-    while (( rq->rq_head != NULL ) &&
-           ( rq->rq_head->re_getrefcnt( rq->rq_head ) == 0 )) {
-       rq->rq_delhead( rq );
-       rq->rq_ndel++;  /* increment count of deleted entries */
-    }
-    rq->rq_unlock( rq ); 
-    return;
-}
-
-
-/*
- * For debugging: dump the contents of the replication queue to a file.
- * Locking is handled internally.
- */
-static void
-Rq_dump(
-    Rq *rq
-)
-{
-    Re         *re;
-    FILE       *fp;
-    int                tmpfd;
-
-    if ( rq == NULL ) {
-       Debug( LDAP_DEBUG_ANY, "Rq_dump: rq is NULL!\n", 0, 0, 0 );
-       return;
-    }
-
-    if (unlink(SLURPD_DUMPFILE) == -1 && errno != ENOENT) {
-       Debug( LDAP_DEBUG_ANY, "Rq_dump: \"%s\" exists, and cannot unlink\n",
-               SLURPD_DUMPFILE, 0, 0 );
-       return;
-    }
-    if (( tmpfd = open(SLURPD_DUMPFILE, O_CREAT|O_RDWR|O_EXCL, 0600)) == -1) {
-       Debug( LDAP_DEBUG_ANY, "Rq_dump: cannot open \"%s\" for write\n",
-               SLURPD_DUMPFILE, 0, 0 );
-       return;
-    }
-    if (( fp = fdopen( tmpfd, "w" )) == NULL ) {
-       Debug( LDAP_DEBUG_ANY, "Rq_dump: cannot fdopen \"%s\" for write\n",
-               SLURPD_DUMPFILE, 0, 0 );
-       return;
-    }
-
-    rq->rq_lock( rq );
-    for ( re = rq->rq_gethead( rq ); re != NULL; re = rq->rq_getnext( re )) {
-       re->re_dump( re, fp );
-    }
-    rq->rq_unlock( rq );
-    fclose( fp );
-    return;
-}
-
-
-/*
- * Write the contents of a replication queue to a file.  Returns zero if
- * successful, -1 if not.  Handles queue locking internally.  Callers should
- * provide an open file pointer, which should refer to a locked file.
- */
-static int
-Rq_write(
-    Rq         *rq,
-    FILE       *fp
-)
-{
-    Re         *re;
-    time_t     now;
-
-    if ( rq == NULL ) {
-       return -1;
-    }
-
-    Debug( LDAP_DEBUG_ARGS, "re-write on-disk replication log\n",
-           0, 0, 0 );
-#ifndef SEEK_SET
-#define SEEK_SET 0
-#endif
-    fseek( fp, 0L, SEEK_SET ); /* Go to beginning of file */
-    rq->rq_lock( rq );
-
-    for ( re = rq->rq_gethead( rq ); re != NULL; re = rq->rq_getnext( re )) {
-       if ( re->re_write( NULL, re, fp ) < 0 ) {
-           fflush( fp );
-           rq->rq_unlock( rq );
-           return -1;
-       }
-    }
-    fflush( fp );
-    sglob->srpos = ftell( fp );        /* update replog file position */
-    /* and truncate to correct len */
-    if ( ftruncate( fileno( fp ), sglob->srpos ) < 0 ) {
-       Debug( LDAP_DEBUG_ANY, "Error truncating replication log: %s\n",
-               sys_errlist[ errno ], 0, 0 );
-    }
-    rq->rq_ndel = 0;   /* reset count of deleted re's */
-    time( &now );
-    rq->rq_lasttrim = now;     /* reset last trim time */
-    rq->rq_unlock( rq );
-    return 0;
-}
-
-
-/*
- * Check to see if the private slurpd replication log needs trimming.
- * The current criteria are:
- *  - The last trim was more than 5 minutes ago, *and*
- *  - We've finished with at least 50 replication log entries since the
- *    last time we re-wrote the replication log.
- *
- * Return 1 if replogfile should be trimmed, 0 if not.
- * Any different policy should be implemented by replacing this function.
- */
-static int
-Rq_needtrim(
-    Rq *rq
-)
-{
-    int                rc = 0;
-    time_t     now;
-
-    if ( rq == NULL ) {
-       return 0;
-    }
-
-    rq->rq_lock( rq );
-
-    time( &now );
-
-    if ( now > ( rq->rq_lasttrim + TRIMCHECK_INTERVAL )) {
-       rc = ( rq->rq_ndel >= 50 );
-    } else {
-       rc = 0;
-    }
-    rq->rq_unlock( rq );
-    return rc;
-}
-
-
-/*
- * Return counts of Re structs in the queue.
- */
-static int
-Rq_getcount(
-    Rq *rq,
-    int        type
-)
-{
-    int        count = 0;
-    Re *re;
-
-    if ( rq == NULL ) {
-       return 0;
-    }
-
-    rq->rq_lock( rq );
-    if ( type == RQ_COUNT_ALL ) {
-       count = rq->rq_nre;
-    } else {
-       for ( re = rq->rq_gethead( rq ); re != NULL;
-               re = rq->rq_getnext( re )) {
-           if ( type == RQ_COUNT_NZRC ) {
-               if ( re->re_getrefcnt( re ) > 0 ) {
-                   count++;
-               }
-           }
-       }
-    }
-    rq->rq_unlock( rq );
-    return count;
-}
-
-
-/* 
- * Allocate and initialize an Rq object.
- */
-int
-Rq_init(
-    Rq **rq
-)
-{
-    /* Instantiate the struct */
-    (*rq) = (Rq *) malloc( sizeof( Rq ));
-    if ( *rq == NULL ) {
-       return -1;
-    }
-
-    /* Fill in all the function pointers */
-    (*rq)->rq_gethead = Rq_gethead;
-    (*rq)->rq_getnext = Rq_getnext;
-    (*rq)->rq_delhead = Rq_delhead;
-    (*rq)->rq_add = Rq_add;
-    (*rq)->rq_gc = Rq_gc;
-    (*rq)->rq_lock = Rq_lock;
-    (*rq)->rq_unlock = Rq_unlock;
-    (*rq)->rq_dump = Rq_dump;
-    (*rq)->rq_needtrim = Rq_needtrim;
-    (*rq)->rq_write = Rq_write;
-    (*rq)->rq_getcount = Rq_getcount;
-
-    /* Initialize private data */
-    ldap_pvt_thread_mutex_init( &((*rq)->rq_mutex) );
-    ldap_pvt_thread_cond_init( &((*rq)->rq_more) );
-    (*rq)->rq_head = NULL;
-    (*rq)->rq_tail = NULL;
-    (*rq)->rq_nre = 0;
-    (*rq)->rq_ndel = 0;
-    (*rq)->rq_lasttrim = (time_t) 0L;
-
-    return 0;
-}
diff --git a/servers/slurpd/sanity.c b/servers/slurpd/sanity.c
deleted file mode 100644 (file)
index 56d1ed3..0000000
+++ /dev/null
@@ -1,225 +0,0 @@
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 1998-2007 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>.
- */
-/* Portions Copyright (c) 1996 Regents of the University of Michigan.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that this notice is preserved and that due credit is given
- * to the University of Michigan at Ann Arbor. The name of the University
- * may not be used to endorse or promote products derived from this
- * software without specific prior written permission. This software
- * is provided ``as is'' without express or implied warranty.
- */
-/* ACKNOWLEDGEMENTS:
- * This work was originally developed by the University of Michigan
- * (as part of U-MICH LDAP).
- */
-
-
-/*
- * sanity.c - perform sanity checks on the environment at startup time,
- * and report any errors before we disassociate from the controlling tty,
- * start up our threads, and do other stuff which makes it hard to give
- * feedback to the users.
- */
-
-#include "portable.h"
-
-#include <stdio.h>
-
-#include <ac/stdlib.h>
-#include <ac/unistd.h>
-#include <ac/string.h>
-
-#include "slurp.h"
-#include "globals.h"
-
-#define FC_DIRBAD      1
-#define FC_DIRUNREAD   2
-#define FC_DIRUNWRITE  4
-#define FC_FILEBAD     8
-#define FC_FILEUNREAD  16
-#define FC_FILEUNWRITE 32
-
-
-/*
- * Forward declarations
- */
-static unsigned int filecheck LDAP_P(( char * ));
-
-
-
-/*
- * Take a look around to catch any fatal errors.  For example, make sure the
- * destination directory for our working files exists, check that all
- * pathnames make sense, and so on.  Returns 0 is everything's ok,
- # -1 if there's something wrong which will keep us from functioning
- * correctly.
- *
- * We do all these checks at startup so we can print a reasonable error
- * message on stderr before we disassociate from the controlling tty.  This
- * keeps some fatal error messages from "disappearing" into syslog.
- */
-
-int
-sanity( void )
-{
-    int        err = 0;
-    int rc;
-
-    /*
-     * Are there any replicas listed in the slapd config file?
-     */
-    if ( sglob->replicas == NULL ) {
-       fprintf( stderr, "No replicas in slapd.conf file \"%s\"!\n",
-           sglob->slapd_configfile );
-       err++;
-    }
-
-    /*
-     * Make sure the directory housing the slapd replogfile exists, and
-     * that the slapd replogfile is readable, if it exists.
-     */
-    if ( sglob->slapd_replogfile == NULL ) {
-       fprintf( stderr, "Fatal error: no \"replogfile\" "
-               "slapd.conf directive given\n" );
-       err++;
-    } else {
-       rc = filecheck( sglob->slapd_replogfile );
-       if ( rc & FC_DIRBAD ) {
-           fprintf( stderr, "Error: %s: directory specified in "
-                       "\"replogfile\" slapd.conf directive does not exist\n", 
-                   sglob->slapd_replogfile );
-           err++;
-       } else if ( rc & FC_DIRUNREAD ) {
-           fprintf( stderr, "Error: %s: directory specified in "
-                       "\"replogfile\" slapd.conf directive is not readable\n", 
-                   sglob->slapd_replogfile );
-           err++;
-       } else if (!( rc & FC_FILEBAD) && ( rc & FC_FILEUNREAD )) {
-           fprintf( stderr, "Error: %s: file specified in "
-                       "\"replogfile\" slapd.conf directive is not readable\n", 
-                   sglob->slapd_replogfile );
-           err++;
-       }
-    }
-
-    /*
-     * Make sure the directory for the slurpd replogfile is there, and
-     * that the slurpd replogfile is readable and writable, if it exists.
-     */
-    if ( sglob->slurpd_replogfile == NULL ) {
-       fprintf( stderr, "Fatal error: no \"replogfile\" directive given\n" );
-       err++;
-    } else {
-       rc = filecheck( sglob->slurpd_replogfile );
-       if ( rc & FC_DIRBAD ) {
-           fprintf( stderr, "Error: %s: slurpd \"replogfile\" "
-                       "directory does not exist\n", 
-                   sglob->slurpd_replogfile );
-           err++;
-       } else if ( rc & FC_DIRUNREAD ) {
-           fprintf( stderr, "Error: %s: slurpd \"replogfile\" "
-                       "directory not readable\n", 
-                   sglob->slurpd_replogfile );
-           err++;
-       } else if ( !( rc & FC_FILEBAD ) && ( rc & FC_FILEUNREAD )) {
-           fprintf( stderr, "Error: %s: slurpd \"replogfile\" not readable\n", 
-                   sglob->slurpd_replogfile );
-           err++;
-       } else if ( !( rc & FC_FILEBAD ) && ( rc & FC_FILEUNWRITE )) {
-           fprintf( stderr, "Error: %s: slurpd \"replogfile\" not writeable\n", 
-                   sglob->slurpd_replogfile );
-           err++;
-       }
-    }
-
-    /*
-     * Make sure that the directory for the slurpd status file is there, and
-     * that the slurpd status file is writable, if it exists.
-     */
-    rc = filecheck( sglob->slurpd_status_file );
-    if ( rc & FC_DIRBAD ) {
-       fprintf( stderr, "Error: %s: status directory does not exist\n", 
-               sglob->slurpd_status_file );
-       err++;
-    } else if ( rc & FC_DIRUNREAD ) {
-       fprintf( stderr, "Error: %s: status directory not readable\n", 
-               sglob->slurpd_status_file );
-       err++;
-    } else if ( !( rc & FC_FILEBAD ) && ( rc & FC_FILEUNREAD )) {
-       fprintf( stderr, "Error: %s: status file not readable\n", 
-               sglob->slurpd_status_file );
-       err++;
-    } else if ( !( rc & FC_FILEBAD ) && ( rc & FC_FILEUNWRITE )) {
-       fprintf( stderr, "Error: %s: status file not writeable\n", 
-               sglob->slurpd_status_file );
-       err++;
-    }
-    
-    return ( err == 0 ? 0 : -1 );
-}
-
-
-
-/*
- * Check for the existence of the file and directory leading to the file.
- * Returns a bitmask which is the logical OR of the following flags:
- *
- *  FC_DIRBAD:         directory containing "f" does not exist.
- *  FC_DIRUNREAD:      directory containing "f" exists but is not readable.
- *  FC_DIRUNWRITE:     directory containing "f" exists but is not writable.
- *  FC_FILEBAD:                "f" does not exist.
- *  FC_FILEUNREAD:     "f" exists but is unreadable.
- *  FC_FILEUNWRITE:    "f" exists but is unwritable.
- *
- * The calling routine is responsible for determining which, if any, of
- * the returned flags is a problem for a particular file.
- */
-static unsigned int
-filecheck(
-    char       *f
-)
-{
-    char               dir[ MAXPATHLEN ];
-    char               *p;
-    unsigned int       ret = 0;
-
-       snprintf( dir, sizeof dir, "%s", f );
-    p = strrchr( dir, LDAP_DIRSEP[0] );
-    if ( p != NULL ) {
-       *p = '\0';
-    }
-    if ( access( dir, F_OK ) < 0 ) {
-       ret |= FC_DIRBAD;
-    }
-    if ( access( dir, R_OK ) < 0 ) {
-       ret |= FC_DIRUNREAD;
-    }
-    if ( access( dir, W_OK ) < 0 ) {
-       ret |= FC_DIRUNWRITE;
-    }
-    if ( access( f, F_OK ) < 0 ) {
-       ret |= FC_FILEBAD;
-    }
-    if ( access( f, R_OK ) < 0 ) {
-       ret |= FC_FILEUNREAD;
-    }
-    if ( access( f, W_OK ) < 0 ) {
-       ret |= FC_FILEUNWRITE;
-    }
-
-    return ret;
-}
diff --git a/servers/slurpd/slurp.h b/servers/slurpd/slurp.h
deleted file mode 100644 (file)
index 9a125c6..0000000
+++ /dev/null
@@ -1,415 +0,0 @@
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 1998-2007 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>.
- */
-/* Portions Copyright (c) 1996 Regents of the University of Michigan.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that this notice is preserved and that due credit is given
- * to the University of Michigan at Ann Arbor. The name of the University
- * may not be used to endorse or promote products derived from this
- * software without specific prior written permission. This software
- * is provided ``as is'' without express or implied warranty.
- */
-/* ACKNOWLEDGEMENTS:
- * This work was originally developed by the University of Michigan
- * (as part of U-MICH LDAP).
- */
-
-/* slurp.h - Standalone Ldap Update Replication Daemon (slurpd) */
-
-#ifndef _SLURPD_H_
-#define _SLURPD_H_
-
-#if !defined(HAVE_WINSOCK) && !defined(LDAP_SYSLOG)
-#define LDAP_SYSLOG 1
-#endif
-
-#include <ac/errno.h>
-#include <ac/param.h>
-#include <ac/signal.h>
-#include <ac/syslog.h>
-#include <ac/time.h>
-
-#include <sys/types.h>
-
-#include <ldap.h>
-
-#undef  ldap_debug
-#define ldap_debug slurp_debug
-#include "ldap_log.h"
-
-#include "ldap_pvt_thread.h"
-#include "ldap_defaults.h"
-#include "ldif.h"
-
-#ifdef HAVE_WINSOCK
-       /* should be moved to portable.h.nt */
-#define ftruncate(a,b) _chsize(a,b)
-#define truncate(a,b) _lclose( _lcreat(a, 0))
-#define mkdir(a,b)     mkdir(a)
-#define S_IRGRP 0
-#define S_IWGRP 0
-#ifndef F_OK
-#define F_OK 0
-#endif
-#ifndef W_OK
-#define W_OK 2
-#endif
-#ifndef R_OK
-#define R_OK 4
-#endif
-#ifndef S_IRUSR
-#define S_IRUSR S_IREAD
-#endif
-#ifndef S_IWUSR
-#define S_IWUSR S_IWRITE
-#endif
-#endif
-
-#undef SERVICE_NAME
-#define SERVICE_NAME   OPENLDAP_PACKAGE "-slurpd"
-
-/* Default directory for slurpd's private copy of replication logs */
-#define        DEFAULT_SLURPD_REPLICA_DIR      LDAP_RUNDIR LDAP_DIRSEP "openldap-slurp"
-
-/* Default name for slurpd's private copy of the replication log */
-#define        DEFAULT_SLURPD_REPLOGFILE       "slurpd.replog"
-
-/* Name of file which stores saved slurpd state info, for restarting */
-#define        DEFAULT_SLURPD_STATUS_FILE      "slurpd.status"
-
-/* slurpd dump file - contents of rq struct are written here (debugging) */
-#define        SLURPD_DUMPFILE                 LDAP_TMPDIR LDAP_DIRSEP "slurpd.dump"
-
-/* Amount of time to sleep if no more work to do */
-#define        DEFAULT_NO_WORK_INTERVAL        3
-
-/* The time we wait between checks to see if the replog file needs trimming */
-#define        TRIMCHECK_INTERVAL              ( 60 * 5 )
-
-/* Only try to trim slurpd replica files larger than this size */
-#define        MIN_TRIM_FILESIZE               ( 10L * 1024L )
-
-/* Maximum line length we can read from replication log */
-#define        REPLBUFLEN                      256
-
-/* TLS flags */
-#define TLS_OFF                        0
-#define TLS_ON                 1
-#define TLS_CRITICAL   2
-
-/* Rejection records are prefaced with this string */
-#define        ERROR_STR       "ERROR"
-
-/* Strings found in replication entries */
-#define        T_CHANGETYPESTR         "changetype"
-#define        T_CHANGETYPE            1
-#define        T_TIMESTR               "time"
-#define        T_TIME                  2
-#define        T_DNSTR                 "dn"
-#define        T_DN                    3
-
-#define        T_ADDCTSTR              "add"
-#define        T_ADDCT                 4
-#define        T_MODIFYCTSTR           "modify"
-#define        T_MODIFYCT              5
-#define        T_DELETECTSTR           "delete"
-#define        T_DELETECT              6
-#define        T_MODRDNCTSTR           "modrdn"
-#define        T_MODDNCTSTR            "moddn"
-#define        T_RENAMECTSTR           "rename"
-#define        T_MODRDNCT              7
-
-#define        T_MODOPADDSTR           "add"
-#define        T_MODOPADD              8
-#define        T_MODOPREPLACESTR       "replace"
-#define        T_MODOPREPLACE          9
-#define        T_MODOPDELETESTR        "delete"
-#define        T_MODOPDELETE           10
-#define        T_MODOPINCREMENTSTR     "increment"
-#define        T_MODOPINCREMENT        11
-#define        T_MODSEPSTR             "-"
-#define        T_MODSEP                12
-
-#define        T_NEWRDNSTR             "newrdn"
-#define        T_DELOLDRDNSTR  "deleteoldrdn"
-#define T_NEWSUPSTR            "newsuperior"
-
-#define        T_ERR                   -1
-
-/* Config file keywords */
-#define        HOSTSTR                 "host"
-#define        URISTR                  "uri"
-#define        ATTRSTR                 "attr"
-#define        SUFFIXSTR               "suffix"
-#define        BINDDNSTR               "binddn"
-#define        BINDMETHSTR             "bindmethod"
-#define        SIMPLESTR               "simple"
-#define        SASLSTR                 "sasl"
-#define        CREDSTR                 "credentials"
-#define        OLDAUTHCSTR             "bindprincipal"
-#define        AUTHCSTR                "authcID"
-#define        AUTHZSTR                "authzID"
-#define        SASLMECHSTR             "saslmech"
-#define        REALMSTR                "realm"
-#define        SECPROPSSTR             "secprops"
-#define STARTTLSSTR            "starttls"
-#define TLSSTR                 "tls"
-#define CRITICALSTR            "critical"
-
-#define        REPLICA_SLEEP_TIME      ( 10 )
-
-/* Enumeration of various types of bind failures */
-#define BIND_OK                                        0
-#define BIND_ERR_BADLDP                                1
-#define        BIND_ERR_OPEN                           2
-#define        BIND_ERR_BAD_ATYPE                      3
-#define        BIND_ERR_SIMPLE_FAILED          4
-#define        BIND_ERR_BADRI                          6
-#define        BIND_ERR_VERSION                        7
-#define        BIND_ERR_REFERRALS                      8
-#define        BIND_ERR_MANAGEDSAIT            9
-#define        BIND_ERR_SASL_FAILED            10
-#define        BIND_ERR_TLS_FAILED                     11
-
-/* Return codes for do_ldap() */
-#define        DO_LDAP_OK                      0
-#define        DO_LDAP_ERR_RETRYABLE           1
-#define        DO_LDAP_ERR_FATAL               2
-
-/*
- * Types of counts one can request from the Rq rq_getcount()
- * member function
- */
-/* all elements */
-#define        RQ_COUNT_ALL                    1
-/* all elements with nonzero refcnt */
-#define        RQ_COUNT_NZRC                   2
-
-/* Amount of time, in seconds, for a thread to sleep when it encounters
- * a retryable error in do_ldap().
- */
-#define        RETRY_SLEEP_TIME                60
-
-
-LDAP_BEGIN_DECL
-
-/*
- * ****************************************************************************
- * Data types for replication queue and queue elements.
- * ****************************************************************************
- */
-
-
-/*
- * Replica host information.  An Ri struct will contain an array of these,
- * with one entry for each replica.  The end of the array is signaled
- * by a NULL value in the rh_hostname field.
- */
-typedef struct rh {
-    char       *rh_hostname;           /* replica hostname  */
-    int                rh_port;                /* replica port */
-} Rh;
-
-
-/*
- * Per-replica information.
- *
- * Notes:
- *  - Private data should not be manipulated expect by Ri member functions.
- */
-typedef struct ri Ri;
-struct ri {
-    /* Private data */
-    char       *ri_hostname;           /* canonical hostname of replica */
-    int                ri_port;                /* port where slave slapd running */
-    char       *ri_uri;                /* e.g. "ldaps://ldap-1.example.com:636" */
-    LDAP       *ri_ldp;                /* LDAP struct for this replica */
-    int                ri_tls;                 /* TLS: 0=no, 1=yes, 2=critical */
-    int                ri_bind_method;         /* AUTH_SIMPLE or AUTH_SASL */
-    char       *ri_bind_dn;            /* DN to bind as when replicating */
-    char       *ri_password;           /* Password for any method */
-    char       *ri_secprops;           /* SASL security properties */
-    char       *ri_realm;                      /* realm for any mechanism */
-    char       *ri_authcId;            /* authentication ID for any mechanism */
-    char       *ri_authzId;            /* authorization ID for any mechanism */
-    char       *ri_saslmech;           /* SASL mechanism to use */
-    struct re  *ri_curr;               /* current repl entry being processed */
-    struct stel        *ri_stel;               /* pointer to Stel for this replica */
-    unsigned long
-               ri_seq;                 /* seq number of last repl */
-    ldap_pvt_thread_t  ri_tid;                 /* ID of thread for this replica */
-
-    /* Member functions */
-    int (*ri_process) LDAP_P(( Ri * ));        /* process the next repl entry */
-    void (*ri_wake)   LDAP_P(( Ri * ));        /* wake up a sleeping thread */
-};
-
-
-
-/*
- * Information about one particular modification to make.  This data should
- * be considered private to routines in re.c, and to routines in ri.c.
- */
-typedef struct mi {
-    /* Private data */
-    char       *mi_type;               /* attr or type */
-    char       *mi_val;                /* value */
-    int                mi_len;                 /* length of mi_val */
-} Mi;
-
-
-
-/* 
- * Information about one particular replication entry.  Only routines in
- * re.c  and rq.c should touch the private data.  Other routines should
- * only use member functions.
- */
-typedef struct re Re;
-struct re {
-    /* Private data */
-    ldap_pvt_thread_mutex_t
-               re_mutex;               /* mutex for this Re */
-    int                re_refcnt;              /* ref count, 0 = done */
-    time_t     re_timestamp;           /* timestamp of this re */
-    int                re_seq;                 /* sequence number */
-    Rh         *re_replicas;           /* array of replica info */
-    char       *re_dn;                 /* dn of entry being modified */
-    int                re_changetype;          /* type of modification */
-    Mi         *re_mods;               /* array of modifications to make */
-    struct re  *re_next;               /* pointer to next element */
-
-    /* Public functions */
-    int        (*re_free)    LDAP_P(( Re * )); /* free an re struct */
-    Re *(*re_getnext) LDAP_P(( Re * ));        /* return next Re in linked list */
-    int (*re_parse) LDAP_P(( Re *, char * )); /* parse replication log entry */
-    int (*re_write) LDAP_P(( Ri *, Re *, FILE * )); /* write repl. log entry */
-    void (*re_dump)  LDAP_P(( Re *, FILE * )); /* debugging - print contents */
-    int (*re_lock)   LDAP_P(( Re * ));   /* lock this re */
-    int (*re_unlock) LDAP_P(( Re * ));   /* unlock this re */
-    int (*re_decrefcnt) LDAP_P(( Re * )); /* decrement the refcnt */
-    int (*re_getrefcnt) LDAP_P(( Re * )); /* get the refcnt */
-};
-
-
-
-
-/* 
- * Definition for the queue of replica information.  Private data is
- * private to rq.c.  Other routines should only touch public data or
- * use member functions.  Note that although we have a member function
- * for locking the queue's mutex, we need to expose the rq_mutex
- * variable so routines in ri.c can use it as a mutex for the
- * rq_more condition variable.
- */
-typedef struct rq Rq;
-struct rq {
-
-    /* Private data */
-    Re         *rq_head;               /* pointer to head */
-    Re         *rq_tail;               /* pointer to tail */
-    int                rq_nre;                 /* total number of Re's in queue */
-    int                rq_ndel;                /* number of deleted Re's in queue */
-    time_t     rq_lasttrim;            /* Last time we trimmed file */
-    
-    /* Public data */
-    ldap_pvt_thread_mutex_t
-               rq_mutex;               /* mutex for whole queue */
-    ldap_pvt_thread_cond_t
-               rq_more;                /* condition var - more work added */
-
-    /* Member functions */
-    Re * (*rq_gethead) LDAP_P(( Rq * )); /* get the element at head */
-    Re * (*rq_getnext) LDAP_P(( Re * )); /* get the next element */
-    int         (*rq_delhead)  LDAP_P(( Rq * )); /* delete the element at head */
-    int         (*rq_add)      LDAP_P(( Rq *, char * )); /* add at tail */
-    void (*rq_gc)      LDAP_P(( Rq * )); /* garbage-collect queue */
-    int         (*rq_lock)     LDAP_P(( Rq * )); /* lock the queue */
-    int         (*rq_unlock)   LDAP_P(( Rq * )); /* unlock the queue */
-    int         (*rq_needtrim) LDAP_P(( Rq * )); /* see if queue needs trimming */
-    int         (*rq_write)    LDAP_P(( Rq *, FILE * )); /*write Rq contents to file*/
-    int         (*rq_getcount) LDAP_P(( Rq *, int )); /* return queue counts */
-    void (*rq_dump)    LDAP_P(( Rq * )); /* debugging - print contents */
-};
-
-
-/*
- * An Stel (status element) contains information about one replica.
- * Stel structs are associated with the St (status) struct, defined 
- * below.
- */
-typedef struct stel {
-    char       *hostname;              /* host name of replica */
-    int                port;                   /* port number of replica */
-    time_t     last;                   /* timestamp of last successful repl */
-    int                seq;                    /* Sequence number of last repl */
-} Stel;
-
-
-/*
- * An St struct in an in-core structure which contains the current
- * slurpd state.  Most importantly, it contains an array of Stel
- * structs which contain the timestamp and sequence number of the last
- * successful replication for each replica.  The st_write() member
- * function is called periodically to flush status information to
- * disk.  At startup time, slurpd checks for the status file, and
- * if present, uses the timestamps to avoid "replaying" replications
- * which have already been sent to a given replica.
- */
-typedef struct st St;
-struct st {
-    /* Private data */
-    ldap_pvt_thread_mutex_t
-               st_mutex;               /* mutex to serialize access */
-    Stel       **st_data;              /* array of pointers to Stel structs */
-    int                st_nreplicas;           /* number of repl hosts */
-    int                st_err_logged;          /* 1 if fopen err logged */
-    FILE       *st_fp;                 /* st file kept open */
-    FILE       *st_lfp;                /* lockfile fp */
-
-    /* Public member functions */
-    int  (*st_update) LDAP_P(( St *, Stel*, Re* ));/*update entry for a host*/
-    Stel*(*st_add)    LDAP_P(( St *, Ri * ));     /*add a new repl host*/
-    int  (*st_write)  LDAP_P(( St * ));        /* write status to disk */
-    int  (*st_read)   LDAP_P(( St * ));        /* read status info from disk */
-    int  (*st_lock)   LDAP_P(( St * ));        /* read status info from disk */
-    int  (*st_unlock) LDAP_P(( St * ));        /* read status info from disk */
-};
-
-#if defined( HAVE_LWP )
-typedef struct tl {
-    thread_t   tl_tid;         /* thread being managed */
-    time_t     tl_wake;        /* time thread should be resumed */
-    struct tl  *tl_next;       /* next node in list */
-} tl_t;
-
-typedef struct tsl {
-    tl_t       *tsl_list;
-    mon_t      tsl_mon;
-} tsl_t;
-#endif /* HAVE_LWP */
-
-/* 
- * Public functions used to instantiate and initialize queue objects.
- */
-extern int Ri_init LDAP_P(( Ri **ri ));
-extern int Rq_init LDAP_P(( Rq **rq ));
-extern int Re_init LDAP_P(( Re **re ));
-
-#include "proto-slurp.h"
-
-LDAP_END_DECL
-
-#endif /* _SLURPD_H_ */
diff --git a/servers/slurpd/st.c b/servers/slurpd/st.c
deleted file mode 100644 (file)
index 609766e..0000000
+++ /dev/null
@@ -1,331 +0,0 @@
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 1998-2007 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>.
- */
-/* Portions Copyright (c) 1996 Regents of the University of Michigan.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that this notice is preserved and that due credit is given
- * to the University of Michigan at Ann Arbor. The name of the University
- * may not be used to endorse or promote products derived from this
- * software without specific prior written permission. This software
- * is provided ``as is'' without express or implied warranty.
- */
-/* ACKNOWLEDGEMENTS:
- * This work was originally developed by the University of Michigan
- * (as part of U-MICH LDAP).
- */
-
-
-/*
- * st.c - routines for managing the status structure, and for reading and
- * writing status information to disk.
- */
-
-#include "portable.h"
-
-#include <stdio.h>
-
-#include <ac/stdlib.h>
-#include <ac/string.h>
-#include <ac/unistd.h>
-
-#include "slurp.h"
-#include "globals.h"
-#include "lutil.h"
-
-/*
- * Add information about replica host specified by Ri to list
- * of hosts.
- */
-static Stel *
-St_add(
-    St *st,
-    Ri *ri
-)
-{
-    int        ind;
-
-    if ( st == NULL || ri == NULL ) {
-       return NULL;
-    }
-
-    /* Serialize access to the St struct */
-    ldap_pvt_thread_mutex_lock( &(st->st_mutex ));
-
-    st->st_nreplicas++;
-    ind = st->st_nreplicas - 1;
-    st->st_data = ( Stel ** ) ch_realloc( st->st_data, 
-           ( st->st_nreplicas * sizeof( Stel * )));
-    if ( st->st_data == NULL ) {
-       ldap_pvt_thread_mutex_unlock( &(st->st_mutex ));
-       return NULL;
-    }
-    st->st_data[ ind ]  = ( Stel * ) ch_malloc( sizeof( Stel ) );
-    if ( st->st_data[ ind ] == NULL ) {
-       ldap_pvt_thread_mutex_unlock( &(st->st_mutex ));
-       return NULL;
-    }
-
-    st->st_data[ ind ]->hostname = strdup( ri->ri_hostname );
-    st->st_data[ ind ]->port = ri->ri_port;
-    st->st_data[ ind ]->last = 0; 
-    st->st_data[ ind ]->seq = 0;
-
-    ldap_pvt_thread_mutex_unlock( &(st->st_mutex ));
-    return st->st_data[ ind ];
-}
-
-
-
-/*
- * Write the contents of an St to disk.
- */
-static int
-St_write (
-    St *st
-)
-{
-    int                rc;
-    Stel       *stel;
-    int                i;
-
-    if ( st == NULL ) {
-       return -1;
-    }
-    ldap_pvt_thread_mutex_lock( &(st->st_mutex ));
-    if ( st->st_fp == NULL ) {
-       /* Open file */
-       if (( rc = acquire_lock( sglob->slurpd_status_file, &(st->st_fp),
-               &(st->st_lfp))) < 0 ) {
-           if ( !st->st_err_logged ) {
-               Debug( LDAP_DEBUG_ANY,
-                       "Error: cannot open status file \"%s\": %s\n",
-                       sglob->slurpd_status_file, sys_errlist[ errno ], 0 );
-               st->st_err_logged = 1;
-               ldap_pvt_thread_mutex_unlock( &(st->st_mutex ));
-               return -1;
-           }
-       } else {
-           st->st_err_logged = 0;
-       }
-    }
-
-    /* Write data to the file */
-    truncate( sglob->slurpd_status_file, 0L );
-    fseek( st->st_fp, 0L, 0 );
-    for ( i = 0; i < st->st_nreplicas; i++ ) {
-       stel = st->st_data[ i ];
-       fprintf( st->st_fp, "%s:%d:%ld:%d\n",
-               stel->hostname, stel->port,
-               (long) stel->last, stel->seq );
-    }
-    fflush( st->st_fp );
-
-    ldap_pvt_thread_mutex_unlock( &(st->st_mutex ));
-
-    return 0;
-}
-    
-
-
-
-/*
- * Update the entry for a given host.
- */
-static int
-St_update(
-    St         *st,
-    Stel       *stel,
-    Re         *re
-)
-{
-    if ( stel == NULL || re == NULL ) {
-       return -1;
-    }
-
-    ldap_pvt_thread_mutex_lock( &(st->st_mutex ));
-    stel->last = re->re_timestamp;
-    stel->seq = re->re_seq;
-    ldap_pvt_thread_mutex_unlock( &(st->st_mutex ));
-    return 0;
-}
-
-
-
-
-/*
- * Read status information from disk file.
- */
-static int
-St_read(
-    St *st
-)
-{
-    FILE       *fp;
-    FILE       *lfp;
-    char       buf[ 255 ];
-    int                i;
-    int                rc;
-    char       *hostname, *port, *timestamp, *seq, *p, *t;
-    int                found;
-
-    if ( st == NULL ) {
-       return -1;
-    }
-    ldap_pvt_thread_mutex_lock( &(st->st_mutex ));
-    if ( access( sglob->slurpd_status_file, F_OK ) < 0 ) {
-       /*
-        * File doesn't exist, so create it and return.
-        */
-       if (( fp = fopen( sglob->slurpd_status_file, "w" )) == NULL ) {
-           Debug( LDAP_DEBUG_ANY, "Error: cannot create status file \"%s\"\n",
-                   sglob->slurpd_status_file, 0, 0 );
-           ldap_pvt_thread_mutex_unlock( &(st->st_mutex ));
-           return -1;
-       }
-       (void) fclose( fp );
-       ldap_pvt_thread_mutex_unlock( &(st->st_mutex ));
-       Debug( LDAP_DEBUG_ARGS, "No status file found, defaulting values\n",
-               0, 0, 0 );
-       return 0;
-    }
-    if (( rc = acquire_lock( sglob->slurpd_status_file, &fp, &lfp)) < 0 ) {
-       ldap_pvt_thread_mutex_unlock( &(st->st_mutex ));
-       return 0;
-    }
-    while ( fgets( buf, sizeof( buf ), fp ) != NULL ) {
-       p = buf;
-       hostname = p;
-       if (( t = strchr( p, ':' )) == NULL ) {
-           goto bad;
-       }
-       *t++ = '\0';
-       p = t;
-       port = p;
-       if (( t = strchr( p, ':' )) == NULL ) {
-           goto bad;
-       }
-       *t++ = '\0';
-       p = t;
-       timestamp = p;
-       if (( t = strchr( p, ':' )) == NULL ) {
-           goto bad;
-       }
-       *t++ = '\0';
-       seq = t;
-       if (( t = strchr( seq, '\n' )) != NULL ) {
-           *t = '\0';
-       }
-
-       found = 0;
-       for ( i = 0; i < sglob->st->st_nreplicas; i++ ) {
-           int p;
-           if ( !strcmp( hostname, sglob->st->st_data[ i ]->hostname ) &&
-                   lutil_atoi( &p, port ) == 0 && p == sglob->st->st_data[ i ]->port )
-           {
-               found = 1;
-               if ( lutil_atol( &sglob->st->st_data[ i ]->last, timestamp ) != 0
-                       || lutil_atoi( &sglob->st->st_data[ i ]->seq, seq ) != 0 )
-               {
-                   found = 0;
-               }
-               break;
-           }
-       }
-       if ( found ) {
-           char tbuf[ 255 ];
-           sprintf( tbuf, "%s.%s", timestamp, seq );
-           Debug( LDAP_DEBUG_ARGS,
-                   "Retrieved state information for %s:%s (timestamp %s)\n",
-                       hostname, port, tbuf );
-       } else {
-           Debug(  LDAP_DEBUG_ANY,
-                   "Warning: saved state for %s:%s, not a known replica\n",
-                   hostname, port, 0 );
-       }
-    }
-    (void) relinquish_lock( sglob->slurpd_status_file, fp, lfp);
-    ldap_pvt_thread_mutex_unlock( &(st->st_mutex ));
-    return 0;
-
-bad:
-    (void) relinquish_lock( sglob->slurpd_status_file, fp, lfp);
-    ldap_pvt_thread_mutex_unlock( &(st->st_mutex ));
-    return -1;
-}
-    
-
-
-
-/*
- * Lock an St struct.
- */
-static int
-St_lock(
-    St *st
-)
-{
-    return( ldap_pvt_thread_mutex_lock( &st->st_mutex ));
-}
-
-
-
-
-/*
- * Lock an St struct.
- */
-static int
-St_unlock(
-    St *st
-)
-{
-    return( ldap_pvt_thread_mutex_unlock( &st->st_mutex ));
-}
-
-
-
-
-/*
- * Allocate and initialize an St struct.
- */
-int
-St_init(
-    St **st
-)
-{
-    if ( st == NULL ) {
-       return -1;
-    }
-
-    (*st) = (St *) malloc( sizeof( St ));
-    if ( *st == NULL ) {
-       return -1;
-    }
-
-    ldap_pvt_thread_mutex_init( &((*st)->st_mutex) );
-    (*st)->st_data = NULL;
-    (*st)->st_fp = NULL;
-    (*st)->st_lfp = NULL;
-    (*st)->st_nreplicas = 0;
-    (*st)->st_err_logged = 0;
-    (*st)->st_update = St_update;
-    (*st)->st_add = St_add;
-    (*st)->st_write = St_write;
-    (*st)->st_read = St_read;
-    (*st)->st_lock = St_lock;
-    (*st)->st_unlock = St_unlock;
-    return 0;
-}
-
index c4c385e02c2a61b14fe27a667e8f8fe91718674d..a20ba4542089c8545644b2b9f76d59294276fc28 100644 (file)
@@ -60,7 +60,7 @@ regressions:  FORCE
 its: regressions
 
 clean-local:   FORCE
-       -$(RM) -r testrun *leak *gmon *core
+       -$(RM) -r testrun configpw configpw.conf *leak *gmon *core
 
 veryclean-local: FORCE
        @-$(RM) run testdata schema ucdata
index b90cc67e18073cd7fcab5909fc11e5efb1f39c3f..d3468a785067f71c1347b4100fbbbe9a46544876 100644 (file)
@@ -1,5 +1,5 @@
 This directory contains a series of test scripts which are used to
-verify basic functionality of the LDAP libraries, slapd, and slurpd.
+verify basic functionality of the LDAP libraries and  slapd.
 
        To run all of the tests, type "make test".
        To run BDB tests, type "make bdb".
index 1dde3108d456d5ece42857059cc92e8b1ae38f51..c6b5be3079cc8922acafda9c546b6cf9f028b5e7 100644 (file)
@@ -127,3 +127,32 @@ FALSE
 # Testing list compare with manageDSAit...
 FALSE
 
+# Testing list search without dgIdentity...
+dn: cn=Dynamic List of Members,ou=Dynamic Lists,dc=example,dc=com
+objectClass: groupOfURLs
+cn: Dynamic List of Members
+memberURL: ldap:///ou=People,dc=example,dc=com??sub?(objectClass=person)
+
+# Testing list search with dgIdentity...
+dn: cn=Dynamic List of Members,ou=Dynamic Lists,dc=example,dc=com
+objectClass: groupOfURLs
+objectClass: dgIdentityAux
+cn: Dynamic List of Members
+memberURL: ldap:///ou=People,dc=example,dc=com??sub?(objectClass=person)
+dgIdentity: cn=Bjorn Jensen,ou=Information Technology Division,ou=People,dc=ex
+ ample,dc=com
+member: cn=Barbara Jensen,ou=Information Technology Division,ou=People,dc=exam
+ ple,dc=com
+member: cn=Bjorn Jensen,ou=Information Technology Division,ou=People,dc=exampl
+ e,dc=com
+member: cn=Dorothy Stevens,ou=Alumni Association,ou=People,dc=example,dc=com
+member: cn=James A Jones 1,ou=Alumni Association,ou=People,dc=example,dc=com
+member: cn=James A Jones 2,ou=Information Technology Division,ou=People,dc=exa
+ mple,dc=com
+member: cn=Jane Doe,ou=Alumni Association,ou=People,dc=example,dc=com
+member: cn=Jennifer Smith,ou=Alumni Association,ou=People,dc=example,dc=com
+member: cn=John Doe,ou=Information Technology Division,ou=People,dc=example,dc
+ =com
+member: cn=Mark Elliot,ou=Alumni Association,ou=People,dc=example,dc=com
+member: cn=Ursula Hampster,ou=Alumni Association,ou=People,dc=example,dc=com
+
index 792a1605cda7d1aa833d3ff1b668e3ad0d444152..f90ad4854fd64a72ff88e5629513a7c03974723d 100644 (file)
@@ -37,6 +37,7 @@ argsfile      @TESTDIR@/slapd.1.args
 
 access to dn=""
        by * read
+
 access to dn="cn=Subschema"
        by * read
 
@@ -49,11 +50,9 @@ rootpw               secret
 #bdb#index             cn,sn,uid       pres,eq,sub
 #hdb#index             objectClass     eq
 #hdb#index             cn,sn,uid       pres,eq,sub
-#ldbm#index            objectClass     eq
-#ldbm#index            cn,sn,uid       pres,eq,sub
 
 access to dn.subtree="dc=example,dc=com"
        by dynacl/aci write
 
 #monitor#database      monitor
-
+#monitor#rootdn                "cn=Monitor"
index 183ce16b1eb4c261ee03ebb99f2b9c01a397d2a7..be1d30f9df2980134bc33537d0d637a1300a00d1 100644 (file)
@@ -42,7 +42,7 @@ access                to *
 #######################################################################
 
 database       @BACKEND@
-#ldbm#cachesize        0
+
 suffix         "dc=example,dc=com"
 directory      @TESTDIR@/db.1.a
 rootdn         "cn=Manager,dc=example,dc=com"
@@ -51,8 +51,6 @@ rootpw                secret
 #bdb#index             cn,sn,uid       pres,eq,sub
 #hdb#index             objectClass     eq
 #hdb#index             cn,sn,uid       pres,eq,sub
-#ldbm#index            objectClass     eq
-#ldbm#index            cn,sn,uid       pres,eq,sub
 
 #access                to attrs=objectclass dn.subtree="dc=example,dc=com"
 access         to attrs=objectclass
index 724acca1e7000b3573406ff709a302da8b18e9a2..2351c31ea654fca1061c3b2844fb9f7a6050f216 100644 (file)
@@ -41,7 +41,5 @@ rootpw                secret
 #bdb#index             cn,sn,uid       pres,eq,sub
 #hdb#index             objectClass     eq
 #hdb#index             cn,sn,uid       pres,eq,sub
-#ldbm#index            objectClass     eq
-#ldbm#index            cn,sn,uid       pres,eq,sub
 
 #monitor#database      monitor
index 731a6e6ab9b0c23d377b04609898499fe0a8c4e4..9266919d5a393959b63aa58395f61be99332fb34 100644 (file)
@@ -50,7 +50,7 @@ chain-idassert-bind   bindmethod=simple
 #
 
 database       @BACKEND@
-#ldbm#cachesize        0
+
 suffix         "dc=example,dc=com"
 directory      @TESTDIR@/db.1.a
 rootdn         "cn=Manager,dc=example,dc=com"
@@ -59,7 +59,5 @@ rootpw                secret
 #bdb#index             cn,sn,uid       pres,eq,sub
 #hdb#index             objectClass     eq
 #hdb#index             cn,sn,uid       pres,eq,sub
-#ldbm#index            objectClass     eq
-#ldbm#index            cn,sn,uid       pres,eq,sub
 
 #monitor#database      monitor
index b4fc03228af255df958082b7bd277e2161b09194..ce70d3c68aec3c382c30eb62125cf452cc33ca6f 100644 (file)
@@ -39,7 +39,7 @@ argsfile      @TESTDIR@/slapd.2.args
 #
 
 database       @BACKEND@
-#ldbm#cachesize        0
+
 suffix         "dc=example,dc=com"
 directory      @TESTDIR@/db.2.a
 rootdn         "cn=Manager,dc=example,dc=com"
@@ -48,8 +48,6 @@ rootpw                secret
 #bdb#index             cn,sn,uid       pres,eq,sub
 #hdb#index             objectClass     eq
 #hdb#index             cn,sn,uid       pres,eq,sub
-#ldbm#index            objectClass     eq
-#ldbm#index            cn,sn,uid       pres,eq,sub
 
 #
 # uses the chain overlay as database specific;
index 8c191a53616ecb36ac677e414869eefd3f3482bb..ab052b8bea51e1d1b1de9c3e3b7a8fad9e7c31b3 100644 (file)
@@ -44,6 +44,5 @@ rootdn                "cn=Manager,dc=example,dc=com"
 rootpw         secret
 #bdb#index             objectClass eq
 #hdb#index             objectClass eq
-#ldbm#index            objectClass eq
 
 #monitor#database      monitor
index d3013c3328e15cbf81c1d15f326850034bbcabd7..5b1e51ab3cba839151d01fad185af405e216cd31 100644 (file)
@@ -14,10 +14,8 @@ rootpw               secret
 #bdb#index             cn,sn,uid       pres,eq,sub
 #hdb#index             objectClass     eq
 #hdb#index             cn,sn,uid       pres,eq,sub
-#ldbm#index            objectClass     eq
-#ldbm#index            cn,sn,uid       pres,eq,sub
 
 #monitor#database      monitor
 
 database config
-include                "configpw.conf"
+include                @TESTDIR@/configpw.conf
index 3fe61a889a2ddbe5a1c3b6884c8048ef03429d6b..19ec40ebdcf035888a6f90d38d75a05f65ebc4f8 100644 (file)
@@ -46,9 +46,6 @@ rootpw                secret
 #hdb#index             objectClass     eq
 #hdb#index             cn,sn,uid       pres,eq,sub
 #hdb#index             entryExpireTimestamp    eq
-#ldbm#index            objectClass     eq
-#ldbm#index            cn,sn,uid       pres,eq,sub
-#ldbm#index            entryExpireTimestamp    eq
 
 overlay                dds
 dds-max-ttl    1d
index 23c0c4846042112e1682c88028234b57e868dbe8..6a17f4bc26891e14b71a04f9780e364198d61f38 100644 (file)
@@ -44,8 +44,6 @@ rootdn                "cn=Manager,dc=example,dc=com"
 #bdb#index             entryUUID,entryCSN      eq
 #hdb#index             objectClass     eq
 #hdb#index             entryUUID,entryCSN      eq
-#ldbm#index            objectClass     eq
-#ldbm#index            entryUUID,entryCSN      eq
 
 overlay syncprov
 syncprov-reloadhint true
@@ -63,8 +61,8 @@ rootpw                secret
 #hdb#index             objectClass     eq
 #hdb#index             cn,sn,uid       pres,eq,sub
 #hdb#index             entryUUID,entryCSN      eq
-#ldbm#index            objectClass     eq
-#ldbm#index            cn,sn,uid       pres,eq,sub
+
+
 access to *
        by users write
        by * read
index 8f363f118f96809d47c2238fbdb6aefb7142632c..438ee50928612d1ac34516a2bf9b4385756cb1f4 100644 (file)
@@ -52,8 +52,6 @@ rootpw                secret
 #bdb#index             cn,sn,uid       pres,eq,sub
 #hdb#index             objectClass     eq
 #hdb#index             cn,sn,uid       pres,eq,sub
-#ldbm#index            objectClass     eq
-#ldbm#index            cn,sn,uid       pres,eq,sub
 
 # Don't change syncrepl spec yet
 syncrepl       rid=1
index 81a387c9391c407ae6106ee3249286cc79a9edb6..5aa6ba6e1bfcb0580610415b4d6f457baea1a3b2 100644 (file)
@@ -42,7 +42,5 @@ rootpw                secret
 #bdb#index             cn,sn,uid       pres,eq,sub
 #hdb#index             objectClass     eq
 #hdb#index             cn,sn,uid       pres,eq,sub
-#ldbm#index            objectClass     eq
-#ldbm#index            cn,sn,uid       pres,eq,sub
 
 #monitor#database      monitor
index fe86edcac648f878e7ac9b7469ad942347f80907..166e58f91220f966a0826b068370c1cc771f149d 100644 (file)
@@ -5,4 +5,4 @@ cn: config
 dn: olcDatabase={0}config,cn=config
 objectClass: olcDatabaseConfig
 olcDatabase: {0}config
-olcRootPW:< file:configpw
+olcRootPW:< file://@TESTDIR@/configpw
index 1584074eebd375201cbe08c0882805b26536f9d8..ef2b13ad94db3d008d91b1d1ac49e8e93ebd5fbc 100644 (file)
@@ -46,8 +46,10 @@ rootpw               secret
 #bdb#index             cn,sn,uid       pres,eq,sub
 #hdb#index             objectClass     eq
 #hdb#index             cn,sn,uid       pres,eq,sub
-#ldbm#index            objectClass     eq
-#ldbm#index            cn,sn,uid       pres,eq,sub
 
+# we'll reconfigure the attrset dynamically
 overlay                        dynlist
-### DO NOT ADD ANY DIRECTIVE BELOW THIS; TEST APPENDS STUFF ###
+dynlist-attrset        groupOfURLs memberURL
+
+database config
+include @TESTDIR@/configpw.conf
index 5ee7b7917d6083da9eee3df17a09cb0d32f11853..f7ec5c5394f867dc21f054ab2009e04565315b14 100644 (file)
@@ -47,8 +47,6 @@ rootpw                secret
 #bdb#index             cn,sn,uid       pres,eq,sub
 #hdb#index             objectClass     eq
 #hdb#index             cn,sn,uid       pres,eq,sub
-#ldbm#index            objectClass     eq
-#ldbm#index            cn,sn,uid       pres,eq,sub
 
 access         to attrs=userPassword
                by dn.exact="cn=Manager,c=US" write
@@ -72,8 +70,6 @@ rootpw                secret
 #bdb#index             cn,sn,uid       pres,eq,sub
 #hdb#index             objectClass     eq
 #hdb#index             cn,sn,uid       pres,eq,sub
-#ldbm#index            objectClass     eq
-#ldbm#index            cn,sn,uid       pres,eq,sub
 
 access         to attrs=userPassword
                by self =wx
index 6748d8b6c1d7fda087ccb8f164090ccf0e525dee..5ee6a8d8177cd921f5d159b4bb033e6175578c1a 100644 (file)
@@ -45,11 +45,7 @@ rootdn               "cn=Manager 1,dc=example,dc=com"
 #hdb#index             uid     pres,eq,sub
 #hdb#index             cn,sn   pres,eq,sub,subany
 #hdb#index             entryUUID,entryCSN      pres
-#ldbm#index            objectclass     eq
-#ldbm#index            uid     pres,eq,sub
-#ldbm#index            cn,sn   pres,eq,sub,subany
-#ldbm#dbnosync
-#ldbm#dbnolocking
+
 overlay                syncprov
 
 database       @BACKEND@
@@ -65,11 +61,7 @@ rootdn               "cn=Manager 1,dc=example,dc=com"
 #hdb#index             uid     pres,eq,sub
 #hdb#index             cn,sn   pres,eq,sub,subany
 #hdb#index             entryUUID,entryCSN      pres
-#ldbm#index            objectclass     eq
-#ldbm#index            uid     pres,eq,sub
-#ldbm#index            cn,sn   pres,eq,sub,subany
-#ldbm#dbnosync
-#ldbm#dbnolocking
+
 syncrepl       rid=1
                provider=@URI2@
                binddn="cn=Manager 2,dc=example,dc=com"
@@ -97,11 +89,7 @@ rootpw               secret
 #hdb#index             objectclass     eq
 #hdb#index             uid     pres,eq,sub
 #hdb#index             cn,sn   pres,eq,sub,subany
-#ldbm#index            objectclass     eq
-#ldbm#index            uid     pres,eq,sub
-#ldbm#index            cn,sn   pres,eq,sub,subany
-#ldbm#dbnosync
-#ldbm#dbnolocking
+
 #overlay               syncprov
 
 #monitor#database      monitor
index e84ac49add6d76e2d13e581964376926039aa8bf..f4fcbdb55e5c3d384fb36b87846bddf1463b0ab1 100644 (file)
@@ -45,11 +45,8 @@ rootdn               "cn=Manager 2,dc=example,dc=com"
 #hdb#index             uid     pres,eq,sub
 #hdb#index             cn,sn   pres,eq,sub,subany
 #hdb#index             entryUUID,entryCSN      pres
-#ldbm#index            objectclass     eq
-#ldbm#index            uid     pres,eq,sub
-#ldbm#index            cn,sn   pres,eq,sub,subany
-#ldbm#dbnosync
-#ldbm#dbnolocking
+
+
 syncrepl       rid=2
                provider=@URI1@
                binddn="cn=Manager 1,dc=example,dc=com"
@@ -78,11 +75,8 @@ rootdn               "cn=Manager 2,dc=example,dc=com"
 #hdb#index             uid     pres,eq,sub
 #hdb#index             cn,sn   pres,eq,sub,subany
 #hdb#index             entryUUID,entryCSN      pres
-#ldbm#index            objectclass     eq
-#ldbm#index            uid     pres,eq,sub
-#ldbm#index            cn,sn   pres,eq,sub,subany
-#ldbm#dbnosync
-#ldbm#dbnolocking
+
+
 overlay                syncprov
 
 
@@ -97,11 +91,8 @@ rootpw               secret
 #hdb#index             objectclass     eq
 #hdb#index             uid     pres,eq,sub
 #hdb#index             cn,sn   pres,eq,sub,subany
-#ldbm#index            objectclass     eq
-#ldbm#index            uid     pres,eq,sub
-#ldbm#index            cn,sn   pres,eq,sub,subany
-#ldbm#dbnosync
-#ldbm#dbnolocking
+
+
 #overlay               syncprov
 
 #monitor#database      monitor
index 9cac035bea16037c5471c2d02488bd827ee74117..747559144594f6cd2740ef7d4fe8eb36a5601c99 100644 (file)
@@ -42,11 +42,6 @@ rootdn               "cn=Manager, dc=example,dc=com"
 #hdb#index             objectclass     eq
 #hdb#index             uid     pres,eq,sub
 #hdb#index             cn,sn   pres,eq,sub,subany
-#ldbm#index            objectclass     eq
-#ldbm#index            uid     pres,eq,sub
-#ldbm#index            cn,sn   pres,eq,sub,subany
-#ldbm#dbnosync
-#ldbm#dbnolocking
 
 database       @BACKEND@
 suffix         "ou=Groups,dc=example,dc=com"
@@ -59,11 +54,6 @@ rootdn               "cn=Manager, dc=example,dc=com"
 #hdb#index             objectclass     eq
 #hdb#index             uid     pres,eq,sub
 #hdb#index             cn,sn   pres,eq,sub,subany
-#ldbm#index            objectclass     eq
-#ldbm#index            uid     pres,eq,sub
-#ldbm#index            cn,sn   pres,eq,sub,subany
-#ldbm#dbnosync
-#ldbm#dbnolocking
 
 database       @BACKEND@
 suffix         "dc=example,dc=com"
@@ -76,10 +66,5 @@ rootpw               secret
 #hdb#index             objectclass     eq
 #hdb#index             uid     pres,eq,sub
 #hdb#index             cn,sn   pres,eq,sub,subany
-#ldbm#index            objectclass     eq
-#ldbm#index            uid     pres,eq,sub
-#ldbm#index            cn,sn   pres,eq,sub,subany
-#ldbm#dbnosync
-#ldbm#dbnolocking
 
 #monitor#database      monitor
index 101e053ddf46ef417e6aac91e5905f4e9b94327a..e9f92300d09eecbecd71682cc44bcd17c5e26b9b 100644 (file)
@@ -58,7 +58,7 @@ access to *
        by * search
 
 database       @BACKEND@
-#ldbm#cachesize        0
+
 suffix         "dc=example,dc=com"
 directory      @TESTDIR@/db.1.a
 rootdn         "cn=Manager,dc=example,dc=com"
@@ -67,8 +67,6 @@ rootpw                secret
 #bdb#index             cn,sn,uid       pres,eq,sub
 #hdb#index             objectClass     eq
 #hdb#index             cn,sn,uid       pres,eq,sub
-#ldbm#index            objectClass     eq
-#ldbm#index            cn,sn,uid       pres,eq,sub
 
 access to dn.exact="cn=Proxy,ou=Admin,dc=example,dc=com"
                attrs=authzTo
@@ -76,7 +74,7 @@ access to dn.exact="cn=Proxy,ou=Admin,dc=example,dc=com"
        by * =x
 
 database       @BACKEND@
-#ldbm#cachesize        0
+
 suffix         "dc=example,dc=it"
 directory      @TESTDIR@/db.2.a
 rootdn         "cn=Manager,dc=example,dc=it"
@@ -85,8 +83,6 @@ rootpw                secret
 #bdb#index             cn,sn,uid       pres,eq,sub
 #hdb#index             objectClass     eq
 #hdb#index             cn,sn,uid       pres,eq,sub
-#ldbm#index            objectClass     eq
-#ldbm#index            cn,sn,uid       pres,eq,sub
 
 database       ldap
 suffix         "o=Example,c=US"
index 2ec9f7b89f8d13aa64ceafabbc8023f5ccf0813e..9e3820923361f52c8b5e892f498a58ffe1c9221a 100644 (file)
@@ -76,7 +76,5 @@ rootpw                secret
 #bdb#index             cn,sn,uid       pres,eq,sub
 #hdb#index             objectClass     eq
 #hdb#index             cn,sn,uid       pres,eq,sub
-#ldbm#index            objectClass     eq
-#ldbm#index            cn,sn,uid       pres,eq,sub
 
 #monitor#database      monitor
index 5df507614b76443e8287d32185774e378351deaf..78a359aaf5e2afd72c00ce70676050908727ac20 100644 (file)
@@ -58,7 +58,5 @@ rootpw                secret
 #bdb#index             cn,sn,uid       pres,eq,sub
 #hdb#index             objectClass     eq
 #hdb#index             cn,sn,uid       pres,eq,sub
-#ldbm#index            objectClass     eq
-#ldbm#index            cn,sn,uid       pres,eq,sub
 
 #monitor#database      monitor
index bd9d199f112449df240ca1aa0c38c89f2e7d3ecb..7c0a86b74154a597eff791cfeb01c5a4f1c770f8 100644 (file)
@@ -59,7 +59,5 @@ rootpw                secret
 #bdb#index             cn,sn,uid       pres,eq,sub
 #hdb#index             objectClass     eq
 #hdb#index             cn,sn,uid       pres,eq,sub
-#ldbm#index            objectClass     eq
-#ldbm#index            cn,sn,uid       pres,eq,sub
 
 #monitor#database      monitor
index cdf8dddf61e4d66fc873374e411846dcc9b6f7c4..a175669c65b8e8415ecf8259fdf7c3fa793e3003 100644 (file)
@@ -41,8 +41,6 @@ rootpw                secret
 #bdb#index             uid eq
 #hdb#index             objectClass eq
 #hdb#index             uid eq
-#ldbm#index            objectClass eq
-#ldbm#index            uid eq
 
 # Need extra limits for pagedResults on backends that support it...
 #bdb#limits    dn.exact="cn=Unlimited User,ou=Paged Results Users,dc=example,dc=com" size=4 size.pr=unlimited
index 300e64eeb3e8b9042b9c287c71284f75e9c3c9a2..6d0ad65d657402aebb1d897c3e2cb734589ba416 100644 (file)
@@ -41,6 +41,5 @@ rootdn                "cn=Manager,dc=example,dc=com"
 rootpw         secret
 #bdb#index             objectClass eq
 #hdb#index             objectClass eq
-#ldbm#index            objectClass eq
 
 #monitor#database      monitor
index 45bd83da31805d05e8cb96551a48a0c0bd559981..fda3b5e75f58624dec04dd76e523807371763cee 100644 (file)
@@ -48,6 +48,5 @@ rootdn                "cn=Manager,ou=Meta,dc=example,dc=com"
 rootpw         secret
 #bdb#index             objectClass eq
 #hdb#index             objectClass eq
-#ldbm#index            objectClass eq
 
 #monitor#database      monitor
index 5f6aab942c3fe5d3b5cf3ecbf90be5758360442f..83d16762f210ec7cc8af9acaa3a57a0f56ece338 100644 (file)
@@ -40,7 +40,7 @@ rootdn                "cn=Manager,dc=example,dc=com"
 rootpw         secret
 #bdb#index             objectClass eq
 #hdb#index             objectClass eq
-#ldbm#index            objectClass eq
+
 overlay                ppolicy
 ppolicy_default        "cn=Standard Policy,ou=Policies,dc=example,dc=com"
 ppolicy_use_lockout
index ceafcfc585d1b9ce3eee83af8fadcd7fdb07124d..b9257c8ff3895a639b7611a130b689dfeac44815 100644 (file)
@@ -52,13 +52,11 @@ proxytemplate       (mail=) 0 @CACHETTL@
        
 #bdb#cachesize 20
 #hdb#cachesize 20
-#ldbm#cachesize 20
+
 directory      @TESTDIR@/db.2.a
 #bdb#index             objectClass     eq
 #bdb#index             cn,sn,uid,mail  pres,eq,sub
 #hdb#index             objectClass     eq
 #hdb#index             cn,sn,uid,mail  pres,eq,sub
-#ldbm#index            objectClass     eq
-#ldbm#index            cn,sn,uid,mail  pres,eq,sub
 
 #monitor#database      monitor
index 3b3d28605f7b3359b46f240f937990d76a8cb9cd..fd734d9ae955206b194a8e37e1aed2fd1287582e 100644 (file)
@@ -32,7 +32,7 @@ argsfile      @TESTDIR@/slapd.1.args
 #######################################################################
 
 database       @BACKEND@
-#ldbm#cachesize        0
+
 suffix         "dc=example,dc=com"
 directory      @TESTDIR@/db.1.a
 rootdn         "cn=Manager,dc=example,dc=com"
@@ -41,8 +41,6 @@ rootpw                secret
 #bdb#index             cn,sn,uid       pres,eq,sub
 #hdb#index             objectClass     eq
 #hdb#index             cn,sn,uid       pres,eq,sub
-#ldbm#index            objectClass     eq
-#ldbm#index            cn,sn,uid       pres,eq,sub
 
 #
 # normal installations should protect root dse,
index 86a96ba9f2fa27c7876d3aaddc0ec87e9bf6242c..aa31427b60c781d6137074d44f1858636c7403a2 100644 (file)
@@ -37,7 +37,7 @@ referral      "@URI1@"
 database       @BACKEND@
 #bdb#cachesize 0
 #hdb#cachesize 0
-#ldbm#cachesize        0
+
 suffix         "o=University of Mich,c=US"
 directory      @TESTDIR@/db.2.a
 rootdn         "cn=Manager,o=University of Mich,c=US"
@@ -46,7 +46,5 @@ rootpw                secret
 #bdb#index             cn,sn,uid       pres,eq,sub
 #hdb#index             objectClass     eq
 #hdb#index             cn,sn,uid       pres,eq,sub
-#ldbm#index            objectClass     eq
-#ldbm#index            cn,sn,uid       pres,eq,sub
 
 #monitor#database      monitor
index 83b010115a75bece2ff6368f927857013f9ae40e..08206ace0c710c2bfcf7bed93e8aec5ff815c708 100644 (file)
@@ -38,6 +38,5 @@ rootdn                "cn=Manager,c=us"
 rootpw         secret
 #bdb#index             objectClass eq
 #hdb#index             objectClass eq
-#ldbm#index            objectClass eq
 
 #monitor#database      monitor
index be919c529efb0d736840aa660c08ff95d49c0226..b48de564c194670e841a1aa24edde1e53a03d350 100644 (file)
@@ -43,8 +43,6 @@ rootpw                secret
 #bdb#index             cn,sn,uid       pres,eq,sub
 #hdb#index             objectClass     eq
 #hdb#index             cn,sn,uid       pres,eq,sub
-#ldbm#index            objectClass     eq
-#ldbm#index            cn,sn,uid       pres,eq,sub
 
 overlay                refint
 refint_attributes      manager secretary member
index a4375def3c6fdd69339499b972718e7612b0fce1..e7ec3e17aa5999b4de123fbbca4970c049e306ce 100644 (file)
@@ -46,12 +46,13 @@ rootdn              "cn=Manager,dc=example,dc=com"
 rootpw         secret
 #bdb#index             objectClass eq
 #hdb#index             objectClass eq
-#ldbm#index            objectClass eq
 
 database       @RELAY@
 suffix         "o=Example,c=US"
 ### back-relay can automatically instantiate the rwm overlay
-#relay-relay#relay             "dc=example,dc=com" massage
+#relay-relay#relay             "dc=example,dc=com"
+#relay-relay#overlay           rwm
+#relay-relay#rwm-suffixmassage "dc=example,dc=com"
 #relay-relay#rwm-map           objectClass groupOfNames groupOfUniqueNames
 #relay-relay#rwm-map           objectClass uidObject dcObject
 #relay-relay#rwm-map           attribute member uniqueMember
@@ -87,7 +88,9 @@ suffix                "o=Esempio,c=IT"
 database       @RELAY@
 suffix         "o=Beispiel,c=DE"
 ### back-relay can automatically instantiate the rwm overlay
-#relay-relay#relay             "dc=example,dc=com" massage
+#relay-relay#relay             "dc=example,dc=com"
+#relay-relay#overlay           rwm
+#relay-relay#rwm-suffixmassage "dc=example,dc=com"
 ### back-ldap needs explicit instantiation of the rwm overlay
 #relay-ldap#uri                "@URI1@"
 #relay-ldap#overlay            rwm
diff --git a/tests/data/slapd-repl-master.conf b/tests/data/slapd-repl-master.conf
deleted file mode 100644 (file)
index b77357b..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-# master slapd config -- for testing of replication
-# $OpenLDAP: pkg/ldap/tests/data/slapd-repl-master.conf,v 1.27.2.4 2003/12/15 
- 22:05:29 kurt Exp $
-## This work is part of OpenLDAP Software <http://www.openldap.org/>.
-##
-## Copyright 1998-2007 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                @SCHEMADIR@/core.schema
-include                @SCHEMADIR@/cosine.schema
-include                @SCHEMADIR@/inetorgperson.schema
-include                @SCHEMADIR@/openldap.schema
-include                @SCHEMADIR@/nis.schema
-#
-pidfile                @TESTDIR@/slapd.1.pid
-argsfile       @TESTDIR@/slapd.1.args
-
-#mod#modulepath        ../servers/slapd/back-@BACKEND@/
-#mod#moduleload        back_@BACKEND@.la
-#monitormod#modulepath ../servers/slapd/back-monitor/
-#monitormod#moduleload back_monitor.la
-
-#######################################################################
-# database definitions
-#######################################################################
-
-database       @BACKEND@
-#ldbm#cachesize        0
-suffix         "dc=example,dc=com"
-directory      @TESTDIR@/db.1.a
-rootdn         "cn=Manager,dc=example,dc=com"
-rootpw         secret
-#bdb#index             objectClass     eq
-#bdb#index             cn,sn,uid       pres,eq,sub
-#hdb#index             objectClass     eq
-#hdb#index             cn,sn,uid       pres,eq,sub
-#ldbm#index            objectClass     eq
-#ldbm#index            cn,sn,uid       pres,eq,sub
-
-replogfile     @TESTDIR@/slapd.1.replog
-
-replica-argsfile       @TESTDIR@/replica.1.args
-replica-pidfile                @TESTDIR@/replica.1.pid
-
-replica                host=localhost:@PORT2@
-               binddn="cn=Replica,dc=example,dc=com"
-               bindmethod=simple
-               credentials=secret
-
-#monitor#database      monitor
index 72838619543e970c7cac455612d110df9f3818f2..00642ef3efb04764a59b41ba9573a028119cbb88 100644 (file)
@@ -48,7 +48,7 @@ access to *
        by * read
 
 database       @BACKEND@
-#ldbm#cachesize        0
+
 suffix         "dc=example,dc=com"
 directory      @TESTDIR@/db.2.a
 rootdn         "cn=Replica,dc=example,dc=com"
diff --git a/tests/data/slapd-repl-slave.conf b/tests/data/slapd-repl-slave.conf
deleted file mode 100644 (file)
index 0ae0f5f..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-# slave slapd config -- for testing of replication
-# $OpenLDAP: pkg/ldap/tests/data/slapd-repl-slave.conf,v 1.31.2.4 2003/12/15 2
- 2:05:29 kurt Exp $
-## This work is part of OpenLDAP Software <http://www.openldap.org/>.
-##
-## Copyright 1998-2007 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                @SCHEMADIR@/core.schema
-include                @SCHEMADIR@/cosine.schema
-include                @SCHEMADIR@/inetorgperson.schema
-include                @SCHEMADIR@/openldap.schema
-include                @SCHEMADIR@/nis.schema
-#
-pidfile                @TESTDIR@/slapd.2.pid
-argsfile       @TESTDIR@/slapd.2.args
-
-#mod#modulepath        ../servers/slapd/back-@BACKEND@/
-#mod#moduleload        back_@BACKEND@.la
-#monitormod#modulepath ../servers/slapd/back-monitor/
-#monitormod#moduleload back_monitor.la
-#ldapmod#modulepath ../servers/slapd/back-ldap/
-#ldapmod#moduleload back_ldap.la
-
-#ldapyes#overlay               chain
-#ldapyes#chain-uri             @URI1@
-#ldapyes#chain-idassert-bind   bindmethod=simple binddn="cn=Manager,dc=example,dc=com" credentials=secret mode=self
-#ldapmod#overlay               chain
-#ldapmod#chain-uri             @URI1@
-#ldapmod#chain-idassert-bind   bindmethod=simple binddn="cn=Manager,dc=example,dc=com" credentials=secret mode=self
-
-#######################################################################
-# database definitions
-#######################################################################
-
-database       @BACKEND@
-#ldbm#cachesize        0
-suffix         "dc=example,dc=com"
-directory      @TESTDIR@/db.2.a
-rootdn         "cn=Replica,dc=example,dc=com"
-rootpw         secret
-updatedn       "cn=Replica,dc=example,dc=com"
-updateref      @URI1@
-#bdb#index             objectClass     eq
-#bdb#index             cn,sn,uid       pres,eq,sub
-#hdb#index             objectClass     eq
-#hdb#index             cn,sn,uid       pres,eq,sub
-#ldbm#index            objectClass     eq
-#ldbm#index            cn,sn,uid       pres,eq,sub
-
-#monitor#database      monitor
index a9984009cee57e3454a52b3df214c0065e21bfb1..d85027fdacfa57502fcc70e01e09d755c80036cb 100644 (file)
@@ -44,8 +44,6 @@ rootpw                secret
 #bdb#index             cn,sn,uid       pres,eq,sub
 #hdb#index             objectClass     eq
 #hdb#index             cn,sn,uid       pres,eq,sub
-#ldbm#index            objectClass     eq
-#ldbm#index            cn,sn,uid       pres,eq,sub
 
 overlay                retcode
 retcode-parent "ou=RetCodes,dc=example,dc=com"
index 341ea1910b488a052b6a58751302173d19b8ec04..28844fcd9c80880fb1c5c751a3066197bdb04ac9 100644 (file)
@@ -50,7 +50,6 @@ suffix                "o=OpenLDAP Project,l=Internet"
 directory      @TESTDIR@/db.1.a
 #bdb#index             objectClass eq
 #hdb#index             objectClass eq
-#ldbm#index            objectClass eq
 
 #database      @BACKEND@
 #suffix                "dc=example,dc=com"
index c2a34ef617cfce1318fe474b3cfb5b0e3285ece4..7ff8153f9b73031da4e7d4b6e2b4d81cd01db9a2 100644 (file)
@@ -45,8 +45,6 @@ rootpw                secret
 #hdb#index             objectClass     eq
 #hdb#index             cn,sn,uid       pres,eq,sub
 #hdb#index             entryUUID,entryCSN      eq
-#ldbm#index            objectClass     eq
-#ldbm#index            cn,sn,uid       pres,eq,sub
 
 overlay        syncprov
 #syncprov-sessionlog 100
index d0b1486d2a2513054ce8968779aa11bb088ad998..4b7dfb65ad4f50712c6357ed6b5e57f3b2d293e5 100644 (file)
@@ -46,8 +46,6 @@ rootpw                secret
 #hdb#index             objectClass     eq
 #hdb#index             cn,sn,uid       pres,eq,sub
 #hdb#index             entryUUID,entryCSN      eq
-#ldbm#index            objectClass     eq
-#ldbm#index            cn,sn,uid       pres,eq,sub
 
 overlay        syncprov
 syncprov-sessionlog 100
index 5e6ac0590c627ba977cb1a33c8683d2bf9f233c5..bf310e43d30a0a501ecfc353a926238a9baba476 100644 (file)
@@ -52,8 +52,6 @@ rootpw                secret
 #bdb#index             cn,sn,uid       pres,eq,sub
 #hdb#index             objectClass     eq
 #hdb#index             cn,sn,uid       pres,eq,sub
-#ldbm#index            objectClass     eq
-#ldbm#index            cn,sn,uid       pres,eq,sub
 
 # Don't change syncrepl spec yet
 syncrepl       rid=1
index 7cd0f9d6f7def6b4b6c0363d873548498447e490..a045dfbdbf185066400abb0d8218d0e1e4939702 100644 (file)
@@ -31,8 +31,6 @@ rootpw                secret
 #hdb#index             objectClass     eq
 #hdb#index             cn,sn,uid       pres,eq,sub
 #hdb#index             entryUUID,entryCSN      eq
-#ldbm#index            objectClass     eq
-#ldbm#index            cn,sn,uid       pres,eq,sub
 
 # Don't change syncrepl spec yet
 syncrepl       rid=1
index 0aa36885510a665f4aef944616cb955d81897c2c..38614190674f980f0a550b490105c160bb98e1c5 100644 (file)
@@ -43,8 +43,6 @@ rootpw                secret
 #hdb#index             objectClass     eq
 #hdb#index             cn,sn,uid       pres,eq,sub
 #hdb#index             entryUUID,entryCSN      eq
-#ldbm#index            objectClass     eq
-#ldbm#index            cn,sn,uid       pres,eq,sub
 
 # Don't change syncrepl spec yet
 syncrepl       rid=1
index 3be2b74ea4dc636cc2dc610628cbfa792a582e98..5ae37edb0a2fa4106ddfdc97e253b91895e0d942 100644 (file)
@@ -45,9 +45,6 @@ rootpw                secret
 #hdb#index             objectClass     eq
 #hdb#index             cn,sn,uid       pres,eq,sub
 #hdb#index             entryUUID,entryCSN      eq
-#ldbm#index            objectClass     eq
-#ldbm#index            cn,sn,uid       pres,eq,sub
-#ldbm#index            entryUUID       eq
 
 # Don't change syncrepl spec yet
 syncrepl       rid=1
index a5edc4f0bd6900b3c516a3ff60740b5c09384c31..28f3a009579693db48a7bc65d397ba7ac7631b0c 100644 (file)
@@ -43,9 +43,6 @@ rootpw                secret
 #hdb#index             objectClass     eq
 #hdb#index             cn,sn,uid       pres,eq,sub
 #hdb#index             entryUUID,entryCSN      eq
-#ldbm#index            objectClass     eq
-#ldbm#index            cn,sn,uid       pres,eq,sub
-#ldbm#index            entryUUID       eq
 
 # Don't change syncrepl spec yet
 syncrepl       rid=1
index df59b2313e3af368c4c8bd9a63f881bafde6cea4..68b85c4cb063fc295ad7ea83e51b9453c067cf71 100644 (file)
@@ -48,8 +48,6 @@ rootpw                secret
 #bdb#index             cn,sn,uid       pres,eq,sub
 #hdb#index             objectClass     eq
 #hdb#index             cn,sn,uid       pres,eq,sub
-#ldbm#index            objectClass     eq
-#ldbm#index            cn,sn,uid       pres,eq,sub
 
 overlay                translucent
 translucent_no_glue
@@ -63,4 +61,4 @@ lastmod       off
 acl-bind       binddn="uid=binder,o=translucent" credentials="bindtest"
 
 database config
-include                "configpw.conf"
+include                @TESTDIR@/configpw.conf
index f331d05d92290e155be3786243129b0df5b31ac9..6df5af9efe9b656329d43060ae444606b78e5c52 100644 (file)
@@ -44,6 +44,3 @@ rootpw                secret
 #bdb#index             cn,sn,uid       pres,eq,sub
 #hdb#index             objectClass     eq
 #hdb#index             cn,sn,uid       pres,eq,sub
-#ldbm#index            objectClass     eq
-#ldbm#index            cn,sn,uid       pres,eq,sub
-
index 1a12ffba63a7ac6ca8c75c53b94e78579dc8f4ee..2a24636a9cd82b89a92529c454d2dd52e18631ee 100644 (file)
@@ -43,11 +43,16 @@ rootpw              secret
 #bdb#index             cn,sn,uid       pres,eq,sub
 #hdb#index             objectClass     eq
 #hdb#index             cn,sn,uid       pres,eq,sub
-#ldbm#index            objectClass     eq
-#ldbm#index            cn,sn,uid       pres,eq,sub
 
 overlay                        unique
-unique_ignore          o cn sn ou objectClass
+
 unique_attributes      employeeNumber displayName
+unique_base            o=unique
+
+#unique_uri ldap:///?description?one
+#unique_uri ldap:///?employeeNumber,displayName?sub
 
 #monitor#database      monitor
+
+database config
+include                @TESTDIR@/configpw.conf
index 468e959b56c11e2d3999ecb3aed3394b72854fa1..e9a70ab3cbcc19d48ce2b1579f447289299e9ab6 100644 (file)
@@ -41,8 +41,6 @@ rootpw                secret
 #bdb#index             cn,sn,uid       pres,eq,sub
 #hdb#index             objectClass     eq
 #hdb#index             cn,sn,uid       pres,eq,sub
-#ldbm#index            objectClass     eq
-#ldbm#index            cn,sn,uid       pres,eq,sub
 
 overlay                        valsort
 valsort-attr           sn ou=users,o=valsort alpha-ascend
@@ -52,6 +50,6 @@ valsort-attr            ou ou=users,o=valsort weighted
 valsort-attr            employeeType ou=users,o=valsort weighted alpha-ascend
 
 database config
-include configpw.conf
+include        @TESTDIR@/configpw.conf
 
 #monitor#database      monitor
index c269008052ff3a54edc9cfcdc14031b627e2df00..3da0f45e60afaca47c0688a31e6db1d43d37ebc1 100644 (file)
@@ -52,7 +52,7 @@ access to *
        by * read
 
 database       @BACKEND@
-#ldbm#cachesize        0
+
 suffix         "dc=example,dc=com"
 directory      @TESTDIR@/db.1.a
 rootdn         "cn=Manager,dc=example,dc=com"
@@ -61,7 +61,5 @@ rootpw                secret
 #bdb#index             cn,sn,uid       pres,eq,sub
 #hdb#index             objectClass     eq
 #hdb#index             cn,sn,uid       pres,eq,sub
-#ldbm#index            objectClass     eq
-#ldbm#index            cn,sn,uid       pres,eq,sub
 
 #monitor#database      monitor
index b4e461fb60515f8e9eef682b165672edcc47a5ac..da8880355ae33b63e30c6669a27ca2a4218ef1d7 100644 (file)
@@ -45,7 +45,5 @@ rootpw                secret
 #bdb#index             cn,sn,uid       pres,eq,sub
 #hdb#index             objectClass     eq
 #hdb#index             cn,sn,uid       pres,eq,sub
-#ldbm#index            objectClass     eq
-#ldbm#index            cn,sn,uid       pres,eq,sub
 
 #monitor#database      monitor
index a88f3192b0a78b5d5fa009fbc92ea93ae10010cc..6c9749eae92ca9563b5f5c8bc474b324476c4149 100644 (file)
@@ -6,6 +6,29 @@ o: Example
 dc: example
 
 # Testing onelevel search...
+dn: cn=Akakiy Zinberstein,dc=example,dc=com
+objectClass: inetOrgPerson
+objectClass: pkiUser
+cn: Akakiy Zinberstein
+sn: Zinberstein
+givenName: Akakiy
+userCertificate;binary:: MIIDazCCAtSgAwIBAgIBAjANBgkqhkiG9w0BAQQFADB3MQswCQYDV
+ QQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEfMB0GA1UEChMWT3BlbkxEQVAgRXhhbXBsZSwgTH
+ RkLjETMBEGA1UEAxMKRXhhbXBsZSBDQTEdMBsGCSqGSIb3DQEJARYOY2FAZXhhbXBsZS5jb20wHhc
+ NMDMxMDE3MTYzMzE5WhcNMDQxMDE2MTYzMzE5WjB+MQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2Fs
+ aWZvcm5pYTEfMB0GA1UEChMWT3BlbkxEQVAgRXhhbXBsZSwgTHRkLjEYMBYGA1UEAxMPVXJzdWxhI
+ EhhbXBzdGVyMR8wHQYJKoZIhvcNAQkBFhB1aGFtQGV4YW1wbGUuY29tMIGfMA0GCSqGSIb3DQEBAQ
+ UAA4GNADCBiQKBgQDuxgp5ELV9LmhxWMpV7qc4028QQT3+zzFDXhruuXE7ji2n3S3ea8bOwDtJh+q
+ nsDe561DhHHHlgIjMKCiDEizYMpxvJPYEXmvp0huRkMgpKZgmel95BSkt6TYmJ0erS3aoimOHLEFi
+ mmnTLolNRMiWqNBvqwobx940PGwUWEePKQIDAQABo4H/MIH8MAkGA1UdEwQCMAAwLAYJYIZIAYb4Q
+ gENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0GA1UdDgQWBBSjI94TbBmuDEeUUO
+ iC37EK0Uf0XjCBoQYDVR0jBIGZMIGWgBRLbyEaNiTSkPlDsFNHLX3hwOaYI6F7pHkwdzELMAkGA1U
+ EBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExHzAdBgNVBAoTFk9wZW5MREFQIEV4YW1wbGUsIEx0
+ ZC4xEzARBgNVBAMTCkV4YW1wbGUgQ0ExHTAbBgkqhkiG9w0BCQEWDmNhQGV4YW1wbGUuY29tggEAM
+ A0GCSqGSIb3DQEBBAUAA4GBAIgUcARb3OlWYNbmr1nmqESuxLn16uqI1Ot6WkcICvpkdQ+Bo+R9AP
+ 05xpoXocZtKdNvBu3FNxB/jFkiOcLU2lX7Px1Ijnsjh60qVRy9HOsHCungIKlGcnXLKHmKu0y//5j
+ ds/HnaJsGcHI5JRG7CBJbW+wrwge3trJ1xHJI8prN
+
 dn: documentTitle=book1,dc=example,dc=com
 objectClass: document
 description: abstract1
@@ -21,8 +44,6 @@ documentTitle: book2
 documentAuthor: cn=Mitya Kovalev,dc=example,dc=com
 documentIdentifier: document 2
 
-# refldap://localhost:9012/dc=example,dc=com??one
-
 dn: cn=Mitya Kovalev,dc=example,dc=com
 objectClass: inetOrgPerson
 cn: Mitya Kovalev
@@ -41,13 +62,32 @@ seeAlso: documentTitle=book1,dc=example,dc=com
 givenName: Torvlobnor
 telephoneNumber: 545-4563
 
+# refldap://localhost:9012/dc=example,dc=com??one
+
+# Testing subtree search...
 dn: cn=Akakiy Zinberstein,dc=example,dc=com
 objectClass: inetOrgPerson
+objectClass: pkiUser
 cn: Akakiy Zinberstein
 sn: Zinberstein
 givenName: Akakiy
+userCertificate;binary:: MIIDazCCAtSgAwIBAgIBAjANBgkqhkiG9w0BAQQFADB3MQswCQYDV
+ QQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEfMB0GA1UEChMWT3BlbkxEQVAgRXhhbXBsZSwgTH
+ RkLjETMBEGA1UEAxMKRXhhbXBsZSBDQTEdMBsGCSqGSIb3DQEJARYOY2FAZXhhbXBsZS5jb20wHhc
+ NMDMxMDE3MTYzMzE5WhcNMDQxMDE2MTYzMzE5WjB+MQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2Fs
+ aWZvcm5pYTEfMB0GA1UEChMWT3BlbkxEQVAgRXhhbXBsZSwgTHRkLjEYMBYGA1UEAxMPVXJzdWxhI
+ EhhbXBzdGVyMR8wHQYJKoZIhvcNAQkBFhB1aGFtQGV4YW1wbGUuY29tMIGfMA0GCSqGSIb3DQEBAQ
+ UAA4GNADCBiQKBgQDuxgp5ELV9LmhxWMpV7qc4028QQT3+zzFDXhruuXE7ji2n3S3ea8bOwDtJh+q
+ nsDe561DhHHHlgIjMKCiDEizYMpxvJPYEXmvp0huRkMgpKZgmel95BSkt6TYmJ0erS3aoimOHLEFi
+ mmnTLolNRMiWqNBvqwobx940PGwUWEePKQIDAQABo4H/MIH8MAkGA1UdEwQCMAAwLAYJYIZIAYb4Q
+ gENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0GA1UdDgQWBBSjI94TbBmuDEeUUO
+ iC37EK0Uf0XjCBoQYDVR0jBIGZMIGWgBRLbyEaNiTSkPlDsFNHLX3hwOaYI6F7pHkwdzELMAkGA1U
+ EBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExHzAdBgNVBAoTFk9wZW5MREFQIEV4YW1wbGUsIEx0
+ ZC4xEzARBgNVBAMTCkV4YW1wbGUgQ0ExHTAbBgkqhkiG9w0BCQEWDmNhQGV4YW1wbGUuY29tggEAM
+ A0GCSqGSIb3DQEBBAUAA4GBAIgUcARb3OlWYNbmr1nmqESuxLn16uqI1Ot6WkcICvpkdQ+Bo+R9AP
+ 05xpoXocZtKdNvBu3FNxB/jFkiOcLU2lX7Px1Ijnsjh60qVRy9HOsHCungIKlGcnXLKHmKu0y//5j
+ ds/HnaJsGcHI5JRG7CBJbW+wrwge3trJ1xHJI8prN
 
-# Testing subtree search...
 dn: documentTitle=book1,dc=example,dc=com
 objectClass: document
 description: abstract1
@@ -63,8 +103,6 @@ documentTitle: book2
 documentAuthor: cn=Mitya Kovalev,dc=example,dc=com
 documentIdentifier: document 2
 
-# refldap://localhost:9012/dc=example,dc=com??sub
-
 dn: dc=example,dc=com
 objectClass: organization
 objectClass: dcObject
@@ -89,13 +127,32 @@ seeAlso: documentTitle=book1,dc=example,dc=com
 givenName: Torvlobnor
 telephoneNumber: 545-4563
 
+# refldap://localhost:9012/dc=example,dc=com??sub
+
+# Testing subtree search with manageDSAit...
 dn: cn=Akakiy Zinberstein,dc=example,dc=com
 objectClass: inetOrgPerson
+objectClass: pkiUser
 cn: Akakiy Zinberstein
 sn: Zinberstein
 givenName: Akakiy
+userCertificate;binary:: MIIDazCCAtSgAwIBAgIBAjANBgkqhkiG9w0BAQQFADB3MQswCQYDV
+ QQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEfMB0GA1UEChMWT3BlbkxEQVAgRXhhbXBsZSwgTH
+ RkLjETMBEGA1UEAxMKRXhhbXBsZSBDQTEdMBsGCSqGSIb3DQEJARYOY2FAZXhhbXBsZS5jb20wHhc
+ NMDMxMDE3MTYzMzE5WhcNMDQxMDE2MTYzMzE5WjB+MQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2Fs
+ aWZvcm5pYTEfMB0GA1UEChMWT3BlbkxEQVAgRXhhbXBsZSwgTHRkLjEYMBYGA1UEAxMPVXJzdWxhI
+ EhhbXBzdGVyMR8wHQYJKoZIhvcNAQkBFhB1aGFtQGV4YW1wbGUuY29tMIGfMA0GCSqGSIb3DQEBAQ
+ UAA4GNADCBiQKBgQDuxgp5ELV9LmhxWMpV7qc4028QQT3+zzFDXhruuXE7ji2n3S3ea8bOwDtJh+q
+ nsDe561DhHHHlgIjMKCiDEizYMpxvJPYEXmvp0huRkMgpKZgmel95BSkt6TYmJ0erS3aoimOHLEFi
+ mmnTLolNRMiWqNBvqwobx940PGwUWEePKQIDAQABo4H/MIH8MAkGA1UdEwQCMAAwLAYJYIZIAYb4Q
+ gENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0GA1UdDgQWBBSjI94TbBmuDEeUUO
+ iC37EK0Uf0XjCBoQYDVR0jBIGZMIGWgBRLbyEaNiTSkPlDsFNHLX3hwOaYI6F7pHkwdzELMAkGA1U
+ EBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExHzAdBgNVBAoTFk9wZW5MREFQIEV4YW1wbGUsIEx0
+ ZC4xEzARBgNVBAMTCkV4YW1wbGUgQ0ExHTAbBgkqhkiG9w0BCQEWDmNhQGV4YW1wbGUuY29tggEAM
+ A0GCSqGSIb3DQEBBAUAA4GBAIgUcARb3OlWYNbmr1nmqESuxLn16uqI1Ot6WkcICvpkdQ+Bo+R9AP
+ 05xpoXocZtKdNvBu3FNxB/jFkiOcLU2lX7Px1Ijnsjh60qVRy9HOsHCungIKlGcnXLKHmKu0y//5j
+ ds/HnaJsGcHI5JRG7CBJbW+wrwge3trJ1xHJI8prN
 
-# Testing subtree search with manageDSAit...
 dn: documentTitle=book1,dc=example,dc=com
 objectClass: document
 description: abstract1
@@ -111,12 +168,6 @@ documentTitle: book2
 documentAuthor: cn=Mitya Kovalev,dc=example,dc=com
 documentIdentifier: document 2
 
-dn: ou=Referral,dc=example,dc=com
-objectClass: referral
-objectClass: extensibleObject
-ou: Referral
-ref: ldap://localhost:9012/
-
 dn: dc=example,dc=com
 objectClass: organization
 objectClass: dcObject
@@ -133,6 +184,12 @@ givenName: Mitya
 telephoneNumber: 222-3234
 telephoneNumber: 332-2334
 
+dn: ou=Referral,dc=example,dc=com
+objectClass: referral
+objectClass: extensibleObject
+ou: Referral
+ref: ldap://localhost:9012/
+
 dn: cn=Torvlobnor Puzdoy,dc=example,dc=com
 objectClass: inetOrgPerson
 cn: Torvlobnor Puzdoy
@@ -141,16 +198,8 @@ seeAlso: documentTitle=book1,dc=example,dc=com
 givenName: Torvlobnor
 telephoneNumber: 545-4563
 
-dn: cn=Akakiy Zinberstein,dc=example,dc=com
-objectClass: inetOrgPerson
-cn: Akakiy Zinberstein
-sn: Zinberstein
-givenName: Akakiy
-
 # Testing invalid filter...
 # Testing exact search...
-# refldap://localhost:9012/dc=example,dc=com??sub
-
 dn: cn=Mitya Kovalev,dc=example,dc=com
 objectClass: inetOrgPerson
 cn: Mitya Kovalev
@@ -161,9 +210,9 @@ givenName: Mitya
 telephoneNumber: 222-3234
 telephoneNumber: 332-2334
 
-# Testing substrings initial search...
 # refldap://localhost:9012/dc=example,dc=com??sub
 
+# Testing substrings initial search...
 dn: cn=Mitya Kovalev,dc=example,dc=com
 objectClass: inetOrgPerson
 cn: Mitya Kovalev
@@ -174,9 +223,9 @@ givenName: Mitya
 telephoneNumber: 222-3234
 telephoneNumber: 332-2334
 
-# Testing substrings any search...
 # refldap://localhost:9012/dc=example,dc=com??sub
 
+# Testing substrings any search...
 dn: cn=Mitya Kovalev,dc=example,dc=com
 objectClass: inetOrgPerson
 cn: Mitya Kovalev
@@ -187,9 +236,9 @@ givenName: Mitya
 telephoneNumber: 222-3234
 telephoneNumber: 332-2334
 
-# Testing substrings final search...
 # refldap://localhost:9012/dc=example,dc=com??sub
 
+# Testing substrings final search...
 dn: cn=Mitya Kovalev,dc=example,dc=com
 objectClass: inetOrgPerson
 cn: Mitya Kovalev
@@ -200,9 +249,9 @@ givenName: Mitya
 telephoneNumber: 222-3234
 telephoneNumber: 332-2334
 
-# Testing approx search...
 # refldap://localhost:9012/dc=example,dc=com??sub
 
+# Testing approx search...
 dn: cn=Mitya Kovalev,dc=example,dc=com
 objectClass: inetOrgPerson
 cn: Mitya Kovalev
@@ -213,9 +262,9 @@ givenName: Mitya
 telephoneNumber: 222-3234
 telephoneNumber: 332-2334
 
-# Testing extensible filter search...
 # refldap://localhost:9012/dc=example,dc=com??sub
 
+# Testing extensible filter search...
 dn: cn=Mitya Kovalev,dc=example,dc=com
 objectClass: inetOrgPerson
 cn: Mitya Kovalev
@@ -226,9 +275,9 @@ givenName: Mitya
 telephoneNumber: 222-3234
 telephoneNumber: 332-2334
 
-# Testing search for telephoneNumber...
 # refldap://localhost:9012/dc=example,dc=com??sub
 
+# Testing search for telephoneNumber...
 dn: cn=Mitya Kovalev,dc=example,dc=com
 objectClass: inetOrgPerson
 cn: Mitya Kovalev
@@ -239,9 +288,9 @@ givenName: Mitya
 telephoneNumber: 222-3234
 telephoneNumber: 332-2334
 
-# Testing AND search...
 # refldap://localhost:9012/dc=example,dc=com??sub
 
+# Testing AND search...
 dn: cn=Mitya Kovalev,dc=example,dc=com
 objectClass: inetOrgPerson
 cn: Mitya Kovalev
@@ -252,6 +301,8 @@ givenName: Mitya
 telephoneNumber: 222-3234
 telephoneNumber: 332-2334
 
+# refldap://localhost:9012/dc=example,dc=com??sub
+
 # Testing AND search on objectClass...
 dn: dc=example,dc=com
 objectClass: organization
@@ -260,8 +311,6 @@ o: Example
 dc: example
 
 # Testing OR search...
-# refldap://localhost:9012/dc=example,dc=com??sub
-
 dn: cn=Mitya Kovalev,dc=example,dc=com
 objectClass: inetOrgPerson
 cn: Mitya Kovalev
@@ -272,6 +321,8 @@ givenName: Mitya
 telephoneNumber: 222-3234
 telephoneNumber: 332-2334
 
+# refldap://localhost:9012/dc=example,dc=com??sub
+
 # Testing OR search on objectClass...
 dn: documentTitle=book1,dc=example,dc=com
 objectClass: document
@@ -295,6 +346,29 @@ o: Example
 dc: example
 
 # Testing NOT search...
+dn: cn=Akakiy Zinberstein,dc=example,dc=com
+objectClass: inetOrgPerson
+objectClass: pkiUser
+cn: Akakiy Zinberstein
+sn: Zinberstein
+givenName: Akakiy
+userCertificate;binary:: MIIDazCCAtSgAwIBAgIBAjANBgkqhkiG9w0BAQQFADB3MQswCQYDV
+ QQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEfMB0GA1UEChMWT3BlbkxEQVAgRXhhbXBsZSwgTH
+ RkLjETMBEGA1UEAxMKRXhhbXBsZSBDQTEdMBsGCSqGSIb3DQEJARYOY2FAZXhhbXBsZS5jb20wHhc
+ NMDMxMDE3MTYzMzE5WhcNMDQxMDE2MTYzMzE5WjB+MQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2Fs
+ aWZvcm5pYTEfMB0GA1UEChMWT3BlbkxEQVAgRXhhbXBsZSwgTHRkLjEYMBYGA1UEAxMPVXJzdWxhI
+ EhhbXBzdGVyMR8wHQYJKoZIhvcNAQkBFhB1aGFtQGV4YW1wbGUuY29tMIGfMA0GCSqGSIb3DQEBAQ
+ UAA4GNADCBiQKBgQDuxgp5ELV9LmhxWMpV7qc4028QQT3+zzFDXhruuXE7ji2n3S3ea8bOwDtJh+q
+ nsDe561DhHHHlgIjMKCiDEizYMpxvJPYEXmvp0huRkMgpKZgmel95BSkt6TYmJ0erS3aoimOHLEFi
+ mmnTLolNRMiWqNBvqwobx940PGwUWEePKQIDAQABo4H/MIH8MAkGA1UdEwQCMAAwLAYJYIZIAYb4Q
+ gENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0GA1UdDgQWBBSjI94TbBmuDEeUUO
+ iC37EK0Uf0XjCBoQYDVR0jBIGZMIGWgBRLbyEaNiTSkPlDsFNHLX3hwOaYI6F7pHkwdzELMAkGA1U
+ EBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExHzAdBgNVBAoTFk9wZW5MREFQIEV4YW1wbGUsIEx0
+ ZC4xEzARBgNVBAMTCkV4YW1wbGUgQ0ExHTAbBgkqhkiG9w0BCQEWDmNhQGV4YW1wbGUuY29tggEAM
+ A0GCSqGSIb3DQEBBAUAA4GBAIgUcARb3OlWYNbmr1nmqESuxLn16uqI1Ot6WkcICvpkdQ+Bo+R9AP
+ 05xpoXocZtKdNvBu3FNxB/jFkiOcLU2lX7Px1Ijnsjh60qVRy9HOsHCungIKlGcnXLKHmKu0y//5j
+ ds/HnaJsGcHI5JRG7CBJbW+wrwge3trJ1xHJI8prN
+
 dn: cn=Torvlobnor Puzdoy,dc=example,dc=com
 objectClass: inetOrgPerson
 cn: Torvlobnor Puzdoy
@@ -303,12 +377,6 @@ seeAlso: documentTitle=book1,dc=example,dc=com
 givenName: Torvlobnor
 telephoneNumber: 545-4563
 
-dn: cn=Akakiy Zinberstein,dc=example,dc=com
-objectClass: inetOrgPerson
-cn: Akakiy Zinberstein
-sn: Zinberstein
-givenName: Akakiy
-
 # Testing NOT search on objectClass...
 dn: documentTitle=book1,dc=example,dc=com
 objectClass: document
@@ -325,15 +393,38 @@ documentTitle: book2
 documentAuthor: cn=Mitya Kovalev,dc=example,dc=com
 documentIdentifier: document 2
 
-# refldap://localhost:9012/dc=example,dc=com??sub
-
 dn: dc=example,dc=com
 objectClass: organization
 objectClass: dcObject
 o: Example
 dc: example
 
+# refldap://localhost:9012/dc=example,dc=com??sub
+
 # Testing NOT search on "auxiliary" objectClass...
+dn: cn=Akakiy Zinberstein,dc=example,dc=com
+objectClass: inetOrgPerson
+objectClass: pkiUser
+cn: Akakiy Zinberstein
+sn: Zinberstein
+givenName: Akakiy
+userCertificate;binary:: MIIDazCCAtSgAwIBAgIBAjANBgkqhkiG9w0BAQQFADB3MQswCQYDV
+ QQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEfMB0GA1UEChMWT3BlbkxEQVAgRXhhbXBsZSwgTH
+ RkLjETMBEGA1UEAxMKRXhhbXBsZSBDQTEdMBsGCSqGSIb3DQEJARYOY2FAZXhhbXBsZS5jb20wHhc
+ NMDMxMDE3MTYzMzE5WhcNMDQxMDE2MTYzMzE5WjB+MQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2Fs
+ aWZvcm5pYTEfMB0GA1UEChMWT3BlbkxEQVAgRXhhbXBsZSwgTHRkLjEYMBYGA1UEAxMPVXJzdWxhI
+ EhhbXBzdGVyMR8wHQYJKoZIhvcNAQkBFhB1aGFtQGV4YW1wbGUuY29tMIGfMA0GCSqGSIb3DQEBAQ
+ UAA4GNADCBiQKBgQDuxgp5ELV9LmhxWMpV7qc4028QQT3+zzFDXhruuXE7ji2n3S3ea8bOwDtJh+q
+ nsDe561DhHHHlgIjMKCiDEizYMpxvJPYEXmvp0huRkMgpKZgmel95BSkt6TYmJ0erS3aoimOHLEFi
+ mmnTLolNRMiWqNBvqwobx940PGwUWEePKQIDAQABo4H/MIH8MAkGA1UdEwQCMAAwLAYJYIZIAYb4Q
+ gENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0GA1UdDgQWBBSjI94TbBmuDEeUUO
+ iC37EK0Uf0XjCBoQYDVR0jBIGZMIGWgBRLbyEaNiTSkPlDsFNHLX3hwOaYI6F7pHkwdzELMAkGA1U
+ EBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExHzAdBgNVBAoTFk9wZW5MREFQIEV4YW1wbGUsIEx0
+ ZC4xEzARBgNVBAMTCkV4YW1wbGUgQ0ExHTAbBgkqhkiG9w0BCQEWDmNhQGV4YW1wbGUuY29tggEAM
+ A0GCSqGSIb3DQEBBAUAA4GBAIgUcARb3OlWYNbmr1nmqESuxLn16uqI1Ot6WkcICvpkdQ+Bo+R9AP
+ 05xpoXocZtKdNvBu3FNxB/jFkiOcLU2lX7Px1Ijnsjh60qVRy9HOsHCungIKlGcnXLKHmKu0y//5j
+ ds/HnaJsGcHI5JRG7CBJbW+wrwge3trJ1xHJI8prN
+
 dn: documentTitle=book1,dc=example,dc=com
 objectClass: document
 description: abstract1
@@ -349,8 +440,6 @@ documentTitle: book2
 documentAuthor: cn=Mitya Kovalev,dc=example,dc=com
 documentIdentifier: document 2
 
-# refldap://localhost:9012/dc=example,dc=com??sub
-
 dn: cn=Mitya Kovalev,dc=example,dc=com
 objectClass: inetOrgPerson
 cn: Mitya Kovalev
@@ -369,11 +458,7 @@ seeAlso: documentTitle=book1,dc=example,dc=com
 givenName: Torvlobnor
 telephoneNumber: 545-4563
 
-dn: cn=Akakiy Zinberstein,dc=example,dc=com
-objectClass: inetOrgPerson
-cn: Akakiy Zinberstein
-sn: Zinberstein
-givenName: Akakiy
+# refldap://localhost:9012/dc=example,dc=com??sub
 
 # Testing attribute inheritance in filter...
 dn: dc=example,dc=com
@@ -383,15 +468,38 @@ o: Example
 dc: example
 
 # Testing undefined attribute in filter...
-# refldap://localhost:9012/dc=example,dc=com??sub
-
 dn: dc=example,dc=com
 objectClass: organization
 objectClass: dcObject
 o: Example
 dc: example
 
+# refldap://localhost:9012/dc=example,dc=com??sub
+
 # Testing objectClass inheritance in filter...
+dn: cn=Akakiy Zinberstein,dc=example,dc=com
+objectClass: inetOrgPerson
+objectClass: pkiUser
+cn: Akakiy Zinberstein
+sn: Zinberstein
+givenName: Akakiy
+userCertificate;binary:: MIIDazCCAtSgAwIBAgIBAjANBgkqhkiG9w0BAQQFADB3MQswCQYDV
+ QQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEfMB0GA1UEChMWT3BlbkxEQVAgRXhhbXBsZSwgTH
+ RkLjETMBEGA1UEAxMKRXhhbXBsZSBDQTEdMBsGCSqGSIb3DQEJARYOY2FAZXhhbXBsZS5jb20wHhc
+ NMDMxMDE3MTYzMzE5WhcNMDQxMDE2MTYzMzE5WjB+MQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2Fs
+ aWZvcm5pYTEfMB0GA1UEChMWT3BlbkxEQVAgRXhhbXBsZSwgTHRkLjEYMBYGA1UEAxMPVXJzdWxhI
+ EhhbXBzdGVyMR8wHQYJKoZIhvcNAQkBFhB1aGFtQGV4YW1wbGUuY29tMIGfMA0GCSqGSIb3DQEBAQ
+ UAA4GNADCBiQKBgQDuxgp5ELV9LmhxWMpV7qc4028QQT3+zzFDXhruuXE7ji2n3S3ea8bOwDtJh+q
+ nsDe561DhHHHlgIjMKCiDEizYMpxvJPYEXmvp0huRkMgpKZgmel95BSkt6TYmJ0erS3aoimOHLEFi
+ mmnTLolNRMiWqNBvqwobx940PGwUWEePKQIDAQABo4H/MIH8MAkGA1UdEwQCMAAwLAYJYIZIAYb4Q
+ gENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0GA1UdDgQWBBSjI94TbBmuDEeUUO
+ iC37EK0Uf0XjCBoQYDVR0jBIGZMIGWgBRLbyEaNiTSkPlDsFNHLX3hwOaYI6F7pHkwdzELMAkGA1U
+ EBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExHzAdBgNVBAoTFk9wZW5MREFQIEV4YW1wbGUsIEx0
+ ZC4xEzARBgNVBAMTCkV4YW1wbGUgQ0ExHTAbBgkqhkiG9w0BCQEWDmNhQGV4YW1wbGUuY29tggEAM
+ A0GCSqGSIb3DQEBBAUAA4GBAIgUcARb3OlWYNbmr1nmqESuxLn16uqI1Ot6WkcICvpkdQ+Bo+R9AP
+ 05xpoXocZtKdNvBu3FNxB/jFkiOcLU2lX7Px1Ijnsjh60qVRy9HOsHCungIKlGcnXLKHmKu0y//5j
+ ds/HnaJsGcHI5JRG7CBJbW+wrwge3trJ1xHJI8prN
+
 dn: cn=Mitya Kovalev,dc=example,dc=com
 objectClass: inetOrgPerson
 cn: Mitya Kovalev
@@ -410,12 +518,6 @@ seeAlso: documentTitle=book1,dc=example,dc=com
 givenName: Torvlobnor
 telephoneNumber: 545-4563
 
-dn: cn=Akakiy Zinberstein,dc=example,dc=com
-objectClass: inetOrgPerson
-cn: Akakiy Zinberstein
-sn: Zinberstein
-givenName: Akakiy
-
 # Testing "auxiliary" objectClass in filter...
 dn: dc=example,dc=com
 objectClass: organization
@@ -424,14 +526,14 @@ o: Example
 dc: example
 
 # Testing hasSubordinates in filter...
-# refldap://localhost:9012/dc=example,dc=com??sub
-
 dn: dc=example,dc=com
 objectClass: organization
 objectClass: dcObject
 o: Example
 dc: example
 
+# refldap://localhost:9012/dc=example,dc=com??sub
+
 # Testing entryUUID in filter...
 dn: cn=Mitya Kovalev,dc=example,dc=com
 objectClass: inetOrgPerson
@@ -444,22 +546,24 @@ telephoneNumber: 222-3234
 telephoneNumber: 332-2334
 
 # Testing attribute inheritance in requested attributes...
-# refldap://localhost:9012/dc=example,dc=com??sub
-
 dn: cn=Mitya Kovalev,dc=example,dc=com
 cn: Mitya Kovalev
 sn: Kovalev
 givenName: Mitya
 
+# refldap://localhost:9012/dc=example,dc=com??sub
+
 # Testing objectClass in requested attributes...
+dn: cn=Akakiy Zinberstein,dc=example,dc=com
+objectClass: inetOrgPerson
+objectClass: pkiUser
+
 dn: documentTitle=book1,dc=example,dc=com
 objectClass: document
 
 dn: documentTitle=book2,dc=example,dc=com
 objectClass: document
 
-# refldap://localhost:9012/dc=example,dc=com??sub
-
 dn: dc=example,dc=com
 objectClass: organization
 objectClass: dcObject
@@ -470,10 +574,16 @@ objectClass: inetOrgPerson
 dn: cn=Torvlobnor Puzdoy,dc=example,dc=com
 objectClass: inetOrgPerson
 
-dn: cn=Akakiy Zinberstein,dc=example,dc=com
-objectClass: inetOrgPerson
+# refldap://localhost:9012/dc=example,dc=com??sub
 
 # Testing operational attributes in request...
+dn: cn=Akakiy Zinberstein,dc=example,dc=com
+structuralObjectClass: inetOrgPerson
+entryDN: cn=Akakiy Zinberstein,dc=example,dc=com
+subschemaSubentry: cn=Subschema
+hasSubordinates: FALSE
+entryUUID: 00000001-0000-0003-0000-000000000000
+
 dn: documentTitle=book1,dc=example,dc=com
 structuralObjectClass: document
 entryDN: documentTitle=book1,dc=example,dc=com
@@ -488,8 +598,6 @@ subschemaSubentry: cn=Subschema
 hasSubordinates: FALSE
 entryUUID: 00000002-0000-0002-0000-000000000000
 
-# refldap://localhost:9012/dc=example,dc=com??sub
-
 dn: dc=example,dc=com
 structuralObjectClass: organization
 entryDN: dc=example,dc=com
@@ -511,10 +619,5 @@ subschemaSubentry: cn=Subschema
 hasSubordinates: FALSE
 entryUUID: 00000001-0000-0002-0000-000000000000
 
-dn: cn=Akakiy Zinberstein,dc=example,dc=com
-structuralObjectClass: inetOrgPerson
-entryDN: cn=Akakiy Zinberstein,dc=example,dc=com
-subschemaSubentry: cn=Subschema
-hasSubordinates: FALSE
-entryUUID: 00000001-0000-0003-0000-000000000000
+# refldap://localhost:9012/dc=example,dc=com??sub
 
index 9fb7d5340f5a9822a11fca93f5bd612b9750836c..45fa164315991e79667da56d6e4cfad781300bfa 100644 (file)
@@ -1,9 +1,26 @@
 # Using ldapsearch to retrieve all the entries...
 dn: cn=Akakiy Zinberstein,dc=example,dc=com
 objectClass: inetOrgPerson
+objectClass: pkiUser
 cn: Akakiy Zinberstein
 sn: Zinberstein
 givenName: Akakiy
+userCertificate;binary:: MIIDazCCAtSgAwIBAgIBAjANBgkqhkiG9w0BAQQFADB3MQswCQYDV
+ QQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEfMB0GA1UEChMWT3BlbkxEQVAgRXhhbXBsZSwgTH
+ RkLjETMBEGA1UEAxMKRXhhbXBsZSBDQTEdMBsGCSqGSIb3DQEJARYOY2FAZXhhbXBsZS5jb20wHhc
+ NMDMxMDE3MTYzMzE5WhcNMDQxMDE2MTYzMzE5WjB+MQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2Fs
+ aWZvcm5pYTEfMB0GA1UEChMWT3BlbkxEQVAgRXhhbXBsZSwgTHRkLjEYMBYGA1UEAxMPVXJzdWxhI
+ EhhbXBzdGVyMR8wHQYJKoZIhvcNAQkBFhB1aGFtQGV4YW1wbGUuY29tMIGfMA0GCSqGSIb3DQEBAQ
+ UAA4GNADCBiQKBgQDuxgp5ELV9LmhxWMpV7qc4028QQT3+zzFDXhruuXE7ji2n3S3ea8bOwDtJh+q
+ nsDe561DhHHHlgIjMKCiDEizYMpxvJPYEXmvp0huRkMgpKZgmel95BSkt6TYmJ0erS3aoimOHLEFi
+ mmnTLolNRMiWqNBvqwobx940PGwUWEePKQIDAQABo4H/MIH8MAkGA1UdEwQCMAAwLAYJYIZIAYb4Q
+ gENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0GA1UdDgQWBBSjI94TbBmuDEeUUO
+ iC37EK0Uf0XjCBoQYDVR0jBIGZMIGWgBRLbyEaNiTSkPlDsFNHLX3hwOaYI6F7pHkwdzELMAkGA1U
+ EBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExHzAdBgNVBAoTFk9wZW5MREFQIEV4YW1wbGUsIEx0
+ ZC4xEzARBgNVBAMTCkV4YW1wbGUgQ0ExHTAbBgkqhkiG9w0BCQEWDmNhQGV4YW1wbGUuY29tggEAM
+ A0GCSqGSIb3DQEBBAUAA4GBAIgUcARb3OlWYNbmr1nmqESuxLn16uqI1Ot6WkcICvpkdQ+Bo+R9AP
+ 05xpoXocZtKdNvBu3FNxB/jFkiOcLU2lX7Px1Ijnsjh60qVRy9HOsHCungIKlGcnXLKHmKu0y//5j
+ ds/HnaJsGcHI5JRG7CBJbW+wrwge3trJ1xHJI8prN
 
 dn: documentTitle=book1,dc=example,dc=com
 objectClass: document
@@ -49,9 +66,26 @@ telephoneNumber: 545-4563
 # Using ldapsearch to retrieve all the entries...
 dn: cn=Akakiy Zinberstein,dc=example,dc=com
 objectClass: inetOrgPerson
+objectClass: pkiUser
 cn: Akakiy Zinberstein
 sn: Zinberstein
 givenName: Akakiy
+userCertificate;binary:: MIIDazCCAtSgAwIBAgIBAjANBgkqhkiG9w0BAQQFADB3MQswCQYDV
+ QQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEfMB0GA1UEChMWT3BlbkxEQVAgRXhhbXBsZSwgTH
+ RkLjETMBEGA1UEAxMKRXhhbXBsZSBDQTEdMBsGCSqGSIb3DQEJARYOY2FAZXhhbXBsZS5jb20wHhc
+ NMDMxMDE3MTYzMzE5WhcNMDQxMDE2MTYzMzE5WjB+MQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2Fs
+ aWZvcm5pYTEfMB0GA1UEChMWT3BlbkxEQVAgRXhhbXBsZSwgTHRkLjEYMBYGA1UEAxMPVXJzdWxhI
+ EhhbXBzdGVyMR8wHQYJKoZIhvcNAQkBFhB1aGFtQGV4YW1wbGUuY29tMIGfMA0GCSqGSIb3DQEBAQ
+ UAA4GNADCBiQKBgQDuxgp5ELV9LmhxWMpV7qc4028QQT3+zzFDXhruuXE7ji2n3S3ea8bOwDtJh+q
+ nsDe561DhHHHlgIjMKCiDEizYMpxvJPYEXmvp0huRkMgpKZgmel95BSkt6TYmJ0erS3aoimOHLEFi
+ mmnTLolNRMiWqNBvqwobx940PGwUWEePKQIDAQABo4H/MIH8MAkGA1UdEwQCMAAwLAYJYIZIAYb4Q
+ gENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0GA1UdDgQWBBSjI94TbBmuDEeUUO
+ iC37EK0Uf0XjCBoQYDVR0jBIGZMIGWgBRLbyEaNiTSkPlDsFNHLX3hwOaYI6F7pHkwdzELMAkGA1U
+ EBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExHzAdBgNVBAoTFk9wZW5MREFQIEV4YW1wbGUsIEx0
+ ZC4xEzARBgNVBAMTCkV4YW1wbGUgQ0ExHTAbBgkqhkiG9w0BCQEWDmNhQGV4YW1wbGUuY29tggEAM
+ A0GCSqGSIb3DQEBBAUAA4GBAIgUcARb3OlWYNbmr1nmqESuxLn16uqI1Ot6WkcICvpkdQ+Bo+R9AP
+ 05xpoXocZtKdNvBu3FNxB/jFkiOcLU2lX7Px1Ijnsjh60qVRy9HOsHCungIKlGcnXLKHmKu0y//5j
+ ds/HnaJsGcHI5JRG7CBJbW+wrwge3trJ1xHJI8prN
 
 dn: o=An Org,dc=example,dc=com
 objectClass: organization
@@ -144,9 +178,26 @@ documentIdentifier: document 3
 # Using ldapsearch to retrieve all the entries...
 dn: cn=Akakiy Zinberstein,dc=example,dc=com
 objectClass: inetOrgPerson
+objectClass: pkiUser
 cn: Akakiy Zinberstein
 sn: Zinberstein
 givenName: Akakiy
+userCertificate;binary:: MIIDazCCAtSgAwIBAgIBAjANBgkqhkiG9w0BAQQFADB3MQswCQYDV
+ QQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEfMB0GA1UEChMWT3BlbkxEQVAgRXhhbXBsZSwgTH
+ RkLjETMBEGA1UEAxMKRXhhbXBsZSBDQTEdMBsGCSqGSIb3DQEJARYOY2FAZXhhbXBsZS5jb20wHhc
+ NMDMxMDE3MTYzMzE5WhcNMDQxMDE2MTYzMzE5WjB+MQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2Fs
+ aWZvcm5pYTEfMB0GA1UEChMWT3BlbkxEQVAgRXhhbXBsZSwgTHRkLjEYMBYGA1UEAxMPVXJzdWxhI
+ EhhbXBzdGVyMR8wHQYJKoZIhvcNAQkBFhB1aGFtQGV4YW1wbGUuY29tMIGfMA0GCSqGSIb3DQEBAQ
+ UAA4GNADCBiQKBgQDuxgp5ELV9LmhxWMpV7qc4028QQT3+zzFDXhruuXE7ji2n3S3ea8bOwDtJh+q
+ nsDe561DhHHHlgIjMKCiDEizYMpxvJPYEXmvp0huRkMgpKZgmel95BSkt6TYmJ0erS3aoimOHLEFi
+ mmnTLolNRMiWqNBvqwobx940PGwUWEePKQIDAQABo4H/MIH8MAkGA1UdEwQCMAAwLAYJYIZIAYb4Q
+ gENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0GA1UdDgQWBBSjI94TbBmuDEeUUO
+ iC37EK0Uf0XjCBoQYDVR0jBIGZMIGWgBRLbyEaNiTSkPlDsFNHLX3hwOaYI6F7pHkwdzELMAkGA1U
+ EBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExHzAdBgNVBAoTFk9wZW5MREFQIEV4YW1wbGUsIEx0
+ ZC4xEzARBgNVBAMTCkV4YW1wbGUgQ0ExHTAbBgkqhkiG9w0BCQEWDmNhQGV4YW1wbGUuY29tggEAM
+ A0GCSqGSIb3DQEBBAUAA4GBAIgUcARb3OlWYNbmr1nmqESuxLn16uqI1Ot6WkcICvpkdQ+Bo+R9AP
+ 05xpoXocZtKdNvBu3FNxB/jFkiOcLU2lX7Px1Ijnsjh60qVRy9HOsHCungIKlGcnXLKHmKu0y//5j
+ ds/HnaJsGcHI5JRG7CBJbW+wrwge3trJ1xHJI8prN
 
 dn: o=An Org,dc=example,dc=com
 objectClass: organization
@@ -242,9 +293,26 @@ documentIdentifier: document 3
 # Using ldapsearch to retrieve all the entries...
 dn: cn=Akakiy Zinberstein,dc=example,dc=com
 objectClass: inetOrgPerson
+objectClass: pkiUser
 cn: Akakiy Zinberstein
 sn: Zinberstein
 givenName: Akakiy
+userCertificate;binary:: MIIDazCCAtSgAwIBAgIBAjANBgkqhkiG9w0BAQQFADB3MQswCQYDV
+ QQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEfMB0GA1UEChMWT3BlbkxEQVAgRXhhbXBsZSwgTH
+ RkLjETMBEGA1UEAxMKRXhhbXBsZSBDQTEdMBsGCSqGSIb3DQEJARYOY2FAZXhhbXBsZS5jb20wHhc
+ NMDMxMDE3MTYzMzE5WhcNMDQxMDE2MTYzMzE5WjB+MQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2Fs
+ aWZvcm5pYTEfMB0GA1UEChMWT3BlbkxEQVAgRXhhbXBsZSwgTHRkLjEYMBYGA1UEAxMPVXJzdWxhI
+ EhhbXBzdGVyMR8wHQYJKoZIhvcNAQkBFhB1aGFtQGV4YW1wbGUuY29tMIGfMA0GCSqGSIb3DQEBAQ
+ UAA4GNADCBiQKBgQDuxgp5ELV9LmhxWMpV7qc4028QQT3+zzFDXhruuXE7ji2n3S3ea8bOwDtJh+q
+ nsDe561DhHHHlgIjMKCiDEizYMpxvJPYEXmvp0huRkMgpKZgmel95BSkt6TYmJ0erS3aoimOHLEFi
+ mmnTLolNRMiWqNBvqwobx940PGwUWEePKQIDAQABo4H/MIH8MAkGA1UdEwQCMAAwLAYJYIZIAYb4Q
+ gENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0GA1UdDgQWBBSjI94TbBmuDEeUUO
+ iC37EK0Uf0XjCBoQYDVR0jBIGZMIGWgBRLbyEaNiTSkPlDsFNHLX3hwOaYI6F7pHkwdzELMAkGA1U
+ EBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExHzAdBgNVBAoTFk9wZW5MREFQIEV4YW1wbGUsIEx0
+ ZC4xEzARBgNVBAMTCkV4YW1wbGUgQ0ExHTAbBgkqhkiG9w0BCQEWDmNhQGV4YW1wbGUuY29tggEAM
+ A0GCSqGSIb3DQEBBAUAA4GBAIgUcARb3OlWYNbmr1nmqESuxLn16uqI1Ot6WkcICvpkdQ+Bo+R9AP
+ 05xpoXocZtKdNvBu3FNxB/jFkiOcLU2lX7Px1Ijnsjh60qVRy9HOsHCungIKlGcnXLKHmKu0y//5j
+ ds/HnaJsGcHI5JRG7CBJbW+wrwge3trJ1xHJI8prN
 
 dn: o=An Org,dc=example,dc=com
 objectClass: organization
@@ -315,9 +383,26 @@ documentIdentifier: document 3
 # Using ldapsearch to retrieve all the entries...
 dn: cn=Akakiy Zinberstein,dc=example,dc=com
 objectClass: inetOrgPerson
+objectClass: pkiUser
 cn: Akakiy Zinberstein
 sn: Zinberstein
 givenName: Akakiy
+userCertificate;binary:: MIIDazCCAtSgAwIBAgIBAjANBgkqhkiG9w0BAQQFADB3MQswCQYDV
+ QQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEfMB0GA1UEChMWT3BlbkxEQVAgRXhhbXBsZSwgTH
+ RkLjETMBEGA1UEAxMKRXhhbXBsZSBDQTEdMBsGCSqGSIb3DQEJARYOY2FAZXhhbXBsZS5jb20wHhc
+ NMDMxMDE3MTYzMzE5WhcNMDQxMDE2MTYzMzE5WjB+MQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2Fs
+ aWZvcm5pYTEfMB0GA1UEChMWT3BlbkxEQVAgRXhhbXBsZSwgTHRkLjEYMBYGA1UEAxMPVXJzdWxhI
+ EhhbXBzdGVyMR8wHQYJKoZIhvcNAQkBFhB1aGFtQGV4YW1wbGUuY29tMIGfMA0GCSqGSIb3DQEBAQ
+ UAA4GNADCBiQKBgQDuxgp5ELV9LmhxWMpV7qc4028QQT3+zzFDXhruuXE7ji2n3S3ea8bOwDtJh+q
+ nsDe561DhHHHlgIjMKCiDEizYMpxvJPYEXmvp0huRkMgpKZgmel95BSkt6TYmJ0erS3aoimOHLEFi
+ mmnTLolNRMiWqNBvqwobx940PGwUWEePKQIDAQABo4H/MIH8MAkGA1UdEwQCMAAwLAYJYIZIAYb4Q
+ gENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0GA1UdDgQWBBSjI94TbBmuDEeUUO
+ iC37EK0Uf0XjCBoQYDVR0jBIGZMIGWgBRLbyEaNiTSkPlDsFNHLX3hwOaYI6F7pHkwdzELMAkGA1U
+ EBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExHzAdBgNVBAoTFk9wZW5MREFQIEV4YW1wbGUsIEx0
+ ZC4xEzARBgNVBAMTCkV4YW1wbGUgQ0ExHTAbBgkqhkiG9w0BCQEWDmNhQGV4YW1wbGUuY29tggEAM
+ A0GCSqGSIb3DQEBBAUAA4GBAIgUcARb3OlWYNbmr1nmqESuxLn16uqI1Ot6WkcICvpkdQ+Bo+R9AP
+ 05xpoXocZtKdNvBu3FNxB/jFkiOcLU2lX7Px1Ijnsjh60qVRy9HOsHCungIKlGcnXLKHmKu0y//5j
+ ds/HnaJsGcHI5JRG7CBJbW+wrwge3trJ1xHJI8prN
 
 dn: dc=example,dc=com
 objectClass: organization
@@ -402,9 +487,26 @@ ref: ldap://localhost:9009/
 # Using ldapsearch to retrieve all the entries...
 dn: cn=Akakiy Zinberstein,dc=example,dc=com
 objectClass: inetOrgPerson
+objectClass: pkiUser
 cn: Akakiy Zinberstein
 sn: Zinberstein
 givenName: Akakiy
+userCertificate;binary:: MIIDazCCAtSgAwIBAgIBAjANBgkqhkiG9w0BAQQFADB3MQswCQYDV
+ QQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEfMB0GA1UEChMWT3BlbkxEQVAgRXhhbXBsZSwgTH
+ RkLjETMBEGA1UEAxMKRXhhbXBsZSBDQTEdMBsGCSqGSIb3DQEJARYOY2FAZXhhbXBsZS5jb20wHhc
+ NMDMxMDE3MTYzMzE5WhcNMDQxMDE2MTYzMzE5WjB+MQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2Fs
+ aWZvcm5pYTEfMB0GA1UEChMWT3BlbkxEQVAgRXhhbXBsZSwgTHRkLjEYMBYGA1UEAxMPVXJzdWxhI
+ EhhbXBzdGVyMR8wHQYJKoZIhvcNAQkBFhB1aGFtQGV4YW1wbGUuY29tMIGfMA0GCSqGSIb3DQEBAQ
+ UAA4GNADCBiQKBgQDuxgp5ELV9LmhxWMpV7qc4028QQT3+zzFDXhruuXE7ji2n3S3ea8bOwDtJh+q
+ nsDe561DhHHHlgIjMKCiDEizYMpxvJPYEXmvp0huRkMgpKZgmel95BSkt6TYmJ0erS3aoimOHLEFi
+ mmnTLolNRMiWqNBvqwobx940PGwUWEePKQIDAQABo4H/MIH8MAkGA1UdEwQCMAAwLAYJYIZIAYb4Q
+ gENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0GA1UdDgQWBBSjI94TbBmuDEeUUO
+ iC37EK0Uf0XjCBoQYDVR0jBIGZMIGWgBRLbyEaNiTSkPlDsFNHLX3hwOaYI6F7pHkwdzELMAkGA1U
+ EBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExHzAdBgNVBAoTFk9wZW5MREFQIEV4YW1wbGUsIEx0
+ ZC4xEzARBgNVBAMTCkV4YW1wbGUgQ0ExHTAbBgkqhkiG9w0BCQEWDmNhQGV4YW1wbGUuY29tggEAM
+ A0GCSqGSIb3DQEBBAUAA4GBAIgUcARb3OlWYNbmr1nmqESuxLn16uqI1Ot6WkcICvpkdQ+Bo+R9AP
+ 05xpoXocZtKdNvBu3FNxB/jFkiOcLU2lX7Px1Ijnsjh60qVRy9HOsHCungIKlGcnXLKHmKu0y//5j
+ ds/HnaJsGcHI5JRG7CBJbW+wrwge3trJ1xHJI8prN
 
 dn: dc=example,dc=com
 objectClass: organization
index 54e08302cf1c6c15aa738d0d51c8cc3d58c1c8c7..39a5770e68e8f9f9d0d0a5dab43cbbb5523ccc87 100644 (file)
@@ -62,7 +62,7 @@ objectClass ( 1.3.6.1.4.1.4203.666.3.15
        name 'testPerson' sup OpenLDAPperson
        may testTime )
 
-objectClass ( 1.3.6.1.3.1.4203.666.3.16
+objectClass ( 1.3.6.1.4.1.4203.666.3.17
        name 'obsoletePerson'
        obsolete auxiliary
        may ( testObsolete ) )
index a51e5aca0be56a00d70c3943323b210389ed9aa4..99499039d77afa65c99d0ea82c0498fbecf084dd 100644 (file)
 
 #include <stdio.h>
 
-#include <ac/stdlib.h>
+#include "ac/stdlib.h"
 
-#include <ac/ctype.h>
-#include <ac/param.h>
-#include <ac/socket.h>
-#include <ac/string.h>
-#include <ac/unistd.h>
-#include <ac/wait.h>
+#include "ac/ctype.h"
+#include "ac/param.h"
+#include "ac/socket.h"
+#include "ac/string.h"
+#include "ac/unistd.h"
+#include "ac/wait.h"
 
-#include <ldap.h>
-#include <lutil.h>
+#include "ldap.h"
+#include "lutil.h"
 
 #include "slapd-common.h"
 
index 21642137a0e978a7667183a041212d88fddddc91..4f1b1f2d5c7f4180f0355ab845b242498889fa09 100644 (file)
 
 #include <stdio.h>
 
-#include <ac/stdlib.h>
-#include <ac/time.h>
-
-#include <ac/ctype.h>
-#include <ac/param.h>
-#include <ac/socket.h>
-#include <ac/string.h>
-#include <ac/unistd.h>
-#include <ac/wait.h>
-#include <ac/time.h>
-
-#include <ldap.h>
-#include <lutil.h>
-#include <lber_pvt.h>
-#include <ldap_pvt.h>
+#include "ac/stdlib.h"
+#include "ac/time.h"
+
+#include "ac/ctype.h"
+#include "ac/param.h"
+#include "ac/socket.h"
+#include "ac/string.h"
+#include "ac/unistd.h"
+#include "ac/wait.h"
+#include "ac/time.h"
+
+#include "ldap.h"
+#include "lutil.h"
+#include "lber_pvt.h"
+#include "ldap_pvt.h"
 
 #include "slapd-common.h"
 
index 7a4df27bfc6f36cd7e29d1c9f4d55e74a897459e..72bfebae11f6ea2ec6dcdb9ca31f049570d5396d 100644 (file)
 
 #include <stdio.h>
 
-#include <ac/stdlib.h>
-#include <ac/unistd.h>
-#include <ac/string.h>
-#include <ac/errno.h>
+#include "ac/stdlib.h"
+#include "ac/unistd.h"
+#include "ac/string.h"
+#include "ac/errno.h"
 
-#include <ldap.h>
+#include "ldap.h"
 
 #include "ldap_pvt.h"
 #include "slapd-common.h"
index ae639572db2d6ef0ddecbf059a14c9e499b852a2..4c20b1f5fc49f62cbff524d0cd960aca8c3df48b 100644 (file)
 
 #include <stdio.h>
 
-#include <ac/stdlib.h>
+#include "ac/stdlib.h"
 
-#include <ac/ctype.h>
-#include <ac/param.h>
-#include <ac/socket.h>
-#include <ac/string.h>
-#include <ac/unistd.h>
-#include <ac/wait.h>
+#include "ac/ctype.h"
+#include "ac/param.h"
+#include "ac/socket.h"
+#include "ac/string.h"
+#include "ac/unistd.h"
+#include "ac/wait.h"
 
-#include <ldap.h>
-#include <lutil.h>
+#include "ldap.h"
+#include "lutil.h"
 
 #include "slapd-common.h"
 
index d2646e4c2460f1ccf520edc058ae314d19a0ea9a..b25c284910e47629f80901b469e52b56ec2dd909 100644 (file)
 
 #include <stdio.h>
 
-#include <ac/stdlib.h>
+#include "ac/stdlib.h"
 
-#include <ac/ctype.h>
-#include <ac/param.h>
-#include <ac/socket.h>
-#include <ac/string.h>
-#include <ac/unistd.h>
-#include <ac/wait.h>
+#include "ac/ctype.h"
+#include "ac/param.h"
+#include "ac/socket.h"
+#include "ac/string.h"
+#include "ac/unistd.h"
+#include "ac/wait.h"
 
-#include <ldap.h>
-#include <lutil.h>
+#include "ldap.h"
+#include "lutil.h"
 
 #include "slapd-common.h"
 
index c938875ec4c0fb7814560f9b015242620df84e01..e4e389ec0da5aae24a4d6aa9182b4543998ad551 100644 (file)
 
 #include <stdio.h>
 
-#include <ac/stdlib.h>
+#include "ac/stdlib.h"
 
-#include <ac/ctype.h>
-#include <ac/param.h>
-#include <ac/socket.h>
-#include <ac/string.h>
-#include <ac/unistd.h>
-#include <ac/wait.h>
+#include "ac/ctype.h"
+#include "ac/param.h"
+#include "ac/socket.h"
+#include "ac/string.h"
+#include "ac/unistd.h"
+#include "ac/wait.h"
 
-#include <ldap.h>
-#include <lutil.h>
+#include "ldap.h"
+#include "lutil.h"
+
+#include "ldap_pvt.h"
 
 #include "slapd-common.h"
 
 
 static void
 do_read( char *uri, char *manager, struct berval *passwd,
-       char *entry, LDAP **ld, int noattrs, int nobind, int maxloop,
+       char *entry, LDAP **ld,
+       char **attrs, int noattrs, int nobind, int maxloop,
        int maxretries, int delay, int force, int chaserefs );
 
 static void
 do_random( char *uri, char *manager, struct berval *passwd,
-       char *sbase, char *filter, int noattrs, int nobind,
+       char *sbase, char *filter, char **attrs, int noattrs, int nobind,
        int innerloop, int maxretries, int delay, int force, int chaserefs );
 
 static void
@@ -66,7 +69,10 @@ usage( char *name )
                "[-l <loops>] "
                "[-L <outerloops>] "
                "[-r <maxretries>] "
-               "[-t <delay>]\n",
+               "[-t <delay>] "
+               "[-T <attrs>] "
+               "[<attrs>] "
+               "\n",
                name );
        exit( EXIT_FAILURE );
 }
@@ -88,6 +94,8 @@ main( int argc, char **argv )
        int             delay = 0;
        int             force = 0;
        int             chaserefs = 0;
+       char            *srchattrs[] = { "1.1", NULL };
+       char            **attrs = srchattrs;
        int             noattrs = 0;
        int             nobind = 0;
 
@@ -96,7 +104,7 @@ main( int argc, char **argv )
        /* by default, tolerate referrals and no such object */
        tester_ignore_str2errlist( "REFERRAL,NO_SUCH_OBJECT" );
 
-       while ( (i = getopt( argc, argv, "ACD:e:Ff:H:h:i:L:l:p:r:t:w:" )) != EOF ) {
+       while ( (i = getopt( argc, argv, "ACD:e:Ff:H:h:i:L:l:p:r:t:T:w:" )) != EOF ) {
                switch ( i ) {
                case 'A':
                        noattrs++;
@@ -174,6 +182,13 @@ main( int argc, char **argv )
                        }
                        break;
 
+               case 'T':
+                       attrs = ldap_str2charray( optarg, "," );
+                       if ( attrs == NULL ) {
+                               usage( argv[0] );
+                       }
+                       break;
+
                default:
                        usage( argv[0] );
                        break;
@@ -189,17 +204,22 @@ main( int argc, char **argv )
                exit( EXIT_FAILURE );
        }
 
+       if ( argv[optind] != NULL ) {
+               attrs = &argv[optind];
+       }
+
        uri = tester_uri( uri, host, port );
 
        for ( i = 0; i < outerloops; i++ ) {
                if ( filter != NULL ) {
-                       do_random( uri, manager, &passwd, entry, filter,
+                       do_random( uri, manager, &passwd, entry, filter, attrs,
                                noattrs, nobind, loops, retries, delay, force,
                                chaserefs );
 
                } else {
-                       do_read( uri, manager, &passwd, entry, NULL, noattrs, nobind,
-                               loops, retries, delay, force, chaserefs );
+                       do_read( uri, manager, &passwd, entry, NULL, attrs,
+                               noattrs, nobind, loops, retries, delay, force,
+                               chaserefs );
                }
        }
 
@@ -208,7 +228,7 @@ main( int argc, char **argv )
 
 static void
 do_random( char *uri, char *manager, struct berval *passwd,
-       char *sbase, char *filter, int noattrs, int nobind,
+       char *sbase, char *filter, char **srchattrs, int noattrs, int nobind,
        int innerloop, int maxretries, int delay, int force, int chaserefs )
 {
        LDAP    *ld = NULL;
@@ -288,8 +308,8 @@ do_random( char *uri, char *manager, struct berval *passwd,
                        int     r = ((double)nvalues)*rand()/(RAND_MAX + 1.0);
 
                        do_read( uri, manager, passwd, values[ r ], &ld,
-                               noattrs, nobind, 1, maxretries, delay, force,
-                               chaserefs );
+                               srchattrs, noattrs, nobind, 1, maxretries,
+                               delay, force, chaserefs );
                }
                free( values );
                break;
@@ -308,12 +328,11 @@ do_random( char *uri, char *manager, struct berval *passwd,
 
 static void
 do_read( char *uri, char *manager, struct berval *passwd, char *entry,
-       LDAP **ldp, int noattrs, int nobind, int maxloop,
+       LDAP **ldp, char **attrs, int noattrs, int nobind, int maxloop,
        int maxretries, int delay, int force, int chaserefs )
 {
        LDAP    *ld = ldp ? *ldp : NULL;
        int     i = 0, do_retry = maxretries;
-       char    *attrs[] = { "1.1", NULL };
        int     rc = LDAP_SUCCESS;
        int     version = LDAP_VERSION3;
 
@@ -343,6 +362,7 @@ retry:;
                                case LDAP_UNAVAILABLE:
                                        if ( do_retry > 0 ) {
                                                ldap_unbind_ext( ld, NULL, NULL );
+                                               ld = NULL;
                                                do_retry--;
                                                if ( delay != 0 ) {
                                                    sleep( delay );
index 7ad90d20e45661c1df123378297037cd2730faad..ddf14e7c37c3db433a55cedc3f2473643d0cda2d 100644 (file)
 
 #include <stdio.h>
 
-#include <ac/stdlib.h>
+#include "ac/stdlib.h"
 
-#include <ac/ctype.h>
-#include <ac/param.h>
-#include <ac/socket.h>
-#include <ac/string.h>
-#include <ac/unistd.h>
-#include <ac/wait.h>
+#include "ac/ctype.h"
+#include "ac/param.h"
+#include "ac/socket.h"
+#include "ac/string.h"
+#include "ac/unistd.h"
+#include "ac/wait.h"
 
-#include <ldap.h>
-#include <lutil.h>
+#include "ldap.h"
+#include "lutil.h"
+#include "ldap_pvt.h"
 
 #include "slapd-common.h"
 
 
 static void
 do_search( char *uri, char *manager, struct berval *passwd,
-       char *sbase, char *filter, LDAP **ldp, int noattrs, int nobind,
+       char *sbase, int scope, char *filter, LDAP **ldp,
+       char **attrs, int noattrs, int nobind,
        int innerloop, int maxretries, int delay, int force, int chaserefs );
 
 static void
 do_random( char *uri, char *manager, struct berval *passwd,
-       char *sbase, char *filter, char *attr, int noattrs, int nobind,
+       char *sbase, int scope, char *filter, char *attr,
+       char **attrs, int noattrs, int nobind,
        int innerloop, int maxretries, int delay, int force, int chaserefs );
 
 static void
-usage( char *name )
+usage( char *name, char o )
 {
+       if ( o != '\0' ) {
+               fprintf( stderr, "unknown/incorrect option \"%c\"\n", o );
+       }
+
         fprintf( stderr,
                "usage: %s "
                "-H <uri> | ([-h <host>] -p <port>) "
                "-D <manager> "
                "-w <passwd> "
                "-b <searchbase> "
+               "-s <scope> "
                "-f <searchfilter> "
                "[-a <attr>] "
                "[-A] "
@@ -67,7 +75,9 @@ usage( char *name )
                "[-l <loops>] "
                "[-L <outerloops>] "
                "[-r <maxretries>] "
-               "[-t <delay>]\n",
+               "[-t <delay>] "
+               "[<attrs>] "
+               "\n",
                        name );
        exit( EXIT_FAILURE );
 }
@@ -82,8 +92,11 @@ main( int argc, char **argv )
        char            *manager = NULL;
        struct berval   passwd = { 0, NULL };
        char            *sbase = NULL;
+       int             scope = LDAP_SCOPE_SUBTREE;
        char            *filter  = NULL;
        char            *attr = NULL;
+       char            *srchattrs[] = { "cn", "sn", NULL };
+       char            **attrs = srchattrs;
        int             loops = LOOPS;
        int             outerloops = 1;
        int             retries = RETRIES;
@@ -98,7 +111,7 @@ main( int argc, char **argv )
        /* by default, tolerate referrals and no such object */
        tester_ignore_str2errlist( "REFERRAL,NO_SUCH_OBJECT" );
 
-       while ( ( i = getopt( argc, argv, "Aa:b:CD:f:FH:h:i:l:L:Np:r:t:w:" ) ) != EOF )
+       while ( ( i = getopt( argc, argv, "Aa:b:CD:f:FH:h:i:l:L:Np:r:s:t:T:w:" ) ) != EOF )
        {
                switch ( i ) {
                case 'A':
@@ -127,7 +140,7 @@ main( int argc, char **argv )
 
                case 'p':               /* the servers port */
                        if ( lutil_atoi( &port, optarg ) != 0 ) {
-                               usage( argv[0] );
+                               usage( argv[0], i );
                        }
                        break;
 
@@ -159,36 +172,50 @@ main( int argc, char **argv )
 
                case 'l':               /* number of loops */
                        if ( lutil_atoi( &loops, optarg ) != 0 ) {
-                               usage( argv[0] );
+                               usage( argv[0], i );
                        }
                        break;
 
                case 'L':               /* number of loops */
                        if ( lutil_atoi( &outerloops, optarg ) != 0 ) {
-                               usage( argv[0] );
+                               usage( argv[0], i );
                        }
                        break;
 
                case 'r':               /* number of retries */
                        if ( lutil_atoi( &retries, optarg ) != 0 ) {
-                               usage( argv[0] );
+                               usage( argv[0], i );
                        }
                        break;
 
                case 't':               /* delay in seconds */
                        if ( lutil_atoi( &delay, optarg ) != 0 ) {
-                               usage( argv[0] );
+                               usage( argv[0], i );
+                       }
+                       break;
+
+               case 'T':
+                       attrs = ldap_str2charray( optarg, "," );
+                       if ( attrs == NULL ) {
+                               usage( argv[0], i );
+                       }
+                       break;
+
+               case 's':
+                       scope = ldap_pvt_str2scope( optarg );
+                       if ( scope == -1 ) {
+                               usage( argv[0], i );
                        }
                        break;
 
                default:
-                       usage( argv[0] );
+                       usage( argv[0], i );
                        break;
                }
        }
 
        if (( sbase == NULL ) || ( filter == NULL ) || ( port == -1 && uri == NULL ))
-               usage( argv[0] );
+               usage( argv[0], '\0' );
 
        if ( *filter == '\0' ) {
 
@@ -198,16 +225,24 @@ main( int argc, char **argv )
 
        }
 
+       if ( argv[optind] != NULL ) {
+               attrs = &argv[optind];
+       }
+
        uri = tester_uri( uri, host, port );
 
        for ( i = 0; i < outerloops; i++ ) {
                if ( attr != NULL ) {
-                       do_random( uri, manager, &passwd, sbase, filter, attr,
-                               noattrs, nobind, loops, retries, delay, force, chaserefs );
+                       do_random( uri, manager, &passwd,
+                               sbase, scope, filter, attr,
+                               attrs, noattrs, nobind,
+                               loops, retries, delay, force, chaserefs );
 
                } else {
-                       do_search( uri, manager, &passwd, sbase, filter, NULL,
-                               noattrs, nobind, loops, retries, delay, force, chaserefs );
+                       do_search( uri, manager, &passwd,
+                               sbase, scope, filter, NULL,
+                               attrs, noattrs, nobind,
+                               loops, retries, delay, force, chaserefs );
                }
        }
 
@@ -217,7 +252,8 @@ main( int argc, char **argv )
 
 static void
 do_random( char *uri, char *manager, struct berval *passwd,
-       char *sbase, char *filter, char *attr, int noattrs, int nobind,
+       char *sbase, int scope, char *filter, char *attr,
+       char **srchattrs, int noattrs, int nobind,
        int innerloop, int maxretries, int delay, int force, int chaserefs )
 {
        LDAP    *ld = NULL;
@@ -315,8 +351,10 @@ do_random( char *uri, char *manager, struct berval *passwd,
 
                        snprintf( buf, sizeof( buf ), "(%s=%s)", attr, values[ r ] );
 
-                       do_search( uri, manager, passwd, sbase, buf, &ld, noattrs, nobind,
-                                       1, maxretries, delay, force, chaserefs );
+                       do_search( uri, manager, passwd,
+                               sbase, scope, buf, &ld,
+                               srchattrs, noattrs, nobind,
+                               1, maxretries, delay, force, chaserefs );
                }
                break;
 
@@ -334,12 +372,12 @@ do_random( char *uri, char *manager, struct berval *passwd,
 
 static void
 do_search( char *uri, char *manager, struct berval *passwd,
-       char *sbase, char *filter, LDAP **ldp, int noattrs, int nobind,
+       char *sbase, int scope, char *filter, LDAP **ldp,
+       char **attrs, int noattrs, int nobind,
        int innerloop, int maxretries, int delay, int force, int chaserefs )
 {
        LDAP    *ld = ldp ? *ldp : NULL;
        int     i = 0, do_retry = maxretries;
-       char    *attrs[] = { "cn", "sn", NULL };
        int     rc = LDAP_SUCCESS;
        int     version = LDAP_VERSION3;
        char    buf[ BUFSIZ ];
@@ -358,8 +396,13 @@ retry:;
                        chaserefs ? LDAP_OPT_ON : LDAP_OPT_OFF );
 
                if ( do_retry == maxretries ) {
-                       fprintf( stderr, "PID=%ld - Search(%d): base=\"%s\", filter=\"%s\".\n",
-                                       (long) pid, innerloop, sbase, filter );
+                       fprintf( stderr,
+                               "PID=%ld - Search(%d): "
+                               "base=\"%s\" scope=%s filter=\"%s\" "
+                               "attrs=%s%s.\n",
+                               (long) pid, innerloop,
+                               sbase, ldap_pvt_scope2str( scope ), filter,
+                               attrs[0], attrs[1] ? " (more...)" : "" );
                }
 
                if ( nobind == 0 ) {
@@ -373,6 +416,7 @@ retry:;
                                case LDAP_UNAVAILABLE:
                                        if ( do_retry > 0 ) {
                                                ldap_unbind_ext( ld, NULL, NULL );
+                                               ld = NULL;
                                                do_retry--;
                                                if ( delay != 0 ) {
                                                    sleep( delay );
@@ -391,7 +435,7 @@ retry:;
        for ( ; i < innerloop; i++ ) {
                LDAPMessage *res = NULL;
 
-               rc = ldap_search_ext_s( ld, sbase, LDAP_SCOPE_SUBTREE,
+               rc = ldap_search_ext_s( ld, sbase, scope,
                                filter, attrs, noattrs, NULL, NULL,
                                NULL, LDAP_NO_LIMIT, &res );
                if ( res != NULL ) {
index 6cbc13fd109665ed5c7ce0711ac770b5e93c17db..d24d3b9e4ee4248dfa454270fc1bcdf3b6117174 100644 (file)
 
 #include <stdio.h>
 
-#include <ac/stdlib.h>
+#include "ac/stdlib.h"
 
-#include <ac/ctype.h>
-#include <ac/dirent.h>
-#include <ac/param.h>
-#include <ac/socket.h>
-#include <ac/string.h>
-#include <ac/unistd.h>
-#include <ac/wait.h>
+#include "ac/ctype.h"
+#include "ac/dirent.h"
+#include "ac/param.h"
+#include "ac/socket.h"
+#include "ac/string.h"
+#include "ac/unistd.h"
+#include "ac/wait.h"
 
 
 #include "ldap_defaults.h"
@@ -60,7 +60,7 @@
 #define TBINDFILE              "do_bind.0"
 
 static char *get_file_name( char *dirname, char *filename );
-static int  get_search_filters( char *filename, char *filters[], char *attrs[], char *bases[] );
+static int  get_search_filters( char *filename, char *filters[], char *attrs[], char *bases[], LDAPURLDesc *luds[] );
 static int  get_read_entries( char *filename, char *entries[], char *filters[] );
 static void fork_child( char *prog, char **args );
 static void    wait4kids( int nkidval );
@@ -133,9 +133,11 @@ main( int argc, char **argv )
        char            *sreqs[MAXREQS];
        char            *sattrs[MAXREQS];
        char            *sbase[MAXREQS];
+       LDAPURLDesc     *slud[MAXREQS];
        int             snum = 0;
        char            *sargs[MAXARGS];
        int             sanum;
+       int             sextra_args = 0;
        char            scmd[MAXPATHLEN];
        /* static so that its address can be used in initializer below. */
        static char     sloops[] = "18446744073709551615UL";
@@ -146,6 +148,7 @@ main( int argc, char **argv )
        char            *rargs[MAXARGS];
        char            *rflts[MAXREQS];
        int             ranum;
+       int             rextra_args = 0;
        char            rcmd[MAXPATHLEN];
        static char     rloops[] = "18446744073709551615UL";
        /* addel */
@@ -412,29 +415,64 @@ main( int argc, char **argv )
                passwd = pw.bv_val;
        }
 
+       if ( !sfile && !rfile && !nfile && !mfile && !bfile && !anum ) {
+               fprintf( stderr, "no data files found.\n" );
+               exit( EXIT_FAILURE );
+       }
+
        /* look for search requests */
        if ( sfile ) {
-               snum = get_search_filters( sfile, sreqs, sattrs, sbase );
+               snum = get_search_filters( sfile, sreqs, sattrs, sbase, slud );
+               if ( snum < 0 ) {
+                       fprintf( stderr,
+                               "unable to parse file \"%s\" line %d\n",
+                               sfile, -2*(snum + 1));
+                       exit( EXIT_FAILURE );
+               }
        }
 
        /* look for read requests */
        if ( rfile ) {
                rnum = get_read_entries( rfile, rreqs, rflts );
+               if ( rnum < 0 ) {
+                       fprintf( stderr,
+                               "unable to parse file \"%s\" line %d\n",
+                               rfile, -2*(rnum + 1) );
+                       exit( EXIT_FAILURE );
+               }
        }
 
        /* look for modrdn requests */
        if ( nfile ) {
                nnum = get_read_entries( nfile, nreqs, NULL );
+               if ( nnum < 0 ) {
+                       fprintf( stderr,
+                               "unable to parse file \"%s\" line %d\n",
+                               nfile, -2*(nnum + 1) );
+                       exit( EXIT_FAILURE );
+               }
        }
 
        /* look for modify requests */
        if ( mfile ) {
-               mnum = get_search_filters( mfile, mreqs, NULL, mdn );
+               mnum = get_search_filters( mfile, mreqs, NULL, mdn, NULL );
+               if ( mnum < 0 ) {
+                       fprintf( stderr,
+                               "unable to parse file \"%s\" line %d\n",
+                               mfile, -2*(mnum + 1) );
+                       exit( EXIT_FAILURE );
+               }
        }
 
        /* look for bind requests */
        if ( bfile ) {
-               bnum = get_search_filters( bfile, bcreds, battrs, breqs );
+               bnum = get_search_filters( bfile, bcreds, battrs, breqs, NULL );
+               if ( bnum < 0 ) {
+                       fprintf( stderr,
+                               "unable to parse file \"%s\" line %d\n",
+                               bfile, -2*(bnum + 1) );
+                       exit( EXIT_FAILURE );
+               }
        }
 
        /* setup friendly option */
@@ -508,13 +546,16 @@ main( int argc, char **argv )
        }
        sargs[sanum++] = "-b";
        sargs[sanum++] = NULL;          /* will hold the search base */
+       sargs[sanum++] = "-s";
+       sargs[sanum++] = NULL;          /* will hold the search scope */
        sargs[sanum++] = "-f";
        sargs[sanum++] = NULL;          /* will hold the search request */
 
        sargs[sanum++] = NULL;
-       sargs[sanum] = NULL;            /* might hold the "attr" request */
+       sargs[sanum++] = NULL;          /* might hold the "attr" request */
+       sextra_args += 2;
 
-       sargs[sanum + 1] = NULL;
+       sargs[sanum] = NULL;
 
        /*
         * generate the read clients
@@ -562,9 +603,10 @@ main( int argc, char **argv )
        rargs[ranum++] = NULL;          /* will hold the read entry */
 
        rargs[ranum++] = NULL;
-       rargs[ranum] = NULL;            /* might hold the filter arg */
+       rargs[ranum++] = NULL;          /* might hold the filter arg */
+       rextra_args += 2;
 
-       rargs[ranum + 1] = NULL;
+       rargs[ranum] = NULL;
 
        /*
         * generate the modrdn clients
@@ -607,7 +649,7 @@ main( int argc, char **argv )
        }
        nargs[nanum++] = "-e";
        nargs[nanum++] = NULL;          /* will hold the modrdn entry */
-       nargs[nanum++] = NULL;
+       nargs[nanum] = NULL;
        
        /*
         * generate the modify clients
@@ -652,7 +694,7 @@ main( int argc, char **argv )
        margs[manum++] = NULL;          /* will hold the modify entry */
        margs[manum++] = "-a";;
        margs[manum++] = NULL;          /* will hold the ava */
-       margs[manum++] = NULL;
+       margs[manum] = NULL;
 
        /*
         * generate the add/delete clients
@@ -695,7 +737,7 @@ main( int argc, char **argv )
        }
        aargs[aanum++] = "-f";
        aargs[aanum++] = NULL;          /* will hold the add data file */
-       aargs[aanum++] = NULL;
+       aargs[aanum] = NULL;
 
        /*
         * generate the bind clients
@@ -745,56 +787,99 @@ main( int argc, char **argv )
        bargs[banum++] = NULL;
        bargs[banum++] = "-w";
        bargs[banum++] = NULL;
-       bargs[banum++] = NULL;
+       bargs[banum] = NULL;
 
 #define        DOREQ(n,j) ((n) && ((maxkids > (n)) ? ((j) < maxkids ) : ((j) < (n))))
 
        for ( j = 0; j < MAXREQS; j++ ) {
+               /* search */
                if ( DOREQ( snum, j ) ) {
                        int     jj = j % snum;
+                       int     x = sanum - sextra_args;
 
-                       sargs[sanum - 2] = sreqs[jj];
-                       sargs[sanum - 4] = sbase[jj];
-                       if ( sattrs[jj] != NULL ) {
-                               sargs[sanum - 1] = "-a";
-                               sargs[sanum] = sattrs[jj];
+                       /* base */
+                       if ( sbase[jj] != NULL ) {
+                               sargs[sanum - 7] = sbase[jj];
+
+                       } else {
+                               sargs[sanum - 7] = slud[jj]->lud_dn;
+                       }
+
+                       /* scope */
+                       if ( slud[jj] != NULL ) {
+                               sargs[sanum - 5] = (char *)ldap_pvt_scope2str( slud[jj]->lud_scope );
+
+                       } else {
+                               sargs[sanum - 5] = "sub";
+                       }
+
+                       /* filter */
+                       if ( sreqs[jj] != NULL ) {
+                               sargs[sanum - 3] = sreqs[jj];
+
+                       } else if ( slud[jj]->lud_filter != NULL ) {
+                               sargs[sanum - 3] = slud[jj]->lud_filter;
 
                        } else {
-                               sargs[sanum - 1] = NULL;
+                               sargs[sanum - 3] = "(objectClass=*)";
                        }
+
+                       /* extras */
+                       sargs[x] = NULL;
+
+                       /* attr */
+                       if ( sattrs[jj] != NULL ) {
+                               sargs[x++] = "-a";
+                               sargs[x++] = sattrs[jj];
+                       }
+
+                       /* attrs */
+                       if ( slud[jj] != NULL && slud[jj]->lud_attrs != NULL ) {
+                               int     i;
+
+                               for ( i = 0; slud[jj]->lud_attrs[ i ] != NULL && x + i < MAXARGS - 1; i++ ) {
+                                       sargs[x + i] = slud[jj]->lud_attrs[ i ];
+                               }
+                               sargs[x + i] = NULL;
+                       }
+
                        fork_child( scmd, sargs );
                }
 
+               /* read */
                if ( DOREQ( rnum, j ) ) {
                        int     jj = j % rnum;
+                       int     x = ranum - rextra_args;
 
-                       rargs[ranum - 2] = rreqs[jj];
+                       rargs[ranum - 3] = rreqs[jj];
                        if ( rflts[jj] != NULL ) {
-                               rargs[ranum - 1] = "-f";
-                               rargs[ranum] = rflts[jj];
-
-                       } else {
-                               rargs[ranum - 1] = NULL;
+                               rargs[x++] = "-f";
+                               rargs[x++] = rflts[jj];
                        }
+                       rargs[x] = NULL;
                        fork_child( rcmd, rargs );
                }
 
+               /* rename */
                if ( j < nnum ) {
-                       nargs[nanum - 2] = nreqs[j];
+                       nargs[nanum - 1] = nreqs[j];
                        fork_child( ncmd, nargs );
                }
 
+               /* modify */
                if ( j < mnum ) {
-                       margs[manum - 4] = mdn[j];
-                       margs[manum - 2] = mreqs[j];
+                       margs[manum - 3] = mdn[j];
+                       margs[manum - 1] = mreqs[j];
                        fork_child( mcmd, margs );
                }
 
+               /* add/delete */
                if ( j < anum ) {
-                       aargs[aanum - 2] = afiles[j];
+                       aargs[aanum - 1] = afiles[j];
                        fork_child( acmd, aargs );
                }
 
+               /* bind */
                if ( DOREQ( bnum, j ) ) {
                        int     jj = j % bnum;
 
@@ -808,23 +893,24 @@ main( int argc, char **argv )
                        }
 
                        if ( battrs[jj] != NULL ) {
-                               bargs[banum - 4] = manager ? manager : "";
-                               bargs[banum - 2] = passwd ? passwd : "";
-
-                               bargs[banum - 1] = "-b";
-                               bargs[banum] = breqs[jj];
-                               bargs[banum + 1] = "-f";
-                               bargs[banum + 2] = bcreds[jj];
-                               bargs[banum + 3] = "-a";
-                               bargs[banum + 4] = battrs[jj];
+                               bargs[banum - 3] = manager ? manager : "";
+                               bargs[banum - 1] = passwd ? passwd : "";
+
+                               bargs[banum - 2] = "-b";
+                               bargs[banum - 1] = breqs[jj];
+                               bargs[banum + 0] = "-f";
+                               bargs[banum + 1] = bcreds[jj];
+                               bargs[banum + 2] = "-a";
+                               bargs[banum + 3] = battrs[jj];
+
                        } else {
-                               bargs[banum - 4] = breqs[jj];
-                               bargs[banum - 2] = bcreds[jj];
-                               bargs[banum - 1] = NULL;
+                               bargs[banum - 3] = breqs[jj];
+                               bargs[banum - 1] = bcreds[jj];
+                               bargs[banum] = NULL;
                        }
 
                        fork_child( bcmd, bargs );
-                       bargs[banum - 1] = NULL;
+                       bargs[banum] = NULL;
                }
        }
 
@@ -845,7 +931,7 @@ get_file_name( char *dirname, char *filename )
 
 
 static int
-get_search_filters( char *filename, char *filters[], char *attrs[], char *bases[] )
+get_search_filters( char *filename, char *filters[], char *attrs[], char *bases[], LDAPURLDesc *luds[] )
 {
        FILE    *fp;
        int     filter = 0;
@@ -854,11 +940,35 @@ get_search_filters( char *filename, char *filters[], char *attrs[], char *bases[
                char  line[BUFSIZ];
 
                while (( filter < MAXREQS ) && ( fgets( line, BUFSIZ, fp ))) {
-                       char *nl;
+                       char    *nl;
+                       int     got_URL = 0;
 
                        if (( nl = strchr( line, '\r' )) || ( nl = strchr( line, '\n' )))
                                *nl = '\0';
-                       bases[filter] = ArgDup( line );
+
+                       if ( luds ) luds[filter] = NULL;
+
+                       if ( luds && strncmp( line, "ldap:///", STRLENOF( "ldap:///" ) ) == 0 ) {
+                               LDAPURLDesc     *lud;
+
+                               got_URL = 1;
+                               bases[filter] = NULL;
+                               if ( ldap_url_parse( line, &lud ) != LDAP_URL_SUCCESS ) {
+                                       filter = -filter - 1;
+                                       break;
+                               }
+
+                               if ( lud->lud_dn == NULL || lud->lud_exts != NULL ) {
+                                       filter = -filter - 1;
+                                       ldap_free_urldesc( lud );
+                                       break;
+                               }
+
+                               luds[filter] = lud;
+
+                       } else {
+                               bases[filter] = ArgDup( line );
+                       }
                        fgets( line, BUFSIZ, fp );
                        if (( nl = strchr( line, '\r' )) || ( nl = strchr( line, '\n' )))
                                *nl = '\0';
@@ -868,15 +978,15 @@ get_search_filters( char *filename, char *filters[], char *attrs[], char *bases[
                                if ( filters[filter][0] == '+') {
                                        char    *sep = strchr( filters[filter], ':' );
 
+                                       attrs[ filter ] = &filters[ filter ][ 1 ];
                                        if ( sep != NULL ) {
-                                               attrs[ filter ] = &filters[ filter ][ 1 ];
                                                sep[ 0 ] = '\0';
                                                /* NOTE: don't free this! */
                                                filters[ filter ] = &sep[ 1 ];
                                        }
 
                                } else {
-                                       attrs[ filter] = NULL;
+                                       attrs[ filter ] = NULL;
                                }
                        }
                        filter++;
@@ -885,7 +995,7 @@ get_search_filters( char *filename, char *filters[], char *attrs[], char *bases[
                fclose( fp );
        }
 
-       return( filter );
+       return filter;
 }
 
 
@@ -907,13 +1017,13 @@ get_read_entries( char *filename, char *entries[], char *filters[] )
                                LDAPURLDesc     *lud;
 
                                if ( ldap_url_parse( &line[1], &lud ) != LDAP_URL_SUCCESS ) {
-                                       entry = -1;
+                                       entry = -entry - 1;
                                        break;
                                }
 
                                if ( lud->lud_dn == NULL || lud->lud_dn[ 0 ] == '\0' ) {
                                        ldap_free_urldesc( lud );
-                                       entry = -1;
+                                       entry = -entry - 1;
                                        break;
                                }
 
index a8bcaa1cacf41ad0cf4d7534cee642db88ae46c3..24133fbcb5d33e0156059cd874b8f927dfb082eb 100644 (file)
@@ -55,10 +55,10 @@ AC_THREADS=threads@BUILD_THREAD@
 AC_LIBS_DYNAMIC=lib@BUILD_LIBS_DYNAMIC@
 
 # sanitize
-if test "${AC_ldap}" = "ldapmod" -a "${AC_LIBS_DYNAMIC}" = "static" ; then
+if test "${AC_ldap}" = "ldapmod" && test "${AC_LIBS_DYNAMIC}" = "static" ; then
        AC_ldap="ldapno"
 fi
-if test "${AC_meta}" = "metamod" -a "${AC_LIBS_DYNAMIC}" = "static" ; then
+if test "${AC_meta}" = "metamod" && test "${AC_LIBS_DYNAMIC}" = "static" ; then
        AC_meta="metano"
 fi
 
@@ -176,22 +176,19 @@ if test -d ${TESTDIR} ; then
                /bin/rm -rf ${TESTDIR}/db.*
        fi
 fi
+mkdir -p ${TESTDIR}
 
 if test $USERDATA = yes ; then
        if test ! -d userdata ; then
                echo "User data directory (userdata) does not exist."
                exit 1
        fi
-       mkdir -p ${TESTDIR}
        cp -R userdata/* ${TESTDIR}
 fi
 
 # disable LDAP initialization
 LDAPNOINIT=true; export LDAPNOINIT
 
-$SLAPPASSWD -g -n >$CONFIGPWF
-echo "rootpw `$SLAPPASSWD -T $CONFIGPWF`" >configpw.conf
-
 echo "Running ${SCRIPT}..."
 $SCRIPT $*
 RC=$?
index e05bba09ab92773dd9b521a49e170c149a79c2b3..3e8c80886f41cc0dd16b531fdd71389086144e80 100755 (executable)
 ## top-level directory of the distribution or, alternatively, at
 ## <http://www.OpenLDAP.org/license.html>.
 
-SHTOOL="$SRCDIR/../build/shtool"
-TB=`$SHTOOL echo -e "%B"`
-TN=`$SHTOOL echo -e "%b"`
+. $SRCDIR/scripts/defines.sh
+
+TB="" TN=""
+if test -t 1 ; then
+       TB=`$SHTOOL echo -e "%B" 2>/dev/null`
+       TN=`$SHTOOL echo -e "%b" 2>/dev/null`
+fi
+
 SLEEPTIME=10
 
 echo ">>>>> Executing all LDAP tests for $BACKEND"
@@ -23,9 +28,9 @@ echo ">>>>> Executing all LDAP tests for $BACKEND"
 for CMD in $SRCDIR/scripts/test*; do
        # remove cruft from prior test
        if test $PRESERVE = yes ; then
-               /bin/rm -rf testrun/db.*
+               /bin/rm -rf $TESTDIR/db.*
        else
-               /bin/rm -rf testrun
+               /bin/rm -rf $TESTDIR
        fi
 
        echo ">>>>> Starting ${TB}`basename $CMD`${TN} ..."
index 8f4e7ad1212c40b15f6a5a2d51fa7e6a53321b18..53bf7eb84347e253fd408f83c0602362124267c3 100755 (executable)
@@ -15,6 +15,8 @@
 
 umask 077
 
+TESTWD=`pwd`
+
 # backends
 MONITORDB=${AC_monitor-no}
 BACKLDAP=${AC_ldap-ldapno}
@@ -41,14 +43,13 @@ VALSORT=${AC_valsort-valsortno}
 # misc
 WITH_SASL=${AC_WITH_SASL-no}
 USE_SASL=${SLAPD_USE_SASL-no}
-WITHTLS=${AC_WITHTLS-yes}
 ACI=${AC_ACI_ENABLED-acino}
 THREADS=${AC_THREADS-threadsno}
 
 # dirs
 PROGDIR=./progs
 DATADIR=${USER_DATADIR-./testdata}
-TESTDIR=${USER_TESTDIR-./testrun}
+TESTDIR=${USER_TESTDIR-$TESTWD/testrun}
 SCHEMADIR=${USER_SCHEMADIR-./schema}
 
 DBDIR1A=$TESTDIR/db.1.a
@@ -77,11 +78,9 @@ PWCONF=$DATADIR/slapd-pw.conf
 WHOAMICONF=$DATADIR/slapd-whoami.conf
 ACLCONF=$DATADIR/slapd-acl.conf
 RCONF=$DATADIR/slapd-referrals.conf
-MASTERCONF=$DATADIR/slapd-repl-master.conf
 SRMASTERCONF=$DATADIR/slapd-syncrepl-master.conf
 DSRMASTERCONF=$DATADIR/slapd-deltasync-master.conf
 DSRSLAVECONF=$DATADIR/slapd-deltasync-slave.conf
-SLAVECONF=$DATADIR/slapd-repl-slave.conf
 PPOLICYCONF=$DATADIR/slapd-ppolicy.conf
 PROXYCACHECONF=$DATADIR/slapd-proxycache.conf
 CACHEMASTERCONF=$DATADIR/slapd-cache-master.conf
@@ -135,6 +134,7 @@ CONF4=$TESTDIR/slapd.4.conf
 CONF5=$TESTDIR/slapd.5.conf
 CONF6=$TESTDIR/slapd.6.conf
 ADDCONF=$TESTDIR/slapadd.conf
+CONFLDIF=$TESTDIR/slapd-dynamic.ldif
 
 LOG1=$TESTDIR/slapd.1.log
 LOG2=$TESTDIR/slapd.2.log
@@ -145,7 +145,7 @@ LOG6=$TESTDIR/slapd.6.log
 SLAPADDLOG1=$TESTDIR/slapadd.1.log
 SLURPLOG=$TESTDIR/slurp.log
 
-CONFIGPWF=./configpw
+CONFIGPWF=$TESTDIR/configpw
 
 # args
 TOOLARGS="-x $LDAP_TOOLARGS"
@@ -155,10 +155,10 @@ TOOLPROTO="-P 3"
 LDIFFILTER=$SRCDIR/scripts/acfilter.sh
 CONFFILTER=$SRCDIR/scripts/conf.sh
 
-SLAPADD="`pwd`/../servers/slapd/slapd -Ta -d 0 $LDAP_VERBOSE"
-SLAPCAT="`pwd`/../servers/slapd/slapd -Tc -d 0 $LDAP_VERBOSE"
-SLAPINDEX="`pwd`/../servers/slapd/slapd -Ti -d 0 $LDAP_VERBOSE"
-SLAPPASSWD="`pwd`/../servers/slapd/slapd -Tpasswd"
+SLAPADD="$TESTWD/../servers/slapd/slapd -Ta -d 0 $LDAP_VERBOSE"
+SLAPCAT="$TESTWD/../servers/slapd/slapd -Tc -d 0 $LDAP_VERBOSE"
+SLAPINDEX="$TESTWD/../servers/slapd/slapd -Ti -d 0 $LDAP_VERBOSE"
+SLAPPASSWD="$TESTWD/../servers/slapd/slapd -Tpasswd"
 
 unset DIFF_OPTIONS
 # NOTE: -u/-c is not that portable...
@@ -166,8 +166,7 @@ DIFF="diff -i"
 CMP="diff -i"
 BCMP="diff -iB"
 CMPOUT=/dev/null
-SLAPD="`pwd`/../servers/slapd/slapd -s0"
-SLURPD="`pwd`/../servers/slurpd/slurpd"
+SLAPD="$TESTWD/../servers/slapd/slapd -s0"
 LDAPPASSWD="$CLIENTDIR/ldappasswd $TOOLARGS"
 LDAPSASLSEARCH="$CLIENTDIR/ldapsearch $TOOLPROTO $LDAP_TOOLARGS -LLL"
 LDAPSEARCH="$CLIENTDIR/ldapsearch $TOOLPROTO $TOOLARGS -LLL"
@@ -325,6 +324,7 @@ SUBTREERENAMEOUT=$DATADIR/subtree-rename.out
 ACIOUT=$DATADIR/aci.out
 DYNLISTOUT=$DATADIR/dynlist.out
 DDSOUT=$DATADIR/dds.out
+SHTOOL="$SRCDIR/../build/shtool"
 
 # Just in case we linked the binaries dynamically
-LD_LIBRARY_PATH=`pwd`/../libraries:${LD_LIBRARY_PATH} export LD_LIBRARY_PATH
+LD_LIBRARY_PATH=$TESTWD/../libraries:${LD_LIBRARY_PATH} export LD_LIBRARY_PATH
index da140b309717f7d7dae604d468c5b149e9226cde..11620ae322d2ad674e71ed0edf585ddf4eb4e62b 100755 (executable)
 ## <http://www.OpenLDAP.org/license.html>.
 
 SHTOOL="$SRCDIR/../build/shtool"
-TB=`$SHTOOL echo -e "%B"`
-TN=`$SHTOOL echo -e "%b"`
+
+TB="" TN=""
+if test -t 1 ; then
+       TB=`$SHTOOL echo -e "%B" 2>/dev/null`
+       TN=`$SHTOOL echo -e "%b" 2>/dev/null`
+fi
 
 echo "#######################################################################"
 echo "###                                                                 ###"
@@ -44,6 +48,5 @@ for CMD in $SRCDIR/data/regressions/its*/its*; do
                exit $RC
        fi
 
-       echo ">>>>> waiting for things to exit"
        echo ""
 done
index 67ff71339413a174b664af6d5494d0e6d91b70b2..5c8fef7408a43b9276fa8e4271fb312e8b085d34 100755 (executable)
 ## <http://www.OpenLDAP.org/license.html>.
 
 SHTOOL="$SRCDIR/../build/shtool"
-TB=`$SHTOOL echo -e "%B"`
-TN=`$SHTOOL echo -e "%b"`
+
+TB="" TN=""
+if test -t 1 ; then
+       TB=`$SHTOOL echo -e "%B" 2>/dev/null`
+       TN=`$SHTOOL echo -e "%b" 2>/dev/null`
+fi
+
 SLEEPTIME=10
 
 echo "#######################################################################"
index 8c70395166733073ebcae1c4e496ff9faefcf3c6..d899763d36148aa31c9d50aa733b3ded7f21b0ef 100755 (executable)
@@ -79,7 +79,8 @@ fi
 
 echo "Testing baseobject search..."
 echo "# Testing baseobject search..." >> $SEARCHOUT
-$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" -s base >> $SEARCHOUT 2>&1
+$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" -s base -S "" \
+       >> $SEARCHOUT 2>&1
 
 RC=$?
 if test $RC != 0 ; then
@@ -90,7 +91,8 @@ fi
 
 echo "Testing onelevel search..."
 echo "# Testing onelevel search..." >> $SEARCHOUT
-$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" -s one >> $SEARCHOUT 2>&1
+$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" -s one -S "" \
+       >> $SEARCHOUT 2>&1
 
 RC=$?
 if test $RC != 0 ; then
@@ -101,7 +103,8 @@ fi
 
 echo "Testing subtree search..."
 echo "# Testing subtree search..." >> $SEARCHOUT
-$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" >> $SEARCHOUT 2>&1
+$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" -S "" \
+       >> $SEARCHOUT 2>&1
 
 RC=$?
 if test $RC != 0 ; then
@@ -112,7 +115,8 @@ fi
 
 echo "Testing subtree search with manageDSAit..."
 echo "# Testing subtree search with manageDSAit..." >> $SEARCHOUT
-$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" -M '*' ref >> $SEARCHOUT 2>&1
+$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" -M -S "" '*' ref \
+       >> $SEARCHOUT 2>&1
 
 RC=$?
 if test $RC != 0 ; then
@@ -123,8 +127,8 @@ fi
 
 echo "Testing invalid filter..."
 echo "# Testing invalid filter..." >> $SEARCHOUT
-$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" \
-        "(foo=)" >> $SEARCHOUT 2>&1
+$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" -S "" "(foo=)" \
+       >> $SEARCHOUT 2>&1
 
 RC=$?
 if test $RC != 0 ; then
@@ -135,8 +139,8 @@ fi
 
 echo "Testing exact search..."
 echo "# Testing exact search..." >> $SEARCHOUT
-$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" \
-        "(sn=Kovalev)" >> $SEARCHOUT 2>&1
+$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" -S "" "(sn=Kovalev)" \
+       >> $SEARCHOUT 2>&1
 
 RC=$?
 if test $RC != 0 ; then
@@ -147,8 +151,8 @@ fi
 
 echo "Testing substrings initial search..."
 echo "# Testing substrings initial search..." >> $SEARCHOUT
-$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" \
-        "(cn=m*)" >> $SEARCHOUT 2>&1
+$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" -S "" "(cn=m*)" \
+       >> $SEARCHOUT 2>&1
 
 RC=$?
 if test $RC != 0 ; then
@@ -159,8 +163,8 @@ fi
 
 echo "Testing substrings any search..."
 echo "# Testing substrings any search..." >> $SEARCHOUT
-$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" \
-        "(cn=*m*)" >> $SEARCHOUT 2>&1
+$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" -S "" "(cn=*m*)" \
+       >> $SEARCHOUT 2>&1
 
 RC=$?
 if test $RC != 0 ; then
@@ -171,8 +175,8 @@ fi
 
 echo "Testing substrings final search..."
 echo "# Testing substrings final search..." >> $SEARCHOUT
-$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" \
-        "(cn=*v)" >> $SEARCHOUT 2>&1
+$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" -S "" "(cn=*v)" \
+       >> $SEARCHOUT 2>&1
 
 RC=$?
 if test $RC != 0 ; then
@@ -183,8 +187,8 @@ fi
 
 echo "Testing approx search..."
 echo "# Testing approx search..." >> $SEARCHOUT
-$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" \
-        "(sn~=kovalev)" >> $SEARCHOUT 2>&1
+$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" -S "" "(sn~=kovalev)" \
+       >> $SEARCHOUT 2>&1
 
 RC=$?
 if test $RC != 0 ; then
@@ -195,7 +199,7 @@ fi
 
 echo "Testing extensible filter search..."
 echo "# Testing extensible filter search..." >> $SEARCHOUT
-$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" \
+$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" -S "" \
         "(sn:caseExactMatch:=Kovalev)" >> $SEARCHOUT 2>&1
 
 RC=$?
@@ -207,7 +211,7 @@ fi
 
 echo "Testing search for telephoneNumber..."
 echo "# Testing search for telephoneNumber..." >> $SEARCHOUT
-$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" \
+$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" -S "" \
         "(telephoneNumber=3322334)" >> $SEARCHOUT 2>&1
 
 RC=$?
@@ -219,7 +223,7 @@ fi
 
 echo "Testing AND search..."
 echo "# Testing AND search..." >> $SEARCHOUT
-$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" \
+$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" -S "" \
         "(&(sn=kovalev)(givenName=mitya))" >> $SEARCHOUT 2>&1
 
 RC=$?
@@ -231,7 +235,7 @@ fi
 
 echo "Testing AND search on objectClass..."
 echo "# Testing AND search on objectClass..." >> $SEARCHOUT
-$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" \
+$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" -S "" \
         "(&(objectClass=organization)(objectClass=dcObject))" >> $SEARCHOUT 2>&1
 
 RC=$?
@@ -243,7 +247,7 @@ fi
 
 echo "Testing OR search..."
 echo "# Testing OR search..." >> $SEARCHOUT
-$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" \
+$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" -S "" \
         "(|(sn=kovalev)(givenName=mitya))" >> $SEARCHOUT 2>&1
 
 RC=$?
@@ -255,8 +259,9 @@ fi
 
 echo "Testing OR search on objectClass..."
 echo "# Testing OR search on objectClass..." >> $SEARCHOUT
-$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" \
-        "(|(objectClass=document)(objectClass=organization))" >> $SEARCHOUT 2>&1
+$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" -S "" \
+        "(|(objectClass=document)(objectClass=organization))" \
+       >> $SEARCHOUT 2>&1
 
 RC=$?
 if test $RC != 0 ; then
@@ -267,7 +272,7 @@ fi
 
 echo "Testing NOT search..."
 echo "# Testing NOT search..." >> $SEARCHOUT
-$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" \
+$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" -S "" \
         '(!(sn=kovalev))' >> $SEARCHOUT 2>&1
 
 RC=$?
@@ -279,7 +284,7 @@ fi
 
 echo "Testing NOT search on objectClass..."
 echo "# Testing NOT search on objectClass..." >> $SEARCHOUT
-$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" \
+$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" -S "" \
         '(!(objectClass=inetOrgPerson))' >> $SEARCHOUT 2>&1
 
 RC=$?
@@ -291,7 +296,7 @@ fi
 
 echo "Testing NOT search on \"auxiliary\" objectClass..."
 echo "# Testing NOT search on \"auxiliary\" objectClass..." >> $SEARCHOUT
-$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" \
+$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" -S "" \
         '(!(objectClass=dcObject))' >> $SEARCHOUT 2>&1
 
 RC=$?
@@ -304,7 +309,7 @@ fi
 #### Needs work...
 echo "Testing NOT presence search... (disabled)"
 ###echo "# Testing NOT presence search..." >> $SEARCHOUT
-###$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" \
+###$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" -S "" \
 ###     '(!(sn=*))' >> $SEARCHOUT 2>&1
 ###
 ###RC=$?
@@ -316,7 +321,7 @@ echo "Testing NOT presence search... (disabled)"
 
 echo "Testing attribute inheritance in filter..."
 echo "# Testing attribute inheritance in filter..." >> $SEARCHOUT
-$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" \
+$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" -S "" \
         "(name=example)" >> $SEARCHOUT 2>&1
 
 RC=$?
@@ -329,7 +334,7 @@ fi
 # ITS#4604
 echo "Testing undefined attribute in filter..."
 echo "# Testing undefined attribute in filter..." >> $SEARCHOUT
-$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" \
+$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" -S "" \
         "(|(o=example)(foobar=x))" >> $SEARCHOUT 2>&1
 
 RC=$?
@@ -341,7 +346,7 @@ fi
 
 echo "Testing objectClass inheritance in filter..."
 echo "# Testing objectClass inheritance in filter..." >> $SEARCHOUT
-$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" \
+$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" -S "" \
         "(objectClass=person)" >> $SEARCHOUT 2>&1
 
 RC=$?
@@ -353,7 +358,7 @@ fi
 
 echo "Testing \"auxiliary\" objectClass in filter..."
 echo "# Testing \"auxiliary\" objectClass in filter..." >> $SEARCHOUT
-$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" \
+$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" -S "" \
         "(objectClass=dcObject)" >> $SEARCHOUT 2>&1
 
 RC=$?
@@ -365,7 +370,7 @@ fi
 
 echo "Testing hasSubordinates in filter..."
 echo "# Testing hasSubordinates in filter..." >> $SEARCHOUT
-$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" \
+$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" -S "" \
         "(hasSubordinates=TRUE)" >> $SEARCHOUT 2>&1
 
 RC=$?
@@ -377,7 +382,7 @@ fi
 
 echo "Testing entryUUID in filter..."
 echo "# Testing entryUUID in filter..." >> $SEARCHOUT
-$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" \
+$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" -S "" \
         "(entryUUID=00000001-0000-0001-0000-000000000000)" >> $SEARCHOUT 2>&1
 
 RC=$?
@@ -389,7 +394,7 @@ fi
 
 echo "Testing attribute inheritance in requested attributes..."
 echo "# Testing attribute inheritance in requested attributes..." >> $SEARCHOUT
-$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" \
+$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" -S "" \
         "(sn=kovalev)" name >> $SEARCHOUT 2>&1
 
 RC=$?
@@ -401,7 +406,7 @@ fi
 
 echo "Testing objectClass in requested attributes..."
 echo "# Testing objectClass in requested attributes..." >> $SEARCHOUT
-$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" \
+$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" -S "" \
         objectClass >> $SEARCHOUT 2>&1
 
 RC=$?
@@ -413,7 +418,7 @@ fi
 
 echo "Testing operational attributes in request..."
 echo "# Testing operational attributes in request..." >> $SEARCHOUT
-$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" \
+$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" -S "" \
         '+' 2>&1 > $SEARCHFLT
 
 RC=$?
diff --git a/tests/scripts/test007-replication b/tests/scripts/test007-replication
deleted file mode 100755 (executable)
index 4ae4e89..0000000
+++ /dev/null
@@ -1,348 +0,0 @@
-#! /bin/sh
-# $OpenLDAP$
-## This work is part of OpenLDAP Software <http://www.openldap.org/>.
-##
-## Copyright 1998-2007 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>.
-
-echo "running defines.sh"
-. $SRCDIR/scripts/defines.sh
-
-if test ! -x $SLURPD ; then
-       echo ">>>>> $SLURPD is not executable or does not exist."
-       echo ">>>>> Test skipped."
-       exit 0
-fi
-
-mkdir -p $TESTDIR $DBDIR1A $DBDIR1B $DBDIR2
-
-#
-# Test replication:
-# - start master (slapd1)
-# - start slave (slapd2)
-# - start slurpd
-# - populate over ldap
-# - perform some modifies and deleted
-# - attempt to modify the slave (referral or chain)
-# - retrieve database over ldap and compare against expected results
-#
-
-echo "Starting master slapd on TCP/IP port $PORT1..."
-. $CONFFILTER $BACKEND $MONITORDB < $MASTERCONF > $CONF1
-$SLAPD -f $CONF1 -h $URI1 -d $LVL $TIMING > $LOG1 2>&1 &
-PID=$!
-if test $WAIT != 0 ; then
-    echo PID $PID
-    read foo
-fi
-KILLPIDS="$PID"
-
-echo "Starting slave slapd on TCP/IP port $PORT2..."
-. $CONFFILTER $BACKEND $MONITORDB < $SLAVECONF > $CONF2
-$SLAPD -f $CONF2 -h $URI2 -d $LVL $TIMING > $LOG2 2>&1 &
-SLAVEPID=$!
-if test $WAIT != 0 ; then
-    echo SLAVEPID $SLAVEPID
-    read foo
-fi
-KILLPIDS="$KILLPIDS $SLAVEPID"
-
-sleep 1
-
-echo "Using ldapsearch to check that master slapd is running..."
-for i in 0 1 2 3 4 5; do
-       $LDAPSEARCH -s base -b "$MONITOR" -h $LOCALHOST -p $PORT1 \
-               'objectclass=*' > /dev/null 2>&1
-       RC=$?
-       if test $RC = 0 ; then
-               break
-       fi
-       echo "Waiting 5 seconds for slapd to start..."
-       sleep 5
-done
-
-echo "Using ldapsearch to check that slave slapd is running..."
-for i in 0 1 2 3 4 5; do
-       $LDAPSEARCH -s base -b "$MONITOR" -h $LOCALHOST -p $PORT2 \
-               'objectclass=*' > /dev/null 2>&1
-       RC=$?
-       if test $RC = 0 ; then
-               break
-       fi
-       echo "Waiting 5 seconds for slapd to start..."
-       sleep 5
-done
-
-echo "Starting slurpd..."
-$SLURPD -f $CONF1 -d ${SLURPD_DEBUG-5} -t $DBDIR1B > $SLURPLOG 2>&1 &
-SLURPPID=$!
-if test $WAIT != 0 ; then
-    echo SLURPPID $SLURPPID
-    read foo
-fi
-KILLPIDS="$KILLPIDS $SLURPPID"
-
-echo "Using ldapadd to populate the master directory..."
-$LDAPADD -D "$MANAGERDN" -h $LOCALHOST -p $PORT1 -w $PASSWD < \
-       $LDIFORDERED > /dev/null 2>&1
-RC=$?
-if test $RC != 0 ; then
-       echo "ldapadd failed ($RC)!"
-       test $KILLSERVERS != no && kill -HUP $KILLPIDS
-       exit $RC
-fi
-
-echo "Waiting 15 seconds for slurpd to send changes..."
-sleep 15
-
-echo "Using ldapmodify to modify master directory..."
-
-#
-# Do some modifications
-#
-
-$LDAPMODIFY -v -D "$MANAGERDN" -h $LOCALHOST -p $PORT1 -w $PASSWD > \
-       $TESTOUT 2>&1 << EOMODS
-dn: cn=James A Jones 1, ou=Alumni Association, ou=People, dc=example, dc=com
-changetype: modify
-add: drink
-drink: Orange Juice
--
-delete: sn
-sn: Jones
--
-add: sn
-sn: Jones
-
-dn: cn=Bjorn Jensen, ou=Information Technology Division, ou=People, dc=example, dc=com
-changetype: modify
-replace: drink
-drink: Iced Tea
-drink: Mad Dog 20/20
-
-dn: cn=ITD Staff,ou=Groups,dc=example, dc=com
-changetype: modify
-delete: uniqueMember
-uniqueMember: cn=James A Jones 2, ou=Information Technology Division,
- ou=People, dc=example, dc=com
-uniqueMember: cn=Bjorn Jensen, ou=Information Technology Division, ou=People, dc=example, dc=com
--
-add: uniqueMember
-uniqueMember: cn=Dorothy Stevens, ou=Alumni Association, ou=People, dc=example, dc=com
-uniqueMember: cn=James A Jones 1, ou=Alumni Association, ou=People, dc=example, dc=com
-
-dn: cn=All Staff,ou=Groups,dc=example, dc=com
-changetype: modify
-delete: description
-
-dn: cn=Gern Jensen, ou=Information Technology Division, ou=People, dc=example, dc=com
-changetype: add
-objectclass: OpenLDAPperson
-cn: Gern Jensen
-sn: Jensen
-uid: gjensen
-title: Chief Investigator, ITD
-postaladdress: ITD $ 535 W. William St $ Ann Arbor, MI 48103
-seealso: cn=All Staff, ou=Groups, dc=example, dc=com
-drink: Coffee
-homepostaladdress: 844 Brown St. Apt. 4 $ Ann Arbor, MI 48104
-description: Very odd
-facsimiletelephonenumber: +1 313 555 7557
-telephonenumber: +1 313 555 8343
-mail: gjensen@mailgw.example.com
-homephone: +1 313 555 8844
-
-dn: ou=Retired, ou=People, dc=example, dc=com
-changetype: add
-objectclass: organizationalUnit
-ou: Retired
-
-dn: cn=Rosco P. Coltrane, ou=Information Technology Division, ou=People, dc=example, dc=com
-changetype: add
-objectclass: OpenLDAPperson
-cn: Rosco P. Coltrane
-sn: Coltrane
-uid: rosco
-
-dn: cn=Rosco P. Coltrane, ou=Information Technology Division, ou=People, dc=example, dc=com
-changetype: modrdn
-newrdn: cn=Rosco P. Coltrane
-deleteoldrdn: 1
-newsuperior: ou=Retired, ou=People, dc=example, dc=com
-
-dn: cn=James A Jones 2, ou=Information Technology Division, ou=People, dc=example, dc=com
-changetype: delete
-
-EOMODS
-
-RC=$?
-if test $RC != 0 ; then
-       echo "ldapmodify failed ($RC)!"
-       test $KILLSERVERS != no && kill -HUP $KILLPIDS
-       exit $RC
-fi
-
-echo "Waiting 15 seconds for slurpd to send changes..."
-sleep 15
-
-echo "Stopping the slave..."
-kill -HUP $SLAVEPID
-KILLPIDS="$PID $SLURPPID"
-
-echo "Waiting for slave slapd to die..."
-wait $SLAVEPID
-
-echo "Applying more changes to the master slapd..."
-$LDAPMODIFY -v -D "$MANAGERDN" -h $LOCALHOST -p $PORT1 -w $PASSWD > \
-       $TESTOUT 2>&1 << EOMODS
-dn: cn=James A Jones 1, ou=Alumni Association, ou=People, dc=example, dc=com
-changetype: modify
-add: description
-description: This change was applied after killing the slave slapd...
-
-EOMODS
-
-RC=$?
-
-if test $RC != 0 ; then
-       echo "ldapmodify failed ($RC)!"
-       test $KILLSERVERS != no && kill -HUP $KILLPIDS
-       exit $RC
-fi
-
-
-echo "Stopping slurpd..."
-kill -HUP $SLURPPID
-KILLPIDS="$PID"
-
-echo "Waiting for slurpd to die..."
-wait $SLURPPID
-
-echo "Applying more changes to the master slapd..."
-$LDAPMODIFY -v -D "$MANAGERDN" -h $LOCALHOST -p $PORT1 -w $PASSWD > \
-       $TESTOUT 2>&1 << EOMODS
-dn: cn=James A Jones 1, ou=Alumni Association, ou=People, dc=example, dc=com
-changetype: modify
-add: description
-description: This change was applied after killing slurpd...
-
-EOMODS
-
-RC=$?
-
-if test $RC != 0 ; then
-       echo "ldapmodify failed ($RC)!"
-       test $KILLSERVERS != no && kill -HUP $KILLPIDS
-       exit $RC
-fi
-
-echo "Restarting slave slapd on TCP/IP port $PORT2..."
-echo "RESTART" >> $LOG2
-$SLAPD -f $CONF2 -h $URI2 -d $LVL $TIMING >> $LOG2 2>&1 &
-SLAVEPID=$!
-if test $WAIT != 0 ; then
-    echo SLAVEPID $SLAVEPID
-    read foo
-fi
-KILLPIDS="$KILLPIDS $SLAVEPID"
-
-sleep 1
-
-echo "Using ldapsearch to check that slave slapd is running..."
-for i in 0 1 2 3 4 5; do
-       $LDAPSEARCH -s base -b "$MONITOR" -h $LOCALHOST -p $PORT2 \
-               'objectclass=*' > /dev/null 2>&1
-       RC=$?
-       if test $RC = 0 ; then
-               break
-       fi
-       echo "Waiting 5 seconds for slapd to start..."
-       sleep 5
-done
-
-echo "Restarting slurpd..."
-echo "RESTART" >> $SLURPLOG
-$SLURPD -f $CONF1 -d ${SLURPD_DEBUG-5} -t $DBDIR1B >> $SLURPLOG 2>&1 &
-SLURPPID=$!
-if test $WAIT != 0 ; then
-    echo SLURPPID $SLURPPID
-    read foo
-fi
-KILLPIDS="$KILLPIDS $SLURPPID"
-
-echo "Waiting 15 seconds for slurpd to send changes..."
-sleep 15
-
-if test ! $BACKLDAP = "ldapno" ; then
-       echo "Try updating the slave slapd..."
-       $LDAPMODIFY -v -D "$MANAGERDN" -h $LOCALHOST -p $PORT2 -w $PASSWD > \
-               $TESTOUT 2>&1 << EOMODS
-dn: cn=James A Jones 1, ou=Alumni Association, ou=People, dc=example, dc=com
-changetype: modify
-add: description
-description: This write must fail because directed to a shadow context,
-description: unless the chain overlay is configured appropriately ;)
-
-EOMODS
-
-       RC=$?
-       if test $RC != 0 ; then
-               echo "ldapmodify failed ($RC)!"
-               test $KILLSERVERS != no && kill -HUP $KILLPIDS
-               exit $RC
-       fi
-
-       echo "Waiting 15 seconds for slurpd to send changes..."
-       sleep 15
-fi
-
-echo "Using ldapsearch to read all the entries from the master..."
-$LDAPSEARCH -S "" -b "$BASEDN" -h $LOCALHOST -p $PORT1 \
-       'objectclass=*' > $MASTEROUT 2>&1
-RC=$?
-
-if test $RC != 0 ; then
-       echo "ldapsearch failed ($RC)!"
-       test $KILLSERVERS != no && kill -HUP $KILLPIDS
-       exit $RC
-fi
-
-echo "Using ldapsearch to read all the entries from the slave..."
-$LDAPSEARCH -S "" -b "$BASEDN" -h $LOCALHOST -p $PORT2 \
-       'objectclass=*' > $SLAVEOUT 2>&1
-RC=$?
-
-if test $RC != 0 ; then
-       echo "ldapsearch failed ($RC)!"
-       test $KILLSERVERS != no && kill -HUP $KILLPIDS
-       exit $RC
-fi
-
-test $KILLSERVERS != no && kill -HUP $KILLPIDS
-
-echo "Filtering master results..."
-. $LDIFFILTER < $MASTEROUT > $MASTERFLT
-echo "Filtering slave results..."
-. $LDIFFILTER < $SLAVEOUT > $SLAVEFLT
-
-echo "Comparing retrieved entries from master and slave..."
-$CMP $MASTERFLT $SLAVEFLT > $CMPOUT
-
-if test $? != 0 ; then
-       echo "test failed - master and slave databases differ"
-       exit 1
-fi
-
-echo ">>>>> Test succeeded"
-
-test $KILLSERVERS != no && wait
-
-exit 0
index 202b295434cf95c43f784be39db5f9e3c9e81275..2e788df6e12240af267bf02aa5ddc19fe9eddd53 100755 (executable)
@@ -220,7 +220,7 @@ RC=$?
 
 # expect 10 (LDAP_REFERRAL)...
 if test $RC != 10 ; then
-       echo "ldapmodify should have failed ($RC)!"
+       echo "ldapmodify should have returned referral ($RC)!"
        test $KILLSERVERS != no && kill -HUP $KILLPIDS
        exit $RC
 fi
index 50cd004a1c660562342809d415b4c8721dd1addc..4f6fb0a0ff42f9cfb70fbf6bccae66f3a9f00d4e 100755 (executable)
@@ -240,6 +240,17 @@ if test $RC != 0 ; then
        exit $RC
 fi
 
+echo "Using ldappasswd to change some passwords..."
+$LDAPPASSWD -D "$MANAGERDN" -h $LOCALHOST -p $PORT1 -w $PASSWD \
+       'cn=Bjorn Jensen,ou=Information Technology Division,ou=People,dc=example,dc=com' \
+       > $TESTOUT 2>&1
+RC=$?
+if test $RC != 0 ; then
+       echo "ldapmodify failed ($RC)!"
+       test $KILLSERVERS != no && kill -HUP $KILLPIDS
+       exit $RC
+fi
+
 echo "Waiting 15 seconds for syncrepl to receive changes..."
 sleep 15
 
@@ -299,6 +310,18 @@ EOMODS
                exit $RC
        fi
 
+       # ITS#4964
+       echo "Trying to change some passwords on the consumer..."
+       $LDAPPASSWD -D "$MANAGERDN" -h $LOCALHOST -p $PORT4 -w $PASSWD \
+               'cn=Barbara Jensen,ou=Information Technology Division,ou=People,dc=example,dc=com' \
+               > $TESTOUT 2>&1
+       RC=$?
+       if test $RC != 0 ; then
+               echo "ldapmodify failed ($RC)!"
+               test $KILLSERVERS != no && kill -HUP $KILLPIDS
+               exit $RC
+       fi
+
        echo "Waiting 15 seconds for syncrepl to receive changes..."
        sleep 15
 fi
index a5dbb2f418658d506ca6943f3d24da4e3aad48f4..8a898b99fb4a70d3c35738adb42c268c709de974 100755 (executable)
 echo "running defines.sh"
 . $SRCDIR/scripts/defines.sh
 
-if test "$AC_WITH_TLS" != "yes" ; then
-       echo "test disabled, requires --with-tls"
-       exit 0
-fi
-
 mkdir -p $TESTDIR $DBDIR1
 
 echo "Running slapadd to build slapd database..."
@@ -309,12 +304,7 @@ fi
 
 test $KILLSERVERS != no && kill -HUP $KILLPIDS
 
-if test "$WITHTLS" = no ; then 
-       echo "Certificate matching not suported without TLS"
-       LDIF=$CERTIFICATEOUT
-else
-       LDIF=$CERTIFICATETLS
-fi 
+LDIF=$CERTIFICATETLS
 
 echo "Filtering ldapsearch results..."
 . $LDIFFILTER < $SEARCHOUT > $SEARCHFLT
index 66050191b924ae81a0a4b46b62000f46a7b2c994..3b16efa140932976e6df1ff8f742a767b060bfd6 100755 (executable)
@@ -186,6 +186,81 @@ if test $RC != 0 ; then
        exit $RC
 fi
 
+if test $BACKEND = "hdb" ; then
+       $LDAPMODIFY -v -D "$REFINTDN" -h $LOCALHOST -p $PORT1 -w $PASSWD > \
+               $TESTOUT 2>&1 << EDEL
+version: 1
+dn: cn=group,o=refint
+changetype: add
+objectClass: groupOfNames
+cn: group
+member: uid=bill,ou=users,o=refint
+member: uid=bob,ou=users,o=refint
+member: uid=dave,ou=users,o=refint
+member: uid=jorge,ou=users,o=refint
+member: uid=theman,ou=users,o=refint
+member: uid=richard,ou=users,o=refint
+EDEL
+
+       RC=$?
+       if test $RC != 0 ; then
+               echo "ldapmodify failed ($RC)!"
+               test $KILLSERVERS != no && kill -HUP $KILLPIDS
+               exit $RC
+       fi
+
+       sleep 1;
+
+       $LDAPSEARCH -S "" -b "o=refint" -h $LOCALHOST -p $PORT1 \
+               manager member secretary > $SEARCHOUT 2>&1
+       RC=$?
+       if test $RC != 0 ; then
+               echo "ldapsearch failed ($RC)!"
+               test $KILLSERVERS != no && kill -HUP $KILLPIDS
+               exit $RC
+       fi
+
+       $EGREP_CMD "(manager|member|secretary):" $SEARCHOUT \
+               | sed "s/ou=users/ou=people/g" | \
+               sort > $TESTOUT 2>&1
+
+       echo "testing subtree rename"
+       $LDAPMODRDN -D "$REFINTDN" -r -h $LOCALHOST -p $PORT1 -w $PASSWD > \
+               /dev/null 2>&1 'ou=users,o=refint' 'ou=people'
+       RC=$?
+       if test $RC != 0 ; then
+               echo "ldapmodrdn failed ($RC)!"
+               test $KILLSERVERS != no && kill -HUP $KILLPIDS
+               exit $RC
+       fi
+
+       sleep 1;
+
+       echo "Using ldapsearch to check dependents new rdn..."
+
+       $LDAPSEARCH -S "" -b "o=refint" -h $LOCALHOST -p $PORT1 \
+               manager member secretary > $SEARCHOUT 2>&1
+
+       RC=$?
+       if test $RC != 0 ; then
+               echo "ldapsearch failed ($RC)!"
+               test $KILLSERVERS != no && kill -HUP $KILLPIDS
+               exit $RC
+       fi
+
+       $EGREP_CMD "(manager|member|secretary):" $SEARCHOUT \
+               | sort > $SEARCHFLT 2>&1
+
+       echo "Comparing ldapsearch results against original..."
+       $CMP $TESTOUT $SEARCHFLT > $CMPOUT
+
+       if test $? != 0 ; then
+               echo "comparison failed - subtree rename operations did not complete correctly"
+               test $KILLSERVERS != no && kill -HUP $KILLPIDS
+               exit 1
+       fi
+fi
+
 test $KILLSERVERS != no && kill -HUP $KILLPIDS
 
 echo ">>>>> Test succeeded"
index 3e17bddd2546a41c85e96ff5d1e0290d6d76eeb8..4d0b0095b9c9634247b4f186c566066b1591273a 100755 (executable)
 echo "running defines.sh"
 . $SRCDIR/scripts/defines.sh
 
-if test $UNIQUE = uniqueno; then 
+if test $UNIQUE = uniqueno; then
        echo "Attribute Uniqueness overlay not available, test skipped"
        exit 0
-fi 
+fi
 
 mkdir -p $TESTDIR $DBDIR1
 
+$SLAPPASSWD -g -n >$CONFIGPWF
+echo "rootpw `$SLAPPASSWD -T $CONFIGPWF`" >$TESTDIR/configpw.conf
+
 echo "Running slapadd to build slapd database..."
 . $CONFFILTER $BACKEND $MONITORDB < $UNIQUECONF > $CONF1
-$SLAPADD -f $CONF1 -l $LDIFUNIQUE
+$SLAPADD -f $CONF1 -l $LDIFUNIQUE -d7
 RC=$?
 if test $RC != 0 ; then
        echo "slapadd failed ($RC)!"
@@ -33,7 +36,8 @@ if test $RC != 0 ; then
 fi
 
 echo "Starting slapd on TCP/IP port $PORT1..."
-$SLAPD -f $CONF1 -h $URI1 -d $LVL $TIMING > $LOG1 2>&1 &
+mkdir testrun/confdir
+$SLAPD -f $CONF1 -F testrun/confdir -h $URI1 -d $LVL $TIMING > $LOG1 2>&1 &
 PID=$!
 if test $WAIT != 0 ; then
     echo PID $PID
@@ -62,9 +66,6 @@ if test $RC != 0 ; then
 fi
 
 echo "Adding a unique record..."
-
-#$LDAPADD -D "$UNIQUEDN" -h $LOCALHOST -p $PORT1 -w $PASSWD > \
-#      $TESTOUT 2>&1 << EOTUNIQ1
 $LDAPADD -D "$UNIQUEDN" -h $LOCALHOST -p $PORT1 -w $PASSWD \
        > /dev/null << EOTUNIQ1
 dn: uid=dave,ou=users,o=unique
@@ -82,7 +83,6 @@ employeeNumber: 69
 employeeType: contractor
 givenName: Dave
 EOTUNIQ1
-
 RC=$?
 if test $RC != 0 ; then
        echo "ldapadd failed ($RC)!"
@@ -90,11 +90,180 @@ if test $RC != 0 ; then
        exit $RC
 fi
 
-#echo ----------------------
-#$LDAPSEARCH -S "" -b "o=unique" -h $LOCALHOST -p $PORT1
+echo "Adding a non-unique record..."
+$LDAPADD -D "$UNIQUEDN" -h $LOCALHOST -p $PORT1 -w $PASSWD > \
+        $TESTOUT 2>&1 << EOTUNIQ2
+dn: uid=bill,ou=users,o=unique
+objectClass: inetOrgPerson
+uid: bill
+sn: johnson
+cn: bill
+businessCategory: rtest
+carLicense: ABC123
+departmentNumber: 42
+displayName: Bill
+employeeNumber: 5150
+employeeType: contractor
+givenName: Bill
+EOTUNIQ2
+RC=$?
+if test $RC != 19 ; then
+       echo "unique check failed ($RC)!"
+       test $KILLSERVERS != no && kill -HUP $KILLPIDS
+       exit -1
+fi
+
+echo Dynamically retrieving initial configuration...
+$LDAPSEARCH -S "" -b olcOverlay='{0}'unique,olcDatabase='{1}'$BACKEND,cn=config -D cn=config -y $CONFIGPWF -h $LOCALHOST -p $PORT1 -LLL | tr -d \\r >testrun/initial-config.ldif
+cat <<EOF >testrun/initial-reference.ldif
+dn: olcOverlay={0}unique,olcDatabase={1}$BACKEND,cn=config
+objectClass: olcOverlayConfig
+objectClass: olcUniqueConfig
+olcOverlay: {0}unique
+olcUniqueBase: o=unique
+olcUniqueAttribute: employeeNumber
+olcUniqueAttribute: displayName
+
+EOF
+diff testrun/initial-config.ldif testrun/initial-reference.ldif > /dev/null 2>&1
+RC=$?
+if test $RC != 0 ; then
+    echo "Initial configuration is not reported correctly."
+    test $KILLSERVERS != no && kill -HUP $KILLPIDS
+    exit -1
+fi
+
+echo Dynamically trying to add a URI with legacy attrs present...
+$LDAPMODIFY -D cn=config -h $LOCALHOST -p $PORT1 -y $CONFIGPWF \
+    > $TESTOUT 2>&1 <<EOF
+dn: olcOverlay={0}unique,olcDatabase={1}$BACKEND,cn=config
+changetype: modify
+add: olcUniqueURI
+olcUniqueURI: ldap:///?employeeNumber,displayName?sub
+EOF
+RC=$?
+if test $RC != 80 ; then
+       echo "legacy and unique_uri allowed together"
+       test $KILLSERVERS != no && kill -HUP $KILLPIDS
+       exit -1
+fi
+
+echo Dynamically trying to add legacy ignored attrs with legacy attrs present...
+$LDAPMODIFY -D cn=config -h $LOCALHOST -p $PORT1 -y $CONFIGPWF \
+    > $TESTOUT 2>&1 <<EOF
+dn: olcOverlay={0}unique,olcDatabase={1}$BACKEND,cn=config
+changetype: modify
+add: olcUniqueIgnore
+olcUniqueIgnore: objectClass
+EOF
+RC=$?
+if test $RC != 80 ; then
+       echo "legacy attrs and legacy ignore attrs allowed together"
+       test $KILLSERVERS != no && kill -HUP $KILLPIDS
+       exit -1
+fi
+
+echo Verifying initial configuration intact...
+$LDAPSEARCH -S "" -b olcOverlay='{0}'unique,olcDatabase='{1}'$BACKEND,cn=config -D cn=config -y $CONFIGPWF -h $LOCALHOST -p $PORT1 -LLL | tr -d \\r >testrun/initial-config-recheck.ldif
+diff testrun/initial-config-recheck.ldif testrun/initial-reference.ldif > /dev/null 2>&1
+RC=$?
+if test $RC != 0 ; then
+    echo "Initial configuration damaged by unsuccessful modifies."
+    test $KILLSERVERS != no && kill -HUP $KILLPIDS
+    exit -1
+fi
+
+echo Dynamically removing legacy base...
+$LDAPMODIFY -D cn=config -h $LOCALHOST -p $PORT1 -y $CONFIGPWF \
+    > $TESTOUT 2>&1 <<EOF
+dn: olcOverlay={0}unique,olcDatabase={1}$BACKEND,cn=config
+changetype: modify
+delete: olcUniqueBase
+EOF
+RC=$?
+if test $RC != 0 ; then
+       echo "base removal failed"
+       test $KILLSERVERS != no && kill -HUP $KILLPIDS
+       exit -1
+fi
+
+echo Verifying base removal...
+$LDAPSEARCH -S "" -b olcOverlay='{0}'unique,olcDatabase='{1}'$BACKEND,cn=config -D cn=config -y $CONFIGPWF -h $LOCALHOST -p $PORT1 -LLL | tr -d \\r >testrun/baseremoval-config.ldif
+cat >testrun/baseremoval-reference.ldif <<EOF
+dn: olcOverlay={0}unique,olcDatabase={1}$BACKEND,cn=config
+objectClass: olcOverlayConfig
+objectClass: olcUniqueConfig
+olcOverlay: {0}unique
+olcUniqueAttribute: employeeNumber
+olcUniqueAttribute: displayName
+
+EOF
+diff testrun/baseremoval-config.ldif testrun/baseremoval-reference.ldif > /dev/null 2>&1
+RC=$?
+if test $RC != 0 ; then
+    echo "Configuration damaged by base removal"
+    test $KILLSERVERS != no && kill -HUP $KILLPIDS
+    exit -1
+fi
 
 echo "Adding a non-unique record..."
+$LDAPADD -D "$UNIQUEDN" -h $LOCALHOST -p $PORT1 -w $PASSWD > \
+        $TESTOUT 2>&1 << EOTUNIQ2
+dn: uid=bill,ou=users,o=unique
+objectClass: inetOrgPerson
+uid: bill
+sn: johnson
+cn: bill
+businessCategory: rtest
+carLicense: ABC123
+departmentNumber: 42
+displayName: Bill
+employeeNumber: 5150
+employeeType: contractor
+givenName: Bill
+EOTUNIQ2
+RC=$?
+if test $RC != 19 ; then
+       echo "unique check failed ($RC)!"
+       test $KILLSERVERS != no && kill -HUP $KILLPIDS
+       exit -1
+fi
 
+echo Trying a legacy base outside of the backend...
+$LDAPMODIFY -D cn=config -h $LOCALHOST -p $PORT1 -y $CONFIGPWF \
+    > $TESTOUT 2>&1 <<EOF
+dn: olcOverlay={0}unique,olcDatabase={1}$BACKEND,cn=config
+changetype: modify
+add: olcUniqueBase
+olcUniqueBase: cn=config
+EOF
+RC=$?
+if test $RC != 80 ; then
+       echo "out of backend scope base allowed"
+       test $KILLSERVERS != no && kill -HUP $KILLPIDS
+       exit -1
+fi
+
+echo "Adding and removing attrs..."
+$LDAPMODIFY -D cn=config -h $LOCALHOST -p $PORT1 -y $CONFIGPWF \
+    > $TESTOUT 2>&1 <<EOF
+dn: olcOverlay={0}unique,olcDatabase={1}$BACKEND,cn=config
+changetype: modify
+add: olcUniqueAttribute
+olcUniqueAttribute: description
+olcUniqueAttribute: telephoneNumber
+-
+delete: olcUniqueAttribute
+olcUniqueAttribute: displayName
+EOF
+RC=$?
+if test $RC != 0 ; then
+       echo "Unable to remove an attribute"
+       test $KILLSERVERS != no && kill -HUP $KILLPIDS
+       exit -1
+fi
+
+echo "Verifying we removed the right attr..."
 $LDAPADD -D "$UNIQUEDN" -h $LOCALHOST -p $PORT1 -w $PASSWD > \
         $TESTOUT 2>&1 << EOTUNIQ2
 dn: uid=bill,ou=users,o=unique
@@ -110,7 +279,66 @@ employeeNumber: 5150
 employeeType: contractor
 givenName: Bill
 EOTUNIQ2
+RC=$?
+if test $RC != 19 ; then
+       echo "olcUniqueAttribtue single deletion hit the wrong value"
+       test $KILLSERVERS != no && kill -HUP $KILLPIDS
+       exit -1
+fi
 
+echo Removing legacy config and adding URIs...
+$LDAPMODIFY -D cn=config -h $LOCALHOST -p $PORT1 -y $CONFIGPWF \
+    > $TESTOUT 2>&1 <<EOF
+dn: olcOverlay={0}unique,olcDatabase={1}$BACKEND,cn=config
+changetype: modify
+delete: olcUniqueAttribute
+-
+add: olcUniqueURI
+olcUniqueURI: ldap:///?employeeNumber,displayName?sub
+olcUniqueURI: ldap:///?description?one
+EOF
+RC=$?
+if test $RC != 0 ; then
+       echo "Reconfiguration to URIs failed"
+       test $KILLSERVERS != no && kill -HUP $KILLPIDS
+       exit -1
+fi
+
+echo Dynamically retrieving second configuration...
+$LDAPSEARCH -S "" -b olcOverlay='{0}'unique,olcDatabase='{1}'$BACKEND,cn=config -D cn=config -y $CONFIGPWF -h $LOCALHOST -p $PORT1 -LLL | tr -d \\r >testrun/second-config.ldif
+cat >testrun/second-reference.ldif <<EOF
+dn: olcOverlay={0}unique,olcDatabase={1}$BACKEND,cn=config
+objectClass: olcOverlayConfig
+objectClass: olcUniqueConfig
+olcOverlay: {0}unique
+olcUniqueURI: ldap:///?employeeNumber,displayName?sub
+olcUniqueURI: ldap:///?description?one
+
+EOF
+diff testrun/second-config.ldif testrun/second-reference.ldif > /dev/null 2>&1
+RC=$?
+if test $RC != 0 ; then
+    echo "Second configuration is not reported correctly."
+    test $KILLSERVERS != no && kill -HUP $KILLPIDS
+    exit -1
+fi
+
+echo "Adding a non-unique record..."
+$LDAPADD -D "$UNIQUEDN" -h $LOCALHOST -p $PORT1 -w $PASSWD > \
+        $TESTOUT 2>&1 << EOTUNIQ2
+dn: uid=bill,ou=users,o=unique
+objectClass: inetOrgPerson
+uid: bill
+sn: johnson
+cn: bill
+businessCategory: rtest
+carLicense: ABC123
+departmentNumber: 42
+displayName: Bill
+employeeNumber: 5150
+employeeType: contractor
+givenName: Bill
+EOTUNIQ2
 RC=$?
 if test $RC != 19 ; then
        echo "unique check failed ($RC)!"
@@ -118,11 +346,222 @@ if test $RC != 19 ; then
        exit -1
 fi
 
+echo Dynamically trying to add legacy base
+$LDAPMODIFY -D cn=config -h $LOCALHOST -p $PORT1 -y $CONFIGPWF \
+    > $TESTOUT 2>&1 <<EOF
+dn: olcOverlay={0}unique,olcDatabase={1}$BACKEND,cn=config
+changetype: modify
+add: olcUniqueBase
+olcUniqueBase: o=unique
+EOF
+RC=$?
+if test $RC != 80 ; then
+       echo "legacy base allowed with URIs"
+       test $KILLSERVERS != no && kill -HUP $KILLPIDS
+       exit -1
+fi
+
+echo Dynamically trying to add legacy attrs
+$LDAPMODIFY -D cn=config -h $LOCALHOST -p $PORT1 -y $CONFIGPWF \
+    > $TESTOUT 2>&1 <<EOF
+dn: olcOverlay={0}unique,olcDatabase={1}$BACKEND,cn=config
+changetype: modify
+add: olcUniqueAttribute
+olcUniqueAttribute: description
+EOF
+RC=$?
+if test $RC != 80 ; then
+       echo "legacy attributes allowed with URIs"
+       test $KILLSERVERS != no && kill -HUP $KILLPIDS
+       exit -1
+fi
+
+echo Dynamically trying to add legacy strictness
+$LDAPMODIFY -D cn=config -h $LOCALHOST -p $PORT1 -y $CONFIGPWF \
+    > $TESTOUT 2>&1 <<EOF
+dn: olcOverlay={0}unique,olcDatabase={1}$BACKEND,cn=config
+changetype: modify
+add: olcUniqueStrict
+olcUniqueStrict: TRUE
+EOF
+RC=$?
+if test $RC != 80 ; then
+       echo "legacy strictness allowed with URIs"
+       test $KILLSERVERS != no && kill -HUP $KILLPIDS
+       exit -1
+fi
+
+#echo ----------------------
+echo Dynamically trying a bad filter...
+$LDAPMODIFY -D cn=config -h $LOCALHOST -p $PORT1 -y $CONFIGPWF \
+    > $TESTOUT 2>&1 <<EOF
+dn: olcOverlay={0}unique,olcDatabase={1}$BACKEND,cn=config
+changetype: modify
+replace: olcUniqueURI
+olcUniqueURI: ldap:///?sn?sub?((cn=e*))
+EOF
+RC=$?
+if test $RC != 80 ; then
+       echo "bad filter allowed"
+       test $KILLSERVERS != no && kill -HUP $KILLPIDS
+       exit -1
+fi
+
+echo Verifying second configuration intact...
+$LDAPSEARCH -S "" -b olcOverlay='{0}'unique,olcDatabase='{1}'$BACKEND,cn=config -D cn=config -y $CONFIGPWF -h $LOCALHOST -p $PORT1 -LLL | tr -d \\r >testrun/second-config-recheck.ldif
+diff testrun/second-config-recheck.ldif testrun/second-reference.ldif > /dev/null 2>&1
+RC=$?
+if test $RC != 0 ; then
+    echo "Second configuration damaged by rejected modifies."
+    test $KILLSERVERS != no && kill -HUP $KILLPIDS
+    exit -1
+fi
+
+#echo ----------------------
+echo Dynamically reconfiguring to use different URIs...
+$LDAPMODIFY -D cn=config -h $LOCALHOST -p $PORT1 -y $CONFIGPWF \
+    > $TESTOUT 2>&1 <<EOF
+dn: olcOverlay={0}unique,olcDatabase={1}$BACKEND,cn=config
+changetype: modify
+add: olcUniqueURI
+olcUniqueURI: ldap:///?sn?sub?(cn=e*)
+-
+delete: olcUniqueURI
+olcUniqueURI: ldap:///?description?one
+EOF
+RC=$?
+if test $RC != 0 ; then
+       echo "unable to reconfigure"
+       test $KILLSERVERS != no && kill -HUP $KILLPIDS
+       exit -1
+fi
+
+echo Dynamically retrieving third configuration...
+$LDAPSEARCH -S "" -b olcOverlay='{0}'unique,olcDatabase='{1}'$BACKEND,cn=config -D cn=config -y $CONFIGPWF -h $LOCALHOST -p $PORT1 -LLL | tr -d \\r >testrun/third-config.ldif
+cat >testrun/third-reference.ldif <<EOF
+dn: olcOverlay={0}unique,olcDatabase={1}$BACKEND,cn=config
+objectClass: olcOverlayConfig
+objectClass: olcUniqueConfig
+olcOverlay: {0}unique
+olcUniqueURI: ldap:///?employeeNumber,displayName?sub
+olcUniqueURI: ldap:///?sn?sub?(cn=e*)
+
+EOF
+diff testrun/third-config.ldif testrun/third-reference.ldif > /dev/null 2>&1
+RC=$?
+if test $RC != 0 ; then
+    echo "Third configuration is not reported correctly."
+    test $KILLSERVERS != no && kill -HUP $KILLPIDS
+    exit -1
+fi
+
+echo "Adding a record unique in both domains if filtered..."
+
+$LDAPADD -D "$UNIQUEDN" -h $LOCALHOST -p $PORT1 -w $PASSWD > \
+        $TESTOUT 2>&1 << EOF
+dn: uid=edgar,ou=users,o=unique
+objectClass: inetOrgPerson
+uid: edgar
+sn: johnson
+cn: edgar
+EOF
+
+RC=$?
+if test $RC != 0 ; then
+       echo "unique check failed ($RC)!"
+       test $KILLSERVERS != no && kill -HUP $KILLPIDS
+       exit -1
+fi
+
+echo "Adding a record unique in one domain, non-unique in the filtered domain..."
+
+$LDAPADD -D "$UNIQUEDN" -h $LOCALHOST -p $PORT1 -w $PASSWD > \
+        $TESTOUT 2>&1 << EOF
+dn: uid=elvis,ou=users,o=unique
+objectClass: inetOrgPerson
+uid: elvis
+sn: johnson
+cn: elvis
+EOF
+
+RC=$?
+if test $RC != 19 ; then
+       echo "unique check failed ($RC)!"
+       test $KILLSERVERS != no && kill -HUP $KILLPIDS
+       exit -1
+fi
 
 #echo ----------------------
-#$LDAPSEARCH -S "" -b "o=unique" -h $LOCALHOST -p $PORT1
+echo Dynamically reconfiguring to use attribute-ignore URIs...
+$LDAPMODIFY -D cn=config -h $LOCALHOST -p $PORT1 -y $CONFIGPWF \
+    > $TESTOUT 2>&1 <<EOF
+dn: olcOverlay={0}unique,olcDatabase={1}$BACKEND,cn=config
+changetype: modify
+replace: olcUniqueURI
+olcUniqueURI: ignore ldap:///?objectClass,uid,cn,sn?sub
+EOF
+RC=$?
+if test $RC != 0 ; then
+       echo "unable to reconfigure"
+       test $KILLSERVERS != no && kill -HUP $KILLPIDS
+       exit -1
+fi
 
+echo Dynamically retrieving fourth configuration...
+$LDAPSEARCH -S "" -b olcOverlay='{0}'unique,olcDatabase='{1}'$BACKEND,cn=config -D cn=config -y $CONFIGPWF -h $LOCALHOST -p $PORT1 -LLL | tr -d \\r >testrun/fourth-config.ldif
+cat >testrun/fourth-reference.ldif <<EOF
+dn: olcOverlay={0}unique,olcDatabase={1}$BACKEND,cn=config
+objectClass: olcOverlayConfig
+objectClass: olcUniqueConfig
+olcOverlay: {0}unique
+olcUniqueURI: ignore ldap:///?objectClass,uid,cn,sn?sub
 
+EOF
+diff testrun/fourth-config.ldif testrun/fourth-reference.ldif > /dev/null 2>&1
+RC=$?
+if test $RC != 0 ; then
+    echo "Fourth configuration is not reported correctly."
+    test $KILLSERVERS != no && kill -HUP $KILLPIDS
+    exit -1
+fi
+
+echo "Adding a record unique in the ignore-domain..."
+
+$LDAPADD -D "$UNIQUEDN" -h $LOCALHOST -p $PORT1 -w $PASSWD > \
+        $TESTOUT 2>&1 << EOF
+dn: uid=elvis,ou=users,o=unique
+objectClass: inetOrgPerson
+uid: elvis
+sn: johnson
+cn: elvis
+description: left the building
+EOF
+
+RC=$?
+if test $RC != 0 ; then
+       echo "unique check failed ($RC)!"
+       test $KILLSERVERS != no && kill -HUP $KILLPIDS
+       exit -1
+fi
+
+echo "Adding a record non-unique in the ignore-domain..."
+
+$LDAPADD -D "$UNIQUEDN" -h $LOCALHOST -p $PORT1 -w $PASSWD > \
+        $TESTOUT 2>&1 << EOF
+dn: uid=harry,ou=users,o=unique
+objectClass: inetOrgPerson
+uid: harry
+sn: johnson
+cn: harry
+description: left the building
+EOF
+
+RC=$?
+if test $RC != 19 ; then
+       echo "unique check failed ($RC)!"
+       test $KILLSERVERS != no && kill -HUP $KILLPIDS
+       exit -1
+fi
 
 test $KILLSERVERS != no && kill -HUP $KILLPIDS
 
index d657b57c39aba4d3636cf430bed42af29f9dc3c9..6cf4e32ad9055339171b4e6e311975c37585d737 100755 (executable)
@@ -33,6 +33,15 @@ fi
 # configure backside
 mkdir -p $TESTDIR $DBDIR1
 
+$SLAPPASSWD -g -n >$CONFIGPWF
+echo "rootpw `$SLAPPASSWD -T $CONFIGPWF`" >$TESTDIR/configpw.conf
+
+if test $MONITORDB != no ; then
+       DBIX=2
+else
+       DBIX=1
+fi
+
 . $CONFFILTER $BACKEND $MONITORDB < $TRANSLUCENTREMOTECONF > $CONF1
 echo "Running slapadd to build remote slapd database..."
 $SLAPADD -f $CONF1 -l $LDIFTRANSLUCENTCONFIG
@@ -199,7 +208,7 @@ fi
 echo "Dynamically configuring local slapd without translucent_no_glue..."
 
 $LDAPMODIFY -D cn=config -H $URI2 -y $CONFIGPWF <<EOF
-dn: olcOverlay={0}translucent,olcDatabase={2}$BACKEND,cn=config
+dn: olcOverlay={0}translucent,olcDatabase={$DBIX}$BACKEND,cn=config
 changetype: modify
 replace: olcTranslucentNoGlue
 olcTranslucentNoGlue: FALSE
@@ -618,7 +627,7 @@ fi
 echo "Dynamically configuring local slapd with translucent_no_glue and translucent_strict..."
 
 $LDAPMODIFY -D cn=config -H $URI2 -y $CONFIGPWF <<EOF
-dn: olcOverlay={0}translucent,olcDatabase={2}$BACKEND,cn=config
+dn: olcOverlay={0}translucent,olcDatabase={$DBIX}$BACKEND,cn=config
 changetype: modify
 replace: olcTranslucentNoGlue
 olcTranslucentNoGlue: TRUE
index 895a9d95074273243daedf80f243ea990c91c499..3289e3336c98606073fabfeea79ea98336e89c07 100755 (executable)
@@ -23,6 +23,9 @@ fi
 
 mkdir -p $TESTDIR $DBDIR1
 
+$SLAPPASSWD -g -n >$CONFIGPWF
+echo "rootpw `$SLAPPASSWD -T $CONFIGPWF`" >$TESTDIR/configpw.conf
+
 echo "Running slapadd to build slapd database..."
 . $CONFFILTER $BACKEND $MONITORDB < $VALSORTCONF > $CONF1
 $SLAPADD -f $CONF1 -l $LDIFVALSORT
index 253d764067b29b7db0a7397da3752e88ebdeb2f1..6138707b7e8200aedf9ebc3b3071ca7801f29312 100755 (executable)
@@ -339,9 +339,9 @@ fi
 test $KILLSERVERS != no && kill -HUP $KILLPIDS
 
 echo "Filtering producer results..."
-. $LDIFFILTER < $MASTEROUT | grep -iv ^auditcontext: > $MASTERFLT
+. $LDIFFILTER < $MASTEROUT | grep -iv "^auditcontext:" > $MASTERFLT
 echo "Filtering consumer results..."
-. $LDIFFILTER < $SLAVEOUT | grep -iv ^auditcontext: > $SLAVEFLT
+. $LDIFFILTER < $SLAVEOUT | grep -iv "^auditcontext:" > $SLAVEFLT
 
 echo "Comparing retrieved entries from producer and consumer..."
 $CMP $MASTERFLT $SLAVEFLT > $CMPOUT
index ef3e94c8838fd38cd0f051878a2f71b3fb0d6ffa..02032be291368a4eb9785d924fa2ab7ee913967c 100755 (executable)
@@ -22,6 +22,9 @@ fi
 
 mkdir -p $TESTDIR $DBDIR1
 
+$SLAPPASSWD -g -n >$CONFIGPWF
+echo "rootpw `$SLAPPASSWD -T $CONFIGPWF`" >$TESTDIR/configpw.conf
+
 echo "Running slapadd to build slapd database..."
 . $CONFFILTER $BACKEND $MONITORDB < $MCONF > $ADDCONF
 $SLAPADD -f $ADDCONF -l $LDIFORDERED
@@ -32,15 +35,6 @@ if test $RC != 0 ; then
 fi
 
 . $CONFFILTER $BACKEND $MONITORDB < $DYNLISTCONF > $CONF1
-echo "dynlist-attrset  groupOfURLs memberURL" >> $CONF1
-
-echo "Running slapindex to index slapd database..."
-$SLAPINDEX -f $CONF1
-RC=$?
-if test $RC != 0 ; then
-       echo "warning: slapindex failed ($RC)"
-       echo "  assuming no indexing support"
-fi
 
 echo "Starting slapd on TCP/IP port $PORT1..."
 $SLAPD -f $CONF1 -h $URI1 -d $LVL $TIMING > $LOG1 2>&1 &
@@ -250,45 +244,21 @@ case $RC in
 esac
 echo "" >> $SEARCHOUT
 
-echo "Stopping slapd..."
-kill -HUP $KILLPIDS
-wait $KILLPIDS
-
 echo "Reconfiguring slapd..."
-. $CONFFILTER $BACKEND $MONITORDB < $DYNLISTCONF > $CONF1
-echo "dynlist-attrset  groupOfURLs memberURL member" >> $CONF1
+$LDAPMODIFY -x -D cn=config -h $LOCALHOST -p $PORT1 -y $CONFIGPWF > \
+       $TESTOUT 2>&1 << EOMODS
+version: 1
+dn: olcOverlay={0}dynlist,olcDatabase={2}$BACKEND,cn=config
+changetype: modify
+delete: olcDLattrSet
+olcDLattrSet: {0}
+-
+add: olcDLattrSet
+olcDLattrSet: groupOfURLs memberURL member
+EOMODS
 
 echo "==========================================================" >> $LOG1
 
-echo "Starting slapd on TCP/IP port $PORT1..."
-$SLAPD -f $CONF1 -h $URI1 -d $LVL $TIMING >> $LOG1 2>&1 &
-PID=$!
-if test $WAIT != 0 ; then
-    echo PID $PID
-    read foo
-fi
-KILLPIDS="$PID"
-
-sleep 1
-
-echo "Testing slapd searching..."
-for i in 0 1 2 3 4 5; do
-       $LDAPSEARCH -s base -b "$MONITOR" -h $LOCALHOST -p $PORT1 \
-               '(objectclass=*)' > /dev/null 2>&1
-       RC=$?
-       if test $RC = 0 ; then
-               break
-       fi
-       echo "Waiting 5 seconds for slapd to start..."
-       sleep 5
-done
-
-if test $RC != 0 ; then
-       echo "ldapsearch failed ($RC)!"
-       test $KILLSERVERS != no && kill -HUP $KILLPIDS
-       exit $RC
-fi
-
 echo "Adding a dynamic list..."
 $LDAPADD -v -D "$MANAGERDN" -h $LOCALHOST -p $PORT1 -w $PASSWD \
        > $TESTOUT 2>&1 << EOMODS
@@ -431,6 +401,56 @@ case $RC in
 esac
 echo "" >> $SEARCHOUT
 
+echo "==========================================================" >> $LOG1
+
+echo "Testing dgIdentity..."
+
+# Set ACL, require authentication to get list contents
+$LDAPMODIFY -x -D cn=config -h $LOCALHOST -p $PORT1 -y $CONFIGPWF > \
+       $TESTOUT 2>&1 << EOMODS
+version: 1
+dn: olcDatabase={2}$BACKEND,cn=config
+changetype: modify
+add: olcAccess
+olcAccess: to dn.base="cn=Dynamic List of Members,$LISTDN" by * read
+olcAccess: to * by users read by * search
+EOMODS
+
+echo "Testing list search without dgIdentity..."
+echo "# Testing list search without dgIdentity..." >> $SEARCHOUT
+$LDAPSEARCH -S "" -b "$LISTDN" -h $LOCALHOST -p $PORT1 \
+       '(cn=Dynamic List of Members)' '*' \
+       >> $SEARCHOUT 2>&1
+RC=$?
+if test $RC != 0 ; then
+       echo "ldapsearch failed ($RC)!"
+       test $KILLSERVERS != no && kill -HUP $KILLPIDS
+       exit $RC
+fi
+
+$LDAPMODIFY -v -D "$MANAGERDN" -h $LOCALHOST -p $PORT1 -w $PASSWD \
+       > $TESTOUT 2>&1 << EOMODS
+dn: cn=Dynamic List of Members,$LISTDN
+changetype: modify
+add: objectClass
+objectClass: dgIdentityAux
+-
+add: dgIdentity
+dgIdentity: $CMPDN
+EOMODS
+
+echo "Testing list search with dgIdentity..."
+echo "# Testing list search with dgIdentity..." >> $SEARCHOUT
+$LDAPSEARCH -S "" -b "$LISTDN" -h $LOCALHOST -p $PORT1 \
+       '(cn=Dynamic List of Members)' '*' \
+       >> $SEARCHOUT 2>&1
+RC=$?
+if test $RC != 0 ; then
+       echo "ldapsearch failed ($RC)!"
+       test $KILLSERVERS != no && kill -HUP $KILLPIDS
+       exit $RC
+fi
+
 test $KILLSERVERS != no && kill -HUP $KILLPIDS
 
 LDIF=$DYNLISTOUT
index 40e7e4bc80af29fcc3e8893f39913fdb8abab507..87727fe2ba46400a66b4be4d307a074abc0e891f 100755 (executable)
@@ -141,7 +141,7 @@ for i in 0 1 2 3 4 5; do
        $LDAPSEARCH -s base -b "$MONITOR" -h $LOCALHOST -p $PORT3 \
                '(objectClass=*)' > /dev/null 2>&1
        RC=$?
-       if test $RC = 0 -o $RC = 53 ; then
+       if test $RC = 0 || test $RC = 53 ; then
                break
        fi
        echo "Waiting 5 seconds for slapd to start..."
index 80406de47f7b70bb0bc232bd75512c868689fbc4..759fcc58dafcb438cbe3c11b482b18a93f9337c3 100755 (executable)
@@ -27,11 +27,11 @@ DBPRO=$PRODIR/db
 DBCON=$CONDIR/db
 CFPRO=$PRODIR/slapd.d
 CFCON=$CONDIR/slapd.d
-LOG1=slapd.1.log
-LOG2=slapd.2.log
 
 mkdir -p $TESTDIR $PRODIR $CONDIR $DBPRO $DBCON $CFPRO $CFCON
 
+$SLAPPASSWD -g -n >$CONFIGPWF
+
 #
 # Test replication of dynamic config:
 # - start producer
@@ -43,16 +43,17 @@ mkdir -p $TESTDIR $PRODIR $CONDIR $DBPRO $DBCON $CFPRO $CFCON
 #
 
 echo "Starting producer slapd on TCP/IP port $PORT1..."
-$SLAPADD -F $CFPRO -n 0 -l $DYNAMICCONF
+. $CONFFILTER $BACKEND $MONITORDB < $DYNAMICCONF > $CONFLDIF
+$SLAPADD -F $CFPRO -n 0 -l $CONFLDIF
 cd $PRODIR
-$SLAPD -F ./slapd.d -h $URI1 -d $LVL $TIMING > ../$LOG1 2>&1 &
+$SLAPD -F ./slapd.d -h $URI1 -d $LVL $TIMING > $LOG1 2>&1 &
 PID=$!
 if test $WAIT != 0 ; then
     echo PID $PID
     read foo
 fi
 KILLPIDS="$PID"
-cd ../..
+cd $TESTWD
 
 sleep 1
 
@@ -90,7 +91,7 @@ EOF
                exit $RC
        fi
 fi
-CONFIGPW=`cat $CONFIGPWF`
+read CONFIGPW < $CONFIGPWF
 $LDAPMODIFY -D cn=config -H $URI1 -y $CONFIGPWF <<EOF >> $TESTOUT 2>&1
 dn: olcDatabase={0}config,cn=config
 changetype: modify
@@ -116,16 +117,16 @@ if test $RC != 0 ; then
 fi
 
 echo "Starting consumer slapd on TCP/IP port $PORT2..."
-$SLAPADD -F $CFCON -n 0 -l $DYNAMICCONF
+$SLAPADD -F $CFCON -n 0 -l $CONFLDIF
 cd $CONDIR
-$SLAPD -F ./slapd.d -h $URI2 -d $LVL $TIMING > ../$LOG2 2>&1 &
+$SLAPD -F ./slapd.d -h $URI2 -d $LVL $TIMING > $LOG2 2>&1 &
 SLAVEPID=$!
 if test $WAIT != 0 ; then
     echo SLAVEPID $SLAVEPID
     read foo
 fi
 KILLPIDS="$KILLPIDS $SLAVEPID"
-cd ../..
+cd $TESTWD
 
 sleep 1
 
index 1540244a25304a132be33a38324929c48b3569fc..3f75c4e5389d9722953d9f857c1cdd121786f559 100755 (executable)
@@ -27,11 +27,11 @@ DBPRO=$PRODIR/db
 DBCON=$CONDIR/db
 CFPRO=$PRODIR/slapd.d
 CFCON=$CONDIR/slapd.d
-LOG1=slapd.1.log
-LOG2=slapd.2.log
 
 mkdir -p $TESTDIR $PRODIR $CONDIR $DBPRO $DBCON $CFPRO $CFCON
 
+$SLAPPASSWD -g -n >$CONFIGPWF
+
 #
 # Test replication of dynamic config:
 # - start producer
@@ -52,7 +52,7 @@ olcServerID: 2
 dn: olcDatabase={0}config,cn=config
 objectClass: olcDatabaseConfig
 olcDatabase: {0}config
-olcRootPW:< file:configpw
+olcRootPW:< file://$CONFIGPWF
 EOF
 
 $SLAPADD -F $CFPRO -n 0 <<EOF
@@ -64,19 +64,19 @@ olcServerID: 1
 dn: olcDatabase={0}config,cn=config
 objectClass: olcDatabaseConfig
 olcDatabase: {0}config
-olcRootPW:< file:configpw
+olcRootPW:< file://$CONFIGPWF
 EOF
 
 echo "Starting producer slapd on TCP/IP port $PORT1..."
 cd $PRODIR
-$SLAPD -F ./slapd.d -h $URI1 -d $LVL $TIMING > ../$LOG1 2>&1 &
+$SLAPD -F slapd.d -h $URI1 -d $LVL $TIMING > $LOG1 2>&1 &
 PID=$!
 if test $WAIT != 0 ; then
     echo PID $PID
     read foo
 fi
 KILLPIDS="$PID"
-cd ../..
+cd $TESTWD
 
 sleep 1
 
@@ -121,7 +121,7 @@ fi
 # neither server will progress. The timeout will drop the syncrepl
 # attempt and allow the modifies to complete.
 #
-CONFIGPW=`cat $CONFIGPWF`
+read CONFIGPW < $CONFIGPWF
 $LDAPMODIFY -D cn=config -H $URI1 -y $CONFIGPWF <<EOF >> $TESTOUT 2>&1
 dn: cn=config
 changetype: modify
@@ -157,14 +157,14 @@ fi
 
 echo "Starting consumer slapd on TCP/IP port $PORT2..."
 cd $CONDIR
-$SLAPD -F ./slapd.d -h $URI2 -d $LVL $TIMING > ../$LOG2 2>&1 &
+$SLAPD -F ./slapd.d -h $URI2 -d $LVL $TIMING > $LOG2 2>&1 &
 SLAVEPID=$!
 if test $WAIT != 0 ; then
     echo SLAVEPID $SLAVEPID
     read foo
 fi
 KILLPIDS="$KILLPIDS $SLAVEPID"
-cd ../..
+cd $TESTWD
 
 sleep 1
 
@@ -379,15 +379,15 @@ test $KILLSERVERS != no && wait
 echo "Restarting servers..."
 echo "Starting producer slapd on TCP/IP port $PORT1..."
 cd $PRODIR
-echo "======================= RESTART =======================" >> ../$LOG1
-$SLAPD -F ./slapd.d -h $URI1 -d $LVL $TIMING >> ../$LOG1 2>&1 &
+echo "======================= RESTART =======================" >> $LOG1
+$SLAPD -F ./slapd.d -h $URI1 -d $LVL $TIMING >> $LOG1 2>&1 &
 PID=$!
 if test $WAIT != 0 ; then
     echo PID $PID
     read foo
 fi
 KILLPIDS="$PID"
-cd ../..
+cd $TESTWD
 echo "Using ldapsearch to check that producer slapd is running..."
 for i in 0 1 2 3 4 5; do
        $LDAPSEARCH -s base -b "" -H $URI1 \
@@ -408,15 +408,15 @@ fi
 #exit 0
 echo "Starting consumer slapd on TCP/IP port $PORT2..."
 cd $CONDIR
-echo "======================= RESTART =======================" >> ../$LOG2
-$SLAPD -F ./slapd.d -h $URI2 -d $LVL $TIMING >> ../$LOG2 2>&1 &
+echo "======================= RESTART =======================" >> $LOG2
+$SLAPD -F ./slapd.d -h $URI2 -d $LVL $TIMING >> $LOG2 2>&1 &
 SLAVEPID=$!
 if test $WAIT != 0 ; then
     echo SLAVEPID $SLAVEPID
     read foo
 fi
 KILLPIDS="$KILLPIDS $SLAVEPID"
-cd ../..
+cd $TESTWD
 
 sleep 1
 
index 825a1159093cefcddb087a22df7597cb9de9da73..273406b7d12ab240faccd89123e396ae9615659e 100755 (executable)
@@ -18,6 +18,9 @@ echo "running defines.sh"
 
 mkdir -p $TESTDIR $DBDIR1
 
+$SLAPPASSWD -g -n >$CONFIGPWF
+echo "rootpw `$SLAPPASSWD -T $CONFIGPWF`" >$TESTDIR/configpw.conf
+
 echo "Running slapadd to build slapd database..."
 . $CONFFILTER $BACKEND $MONITORDB < $UNDOCONF > $CONF1
 $SLAPADD -f $CONF1 <<EOF
@@ -33,8 +36,8 @@ if test $RC != 0 ; then
 fi
 
 echo "Starting slapd on TCP/IP port $PORT1..."
-mkdir testrun/confdir
-$SLAPD -f $CONF1 -F testrun/confdir -h $URI1 -d $LVL $TIMING > $LOG1 2>&1 &
+mkdir $TESTDIR/confdir
+$SLAPD -f $CONF1 -F $TESTDIR/confdir -h $URI1 -d $LVL $TIMING > $LOG1 2>&1 &
 PID=$!
 if test $WAIT != 0 ; then
     echo PID $PID
@@ -91,7 +94,7 @@ if test $RC != 80 ; then
 fi
 
 echo Surveying the damage
-$LDAPMODIFY -D cn=manager,o=undo -w secret -h $LOCALHOST -p $PORT1 <<EOF
+$LDAPMODIFY -D "cn=manager,o=undo" -w secret -h $LOCALHOST -p $PORT1 <<EOF
 dn: o=foo,o=undo
 changetype: add
 objectClass: organization