]> git.sur5r.net Git - openldap/commitdiff
Import latest from devel
authorKurt Zeilenga <kurt@openldap.org>
Sat, 29 Jul 2000 03:52:27 +0000 (03:52 +0000)
committerKurt Zeilenga <kurt@openldap.org>
Sat, 29 Jul 2000 03:52:27 +0000 (03:52 +0000)
194 files changed:
COPYRIGHT
INSTALL
LICENSE
README
clients/gopher/go500.c
clients/gopher/go500gw.c
clients/tools/ldapdelete.c
clients/tools/ldapmodify.c
clients/tools/ldapmodrdn.c
clients/tools/ldappasswd.c
clients/tools/ldapsearch.c
clients/ud/main.c
clients/ud/print.c
clients/ud/string_to_key.c
clients/ud/util.c
configure
configure.in
doc/drafts/README
doc/drafts/draft-ietf-ldapext-acl-model-xx.txt
doc/drafts/draft-ietf-ldapext-locate-xx.txt
doc/drafts/draft-ietf-ldapext-matchedval-xx.txt
doc/drafts/draft-ietf-ldapext-namedref-xx.txt [deleted file]
doc/drafts/draft-ietf-ldapext-refer-xx.txt [new file with mode: 0644]
doc/drafts/draft-ietf-ldup-subentry-xx.txt
doc/drafts/draft-ietf-ldup-urp-xx.txt
doc/drafts/draft-zeilenga-ldap-authpasswd-xx.txt [new file with mode: 0644]
doc/drafts/draft-zeilenga-ldap-grouping-xx.txt [new file with mode: 0644]
doc/drafts/draft-zeilenga-ldap-namedref-xx.txt [new file with mode: 0644]
doc/drafts/draft-zeilenga-ldap-passwd-exop-xx.txt [new file with mode: 0644]
doc/drafts/draft-zeilenga-ldapv3bis-opattrs-xx.txt [new file with mode: 0644]
doc/man/man1/ldapdelete.1
doc/man/man1/ldapmodify.1
doc/man/man1/ldapmodrdn.1
doc/man/man1/ldappasswd.1
doc/man/man1/ldapsearch.1
doc/man/man3/lber-decode.3
doc/man/man3/lber-encode.3
doc/man/man3/lber-memory.3 [new file with mode: 0644]
doc/man/man3/lber-types.3 [new file with mode: 0644]
doc/man/man3/ldap.3
doc/man/man3/ldap_abandon.3.links [new file with mode: 0644]
doc/man/man3/ldap_add.3.links
doc/man/man3/ldap_bind.3.links
doc/man/man3/ldap_charset.3 [deleted file]
doc/man/man3/ldap_charset.3.links [deleted file]
doc/man/man3/ldap_compare.3.links
doc/man/man3/ldap_delete.3.links
doc/man/man3/ldap_get_dn.3
doc/man/man3/ldap_get_dn.3.links
doc/man/man3/ldap_modify.3.links
doc/man/man3/ldap_search.3.links
doc/man/man5/ldap.conf.5
doc/man/man5/slapd.conf.5
doc/man/man8/slapcat.8
doc/man/man8/slapindex.8 [new file with mode: 0644]
doc/man/man8/slappasswd.8
doc/rfc/INDEX
doc/rfc/rfc2820.txt [new file with mode: 0644]
include/ac/alloca.h
include/ac/signal.h
include/ac/socket.h
include/ac/string.h
include/ldap.h
include/ldap_pvt.h
include/ldap_schema.h
include/lutil_ldap.h [new file with mode: 0644]
include/portable.h.in
libraries/liblber/decode.c
libraries/liblber/encode.c
libraries/liblber/io.c
libraries/liblber/lber-int.h
libraries/liblber/memory.c
libraries/liblber/options.c
libraries/liblber/sockbuf.c
libraries/libldap/Makefile.in
libraries/libldap/cache.c
libraries/libldap/charray.c
libraries/libldap/cldap.c
libraries/libldap/controls.c
libraries/libldap/cyrus.c [new file with mode: 0644]
libraries/libldap/dsparse.c
libraries/libldap/error.c
libraries/libldap/getdn.c
libraries/libldap/getentry.c
libraries/libldap/getfilter.c
libraries/libldap/init.c
libraries/libldap/kbind.c
libraries/libldap/ldap-int.h
libraries/libldap/ldap.conf
libraries/libldap/libldap.dsp
libraries/libldap/open.c
libraries/libldap/options.c
libraries/libldap/os-ip.c
libraries/libldap/os-local.c
libraries/libldap/references.c
libraries/libldap/request.c
libraries/libldap/sasl.c
libraries/libldap/schema.c
libraries/libldap/sortctrl.c
libraries/libldap/tls.c
libraries/libldap/tmplout.c
libraries/libldap/ufn.c
libraries/libldap/unbind.c
libraries/libldap/util-int.c
libraries/libldap/vlvctrl.c
libraries/libldap_r/Makefile.in
libraries/libldap_r/libldap_r.dsp
libraries/libldbm/ldbm.c
libraries/libldif/fetch.c
libraries/libldif/line64.c
libraries/liblutil/Makefile.in
libraries/liblutil/authpasswd.c
libraries/liblutil/entropy.c
libraries/liblutil/liblutil.dsp
libraries/liblutil/md5.c
libraries/liblutil/passwd.c
libraries/liblutil/sasl.c [new file with mode: 0644]
libraries/liblutil/sha1.c
libraries/liblutil/signal.c [new file with mode: 0644]
servers/slapd/Makefile.in
servers/slapd/acl.c
servers/slapd/aclparse.c
servers/slapd/add.c
servers/slapd/at.c
servers/slapd/back-dnssrv/init.c
servers/slapd/back-ldap/init.c
servers/slapd/back-ldbm/alias.c
servers/slapd/back-ldbm/dn2id.c
servers/slapd/back-ldbm/external.h
servers/slapd/back-ldbm/idl.c
servers/slapd/back-ldbm/index.c
servers/slapd/back-ldbm/init.c
servers/slapd/back-ldbm/nextid.c
servers/slapd/back-ldbm/proto-back-ldbm.h
servers/slapd/back-ldbm/sasl.c
servers/slapd/back-ldbm/tools.c
servers/slapd/back-passwd/init.c
servers/slapd/back-shell/init.c
servers/slapd/backend.c
servers/slapd/bind.c
servers/slapd/config.c
servers/slapd/connection.c
servers/slapd/daemon.c
servers/slapd/filterentry.c
servers/slapd/init.c
servers/slapd/kerberos.c
servers/slapd/main.c
servers/slapd/monitor.c
servers/slapd/mr.c
servers/slapd/oc.c
servers/slapd/phonetic.c
servers/slapd/proto-slap.h
servers/slapd/result.c
servers/slapd/root_dse.c
servers/slapd/sasl.c
servers/slapd/schema/core.schema
servers/slapd/schema/misc.schema
servers/slapd/schema_init.c
servers/slapd/schemaparse.c
servers/slapd/search.c
servers/slapd/sets.c
servers/slapd/slap.h
servers/slapd/syntax.c
servers/slapd/tools/Makefile.in
servers/slapd/tools/mimic.c
servers/slapd/tools/slapcommon.c
servers/slapd/tools/slapindex.c
servers/slapd/tools/slappasswd.c
servers/slapd/value.c
servers/slurpd/admin.c
servers/slurpd/config.c
servers/slurpd/fm.c
servers/slurpd/re.c
tests/data/slapd-acl.conf
tests/data/slapd-dnssrv.conf
tests/data/slapd-master.conf
tests/data/slapd-nis-master.conf
tests/data/slapd-pw.conf
tests/data/slapd-ref-slave.conf
tests/data/slapd-repl-master.conf
tests/data/slapd-repl-slave.conf
tests/data/slapd.conf [new file with mode: 0644]
tests/progs/slapd-addel.c
tests/scripts/defines.sh
tests/scripts/startup_nis_ldap_server.sh
tests/scripts/test001-slapadd
tests/scripts/test002-populate
tests/scripts/test003-search
tests/scripts/test004-modify
tests/scripts/test005-modrdn
tests/scripts/test006-acls
tests/scripts/test007-replication
tests/scripts/test008-concurrency
tests/scripts/test009-referral

index 53856a21bcb7a2bfdb2a391a2d549cac03da6d05..708f6d80ad827a02ed7ff1344abe00c5d6b40ec7 100644 (file)
--- a/COPYRIGHT
+++ b/COPYRIGHT
@@ -32,3 +32,6 @@ 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.
+
+---
+$OpenLDAP$
diff --git a/INSTALL b/INSTALL
index 6aafa69e411b6dcac0f8f521966101636862796f..ca3512e62b7edce10a97074f4d5a03605e1c7b5c 100644 (file)
--- a/INSTALL
+++ b/INSTALL
@@ -90,7 +90,7 @@ these steps:
  7. install the binaries and man pages.  You may need to be superuser to
     do this (depending on where you are installing things):
 
-       % su root -c make install
+       % su root -c 'make install'
 
     That's it!
 
@@ -107,10 +107,10 @@ these steps:
          ldaptemplates.conf   - display template definitions
 
        Server configuration files:
-         ldapd.conf           - LDAP - X.500 daemon
-         slapd.conf           - Standalone LDAP daemon
+         slapd.conf           - Standalone LDAP daemon configuration
+         schema/*.schema      - Schema Definitions
 
-    There are section 5 man pages for all of these files.
+    There are section 5 man pages for these configuration files.
 
 
 Building LDAP For More Than One Platform
@@ -138,8 +138,6 @@ Follow these steps for each different platform:
 
  4. Continue as above (starting at step 6).
 
-       Note: make depend in VPATH environment is not yet supported.
-
 
 CONFIGURE OPTIONS
 
@@ -224,4 +222,5 @@ HINTS
                ./configure
 
 
-End of OpenLDAP INSTALL file.
+---
+$OpenLDAP$
diff --git a/LICENSE b/LICENSE
index 123dfc37aeee60d5977a6d8b883fe1fbd9caea4e..f4fc4ae57dd8fd14fb1da36a0077541ccf7735e1 100644 (file)
--- a/LICENSE
+++ b/LICENSE
@@ -1,31 +1,32 @@
 The OpenLDAP Public License
-  Version 2.2.1, 1 March 2000
+  Version 2.3, 28 July 2000
 
 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 of source code must retain copyright statements
-and notices.  Redistributions must also contain a copy of this
-document.
+and notices.
 
-2. Redistributions in binary form must reproduce the above copyright
-notice, this list of conditions and the following disclaimer in
-the documentation and/or other materials provided with the
-distribution.
+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.
 
-3. The name "OpenLDAP" must not be used to endorse or promote
+3. Redistributions must contain a verbatim copy of this document.
+
+4. The name "OpenLDAP" must not be used to endorse or promote
 products derived from this Software without prior written permission
 of the OpenLDAP Foundation.
 
-4. Products derived from this Software may not be called "OpenLDAP"
+5. Products derived from this Software may not be called "OpenLDAP"
 nor may "OpenLDAP" appear in their names without prior written
 permission of the OpenLDAP Foundation.
 
-5. Due credit should be given to the OpenLDAP Project
+6. Due credit should be given to the OpenLDAP Project
 (http://www.openldap.org/).
 
-6. The OpenLDAP Foundation may revise this license from time to
+7. The OpenLDAP Foundation may revise this license from time to
 time.  Each revision is distinguished by a version number.  You
 may use the Software under terms of this license revision or under
 the terms of any subsequent revision of the license.
diff --git a/README b/README
index 50c603017ac47a2e380d862889eedfd22e7ec230..e7ce990aef947903ca69a4886a33361ad29433de 100644 (file)
--- a/README
+++ b/README
@@ -74,3 +74,6 @@ SUPPORT / FEEDBACK / PROBLEM REPORTS / DISCUSSIONS
        by sending mail to OpenLDAP-its@OpenLDAP.org.  Do not use
        this system for general or software equiries.  Please direct
        these to the appropriate mailing list.
+
+---
+$OpenLDAP$
index ca03ce0a98a9614739bc039449f15329ab71c4eb..2b7c4ed6752af712cff475b8d0cdf4caf5c51fd2 100644 (file)
@@ -139,11 +139,12 @@ main( int argc, char **argv )
 #ifdef GO500_HOSTNAME
        strcpy( myhost, GO500_HOSTNAME );
 #else
-       if ( myhost[0] == '\0' && gethostname( myhost, sizeof(myhost) )
+       if ( myhost[0] == '\0' && gethostname( myhost, sizeof(myhost)-1 )
            == -1 ) {
                perror( "gethostname" );
                exit( EXIT_FAILURE );
        }
+       myhost[sizeof(myhost)-1] = '\0';
 #endif
 
 #ifdef HAVE_SYSCONF
@@ -213,7 +214,7 @@ main( int argc, char **argv )
                        }
 
 #ifdef LDAP_PROCTITLE
-                       setproctitle( hp == NULL ? inet_ntoa( from.sin_addr ) :
+                       setproctitle( "%s", hp == NULL ? inet_ntoa( from.sin_addr ) :
                            hp->h_name );
 #endif
                }
@@ -344,7 +345,7 @@ wait4child( int sig )
                ;       /* NULL */
 #endif
 
-       (void) SIGNAL( SIGCHLD, wait4child );
+       (void) SIGNAL_REINSTALL ( SIGCHLD, wait4child );
 }
 
 static void
index dfda607001f42358689535db12433571c8e4991e..efe5054d811d97c2bcb67c7e32d0f6f0c11fe69b 100644 (file)
@@ -176,11 +176,12 @@ main (int  argc, char **argv )
 #ifdef GO500GW_HOSTNAME
        strcpy( myhost, GO500GW_HOSTNAME );
 #else
-       if ( myhost[0] == '\0' && gethostname( myhost, sizeof(myhost) )
+       if ( myhost[0] == '\0' && gethostname( myhost, sizeof(myhost)-1 )
            == -1 ) {
                perror( "gethostname" );
                exit( EXIT_FAILURE );
        }
+       myhost[sizeof(myhost)-1] = '\0';
 #endif
 
        /* detach if stderr is redirected or no debugging */
@@ -236,7 +237,7 @@ main (int  argc, char **argv )
                        }
 
 #ifdef LDAP_PROCTITLE
-                       setproctitle( hp == NULL ? inet_ntoa( from.sin_addr ) :
+                       setproctitle( "%s", hp == NULL ? inet_ntoa( from.sin_addr ) :
                            hp->h_name );
 #endif
                }
@@ -370,7 +371,7 @@ wait4child( int sig )
                ;       /* NULL */
 #endif
 
-       (void) SIGNAL( SIGCHLD, wait4child );
+       (void) SIGNAL_REINSTALL ( SIGCHLD, wait4child );
 }
 
 static void
index 200d9f2a21fc90033c61c781dcfc1c6b112d7381..9894aa428ecc7ae708b666e70a89755954560fd6 100644 (file)
 #include <ac/unistd.h>
 
 #include <ldap.h>
+#include "lutil_ldap.h"
+#include "ldap_defaults.h"
 
+static char    *prog;
 static char    *binddn = NULL;
-static struct berval passwd = { 0, NULL};
+static struct berval passwd = { 0, NULL };
 static char    *ldaphost = NULL;
 static int     ldapport = 0;
 static int     prune = 0;
 #ifdef HAVE_CYRUS_SASL
+static unsigned sasl_flags = LDAP_SASL_AUTOMATIC;
+static char    *sasl_mech = NULL;
+static char *sasl_realm = NULL;
 static char    *sasl_authc_id = NULL;
 static char    *sasl_authz_id = NULL;
-static char    *sasl_mech = NULL;
-static int     sasl_integrity = 0;
-static int     sasl_privacy = 0;
+static char    *sasl_secprops = NULL;
 #endif
 static int     use_tls = 0;
 static int     not, verbose, contoper;
@@ -50,30 +54,32 @@ usage( const char *s )
 "usage: %s [options] [dn]...\n"
 "      dn: list of DNs to delete. If not given, it will be readed from stdin\n"
 "          or from the file specified with \"-f file\".\n"
-"options:\n"
-"      -c\t\tcontinuous operation mode (do not stop on errors)\n"
-"      -C\t\tchase referrals\n"
-"      -d level\tset LDAP debugging level to `level'\n"
-"      -D binddn\tbind DN\n"
-"      -E\t\trequest SASL privacy (-EE to make it critical)\n"
-"      -f file\t\tdelete DNs listed in `file'\n"
-"      -h host\t\tLDAP server\n"
-"      -I\t\trequest SASL integrity checking (-II to make it\n"
-"              \tcritical)\n"
-"      -k\t\tuse Kerberos authentication\n"
-"      -K\t\tlike -k, but do only step 1 of the Kerberos bind\n"
-"      -M\t\tenable Manage DSA IT control (-MM to make it critical)\n"
-"      -n\t\tshow what would be done but don't actually delete\n"
-"      -p port\t\tport on LDAP server\n"
-"      -P version\tprocotol version (default: 3)\n"
-"      -r\t\tdelete recursively\n"
-"      -U user\t\tSASL authentication identity (username)\n"
-"      -v\t\trun in verbose mode (diagnostics to standard output)\n"
-"      -w passwd\tbind passwd (for simple authentication)\n"
-"      -W\t\tprompt for bind passwd\n"
-"      -X id\t\tSASL authorization identity (\"dn:<dn>\" or \"u:<user>\")\n"
-"      -Y mech\t\tSASL mechanism\n"
-"      -Z\t\tissue Start TLS request (-ZZ to require successful response)\n"
+"Delete Options:\n"
+"  -r         delete recursively\n"
+
+"Common options:\n"
+"  -d level   set LDAP debugging level to `level'\n"
+"  -D binddn  bind DN\n"
+"  -f file    read operations from `file'\n"
+"  -h host    LDAP server\n"
+"  -I         use SASL Interactive mode\n"
+"  -k         use Kerberos authentication\n"
+"  -K         like -k, but do only step 1 of the Kerberos bind\n"
+"  -M         enable Manage DSA IT control (-MM to make critical)\n"
+"  -n         show what would be done but don't actually search\n"
+"  -O props   SASL security properties\n"
+"  -p port    port on LDAP server\n"
+"  -P version procotol version (default: 3)\n"
+"  -Q         use SASL Quiet mode\n"
+"  -R realm   SASL realm\n"
+"  -U user    SASL authentication identity (username)\n"
+"  -v         run in verbose mode (diagnostics to standard output)\n"
+"  -w passwd  bind passwd (for simple authentication)\n"
+"  -W         prompt for bind passwd\n"
+"  -x         Simple authentication\n"
+"  -X id      SASL authorization identity (\"dn:<dn>\" or \"u:<user>\")\n"
+"  -Y mech    SASL mechanism\n"
+"  -Z         Start TLS request (-ZZ to require successful response)\n"
 ,              s );
 
        exit( EXIT_FAILURE );
@@ -89,190 +95,362 @@ main( int argc, char **argv )
 
     not = verbose = contoper = want_bindpw = debug = manageDSAit = referrals = 0;
     fp = NULL;
-    authmethod = LDAP_AUTH_SIMPLE;
+    authmethod = -1;
        version = -1;
 
-    while (( i = getopt( argc, argv, "cCD:d:Ef:h:IKMnP:p:rU:vWw:X:Y:Z" )) != EOF ) {
+    prog = (prog = strrchr(argv[0], *LDAP_DIRSEP)) == NULL ? argv[0] : ++prog;
+
+    while (( i = getopt( argc, argv, "cf:r" "Cd:D:h:IkKMnO:p:P:QRU:vw:WxX:Y:Z" )) != EOF ) {
        switch( i ) {
-       case 'k':       /* kerberos bind */
-#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND
-               authmethod = LDAP_AUTH_KRBV4;
-#else
-               fprintf( stderr, "%s was not compiled with Kerberos support\n", argv[0] );
-               return( EXIT_FAILURE );
-#endif
-           break;
-       case 'K':       /* kerberos bind, part one only */
-#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND
-               authmethod = LDAP_AUTH_KRBV41;
-#else
-               fprintf( stderr, "%s was not compiled with Kerberos support\n", argv[0] );
-               return( EXIT_FAILURE );
-#endif
-           break;
+       /* Delete Specific Options */
        case 'c':       /* continuous operation mode */
            ++contoper;
            break;
-       case 'C':
-               referrals++;
-               break;
-       case 'h':       /* ldap host */
-           ldaphost = strdup( optarg );
-           break;
-       case 'D':       /* bind DN */
-           binddn = strdup( optarg );
-           break;
-       case 'w':       /* password */
-           passwd.bv_val = strdup( optarg );
-               {
-                       char* p;
-
-                       for( p = optarg; *p == '\0'; p++ ) {
-                               *p = '*';
-                       }
-               }
-               passwd.bv_len = strlen( passwd.bv_val );
-           break;
        case 'f':       /* read DNs from a file */
+               if( fp != NULL ) {
+                       fprintf( stderr, "%s: -f previously specified\n" );
+                       return EXIT_FAILURE;
+               }
            if (( fp = fopen( optarg, "r" )) == NULL ) {
                perror( optarg );
                exit( EXIT_FAILURE );
            }
            break;
+       case 'r':
+               prune = 1;
+               break;
+
+       /* Common Options */
+       case 'C':
+               referrals++;
+               break;
        case 'd':
            debug |= atoi( optarg );
            break;
-       case 'p':
-           ldapport = atoi( optarg );
+       case 'D':       /* bind DN */
+               if( binddn != NULL ) {
+                       fprintf( stderr, "%s: -D previously specified\n" );
+                       return EXIT_FAILURE;
+               }
+           binddn = strdup( optarg );
            break;
-       case 'n':       /* print deletes, don't actually do them */
-           ++not;
+       case 'h':       /* ldap host */
+               if( ldaphost != NULL ) {
+                       fprintf( stderr, "%s: -h previously specified\n" );
+                       return EXIT_FAILURE;
+               }
+           ldaphost = strdup( optarg );
            break;
-       case 'r':
-               prune = 1;
+       case 'I':
+#ifdef HAVE_CYRUS_SASL
+               if( version == LDAP_VERSION2 ) {
+                       fprintf( stderr, "%s: -I incompatible with version %d\n",
+                               prog, version );
+                       return EXIT_FAILURE;
+               }
+               if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
+                       fprintf( stderr, "%s: incompatible previous "
+                               "authentication choice\n",
+                               prog );
+                       return EXIT_FAILURE;
+               }
+               authmethod = LDAP_AUTH_SASL;
+               version = LDAP_VERSION3;
+               sasl_flags = LDAP_SASL_INTERACTIVE;
                break;
-       case 'v':       /* verbose mode */
-           verbose++;
+#else
+               fprintf( stderr, "%s: was not compiled with SASL support\n",
+                       prog );
+               return( EXIT_FAILURE );
+#endif
+       case 'k':       /* kerberos bind */
+#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND
+               if( version > LDAP_VERSION2 ) {
+                       fprintf( stderr, "%s: -k incompatible with LDAPv%d\n",
+                               prog, version );
+                       return EXIT_FAILURE;
+               }
+
+               if( authmethod != -1 ) {
+                       fprintf( stderr, "%s: -k incompatible with previous "
+                               "authentication choice\n", prog );
+                       return EXIT_FAILURE;
+               }
+                       
+               authmethod = LDAP_AUTH_KRBV4;
+#else
+               fprintf( stderr, "%s: not compiled with Kerberos support\n", prog );
+               return EXIT_FAILURE;
+#endif
+           break;
+       case 'K':       /* kerberos bind, part one only */
+#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND
+               if( version > LDAP_VERSION2 ) {
+                       fprintf( stderr, "%s: -k incompatible with LDAPv%d\n",
+                               prog, version );
+                       return EXIT_FAILURE;
+               }
+               if( authmethod != -1 ) {
+                       fprintf( stderr, "%s: incompatible with previous "
+                               "authentication choice\n", prog );
+                       return EXIT_FAILURE;
+               }
+
+               authmethod = LDAP_AUTH_KRBV41;
+#else
+               fprintf( stderr, "%s: not compiled with Kerberos support\n", prog );
+               return( EXIT_FAILURE );
+#endif
            break;
        case 'M':
                /* enable Manage DSA IT */
+               if( version == LDAP_VERSION2 ) {
+                       fprintf( stderr, "%s: -M incompatible with LDAPv%d\n",
+                               prog, version );
+                       return EXIT_FAILURE;
+               }
                manageDSAit++;
+               version = LDAP_VERSION3;
                break;
-       case 'W':
-               want_bindpw++;
+       case 'n':       /* print deletes, don't actually do them */
+           ++not;
+           break;
+       case 'O':
+#ifdef HAVE_CYRUS_SASL
+               if( sasl_secprops != NULL ) {
+                       fprintf( stderr, "%s: -O previously specified\n" );
+                       return EXIT_FAILURE;
+               }
+               if( version == LDAP_VERSION2 ) {
+                       fprintf( stderr, "%s: -O incompatible with LDAPv%d\n",
+                               prog, version );
+                       return EXIT_FAILURE;
+               }
+               if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
+                       fprintf( stderr, "%s: incompatible previous "
+                               "authentication choice\n", prog );
+                       return EXIT_FAILURE;
+               }
+               authmethod = LDAP_AUTH_SASL;
+               version = LDAP_VERSION3;
+               sasl_secprops = strdup( optarg );
+#else
+               fprintf( stderr, "%s: not compiled with SASL support\n",
+                       prog );
+               return( EXIT_FAILURE );
+#endif
                break;
+       case 'p':
+               if( ldapport ) {
+                       fprintf( stderr, "%s: -p previously specified\n" );
+                       return EXIT_FAILURE;
+               }
+           ldapport = atoi( optarg );
+           break;
        case 'P':
-               switch( atoi(optarg) )
-               {
+               switch( atoi(optarg) ) {
                case 2:
+                       if( version == LDAP_VERSION3 ) {
+                               fprintf( stderr, "%s: -P 2 incompatible with version %d\n",
+                                       prog, version );
+                               return EXIT_FAILURE;
+                       }
                        version = LDAP_VERSION2;
                        break;
                case 3:
+                       if( version == LDAP_VERSION2 ) {
+                               fprintf( stderr, "%s: -P 2 incompatible with version %d\n",
+                                       prog, version );
+                               return EXIT_FAILURE;
+                       }
                        version = LDAP_VERSION3;
                        break;
                default:
-                       fprintf( stderr, "protocol version should be 2 or 3\n" );
-                       usage( argv[0] );
+                       fprintf( stderr, "%s: protocol version should be 2 or 3\n",
+                               prog );
+                       usage( prog );
                        return( EXIT_FAILURE );
-               }
-               break;
-       case 'I':
+               } break;
+       case 'Q':
 #ifdef HAVE_CYRUS_SASL
-               sasl_integrity++;
+               if( version == LDAP_VERSION2 ) {
+                       fprintf( stderr, "%s: -Q incompatible with version %d\n",
+                               prog, version );
+                       return EXIT_FAILURE;
+               }
+               if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
+                       fprintf( stderr, "%s: incompatible previous "
+                               "authentication choice\n",
+                               prog );
+                       return EXIT_FAILURE;
+               }
                authmethod = LDAP_AUTH_SASL;
+               version = LDAP_VERSION3;
+               sasl_flags = LDAP_SASL_QUIET;
+               break;
 #else
-               fprintf( stderr, "%s was not compiled with SASL support\n",
-                       argv[0] );
+               fprintf( stderr, "%s: not compiled with SASL support\n",
+                       prog );
                return( EXIT_FAILURE );
 #endif
-               break;
-       case 'E':
+       case 'R':
 #ifdef HAVE_CYRUS_SASL
-               sasl_privacy++;
+               if( sasl_realm != NULL ) {
+                       fprintf( stderr, "%s: -R previously specified\n" );
+                       return EXIT_FAILURE;
+               }
+               if( version == LDAP_VERSION2 ) {
+                       fprintf( stderr, "%s: -R incompatible with version %d\n",
+                               prog, version );
+                       return EXIT_FAILURE;
+               }
+               if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
+                       fprintf( stderr, "%s: incompatible previous "
+                               "authentication choice\n",
+                               prog );
+                       return EXIT_FAILURE;
+               }
                authmethod = LDAP_AUTH_SASL;
+               version = LDAP_VERSION3;
+               sasl_realm = strdup( optarg );
 #else
-               fprintf( stderr, "%s was not compiled with SASL support\n",
-                       argv[0] );
+               fprintf( stderr, "%s: not compiled with SASL support\n",
+                       prog );
                return( EXIT_FAILURE );
 #endif
                break;
-       case 'Y':
+       case 'U':
 #ifdef HAVE_CYRUS_SASL
-               if ( strcasecmp( optarg, "any" ) && strcmp( optarg, "*" ) ) {
-                       sasl_mech = strdup( optarg );
+               if( sasl_authc_id != NULL ) {
+                       fprintf( stderr, "%s: -U previously specified\n" );
+                       return EXIT_FAILURE;
+               }
+               if( version == LDAP_VERSION2 ) {
+                       fprintf( stderr, "%s: -U incompatible with version %d\n",
+                               prog, version );
+                       return EXIT_FAILURE;
+               }
+               if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
+                       fprintf( stderr, "%s: incompatible previous "
+                               "authentication choice\n",
+                               prog );
+                       return EXIT_FAILURE;
                }
                authmethod = LDAP_AUTH_SASL;
+               version = LDAP_VERSION3;
+               sasl_authc_id = strdup( optarg );
 #else
-               fprintf( stderr, "%s was not compiled with SASL support\n",
-                       argv[0] );
+               fprintf( stderr, "%s: not compiled with SASL support\n",
+                       prog );
                return( EXIT_FAILURE );
 #endif
                break;
-       case 'U':
+       case 'v':       /* verbose mode */
+           verbose++;
+           break;
+       case 'w':       /* password */
+           passwd.bv_val = strdup( optarg );
+               {
+                       char* p;
+
+                       for( p = optarg; *p == '\0'; p++ ) {
+                               *p = '\0';
+                       }
+               }
+               passwd.bv_len = strlen( passwd.bv_val );
+           break;
+       case 'W':
+               want_bindpw++;
+               break;
+       case 'Y':
 #ifdef HAVE_CYRUS_SASL
-               sasl_authc_id = strdup( optarg );
+               if( sasl_mech != NULL ) {
+                       fprintf( stderr, "%s: -Y previously specified\n" );
+                       return EXIT_FAILURE;
+               }
+               if( version == LDAP_VERSION2 ) {
+                       fprintf( stderr, "%s: -Y incompatible with version %d\n",
+                               prog, version );
+                       return EXIT_FAILURE;
+               }
+               if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
+                       fprintf( stderr, "%s: incompatible with authentication choice\n", prog );
+                       return EXIT_FAILURE;
+               }
                authmethod = LDAP_AUTH_SASL;
+               version = LDAP_VERSION3;
+               sasl_mech = strdup( optarg );
 #else
-               fprintf( stderr, "%s was not compiled with SASL support\n",
-                       argv[0] );
+               fprintf( stderr, "%s: not compiled with SASL support\n",
+                       prog );
                return( EXIT_FAILURE );
 #endif
                break;
+       case 'x':
+               if( authmethod != -1 && authmethod != LDAP_AUTH_SIMPLE ) {
+                       fprintf( stderr, "%s: incompatible with previous "
+                               "authentication choice\n", prog );
+                       return EXIT_FAILURE;
+               }
+               authmethod = LDAP_AUTH_SIMPLE;
+               break;
        case 'X':
 #ifdef HAVE_CYRUS_SASL
-               sasl_authz_id = strdup( optarg );
+               if( sasl_authz_id != NULL ) {
+                       fprintf( stderr, "%s: -X previously specified\n" );
+                       return EXIT_FAILURE;
+               }
+               if( version == LDAP_VERSION2 ) {
+                       fprintf( stderr, "%s: -X incompatible with LDAPv%d\n",
+                               prog, version );
+                       return EXIT_FAILURE;
+               }
+               if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
+                       fprintf( stderr, "%s: -X incompatible with "
+                               "authentication choice\n", prog );
+                       return EXIT_FAILURE;
+               }
                authmethod = LDAP_AUTH_SASL;
+               version = LDAP_VERSION3;
+               sasl_authz_id = strdup( optarg );
 #else
-               fprintf( stderr, "%s was not compiled with SASL support\n",
-                       argv[0] );
+               fprintf( stderr, "%s: not compiled with SASL support\n",
+                       prog );
                return( EXIT_FAILURE );
 #endif
                break;
        case 'Z':
 #ifdef HAVE_TLS
+               if( version == LDAP_VERSION2 ) {
+                       fprintf( stderr, "%s: -Z incompatible with version %d\n",
+                               prog, version );
+                       return EXIT_FAILURE;
+               }
+               version = LDAP_VERSION3;
                use_tls++;
 #else
-               fprintf( stderr, "%s was not compiled with TLS support\n",
-                       argv[0] );
+               fprintf( stderr, "%s: not compiled with TLS support\n",
+                       prog );
                return( EXIT_FAILURE );
 #endif
                break;
        default:
-               usage( argv[0] );
+               fprintf( stderr, "%s: unrecongized option -%c\n",
+                       prog, optopt );
+               usage( prog );
                return( EXIT_FAILURE );
        }
     }
 
-       if ( ( authmethod == LDAP_AUTH_KRBV4 ) || ( authmethod ==
-                       LDAP_AUTH_KRBV41 ) ) {
-               if( version > LDAP_VERSION2 ) {
-                       fprintf( stderr, "Kerberos requires LDAPv2\n" );
-                       return( EXIT_FAILURE );
-               }
-               version = LDAP_VERSION2;
-       }
-       else if ( authmethod == LDAP_AUTH_SASL ) {
-               if( version != -1 && version != LDAP_VERSION3 ) {
-                       fprintf( stderr, "SASL requires LDAPv3\n" );
-                       return( EXIT_FAILURE );
-               }
-               version = LDAP_VERSION3;
-       }
-
-       if( manageDSAit ) {
-               if( version != -1 && version != LDAP_VERSION3 ) {
-                       fprintf(stderr, "manage DSA control requires LDAPv3\n");
-                       return EXIT_FAILURE;
-               }
+       if (version == -1) {
                version = LDAP_VERSION3;
        }
-
-       if( use_tls ) {
-               if( version != -1 && version != LDAP_VERSION3 ) {
-                       fprintf(stderr, "Start TLS requires LDAPv3\n");
-                       return EXIT_FAILURE;
-               }
-               version = LDAP_VERSION3;
+       if (authmethod == -1 && version > LDAP_VERSION2) {
+#ifdef HAVE_CYRUS_SASL
+               authmethod = LDAP_AUTH_SASL;
+#else
+               authmethod = LDAP_AUTH_SIMPLE;
+#endif
        }
 
     if ( fp == NULL ) {
@@ -314,10 +492,6 @@ main( int argc, char **argv )
                return EXIT_FAILURE;
        }
 
-       if (version == -1 ) {
-               version = 3;
-       }
-
        if( ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &version )
                != LDAP_OPT_SUCCESS )
        {
@@ -341,41 +515,37 @@ main( int argc, char **argv )
 
        if ( authmethod == LDAP_AUTH_SASL ) {
 #ifdef HAVE_CYRUS_SASL
-               int     minssf = 0, maxssf = 0;
-
-               if ( sasl_integrity > 0 )
-                       maxssf = 1;
-               if ( sasl_integrity > 1 )
-                       minssf = 1;
-               if ( sasl_privacy > 0 )
-                       maxssf = 100000; /* Something big value */
-               if ( sasl_privacy > 1 )
-                       minssf = 56;
-               
-               if ( ldap_set_option( ld, LDAP_OPT_X_SASL_MINSSF,
-                               (void *)&minssf ) != LDAP_OPT_SUCCESS ) {
-                       fprintf( stderr, "Could not set LDAP_OPT_X_SASL_MINSSF"
-                               "%d\n", minssf);
-                       return( EXIT_FAILURE );
-               }
-               if ( ldap_set_option( ld, LDAP_OPT_X_SASL_MAXSSF,
-                               (void *)&maxssf ) != LDAP_OPT_SUCCESS ) {
-                       fprintf( stderr, "Could not set LDAP_OPT_X_SASL_MAXSSF"
-                               "%d\n", maxssf);
-                       return( EXIT_FAILURE );
+               void *defaults;
+
+               if( sasl_secprops != NULL ) {
+                       rc = ldap_set_option( ld, LDAP_OPT_X_SASL_SECPROPS,
+                               (void *) sasl_secprops );
+                       
+                       if( rc != LDAP_OPT_SUCCESS ) {
+                               fprintf( stderr,
+                                       "Could not set LDAP_OPT_X_SASL_SECPROPS: %s\n",
+                                       sasl_secprops );
+                               return( EXIT_FAILURE );
+                       }
                }
                
-               rc = ldap_negotiated_sasl_bind_s( ld, binddn, sasl_authc_id,
-                               sasl_authz_id, sasl_mech,
-                               passwd.bv_len ? &passwd : NULL,
-                               NULL, NULL );
+               defaults = lutil_sasl_defaults( ld,
+                       sasl_mech,
+                       sasl_realm,
+                       sasl_authc_id,
+                       passwd.bv_val,
+                       sasl_authz_id );
+
+               rc = ldap_sasl_interactive_bind_s( ld, binddn,
+                       sasl_mech, NULL, NULL,
+                       sasl_flags, lutil_sasl_interact, defaults );
 
                if( rc != LDAP_SUCCESS ) {
-                       ldap_perror( ld, "ldap_negotiated_sasl_bind_s" );
+                       ldap_perror( ld, "ldap_sasl_interactive_bind_s" );
                        return( EXIT_FAILURE );
                }
 #else
-               fprintf( stderr, "%s was not compiled with SASL support\n",
+               fprintf( stderr, "%s: not compiled with SASL support\n",
                        argv[0] );
                return( EXIT_FAILURE );
 #endif
@@ -456,8 +626,8 @@ static int dodelete(
 
        rc = ldap_delete_ext( ld, dn, NULL, NULL, &id );
        if ( rc != LDAP_SUCCESS ) {
-               fprintf( stderr, "ldapdelete: ldap_delete_ext: %s (%d)\n",
-                       ldap_err2string( rc ), rc );
+               fprintf( stderr, "%s: ldap_delete_ext: %s (%d)\n",
+                       prog, ldap_err2string( rc ), rc );
                return rc;
        }
 
@@ -470,8 +640,8 @@ static int dodelete(
        rc = ldap_parse_result( ld, res, &code, &matcheddn, &text, &refs, NULL, 1 );
 
        if( rc != LDAP_SUCCESS ) {
-               fprintf( stderr, "ldapdelete: ldap_parse_result: %s (%d)\n",
-                       ldap_err2string( rc ), rc );
+               fprintf( stderr, "%s: ldap_parse_result: %s (%d)\n",
+                       prog, ldap_err2string( rc ), rc );
                return rc;
        }
 
index 18385bffb7c3e4fc1fc1632848103ffd4116bf72..910e0466eb520eeed1c99fa5003ad819c50f82ef 100644 (file)
 
 #include <ldap.h>
 
+#include "lutil_ldap.h"
 #include "ldif.h"
 #include "ldap_defaults.h"
 
 static char    *prog;
 static char    *binddn = NULL;
-static struct berval passwd = { 0, NULL};
+static struct berval passwd = { 0, NULL };
 static char    *ldaphost = NULL;
 static int     ldapport = 0;
 #ifdef HAVE_CYRUS_SASL
+static unsigned sasl_flags = LDAP_SASL_AUTOMATIC;
+static char *sasl_realm = NULL;
 static char    *sasl_authc_id = NULL;
 static char    *sasl_authz_id = NULL;
 static char    *sasl_mech = NULL;
-static int     sasl_integrity = 0;
-static int     sasl_privacy = 0;
+static char    *sasl_secprops = NULL;
 #endif
 static int     use_tls = 0;
 static int     ldapadd, replace, not, verbose, contoper, force;
@@ -97,32 +99,36 @@ usage( const char *prog )
 "usage: %s [options]\n"
 "      The list of desired operations are read from stdin or from the file\n"
 "      specified by \"-f file\".\n"
-"options:\n"
-"      -a\t\tadd values (default%s)\n"
-"      -b\t\tread values from files (for binary attributes)\n"
-"      -c\t\tcontinuous operation\n"
-"      -C\t\tchase referrals\n"
-"      -d level\tset LDAP debugging level to `level'\n"
-"      -D dn\t\tbind DN\n"
-"      -E\t\trequest SASL privacy (-EE to make it critical)\n"
-"      -f file\t\tperform sequence of operations listed in file\n"
-"      -F\t\tforce all changes records to be used\n"
-"      -h host\t\tLDAP server\n"
-"      -I\t\trequest SASL integrity checking (-II to make it\n"
-"              \tcritical)\n"
-"      -k\t\tuse Kerberos authentication\n"
-"      -K\t\tlike -k, but do only step 1 of the Kerberos bind\n"
-"      -M\t\tenable Manage DSA IT control (-MM to make it critical)\n"
-"      -n\t\tprint changes, don't actually do them\n"
-"      -p port\t\tport on LDAP server\n"
-"      -r\t\treplace values\n"
-"      -U user\t\tSASL authentication identity (username)\n"
-"      -v\t\tverbose mode\n"
-"      -w passwd\tbind password (for Simple authentication)\n"
-"      -X id\t\tSASL authorization identity (\"dn:<dn>\" or \"u:<user>\")\n"
-"      -Y mech\t\tSASL mechanism\n"
-"      -Z\t\tissue Start TLS request (-ZZ to require successful response)\n"
+"Add or modify options:\n"
+"  -a         add values (default%s)\n"
+"  -r         replace values\n"
+"  -F         force all changes records to be used\n"
+
+"Common options:\n"
+"  -d level   set LDAP debugging level to `level'\n"
+"  -D binddn  bind DN\n"
+"  -f file    read operations from `file'\n"
+"  -h host    LDAP server\n"
+"  -I         use SASL Interactive mode\n"
+"  -k         use Kerberos authentication\n"
+"  -K         like -k, but do only step 1 of the Kerberos bind\n"
+"  -M         enable Manage DSA IT control (-MM to make critical)\n"
+"  -n         show what would be done but don't actually search\n"
+"  -O props   SASL security properties\n"
+"  -p port    port on LDAP server\n"
+"  -P version procotol version (default: 3)\n"
+"  -Q         use SASL Quiet mode\n"
+"  -R realm   SASL realm\n"
+"  -U user    SASL authentication identity (username)\n"
+"  -v         run in verbose mode (diagnostics to standard output)\n"
+"  -w passwd  bind passwd (for simple authentication)\n"
+"  -W         prompt for bind passwd\n"
+"  -x         Simple authentication\n"
+"  -X id      SASL authorization identity (\"dn:<dn>\" or \"u:<user>\")\n"
+"  -Y mech    SASL mechanism\n"
+"  -Z         Start TLS request (-ZZ to require successful response)\n"
             , prog, (strcmp( prog, "ldapadd" ) ? " is to replace" : "") );
+
     exit( EXIT_FAILURE );
 }
 
@@ -148,195 +154,366 @@ main( int argc, char **argv )
 
     infile = NULL;
     not = verbose = want_bindpw = debug = manageDSAit = referrals = 0;
-    authmethod = LDAP_AUTH_SIMPLE;
+    authmethod = -1;
        version = -1;
 
-    while (( i = getopt( argc, argv, "acCD:d:EFf:h:IKkMnP:p:rtU:vWw:X:Y:Z" )) != EOF ) {
+    while (( i = getopt( argc, argv, "acrf:F" "Cd:D:h:IkKMnO:p:P:QRU:vw:WxX:Y:Z" )) != EOF ) {
        switch( i ) {
+       /* Modify Options */
        case 'a':       /* add */
            ldapadd = 1;
            break;
        case 'c':       /* continuous operation */
            contoper = 1;
            break;
+       case 'f':       /* read from file */
+               if( infile != NULL ) {
+                       fprintf( stderr, "%s: -f previously specified\n" );
+                       return EXIT_FAILURE;
+               }
+           infile = strdup( optarg );
+           break;
+       case 'F':       /* force all changes records to be used */
+           force = 1;
+           break;
+       case 'r':       /* default is to replace rather than add values */
+           replace = 1;
+           break;
+
+       /* Common Options */
        case 'C':
                referrals++;
                break;
-       case 'r':       /* default is to replace rather than add values */
-           replace = 1;
+       case 'd':
+           debug |= atoi( optarg );
+           break;
+       case 'D':       /* bind DN */
+               if( binddn != NULL ) {
+                       fprintf( stderr, "%s: -D previously specified\n" );
+                       return EXIT_FAILURE;
+               }
+           binddn = strdup( optarg );
+           break;
+       case 'h':       /* ldap host */
+               if( ldaphost != NULL ) {
+                       fprintf( stderr, "%s: -h previously specified\n" );
+                       return EXIT_FAILURE;
+               }
+           ldaphost = strdup( optarg );
            break;
+       case 'I':
+#ifdef HAVE_CYRUS_SASL
+               if( version == LDAP_VERSION2 ) {
+                       fprintf( stderr, "%s: -I incompatible with version %d\n",
+                               prog, version );
+                       return EXIT_FAILURE;
+               }
+               if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
+                       fprintf( stderr, "%s: incompatible previous "
+                               "authentication choice\n",
+                               prog );
+                       return EXIT_FAILURE;
+               }
+               authmethod = LDAP_AUTH_SASL;
+               version = LDAP_VERSION3;
+               sasl_flags = LDAP_SASL_INTERACTIVE;
+               break;
+#else
+               fprintf( stderr, "%s: was not compiled with SASL support\n",
+                       prog );
+               return( EXIT_FAILURE );
+#endif
        case 'k':       /* kerberos bind */
 #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND
+               if( version > LDAP_VERSION2 ) {
+                       fprintf( stderr, "%s: -k incompatible with LDAPv%d\n",
+                               prog, version );
+                       return EXIT_FAILURE;
+               }
+
+               if( authmethod != -1 ) {
+                       fprintf( stderr, "%s: -k incompatible with previous "
+                               "authentication choice\n", prog );
+                       return EXIT_FAILURE;
+               }
+                       
                authmethod = LDAP_AUTH_KRBV4;
 #else
-               fprintf( stderr, "%s was not compiled with Kerberos support\n", argv[0] );
-               return( EXIT_FAILURE );
+               fprintf( stderr, "%s: not compiled with Kerberos support\n", prog );
+               return EXIT_FAILURE;
 #endif
            break;
-       case 'K':       /* kerberos bind, part 1 only */
+       case 'K':       /* kerberos bind, part one only */
 #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND
+               if( version > LDAP_VERSION2 ) {
+                       fprintf( stderr, "%s: -k incompatible with LDAPv%d\n",
+                               prog, version );
+                       return EXIT_FAILURE;
+               }
+               if( authmethod != -1 ) {
+                       fprintf( stderr, "%s: incompatible with previous "
+                               "authentication choice\n", prog );
+                       return EXIT_FAILURE;
+               }
+
                authmethod = LDAP_AUTH_KRBV41;
 #else
-               fprintf( stderr, "%s was not compiled with Kerberos support\n", argv[0] );
+               fprintf( stderr, "%s: not compiled with Kerberos support\n", prog );
                return( EXIT_FAILURE );
 #endif
            break;
-       case 'F':       /* force all changes records to be used */
-           force = 1;
-           break;
-       case 'h':       /* ldap host */
-           ldaphost = strdup( optarg );
-           break;
-       case 'D':       /* bind DN */
-           binddn = strdup( optarg );
-           break;
-       case 'w':       /* password */
-           passwd.bv_val = strdup( optarg );
-               {
-                       char* p;
-
-                       for( p = optarg; *p == '\0'; p++ ) {
-                               *p = '*';
-                       }
-               }
-               passwd.bv_len = strlen( passwd.bv_val );
-           break;
-       case 'd':
-           debug |= atoi( optarg );
-           break;
-       case 'f':       /* read from file */
-           infile = strdup( optarg );
-           break;
-       case 'p':
-           ldapport = atoi( optarg );
-           break;
-       case 'n':       /* print adds, don't actually do them */
-           ++not;
-           break;
-       case 'v':       /* verbose mode */
-           verbose++;
-           break;
        case 'M':
                /* enable Manage DSA IT */
+               if( version == LDAP_VERSION2 ) {
+                       fprintf( stderr, "%s: -M incompatible with LDAPv%d\n",
+                               prog, version );
+                       return EXIT_FAILURE;
+               }
                manageDSAit++;
+               version = LDAP_VERSION3;
                break;
-       case 'W':
-               want_bindpw++;
+       case 'n':       /* print deletes, don't actually do them */
+           ++not;
+           break;
+       case 'O':
+#ifdef HAVE_CYRUS_SASL
+               if( sasl_secprops != NULL ) {
+                       fprintf( stderr, "%s: -O previously specified\n" );
+                       return EXIT_FAILURE;
+               }
+               if( version == LDAP_VERSION2 ) {
+                       fprintf( stderr, "%s: -O incompatible with LDAPv%d\n",
+                               prog, version );
+                       return EXIT_FAILURE;
+               }
+               if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
+                       fprintf( stderr, "%s: incompatible previous "
+                               "authentication choice\n", prog );
+                       return EXIT_FAILURE;
+               }
+               authmethod = LDAP_AUTH_SASL;
+               version = LDAP_VERSION3;
+               sasl_secprops = strdup( optarg );
+#else
+               fprintf( stderr, "%s: not compiled with SASL support\n",
+                       prog );
+               return( EXIT_FAILURE );
+#endif
                break;
+       case 'p':
+               if( ldapport ) {
+                       fprintf( stderr, "%s: -p previously specified\n" );
+                       return EXIT_FAILURE;
+               }
+           ldapport = atoi( optarg );
+           break;
        case 'P':
-               switch( atoi(optarg) )
-               {
+               switch( atoi(optarg) ) {
                case 2:
+                       if( version == LDAP_VERSION3 ) {
+                               fprintf( stderr, "%s: -P 2 incompatible with version %d\n",
+                                       prog, version );
+                               return EXIT_FAILURE;
+                       }
                        version = LDAP_VERSION2;
                        break;
                case 3:
+                       if( version == LDAP_VERSION2 ) {
+                               fprintf( stderr, "%s: -P 2 incompatible with version %d\n",
+                                       prog, version );
+                               return EXIT_FAILURE;
+                       }
                        version = LDAP_VERSION3;
                        break;
                default:
-                       fprintf( stderr, "protocol version should be 2 or 3\n" );
-                       usage( argv[0] );
-               }
-               break;
-       case 'I':
+                       fprintf( stderr, "%s: protocol version should be 2 or 3\n",
+                               prog );
+                       usage( prog );
+                       return( EXIT_FAILURE );
+               } break;
+       case 'Q':
 #ifdef HAVE_CYRUS_SASL
-               sasl_integrity++;
+               if( version == LDAP_VERSION2 ) {
+                       fprintf( stderr, "%s: -Q incompatible with version %d\n",
+                               prog, version );
+                       return EXIT_FAILURE;
+               }
+               if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
+                       fprintf( stderr, "%s: incompatible previous "
+                               "authentication choice\n",
+                               prog );
+                       return EXIT_FAILURE;
+               }
                authmethod = LDAP_AUTH_SASL;
+               version = LDAP_VERSION3;
+               sasl_flags = LDAP_SASL_QUIET;
+               break;
 #else
-               fprintf( stderr, "%s was not compiled with SASL support\n",
-                       argv[0] );
+               fprintf( stderr, "%s: not compiled with SASL support\n",
+                       prog );
                return( EXIT_FAILURE );
 #endif
-               break;
-       case 'E':
+       case 'R':
 #ifdef HAVE_CYRUS_SASL
-               sasl_privacy++;
+               if( sasl_realm != NULL ) {
+                       fprintf( stderr, "%s: -R previously specified\n" );
+                       return EXIT_FAILURE;
+               }
+               if( version == LDAP_VERSION2 ) {
+                       fprintf( stderr, "%s: -R incompatible with version %d\n",
+                               prog, version );
+                       return EXIT_FAILURE;
+               }
+               if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
+                       fprintf( stderr, "%s: incompatible previous "
+                               "authentication choice\n",
+                               prog );
+                       return EXIT_FAILURE;
+               }
                authmethod = LDAP_AUTH_SASL;
+               version = LDAP_VERSION3;
+               sasl_realm = strdup( optarg );
 #else
-               fprintf( stderr, "%s was not compiled with SASL support\n",
-                       argv[0] );
+               fprintf( stderr, "%s: not compiled with SASL support\n",
+                       prog );
                return( EXIT_FAILURE );
 #endif
                break;
-       case 'Y':
+       case 'U':
 #ifdef HAVE_CYRUS_SASL
-               if ( strcasecmp( optarg, "any" ) && strcmp( optarg, "*" ) ) {
-                       sasl_mech = strdup( optarg );
+               if( sasl_authc_id != NULL ) {
+                       fprintf( stderr, "%s: -U previously specified\n" );
+                       return EXIT_FAILURE;
+               }
+               if( version == LDAP_VERSION2 ) {
+                       fprintf( stderr, "%s: -U incompatible with version %d\n",
+                               prog, version );
+                       return EXIT_FAILURE;
+               }
+               if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
+                       fprintf( stderr, "%s: incompatible previous "
+                               "authentication choice\n",
+                               prog );
+                       return EXIT_FAILURE;
                }
                authmethod = LDAP_AUTH_SASL;
+               version = LDAP_VERSION3;
+               sasl_authc_id = strdup( optarg );
 #else
-               fprintf( stderr, "%s was not compiled with SASL support\n",
-                       argv[0] );
+               fprintf( stderr, "%s: not compiled with SASL support\n",
+                       prog );
                return( EXIT_FAILURE );
 #endif
                break;
-       case 'U':
+       case 'v':       /* verbose mode */
+           verbose++;
+           break;
+       case 'w':       /* password */
+           passwd.bv_val = strdup( optarg );
+               {
+                       char* p;
+
+                       for( p = optarg; *p == '\0'; p++ ) {
+                               *p = '\0';
+                       }
+               }
+               passwd.bv_len = strlen( passwd.bv_val );
+           break;
+       case 'W':
+               want_bindpw++;
+               break;
+       case 'Y':
 #ifdef HAVE_CYRUS_SASL
-               sasl_authc_id = strdup( optarg );
+               if( sasl_mech != NULL ) {
+                       fprintf( stderr, "%s: -Y previously specified\n" );
+                       return EXIT_FAILURE;
+               }
+               if( version == LDAP_VERSION2 ) {
+                       fprintf( stderr, "%s: -Y incompatible with version %d\n",
+                               prog, version );
+                       return EXIT_FAILURE;
+               }
+               if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
+                       fprintf( stderr, "%s: incompatible with authentication choice\n", prog );
+                       return EXIT_FAILURE;
+               }
                authmethod = LDAP_AUTH_SASL;
+               version = LDAP_VERSION3;
+               sasl_mech = strdup( optarg );
 #else
-               fprintf( stderr, "%s was not compiled with SASL support\n",
-                       argv[0] );
+               fprintf( stderr, "%s: not compiled with SASL support\n",
+                       prog );
                return( EXIT_FAILURE );
 #endif
                break;
+       case 'x':
+               if( authmethod != -1 && authmethod != LDAP_AUTH_SIMPLE ) {
+                       fprintf( stderr, "%s: incompatible with previous "
+                               "authentication choice\n", prog );
+                       return EXIT_FAILURE;
+               }
+               authmethod = LDAP_AUTH_SIMPLE;
+               break;
        case 'X':
 #ifdef HAVE_CYRUS_SASL
-               sasl_authz_id = strdup( optarg );
+               if( sasl_authz_id != NULL ) {
+                       fprintf( stderr, "%s: -X previously specified\n" );
+                       return EXIT_FAILURE;
+               }
+               if( version == LDAP_VERSION2 ) {
+                       fprintf( stderr, "%s: -X incompatible with LDAPv%d\n",
+                               prog, version );
+                       return EXIT_FAILURE;
+               }
+               if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
+                       fprintf( stderr, "%s: -X incompatible with "
+                               "authentication choice\n", prog );
+                       return EXIT_FAILURE;
+               }
                authmethod = LDAP_AUTH_SASL;
+               version = LDAP_VERSION3;
+               sasl_authz_id = strdup( optarg );
 #else
-               fprintf( stderr, "%s was not compiled with SASL support\n",
-                       argv[0] );
+               fprintf( stderr, "%s: not compiled with SASL support\n",
+                       prog );
                return( EXIT_FAILURE );
 #endif
                break;
        case 'Z':
 #ifdef HAVE_TLS
+               if( version == LDAP_VERSION2 ) {
+                       fprintf( stderr, "%s: -Z incompatible with version %d\n",
+                               prog, version );
+                       return EXIT_FAILURE;
+               }
+               version = LDAP_VERSION3;
                use_tls++;
 #else
-               fprintf( stderr, "%s was not compiled with TLS support\n",
-                       argv[0] );
+               fprintf( stderr, "%s: not compiled with TLS support\n",
+                       prog );
                return( EXIT_FAILURE );
 #endif
                break;
        default:
+               fprintf( stderr, "%s: unrecongized option -%c\n",
+                       prog, optopt );
            usage( prog );
        }
     }
 
-    if ( argc != optind )
-       usage( prog );
-
-       if ( ( authmethod == LDAP_AUTH_KRBV4 ) || ( authmethod ==
-                       LDAP_AUTH_KRBV41 ) ) {
-               if( version > LDAP_VERSION2 ) {
-                       fprintf( stderr, "Kerberos requires LDAPv2\n" );
-                       return( EXIT_FAILURE );
-               }
-               version = LDAP_VERSION2;
-       }
-       else if ( authmethod == LDAP_AUTH_SASL ) {
-               if( version != -1 && version != LDAP_VERSION3 ) {
-                       fprintf( stderr, "SASL requires LDAPv3\n" );
-                       return( EXIT_FAILURE );
-               }
+       if (version == -1) {
                version = LDAP_VERSION3;
        }
-
-       if( manageDSAit ) {
-               if( version != -1 && version != LDAP_VERSION3 ) {
-                       fprintf(stderr, "manage DSA control requires LDAPv3\n");
-                       return EXIT_FAILURE;
-               }
-               version = LDAP_VERSION3;
+       if (authmethod == -1 && version > LDAP_VERSION2) {
+#ifdef HAVE_CYRUS_SASL
+               authmethod = LDAP_AUTH_SASL;
+#else
+               authmethod = LDAP_AUTH_SIMPLE;
+#endif
        }
 
-       if( use_tls ) {
-               if( version != -1 && version != LDAP_VERSION3 ) {
-                       fprintf(stderr, "Start TLS requires LDAPv3\n");
-                       return EXIT_FAILURE;
-               }
-               version = LDAP_VERSION3;
-       }
+       if ( argc != optind )
+       usage( prog );
 
     if ( infile != NULL ) {
        if (( fp = fopen( infile, "r" )) == NULL ) {
@@ -404,41 +581,37 @@ main( int argc, char **argv )
 
        if ( authmethod == LDAP_AUTH_SASL ) {
 #ifdef HAVE_CYRUS_SASL
-               int     minssf = 0, maxssf = 0;
-
-               if ( sasl_integrity > 0 )
-                       maxssf = 1;
-               if ( sasl_integrity > 1 )
-                       minssf = 1;
-               if ( sasl_privacy > 0 )
-                       maxssf = 100000; /* Something big value */
-               if ( sasl_privacy > 1 )
-                       minssf = 56;
-               
-               if ( ldap_set_option( ld, LDAP_OPT_X_SASL_MINSSF,
-                       (void *)&minssf ) != LDAP_OPT_SUCCESS ) {
-                       fprintf( stderr, "Could not set LDAP_OPT_X_SASL_MINSSF"
-                               "%d\n", minssf);
-                       return( EXIT_FAILURE );
-               }
-               if ( ldap_set_option( ld, LDAP_OPT_X_SASL_MAXSSF,
-                       (void *)&maxssf ) != LDAP_OPT_SUCCESS ) {
-                       fprintf( stderr, "Could not set LDAP_OPT_X_SASL_MINSSF"
-                               "%d\n", minssf);
-                       return( EXIT_FAILURE );
+               void *defaults;
+
+               if( sasl_secprops != NULL ) {
+                       rc = ldap_set_option( ld, LDAP_OPT_X_SASL_SECPROPS,
+                               (void *) sasl_secprops );
+                       
+                       if( rc != LDAP_OPT_SUCCESS ) {
+                               fprintf( stderr,
+                                       "Could not set LDAP_OPT_X_SASL_SECPROPS: %s\n",
+                                       sasl_secprops );
+                               return( EXIT_FAILURE );
+                       }
                }
                
-               rc = ldap_negotiated_sasl_bind_s( ld, binddn, sasl_authc_id,
-                               sasl_authz_id, sasl_mech,
-                               passwd.bv_len ? &passwd : NULL,
-                               NULL, NULL );
+               defaults = lutil_sasl_defaults( ld,
+                       sasl_mech,
+                       sasl_realm,
+                       sasl_authc_id,
+                       passwd.bv_val,
+                       sasl_authz_id );
+
+               rc = ldap_sasl_interactive_bind_s( ld, binddn,
+                       sasl_mech, NULL, NULL,
+                       sasl_flags, lutil_sasl_interact, defaults );
 
                if( rc != LDAP_SUCCESS ) {
-                       ldap_perror( ld, "ldap_negotiated_sasl_bind_s" );
+                       ldap_perror( ld, "ldap_sasl_interactive_bind_s" );
                        return( EXIT_FAILURE );
                }
 #else
-               fprintf( stderr, "%s was not compiled with SASL support\n",
+               fprintf( stderr, "%s: not compiled with SASL support\n",
                        argv[0] );
                return( EXIT_FAILURE );
 #endif
index 142efb62dcce355aec30748eb494c2e36c317290..b93490912092a27151a11877f3bf7efbc61e0dc9 100644 (file)
 #include <ac/unistd.h>
 
 #include <ldap.h>
+#include "lutil_ldap.h"
+#include "ldap_defaults.h"
 
+static char *prog = NULL;
 static char    *binddn = NULL;
-static struct berval passwd = { 0, NULL};
+static struct berval passwd = { 0, NULL };
 static char    *ldaphost = NULL;
 static int     ldapport = 0;
 #ifdef HAVE_CYRUS_SASL
+static unsigned sasl_flags = LDAP_SASL_AUTOMATIC;
+static char *sasl_realm = NULL;
 static char    *sasl_authc_id = NULL;
 static char    *sasl_authz_id = NULL;
 static char    *sasl_mech = NULL;
-static int     sasl_integrity = 0;
-static int     sasl_privacy = 0;
+static char    *sasl_secprops = NULL;
 #endif
 static int     use_tls = 0;
 static int     not, verbose, contoper;
@@ -61,31 +65,35 @@ usage( const char *s )
 "      dn rdn: If given, rdn will replace the RDN of the entry specified by DN\n"
 "              If not given, the list of modifications is read from stdin or\n"
 "              from the file specified by \"-f file\" (see man page).\n"
-"options:\n"
-"      -c\t\tcontinuous operation mode (do not stop on errors)\n"
-"      -C\t\tchase referrals\n"
-"      -d level\tset LDAP debugging level to `level'\n"
-"      -D binddn\tbind DN\n"
-"      -E\t\trequest SASL privacy (-EE to make it critical)\n"
-"      -f file\t\tdo renames listed in `file'\n"
-"      -h host\t\tLDAP server\n"
-"      -I\t\trequest SASL integrity checking (-II to make it\n"
-"              \tcritical)\n"
-"      -k\t\tuse Kerberos authentication\n"
-"      -K\t\tlike -k, but do only step 1 of the Kerberos bind\n"
-"      -M\t\tenable Manage DSA IT control (-MM to make it critical)\n"
-"      -n\t\tshow what would be done but don't actually do it\n"
-"      -p port\t\tport on LDAP server\n"
-"      -P version\tprocotol version (default: 3)\n"
-"      -r\t\tremove old RDN\n"
-"      -s newsuperior\tnew superior entry\n"
-"      -U user\t\tSASL authentication identity (username)\n"
-"      -v\t\trun in verbose mode (diagnostics to standard output)\n"
-"      -w passwd\tbind passwd (for simple authentication)\n"
-"      -W\t\tprompt for bind passwd\n"
-"      -X id\t\tSASL authorization identity (\"dn:<dn>\" or \"u:<user>\")\n"
-"      -Y mech\t\tSASL mechanism\n"
-"      -Z\t\tissue Start TLS request (-ZZ to require successful response)\n"
+"Rename options:\n"
+"  -c         continuous operation mode (do not stop on errors)\n"
+"  -f file    read operations from `file'\n"
+"  -r         remove old RDN\n"
+"  -s newsup  new superior entry\n"
+
+"Common options:\n"
+"  -d level   set LDAP debugging level to `level'\n"
+"  -D binddn  bind DN\n"
+"  -f file    read operations from `file'\n"
+"  -h host    LDAP server\n"
+"  -I         use SASL Interactive mode\n"
+"  -k         use Kerberos authentication\n"
+"  -K         like -k, but do only step 1 of the Kerberos bind\n"
+"  -M         enable Manage DSA IT control (-MM to make critical)\n"
+"  -n         show what would be done but don't actually search\n"
+"  -O props   SASL security properties\n"
+"  -p port    port on LDAP server\n"
+"  -P version procotol version (default: 3)\n"
+"  -Q         use SASL Quiet mode\n"
+"  -R realm   SASL realm\n"
+"  -U user    SASL authentication identity (username)\n"
+"  -v         run in verbose mode (diagnostics to standard output)\n"
+"  -w passwd  bind passwd (for simple authentication)\n"
+"  -W         prompt for bind passwd\n"
+"  -x         Simple authentication\n"
+"  -X id      SASL authorization identity (\"dn:<dn>\" or \"u:<user>\")\n"
+"  -Y mech    SASL mechanism\n"
+"  -Z         Start TLS request (-ZZ to require successful response)\n"
 ,              s );
 
        exit( EXIT_FAILURE );
@@ -94,7 +102,7 @@ usage( const char *s )
 int
 main(int argc, char **argv)
 {
-    char               *myname,*infile, *entrydn = NULL, *rdn = NULL, buf[ 4096 ];
+    char               *infile, *entrydn = NULL, *rdn = NULL, buf[ 4096 ];
     FILE               *fp;
        int             rc, i, remove, havedn, authmethod, version, want_bindpw, debug, manageDSAit;
        int             referrals;
@@ -106,203 +114,367 @@ main(int argc, char **argv)
     authmethod = LDAP_AUTH_SIMPLE;
        version = -1;
 
-    myname = (myname = strrchr(argv[0], '/')) == NULL ? argv[0] : ++myname;
+    prog = (prog = strrchr(argv[0], *LDAP_DIRSEP)) == NULL ? argv[0] : ++prog;
 
-    while (( i = getopt( argc, argv, "cCD:d:Ef:h:IKkMnP:p:rs:U:vWw:X:Y:Z" )) != EOF ) {
+    while (( i = getopt( argc, argv, "cf:rs:" "Cd:D:h:IkKMnO:p:P:QRU:vw:WxX:Y:Z" )) != EOF ) {
        switch( i ) {
-       case 'k':       /* kerberos bind */
-#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND
-               authmethod = LDAP_AUTH_KRBV4;
-#else
-               fprintf( stderr, "%s was not compiled with Kerberos support\n", argv[0] );
-               return( EXIT_FAILURE );
-#endif
+       /* Modrdn Options */
+       case 'c':
+               contoper++;
                break;
-       case 'K':       /* kerberos bind, part one only */
-#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND
-               authmethod = LDAP_AUTH_KRBV41;
-#else
-               fprintf( stderr, "%s was not compiled with Kerberos support\n", argv[0] );
-               return( EXIT_FAILURE );
-#endif
-               break;
-       case 'c':       /* continuous operation mode */
-           ++contoper;
-           break;
-       case 'C':
-               referrals++;
-               break;
-       case 'h':       /* ldap host */
-           ldaphost = strdup( optarg );
+       case 'f':       /* read from file */
+               if( infile != NULL ) {
+                       fprintf( stderr, "%s: -f previously specified\n" );
+                       return EXIT_FAILURE;
+               }
+           infile = strdup( optarg );
            break;
-       case 'D':       /* bind DN */
-           binddn = strdup( optarg );
+       case 'r':       /* remove old RDN */
+           remove++;
            break;
        case 's':       /* newSuperior */
+               if( version == LDAP_VERSION2 ) {
+                       fprintf( stderr, "%s: -X incompatible with LDAPv%d\n",
+                               prog, version );
+                       return EXIT_FAILURE;
+               }
            newSuperior = strdup( optarg );
-           version = LDAP_VERSION3;    /* This option => force V3 */
+           version = LDAP_VERSION3;
            break;
-       case 'w':       /* password */
-           passwd.bv_val = strdup( optarg );
-               {
-                       char* p;
 
-                       for( p = optarg; *p == '\0'; p++ ) {
-                               *p = '*';
-                       }
-               }
-               passwd.bv_len = strlen( passwd.bv_val );
-           break;
+       /* Common Options */
+       case 'C':
+               referrals++;
+               break;
        case 'd':
            debug |= atoi( optarg );
            break;
-       case 'f':       /* read from file */
-           infile = strdup( optarg );
-           break;
-       case 'p':
-           ldapport = atoi( optarg );
+       case 'D':       /* bind DN */
+               if( binddn != NULL ) {
+                       fprintf( stderr, "%s: -D previously specified\n" );
+                       return EXIT_FAILURE;
+               }
+           binddn = strdup( optarg );
            break;
-       case 'n':       /* print adds, don't actually do them */
-           ++not;
+       case 'h':       /* ldap host */
+               if( ldaphost != NULL ) {
+                       fprintf( stderr, "%s: -h previously specified\n" );
+                       return EXIT_FAILURE;
+               }
+           ldaphost = strdup( optarg );
            break;
-       case 'v':       /* verbose mode */
-           verbose++;
+       case 'I':
+#ifdef HAVE_CYRUS_SASL
+               if( version == LDAP_VERSION2 ) {
+                       fprintf( stderr, "%s: -I incompatible with version %d\n",
+                               prog, version );
+                       return EXIT_FAILURE;
+               }
+               if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
+                       fprintf( stderr, "%s: incompatible previous "
+                               "authentication choice\n",
+                               prog );
+                       return EXIT_FAILURE;
+               }
+               authmethod = LDAP_AUTH_SASL;
+               version = LDAP_VERSION3;
+               sasl_flags = LDAP_SASL_INTERACTIVE;
+               break;
+#else
+               fprintf( stderr, "%s: was not compiled with SASL support\n",
+                       prog );
+               return( EXIT_FAILURE );
+#endif
+       case 'k':       /* kerberos bind */
+#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND
+               if( version > LDAP_VERSION2 ) {
+                       fprintf( stderr, "%s: -k incompatible with LDAPv%d\n",
+                               prog, version );
+                       return EXIT_FAILURE;
+               }
+
+               if( authmethod != -1 ) {
+                       fprintf( stderr, "%s: -k incompatible with previous "
+                               "authentication choice\n", prog );
+                       return EXIT_FAILURE;
+               }
+                       
+               authmethod = LDAP_AUTH_KRBV4;
+#else
+               fprintf( stderr, "%s: not compiled with Kerberos support\n", prog );
+               return EXIT_FAILURE;
+#endif
            break;
-       case 'r':       /* remove old RDN */
-           remove++;
+       case 'K':       /* kerberos bind, part one only */
+#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND
+               if( version > LDAP_VERSION2 ) {
+                       fprintf( stderr, "%s: -k incompatible with LDAPv%d\n",
+                               prog, version );
+                       return EXIT_FAILURE;
+               }
+               if( authmethod != -1 ) {
+                       fprintf( stderr, "%s: incompatible with previous "
+                               "authentication choice\n", prog );
+                       return EXIT_FAILURE;
+               }
+
+               authmethod = LDAP_AUTH_KRBV41;
+#else
+               fprintf( stderr, "%s: not compiled with Kerberos support\n", prog );
+               return( EXIT_FAILURE );
+#endif
            break;
        case 'M':
                /* enable Manage DSA IT */
+               if( version == LDAP_VERSION2 ) {
+                       fprintf( stderr, "%s: -M incompatible with LDAPv%d\n",
+                               prog, version );
+                       return EXIT_FAILURE;
+               }
                manageDSAit++;
+               version = LDAP_VERSION3;
                break;
-       case 'W':
-               want_bindpw++;
+       case 'n':       /* print deletes, don't actually do them */
+           ++not;
+           break;
+       case 'O':
+#ifdef HAVE_CYRUS_SASL
+               if( sasl_secprops != NULL ) {
+                       fprintf( stderr, "%s: -O previously specified\n" );
+                       return EXIT_FAILURE;
+               }
+               if( version == LDAP_VERSION2 ) {
+                       fprintf( stderr, "%s: -O incompatible with LDAPv%d\n",
+                               prog, version );
+                       return EXIT_FAILURE;
+               }
+               if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
+                       fprintf( stderr, "%s: incompatible previous "
+                               "authentication choice\n", prog );
+                       return EXIT_FAILURE;
+               }
+               authmethod = LDAP_AUTH_SASL;
+               version = LDAP_VERSION3;
+               sasl_secprops = strdup( optarg );
+#else
+               fprintf( stderr, "%s: not compiled with SASL support\n",
+                       prog );
+               return( EXIT_FAILURE );
+#endif
                break;
+       case 'p':
+               if( ldapport ) {
+                       fprintf( stderr, "%s: -p previously specified\n" );
+                       return EXIT_FAILURE;
+               }
+           ldapport = atoi( optarg );
+           break;
        case 'P':
-               switch( atoi(optarg) )
-               {
+               switch( atoi(optarg) ) {
                case 2:
+                       if( version == LDAP_VERSION3 ) {
+                               fprintf( stderr, "%s: -P 2 incompatible with version %d\n",
+                                       prog, version );
+                               return EXIT_FAILURE;
+                       }
                        version = LDAP_VERSION2;
                        break;
                case 3:
+                       if( version == LDAP_VERSION2 ) {
+                               fprintf( stderr, "%s: -P 2 incompatible with version %d\n",
+                                       prog, version );
+                               return EXIT_FAILURE;
+                       }
                        version = LDAP_VERSION3;
                        break;
                default:
-                       fprintf( stderr, "protocol version should be 2 or 3\n" );
-                       usage( argv[0] );
+                       fprintf( stderr, "%s: protocol version should be 2 or 3\n",
+                               prog );
+                       usage( prog );
                        return( EXIT_FAILURE );
-               }
-               break;
-       case 'I':
+               } break;
+       case 'Q':
 #ifdef HAVE_CYRUS_SASL
-               sasl_integrity++;
+               if( version == LDAP_VERSION2 ) {
+                       fprintf( stderr, "%s: -Q incompatible with version %d\n",
+                               prog, version );
+                       return EXIT_FAILURE;
+               }
+               if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
+                       fprintf( stderr, "%s: incompatible previous "
+                               "authentication choice\n",
+                               prog );
+                       return EXIT_FAILURE;
+               }
                authmethod = LDAP_AUTH_SASL;
+               version = LDAP_VERSION3;
+               sasl_flags = LDAP_SASL_QUIET;
+               break;
 #else
-               fprintf( stderr, "%s was not compiled with SASL support\n",
-                       argv[0] );
+               fprintf( stderr, "%s: not compiled with SASL support\n",
+                       prog );
                return( EXIT_FAILURE );
 #endif
-               break;
-       case 'E':
+       case 'R':
 #ifdef HAVE_CYRUS_SASL
-               sasl_privacy++;
+               if( sasl_realm != NULL ) {
+                       fprintf( stderr, "%s: -R previously specified\n" );
+                       return EXIT_FAILURE;
+               }
+               if( version == LDAP_VERSION2 ) {
+                       fprintf( stderr, "%s: -R incompatible with version %d\n",
+                               prog, version );
+                       return EXIT_FAILURE;
+               }
+               if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
+                       fprintf( stderr, "%s: incompatible previous "
+                               "authentication choice\n",
+                               prog );
+                       return EXIT_FAILURE;
+               }
                authmethod = LDAP_AUTH_SASL;
+               version = LDAP_VERSION3;
+               sasl_realm = strdup( optarg );
 #else
-               fprintf( stderr, "%s was not compiled with SASL support\n",
-                       argv[0] );
+               fprintf( stderr, "%s: not compiled with SASL support\n",
+                       prog );
                return( EXIT_FAILURE );
 #endif
                break;
-       case 'Y':
+       case 'U':
 #ifdef HAVE_CYRUS_SASL
-               if ( strcasecmp( optarg, "any" ) && strcmp( optarg, "*" ) ) {
-                       sasl_mech = strdup( optarg );
+               if( sasl_authc_id != NULL ) {
+                       fprintf( stderr, "%s: -U previously specified\n" );
+                       return EXIT_FAILURE;
+               }
+               if( version == LDAP_VERSION2 ) {
+                       fprintf( stderr, "%s: -U incompatible with version %d\n",
+                               prog, version );
+                       return EXIT_FAILURE;
+               }
+               if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
+                       fprintf( stderr, "%s: incompatible previous "
+                               "authentication choice\n",
+                               prog );
+                       return EXIT_FAILURE;
                }
                authmethod = LDAP_AUTH_SASL;
+               version = LDAP_VERSION3;
+               sasl_authc_id = strdup( optarg );
 #else
-               fprintf( stderr, "%s was not compiled with SASL support\n",
-                       argv[0] );
+               fprintf( stderr, "%s: not compiled with SASL support\n",
+                       prog );
                return( EXIT_FAILURE );
 #endif
                break;
-       case 'U':
+       case 'v':       /* verbose mode */
+           verbose++;
+           break;
+       case 'w':       /* password */
+           passwd.bv_val = strdup( optarg );
+               {
+                       char* p;
+
+                       for( p = optarg; *p == '\0'; p++ ) {
+                               *p = '\0';
+                       }
+               }
+               passwd.bv_len = strlen( passwd.bv_val );
+           break;
+       case 'W':
+               want_bindpw++;
+               break;
+       case 'Y':
 #ifdef HAVE_CYRUS_SASL
-               sasl_authc_id = strdup( optarg );
+               if( sasl_mech != NULL ) {
+                       fprintf( stderr, "%s: -Y previously specified\n" );
+                       return EXIT_FAILURE;
+               }
+               if( version == LDAP_VERSION2 ) {
+                       fprintf( stderr, "%s: -Y incompatible with version %d\n",
+                               prog, version );
+                       return EXIT_FAILURE;
+               }
+               if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
+                       fprintf( stderr, "%s: incompatible with authentication choice\n", prog );
+                       return EXIT_FAILURE;
+               }
                authmethod = LDAP_AUTH_SASL;
+               version = LDAP_VERSION3;
+               sasl_mech = strdup( optarg );
 #else
-               fprintf( stderr, "%s was not compiled with SASL support\n",
-                       argv[0] );
+               fprintf( stderr, "%s: not compiled with SASL support\n",
+                       prog );
                return( EXIT_FAILURE );
 #endif
                break;
+       case 'x':
+               if( authmethod != -1 && authmethod != LDAP_AUTH_SIMPLE ) {
+                       fprintf( stderr, "%s: incompatible with previous "
+                               "authentication choice\n", prog );
+                       return EXIT_FAILURE;
+               }
+               authmethod = LDAP_AUTH_SIMPLE;
+               break;
        case 'X':
 #ifdef HAVE_CYRUS_SASL
-               sasl_authz_id = strdup( optarg );
+               if( sasl_authz_id != NULL ) {
+                       fprintf( stderr, "%s: -X previously specified\n" );
+                       return EXIT_FAILURE;
+               }
+               if( version == LDAP_VERSION2 ) {
+                       fprintf( stderr, "%s: -X incompatible with LDAPv%d\n",
+                               prog, version );
+                       return EXIT_FAILURE;
+               }
+               if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
+                       fprintf( stderr, "%s: -X incompatible with "
+                               "authentication choice\n", prog );
+                       return EXIT_FAILURE;
+               }
                authmethod = LDAP_AUTH_SASL;
+               version = LDAP_VERSION3;
+               sasl_authz_id = strdup( optarg );
 #else
-               fprintf( stderr, "%s was not compiled with SASL support\n",
-                       argv[0] );
+               fprintf( stderr, "%s: not compiled with SASL support\n",
+                       prog );
                return( EXIT_FAILURE );
 #endif
                break;
        case 'Z':
 #ifdef HAVE_TLS
+               if( version == LDAP_VERSION2 ) {
+                       fprintf( stderr, "%s: -Z incompatible with version %d\n",
+                               prog, version );
+                       return EXIT_FAILURE;
+               }
+               version = LDAP_VERSION3;
                use_tls++;
 #else
-               fprintf( stderr, "%s was not compiled with TLS support\n",
-                       argv[0] );
+               fprintf( stderr, "%s: not compiled with TLS support\n",
+                       prog );
                return( EXIT_FAILURE );
 #endif
                break;
        default:
+               fprintf( stderr, "%s: unrecongized option -%c\n",
+                       prog, optopt );
            usage( argv[0] );
            return( EXIT_FAILURE );
        }
     }
 
-       if ( ( authmethod == LDAP_AUTH_KRBV4 ) || ( authmethod ==
-                       LDAP_AUTH_KRBV41 ) ) {
-               if( version > LDAP_VERSION2 ) {
-                       fprintf( stderr, "Kerberos requires LDAPv2\n" );
-                       return( EXIT_FAILURE );
-               }
-               version = LDAP_VERSION2;
-       }
-       else if ( authmethod == LDAP_AUTH_SASL ) {
-               if( version != -1 && version != LDAP_VERSION3 ) {
-                       fprintf( stderr, "SASL requires LDAPv3\n" );
-                       return( EXIT_FAILURE );
-               }
-               version = LDAP_VERSION3;
-       }
-
-       if( manageDSAit ) {
-               if( version != -1 && version != LDAP_VERSION3 ) {
-                       fprintf(stderr, "manage DSA control requires LDAPv3\n");
-                       return EXIT_FAILURE;
-               }
+       if (version == -1) {
                version = LDAP_VERSION3;
        }
-
-       if( use_tls ) {
-               if( version != -1 && version != LDAP_VERSION3 ) {
-                       fprintf(stderr, "Start TLS requires LDAPv3\n");
-                       return EXIT_FAILURE;
-               }
-               version = LDAP_VERSION3;
+       if (authmethod == -1 && version > LDAP_VERSION2) {
+#ifdef HAVE_CYRUS_SASL
+               authmethod = LDAP_AUTH_SASL;
+#else
+               authmethod = LDAP_AUTH_SIMPLE;
+#endif
        }
 
-    if (newSuperior != NULL) {
-               if (version == LDAP_VERSION2) {
-                       fprintf( stderr,
-                               "%s: version conflict!, -s newSuperior requires LDAPv3\n",
-                               myname);
-                       usage( argv[0] );
-                       return( EXIT_FAILURE );
-               }
-               version = LDAP_VERSION3;
-    }
-    
     havedn = 0;
     if (argc - optind == 2) {
        if (( rdn = strdup( argv[argc - 1] )) == NULL ) {
@@ -315,7 +487,8 @@ main(int argc, char **argv)
         }
        ++havedn;
     } else if ( argc - optind != 0 ) {
-       fprintf( stderr, "%s: invalid number of arguments, only two allowed\n", myname);
+       fprintf( stderr, "%s: invalid number of arguments (%d), "
+               "only two allowed\n", prog, argc-optind );
        usage( argv[0] );
        return( EXIT_FAILURE );
     }
@@ -356,10 +529,6 @@ main(int argc, char **argv)
                return EXIT_FAILURE;
        }
 
-       if (version == -1 ) {
-               version = 3;
-       }
-
        if( ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &version )
                != LDAP_OPT_SUCCESS )
        {
@@ -383,41 +552,37 @@ main(int argc, char **argv)
 
        if ( authmethod == LDAP_AUTH_SASL ) {
 #ifdef HAVE_CYRUS_SASL
-               int     minssf = 0, maxssf = 0;
-
-               if ( sasl_integrity > 0 )
-                       maxssf = 1;
-               if ( sasl_integrity > 1 )
-                       minssf = 1;
-               if ( sasl_privacy > 0 )
-                       maxssf = 100000; /* Something big value */
-               if ( sasl_privacy > 1 )
-                       minssf = 56;
-               
-               if ( ldap_set_option( ld, LDAP_OPT_X_SASL_MINSSF,
-                       (void *)&minssf ) != LDAP_OPT_SUCCESS ) {
-                       fprintf( stderr, "Could not set LDAP_OPT_X_SASL_MINSSF"
-                               "%d\n", minssf);
-                       return( EXIT_FAILURE );
-               }
-               if ( ldap_set_option( ld, LDAP_OPT_X_SASL_MAXSSF,
-                       (void *)&maxssf ) != LDAP_OPT_SUCCESS ) {
-                       fprintf( stderr, "Could not set LDAP_OPT_X_SASL_MAXSSF"
-                               "%d\n", maxssf);
-                       return( EXIT_FAILURE );
+               void *defaults;
+
+               if( sasl_secprops != NULL ) {
+                       rc = ldap_set_option( ld, LDAP_OPT_X_SASL_SECPROPS,
+                               (void *) sasl_secprops );
+                       
+                       if( rc != LDAP_OPT_SUCCESS ) {
+                               fprintf( stderr,
+                                       "Could not set LDAP_OPT_X_SASL_SECPROPS: %s\n",
+                                       sasl_secprops );
+                               return( EXIT_FAILURE );
+                       }
                }
                
-               rc = ldap_negotiated_sasl_bind_s( ld, binddn, sasl_authc_id,
-                               sasl_authz_id, sasl_mech,
-                               passwd.bv_len ? &passwd : NULL,
-                               NULL, NULL );
+               defaults = lutil_sasl_defaults( ld,
+                       sasl_mech,
+                       sasl_realm,
+                       sasl_authc_id,
+                       passwd.bv_val,
+                       sasl_authz_id );
+
+               rc = ldap_sasl_interactive_bind_s( ld, binddn,
+                       sasl_mech, NULL, NULL,
+                       sasl_flags, lutil_sasl_interact, defaults );
 
                if( rc != LDAP_SUCCESS ) {
-                       ldap_perror( ld, "ldap_negotiated_sasl_bind_s" );
+                       ldap_perror( ld, "ldap_sasl_interactive_bind_s" );
                        return( EXIT_FAILURE );
                }
 #else
-               fprintf( stderr, "%s was not compiled with SASL support\n",
+               fprintf( stderr, "%s: not compiled with SASL support\n",
                        argv[0] );
                return( EXIT_FAILURE );
 #endif
@@ -509,8 +674,8 @@ static int domodrdn(
                NULL, NULL, &id );
 
        if ( rc != LDAP_SUCCESS ) {
-               fprintf( stderr, "ldapmodrdn: ldap_rename: %s (%d)\n",
-                       ldap_err2string( rc ), rc );
+               fprintf( stderr, "%s: ldap_rename: %s (%d)\n",
+                       prog, ldap_err2string( rc ), rc );
                return rc;
        }
 
@@ -523,8 +688,8 @@ static int domodrdn(
        rc = ldap_parse_result( ld, res, &code, &matcheddn, &text, &refs, NULL, 1 );
 
        if( rc != LDAP_SUCCESS ) {
-               fprintf( stderr, "ldapmodrdn: ldap_parse_result: %s (%d)\n",
-                       ldap_err2string( rc ), rc );
+               fprintf( stderr, "%s: ldap_parse_result: %s (%d)\n",
+                       prog, ldap_err2string( rc ), rc );
                return rc;
        }
 
index 5385aa1d584e8e0ce1006d0bb8330a08ca5b5f0c..32c8650cd3641f6d3c5183e4c027f24f22952f89 100644 (file)
@@ -19,6 +19,7 @@
 
 #include <ldap.h>
 
+#include "lutil_ldap.h"
 #include "ldap_defaults.h"
 
 static int     verbose = 0;
@@ -27,30 +28,34 @@ static void
 usage(const char *s)
 {
        fprintf(stderr,
-"Change the password of an LDAP entry\n\n"
-"usage: %s [options] dn\n"
-"      dn: the DN of the entry whose password must be changed\n"
-"options:\n"
-"      -a secret\told password\n"
-"      -A\t\tprompt for old password\n"
-"      -d level\tdebugging level\n"
-"      -C\t\tchase referrals\n"
-"      -D binddn\tbind DN\n"
-"      -E\t\trequest SASL privacy (-EE to make it critical)\n"
-"      -h host\t\tLDAP server (default: localhost)\n"
-"      -I\t\trequest SASL integrity checking (-II to make it\n"
-"              \tcritical)\n"
-"      -n\t\tmake no modifications\n"
-"      -p port\t\tport on LDAP server\n"
-"      -S\t\tprompt for new password\n"
-"      -s secret\tnew password\n"
-"      -U user\t\tSASL authentication identity (username)\n"
-"      -v\t\tverbose mode\n"
-"      -w passwd\tbind password (for simple authentication)\n"
-"      -W\t\tprompt for bind password\n"
-"      -X id\t\tSASL authorization identity (\"dn:<dn>\" or \"u:<user>\")\n"
-"      -Y mech\t\tSASL mechanism\n"
-"      -Z\t\tissue Start TLS request (-ZZ to require successful response)\n"
+"Change password of an LDAP user\n\n"
+"usage: %s [options] user\n"
+"  user: the identity of the user, normally a DN\n"
+"Password change options:\n"
+"  -a secret  old password\n"
+"  -A         prompt for old password\n"
+"  -s secret  new password\n"
+"  -S         prompt for new password\n"
+
+"Common options:\n"
+"  -d level   set LDAP debugging level to `level'\n"
+"  -D binddn  bind DN\n"
+"  -f file    read operations from `file'\n"
+"  -h host    LDAP server\n"
+"  -I         use SASL Interactive mode\n"
+"  -n         show what would be done but don't actually search\n"
+"  -O props   SASL security properties\n"
+"  -p port    port on LDAP server\n"
+"  -Q         use SASL Quiet mode\n"
+"  -R realm   SASL realm\n"
+"  -U user    SASL authentication identity (username)\n"
+"  -v         run in verbose mode (diagnostics to standard output)\n"
+"  -w passwd  bind passwd (for simple authentication)\n"
+"  -W         prompt for bind passwd\n"
+"  -x         Simple authentication\n"
+"  -X id      SASL authorization identity (\"dn:<dn>\" or \"u:<user>\")\n"
+"  -Y mech    SASL mechanism\n"
+"  -Z         Start TLS request (-ZZ to require successful response)\n"
                , s );
 
        exit( EXIT_FAILURE );
@@ -60,12 +65,13 @@ int
 main( int argc, char *argv[] )
 {
        int rc;
+       char    *prog = NULL;
        char    *ldaphost = NULL;
 
        char    *dn = NULL;
        char    *binddn = NULL;
 
-       struct berval passwd = { 0, NULL};
+       struct berval passwd = { 0, NULL };
        char    *newpw = NULL;
        char    *oldpw = NULL;
 
@@ -73,18 +79,20 @@ main( int argc, char *argv[] )
        int             want_newpw = 0;
        int             want_oldpw = 0;
 
-       int             noupdates = 0;
+       int             not = 0;
        int             i;
        int             ldapport = 0;
        int             debug = 0;
        int             version = -1;
-       int             authmethod = LDAP_AUTH_SIMPLE;
+       int             authmethod = -1;
+       int             manageDSAit = 0;
 #ifdef HAVE_CYRUS_SASL
+       unsigned        sasl_flags = LDAP_SASL_AUTOMATIC;
+       char            *sasl_realm = NULL;
        char            *sasl_authc_id = NULL;
        char            *sasl_authz_id = NULL;
        char            *sasl_mech = NULL;
-       int             sasl_integrity = 0;
-       int             sasl_privacy = 0;
+       char            *sasl_secprops = NULL;
 #endif
        int             use_tls = 0;
        int             referrals = 0;
@@ -97,16 +105,20 @@ main( int argc, char *argv[] )
        char    *retoid = NULL;
        struct berval *retdata = NULL;
 
+    prog = (prog = strrchr(argv[0], *LDAP_DIRSEP)) == NULL ? argv[0] : ++prog;
+
        if (argc == 1)
                usage (argv[0]);
 
        while( (i = getopt( argc, argv,
-               "Aa:CD:d:EIh:np:Ss:U:vWw:X:Y:Z" )) != EOF )
+               "Aa:Ss:" "Cd:D:h:InO:p:QRU:vw:WxX:Y:Z" )) != EOF )
        {
                switch (i) {
-               case 'A':       /* prompt for oldr password */
+               /* Password Options */
+               case 'A':       /* prompt for old password */
                        want_oldpw++;
                        break;
+
                case 'a':       /* old password (secret) */
                        oldpw = strdup (optarg);
 
@@ -114,32 +126,10 @@ main( int argc, char *argv[] )
                                char* p;
 
                                for( p = optarg; *p == '\0'; p++ ) {
-                                       *p = '*';
+                                       *p = '\0';
                                }
                        }
                        break;
-               case 'C':
-                       referrals++;
-                       break;
-               case 'D':       /* bind distinguished name */
-                       binddn = strdup (optarg);
-                       break;
-
-               case 'd':       /* debugging option */
-                       debug |= atoi (optarg);
-                       break;
-
-               case 'h':       /* ldap host */
-                       ldaphost = strdup (optarg);
-                       break;
-
-               case 'n':       /* don't update entry(s) */
-                       noupdates++;
-                       break;
-
-               case 'p':       /* ldap port */
-                       ldapport = strtol( optarg, NULL, 10 );
-                       break;
 
                case 'S':       /* prompt for user password */
                        want_newpw++;
@@ -151,95 +141,330 @@ main( int argc, char *argv[] )
                                char* p;
 
                                for( p = optarg; *p == '\0'; p++ ) {
-                                       *p = '*';
+                                       *p = '\0';
                                }
                        }
                        break;
 
-               case 'v':       /* verbose */
-                       verbose++;
-                       break;
-
-               case 'W':       /* prompt for bind password */
-                       want_bindpw++;
-                       break;
+       /* Common Options (including options we don't use) */
+       case 'C':
+               referrals++;
+               break;
+       case 'd':
+           debug |= atoi( optarg );
+           break;
+       case 'D':       /* bind DN */
+               if( binddn != NULL ) {
+                       fprintf( stderr, "%s: -D previously specified\n" );
+                       return EXIT_FAILURE;
+               }
+           binddn = strdup( optarg );
+           break;
+       case 'h':       /* ldap host */
+               if( ldaphost != NULL ) {
+                       fprintf( stderr, "%s: -h previously specified\n" );
+                       return EXIT_FAILURE;
+               }
+           ldaphost = strdup( optarg );
+           break;
+       case 'I':
+#ifdef HAVE_CYRUS_SASL
+               if( version == LDAP_VERSION2 ) {
+                       fprintf( stderr, "%s: -I incompatible with version %d\n",
+                               prog, version );
+                       return EXIT_FAILURE;
+               }
+               if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
+                       fprintf( stderr, "%s: incompatible previous "
+                               "authentication choice\n",
+                               prog );
+                       return EXIT_FAILURE;
+               }
+               authmethod = LDAP_AUTH_SASL;
+               version = LDAP_VERSION3;
+               sasl_flags = LDAP_SASL_INTERACTIVE;
+               break;
+#else
+               fprintf( stderr, "%s: was not compiled with SASL support\n",
+                       prog );
+               return( EXIT_FAILURE );
+#endif
+       case 'k':       /* kerberos bind */
+#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND
+               if( version > LDAP_VERSION2 ) {
+                       fprintf( stderr, "%s: -k incompatible with LDAPv%d\n",
+                               prog, version );
+                       return EXIT_FAILURE;
+               }
 
-               case 'w':       /* bind password */
-                       passwd.bv_val = strdup (optarg);
-                       {
-                               char* p;
+               if( authmethod != -1 ) {
+                       fprintf( stderr, "%s: -k incompatible with previous "
+                               "authentication choice\n", prog );
+                       return EXIT_FAILURE;
+               }
+                       
+               authmethod = LDAP_AUTH_KRBV4;
+#else
+               fprintf( stderr, "%s: not compiled with Kerberos support\n", prog );
+               return EXIT_FAILURE;
+#endif
+           break;
+       case 'K':       /* kerberos bind, part one only */
+#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND
+               if( version > LDAP_VERSION2 ) {
+                       fprintf( stderr, "%s: -k incompatible with LDAPv%d\n",
+                               prog, version );
+                       return EXIT_FAILURE;
+               }
+               if( authmethod != -1 ) {
+                       fprintf( stderr, "%s: incompatible with previous "
+                               "authentication choice\n", prog );
+                       return EXIT_FAILURE;
+               }
 
-                               for( p = optarg; *p == '\0'; p++ ) {
-                                       *p = '*';
-                               }
+               authmethod = LDAP_AUTH_KRBV41;
+#else
+               fprintf( stderr, "%s: not compiled with Kerberos support\n", prog );
+               return( EXIT_FAILURE );
+#endif
+           break;
+       case 'M':
+               /* enable Manage DSA IT */
+               if( version == LDAP_VERSION2 ) {
+                       fprintf( stderr, "%s: -M incompatible with LDAPv%d\n",
+                               prog, version );
+                       return EXIT_FAILURE;
+               }
+               manageDSAit++;
+               version = LDAP_VERSION3;
+               break;
+       case 'n':       /* print deletes, don't actually do them */
+           ++not;
+           break;
+       case 'O':
+#ifdef HAVE_CYRUS_SASL
+               if( sasl_secprops != NULL ) {
+                       fprintf( stderr, "%s: -O previously specified\n" );
+                       return EXIT_FAILURE;
+               }
+               if( version == LDAP_VERSION2 ) {
+                       fprintf( stderr, "%s: -O incompatible with LDAPv%d\n",
+                               prog, version );
+                       return EXIT_FAILURE;
+               }
+               if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
+                       fprintf( stderr, "%s: incompatible previous "
+                               "authentication choice\n", prog );
+                       return EXIT_FAILURE;
+               }
+               authmethod = LDAP_AUTH_SASL;
+               version = LDAP_VERSION3;
+               sasl_secprops = strdup( optarg );
+#else
+               fprintf( stderr, "%s: not compiled with SASL support\n",
+                       prog );
+               return( EXIT_FAILURE );
+#endif
+               break;
+       case 'p':
+               if( ldapport ) {
+                       fprintf( stderr, "%s: -p previously specified\n" );
+                       return EXIT_FAILURE;
+               }
+           ldapport = atoi( optarg );
+           break;
+       case 'P':
+               switch( atoi(optarg) ) {
+               case 2:
+                       if( version == LDAP_VERSION3 ) {
+                               fprintf( stderr, "%s: -P 2 incompatible with version %d\n",
+                                       prog, version );
+                               return EXIT_FAILURE;
                        }
-                       passwd.bv_len = strlen( passwd.bv_val );
+                       version = LDAP_VERSION2;
                        break;
-
-               case 'I':
+               case 3:
+                       if( version == LDAP_VERSION2 ) {
+                               fprintf( stderr, "%s: -P 2 incompatible with version %d\n",
+                                       prog, version );
+                               return EXIT_FAILURE;
+                       }
+                       version = LDAP_VERSION3;
+                       break;
+               default:
+                       fprintf( stderr, "%s: protocol version should be 2 or 3\n",
+                               prog );
+                       usage( prog );
+                       return( EXIT_FAILURE );
+               } break;
+       case 'Q':
 #ifdef HAVE_CYRUS_SASL
-                       sasl_integrity++;
-                       authmethod = LDAP_AUTH_SASL;
+               if( version == LDAP_VERSION2 ) {
+                       fprintf( stderr, "%s: -Q incompatible with version %d\n",
+                               prog, version );
+                       return EXIT_FAILURE;
+               }
+               if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
+                       fprintf( stderr, "%s: incompatible previous "
+                               "authentication choice\n",
+                               prog );
+                       return EXIT_FAILURE;
+               }
+               authmethod = LDAP_AUTH_SASL;
+               version = LDAP_VERSION3;
+               sasl_flags = LDAP_SASL_QUIET;
+               break;
 #else
-                       fprintf( stderr, "%s was not compiled with SASL "
-                               "support\n", argv[0] );
-                       return( EXIT_FAILURE );
+               fprintf( stderr, "%s: not compiled with SASL support\n",
+                       prog );
+               return( EXIT_FAILURE );
 #endif
-                       break;
-               case 'E':
+       case 'R':
 #ifdef HAVE_CYRUS_SASL
-                       sasl_privacy++;
-                       authmethod = LDAP_AUTH_SASL;
+               if( sasl_realm != NULL ) {
+                       fprintf( stderr, "%s: -R previously specified\n" );
+                       return EXIT_FAILURE;
+               }
+               if( version == LDAP_VERSION2 ) {
+                       fprintf( stderr, "%s: -R incompatible with version %d\n",
+                               prog, version );
+                       return EXIT_FAILURE;
+               }
+               if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
+                       fprintf( stderr, "%s: incompatible previous "
+                               "authentication choice\n",
+                               prog );
+                       return EXIT_FAILURE;
+               }
+               authmethod = LDAP_AUTH_SASL;
+               version = LDAP_VERSION3;
+               sasl_realm = strdup( optarg );
 #else
-                       fprintf( stderr, "%s was not compiled with SASL "
-                               "support\n", argv[0] );
-                       return( EXIT_FAILURE );
+               fprintf( stderr, "%s: not compiled with SASL support\n",
+                       prog );
+               return( EXIT_FAILURE );
 #endif
-                       break;
-               case 'Y':
+               break;
+       case 'U':
 #ifdef HAVE_CYRUS_SASL
-                       if ( strcasecmp( optarg, "any" ) &&
-                                       strcmp( optarg, "*" ) ) {
-                               sasl_mech = strdup( optarg );
-                       }
-                       authmethod = LDAP_AUTH_SASL;
+               if( sasl_authc_id != NULL ) {
+                       fprintf( stderr, "%s: -U previously specified\n" );
+                       return EXIT_FAILURE;
+               }
+               if( version == LDAP_VERSION2 ) {
+                       fprintf( stderr, "%s: -U incompatible with version %d\n",
+                               prog, version );
+                       return EXIT_FAILURE;
+               }
+               if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
+                       fprintf( stderr, "%s: incompatible previous "
+                               "authentication choice\n",
+                               prog );
+                       return EXIT_FAILURE;
+               }
+               authmethod = LDAP_AUTH_SASL;
+               version = LDAP_VERSION3;
+               sasl_authc_id = strdup( optarg );
 #else
-                       fprintf( stderr, "%s was not compiled with SASL "
-                               "support\n", argv[0] );
-                       return( EXIT_FAILURE );
+               fprintf( stderr, "%s: not compiled with SASL support\n",
+                       prog );
+               return( EXIT_FAILURE );
 #endif
-                       break;
-               case 'U':
+               break;
+       case 'v':       /* verbose mode */
+           verbose++;
+           break;
+       case 'w':       /* password */
+           passwd.bv_val = strdup( optarg );
+               {
+                       char* p;
+
+                       for( p = optarg; *p == '\0'; p++ ) {
+                               *p = '\0';
+                       }
+               }
+               passwd.bv_len = strlen( passwd.bv_val );
+           break;
+       case 'W':
+               want_bindpw++;
+               break;
+       case 'Y':
 #ifdef HAVE_CYRUS_SASL
-                       sasl_authc_id = strdup( optarg );
-                       authmethod = LDAP_AUTH_SASL;
+               if( sasl_mech != NULL ) {
+                       fprintf( stderr, "%s: -Y previously specified\n" );
+                       return EXIT_FAILURE;
+               }
+               if( version == LDAP_VERSION2 ) {
+                       fprintf( stderr, "%s: -Y incompatible with version %d\n",
+                               prog, version );
+                       return EXIT_FAILURE;
+               }
+               if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
+                       fprintf( stderr, "%s: incompatible with authentication choice\n", prog );
+                       return EXIT_FAILURE;
+               }
+               authmethod = LDAP_AUTH_SASL;
+               version = LDAP_VERSION3;
+               sasl_mech = strdup( optarg );
 #else
-                       fprintf( stderr, "%s was not compiled with SASL "
-                               "support\n", argv[0] );
-                       return( EXIT_FAILURE );
+               fprintf( stderr, "%s: not compiled with SASL support\n",
+                       prog );
+               return( EXIT_FAILURE );
 #endif
-                       break;
-               case 'X':
+               break;
+       case 'x':
+               if( authmethod != -1 && authmethod != LDAP_AUTH_SIMPLE ) {
+                       fprintf( stderr, "%s: incompatible with previous "
+                               "authentication choice\n", prog );
+                       return EXIT_FAILURE;
+               }
+               authmethod = LDAP_AUTH_SIMPLE;
+               break;
+       case 'X':
 #ifdef HAVE_CYRUS_SASL
-                       sasl_authz_id = strdup( optarg );
-                       authmethod = LDAP_AUTH_SASL;
+               if( sasl_authz_id != NULL ) {
+                       fprintf( stderr, "%s: -X previously specified\n" );
+                       return EXIT_FAILURE;
+               }
+               if( version == LDAP_VERSION2 ) {
+                       fprintf( stderr, "%s: -X incompatible with LDAPv%d\n",
+                               prog, version );
+                       return EXIT_FAILURE;
+               }
+               if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
+                       fprintf( stderr, "%s: -X incompatible with "
+                               "authentication choice\n", prog );
+                       return EXIT_FAILURE;
+               }
+               authmethod = LDAP_AUTH_SASL;
+               version = LDAP_VERSION3;
+               sasl_authz_id = strdup( optarg );
 #else
-                       fprintf( stderr, "%s was not compiled with SASL "
-                               "support\n", argv[0] );
-                       return( EXIT_FAILURE );
+               fprintf( stderr, "%s: not compiled with SASL support\n",
+                       prog );
+               return( EXIT_FAILURE );
 #endif
-                       break;
-               case 'Z':
+               break;
+       case 'Z':
 #ifdef HAVE_TLS
-                       use_tls++;
+               if( version == LDAP_VERSION2 ) {
+                       fprintf( stderr, "%s: -Z incompatible with version %d\n",
+                               prog, version );
+                       return EXIT_FAILURE;
+               }
+               version = LDAP_VERSION3;
+               use_tls++;
 #else
-                       fprintf( stderr, "%s was not compiled with TLS "
-                               "support\n", argv[0] );
-                       return( EXIT_FAILURE );
+               fprintf( stderr, "%s: not compiled with TLS support\n",
+                       prog );
+               return( EXIT_FAILURE );
 #endif
-                       break;
+               break;
+
 
                default:
+                       fprintf( stderr, "%s: unrecongized option -%c\n",
+                               prog, optopt );
                        usage (argv[0]);
                }
        }
@@ -248,6 +473,14 @@ main( int argc, char *argv[] )
                usage( argv[0] );
        } 
 
+       if (authmethod == -1) {
+#ifdef HAVE_CYRUS_SASL
+               authmethod = LDAP_AUTH_SASL;
+#else
+               authmethod = LDAP_AUTH_SIMPLE;
+#endif
+       }
+
        dn = strdup( argv[optind] );
 
        if( want_oldpw && oldpw == NULL ) {
@@ -342,41 +575,37 @@ main( int argc, char *argv[] )
 
        if ( authmethod == LDAP_AUTH_SASL ) {
 #ifdef HAVE_CYRUS_SASL
-               int     minssf = 0, maxssf = 0;
-
-               if ( sasl_integrity > 0 )
-                       maxssf = 1;
-               if ( sasl_integrity > 1 )
-                       minssf = 1;
-               if ( sasl_privacy > 0 )
-                       maxssf = 100000; /* Something big value */
-               if ( sasl_privacy > 1 )
-                       minssf = 56;
-               
-               if ( ldap_set_option( ld, LDAP_OPT_X_SASL_MINSSF,
-                               (void *)&minssf ) != LDAP_OPT_SUCCESS ) {
-                       fprintf( stderr, "Could not set LDAP_OPT_X_SASL_MINSSF"
-                               "%d\n", minssf);
-                       return( EXIT_FAILURE );
-               }
-               if ( ldap_set_option( ld, LDAP_OPT_X_SASL_MAXSSF,
-                               (void *)&maxssf ) != LDAP_OPT_SUCCESS ) {
-                       fprintf( stderr, "Could not set LDAP_OPT_X_SASL_MAXSSF"
-                               "%d\n", maxssf);
-                       return( EXIT_FAILURE );
+               void *defaults;
+
+               if( sasl_secprops != NULL ) {
+                       rc = ldap_set_option( ld, LDAP_OPT_X_SASL_SECPROPS,
+                               (void *) sasl_secprops );
+                       
+                       if( rc != LDAP_OPT_SUCCESS ) {
+                               fprintf( stderr,
+                                       "Could not set LDAP_OPT_X_SASL_SECPROPS: %s\n",
+                                       sasl_secprops );
+                               return( EXIT_FAILURE );
+                       }
                }
                
-               rc = ldap_negotiated_sasl_bind_s( ld, binddn, sasl_authc_id,
-                               sasl_authz_id, sasl_mech,
-                               passwd.bv_len ? &passwd : NULL,
-                               NULL, NULL );
+               defaults = lutil_sasl_defaults( ld,
+                       sasl_mech,
+                       sasl_realm,
+                       sasl_authc_id,
+                       passwd.bv_val,
+                       sasl_authz_id );
+
+               rc = ldap_sasl_interactive_bind_s( ld, binddn,
+                       sasl_mech, NULL, NULL,
+                       sasl_flags, lutil_sasl_interact, defaults );
 
                if( rc != LDAP_SUCCESS ) {
-                       ldap_perror( ld, "ldap_negotiated_sasl_bind_s" );
+                       ldap_perror( ld, "ldap_sasl_interactive_bind_s" );
                        return( EXIT_FAILURE );
                }
 #else
-               fprintf( stderr, "%s was not compiled with SASL support\n",
+               fprintf( stderr, "%s: not compiled with SASL support\n",
                        argv[0] );
                return( EXIT_FAILURE );
 #endif
@@ -432,7 +661,7 @@ main( int argc, char *argv[] )
                ber_free( ber, 1 );
        }
 
-       if ( noupdates ) {
+       if ( not ) {
                rc = LDAP_SUCCESS;
                goto skip;
        }
index a07370ecb631df5aae3b254759eac4b7e61a1265..9c4c434cdd7f7718c349d25c6303d1eaf09cb539 100644 (file)
@@ -31,6 +31,7 @@
 
 #include "ldif.h"
 #include "lutil.h"
+#include "lutil_ldap.h"
 #include "ldap_defaults.h"
 
 static void
@@ -38,50 +39,55 @@ usage( const char *s )
 {
        fprintf( stderr,
 "usage: %s [options] [filter [attributes...]]\nwhere:\n"
-"\tfilter\tRFC-2254 compliant LDAP search filter\n"
-"\tattributes\twhitespace-separated list of attribute descriptions\n"
-"\t  which may include:\n"
-"\t\t1.1 -- no attributes\n"
-"\t\t*   -- all user attributes\n"
-"\t\t+   -- all operational attributes\n"
-"options:\n"
-"\t-a deref\tdereference aliases: never (default), always, search, or find\n"
-"\t-A\t\tretrieve attribute names only (no values)\n"
-"\t-b basedn\tbase dn for search\n"
-"\t-d level\tset LDAP debugging level to `level'\n"
-"\t-D binddn\tbind DN\n"
-"\t-E\t\trequest SASL privacy (-EE to make it critical)\n"
-"\t-f file\t\tperform sequence of searches listed in `file'\n"
-"\t-h host\t\tLDAP server\n"
-"\t-I\t\trequest SASL integrity checking (-II to make it\n"
-"\t\t\tcritical)\n"
-"\t-k\t\tuse Kerberos authentication\n"
-"\t-K\t\tlike -k, but do only step 1 of the Kerberos bind\n"
-"\t-l limit\ttime limit (in seconds) for search\n"
-"\t-L\t\tprint responses in LDIFv1 format\n"
-"\t-LL\t\tprint responses in LDIF format without comments\n"
-"\t-LLL\t\tprint responses in LDIF format without comments\n"
-"\t\t\tand version\n"
-"\t-M\t\tenable Manage DSA IT control (-MM to make critical)\n"
-"\t-n\t\tshow what would be done but don't actually search\n"
-"\t-p port\t\tport on LDAP server\n"
-"\t-P version\tprocotol version (default: 3)\n"
-"\t-s scope\tone of base, one, or sub (search scope)\n"
-"\t-S attr\t\tsort the results by attribute `attr'\n"
-"\t-t\t\twrite binary values to files in temporary directory\n"
-"\t-tt\t\twrite all values to files in temporary directory\n"
-"\t-T path\t\twrite files to directory specified by path (default:\n"
-"\t\t\t\"" LDAP_TMPDIR "\")\n"
-"\t-u\t\tinclude User Friendly entry names in the output\n"
-"\t-U user\t\tSASL authentication identity (username)\n"
-"\t-v\t\trun in verbose mode (diagnostics to standard output)\n"
-"\t-V prefix\tURL prefix for files (default: \"" LDAP_FILE_URI_PREFIX ")\n"
-"\t-w passwd\tbind passwd (for simple authentication)\n"
-"\t-W\t\tprompt for bind passwd\n"
-"\t-X id\t\tSASL authorization identity (\"dn:<dn>\" or \"u:<user>\")\n"
-"\t-Y mech\t\tSASL mechanism\n"
-"\t-z limit\tsize limit (in entries) for search\n"
-"\t-Z\t\tissue Start TLS request (-ZZ to require successful response)\n"
+"  filter\tRFC-2254 compliant LDAP search filter\n"
+"  attributes\twhitespace-separated list of attribute descriptions\n"
+"    which may include:\n"
+"      1.1   no attributes\n"
+"      *     all user attributes\n"
+"      +     all operational attributes\n"
+
+"Search options:\n"
+"  -a deref   one of never (default), always, search, or find\n"
+"  -A         retrieve attribute names only (no values)\n"
+"  -b basedn  base dn for search\n"
+"  -l limit   time limit (in seconds) for search\n"
+"  -L         print responses in LDIFv1 format\n"
+"  -LL        print responses in LDIF format without comments\n"
+"  -LLL       print responses in LDIF format without comments\n"
+"             and version\n"
+"  -s scope   one of base, one, or sub (search scope)\n"
+"  -S attr    sort the results by attribute `attr'\n"
+"  -t         write binary values to files in temporary directory\n"
+"  -tt        write all values to files in temporary directory\n"
+"  -T path    write files to directory specified by path (default:\n"
+"             " LDAP_TMPDIR ")\n"
+"  -u         include User Friendly entry names in the output\n"
+"  -V prefix  URL prefix for files (default: \"" LDAP_FILE_URI_PREFIX ")\n"
+"  -z limit   size limit (in entries) for search\n"
+
+"Common options:\n"
+"  -d level   set LDAP debugging level to `level'\n"
+"  -D binddn  bind DN\n"
+"  -f file    read operations from `file'\n"
+"  -h host    LDAP server\n"
+"  -I         use SASL Interactive mode\n"
+"  -k         use Kerberos authentication\n"
+"  -K         like -k, but do only step 1 of the Kerberos bind\n"
+"  -M         enable Manage DSA IT control (-MM to make critical)\n"
+"  -n         show what would be done but don't actually search\n"
+"  -O props   SASL security properties\n"
+"  -p port    port on LDAP server\n"
+"  -P version procotol version (default: 3)\n"
+"  -Q         use SASL Quiet mode\n"
+"  -R realm   SASL realm\n"
+"  -U user    SASL authentication identity (username)\n"
+"  -v         run in verbose mode (diagnostics to standard output)\n"
+"  -w passwd  bind passwd (for simple authentication)\n"
+"  -W         prompt for bind passwd\n"
+"  -x         Simple authentication\n"
+"  -X id      SASL authorization identity (\"dn:<dn>\" or \"u:<user>\")\n"
+"  -Y mech    SASL mechanism\n"
+"  -Z         Start TLS request (-ZZ to require successful response)\n"
 , s );
 
        exit( EXIT_FAILURE );
@@ -134,17 +140,19 @@ static int dosearch LDAP_P((
 static char *tmpdir = NULL;
 static char *urlpre = NULL;
 
+static char *prog = NULL;
 static char    *binddn = NULL;
 static struct berval passwd = { 0, NULL };
 static char    *base = NULL;
 static char    *ldaphost = NULL;
 static int     ldapport = 0;
 #ifdef HAVE_CYRUS_SASL
+static unsigned sasl_flags = LDAP_SASL_AUTOMATIC;
+static char    *sasl_realm = NULL;
 static char    *sasl_authc_id = NULL;
 static char    *sasl_authz_id = NULL;
 static char    *sasl_mech = NULL;
-static int     sasl_integrity = 0;
-static int     sasl_privacy = 0;
+static char    *sasl_secprops = NULL;
 #endif
 static int     use_tls = 0;
 static char    *sortattr = NULL;
@@ -167,60 +175,48 @@ main( int argc, char **argv )
        deref = sizelimit = timelimit = version = -1;
 
        scope = LDAP_SCOPE_SUBTREE;
-       authmethod = LDAP_AUTH_SIMPLE;
+       authmethod = -1;
+
+    prog = (prog = strrchr(argv[0], *LDAP_DIRSEP)) == NULL ? argv[0] : ++prog;
 
        while (( i = getopt( argc, argv,
-               "Aa:b:CD:d:Ef:h:IKkLl:MnP:p:RS:s:T:tU:uV:vWw:X:Y:Zz:")) != EOF )
+               "Aa:b:f:Ll:S:s:T:tuV:z:" "Cd:D:h:IkKMnO:p:P:QRU:vw:WxX:Y:Z")) != EOF )
        {
        switch( i ) {
-       case 'n':       /* do nothing */
-               ++not;
-               break;
-       case 'v':       /* verbose mode */
-               ++verbose;
-               break;
-       case 'd':
-               debug |= atoi( optarg );
-               break;
-       case 'k':       /* use kerberos bind */
-#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND
-               authmethod = LDAP_AUTH_KRBV4;
-#else
-               fprintf( stderr, "%s was not compiled with Kerberos support\n", argv[0] );
-               return( EXIT_FAILURE );
-#endif
-               break;
-       case 'K':       /* use kerberos bind, 1st part only */
-#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND
-               authmethod = LDAP_AUTH_KRBV41;
-#else
-               fprintf( stderr, "%s was not compiled with Kerberos support\n", argv[0] );
-               return( EXIT_FAILURE );
-#endif
-               break;
-               break;
-       case 'u':       /* include UFN */
-               ++includeufn;
-               break;
-       case 't':       /* write attribute values to TMPDIR files */
-               ++vals2tmp;
+       /* Search Options */
+       case 'a':       /* set alias deref option */
+               if ( strcasecmp( optarg, "never" ) == 0 ) {
+               deref = LDAP_DEREF_NEVER;
+               } else if ( strncasecmp( optarg, "search", sizeof("search")-1 ) == 0 ) {
+               deref = LDAP_DEREF_SEARCHING;
+               } else if ( strncasecmp( optarg, "find", sizeof("find")-1 ) == 0 ) {
+               deref = LDAP_DEREF_FINDING;
+               } else if ( strcasecmp( optarg, "always" ) == 0 ) {
+               deref = LDAP_DEREF_ALWAYS;
+               } else {
+               fprintf( stderr, "alias deref should be never, search, find, or always\n" );
+               usage( argv[ 0 ] );
+               }
                break;
-       case 'M':
-               /* enable Manage DSA IT */
-               manageDSAit++;
+       case 'A':       /* retrieve attribute names only -- no values */
+               ++attrsonly;
                break;
-       case 'C':
-               referrals++;
+       case 'b': /* search base */
+               base = strdup( optarg );
                break;
-       case 'R':       /* ignore */
+       case 'f':       /* input file */
+               if( infile != NULL ) {
+                       fprintf( stderr, "%s: -f previously specified\n" );
+                       return EXIT_FAILURE;
+               }
+               infile = strdup( optarg );
                break;
-       case 'A':       /* retrieve attribute names only -- no values */
-               ++attrsonly;
+       case 'l':       /* time limit */
+               timelimit = atoi( optarg );
                break;
        case 'L':       /* print entries in LDIF format */
                ++ldif;
                break;
-
        case 's':       /* search scope */
                if ( strcasecmp( optarg, "base" ) == 0 ) {
                scope = LDAP_SCOPE_BASE;
@@ -233,22 +229,15 @@ main( int argc, char **argv )
                usage( argv[ 0 ] );
                }
                break;
-
-       case 'a':       /* set alias deref option */
-               if ( strcasecmp( optarg, "never" ) == 0 ) {
-               deref = LDAP_DEREF_NEVER;
-               } else if ( strncasecmp( optarg, "search", sizeof("search")-1 ) == 0 ) {
-               deref = LDAP_DEREF_SEARCHING;
-               } else if ( strncasecmp( optarg, "find", sizeof("find")-1 ) == 0 ) {
-               deref = LDAP_DEREF_FINDING;
-               } else if ( strcasecmp( optarg, "always" ) == 0 ) {
-               deref = LDAP_DEREF_ALWAYS;
-               } else {
-               fprintf( stderr, "alias deref should be never, search, find, or always\n" );
-               usage( argv[ 0 ] );
-               }
+       case 'S':       /* sort attribute */
+               sortattr = strdup( optarg );
+               break;
+       case 'u':       /* include UFN */
+               ++includeufn;
+               break;
+       case 't':       /* write attribute values to TMPDIR files */
+               ++vals2tmp;
                break;
-               
        case 'T':       /* tmpdir */
                if( tmpdir ) free( tmpdir );
                tmpdir = strdup( optarg );
@@ -257,157 +246,346 @@ main( int argc, char **argv )
                if( urlpre ) free( urlpre );
                urlpre = strdup( optarg );
                break;
-       case 'f':       /* input file */
-               infile = strdup( optarg );
-               break;
-       case 'h':       /* ldap host */
-               ldaphost = strdup( optarg );
+       case 'z':       /* size limit */
+               sizelimit = atoi( optarg );
                break;
-       case 'b':       /* search base */
-               base = strdup( optarg );
+
+       /* Common Options */
+       case 'C':
+               referrals++;
                break;
+       case 'd':
+           debug |= atoi( optarg );
+           break;
        case 'D':       /* bind DN */
-               binddn = strdup( optarg );
-               break;
-       case 'p':       /* ldap port */
-               ldapport = atoi( optarg );
+               if( binddn != NULL ) {
+                       fprintf( stderr, "%s: -D previously specified\n" );
+                       return EXIT_FAILURE;
+               }
+           binddn = strdup( optarg );
+           break;
+       case 'h':       /* ldap host */
+               if( ldaphost != NULL ) {
+                       fprintf( stderr, "%s: -h previously specified\n" );
+                       return EXIT_FAILURE;
+               }
+           ldaphost = strdup( optarg );
+           break;
+       case 'I':
+#ifdef HAVE_CYRUS_SASL
+               if( version == LDAP_VERSION2 ) {
+                       fprintf( stderr, "%s: -I incompatible with version %d\n",
+                               prog, version );
+                       return EXIT_FAILURE;
+               }
+               if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
+                       fprintf( stderr, "%s: incompatible previous "
+                               "authentication choice\n",
+                               prog );
+                       return EXIT_FAILURE;
+               }
+               authmethod = LDAP_AUTH_SASL;
+               version = LDAP_VERSION3;
+               sasl_flags = LDAP_SASL_INTERACTIVE;
                break;
-       case 'w':       /* bind password */
-               passwd.bv_val = strdup( optarg );
-               {
-                       char* p;
+#else
+               fprintf( stderr, "%s: was not compiled with SASL support\n",
+                       prog );
+               return( EXIT_FAILURE );
+#endif
+       case 'k':       /* kerberos bind */
+#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND
+               if( version > LDAP_VERSION2 ) {
+                       fprintf( stderr, "%s: -k incompatible with LDAPv%d\n",
+                               prog, version );
+                       return EXIT_FAILURE;
+               }
 
-                       for( p = optarg; *p == '\0'; p++ ) {
-                               *p = '*';
-                       }
+               if( authmethod != -1 ) {
+                       fprintf( stderr, "%s: -k incompatible with previous "
+                               "authentication choice\n", prog );
+                       return EXIT_FAILURE;
                }
-               passwd.bv_len = strlen( passwd.bv_val );
-               break;
-       case 'l':       /* time limit */
-               timelimit = atoi( optarg );
-               break;
-       case 'z':       /* size limit */
-               sizelimit = atoi( optarg );
-               break;
-       case 'S':       /* sort attribute */
-               sortattr = strdup( optarg );
+                       
+               authmethod = LDAP_AUTH_KRBV4;
+#else
+               fprintf( stderr, "%s: not compiled with Kerberos support\n", prog );
+               return EXIT_FAILURE;
+#endif
+           break;
+       case 'K':       /* kerberos bind, part one only */
+#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND
+               if( version > LDAP_VERSION2 ) {
+                       fprintf( stderr, "%s: -k incompatible with LDAPv%d\n",
+                               prog, version );
+                       return EXIT_FAILURE;
+               }
+               if( authmethod != -1 ) {
+                       fprintf( stderr, "%s: incompatible with previous "
+                               "authentication choice\n", prog );
+                       return EXIT_FAILURE;
+               }
+
+               authmethod = LDAP_AUTH_KRBV41;
+#else
+               fprintf( stderr, "%s: not compiled with Kerberos support\n", prog );
+               return( EXIT_FAILURE );
+#endif
+           break;
+       case 'M':
+               /* enable Manage DSA IT */
+               if( version == LDAP_VERSION2 ) {
+                       fprintf( stderr, "%s: -M incompatible with LDAPv%d\n",
+                               prog, version );
+                       return EXIT_FAILURE;
+               }
+               manageDSAit++;
+               version = LDAP_VERSION3;
                break;
-       case 'W':
-               want_bindpw++;
+       case 'n':       /* print deletes, don't actually do them */
+           ++not;
+           break;
+       case 'O':
+#ifdef HAVE_CYRUS_SASL
+               if( sasl_secprops != NULL ) {
+                       fprintf( stderr, "%s: -O previously specified\n" );
+                       return EXIT_FAILURE;
+               }
+               if( version == LDAP_VERSION2 ) {
+                       fprintf( stderr, "%s: -O incompatible with LDAPv%d\n",
+                               prog, version );
+                       return EXIT_FAILURE;
+               }
+               if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
+                       fprintf( stderr, "%s: incompatible previous "
+                               "authentication choice\n", prog );
+                       return EXIT_FAILURE;
+               }
+               authmethod = LDAP_AUTH_SASL;
+               version = LDAP_VERSION3;
+               sasl_secprops = strdup( optarg );
+#else
+               fprintf( stderr, "%s: not compiled with SASL support\n",
+                       prog );
+               return( EXIT_FAILURE );
+#endif
                break;
+       case 'p':
+               if( ldapport ) {
+                       fprintf( stderr, "%s: -p previously specified\n" );
+                       return EXIT_FAILURE;
+               }
+           ldapport = atoi( optarg );
+           break;
        case 'P':
-               switch( atoi( optarg ) )
-               {
+               switch( atoi(optarg) ) {
                case 2:
+                       if( version == LDAP_VERSION3 ) {
+                               fprintf( stderr, "%s: -P 2 incompatible with version %d\n",
+                                       prog, version );
+                               return EXIT_FAILURE;
+                       }
                        version = LDAP_VERSION2;
                        break;
                case 3:
+                       if( version == LDAP_VERSION2 ) {
+                               fprintf( stderr, "%s: -P 2 incompatible with version %d\n",
+                                       prog, version );
+                               return EXIT_FAILURE;
+                       }
                        version = LDAP_VERSION3;
                        break;
                default:
-                       fprintf( stderr, "protocol version should be 2 or 3\n" );
-                       usage( argv[0] );
-               }
-               break;
-       case 'I':
+                       fprintf( stderr, "%s: protocol version should be 2 or 3\n",
+                               prog );
+                       usage( prog );
+                       return( EXIT_FAILURE );
+               } break;
+       case 'Q':
 #ifdef HAVE_CYRUS_SASL
-               sasl_integrity++;
+               if( version == LDAP_VERSION2 ) {
+                       fprintf( stderr, "%s: -Q incompatible with version %d\n",
+                               prog, version );
+                       return EXIT_FAILURE;
+               }
+               if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
+                       fprintf( stderr, "%s: incompatible previous "
+                               "authentication choice\n",
+                               prog );
+                       return EXIT_FAILURE;
+               }
                authmethod = LDAP_AUTH_SASL;
+               version = LDAP_VERSION3;
+               sasl_flags = LDAP_SASL_QUIET;
+               break;
 #else
-               fprintf( stderr, "%s was not compiled with SASL support\n",
-                       argv[0] );
+               fprintf( stderr, "%s: not compiled with SASL support\n",
+                       prog );
                return( EXIT_FAILURE );
 #endif
-               break;
-       case 'E':
+       case 'R':
 #ifdef HAVE_CYRUS_SASL
-               sasl_privacy++;
+               if( sasl_realm != NULL ) {
+                       fprintf( stderr, "%s: -R previously specified\n" );
+                       return EXIT_FAILURE;
+               }
+               if( version == LDAP_VERSION2 ) {
+                       fprintf( stderr, "%s: -R incompatible with version %d\n",
+                               prog, version );
+                       return EXIT_FAILURE;
+               }
+               if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
+                       fprintf( stderr, "%s: incompatible previous "
+                               "authentication choice\n",
+                               prog );
+                       return EXIT_FAILURE;
+               }
                authmethod = LDAP_AUTH_SASL;
+               version = LDAP_VERSION3;
+               sasl_realm = strdup( optarg );
 #else
-               fprintf( stderr, "%s was not compiled with SASL support\n",
-                       argv[0] );
+               fprintf( stderr, "%s: not compiled with SASL support\n",
+                       prog );
                return( EXIT_FAILURE );
 #endif
                break;
-       case 'Y':
+       case 'U':
 #ifdef HAVE_CYRUS_SASL
-               if ( strcasecmp( optarg, "any" ) && strcmp( optarg, "*" ) ) {
-                       sasl_mech = strdup( optarg );
+               if( sasl_authc_id != NULL ) {
+                       fprintf( stderr, "%s: -U previously specified\n" );
+                       return EXIT_FAILURE;
+               }
+               if( version == LDAP_VERSION2 ) {
+                       fprintf( stderr, "%s: -U incompatible with version %d\n",
+                               prog, version );
+                       return EXIT_FAILURE;
+               }
+               if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
+                       fprintf( stderr, "%s: incompatible previous "
+                               "authentication choice\n",
+                               prog );
+                       return EXIT_FAILURE;
                }
                authmethod = LDAP_AUTH_SASL;
+               version = LDAP_VERSION3;
+               sasl_authc_id = strdup( optarg );
 #else
-               fprintf( stderr, "%s was not compiled with SASL support\n",
-                       argv[0] );
+               fprintf( stderr, "%s: not compiled with SASL support\n",
+                       prog );
                return( EXIT_FAILURE );
 #endif
                break;
-       case 'U':
+       case 'v':       /* verbose mode */
+           verbose++;
+           break;
+       case 'w':       /* password */
+           passwd.bv_val = strdup( optarg );
+               {
+                       char* p;
+
+                       for( p = optarg; *p == '\0'; p++ ) {
+                               *p = '\0';
+                       }
+               }
+               passwd.bv_len = strlen( passwd.bv_val );
+           break;
+       case 'W':
+               want_bindpw++;
+               break;
+       case 'Y':
 #ifdef HAVE_CYRUS_SASL
-               sasl_authc_id = strdup( optarg );
+               if( sasl_mech != NULL ) {
+                       fprintf( stderr, "%s: -Y previously specified\n" );
+                       return EXIT_FAILURE;
+               }
+               if( version == LDAP_VERSION2 ) {
+                       fprintf( stderr, "%s: -Y incompatible with version %d\n",
+                               prog, version );
+                       return EXIT_FAILURE;
+               }
+               if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
+                       fprintf( stderr, "%s: incompatible with authentication choice\n", prog );
+                       return EXIT_FAILURE;
+               }
                authmethod = LDAP_AUTH_SASL;
+               version = LDAP_VERSION3;
+               sasl_mech = strdup( optarg );
 #else
-               fprintf( stderr, "%s was not compiled with SASL support\n",
-                       argv[0] );
+               fprintf( stderr, "%s: not compiled with SASL support\n",
+                       prog );
                return( EXIT_FAILURE );
 #endif
                break;
+       case 'x':
+               if( authmethod != -1 && authmethod != LDAP_AUTH_SIMPLE ) {
+                       fprintf( stderr, "%s: incompatible with previous "
+                               "authentication choice\n", prog );
+                       return EXIT_FAILURE;
+               }
+               authmethod = LDAP_AUTH_SIMPLE;
+               break;
        case 'X':
 #ifdef HAVE_CYRUS_SASL
-               sasl_authz_id = strdup( optarg );
+               if( sasl_authz_id != NULL ) {
+                       fprintf( stderr, "%s: -X previously specified\n" );
+                       return EXIT_FAILURE;
+               }
+               if( version == LDAP_VERSION2 ) {
+                       fprintf( stderr, "%s: -X incompatible with LDAPv%d\n",
+                               prog, version );
+                       return EXIT_FAILURE;
+               }
+               if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
+                       fprintf( stderr, "%s: -X incompatible with "
+                               "authentication choice\n", prog );
+                       return EXIT_FAILURE;
+               }
                authmethod = LDAP_AUTH_SASL;
+               version = LDAP_VERSION3;
+               sasl_authz_id = strdup( optarg );
 #else
-               fprintf( stderr, "%s was not compiled with SASL support\n",
-                       argv[0] );
+               fprintf( stderr, "%s: not compiled with SASL support\n",
+                       prog );
                return( EXIT_FAILURE );
 #endif
                break;
        case 'Z':
 #ifdef HAVE_TLS
+               if( version == LDAP_VERSION2 ) {
+                       fprintf( stderr, "%s: -Z incompatible with version %d\n",
+                               prog, version );
+                       return EXIT_FAILURE;
+               }
+               version = LDAP_VERSION3;
                use_tls++;
 #else
-               fprintf( stderr, "%s was not compiled with TLS support\n",
-                       argv[0] );
+               fprintf( stderr, "%s: not compiled with TLS support\n",
+                       prog );
                return( EXIT_FAILURE );
 #endif
                break;
        default:
+               fprintf( stderr, "%s: unrecongized option -%c\n",
+                       prog, optopt );
                usage( argv[0] );
        }
        }
 
-       if ( ( authmethod == LDAP_AUTH_KRBV4 ) || ( authmethod ==
-                       LDAP_AUTH_KRBV41 ) ) {
-               if( version > LDAP_VERSION2 ) {
-                       fprintf( stderr, "Kerberos requires LDAPv2\n" );
-                       return( EXIT_FAILURE );
-               }
-               version = LDAP_VERSION2;
-       }
-       else if ( authmethod == LDAP_AUTH_SASL ) {
-               if( version != -1 && version != LDAP_VERSION3 ) {
-                       fprintf( stderr, "SASL requires LDAPv3\n" );
-                       return( EXIT_FAILURE );
-               }
-               version = LDAP_VERSION3;
-       }
-
-       if( manageDSAit ) {
-               if( version != -1 && version != LDAP_VERSION3 ) {
-                       fprintf(stderr, "manage DSA control requires LDAPv3\n");
-                       return EXIT_FAILURE;
-               }
+       if (version == -1) {
                version = LDAP_VERSION3;
        }
-
-       if( use_tls ) {
-               if( version != -1 && version != LDAP_VERSION3 ) {
-                       fprintf(stderr, "Start TLS requires LDAPv3\n");
-                       return EXIT_FAILURE;
-               }
-               version = LDAP_VERSION3;
+       if (authmethod == -1 && version > LDAP_VERSION2) {
+#ifdef HAVE_CYRUS_SASL
+               authmethod = LDAP_AUTH_SASL;
+#else
+               authmethod = LDAP_AUTH_SIMPLE;
+#endif
        }
 
-       if ( argc - optind < 1 ) {
+       if (( argc - optind < 1 ) ||
+               ( *argv[optind] != '(' /*')'*/ &&
+               ( strchr( argv[optind], '=' ) == NULL ) ) )
+       {
                filtpattern = "(objectclass=*)";
        } else {
                filtpattern = strdup( argv[optind++] );
@@ -531,42 +709,38 @@ main( int argc, char **argv )
 
        if ( authmethod == LDAP_AUTH_SASL ) {
 #ifdef HAVE_CYRUS_SASL
-               int     minssf = 0, maxssf = 0;
-
-               if ( sasl_integrity > 0 )
-                       maxssf = 1;
-               if ( sasl_integrity > 1 )
-                       minssf = 1;
-               if ( sasl_privacy > 0 )
-                       maxssf = 100000; /* Something big value */
-               if ( sasl_privacy > 1 )
-                       minssf = 56;
-               
-               if ( ldap_set_option( ld, LDAP_OPT_X_SASL_MINSSF,
-                               (void *)&minssf ) != LDAP_OPT_SUCCESS ) {
-                       fprintf( stderr, "Could not set LDAP_OPT_X_SASL_MINSSF"
-                               "%d\n", minssf);
-                       return( EXIT_FAILURE );
-               }
-               if ( ldap_set_option( ld, LDAP_OPT_X_SASL_MAXSSF,
-                               (void *)&maxssf ) != LDAP_OPT_SUCCESS ) {
-                       fprintf( stderr, "Could not set LDAP_OPT_X_SASL_MAXSSF"
-                               "%d\n", maxssf);
-                       return( EXIT_FAILURE );
+               void *defaults;
+
+               if( sasl_secprops != NULL ) {
+                       rc = ldap_set_option( ld, LDAP_OPT_X_SASL_SECPROPS,
+                               (void *) sasl_secprops );
+                       
+                       if( rc != LDAP_OPT_SUCCESS ) {
+                               fprintf( stderr,
+                                       "Could not set LDAP_OPT_X_SASL_SECPROPS: %s\n",
+                                       sasl_secprops );
+                               return( EXIT_FAILURE );
+                       }
                }
                
-               rc = ldap_negotiated_sasl_bind_s( ld, binddn, sasl_authc_id,
-                               sasl_authz_id, sasl_mech,
-                               passwd.bv_len ? &passwd : NULL,
-                               NULL, NULL );
+               defaults = lutil_sasl_defaults( ld,
+                       sasl_mech,
+                       sasl_realm,
+                       sasl_authc_id,
+                       passwd.bv_val,
+                       sasl_authz_id );
+
+               rc = ldap_sasl_interactive_bind_s( ld, binddn,
+                       sasl_mech, NULL, NULL,
+                       sasl_flags, lutil_sasl_interact, defaults );
 
                if( rc != LDAP_SUCCESS ) {
-                       ldap_perror( ld, "ldap_negotiated_sasl_bind_s" );
+                       ldap_perror( ld, "ldap_sasl_interactive_bind_s" );
                        return( EXIT_FAILURE );
                }
 #else
-               fprintf( stderr, "%s was not compiled with SASL support\n",
-                       argv[0] );
+               fprintf( stderr, "%s: not compiled with SASL support\n",
+                       prog, argv[0] );
                return( EXIT_FAILURE );
 #endif
        } else {
@@ -713,8 +887,8 @@ static int dosearch(
                sctrls, cctrls, timelimit, sizelimit, &msgid );
 
        if( rc != LDAP_SUCCESS ) {
-               fprintf( stderr, "ldapsearch: ldap_search_ext: %s (%d)\n",
-                       ldap_err2string( rc ), rc );
+               fprintf( stderr, "%s: ldap_search_ext: %s (%d)\n",
+                       prog, ldap_err2string( rc ), rc );
                return( rc );
        }
 
index 97d138fa388579cc4ace035339af77635699ad8d..aebf89c4dc83e8919d70e27f696cdd5fbe48b4be 100644 (file)
@@ -727,7 +727,7 @@ attn( int sig )
        fflush(stdout);
        printf("\n\n  INTERRUPTED!\n");
 
-       (void) SIGNAL (SIGINT, attn);
+       (void) SIGNAL_REINSTALL (SIGINT, attn);
 
        longjmp(env, 1);
 }
@@ -746,6 +746,6 @@ chwinsz( int sig )
                        col_size = win.ws_col;
        }
 
-       (void) SIGNAL (SIGWINCH, chwinsz);
+       (void) SIGNAL_REINSTALL (SIGWINCH, chwinsz);
 }
 #endif
index 9275f6d07cf8ae38dd0cee15c2a6cac6ba1abee7..6f9afab38729e8a44c8df31928403c8fa846bf22 100644 (file)
@@ -603,7 +603,7 @@ time2text( char *ldtimestr, int dateonly )
 
     timestr[ strlen( timestr ) - 1 ] = zone;   /* replace trailing newline */
     if ( dateonly ) {
-       SAFEMEMCPY( timestr + 11, timestr + 20, strlen( timestr + 20 ) + 1 );
+               AC_MEMCPY( timestr + 11, timestr + 20, strlen( timestr + 20 ) + 1 );
     }
 
     return( strdup( timestr ) );
index 120cde80cfddbb7a7377af594b3e8d4d6c71cbce..66d2eb664302825d724d7c5600b7065b44eaa8ed 100644 (file)
@@ -208,13 +208,13 @@ StringToKey(
         strncat (password, cell, sizeof(password)-passlen);
     if ((passlen = strlen(password)) > sizeof(password)) passlen = sizeof(password);
 
-    memcpy(ivec, "kerberos", 8);
-    memcpy(temp_key, "kerberos", 8);
+    AC_MEMCPY(ivec, "kerberos", 8);
+    AC_MEMCPY(temp_key, "kerberos", 8);
     des_fixup_key_parity (temp_key);
     des_key_sched (temp_key, schedule);
     des_cbc_cksum (password, ivec, passlen, schedule, ivec);
 
-    memcpy(temp_key, ivec, 8);
+    AC_MEMCPY(temp_key, ivec, 8);
     des_fixup_key_parity (temp_key);
     des_key_sched (temp_key, schedule);
     des_cbc_cksum (password, key, passlen, schedule, ivec);
index 603d2c770dc685c4b302001eea25a26502fbd14b..16253263a49f0f76b044808894363f169fe5e497 100644 (file)
@@ -92,7 +92,7 @@ fetch_buffer( char *buffer, int length, FILE *where )
                if ( isprint( (unsigned char) *p )) {
                        ++p;
                } else {
-                       SAFEMEMCPY( p, p + 1, strlen( p + 1 ) + 1 ); 
+                       AC_MEMCPY( p, p + 1, strlen( p + 1 ) + 1 ); 
                }
        }
 
index 0aebb038e42433bbe2434cde2170c65fcd6479ed..e3ba90595408a8627f3996b9409d0cc268588b88 100755 (executable)
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
 #! /bin/sh
 # $OpenLDAP$
-# from OpenLDAP 
+# from OpenLDAP: pkg/ldap/configure.in,v 1.223.2.7 2000/07/06 16:45:22 kurt Exp  
 
 # Copyright 1998-2000 The OpenLDAP Foundation.  All Rights Reserved.
 # 
@@ -27,97 +27,97 @@ ac_default_prefix=/usr/local
 ac_help="$ac_help
   --with-subdir=DIR change default subdirectory used for installs"
 ac_help="$ac_help
-  --enable-debug       enable debugging (yes)"
+  --enable-debug         enable debugging (yes)"
 ac_help="$ac_help
-  --enable-syslog      enable syslog support (auto)"
+  --enable-syslog        enable syslog support (auto)"
 ac_help="$ac_help
-  --enable-proctitle   enable proctitle support (yes)"
+  --enable-proctitle     enable proctitle support (yes)"
 ac_help="$ac_help
-  --enable-cache       enable caching (yes)"
+  --enable-cache         enable caching (yes)"
 ac_help="$ac_help
-  --enable-referrals   enable V2 Referrals extension (yes)"
+  --enable-referrals     enable V2 Referrals extension (yes)"
 ac_help="$ac_help
-  --enable-kbind       enable V2 Kerberos IV bind (auto)"
+  --enable-kbind         enable V2 Kerberos IV bind (auto)"
 ac_help="$ac_help
-  --enable-cldap       enable connectionless ldap (no)"
+  --enable-cldap         enable connectionless ldap (no)"
 ac_help="$ac_help
-  --enable-ipv6        enable IPv6 support (auto)"
+  --enable-ipv6          enable IPv6 support (auto)"
 ac_help="$ac_help
-  --enable-unix                enable UNIX domain socket support (auto)"
+  --enable-local         enable AF_LOCAL (AF_UNIX) socket support (auto)"
 ac_help="$ac_help
-  --enable-x-compile   enable cross compiling (no)"
+  --enable-x-compile     enable cross compiling (no)"
 ac_help="$ac_help
-  --with-cyrus-sasl    with Cyrus SASL support (auto)"
+  --with-cyrus-sasl      with Cyrus SASL support (auto)"
 ac_help="$ac_help
-  --with-fetch         with fetch URL support (auto)"
+  --with-fetch           with fetch URL support (auto)"
 ac_help="$ac_help
-  --with-kerberos      with support (auto)"
+  --with-kerberos        with support (auto)"
 ac_help="$ac_help
-  --with-readline      with readline support (auto)"
+  --with-readline        with readline support (auto)"
 ac_help="$ac_help
-  --with-threads       use threads (auto)"
+  --with-threads         with threads (auto)"
 ac_help="$ac_help
-  --with-tls           with TLS/SSL support (auto)"
+  --with-tls             with TLS/SSL support (auto)"
 ac_help="$ac_help
-  --with-yielding-select       with implicitly yielding select (auto)"
+  --with-yielding-select  with implicitly yielding select (auto)"
 ac_help="$ac_help
 SLAPD (Standalone LDAP Daemon) Options:"
 ac_help="$ac_help
-  --enable-slapd       enable building slapd (yes)"
+  --enable-slapd         enable building slapd (yes)"
 ac_help="$ac_help
-    --enable-cleartext enable cleartext passwords (yes)"
+    --enable-cleartext   enable cleartext passwords (yes)"
 ac_help="$ac_help
-    --enable-crypt     enable crypt(3) passwords (auto)"
+    --enable-crypt       enable crypt(3) passwords (auto)"
 ac_help="$ac_help
-    --enable-kpasswd   enable kerberos password verification (no)"
+    --enable-kpasswd     enable kerberos password verification (no)"
 ac_help="$ac_help
-    --enable-spasswd   enable (Cyrus) SASL password verification (no)"
+    --enable-spasswd     enable (Cyrus) SASL password verification (no)"
 ac_help="$ac_help
-    --enable-modules   enable dynamic module support (no)"
+    --enable-modules     enable dynamic module support (no)"
 ac_help="$ac_help
-    --enable-multimaster       enable multimaster replication (no)"
+    --enable-multimaster  enable multimaster replication (no)"
 ac_help="$ac_help
-    --enable-phonetic  enable phonetic/soundex (no)"
+    --enable-phonetic    enable phonetic/soundex (no)"
 ac_help="$ac_help
-    --enable-rlookups  enable reverse lookups (auto)"
+    --enable-rlookups    enable reverse lookups (auto)"
 ac_help="$ac_help
-    --enable-aci       enable per-object ACIs (no)"
+    --enable-aci         enable per-object ACIs (no)"
 ac_help="$ac_help
-    --enable-wrappers  enable tcp wrapper support (no)"
+    --enable-wrappers    enable tcp wrapper support (no)"
 ac_help="$ac_help
-    --enable-dynamic   enable linking built binaries with dynamic libs (no)"
+    --enable-dynamic     enable linking built binaries with dynamic libs (no)"
 ac_help="$ac_help
-    --enable-dnssrv    enable dnssrv backend (no)"
+    --enable-dnssrv      enable dnssrv backend (no)"
 ac_help="$ac_help
-      --with-dnssrv-module     module type (static)"
+    --with-dnssrv-module  module type (static)"
 ac_help="$ac_help
-    --enable-ldap      enable ldap backend (no)"
+    --enable-ldap        enable ldap backend (no)"
 ac_help="$ac_help
-      --with-ldap-module       module type (static)"
+    --with-ldap-module   module type (static)"
 ac_help="$ac_help
-    --enable-ldbm      enable ldbm backend (yes)"
+    --enable-ldbm        enable ldbm backend (yes)"
 ac_help="$ac_help
-      --with-ldbm-api  use LDBM API (auto)"
+    --with-ldbm-api       with LDBM API (auto)"
 ac_help="$ac_help
-      --with-ldbm-module       module type (static)"
+    --with-ldbm-module   module type (static)"
 ac_help="$ac_help
-      --with-ldbm-type use LDBM type (auto)"
+    --with-ldbm-type     use LDBM type (auto)"
 ac_help="$ac_help
-    --enable-passwd    enable passwd backend (no)"
+    --enable-passwd      enable passwd backend (no)"
 ac_help="$ac_help
-      --with-passwd-module     module type (static)"
+    --with-passwd-module  module type (static)"
 ac_help="$ac_help
-    --enable-shell     enable shell backend (no)"
+    --enable-shell       enable shell backend (no)"
 ac_help="$ac_help
-      --with-shell-module      module type (static)"
+    --with-shell-module          module type (static)"
 ac_help="$ac_help
-    --enable-sql       enable sql backend (no)"
+    --enable-sql         enable sql backend (no)"
 ac_help="$ac_help
-      --with-sql-module        module type (static)"
+    --with-sql-module    module type (static)"
 ac_help="$ac_help
 SLURPD (Replication Daemon) Options:"
 ac_help="$ac_help
-  --enable-slurpd      enable building slurpd (auto)"
+  --enable-slurpd        enable building slurpd (auto)"
 ac_help="$ac_help
 Library Generation & Linking Options"
 ac_help="$ac_help
@@ -1329,10 +1329,10 @@ else
        ol_enable_ipv6="auto"
 fi
 # end --enable-ipv6
-# OpenLDAP --enable-unix
-       # Check whether --enable-unix or --disable-unix was given.
-if test "${enable_unix+set}" = set; then
-  enableval="$enable_unix"
+# OpenLDAP --enable-local
+       # Check whether --enable-local or --disable-local was given.
+if test "${enable_local+set}" = set; then
+  enableval="$enable_local"
   
        ol_arg=invalid
        for ol_val in auto yes no ; do
@@ -1341,14 +1341,14 @@ if test "${enable_unix+set}" = set; then
                fi
        done
        if test "$ol_arg" = "invalid" ; then
-               { echo "configure: error: bad value $enableval for --enable-unix" 1>&2; exit 1; }
+               { echo "configure: error: bad value $enableval for --enable-local" 1>&2; exit 1; }
        fi
-       ol_enable_unix="$ol_arg"
+       ol_enable_local="$ol_arg"
 
 else
-       ol_enable_unix="auto"
+       ol_enable_local="auto"
 fi
-# end --enable-unix
+# end --enable-local
 # OpenLDAP --enable-x_compile
        # Check whether --enable-x_compile or --disable-x_compile was given.
 if test "${enable_x_compile+set}" = set; then
@@ -4020,7 +4020,7 @@ if test $ac_cv_func_getaddrinfo = no ; then
        ol_enable_ipv6=no
 fi
 
-if test $ol_enable_unix != no ; then
+if test $ol_enable_local != no ; then
        for ac_hdr in sys/un.h 
 do
 ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
@@ -4062,10 +4062,10 @@ fi
 done
 
 
-       if test $ol_enable_unix = auto ; then
-               ol_enable_unix=$ac_cv_header_sys_un_h
+       if test $ol_enable_local = auto ; then
+               ol_enable_local=$ac_cv_header_sys_un_h
        elif test $ac_cv_header_sys_un_h = no ; then
-               { echo "configure: error: UNIX domain support requires sys/un.h" 1>&2; exit 1; }
+               { echo "configure: error: AF_LOCAL domain support requires sys/un.h" 1>&2; exit 1; }
        fi
 fi
 
@@ -6112,22 +6112,21 @@ fi
 
 ol_link_tls=no
 if test $ol_with_tls != no ; then
-       
        for ac_hdr in openssl/ssl.h ssl.h
 do
 ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:6121: checking for $ac_hdr" >&5
+echo "configure:6120: checking for $ac_hdr" >&5
 if eval "test \"\${ac_cv_header_$ac_safe+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 6126 "configure"
+#line 6125 "configure"
 #include "confdefs.h"
 #include <$ac_hdr>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:6131: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:6130: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -6156,7 +6155,7 @@ done
        
        if test $ac_cv_header_openssl_ssl_h = yes -o $ac_cv_header_ssl_h = yes ; then
                echo $ac_n "checking for SSLeay_add_ssl_algorithms in -lssl""... $ac_c" 1>&6
-echo "configure:6160: checking for SSLeay_add_ssl_algorithms in -lssl" >&5
+echo "configure:6159: checking for SSLeay_add_ssl_algorithms in -lssl" >&5
 ac_lib_var=`echo ssl'_'SSLeay_add_ssl_algorithms | sed 'y%./+-:%__p__%'`
 if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -6164,7 +6163,7 @@ else
   ac_save_LIBS="$LIBS"
 LIBS="-lssl -lcrypto $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 6168 "configure"
+#line 6167 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -6175,7 +6174,7 @@ int main() {
 SSLeay_add_ssl_algorithms()
 ; return 0; }
 EOF
-if { (eval echo configure:6179: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:6178: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -6200,7 +6199,7 @@ fi
                        
                if test $have_ssleay = no ; then
                        echo $ac_n "checking for SSL_library_init in -lssl""... $ac_c" 1>&6
-echo "configure:6204: checking for SSL_library_init in -lssl" >&5
+echo "configure:6203: checking for SSL_library_init in -lssl" >&5
 ac_lib_var=`echo ssl'_'SSL_library_init | sed 'y%./+-:%__p__%'`
 if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -6208,7 +6207,7 @@ else
   ac_save_LIBS="$LIBS"
 LIBS="-lssl -lcrypto $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 6212 "configure"
+#line 6211 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -6219,7 +6218,7 @@ int main() {
 SSL_library_init()
 ; return 0; }
 EOF
-if { (eval echo configure:6223: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:6222: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -6245,7 +6244,7 @@ fi
 
                if test $have_ssleay = no ; then
                        echo $ac_n "checking for ssl3_accept in -lssl""... $ac_c" 1>&6
-echo "configure:6249: checking for ssl3_accept in -lssl" >&5
+echo "configure:6248: checking for ssl3_accept in -lssl" >&5
 ac_lib_var=`echo ssl'_'ssl3_accept | sed 'y%./+-:%__p__%'`
 if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -6253,7 +6252,7 @@ else
   ac_save_LIBS="$LIBS"
 LIBS="-lssl -lcrypto -lRSAglue -lrsaref $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 6257 "configure"
+#line 6256 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -6264,7 +6263,7 @@ int main() {
 ssl3_accept()
 ; return 0; }
 EOF
-if { (eval echo configure:6268: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:6267: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -6309,6 +6308,9 @@ EOF
                        fi
                fi
        fi
+
+else
+       echo "configure: warning: TLS privacy protection not supported!" 1>&2
 fi
 
 if test $ol_link_tls = yes ; then
@@ -6316,7 +6318,14 @@ if test $ol_link_tls = yes ; then
 #define HAVE_TLS 1
 EOF
 
-fi     
+
+elif test $ol_with_tls = auto ; then
+       echo "configure: warning: Could not locate TLS/SSL package" 1>&2
+       echo "configure: warning: TLS privacy protection not supported!" 1>&2
+
+elif test $ol_with_tls != no ; then
+       { echo "configure: error: Could not locate TLS/SSL package" 1>&2; exit 1; }
+fi
 
 for ac_func in \
        ctime_r                 \
@@ -6324,12 +6333,12 @@ for ac_func in \
 
 do
 echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:6328: checking for $ac_func" >&5
+echo "configure:6337: checking for $ac_func" >&5
 if eval "test \"\${ac_cv_func_$ac_func+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 6333 "configure"
+#line 6342 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func(); below.  */
@@ -6353,7 +6362,7 @@ f = $ac_func;
 
 ; return 0; }
 EOF
-if { (eval echo configure:6357: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:6366: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_func_$ac_func=yes"
 else
@@ -6382,19 +6391,19 @@ if test "$ac_cv_func_ctime_r" = no ; then
        ol_cv_func_ctime_r_nargs=0
 else
        echo $ac_n "checking number of arguments of ctime_r""... $ac_c" 1>&6
-echo "configure:6386: checking number of arguments of ctime_r" >&5
+echo "configure:6395: checking number of arguments of ctime_r" >&5
 if eval "test \"\${ol_cv_func_ctime_r_nargs+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 6391 "configure"
+#line 6400 "configure"
 #include "confdefs.h"
 #include <time.h>
 int main() {
 time_t ti; char *buffer; ctime_r(&ti,buffer,32);
 ; return 0; }
 EOF
-if { (eval echo configure:6398: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:6407: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ol_cv_func_ctime_r_nargs3=yes
 else
@@ -6406,14 +6415,14 @@ fi
 rm -f conftest*
 
        cat > conftest.$ac_ext <<EOF
-#line 6410 "configure"
+#line 6419 "configure"
 #include "confdefs.h"
 #include <time.h>
 int main() {
 time_t ti; char *buffer; ctime_r(&ti,buffer);
 ; return 0; }
 EOF
-if { (eval echo configure:6417: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:6426: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ol_cv_func_ctime_r_nargs2=yes
 else
@@ -6453,12 +6462,12 @@ fi
 
 if test "$ac_cv_func_gethostbyname_r" = yes ; then
        echo $ac_n "checking number of arguments of gethostbyname_r""... $ac_c" 1>&6
-echo "configure:6457: checking number of arguments of gethostbyname_r" >&5
+echo "configure:6466: checking number of arguments of gethostbyname_r" >&5
 if eval "test \"\${ol_cv_func_gethostbyname_r_nargs+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 6462 "configure"
+#line 6471 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #include <sys/socket.h>
@@ -6472,7 +6481,7 @@ struct hostent hent; char buffer[BUFSIZE];
                        buffer, bufsize, &h_errno);
 ; return 0; }
 EOF
-if { (eval echo configure:6476: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:6485: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ol_cv_func_gethostbyname_r_nargs5=yes
 else
@@ -6484,7 +6493,7 @@ fi
 rm -f conftest*
 
        cat > conftest.$ac_ext <<EOF
-#line 6488 "configure"
+#line 6497 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #include <sys/socket.h>
@@ -6499,7 +6508,7 @@ struct hostent hent;struct hostent *rhent;
                        &rhent, &h_errno);
 ; return 0; }
 EOF
-if { (eval echo configure:6503: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:6512: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ol_cv_func_gethostbyname_r_nargs6=yes
 else
@@ -6540,12 +6549,12 @@ fi
  
 if test "$ac_cv_func_gethostbyaddr_r" = yes ; then
        echo $ac_n "checking number of arguments of gethostbyaddr_r""... $ac_c" 1>&6
-echo "configure:6544: checking number of arguments of gethostbyaddr_r" >&5
+echo "configure:6553: checking number of arguments of gethostbyaddr_r" >&5
 if eval "test \"\${ol_cv_func_gethostbyaddr_r_nargs+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 6549 "configure"
+#line 6558 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #include <sys/socket.h>
@@ -6561,7 +6570,7 @@ struct hostent hent; char buffer[BUFSIZE];
                        alen, AF_INET, &hent, buffer, bufsize, &h_errno);
 ; return 0; }
 EOF
-if { (eval echo configure:6565: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:6574: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ol_cv_func_gethostbyaddr_r_nargs7=yes
 else
@@ -6573,7 +6582,7 @@ fi
 rm -f conftest*
 
        cat > conftest.$ac_ext <<EOF
-#line 6577 "configure"
+#line 6586 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #include <sys/socket.h>
@@ -6591,7 +6600,7 @@ struct hostent hent;
                        &rhent, &h_errno);
 ; return 0; }
 EOF
-if { (eval echo configure:6595: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:6604: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ol_cv_func_gethostbyaddr_r_nargs8=yes
 else
@@ -6654,18 +6663,18 @@ if test $ol_with_threads = auto -o $ol_with_threads = yes \
 
        
        echo $ac_n "checking for NT Threads""... $ac_c" 1>&6
-echo "configure:6658: checking for NT Threads" >&5
+echo "configure:6667: checking for NT Threads" >&5
 if eval "test \"\${ol_cv_nt_threads+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   
                echo $ac_n "checking for _beginthread""... $ac_c" 1>&6
-echo "configure:6664: checking for _beginthread" >&5
+echo "configure:6673: checking for _beginthread" >&5
 if eval "test \"\${ac_cv_func__beginthread+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 6669 "configure"
+#line 6678 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char _beginthread(); below.  */
@@ -6689,7 +6698,7 @@ f = _beginthread;
 
 ; return 0; }
 EOF
-if { (eval echo configure:6693: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:6702: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_func__beginthread=yes"
 else
@@ -6749,17 +6758,17 @@ if test $ol_with_threads = auto -o $ol_with_threads = yes \
 do
 ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:6753: checking for $ac_hdr" >&5
+echo "configure:6762: checking for $ac_hdr" >&5
 if eval "test \"\${ac_cv_header_$ac_safe+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 6758 "configure"
+#line 6767 "configure"
 #include "confdefs.h"
 #include <$ac_hdr>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:6763: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:6772: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -6788,13 +6797,13 @@ done
 
        if test $ac_cv_header_pthread_h = yes ; then
                echo $ac_n "checking POSIX thread version""... $ac_c" 1>&6
-echo "configure:6792: checking POSIX thread version" >&5
+echo "configure:6801: checking POSIX thread version" >&5
 if eval "test \"\${ol_cv_pthread_version+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   
        cat > conftest.$ac_ext <<EOF
-#line 6798 "configure"
+#line 6807 "configure"
 #include "confdefs.h"
 
 #              include <pthread.h>
@@ -6816,7 +6825,7 @@ rm -f conftest*
 
 
        cat > conftest.$ac_ext <<EOF
-#line 6820 "configure"
+#line 6829 "configure"
 #include "confdefs.h"
 
 #              include <pthread.h>
@@ -6869,12 +6878,12 @@ EOF
 
                
        echo $ac_n "checking for LinuxThreads pthread.h""... $ac_c" 1>&6
-echo "configure:6873: checking for LinuxThreads pthread.h" >&5
+echo "configure:6882: checking for LinuxThreads pthread.h" >&5
 if eval "test \"\${ol_cv_header_linux_threads+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 6878 "configure"
+#line 6887 "configure"
 #include "confdefs.h"
 #include <pthread.h>
 EOF
@@ -6901,12 +6910,12 @@ EOF
 
                
        echo $ac_n "checking for GNU Pth pthread.h""... $ac_c" 1>&6
-echo "configure:6905: checking for GNU Pth pthread.h" >&5
+echo "configure:6914: checking for GNU Pth pthread.h" >&5
 if eval "test \"\${ol_cv_header_gnu_pth_pthread_h+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 6910 "configure"
+#line 6919 "configure"
 #include "confdefs.h"
 #include <pthread.h>
 #ifdef _POSIX_THREAD_IS_GNU_PTH
@@ -6935,17 +6944,17 @@ echo "$ac_t""$ol_cv_header_gnu_pth_pthread_h" 1>&6
 do
 ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:6939: checking for $ac_hdr" >&5
+echo "configure:6948: checking for $ac_hdr" >&5
 if eval "test \"\${ac_cv_header_$ac_safe+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 6944 "configure"
+#line 6953 "configure"
 #include "confdefs.h"
 #include <$ac_hdr>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:6949: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:6958: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -6975,14 +6984,14 @@ done
 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
                                echo $ac_n "checking for pthread_create in default libraries""... $ac_c" 1>&6
-echo "configure:6979: checking for pthread_create in default libraries" >&5
+echo "configure:6988: checking for pthread_create in default libraries" >&5
 if eval "test \"\${ol_cv_pthread_create+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   
                if test "$cross_compiling" = yes; then
   cat > conftest.$ac_ext <<EOF
-#line 6986 "configure"
+#line 6995 "configure"
 #include "confdefs.h"
 /* pthread test headers */
 #include <pthread.h>
@@ -7038,7 +7047,7 @@ int main() {
 
 ; return 0; }
 EOF
-if { (eval echo configure:7042: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:7051: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   ol_cv_pthread_create=yes
 else
@@ -7050,7 +7059,7 @@ fi
 rm -f conftest*
 else
   cat > conftest.$ac_ext <<EOF
-#line 7054 "configure"
+#line 7063 "configure"
 #include "confdefs.h"
 /* pthread test headers */
 #include <pthread.h>
@@ -7111,7 +7120,7 @@ int main(argc, argv)
 }
 
 EOF
-if { (eval echo configure:7115: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:7124: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   ol_cv_pthread_create=yes
 else
@@ -7136,7 +7145,7 @@ echo "$ac_t""$ol_cv_pthread_create" 1>&6
 if test "$ol_link_threads" = no ; then
        # try -kthread
        echo $ac_n "checking for pthread link with -kthread""... $ac_c" 1>&6
-echo "configure:7140: checking for pthread link with -kthread" >&5
+echo "configure:7149: checking for pthread link with -kthread" >&5
 if eval "test \"\${ol_cv_pthread_kthread+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -7147,7 +7156,7 @@ else
 
                if test "$cross_compiling" = yes; then
   cat > conftest.$ac_ext <<EOF
-#line 7151 "configure"
+#line 7160 "configure"
 #include "confdefs.h"
 /* pthread test headers */
 #include <pthread.h>
@@ -7203,7 +7212,7 @@ int main() {
 
 ; return 0; }
 EOF
-if { (eval echo configure:7207: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:7216: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   ol_cv_pthread_kthread=yes
 else
@@ -7215,7 +7224,7 @@ fi
 rm -f conftest*
 else
   cat > conftest.$ac_ext <<EOF
-#line 7219 "configure"
+#line 7228 "configure"
 #include "confdefs.h"
 /* pthread test headers */
 #include <pthread.h>
@@ -7276,7 +7285,7 @@ int main(argc, argv)
 }
 
 EOF
-if { (eval echo configure:7280: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:7289: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   ol_cv_pthread_kthread=yes
 else
@@ -7306,7 +7315,7 @@ fi
 if test "$ol_link_threads" = no ; then
        # try -pthread
        echo $ac_n "checking for pthread link with -pthread""... $ac_c" 1>&6
-echo "configure:7310: checking for pthread link with -pthread" >&5
+echo "configure:7319: checking for pthread link with -pthread" >&5
 if eval "test \"\${ol_cv_pthread_pthread+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -7317,7 +7326,7 @@ else
 
                if test "$cross_compiling" = yes; then
   cat > conftest.$ac_ext <<EOF
-#line 7321 "configure"
+#line 7330 "configure"
 #include "confdefs.h"
 /* pthread test headers */
 #include <pthread.h>
@@ -7373,7 +7382,7 @@ int main() {
 
 ; return 0; }
 EOF
-if { (eval echo configure:7377: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:7386: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   ol_cv_pthread_pthread=yes
 else
@@ -7385,7 +7394,7 @@ fi
 rm -f conftest*
 else
   cat > conftest.$ac_ext <<EOF
-#line 7389 "configure"
+#line 7398 "configure"
 #include "confdefs.h"
 /* pthread test headers */
 #include <pthread.h>
@@ -7446,7 +7455,7 @@ int main(argc, argv)
 }
 
 EOF
-if { (eval echo configure:7450: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:7459: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   ol_cv_pthread_pthread=yes
 else
@@ -7476,7 +7485,7 @@ fi
 if test "$ol_link_threads" = no ; then
        # try -pthreads
        echo $ac_n "checking for pthread link with -pthreads""... $ac_c" 1>&6
-echo "configure:7480: checking for pthread link with -pthreads" >&5
+echo "configure:7489: checking for pthread link with -pthreads" >&5
 if eval "test \"\${ol_cv_pthread_pthreads+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -7487,7 +7496,7 @@ else
 
                if test "$cross_compiling" = yes; then
   cat > conftest.$ac_ext <<EOF
-#line 7491 "configure"
+#line 7500 "configure"
 #include "confdefs.h"
 /* pthread test headers */
 #include <pthread.h>
@@ -7543,7 +7552,7 @@ int main() {
 
 ; return 0; }
 EOF
-if { (eval echo configure:7547: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:7556: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   ol_cv_pthread_pthreads=yes
 else
@@ -7555,7 +7564,7 @@ fi
 rm -f conftest*
 else
   cat > conftest.$ac_ext <<EOF
-#line 7559 "configure"
+#line 7568 "configure"
 #include "confdefs.h"
 /* pthread test headers */
 #include <pthread.h>
@@ -7616,7 +7625,7 @@ int main(argc, argv)
 }
 
 EOF
-if { (eval echo configure:7620: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:7629: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   ol_cv_pthread_pthreads=yes
 else
@@ -7646,7 +7655,7 @@ fi
 if test "$ol_link_threads" = no ; then
        # try -mthreads
        echo $ac_n "checking for pthread link with -mthreads""... $ac_c" 1>&6
-echo "configure:7650: checking for pthread link with -mthreads" >&5
+echo "configure:7659: checking for pthread link with -mthreads" >&5
 if eval "test \"\${ol_cv_pthread_mthreads+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -7657,7 +7666,7 @@ else
 
                if test "$cross_compiling" = yes; then
   cat > conftest.$ac_ext <<EOF
-#line 7661 "configure"
+#line 7670 "configure"
 #include "confdefs.h"
 /* pthread test headers */
 #include <pthread.h>
@@ -7713,7 +7722,7 @@ int main() {
 
 ; return 0; }
 EOF
-if { (eval echo configure:7717: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:7726: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   ol_cv_pthread_mthreads=yes
 else
@@ -7725,7 +7734,7 @@ fi
 rm -f conftest*
 else
   cat > conftest.$ac_ext <<EOF
-#line 7729 "configure"
+#line 7738 "configure"
 #include "confdefs.h"
 /* pthread test headers */
 #include <pthread.h>
@@ -7786,7 +7795,7 @@ int main(argc, argv)
 }
 
 EOF
-if { (eval echo configure:7790: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:7799: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   ol_cv_pthread_mthreads=yes
 else
@@ -7816,7 +7825,7 @@ fi
 if test "$ol_link_threads" = no ; then
        # try -thread
        echo $ac_n "checking for pthread link with -thread""... $ac_c" 1>&6
-echo "configure:7820: checking for pthread link with -thread" >&5
+echo "configure:7829: checking for pthread link with -thread" >&5
 if eval "test \"\${ol_cv_pthread_thread+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -7827,7 +7836,7 @@ else
 
                if test "$cross_compiling" = yes; then
   cat > conftest.$ac_ext <<EOF
-#line 7831 "configure"
+#line 7840 "configure"
 #include "confdefs.h"
 /* pthread test headers */
 #include <pthread.h>
@@ -7883,7 +7892,7 @@ int main() {
 
 ; return 0; }
 EOF
-if { (eval echo configure:7887: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:7896: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   ol_cv_pthread_thread=yes
 else
@@ -7895,7 +7904,7 @@ fi
 rm -f conftest*
 else
   cat > conftest.$ac_ext <<EOF
-#line 7899 "configure"
+#line 7908 "configure"
 #include "confdefs.h"
 /* pthread test headers */
 #include <pthread.h>
@@ -7956,7 +7965,7 @@ int main(argc, argv)
 }
 
 EOF
-if { (eval echo configure:7960: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:7969: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   ol_cv_pthread_thread=yes
 else
@@ -7987,7 +7996,7 @@ fi
 if test "$ol_link_threads" = no ; then
        # try -lpthread -lmach -lexc -lc_r
        echo $ac_n "checking for pthread link with -lpthread -lmach -lexc -lc_r""... $ac_c" 1>&6
-echo "configure:7991: checking for pthread link with -lpthread -lmach -lexc -lc_r" >&5
+echo "configure:8000: checking for pthread link with -lpthread -lmach -lexc -lc_r" >&5
 if eval "test \"\${ol_cv_pthread_lpthread_lmach_lexc_lc_r+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -7998,7 +8007,7 @@ else
 
                if test "$cross_compiling" = yes; then
   cat > conftest.$ac_ext <<EOF
-#line 8002 "configure"
+#line 8011 "configure"
 #include "confdefs.h"
 /* pthread test headers */
 #include <pthread.h>
@@ -8054,7 +8063,7 @@ int main() {
 
 ; return 0; }
 EOF
-if { (eval echo configure:8058: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:8067: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   ol_cv_pthread_lpthread_lmach_lexc_lc_r=yes
 else
@@ -8066,7 +8075,7 @@ fi
 rm -f conftest*
 else
   cat > conftest.$ac_ext <<EOF
-#line 8070 "configure"
+#line 8079 "configure"
 #include "confdefs.h"
 /* pthread test headers */
 #include <pthread.h>
@@ -8127,7 +8136,7 @@ int main(argc, argv)
 }
 
 EOF
-if { (eval echo configure:8131: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:8140: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   ol_cv_pthread_lpthread_lmach_lexc_lc_r=yes
 else
@@ -8157,7 +8166,7 @@ fi
 if test "$ol_link_threads" = no ; then
        # try -lpthread -lmach -lexc
        echo $ac_n "checking for pthread link with -lpthread -lmach -lexc""... $ac_c" 1>&6
-echo "configure:8161: checking for pthread link with -lpthread -lmach -lexc" >&5
+echo "configure:8170: checking for pthread link with -lpthread -lmach -lexc" >&5
 if eval "test \"\${ol_cv_pthread_lpthread_lmach_lexc+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -8168,7 +8177,7 @@ else
 
                if test "$cross_compiling" = yes; then
   cat > conftest.$ac_ext <<EOF
-#line 8172 "configure"
+#line 8181 "configure"
 #include "confdefs.h"
 /* pthread test headers */
 #include <pthread.h>
@@ -8224,7 +8233,7 @@ int main() {
 
 ; return 0; }
 EOF
-if { (eval echo configure:8228: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:8237: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   ol_cv_pthread_lpthread_lmach_lexc=yes
 else
@@ -8236,7 +8245,7 @@ fi
 rm -f conftest*
 else
   cat > conftest.$ac_ext <<EOF
-#line 8240 "configure"
+#line 8249 "configure"
 #include "confdefs.h"
 /* pthread test headers */
 #include <pthread.h>
@@ -8297,7 +8306,7 @@ int main(argc, argv)
 }
 
 EOF
-if { (eval echo configure:8301: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:8310: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   ol_cv_pthread_lpthread_lmach_lexc=yes
 else
@@ -8328,7 +8337,7 @@ fi
 if test "$ol_link_threads" = no ; then
        # try -lpthread -Wl,-woff,85
        echo $ac_n "checking for pthread link with -lpthread -Wl,-woff,85""... $ac_c" 1>&6
-echo "configure:8332: checking for pthread link with -lpthread -Wl,-woff,85" >&5
+echo "configure:8341: checking for pthread link with -lpthread -Wl,-woff,85" >&5
 if eval "test \"\${ol_cv_pthread_lib_lpthread_woff+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -8339,7 +8348,7 @@ else
 
                if test "$cross_compiling" = yes; then
   cat > conftest.$ac_ext <<EOF
-#line 8343 "configure"
+#line 8352 "configure"
 #include "confdefs.h"
 /* pthread test headers */
 #include <pthread.h>
@@ -8395,7 +8404,7 @@ int main() {
 
 ; return 0; }
 EOF
-if { (eval echo configure:8399: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:8408: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   ol_cv_pthread_lib_lpthread_woff=yes
 else
@@ -8407,7 +8416,7 @@ fi
 rm -f conftest*
 else
   cat > conftest.$ac_ext <<EOF
-#line 8411 "configure"
+#line 8420 "configure"
 #include "confdefs.h"
 /* pthread test headers */
 #include <pthread.h>
@@ -8468,7 +8477,7 @@ int main(argc, argv)
 }
 
 EOF
-if { (eval echo configure:8472: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:8481: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   ol_cv_pthread_lib_lpthread_woff=yes
 else
@@ -8499,7 +8508,7 @@ fi
 if test "$ol_link_threads" = no ; then
        # try -lpthread
        echo $ac_n "checking for pthread link with -lpthread""... $ac_c" 1>&6
-echo "configure:8503: checking for pthread link with -lpthread" >&5
+echo "configure:8512: checking for pthread link with -lpthread" >&5
 if eval "test \"\${ol_cv_pthread_lpthread+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -8510,7 +8519,7 @@ else
 
                if test "$cross_compiling" = yes; then
   cat > conftest.$ac_ext <<EOF
-#line 8514 "configure"
+#line 8523 "configure"
 #include "confdefs.h"
 /* pthread test headers */
 #include <pthread.h>
@@ -8566,7 +8575,7 @@ int main() {
 
 ; return 0; }
 EOF
-if { (eval echo configure:8570: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:8579: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   ol_cv_pthread_lpthread=yes
 else
@@ -8578,7 +8587,7 @@ fi
 rm -f conftest*
 else
   cat > conftest.$ac_ext <<EOF
-#line 8582 "configure"
+#line 8591 "configure"
 #include "confdefs.h"
 /* pthread test headers */
 #include <pthread.h>
@@ -8639,7 +8648,7 @@ int main(argc, argv)
 }
 
 EOF
-if { (eval echo configure:8643: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:8652: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   ol_cv_pthread_lpthread=yes
 else
@@ -8669,7 +8678,7 @@ fi
 if test "$ol_link_threads" = no ; then
        # try -lc_r
        echo $ac_n "checking for pthread link with -lc_r""... $ac_c" 1>&6
-echo "configure:8673: checking for pthread link with -lc_r" >&5
+echo "configure:8682: checking for pthread link with -lc_r" >&5
 if eval "test \"\${ol_cv_pthread_lc_r+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -8680,7 +8689,7 @@ else
 
                if test "$cross_compiling" = yes; then
   cat > conftest.$ac_ext <<EOF
-#line 8684 "configure"
+#line 8693 "configure"
 #include "confdefs.h"
 /* pthread test headers */
 #include <pthread.h>
@@ -8736,7 +8745,7 @@ int main() {
 
 ; return 0; }
 EOF
-if { (eval echo configure:8740: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:8749: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   ol_cv_pthread_lc_r=yes
 else
@@ -8748,7 +8757,7 @@ fi
 rm -f conftest*
 else
   cat > conftest.$ac_ext <<EOF
-#line 8752 "configure"
+#line 8761 "configure"
 #include "confdefs.h"
 /* pthread test headers */
 #include <pthread.h>
@@ -8809,7 +8818,7 @@ int main(argc, argv)
 }
 
 EOF
-if { (eval echo configure:8813: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:8822: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   ol_cv_pthread_lc_r=yes
 else
@@ -8840,7 +8849,7 @@ fi
 if test "$ol_link_threads" = no ; then
        # try -threads
        echo $ac_n "checking for pthread link with -threads""... $ac_c" 1>&6
-echo "configure:8844: checking for pthread link with -threads" >&5
+echo "configure:8853: checking for pthread link with -threads" >&5
 if eval "test \"\${ol_cv_pthread_threads+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -8851,7 +8860,7 @@ else
 
                if test "$cross_compiling" = yes; then
   cat > conftest.$ac_ext <<EOF
-#line 8855 "configure"
+#line 8864 "configure"
 #include "confdefs.h"
 /* pthread test headers */
 #include <pthread.h>
@@ -8907,7 +8916,7 @@ int main() {
 
 ; return 0; }
 EOF
-if { (eval echo configure:8911: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:8920: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   ol_cv_pthread_threads=yes
 else
@@ -8919,7 +8928,7 @@ fi
 rm -f conftest*
 else
   cat > conftest.$ac_ext <<EOF
-#line 8923 "configure"
+#line 8932 "configure"
 #include "confdefs.h"
 /* pthread test headers */
 #include <pthread.h>
@@ -8980,7 +8989,7 @@ int main(argc, argv)
 }
 
 EOF
-if { (eval echo configure:8984: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:8993: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   ol_cv_pthread_threads=yes
 else
@@ -9011,7 +9020,7 @@ fi
 if test "$ol_link_threads" = no ; then
        # try -lpthreads -lmach -lexc -lc_r
        echo $ac_n "checking for pthread link with -lpthreads -lmach -lexc -lc_r""... $ac_c" 1>&6
-echo "configure:9015: checking for pthread link with -lpthreads -lmach -lexc -lc_r" >&5
+echo "configure:9024: checking for pthread link with -lpthreads -lmach -lexc -lc_r" >&5
 if eval "test \"\${ol_cv_pthread_lpthreads_lmach_lexc_lc_r+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -9022,7 +9031,7 @@ else
 
                if test "$cross_compiling" = yes; then
   cat > conftest.$ac_ext <<EOF
-#line 9026 "configure"
+#line 9035 "configure"
 #include "confdefs.h"
 /* pthread test headers */
 #include <pthread.h>
@@ -9078,7 +9087,7 @@ int main() {
 
 ; return 0; }
 EOF
-if { (eval echo configure:9082: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:9091: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   ol_cv_pthread_lpthreads_lmach_lexc_lc_r=yes
 else
@@ -9090,7 +9099,7 @@ fi
 rm -f conftest*
 else
   cat > conftest.$ac_ext <<EOF
-#line 9094 "configure"
+#line 9103 "configure"
 #include "confdefs.h"
 /* pthread test headers */
 #include <pthread.h>
@@ -9151,7 +9160,7 @@ int main(argc, argv)
 }
 
 EOF
-if { (eval echo configure:9155: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:9164: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   ol_cv_pthread_lpthreads_lmach_lexc_lc_r=yes
 else
@@ -9181,7 +9190,7 @@ fi
 if test "$ol_link_threads" = no ; then
        # try -lpthreads -lmach -lexc
        echo $ac_n "checking for pthread link with -lpthreads -lmach -lexc""... $ac_c" 1>&6
-echo "configure:9185: checking for pthread link with -lpthreads -lmach -lexc" >&5
+echo "configure:9194: checking for pthread link with -lpthreads -lmach -lexc" >&5
 if eval "test \"\${ol_cv_pthread_lpthreads_lmach_lexc+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -9192,7 +9201,7 @@ else
 
                if test "$cross_compiling" = yes; then
   cat > conftest.$ac_ext <<EOF
-#line 9196 "configure"
+#line 9205 "configure"
 #include "confdefs.h"
 /* pthread test headers */
 #include <pthread.h>
@@ -9248,7 +9257,7 @@ int main() {
 
 ; return 0; }
 EOF
-if { (eval echo configure:9252: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:9261: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   ol_cv_pthread_lpthreads_lmach_lexc=yes
 else
@@ -9260,7 +9269,7 @@ fi
 rm -f conftest*
 else
   cat > conftest.$ac_ext <<EOF
-#line 9264 "configure"
+#line 9273 "configure"
 #include "confdefs.h"
 /* pthread test headers */
 #include <pthread.h>
@@ -9321,7 +9330,7 @@ int main(argc, argv)
 }
 
 EOF
-if { (eval echo configure:9325: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:9334: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   ol_cv_pthread_lpthreads_lmach_lexc=yes
 else
@@ -9351,7 +9360,7 @@ fi
 if test "$ol_link_threads" = no ; then
        # try -lpthreads -lexc
        echo $ac_n "checking for pthread link with -lpthreads -lexc""... $ac_c" 1>&6
-echo "configure:9355: checking for pthread link with -lpthreads -lexc" >&5
+echo "configure:9364: checking for pthread link with -lpthreads -lexc" >&5
 if eval "test \"\${ol_cv_pthread_lpthreads_lexc+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -9362,7 +9371,7 @@ else
 
                if test "$cross_compiling" = yes; then
   cat > conftest.$ac_ext <<EOF
-#line 9366 "configure"
+#line 9375 "configure"
 #include "confdefs.h"
 /* pthread test headers */
 #include <pthread.h>
@@ -9418,7 +9427,7 @@ int main() {
 
 ; return 0; }
 EOF
-if { (eval echo configure:9422: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:9431: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   ol_cv_pthread_lpthreads_lexc=yes
 else
@@ -9430,7 +9439,7 @@ fi
 rm -f conftest*
 else
   cat > conftest.$ac_ext <<EOF
-#line 9434 "configure"
+#line 9443 "configure"
 #include "confdefs.h"
 /* pthread test headers */
 #include <pthread.h>
@@ -9491,7 +9500,7 @@ int main(argc, argv)
 }
 
 EOF
-if { (eval echo configure:9495: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:9504: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   ol_cv_pthread_lpthreads_lexc=yes
 else
@@ -9522,7 +9531,7 @@ fi
 if test "$ol_link_threads" = no ; then
        # try -lpthreads
        echo $ac_n "checking for pthread link with -lpthreads""... $ac_c" 1>&6
-echo "configure:9526: checking for pthread link with -lpthreads" >&5
+echo "configure:9535: checking for pthread link with -lpthreads" >&5
 if eval "test \"\${ol_cv_pthread_lib_lpthreads+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -9533,7 +9542,7 @@ else
 
                if test "$cross_compiling" = yes; then
   cat > conftest.$ac_ext <<EOF
-#line 9537 "configure"
+#line 9546 "configure"
 #include "confdefs.h"
 /* pthread test headers */
 #include <pthread.h>
@@ -9589,7 +9598,7 @@ int main() {
 
 ; return 0; }
 EOF
-if { (eval echo configure:9593: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:9602: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   ol_cv_pthread_lib_lpthreads=yes
 else
@@ -9601,7 +9610,7 @@ fi
 rm -f conftest*
 else
   cat > conftest.$ac_ext <<EOF
-#line 9605 "configure"
+#line 9614 "configure"
 #include "confdefs.h"
 /* pthread test headers */
 #include <pthread.h>
@@ -9662,7 +9671,7 @@ int main(argc, argv)
 }
 
 EOF
-if { (eval echo configure:9666: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:9675: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   ol_cv_pthread_lib_lpthreads=yes
 else
@@ -9704,12 +9713,12 @@ EOF
                                                                                                for ac_func in sched_yield pthread_yield
 do
 echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:9708: checking for $ac_func" >&5
+echo "configure:9717: checking for $ac_func" >&5
 if eval "test \"\${ac_cv_func_$ac_func+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 9713 "configure"
+#line 9722 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func(); below.  */
@@ -9733,7 +9742,7 @@ f = $ac_func;
 
 ; return 0; }
 EOF
-if { (eval echo configure:9737: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:9746: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_func_$ac_func=yes"
 else
@@ -9761,7 +9770,7 @@ done
                        if test $ac_cv_func_sched_yield = no -a \
                                $ac_cv_func_pthread_yield = no ; then
                                                                echo $ac_n "checking for sched_yield in -lrt""... $ac_c" 1>&6
-echo "configure:9765: checking for sched_yield in -lrt" >&5
+echo "configure:9774: checking for sched_yield in -lrt" >&5
 ac_lib_var=`echo rt'_'sched_yield | sed 'y%./+-:%__p__%'`
 if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -9769,7 +9778,7 @@ else
   ac_save_LIBS="$LIBS"
 LIBS="-lrt  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 9773 "configure"
+#line 9782 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -9780,7 +9789,7 @@ int main() {
 sched_yield()
 ; return 0; }
 EOF
-if { (eval echo configure:9784: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:9793: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -9812,12 +9821,12 @@ fi
                                                                                                for ac_func in thr_yield
 do
 echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:9816: checking for $ac_func" >&5
+echo "configure:9825: checking for $ac_func" >&5
 if eval "test \"\${ac_cv_func_$ac_func+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 9821 "configure"
+#line 9830 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func(); below.  */
@@ -9841,7 +9850,7 @@ f = $ac_func;
 
 ; return 0; }
 EOF
-if { (eval echo configure:9845: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:9854: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_func_$ac_func=yes"
 else
@@ -9875,12 +9884,12 @@ done
                                                for ac_func in pthread_kill pthread_rwlock_destroy
 do
 echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:9879: checking for $ac_func" >&5
+echo "configure:9888: checking for $ac_func" >&5
 if eval "test \"\${ac_cv_func_$ac_func+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 9884 "configure"
+#line 9893 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func(); below.  */
@@ -9904,7 +9913,7 @@ f = $ac_func;
 
 ; return 0; }
 EOF
-if { (eval echo configure:9908: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:9917: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_func_$ac_func=yes"
 else
@@ -9930,13 +9939,13 @@ done
 
 
                                                                        echo $ac_n "checking for pthread_detach with <pthread.h>""... $ac_c" 1>&6
-echo "configure:9934: checking for pthread_detach with <pthread.h>" >&5
+echo "configure:9943: checking for pthread_detach with <pthread.h>" >&5
 if eval "test \"\${ol_cv_func_pthread_detach+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   
                                                                cat > conftest.$ac_ext <<EOF
-#line 9940 "configure"
+#line 9949 "configure"
 #include "confdefs.h"
 
 #include <pthread.h>
@@ -9948,7 +9957,7 @@ int main() {
 pthread_detach(NULL);
 ; return 0; }
 EOF
-if { (eval echo configure:9952: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:9961: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   ol_cv_func_pthread_detach=yes
 else
@@ -9980,12 +9989,12 @@ EOF
                        
 do
 echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:9984: checking for $ac_func" >&5
+echo "configure:9993: checking for $ac_func" >&5
 if eval "test \"\${ac_cv_func_$ac_func+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 9989 "configure"
+#line 9998 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func(); below.  */
@@ -10009,7 +10018,7 @@ f = $ac_func;
 
 ; return 0; }
 EOF
-if { (eval echo configure:10013: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:10022: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_func_$ac_func=yes"
 else
@@ -10038,12 +10047,12 @@ done
        for ac_func in pthread_kill_other_threads_np
 do
 echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:10042: checking for $ac_func" >&5
+echo "configure:10051: checking for $ac_func" >&5
 if eval "test \"\${ac_cv_func_$ac_func+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 10047 "configure"
+#line 10056 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func(); below.  */
@@ -10067,7 +10076,7 @@ f = $ac_func;
 
 ; return 0; }
 EOF
-if { (eval echo configure:10071: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:10080: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_func_$ac_func=yes"
 else
@@ -10092,7 +10101,7 @@ fi
 done
 
        echo $ac_n "checking for LinuxThreads implementation""... $ac_c" 1>&6
-echo "configure:10096: checking for LinuxThreads implementation" >&5
+echo "configure:10105: checking for LinuxThreads implementation" >&5
 if eval "test \"\${ol_cv_sys_linux_threads+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -10105,7 +10114,7 @@ echo "$ac_t""$ol_cv_sys_linux_threads" 1>&6
        
        
        echo $ac_n "checking for LinuxThreads consistency""... $ac_c" 1>&6
-echo "configure:10109: checking for LinuxThreads consistency" >&5
+echo "configure:10118: checking for LinuxThreads consistency" >&5
 if eval "test \"\${ol_cv_linux_threads+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -10130,7 +10139,7 @@ echo "$ac_t""$ol_cv_linux_threads" 1>&6
                        fi
 
                        echo $ac_n "checking if pthread_create() works""... $ac_c" 1>&6
-echo "configure:10134: checking if pthread_create() works" >&5
+echo "configure:10143: checking if pthread_create() works" >&5
 if eval "test \"\${ol_cv_pthread_create_works+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -10139,7 +10148,7 @@ else
                                ol_cv_pthread_create_works=yes
 else
   cat > conftest.$ac_ext <<EOF
-#line 10143 "configure"
+#line 10152 "configure"
 #include "confdefs.h"
 /* pthread test headers */
 #include <pthread.h>
@@ -10200,7 +10209,7 @@ int main(argc, argv)
 }
 
 EOF
-if { (eval echo configure:10204: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:10213: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   ol_cv_pthread_create_works=yes
 else
@@ -10222,7 +10231,7 @@ echo "$ac_t""$ol_cv_pthread_create_works" 1>&6
 
                                                if test $ol_with_yielding_select = auto ; then
                                echo $ac_n "checking if select yields when using pthreads""... $ac_c" 1>&6
-echo "configure:10226: checking if select yields when using pthreads" >&5
+echo "configure:10235: checking if select yields when using pthreads" >&5
 if eval "test \"\${ol_cv_pthread_select_yields+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -10231,7 +10240,7 @@ else
   ol_cv_pthread_select_yields=cross
 else
   cat > conftest.$ac_ext <<EOF
-#line 10235 "configure"
+#line 10244 "configure"
 #include "confdefs.h"
 
 #include <sys/types.h>
@@ -10307,7 +10316,7 @@ int main(argc, argv)
        exit(2);
 }
 EOF
-if { (eval echo configure:10311: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:10320: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   ol_cv_pthread_select_yields=no
 else
@@ -10351,17 +10360,17 @@ if test $ol_with_threads = auto -o $ol_with_threads = yes \
 do
 ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:10355: checking for $ac_hdr" >&5
+echo "configure:10364: checking for $ac_hdr" >&5
 if eval "test \"\${ac_cv_header_$ac_safe+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 10360 "configure"
+#line 10369 "configure"
 #include "confdefs.h"
 #include <$ac_hdr>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:10365: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:10374: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -10391,12 +10400,12 @@ done
                ol_with_threads=found
 
                                echo $ac_n "checking for cthread_fork""... $ac_c" 1>&6
-echo "configure:10395: checking for cthread_fork" >&5
+echo "configure:10404: checking for cthread_fork" >&5
 if eval "test \"\${ac_cv_func_cthread_fork+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 10400 "configure"
+#line 10409 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char cthread_fork(); below.  */
@@ -10420,7 +10429,7 @@ f = cthread_fork;
 
 ; return 0; }
 EOF
-if { (eval echo configure:10424: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:10433: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_func_cthread_fork=yes"
 else
@@ -10442,7 +10451,7 @@ fi
 
                if test $ol_link_threads = no ; then
                                                                        echo $ac_n "checking for cthread_fork with -all_load""... $ac_c" 1>&6
-echo "configure:10446: checking for cthread_fork with -all_load" >&5
+echo "configure:10455: checking for cthread_fork with -all_load" >&5
 if eval "test \"\${ol_cv_cthread_all_load+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -10450,7 +10459,7 @@ else
                                                                save_LIBS="$LIBS"
                                LIBS="-all_load $LIBS"
                                cat > conftest.$ac_ext <<EOF
-#line 10454 "configure"
+#line 10463 "configure"
 #include "confdefs.h"
 #include <mach/cthreads.h>
 int main() {
@@ -10459,7 +10468,7 @@ int main() {
                                        
 ; return 0; }
 EOF
-if { (eval echo configure:10463: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:10472: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   ol_cv_cthread_all_load=yes
 else
@@ -10504,17 +10513,17 @@ if test $ol_with_threads = auto -o $ol_with_threads = yes \
 do
 ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:10508: checking for $ac_hdr" >&5
+echo "configure:10517: checking for $ac_hdr" >&5
 if eval "test \"\${ac_cv_header_$ac_safe+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 10513 "configure"
+#line 10522 "configure"
 #include "confdefs.h"
 #include <$ac_hdr>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:10518: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:10527: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -10543,7 +10552,7 @@ done
 
        if test $ac_cv_header_pth_h = yes ; then
                echo $ac_n "checking for pth_version in -lpth""... $ac_c" 1>&6
-echo "configure:10547: checking for pth_version in -lpth" >&5
+echo "configure:10556: checking for pth_version in -lpth" >&5
 ac_lib_var=`echo pth'_'pth_version | sed 'y%./+-:%__p__%'`
 if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -10551,7 +10560,7 @@ else
   ac_save_LIBS="$LIBS"
 LIBS="-lpth  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 10555 "configure"
+#line 10564 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -10562,7 +10571,7 @@ int main() {
 pth_version()
 ; return 0; }
 EOF
-if { (eval echo configure:10566: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:10575: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -10606,17 +10615,17 @@ if test $ol_with_threads = auto -o $ol_with_threads = yes \
 do
 ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:10610: checking for $ac_hdr" >&5
+echo "configure:10619: checking for $ac_hdr" >&5
 if eval "test \"\${ac_cv_header_$ac_safe+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 10615 "configure"
+#line 10624 "configure"
 #include "confdefs.h"
 #include <$ac_hdr>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:10620: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:10629: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -10644,7 +10653,7 @@ done
 
        if test $ac_cv_header_thread_h = yes -a $ac_cv_header_synch_h = yes ; then
                echo $ac_n "checking for thr_create in -lthread""... $ac_c" 1>&6
-echo "configure:10648: checking for thr_create in -lthread" >&5
+echo "configure:10657: checking for thr_create in -lthread" >&5
 ac_lib_var=`echo thread'_'thr_create | sed 'y%./+-:%__p__%'`
 if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -10652,7 +10661,7 @@ else
   ac_save_LIBS="$LIBS"
 LIBS="-lthread  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 10656 "configure"
+#line 10665 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -10663,7 +10672,7 @@ int main() {
 thr_create()
 ; return 0; }
 EOF
-if { (eval echo configure:10667: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:10676: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -10703,12 +10712,12 @@ EOF
                        
 do
 echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:10707: checking for $ac_func" >&5
+echo "configure:10716: checking for $ac_func" >&5
 if eval "test \"\${ac_cv_func_$ac_func+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 10712 "configure"
+#line 10721 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func(); below.  */
@@ -10732,7 +10741,7 @@ f = $ac_func;
 
 ; return 0; }
 EOF
-if { (eval echo configure:10736: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:10745: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_func_$ac_func=yes"
 else
@@ -10763,17 +10772,17 @@ done
 do
 ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:10767: checking for $ac_hdr" >&5
+echo "configure:10776: checking for $ac_hdr" >&5
 if eval "test \"\${ac_cv_header_$ac_safe+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 10772 "configure"
+#line 10781 "configure"
 #include "confdefs.h"
 #include <$ac_hdr>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:10777: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:10786: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -10801,7 +10810,7 @@ done
 
        if test $ac_cv_header_lwp_lwp_h = yes ; then
                echo $ac_n "checking for lwp_create in -llwp""... $ac_c" 1>&6
-echo "configure:10805: checking for lwp_create in -llwp" >&5
+echo "configure:10814: checking for lwp_create in -llwp" >&5
 ac_lib_var=`echo lwp'_'lwp_create | sed 'y%./+-:%__p__%'`
 if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -10809,7 +10818,7 @@ else
   ac_save_LIBS="$LIBS"
 LIBS="-llwp  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 10813 "configure"
+#line 10822 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -10820,7 +10829,7 @@ int main() {
 lwp_create()
 ; return 0; }
 EOF
-if { (eval echo configure:10824: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:10833: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -10873,17 +10882,17 @@ if test $ol_with_threads = manual ; then
 do
 ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:10877: checking for $ac_hdr" >&5
+echo "configure:10886: checking for $ac_hdr" >&5
 if eval "test \"\${ac_cv_header_$ac_safe+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 10882 "configure"
+#line 10891 "configure"
 #include "confdefs.h"
 #include <$ac_hdr>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:10887: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:10896: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -10912,12 +10921,12 @@ done
        for ac_func in sched_yield pthread_yield
 do
 echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:10916: checking for $ac_func" >&5
+echo "configure:10925: checking for $ac_func" >&5
 if eval "test \"\${ac_cv_func_$ac_func+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 10921 "configure"
+#line 10930 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func(); below.  */
@@ -10941,7 +10950,7 @@ f = $ac_func;
 
 ; return 0; }
 EOF
-if { (eval echo configure:10945: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:10954: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_func_$ac_func=yes"
 else
@@ -10967,12 +10976,12 @@ done
 
        
        echo $ac_n "checking for LinuxThreads pthread.h""... $ac_c" 1>&6
-echo "configure:10971: checking for LinuxThreads pthread.h" >&5
+echo "configure:10980: checking for LinuxThreads pthread.h" >&5
 if eval "test \"\${ol_cv_header_linux_threads+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 10976 "configure"
+#line 10985 "configure"
 #include "confdefs.h"
 #include <pthread.h>
 EOF
@@ -11002,17 +11011,17 @@ EOF
 do
 ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:11006: checking for $ac_hdr" >&5
+echo "configure:11015: checking for $ac_hdr" >&5
 if eval "test \"\${ac_cv_header_$ac_safe+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 11011 "configure"
+#line 11020 "configure"
 #include "confdefs.h"
 #include <$ac_hdr>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:11016: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:11025: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -11042,17 +11051,17 @@ done
 do
 ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:11046: checking for $ac_hdr" >&5
+echo "configure:11055: checking for $ac_hdr" >&5
 if eval "test \"\${ac_cv_header_$ac_safe+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 11051 "configure"
+#line 11060 "configure"
 #include "confdefs.h"
 #include <$ac_hdr>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:11056: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:11065: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -11082,17 +11091,17 @@ done
 do
 ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:11086: checking for $ac_hdr" >&5
+echo "configure:11095: checking for $ac_hdr" >&5
 if eval "test \"\${ac_cv_header_$ac_safe+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 11091 "configure"
+#line 11100 "configure"
 #include "confdefs.h"
 #include <$ac_hdr>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:11096: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:11105: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -11151,20 +11160,20 @@ EOF
 
 
                        echo $ac_n "checking for thread specific errno""... $ac_c" 1>&6
-echo "configure:11155: checking for thread specific errno" >&5
+echo "configure:11164: checking for thread specific errno" >&5
 if eval "test \"\${ol_cv_errno_thread_specific+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   
                cat > conftest.$ac_ext <<EOF
-#line 11161 "configure"
+#line 11170 "configure"
 #include "confdefs.h"
 #include <errno.h>
 int main() {
 errno = 0;
 ; return 0; }
 EOF
-if { (eval echo configure:11168: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:11177: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   ol_cv_errno_thread_specific=yes
 else
 echo "$ac_t""$ol_cv_errno_thread_specific" 1>&6
 
                        echo $ac_n "checking for thread specific h_errno""... $ac_c" 1>&6
-echo "configure:11184: checking for thread specific h_errno" >&5
+echo "configure:11193: checking for thread specific h_errno" >&5
 if eval "test \"\${ol_cv_h_errno_thread_specific+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   
                cat > conftest.$ac_ext <<EOF
-#line 11190 "configure"
+#line 11199 "configure"
 #include "confdefs.h"
 #include <netdb.h>
 int main() {
 h_errno = 0;
 ; return 0; }
 EOF
-if { (eval echo configure:11197: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:11206: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   ol_cv_h_errno_thread_specific=yes
 else
@@ -11252,17 +11261,17 @@ for ac_hdr in db_185.h db.h
 do
 ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:11256: checking for $ac_hdr" >&5
+echo "configure:11265: checking for $ac_hdr" >&5
 if eval "test \"\${ac_cv_header_$ac_safe+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 11261 "configure"
+#line 11270 "configure"
 #include "confdefs.h"
 #include <$ac_hdr>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:11266: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:11275: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -11290,13 +11299,13 @@ done
 
 if test $ac_cv_header_db_185_h = yes -o $ac_cv_header_db_h = yes; then
        echo $ac_n "checking if Berkeley DB header compatibility""... $ac_c" 1>&6
-echo "configure:11294: checking if Berkeley DB header compatibility" >&5
+echo "configure:11303: checking if Berkeley DB header compatibility" >&5
 if eval "test \"\${ol_cv_header_db1+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   
                cat > conftest.$ac_ext <<EOF
-#line 11300 "configure"
+#line 11309 "configure"
 #include "confdefs.h"
 
 #if HAVE_DB_185_H
@@ -11333,7 +11342,7 @@ echo "$ac_t""$ol_cv_header_db1" 1>&6
                ol_cv_lib_db=no
 if test $ol_cv_lib_db = no ; then
        echo $ac_n "checking for Berkeley DB link (default)""... $ac_c" 1>&6
-echo "configure:11337: checking for Berkeley DB link (default)" >&5
+echo "configure:11346: checking for Berkeley DB link (default)" >&5
 if eval "test \"\${ol_cv_db_none+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -11343,7 +11352,7 @@ else
        LIBS="$ol_DB_LIB $LIBS"
 
        cat > conftest.$ac_ext <<EOF
-#line 11347 "configure"
+#line 11356 "configure"
 #include "confdefs.h"
 
 #ifdef HAVE_DB_185_H
@@ -11372,7 +11381,7 @@ int main() {
 
 ; return 0; }
 EOF
-if { (eval echo configure:11376: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:11385: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   ol_cv_db_none=yes
 else
@@ -11396,7 +11405,7 @@ fi
 
 if test $ol_cv_lib_db = no ; then
        echo $ac_n "checking for Berkeley DB link (-ldb)""... $ac_c" 1>&6
-echo "configure:11400: checking for Berkeley DB link (-ldb)" >&5
+echo "configure:11409: checking for Berkeley DB link (-ldb)" >&5
 if eval "test \"\${ol_cv_db_db+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -11406,7 +11415,7 @@ else
        LIBS="$ol_DB_LIB $LIBS"
 
        cat > conftest.$ac_ext <<EOF
-#line 11410 "configure"
+#line 11419 "configure"
 #include "confdefs.h"
 
 #ifdef HAVE_DB_185_H
@@ -11435,7 +11444,7 @@ int main() {
 
 ; return 0; }
 EOF
-if { (eval echo configure:11439: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:11448: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   ol_cv_db_db=yes
 else
@@ -11459,7 +11468,7 @@ fi
 
 if test $ol_cv_lib_db = no ; then
        echo $ac_n "checking for Berkeley DB link (-ldb3)""... $ac_c" 1>&6
-echo "configure:11463: checking for Berkeley DB link (-ldb3)" >&5
+echo "configure:11472: checking for Berkeley DB link (-ldb3)" >&5
 if eval "test \"\${ol_cv_db_db3+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -11469,7 +11478,7 @@ else
        LIBS="$ol_DB_LIB $LIBS"
 
        cat > conftest.$ac_ext <<EOF
-#line 11473 "configure"
+#line 11482 "configure"
 #include "confdefs.h"
 
 #ifdef HAVE_DB_185_H
@@ -11498,7 +11507,7 @@ int main() {
 
 ; return 0; }
 EOF
-if { (eval echo configure:11502: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:11511: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   ol_cv_db_db3=yes
 else
@@ -11522,7 +11531,7 @@ fi
 
 if test $ol_cv_lib_db = no ; then
        echo $ac_n "checking for Berkeley DB link (-ldb2)""... $ac_c" 1>&6
-echo "configure:11526: checking for Berkeley DB link (-ldb2)" >&5
+echo "configure:11535: checking for Berkeley DB link (-ldb2)" >&5
 if eval "test \"\${ol_cv_db_db2+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -11532,7 +11541,7 @@ else
        LIBS="$ol_DB_LIB $LIBS"
 
        cat > conftest.$ac_ext <<EOF
-#line 11536 "configure"
+#line 11545 "configure"
 #include "confdefs.h"
 
 #ifdef HAVE_DB_185_H
@@ -11561,7 +11570,7 @@ int main() {
 
 ; return 0; }
 EOF
-if { (eval echo configure:11565: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:11574: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   ol_cv_db_db2=yes
 else
@@ -11585,7 +11594,7 @@ fi
 
 if test $ol_cv_lib_db = no ; then
        echo $ac_n "checking for Berkeley DB link (-ldb1)""... $ac_c" 1>&6
-echo "configure:11589: checking for Berkeley DB link (-ldb1)" >&5
+echo "configure:11598: checking for Berkeley DB link (-ldb1)" >&5
 if eval "test \"\${ol_cv_db_db1+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -11595,7 +11604,7 @@ else
        LIBS="$ol_DB_LIB $LIBS"
 
        cat > conftest.$ac_ext <<EOF
-#line 11599 "configure"
+#line 11608 "configure"
 #include "confdefs.h"
 
 #ifdef HAVE_DB_185_H
@@ -11624,7 +11633,7 @@ int main() {
 
 ; return 0; }
 EOF
-if { (eval echo configure:11628: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:11637: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   ol_cv_db_db1=yes
 else
@@ -11659,17 +11668,17 @@ for ac_hdr in db.h
 do
 ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:11663: checking for $ac_hdr" >&5
+echo "configure:11672: checking for $ac_hdr" >&5
 if eval "test \"\${ac_cv_header_$ac_safe+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 11668 "configure"
+#line 11677 "configure"
 #include "confdefs.h"
 #include <$ac_hdr>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:11673: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:11682: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -11699,7 +11708,7 @@ if test $ac_cv_header_db_h = yes; then
        ol_cv_lib_db=no
 if test $ol_cv_lib_db = no ; then
        echo $ac_n "checking for Berkeley DB link (default)""... $ac_c" 1>&6
-echo "configure:11703: checking for Berkeley DB link (default)" >&5
+echo "configure:11712: checking for Berkeley DB link (default)" >&5
 if eval "test \"\${ol_cv_db_none+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -11709,7 +11718,7 @@ else
        LIBS="$ol_DB_LIB $LIBS"
 
        cat > conftest.$ac_ext <<EOF
-#line 11713 "configure"
+#line 11722 "configure"
 #include "confdefs.h"
 
 #ifdef HAVE_DB_185_H
@@ -11738,7 +11747,7 @@ int main() {
 
 ; return 0; }
 EOF
-if { (eval echo configure:11742: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:11751: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   ol_cv_db_none=yes
 else
@@ -11762,7 +11771,7 @@ fi
 
 if test $ol_cv_lib_db = no ; then
        echo $ac_n "checking for Berkeley DB link (-ldb)""... $ac_c" 1>&6
-echo "configure:11766: checking for Berkeley DB link (-ldb)" >&5
+echo "configure:11775: checking for Berkeley DB link (-ldb)" >&5
 if eval "test \"\${ol_cv_db_db+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -11772,7 +11781,7 @@ else
        LIBS="$ol_DB_LIB $LIBS"
 
        cat > conftest.$ac_ext <<EOF
-#line 11776 "configure"
+#line 11785 "configure"
 #include "confdefs.h"
 
 #ifdef HAVE_DB_185_H
@@ -11801,7 +11810,7 @@ int main() {
 
 ; return 0; }
 EOF
-if { (eval echo configure:11805: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:11814: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   ol_cv_db_db=yes
 else
@@ -11825,7 +11834,7 @@ fi
 
 if test $ol_cv_lib_db = no ; then
        echo $ac_n "checking for Berkeley DB link (-ldb3)""... $ac_c" 1>&6
-echo "configure:11829: checking for Berkeley DB link (-ldb3)" >&5
+echo "configure:11838: checking for Berkeley DB link (-ldb3)" >&5
 if eval "test \"\${ol_cv_db_db3+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -11835,7 +11844,7 @@ else
        LIBS="$ol_DB_LIB $LIBS"
 
        cat > conftest.$ac_ext <<EOF
-#line 11839 "configure"
+#line 11848 "configure"
 #include "confdefs.h"
 
 #ifdef HAVE_DB_185_H
@@ -11864,7 +11873,7 @@ int main() {
 
 ; return 0; }
 EOF
-if { (eval echo configure:11868: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:11877: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   ol_cv_db_db3=yes
 else
@@ -11888,7 +11897,7 @@ fi
 
 if test $ol_cv_lib_db = no ; then
        echo $ac_n "checking for Berkeley DB link (-ldb2)""... $ac_c" 1>&6
-echo "configure:11892: checking for Berkeley DB link (-ldb2)" >&5
+echo "configure:11901: checking for Berkeley DB link (-ldb2)" >&5
 if eval "test \"\${ol_cv_db_db2+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -11898,7 +11907,7 @@ else
        LIBS="$ol_DB_LIB $LIBS"
 
        cat > conftest.$ac_ext <<EOF
-#line 11902 "configure"
+#line 11911 "configure"
 #include "confdefs.h"
 
 #ifdef HAVE_DB_185_H
@@ -11927,7 +11936,7 @@ int main() {
 
 ; return 0; }
 EOF
-if { (eval echo configure:11931: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:11940: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   ol_cv_db_db2=yes
 else
@@ -11951,7 +11960,7 @@ fi
 
 if test $ol_cv_lib_db = no ; then
        echo $ac_n "checking for Berkeley DB link (-ldb1)""... $ac_c" 1>&6
-echo "configure:11955: checking for Berkeley DB link (-ldb1)" >&5
+echo "configure:11964: checking for Berkeley DB link (-ldb1)" >&5
 if eval "test \"\${ol_cv_db_db1+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -11961,7 +11970,7 @@ else
        LIBS="$ol_DB_LIB $LIBS"
 
        cat > conftest.$ac_ext <<EOF
-#line 11965 "configure"
+#line 11974 "configure"
 #include "confdefs.h"
 
 #ifdef HAVE_DB_185_H
@@ -11990,7 +11999,7 @@ int main() {
 
 ; return 0; }
 EOF
-if { (eval echo configure:11994: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:12003: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   ol_cv_db_db1=yes
 else
@@ -12016,7 +12025,7 @@ fi
        if test "$ol_cv_lib_db" != no ; then
                ol_cv_berkeley_db=yes
                echo $ac_n "checking for Berkeley DB thread support""... $ac_c" 1>&6
-echo "configure:12020: checking for Berkeley DB thread support" >&5
+echo "configure:12029: checking for Berkeley DB thread support" >&5
 if eval "test \"\${ol_cv_berkeley_db_thread+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -12030,7 +12039,7 @@ else
   ol_cv_berkeley_db_thread=cross
 else
   cat > conftest.$ac_ext <<EOF
-#line 12034 "configure"
+#line 12043 "configure"
 #include "confdefs.h"
 
 #ifdef HAVE_DB_185_H
@@ -12070,7 +12079,7 @@ main()
        return rc;
 }
 EOF
-if { (eval echo configure:12074: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:12083: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   ol_cv_berkeley_db_thread=yes
 else
 
 if test $ol_with_ldbm_api = auto -o $ol_with_ldbm_api = mdbm ; then
        echo $ac_n "checking for MDBM library""... $ac_c" 1>&6
-echo "configure:12138: checking for MDBM library" >&5
+echo "configure:12147: checking for MDBM library" >&5
 if eval "test \"\${ol_cv_lib_mdbm+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
        ol_LIBS="$LIBS"
        echo $ac_n "checking for mdbm_set_chain""... $ac_c" 1>&6
-echo "configure:12144: checking for mdbm_set_chain" >&5
+echo "configure:12153: checking for mdbm_set_chain" >&5
 if eval "test \"\${ac_cv_func_mdbm_set_chain+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 12149 "configure"
+#line 12158 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char mdbm_set_chain(); below.  */
@@ -12169,7 +12178,7 @@ f = mdbm_set_chain;
 
 ; return 0; }
 EOF
-if { (eval echo configure:12173: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:12182: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_func_mdbm_set_chain=yes"
 else
@@ -12188,7 +12197,7 @@ else
   echo "$ac_t""no" 1>&6
 
                echo $ac_n "checking for mdbm_set_chain in -lmdbm""... $ac_c" 1>&6
-echo "configure:12192: checking for mdbm_set_chain in -lmdbm" >&5
+echo "configure:12201: checking for mdbm_set_chain in -lmdbm" >&5
 ac_lib_var=`echo mdbm'_'mdbm_set_chain | sed 'y%./+-:%__p__%'`
 if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -12196,7 +12205,7 @@ else
   ac_save_LIBS="$LIBS"
 LIBS="-lmdbm  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 12200 "configure"
+#line 12209 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -12207,7 +12216,7 @@ int main() {
 mdbm_set_chain()
 ; return 0; }
 EOF
-if { (eval echo configure:12211: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:12220: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -12242,17 +12251,17 @@ echo "$ac_t""$ol_cv_lib_mdbm" 1>&6
 do
 ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:12246: checking for $ac_hdr" >&5
+echo "configure:12255: checking for $ac_hdr" >&5
 if eval "test \"\${ac_cv_header_$ac_safe+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 12251 "configure"
+#line 12260 "configure"
 #include "confdefs.h"
 #include <$ac_hdr>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:12256: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:12265: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -12279,7 +12288,7 @@ fi
 done
 
  echo $ac_n "checking for db""... $ac_c" 1>&6
-echo "configure:12283: checking for db" >&5
+echo "configure:12292: checking for db" >&5
 if eval "test \"\${ol_cv_mdbm+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
 
 if test $ol_with_ldbm_api = auto -o $ol_with_ldbm_api = gdbm ; then
        echo $ac_n "checking for GDBM library""... $ac_c" 1>&6
-echo "configure:12316: checking for GDBM library" >&5
+echo "configure:12325: checking for GDBM library" >&5
 if eval "test \"\${ol_cv_lib_gdbm+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
        ol_LIBS="$LIBS"
        echo $ac_n "checking for gdbm_open""... $ac_c" 1>&6
-echo "configure:12322: checking for gdbm_open" >&5
+echo "configure:12331: checking for gdbm_open" >&5
 if eval "test \"\${ac_cv_func_gdbm_open+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 12327 "configure"
+#line 12336 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char gdbm_open(); below.  */
@@ -12347,7 +12356,7 @@ f = gdbm_open;
 
 ; return 0; }
 EOF
-if { (eval echo configure:12351: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:12360: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_func_gdbm_open=yes"
 else
@@ -12366,7 +12375,7 @@ else
   echo "$ac_t""no" 1>&6
 
                echo $ac_n "checking for gdbm_open in -lgdbm""... $ac_c" 1>&6
-echo "configure:12370: checking for gdbm_open in -lgdbm" >&5
+echo "configure:12379: checking for gdbm_open in -lgdbm" >&5
 ac_lib_var=`echo gdbm'_'gdbm_open | sed 'y%./+-:%__p__%'`
 if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -12374,7 +12383,7 @@ else
   ac_save_LIBS="$LIBS"
 LIBS="-lgdbm  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 12378 "configure"
+#line 12387 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -12385,7 +12394,7 @@ int main() {
 gdbm_open()
 ; return 0; }
 EOF
-if { (eval echo configure:12389: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:12398: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -12420,17 +12429,17 @@ echo "$ac_t""$ol_cv_lib_gdbm" 1>&6
 do
 ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:12424: checking for $ac_hdr" >&5
+echo "configure:12433: checking for $ac_hdr" >&5
 if eval "test \"\${ac_cv_header_$ac_safe+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 12429 "configure"
+#line 12438 "configure"
 #include "confdefs.h"
 #include <$ac_hdr>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:12434: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:12443: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -12457,7 +12466,7 @@ fi
 done
 
  echo $ac_n "checking for db""... $ac_c" 1>&6
-echo "configure:12461: checking for db" >&5
+echo "configure:12470: checking for db" >&5
 if eval "test \"\${ol_cv_gdbm+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
 
 if test $ol_with_ldbm_api = ndbm ; then
        echo $ac_n "checking for NDBM library""... $ac_c" 1>&6
-echo "configure:12495: checking for NDBM library" >&5
+echo "configure:12504: checking for NDBM library" >&5
 if eval "test \"\${ol_cv_lib_ndbm+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
        ol_LIBS="$LIBS"
        echo $ac_n "checking for dbm_open""... $ac_c" 1>&6
-echo "configure:12501: checking for dbm_open" >&5
+echo "configure:12510: checking for dbm_open" >&5
 if eval "test \"\${ac_cv_func_dbm_open+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 12506 "configure"
+#line 12515 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char dbm_open(); below.  */
@@ -12526,7 +12535,7 @@ f = dbm_open;
 
 ; return 0; }
 EOF
-if { (eval echo configure:12530: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:12539: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_func_dbm_open=yes"
 else
@@ -12545,7 +12554,7 @@ else
   echo "$ac_t""no" 1>&6
 
                echo $ac_n "checking for dbm_open in -lndbm""... $ac_c" 1>&6
-echo "configure:12549: checking for dbm_open in -lndbm" >&5
+echo "configure:12558: checking for dbm_open in -lndbm" >&5
 ac_lib_var=`echo ndbm'_'dbm_open | sed 'y%./+-:%__p__%'`
 if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -12553,7 +12562,7 @@ else
   ac_save_LIBS="$LIBS"
 LIBS="-lndbm  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 12557 "configure"
+#line 12566 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -12564,7 +12573,7 @@ int main() {
 dbm_open()
 ; return 0; }
 EOF
-if { (eval echo configure:12568: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:12577: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -12584,7 +12593,7 @@ else
   echo "$ac_t""no" 1>&6
 
                        echo $ac_n "checking for dbm_open in -ldbm""... $ac_c" 1>&6
-echo "configure:12588: checking for dbm_open in -ldbm" >&5
+echo "configure:12597: checking for dbm_open in -ldbm" >&5
 ac_lib_var=`echo dbm'_'dbm_open | sed 'y%./+-:%__p__%'`
 if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -12592,7 +12601,7 @@ else
   ac_save_LIBS="$LIBS"
 LIBS="-ldbm  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 12596 "configure"
+#line 12605 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -12603,7 +12612,7 @@ int main() {
 dbm_open()
 ; return 0; }
 EOF
-if { (eval echo configure:12607: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:12616: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -12640,17 +12649,17 @@ echo "$ac_t""$ol_cv_lib_ndbm" 1>&6
 do
 ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:12644: checking for $ac_hdr" >&5
+echo "configure:12653: checking for $ac_hdr" >&5
 if eval "test \"\${ac_cv_header_$ac_safe+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 12649 "configure"
+#line 12658 "configure"
 #include "confdefs.h"
 #include <$ac_hdr>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:12654: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:12663: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -12677,7 +12686,7 @@ fi
 done
 
  echo $ac_n "checking for db""... $ac_c" 1>&6
-echo "configure:12681: checking for db" >&5
+echo "configure:12690: checking for db" >&5
 if eval "test \"\${ol_cv_ndbm+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -12730,17 +12739,17 @@ if test $ol_enable_wrappers != no ; then
 do
 ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:12734: checking for $ac_hdr" >&5
+echo "configure:12743: checking for $ac_hdr" >&5
 if eval "test \"\${ac_cv_header_$ac_safe+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 12739 "configure"
+#line 12748 "configure"
 #include "confdefs.h"
 #include <$ac_hdr>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:12744: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:12753: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -12771,7 +12780,7 @@ done
                have_wrappers=no
        else
                cat > conftest.$ac_ext <<EOF
-#line 12775 "configure"
+#line 12784 "configure"
 #include "confdefs.h"
 
 int allow_severity = 0;
@@ -12781,7 +12790,7 @@ int main() {
 hosts_access()
 ; return 0; }
 EOF
-if { (eval echo configure:12785: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:12794: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   have_wrappers=yes
 else
@@ -12801,7 +12810,7 @@ EOF
                WRAP_LIBS="-lwrap"
 
                                                echo $ac_n "checking for main in -lnsl""... $ac_c" 1>&6
-echo "configure:12805: checking for main in -lnsl" >&5
+echo "configure:12814: checking for main in -lnsl" >&5
 ac_lib_var=`echo nsl'_'main | sed 'y%./+-:%__p__%'`
 if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -12809,14 +12818,14 @@ else
   ac_save_LIBS="$LIBS"
 LIBS="-lnsl  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 12813 "configure"
+#line 12822 "configure"
 #include "confdefs.h"
 
 int main() {
 main()
 ; return 0; }
 EOF
-if { (eval echo configure:12820: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:12829: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
 
 if test $ol_enable_syslog != no ; then
        echo $ac_n "checking for openlog""... $ac_c" 1>&6
-echo "configure:12861: checking for openlog" >&5
+echo "configure:12870: checking for openlog" >&5
 if eval "test \"\${ac_cv_func_openlog+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 12866 "configure"
+#line 12875 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char openlog(); below.  */
@@ -12886,7 +12895,7 @@ f = openlog;
 
 ; return 0; }
 EOF
-if { (eval echo configure:12890: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:12899: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_func_openlog=yes"
 else
@@ -12916,17 +12925,17 @@ for ac_hdr in termcap.h ncurses.h
 do
 ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:12920: checking for $ac_hdr" >&5
+echo "configure:12929: checking for $ac_hdr" >&5
 if eval "test \"\${ac_cv_header_$ac_safe+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 12925 "configure"
+#line 12934 "configure"
 #include "confdefs.h"
 #include <$ac_hdr>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:12930: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:12939: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -12955,7 +12964,7 @@ done
 
 if test $ol_link_termcap = no ; then
        echo $ac_n "checking for tputs in -ltermcap""... $ac_c" 1>&6
-echo "configure:12959: checking for tputs in -ltermcap" >&5
+echo "configure:12968: checking for tputs in -ltermcap" >&5
 ac_lib_var=`echo termcap'_'tputs | sed 'y%./+-:%__p__%'`
 if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -12963,7 +12972,7 @@ else
   ac_save_LIBS="$LIBS"
 LIBS="-ltermcap  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 12967 "configure"
+#line 12976 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -12974,7 +12983,7 @@ int main() {
 tputs()
 ; return 0; }
 EOF
-if { (eval echo configure:12978: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:12987: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -13007,7 +13016,7 @@ fi
 
 if test $ol_link_termcap = no ; then
        echo $ac_n "checking for initscr in -lncurses""... $ac_c" 1>&6
-echo "configure:13011: checking for initscr in -lncurses" >&5
+echo "configure:13020: checking for initscr in -lncurses" >&5
 ac_lib_var=`echo ncurses'_'initscr | sed 'y%./+-:%__p__%'`
 if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -13015,7 +13024,7 @@ else
   ac_save_LIBS="$LIBS"
 LIBS="-lncurses  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 13019 "configure"
+#line 13028 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -13026,7 +13035,7 @@ int main() {
 initscr()
 ; return 0; }
 EOF
-if { (eval echo configure:13030: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:13039: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -13070,17 +13079,17 @@ ol_link_spasswd=no
 if test $ol_with_cyrus_sasl != no ; then
        ac_safe=`echo "sasl.h" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for sasl.h""... $ac_c" 1>&6
-echo "configure:13074: checking for sasl.h" >&5
+echo "configure:13083: checking for sasl.h" >&5
 if eval "test \"\${ac_cv_header_$ac_safe+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 13079 "configure"
+#line 13088 "configure"
 #include "confdefs.h"
 #include <sasl.h>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:13084: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:13093: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -13104,7 +13113,7 @@ fi
 
        if test $ac_cv_header_sasl_h = yes ; then
                echo $ac_n "checking for sasl_client_init in -lsasl""... $ac_c" 1>&6
-echo "configure:13108: checking for sasl_client_init in -lsasl" >&5
+echo "configure:13117: checking for sasl_client_init in -lsasl" >&5
 ac_lib_var=`echo sasl'_'sasl_client_init | sed 'y%./+-:%__p__%'`
 if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -13112,7 +13121,7 @@ else
   ac_save_LIBS="$LIBS"
 LIBS="-lsasl  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 13116 "configure"
+#line 13125 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -13123,7 +13132,7 @@ int main() {
 sasl_client_init()
 ; return 0; }
 EOF
-if { (eval echo configure:13127: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:13136: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -13155,8 +13164,21 @@ EOF
                fi
        fi
 
-       if test $ol_link_sasl = no -a $ol_with_cyrus_sasl = yes ; then
-               { echo "configure: error: no suitable API for --with-cyrus-sasl=$ol_with_cyrus_sasl" 1>&2; exit 1; }
+       if test $ol_link_sasl = no ; then
+               if test $ol_with_cyrus_sasl != auto ; then
+                       { echo "configure: error: Could not locate Cyrus SASL" 1>&2; exit 1; }
+               else
+                       echo "configure: warning: Could not locate Cyrus SASL" 1>&2
+                       echo "configure: warning: SASL authentication not supported!" 1>&2
+                       if test $ol_link_tls = no ; then
+                               echo "configure: warning: Strong authentication not supported!" 1>&2
+                       fi
+               fi
+       fi
+else
+       echo "configure: warning: SASL authentication not supported!" 1>&2
+       if test $ol_link_tls = no ; then
+               echo "configure: warning: Strong authentication not supported!" 1>&2
        fi
 fi
 
@@ -13187,13 +13209,13 @@ if test $ol_with_fetch != no ; then
        ol_LIBS=$LIBS
 LIBS="-lfetch -lcom_err $LIBS"
 echo $ac_n "checking fetch(3) library""... $ac_c" 1>&6
-echo "configure:13191: checking fetch(3) library" >&5
+echo "configure:13213: checking fetch(3) library" >&5
 if eval "test \"\${ol_cv_lib_fetch+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   
        cat > conftest.$ac_ext <<EOF
-#line 13197 "configure"
+#line 13219 "configure"
 #include "confdefs.h"
 
 #include <sys/param.h>
@@ -13203,7 +13225,7 @@ int main() {
 struct url *u = fetchParseURL("file:///"); 
 ; return 0; }
 EOF
-if { (eval echo configure:13207: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:13229: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   ol_cv_lib_fetch=yes
 else
@@ -13241,17 +13263,17 @@ if test $ol_with_readline != no ; then
 do
 ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:13245: checking for $ac_hdr" >&5
+echo "configure:13267: checking for $ac_hdr" >&5
 if eval "test \"\${ac_cv_header_$ac_safe+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 13250 "configure"
+#line 13272 "configure"
 #include "confdefs.h"
 #include <$ac_hdr>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:13255: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:13277: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -13282,7 +13304,7 @@ done
                save_LIBS="$LIBS"
                LIBS="$TERMCAP_LIBS $LIBS"
                echo $ac_n "checking for readline in -lreadline""... $ac_c" 1>&6
-echo "configure:13286: checking for readline in -lreadline" >&5
+echo "configure:13308: checking for readline in -lreadline" >&5
 ac_lib_var=`echo readline'_'readline | sed 'y%./+-:%__p__%'`
 if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -13290,7 +13312,7 @@ else
   ac_save_LIBS="$LIBS"
 LIBS="-lreadline  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 13294 "configure"
+#line 13316 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -13301,7 +13323,7 @@ int main() {
 readline()
 ; return 0; }
 EOF
-if { (eval echo configure:13305: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:13327: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
 
 if test $ol_enable_crypt != no ; then
        echo $ac_n "checking for crypt""... $ac_c" 1>&6
-echo "configure:13347: checking for crypt" >&5
+echo "configure:13369: checking for crypt" >&5
 if eval "test \"\${ac_cv_func_crypt+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 13352 "configure"
+#line 13374 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char crypt(); below.  */
@@ -13372,7 +13394,7 @@ f = crypt;
 
 ; return 0; }
 EOF
-if { (eval echo configure:13376: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:13398: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_func_crypt=yes"
 else
@@ -13391,7 +13413,7 @@ else
   echo "$ac_t""no" 1>&6
 
                echo $ac_n "checking for crypt in -lcrypt""... $ac_c" 1>&6
-echo "configure:13395: checking for crypt in -lcrypt" >&5
+echo "configure:13417: checking for crypt in -lcrypt" >&5
 ac_lib_var=`echo crypt'_'crypt | sed 'y%./+-:%__p__%'`
 if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -13399,7 +13421,7 @@ else
   ac_save_LIBS="$LIBS"
 LIBS="-lcrypt  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 13403 "configure"
+#line 13425 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -13410,7 +13432,7 @@ int main() {
 crypt()
 ; return 0; }
 EOF
-if { (eval echo configure:13414: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:13436: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
 
 if test $ol_enable_proctitle != no ; then
        echo $ac_n "checking for setproctitle""... $ac_c" 1>&6
-echo "configure:13457: checking for setproctitle" >&5
+echo "configure:13479: checking for setproctitle" >&5
 if eval "test \"\${ac_cv_func_setproctitle+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 13462 "configure"
+#line 13484 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char setproctitle(); below.  */
@@ -13482,7 +13504,7 @@ f = setproctitle;
 
 ; return 0; }
 EOF
-if { (eval echo configure:13486: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:13508: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_func_setproctitle=yes"
 else
@@ -13501,7 +13523,7 @@ else
   echo "$ac_t""no" 1>&6
 
                echo $ac_n "checking for setproctitle in -lutil""... $ac_c" 1>&6
-echo "configure:13505: checking for setproctitle in -lutil" >&5
+echo "configure:13527: checking for setproctitle in -lutil" >&5
 ac_lib_var=`echo util'_'setproctitle | sed 'y%./+-:%__p__%'`
 if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -13509,7 +13531,7 @@ else
   ac_save_LIBS="$LIBS"
 LIBS="-lutil  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 13513 "configure"
+#line 13535 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -13520,7 +13542,7 @@ int main() {
 setproctitle()
 ; return 0; }
 EOF
-if { (eval echo configure:13524: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:13546: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -13556,12 +13578,12 @@ EOF
 fi
 
 echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6
-echo "configure:13560: checking for ANSI C header files" >&5
+echo "configure:13582: checking for ANSI C header files" >&5
 if eval "test \"\${ac_cv_header_stdc+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 13565 "configure"
+#line 13587 "configure"
 #include "confdefs.h"
 #include <stdlib.h>
 #include <stdarg.h>
@@ -13569,7 +13591,7 @@ else
 #include <float.h>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:13573: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:13595: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -13586,7 +13608,7 @@ rm -f conftest*
 if test $ac_cv_header_stdc = yes; then
   # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
 cat > conftest.$ac_ext <<EOF
-#line 13590 "configure"
+#line 13612 "configure"
 #include "confdefs.h"
 #include <string.h>
 EOF
@@ -13604,7 +13626,7 @@ fi
 if test $ac_cv_header_stdc = yes; then
   # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
 cat > conftest.$ac_ext <<EOF
-#line 13608 "configure"
+#line 13630 "configure"
 #include "confdefs.h"
 #include <stdlib.h>
 EOF
@@ -13625,7 +13647,7 @@ if test "$cross_compiling" = yes; then
   :
 else
   cat > conftest.$ac_ext <<EOF
-#line 13629 "configure"
+#line 13651 "configure"
 #include "confdefs.h"
 #include <ctype.h>
 #if ((' ' & 0x0FF) == 0x020)
@@ -13643,7 +13665,7 @@ if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2);
 exit (0); }
 
 EOF
-if { (eval echo configure:13647: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:13669: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   :
 else
@@ -13667,12 +13689,12 @@ EOF
 fi
 
 echo $ac_n "checking for mode_t""... $ac_c" 1>&6
-echo "configure:13671: checking for mode_t" >&5
+echo "configure:13693: checking for mode_t" >&5
 if eval "test \"\${ac_cv_type_mode_t+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 13676 "configure"
+#line 13698 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #if STDC_HEADERS
@@ -13703,12 +13725,12 @@ EOF
 fi
 
 echo $ac_n "checking for off_t""... $ac_c" 1>&6
-echo "configure:13707: checking for off_t" >&5
+echo "configure:13729: checking for off_t" >&5
 if eval "test \"\${ac_cv_type_off_t+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 13712 "configure"
+#line 13734 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #if STDC_HEADERS
@@ -13739,12 +13761,12 @@ EOF
 fi
 
 echo $ac_n "checking for pid_t""... $ac_c" 1>&6
-echo "configure:13743: checking for pid_t" >&5
+echo "configure:13765: checking for pid_t" >&5
 if eval "test \"\${ac_cv_type_pid_t+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 13748 "configure"
+#line 13770 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #if STDC_HEADERS
@@ -13775,19 +13797,19 @@ EOF
 fi
 
 echo $ac_n "checking for ptrdiff_t""... $ac_c" 1>&6
-echo "configure:13779: checking for ptrdiff_t" >&5
+echo "configure:13801: checking for ptrdiff_t" >&5
 if eval "test \"\${am_cv_type_ptrdiff_t+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 13784 "configure"
+#line 13806 "configure"
 #include "confdefs.h"
 #include <stddef.h>
 int main() {
 ptrdiff_t p
 ; return 0; }
 EOF
-if { (eval echo configure:13791: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:13813: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   am_cv_type_ptrdiff_t=yes
 else
@@ -13808,12 +13830,12 @@ EOF
    fi
 
 echo $ac_n "checking return type of signal handlers""... $ac_c" 1>&6
-echo "configure:13812: checking return type of signal handlers" >&5
+echo "configure:13834: checking return type of signal handlers" >&5
 if eval "test \"\${ac_cv_type_signal+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 13817 "configure"
+#line 13839 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #include <signal.h>
@@ -13830,7 +13852,7 @@ int main() {
 int i;
 ; return 0; }
 EOF
-if { (eval echo configure:13834: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:13856: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ac_cv_type_signal=void
 else
@@ -13849,12 +13871,12 @@ EOF
 
 
 echo $ac_n "checking for size_t""... $ac_c" 1>&6
-echo "configure:13853: checking for size_t" >&5
+echo "configure:13875: checking for size_t" >&5
 if eval "test \"\${ac_cv_type_size_t+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 13858 "configure"
+#line 13880 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #if STDC_HEADERS
 
 
 echo $ac_n "checking for ssize_t""... $ac_c" 1>&6
-echo "configure:13890: checking for ssize_t" >&5
+echo "configure:13912: checking for ssize_t" >&5
 if eval "test \"\${ac_cv_type_ssize_t+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 13895 "configure"
+#line 13917 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #if STDC_HEADERS
@@ -13922,12 +13944,12 @@ EOF
 fi
 
 echo $ac_n "checking for caddr_t""... $ac_c" 1>&6
-echo "configure:13926: checking for caddr_t" >&5
+echo "configure:13948: checking for caddr_t" >&5
 if eval "test \"\${ac_cv_type_caddr_t+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 13931 "configure"
+#line 13953 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #if STDC_HEADERS
 
 
 echo $ac_n "checking for socklen_t""... $ac_c" 1>&6
-echo "configure:13963: checking for socklen_t" >&5
+echo "configure:13985: checking for socklen_t" >&5
 if eval "test \"\${ol_cv_type_socklen_t+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 13968 "configure"
+#line 13990 "configure"
 #include "confdefs.h"
 
 #ifdef HAVE_SYS_TYPES_H
@@ -13978,7 +14000,7 @@ int main() {
 socklen_t len;
 ; return 0; }
 EOF
-if { (eval echo configure:13982: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:14004: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ol_cv_type_socklen_t=yes
 else
@@ -13999,12 +14021,12 @@ EOF
   fi
  
 echo $ac_n "checking for member st_blksize in aggregate type struct stat""... $ac_c" 1>&6
-echo "configure:14003: checking for member st_blksize in aggregate type struct stat" >&5
+echo "configure:14025: checking for member st_blksize in aggregate type struct stat" >&5
 if eval "test \"\${ac_cv_c_struct_member_st_blksize+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 14008 "configure"
+#line 14030 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -14012,7 +14034,7 @@ int main() {
 struct stat foo; foo.st_blksize;
 ; return 0; }
 EOF
-if { (eval echo configure:14016: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:14038: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ac_cv_c_struct_member_st_blksize=yes
 else
@@ -14034,12 +14056,12 @@ EOF
 fi
 
 echo $ac_n "checking whether time.h and sys/time.h may both be included""... $ac_c" 1>&6
-echo "configure:14038: checking whether time.h and sys/time.h may both be included" >&5
+echo "configure:14060: checking whether time.h and sys/time.h may both be included" >&5
 if eval "test \"\${ac_cv_header_time+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 14043 "configure"
+#line 14065 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #include <sys/time.h>
@@ -14048,7 +14070,7 @@ int main() {
 struct tm *tp;
 ; return 0; }
 EOF
-if { (eval echo configure:14052: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:14074: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ac_cv_header_time=yes
 else
@@ -14069,12 +14091,12 @@ EOF
 fi
 
 echo $ac_n "checking whether struct tm is in sys/time.h or time.h""... $ac_c" 1>&6
-echo "configure:14073: checking whether struct tm is in sys/time.h or time.h" >&5
+echo "configure:14095: checking whether struct tm is in sys/time.h or time.h" >&5
 if eval "test \"\${ac_cv_struct_tm+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 14078 "configure"
+#line 14100 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #include <time.h>
@@ -14082,7 +14104,7 @@ int main() {
 struct tm *tp; tp->tm_sec;
 ; return 0; }
 EOF
-if { (eval echo configure:14086: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:14108: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ac_cv_struct_tm=time.h
 else
@@ -14103,12 +14125,12 @@ EOF
 fi
 
 echo $ac_n "checking for uid_t in sys/types.h""... $ac_c" 1>&6
-echo "configure:14107: checking for uid_t in sys/types.h" >&5
+echo "configure:14129: checking for uid_t in sys/types.h" >&5
 if eval "test \"\${ac_cv_type_uid_t+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 14112 "configure"
+#line 14134 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 EOF
@@ -14137,19 +14159,19 @@ EOF
 fi
 
 echo $ac_n "checking for sig_atomic_t""... $ac_c" 1>&6
-echo "configure:14141: checking for sig_atomic_t" >&5
+echo "configure:14163: checking for sig_atomic_t" >&5
 if eval "test \"\${ol_cv_type_sig_atomic_t+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 14146 "configure"
+#line 14168 "configure"
 #include "confdefs.h"
 #include <signal.h>
 int main() {
 sig_atomic_t atomic;
 ; return 0; }
 EOF
-if { (eval echo configure:14153: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:14175: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ol_cv_type_sig_atomic_t=yes
 else
@@ -14173,13 +14195,13 @@ EOF
 
 # test for pw_gecos in struct passwd
 echo $ac_n "checking struct passwd for pw_gecos""... $ac_c" 1>&6
-echo "configure:14177: checking struct passwd for pw_gecos" >&5
+echo "configure:14199: checking struct passwd for pw_gecos" >&5
 if eval "test \"\${ol_cv_struct_passwd_pw_gecos+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   
        cat > conftest.$ac_ext <<EOF
-#line 14183 "configure"
+#line 14205 "configure"
 #include "confdefs.h"
 #include <pwd.h>
 int main() {
@@ -14189,7 +14211,7 @@ int main() {
 
 ; return 0; }
 EOF
-if { (eval echo configure:14193: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:14215: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ol_cv_struct_passwd_pw_gecos=yes
 else
 
 # test for pw_passwd in struct passwd
 echo $ac_n "checking struct passwd for pw_passwd""... $ac_c" 1>&6
-echo "configure:14215: checking struct passwd for pw_passwd" >&5
+echo "configure:14237: checking struct passwd for pw_passwd" >&5
 if eval "test \"\${ol_cv_struct_passwd_pw_passwd+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   
        cat > conftest.$ac_ext <<EOF
-#line 14221 "configure"
+#line 14243 "configure"
 #include "confdefs.h"
 #include <pwd.h>
 int main() {
@@ -14227,7 +14249,7 @@ int main() {
 
 ; return 0; }
 EOF
-if { (eval echo configure:14231: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:14253: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ol_cv_struct_passwd_pw_passwd=yes
 else
@@ -14249,7 +14271,7 @@ fi
 
 
 echo $ac_n "checking if toupper() requires islower()""... $ac_c" 1>&6
-echo "configure:14253: checking if toupper() requires islower()" >&5
+echo "configure:14275: checking if toupper() requires islower()" >&5
 if eval "test \"\${ol_cv_c_upper_lower+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -14258,7 +14280,7 @@ else
   ol_cv_c_upper_lower=safe
 else
   cat > conftest.$ac_ext <<EOF
-#line 14262 "configure"
+#line 14284 "configure"
 #include "confdefs.h"
 
 #include <ctype.h>
@@ -14270,7 +14292,7 @@ main()
                exit(1);
 }
 EOF
-if { (eval echo configure:14274: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:14296: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   ol_cv_c_upper_lower=no
 else
@@ -14293,12 +14315,12 @@ EOF
 fi
 
 echo $ac_n "checking for working const""... $ac_c" 1>&6
-echo "configure:14297: checking for working const" >&5
+echo "configure:14319: checking for working const" >&5
 if eval "test \"\${ac_cv_c_const+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 14302 "configure"
+#line 14324 "configure"
 #include "confdefs.h"
 
 int main() {
@@ -14347,7 +14369,7 @@ ccp = (char const *const *) p;
 
 ; return 0; }
 EOF
-if { (eval echo configure:14351: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:14373: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ac_cv_c_const=yes
 else
@@ -14368,12 +14390,12 @@ EOF
 fi
 
 echo $ac_n "checking if compiler understands volatile""... $ac_c" 1>&6
-echo "configure:14372: checking if compiler understands volatile" >&5
+echo "configure:14394: checking if compiler understands volatile" >&5
 if eval "test \"\${ol_cv_c_volatile+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 14377 "configure"
+#line 14399 "configure"
 #include "confdefs.h"
 int x, y, z;
 int main() {
@@ -14382,7 +14404,7 @@ volatile int a; int * volatile b = x ? &y : &z;
       *b = 0;
 ; return 0; }
 EOF
-if { (eval echo configure:14386: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:14408: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ol_cv_c_volatile=yes
 else
@@ -14412,14 +14434,14 @@ EOF
 
 else
        echo $ac_n "checking whether byte ordering is bigendian""... $ac_c" 1>&6
-echo "configure:14416: checking whether byte ordering is bigendian" >&5
+echo "configure:14438: checking whether byte ordering is bigendian" >&5
 if eval "test \"\${ac_cv_c_bigendian+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   ac_cv_c_bigendian=unknown
 # See if sys/param.h defines the BYTE_ORDER macro.
 cat > conftest.$ac_ext <<EOF
-#line 14423 "configure"
+#line 14445 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #include <sys/param.h>
@@ -14430,11 +14452,11 @@ int main() {
 #endif
 ; return 0; }
 EOF
-if { (eval echo configure:14434: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:14456: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   # It does; now see whether it defined to BIG_ENDIAN or not.
 cat > conftest.$ac_ext <<EOF
-#line 14438 "configure"
+#line 14460 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #include <sys/param.h>
@@ -14445,7 +14467,7 @@ int main() {
 #endif
 ; return 0; }
 EOF
-if { (eval echo configure:14449: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:14471: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ac_cv_c_bigendian=yes
 else
@@ -14465,7 +14487,7 @@ if test "$cross_compiling" = yes; then
     { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; }
 else
   cat > conftest.$ac_ext <<EOF
-#line 14469 "configure"
+#line 14491 "configure"
 #include "confdefs.h"
 main () {
   /* Are we little or big endian?  From Harbison&Steele.  */
@@ -14478,7 +14500,7 @@ main () {
   exit (u.c[sizeof (long) - 1] == 1);
 }
 EOF
-if { (eval echo configure:14482: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:14504: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   ac_cv_c_bigendian=no
 else
 fi
 
 echo $ac_n "checking size of short""... $ac_c" 1>&6
-echo "configure:14508: checking size of short" >&5 
+echo "configure:14530: checking size of short" >&5 
 if eval "test \"\${ac_cv_sizeof_short+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   for ac_size in 4 8 1 2 16  ; do # List sizes in rough order of prevalence. 
   cat > conftest.$ac_ext <<EOF
-#line 14514 "configure"
+#line 14536 "configure"
 #include "confdefs.h"
 #include "confdefs.h" 
 #include <sys/types.h> 
@@ -14520,7 +14542,7 @@ int main() {
 switch (0) case 0: case (sizeof (short) == $ac_size):;
 ; return 0; }
 EOF
-if { (eval echo configure:14524: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:14546: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ac_cv_sizeof_short=$ac_size
 else
@@ -14543,13 +14565,13 @@ EOF
  
  
 echo $ac_n "checking size of int""... $ac_c" 1>&6
-echo "configure:14547: checking size of int" >&5 
+echo "configure:14569: checking size of int" >&5 
 if eval "test \"\${ac_cv_sizeof_int+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   for ac_size in 4 8 1 2 16  ; do # List sizes in rough order of prevalence. 
   cat > conftest.$ac_ext <<EOF
-#line 14553 "configure"
+#line 14575 "configure"
 #include "confdefs.h"
 #include "confdefs.h" 
 #include <sys/types.h> 
@@ -14559,7 +14581,7 @@ int main() {
 switch (0) case 0: case (sizeof (int) == $ac_size):;
 ; return 0; }
 EOF
-if { (eval echo configure:14563: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:14585: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ac_cv_sizeof_int=$ac_size
 else
@@ -14582,13 +14604,13 @@ EOF
  
  
 echo $ac_n "checking size of long""... $ac_c" 1>&6
-echo "configure:14586: checking size of long" >&5 
+echo "configure:14608: checking size of long" >&5 
 if eval "test \"\${ac_cv_sizeof_long+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   for ac_size in 4 8 1 2 16  ; do # List sizes in rough order of prevalence. 
   cat > conftest.$ac_ext <<EOF
-#line 14592 "configure"
+#line 14614 "configure"
 #include "confdefs.h"
 #include "confdefs.h" 
 #include <sys/types.h> 
@@ -14598,7 +14620,7 @@ int main() {
 switch (0) case 0: case (sizeof (long) == $ac_size):;
 ; return 0; }
 EOF
-if { (eval echo configure:14602: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:14624: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ac_cv_sizeof_long=$ac_size
 else
@@ -14649,7 +14671,7 @@ EOF
 
 
 echo $ac_n "checking for 8-bit clean memcmp""... $ac_c" 1>&6
-echo "configure:14653: checking for 8-bit clean memcmp" >&5
+echo "configure:14675: checking for 8-bit clean memcmp" >&5
 if eval "test \"\${ac_cv_func_memcmp_clean+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -14657,7 +14679,7 @@ else
   ac_cv_func_memcmp_clean=no
 else
   cat > conftest.$ac_ext <<EOF
-#line 14661 "configure"
+#line 14683 "configure"
 #include "confdefs.h"
 
 main()
@@ -14667,7 +14689,7 @@ main()
 }
 
 EOF
-if { (eval echo configure:14671: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:14693: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   ac_cv_func_memcmp_clean=yes
 else
@@ -14685,12 +14707,12 @@ echo "$ac_t""$ac_cv_func_memcmp_clean" 1>&6
 test $ac_cv_func_memcmp_clean = no && LIBOBJS="$LIBOBJS memcmp.${ac_objext}"
 
 echo $ac_n "checking for strftime""... $ac_c" 1>&6
-echo "configure:14689: checking for strftime" >&5
+echo "configure:14711: checking for strftime" >&5
 if eval "test \"\${ac_cv_func_strftime+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 14694 "configure"
+#line 14716 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char strftime(); below.  */
@@ -14714,7 +14736,7 @@ f = strftime;
 
 ; return 0; }
 EOF
-if { (eval echo configure:14718: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:14740: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_func_strftime=yes"
 else
@@ -14736,7 +14758,7 @@ else
   echo "$ac_t""no" 1>&6
 # strftime is in -lintl on SCO UNIX.
 echo $ac_n "checking for strftime in -lintl""... $ac_c" 1>&6
-echo "configure:14740: checking for strftime in -lintl" >&5
+echo "configure:14762: checking for strftime in -lintl" >&5
 ac_lib_var=`echo intl'_'strftime | sed 'y%./+-:%__p__%'`
 if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -14744,7 +14766,7 @@ else
   ac_save_LIBS="$LIBS"
 LIBS="-lintl  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 14748 "configure"
+#line 14770 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -14755,7 +14777,7 @@ int main() {
 strftime()
 ; return 0; }
 EOF
-if { (eval echo configure:14759: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:14781: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
 
 
 echo $ac_n "checking for inet_aton()""... $ac_c" 1>&6
-echo "configure:14787: checking for inet_aton()" >&5
+echo "configure:14809: checking for inet_aton()" >&5
 if eval "test \"\${ol_cv_func_inet_aton+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 14792 "configure"
+#line 14814 "configure"
 #include "confdefs.h"
 
 #ifdef HAVE_SYS_TYPES_H
@@ -14810,7 +14832,7 @@ struct in_addr in;
 int rc = inet_aton( "255.255.255.255", &in );
 ; return 0; }
 EOF
-if { (eval echo configure:14814: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:14836: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   ol_cv_func_inet_aton=yes
 else
@@ -14832,12 +14854,12 @@ EOF
  
 
 echo $ac_n "checking for _spawnlp""... $ac_c" 1>&6
-echo "configure:14836: checking for _spawnlp" >&5
+echo "configure:14858: checking for _spawnlp" >&5
 if eval "test \"\${ac_cv_func__spawnlp+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 14841 "configure"
+#line 14863 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char _spawnlp(); below.  */
@@ -14861,7 +14883,7 @@ f = _spawnlp;
 
 ; return 0; }
 EOF
-if { (eval echo configure:14865: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:14887: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_func__spawnlp=yes"
 else
 
 
 echo $ac_n "checking for _snprintf""... $ac_c" 1>&6
-echo "configure:14889: checking for _snprintf" >&5
+echo "configure:14911: checking for _snprintf" >&5
 if eval "test \"\${ac_cv_func__snprintf+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 14894 "configure"
+#line 14916 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char _snprintf(); below.  */
@@ -14914,7 +14936,7 @@ f = _snprintf;
 
 ; return 0; }
 EOF
-if { (eval echo configure:14918: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:14940: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_func__snprintf=yes"
 else
 
 
 echo $ac_n "checking for _vsnprintf""... $ac_c" 1>&6
-echo "configure:14944: checking for _vsnprintf" >&5
+echo "configure:14966: checking for _vsnprintf" >&5
 if eval "test \"\${ac_cv_func__vsnprintf+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 14949 "configure"
+#line 14971 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char _vsnprintf(); below.  */
@@ -14969,7 +14991,7 @@ f = _vsnprintf;
 
 ; return 0; }
 EOF
-if { (eval echo configure:14973: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:14995: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_func__vsnprintf=yes"
 else
 
 
 echo $ac_n "checking for vprintf""... $ac_c" 1>&6
-echo "configure:14999: checking for vprintf" >&5
+echo "configure:15021: checking for vprintf" >&5
 if eval "test \"\${ac_cv_func_vprintf+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 15004 "configure"
+#line 15026 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char vprintf(); below.  */
@@ -15024,7 +15046,7 @@ f = vprintf;
 
 ; return 0; }
 EOF
-if { (eval echo configure:15028: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:15050: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_func_vprintf=yes"
 else
 
 if test "$ac_cv_func_vprintf" != yes; then
 echo $ac_n "checking for _doprnt""... $ac_c" 1>&6
-echo "configure:15052: checking for _doprnt" >&5
+echo "configure:15074: checking for _doprnt" >&5
 if eval "test \"\${ac_cv_func__doprnt+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 15057 "configure"
+#line 15079 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char _doprnt(); below.  */
@@ -15077,7 +15099,7 @@ f = _doprnt;
 
 ; return 0; }
 EOF
-if { (eval echo configure:15081: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:15103: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_func__doprnt=yes"
 else
@@ -15106,12 +15128,12 @@ if test $ac_cv_func_vprintf = yes ; then
                for ac_func in vsnprintf vsprintf
 do
 echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:15110: checking for $ac_func" >&5
+echo "configure:15132: checking for $ac_func" >&5
 if eval "test \"\${ac_cv_func_$ac_func+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 15115 "configure"
+#line 15137 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func(); below.  */
@@ -15135,7 +15157,7 @@ f = $ac_func;
 
 ; return 0; }
 EOF
-if { (eval echo configure:15139: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:15161: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_func_$ac_func=yes"
 else
@@ -15214,12 +15236,12 @@ for ac_func in \
 
 do
 echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:15218: checking for $ac_func" >&5
+echo "configure:15240: checking for $ac_func" >&5
 if eval "test \"\${ac_cv_func_$ac_func+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 15223 "configure"
+#line 15245 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func(); below.  */
@@ -15243,7 +15265,7 @@ f = $ac_func;
 
 ; return 0; }
 EOF
-if { (eval echo configure:15247: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:15269: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_func_$ac_func=yes"
 else
@@ -15271,12 +15293,12 @@ done
 for ac_func in getopt tempnam
 do
 echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:15275: checking for $ac_func" >&5
+echo "configure:15297: checking for $ac_func" >&5
 if eval "test \"\${ac_cv_func_$ac_func+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 15280 "configure"
+#line 15302 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func(); below.  */
@@ -15300,7 +15322,7 @@ f = $ac_func;
 
 ; return 0; }
 EOF
-if { (eval echo configure:15304: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:15326: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_func_$ac_func=yes"
 else
 
 # Check Configuration
 echo $ac_n "checking declaration of sys_errlist""... $ac_c" 1>&6
-echo "configure:15341: checking declaration of sys_errlist" >&5
+echo "configure:15363: checking declaration of sys_errlist" >&5
 if eval "test \"\${ol_cv_dcl_sys_errlist+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   
        cat > conftest.$ac_ext <<EOF
-#line 15347 "configure"
+#line 15369 "configure"
 #include "confdefs.h"
 
 #include <stdio.h>
@@ -15356,7 +15378,7 @@ int main() {
 char *c = (char *) *sys_errlist
 ; return 0; }
 EOF
-if { (eval echo configure:15360: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:15382: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ol_cv_dcl_sys_errlist=yes
        ol_cv_have_sys_errlist=yes
@@ -15379,20 +15401,20 @@ EOF
 
 
        echo $ac_n "checking existence of sys_errlist""... $ac_c" 1>&6
-echo "configure:15383: checking existence of sys_errlist" >&5
+echo "configure:15405: checking existence of sys_errlist" >&5
 if eval "test \"\${ol_cv_have_sys_errlist+set}\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   
                cat > conftest.$ac_ext <<EOF
-#line 15389 "configure"
+#line 15411 "configure"
 #include "confdefs.h"
 #include <errno.h>
 int main() {
 char *c = (char *) *sys_errlist
 ; return 0; }
 EOF
-if { (eval echo configure:15396: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:15418: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   ol_cv_have_sys_errlist=yes
 else
@@ -15463,9 +15485,9 @@ if test "$ol_enable_cldap" != no ; then
 EOF
 
 fi
-if test "$ol_enable_unix" != no; then
+if test "$ol_enable_local" != no; then
        cat >> confdefs.h <<\EOF
-#define LDAP_PF_UNIX 1
+#define LDAP_PF_LOCAL 1
 EOF
 
 fi
index bedb3ecac34571fbf7cd5c440ea4d3a6e7dd7aa8..041e532f12aaf5a8d137f68aff01a61e3ad7f093 100644 (file)
@@ -100,35 +100,35 @@ AC_SUBST(ldap_subdir)dnl
 
 dnl ----------------------------------------------------------------
 dnl General "enable" options
-OL_ARG_ENABLE(debug,[  --enable-debug  enable debugging], yes)dnl
-OL_ARG_ENABLE(syslog,[  --enable-syslog        enable syslog support], auto)dnl
-OL_ARG_ENABLE(proctitle,[  --enable-proctitle  enable proctitle support], yes)dnl
-OL_ARG_ENABLE(cache,[  --enable-cache  enable caching], yes)dnl
-OL_ARG_ENABLE(referrals,[  --enable-referrals  enable V2 Referrals extension], yes)dnl
-OL_ARG_ENABLE(kbind,[  --enable-kbind  enable V2 Kerberos IV bind], auto)dnl
-OL_ARG_ENABLE(cldap,[  --enable-cldap  enable connectionless ldap], no)dnl
-OL_ARG_ENABLE(ipv6,[  --enable-ipv6    enable IPv6 support], auto)dnl
-OL_ARG_ENABLE(unix,[  --enable-unix            enable UNIX domain socket support], auto)dnl
-OL_ARG_ENABLE(x_compile,[  --enable-x-compile  enable cross compiling],
+OL_ARG_ENABLE(debug,[  --enable-debug    enable debugging], yes)dnl
+OL_ARG_ENABLE(syslog,[  --enable-syslog          enable syslog support], auto)dnl
+OL_ARG_ENABLE(proctitle,[  --enable-proctitle    enable proctitle support], yes)dnl
+OL_ARG_ENABLE(cache,[  --enable-cache    enable caching], yes)dnl
+OL_ARG_ENABLE(referrals,[  --enable-referrals    enable V2 Referrals extension], yes)dnl
+OL_ARG_ENABLE(kbind,[  --enable-kbind    enable V2 Kerberos IV bind], auto)dnl
+OL_ARG_ENABLE(cldap,[  --enable-cldap    enable connectionless ldap], no)dnl
+OL_ARG_ENABLE(ipv6,[  --enable-ipv6      enable IPv6 support], auto)dnl
+OL_ARG_ENABLE(local,[  --enable-local    enable AF_LOCAL (AF_UNIX) socket support], auto)dnl
+OL_ARG_ENABLE(x_compile,[  --enable-x-compile    enable cross compiling],
        no, [yes no])dnl
 
 dnl ----------------------------------------------------------------
 dnl General "with" options
-dnl OL_ARG_ENABLE(dmalloc,[  --enable-dmalloc  enable debug malloc support], no)dnl
+dnl OL_ARG_ENABLE(dmalloc,[  --enable-dmalloc    enable debug malloc support], no)dnl
 
-OL_ARG_WITH(cyrus_sasl,[  --with-cyrus-sasl    with Cyrus SASL support],
+OL_ARG_WITH(cyrus_sasl,[  --with-cyrus-sasl      with Cyrus SASL support],
        auto, [auto yes no] )
-OL_ARG_WITH(fetch,[  --with-fetch              with fetch URL support],
+OL_ARG_WITH(fetch,[  --with-fetch                with fetch URL support],
        auto, [auto yes no] )
-OL_ARG_WITH(kerberos,[  --with-kerberos        with support],
+OL_ARG_WITH(kerberos,[  --with-kerberos          with support],
        auto, [auto k5 k5only k425 kth k4 afs yes no])
-OL_ARG_WITH(readline,[  --with-readline        with readline support],
+OL_ARG_WITH(readline,[  --with-readline          with readline support],
        auto, [auto yes no] )
-OL_ARG_WITH(threads,[  --with-threads  use threads],
+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],
+OL_ARG_WITH(tls,[  --with-tls            with TLS/SSL support],
        auto, [auto ssleay openssl yes no] )
-OL_ARG_WITH(yielding_select,[  --with-yielding-select  with implicitly yielding select],
+OL_ARG_WITH(yielding_select,[  --with-yielding-select  with implicitly yielding select],
        auto, [auto yes no manual] )
 
 dnl ----------------------------------------------------------------
@@ -138,47 +138,47 @@ dnl ----------------------------------------------------------------
 dnl ----------------------------------------------------------------
 dnl SLAPD OPTIONS
 AC_ARG_WITH(xxslapdoptions,[SLAPD (Standalone LDAP Daemon) Options:])
-OL_ARG_ENABLE(slapd,[  --enable-slapd  enable building slapd], yes)dnl
-OL_ARG_ENABLE(cleartext,[    --enable-cleartext        enable cleartext passwords], yes)dnl
-OL_ARG_ENABLE(crypt,[    --enable-crypt        enable crypt(3) passwords], auto)dnl
-OL_ARG_ENABLE(kpasswd,[    --enable-kpasswd    enable kerberos password verification], no)dnl
-OL_ARG_ENABLE(spasswd,[    --enable-spasswd    enable (Cyrus) SASL password verification], no)dnl
-OL_ARG_ENABLE(modules,[    --enable-modules    enable dynamic module support], no)dnl
-OL_ARG_ENABLE(multimaster,[    --enable-multimaster    enable multimaster replication], no)dnl
-OL_ARG_ENABLE(phonetic,[    --enable-phonetic  enable phonetic/soundex], no)dnl
-OL_ARG_ENABLE(rlookups,[    --enable-rlookups  enable reverse lookups], auto)dnl
-OL_ARG_ENABLE(aci,[    --enable-aci    enable per-object ACIs], no)dnl
-OL_ARG_ENABLE(wrappers,[    --enable-wrappers  enable tcp wrapper support], no)dnl
-OL_ARG_ENABLE(dynamic,[    --enable-dynamic    enable linking built binaries with dynamic libs], no)dnl
+OL_ARG_ENABLE(slapd,[  --enable-slapd    enable building slapd], yes)dnl
+OL_ARG_ENABLE(cleartext,[    --enable-cleartext          enable cleartext passwords], yes)dnl
+OL_ARG_ENABLE(crypt,[    --enable-crypt          enable crypt(3) passwords], auto)dnl
+OL_ARG_ENABLE(kpasswd,[    --enable-kpasswd      enable kerberos password verification], no)dnl
+OL_ARG_ENABLE(spasswd,[    --enable-spasswd      enable (Cyrus) SASL password verification], no)dnl
+OL_ARG_ENABLE(modules,[    --enable-modules      enable dynamic module support], no)dnl
+OL_ARG_ENABLE(multimaster,[    --enable-multimaster  enable multimaster replication], no)dnl
+OL_ARG_ENABLE(phonetic,[    --enable-phonetic    enable phonetic/soundex], no)dnl
+OL_ARG_ENABLE(rlookups,[    --enable-rlookups    enable reverse lookups], auto)dnl
+OL_ARG_ENABLE(aci,[    --enable-aci      enable per-object ACIs], no)dnl
+OL_ARG_ENABLE(wrappers,[    --enable-wrappers    enable tcp wrapper support], no)dnl
+OL_ARG_ENABLE(dynamic,[    --enable-dynamic      enable linking built binaries with dynamic libs], no)dnl
 
 dnl SLAPD Backend options
-OL_ARG_ENABLE(dnssrv,[    --enable-dnssrv      enable dnssrv backend], no)dnl
-OL_ARG_WITH(dnssrv_module,[      --with-dnssrv-module  module type], static,
+OL_ARG_ENABLE(dnssrv,[    --enable-dnssrv        enable dnssrv backend], no)dnl
+OL_ARG_WITH(dnssrv_module,[    --with-dnssrv-module  module type], static,
        [static dynamic])
-OL_ARG_ENABLE(ldap,[    --enable-ldap  enable ldap backend], no)dnl
-OL_ARG_WITH(ldap_module,[      --with-ldap-module      module type], static,
+OL_ARG_ENABLE(ldap,[    --enable-ldap    enable ldap backend], no)dnl
+OL_ARG_WITH(ldap_module,[    --with-ldap-module          module type], static,
        [static dynamic])
-OL_ARG_ENABLE(ldbm,[    --enable-ldbm  enable ldbm backend], yes)dnl
-OL_ARG_WITH(ldbm_api,[      --with-ldbm-api    use LDBM API], auto,
+OL_ARG_ENABLE(ldbm,[    --enable-ldbm    enable ldbm backend], yes)dnl
+OL_ARG_WITH(ldbm_api,[    --with-ldbm-api       with LDBM API], auto,
        [auto berkeley bcompat mdbm gdbm])
-OL_ARG_WITH(ldbm_module,[      --with-ldbm-module      module type], static,
+OL_ARG_WITH(ldbm_module,[    --with-ldbm-module          module type], static,
        [static dynamic])
-OL_ARG_WITH(ldbm_type,[      --with-ldbm-type  use LDBM type], auto,
+OL_ARG_WITH(ldbm_type,[    --with-ldbm-type      use LDBM type], auto,
        [auto btree hash])
-OL_ARG_ENABLE(passwd,[    --enable-passwd      enable passwd backend], no)dnl
-OL_ARG_WITH(passwd_module,[      --with-passwd-module  module type], static,
+OL_ARG_ENABLE(passwd,[    --enable-passwd        enable passwd backend], no)dnl
+OL_ARG_WITH(passwd_module,[    --with-passwd-module  module type], static,
        [static dynamic])
-OL_ARG_ENABLE(shell,[    --enable-shell        enable shell backend], no)dnl
-OL_ARG_WITH(shell_module,[      --with-shell-module    module type], static,
+OL_ARG_ENABLE(shell,[    --enable-shell          enable shell backend], no)dnl
+OL_ARG_WITH(shell_module,[    --with-shell-module        module type], static,
        [static dynamic])
-OL_ARG_ENABLE(sql,[    --enable-sql    enable sql backend], no)dnl
-OL_ARG_WITH(sql_module,[      --with-sql-module        module type], static,
+OL_ARG_ENABLE(sql,[    --enable-sql      enable sql backend], no)dnl
+OL_ARG_WITH(sql_module,[    --with-sql-module    module type], static,
        [static dynamic])
 
 dnl ----------------------------------------------------------------
 dnl SLURPD OPTIONS
 AC_ARG_WITH(xxslurpdoptions,[SLURPD (Replication Daemon) Options:])
-OL_ARG_ENABLE(slurpd,[  --enable-slurpd        enable building slurpd], auto)dnl
+OL_ARG_ENABLE(slurpd,[  --enable-slurpd          enable building slurpd], auto)dnl
 
 dnl ----------------------------------------------------------------
 AC_ARG_WITH(xxliboptions,[Library Generation & Linking Options])
@@ -541,7 +541,7 @@ AC_CHECK_LIB(s, afopen, [
 
 dnl ----------------------------------------------------------------
 dnl PF_INET6 support requires getaddrinfo
-dnl PF_UNIX may use getaddrinfo in available
+dnl PF_LOCAL may use getaddrinfo in available
 AC_CHECK_FUNCS( getaddrinfo )
 
 if test $ac_cv_func_getaddrinfo = no ; then
@@ -551,13 +551,13 @@ if test $ac_cv_func_getaddrinfo = no ; then
        ol_enable_ipv6=no
 fi
 
-if test $ol_enable_unix != no ; then
+if test $ol_enable_local != no ; then
        AC_CHECK_HEADERS( sys/un.h )
 
-       if test $ol_enable_unix = auto ; then
-               ol_enable_unix=$ac_cv_header_sys_un_h
+       if test $ol_enable_local = auto ; then
+               ol_enable_local=$ac_cv_header_sys_un_h
        elif test $ac_cv_header_sys_un_h = no ; then
-               AC_MSG_ERROR([UNIX domain support requires sys/un.h])
+               AC_MSG_ERROR([AF_LOCAL domain support requires sys/un.h])
        fi
 fi
 
@@ -913,7 +913,6 @@ dnl ----------------------------------------------------------------
 dnl TLS/SSL
 ol_link_tls=no
 if test $ol_with_tls != no ; then
-       
        AC_CHECK_HEADERS(openssl/ssl.h ssl.h)
        
        if test $ac_cv_header_openssl_ssl_h = yes -o $ac_cv_header_ssl_h = yes ; then
@@ -954,11 +953,21 @@ if test $ol_with_tls != no ; then
                        fi
                fi
        fi
+
+else
+       AC_WARN([TLS privacy protection not supported!])
 fi
 
 if test $ol_link_tls = yes ; then
        AC_DEFINE(HAVE_TLS, 1, [define if you have TLS])
-fi     
+
+elif test $ol_with_tls = auto ; then
+       AC_WARN([Could not locate TLS/SSL package])
+       AC_WARN([TLS privacy protection not supported!])
+
+elif test $ol_with_tls != no ; then
+       AC_ERROR([Could not locate TLS/SSL package])
+fi
 
 dnl ----------------------------------------------------------------
 dnl Tests for reentrant functions necessary to build a
@@ -1746,8 +1755,21 @@ if test $ol_with_cyrus_sasl != no ; then
                fi
        fi
 
-       if test $ol_link_sasl = no -a $ol_with_cyrus_sasl = yes ; then
-               AC_MSG_ERROR(no suitable API for --with-cyrus-sasl=$ol_with_cyrus_sasl)
+       if test $ol_link_sasl = no ; then
+               if test $ol_with_cyrus_sasl != auto ; then
+                       AC_MSG_ERROR([Could not locate Cyrus SASL])
+               else
+                       AC_MSG_WARN([Could not locate Cyrus SASL])
+                       AC_MSG_WARN([SASL authentication not supported!])
+                       if test $ol_link_tls = no ; then
+                               AC_MSG_WARN([Strong authentication not supported!])
+                       fi
+               fi
+       fi
+else
+       AC_MSG_WARN([SASL authentication not supported!])
+       if test $ol_link_tls = no ; then
+               AC_MSG_WARN([Strong authentication not supported!])
        fi
 fi
 
@@ -2032,8 +2054,8 @@ fi
 if test "$ol_enable_cldap" != no ; then
        AC_DEFINE(LDAP_CONNECTIONLESS,1,[define to support CLDAP])
 fi
-if test "$ol_enable_unix" != no; then
-       AC_DEFINE(LDAP_PF_UNIX,1,[define to support PF_UNIX])
+if test "$ol_enable_local" != no; then
+       AC_DEFINE(LDAP_PF_LOCAL,1,[define to support PF_LOCAL])
 fi
 if test "$ol_enable_ipv6" != no; then
        AC_DEFINE(LDAP_PF_INET6,1,[define to support PF_INET6])
index 217d6f4114b6b777ea41c11d52025ee90762530e..d182b3f4b8c0a6e01d553cec9aecf68102a507ac 100644 (file)
@@ -9,7 +9,7 @@ or to cite them other than as "work in progress."
 
 OpenLDAP maintains copies of drafts for which we find interesting.
 It existance does not necessarily imply any support or any plans to
-support for the I-D.  The I-D found in this directory may be stale,
+support for the I-D.  The I-Ds found in this directory may be stale,
 expired, or otherwise out of date.
 
 Please refer to http://www.ietf.org/ for latest revisions (and
index 9beb721f9f60975d25387479f14e1534a7adb940..7e159eb220dd77a176590df04b62e3d0ed9f9dcd 100644 (file)
 
 
 
-          Internet-Draft                                     E. Stokes
-          LDAP Extensions WG                                  D. Byrne
-          Intended Category: Standards Track                       IBM
-          Expires: 10 September 2000                        B. Blakley
-                                                                Dascom
-                                                         10 March 2000
+Internet-Draft                                     E. Stokes
+LDAP Extensions WG                                B. Blakley
+Intended Category: Standards Track            Tivoli Systems
+Expires: 14 January 2001                        D. Rinkevich
+                                                         IBM
+                                                    R. Byrne
+                                            Sun Microsystems
+                                                14 July 2000
 
-                         Access Control Model for LDAP
-                     <draft-ietf-ldapext-acl-model-05.txt>
+              Access Control Model for LDAPv3
+           <draft-ietf-ldapext-acl-model-06.txt>
 
-          STATUS OF THIS MEMO
+STATUS OF THIS MEMO
 
-             This document is an Internet-Draft and is in full
-             conformance with all provisions of Section 10 of RFC2026.
+This document is an Internet-Draft and is in full
+conformance with all provisions of Section 10 of RFC2026.
 
-             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."
+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 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.
+The list of Internet-Draft Shadow Directories can be
+accessed at http://www.ietf.org/shadow.html.
 
-             Comments and suggestions on this document are encouraged.
-             Comments on this document should be sent to the  LDAPEXT
-             working group discussion list:
+Comments and suggestions on this document are encouraged.
+Comments on this document should be sent to the  LDAPEXT
+working group discussion list:
 
-                    ietf-ldapext@netscape.com
+          ietf-ldapext@netscape.com
 
-          COPYRIGHT NOTICE
-             Copyright (C) The Internet Society (1997).  All Rights
-             Reserved.
+COPYRIGHT NOTICE
 
-          ABSTRACT
+Copyright (C) The Internet Society (2000).  All Rights
+Reserved.
 
-             This document describes the access control model for the
-             Lightweight Directory Application Protocol (LDAP)
+ABSTRACT
 
+This document describes the access control model for the
+Lightweight Directory Application Protocol V3 (LDAPv3)
+directory service. It includes a description of the model,
+the LDAP controls, and the extended operations to the LDAP
+protocol.  The current LDAP APIs are sufficient for most
 
 
-          Stokes, Byrne, Blakley   Expires 10 September 2000        [Page 1]
 
+Stokes, et al      Expires 14 January 2001          [Page 1]
+\f
 
 
 
 
+Internet-Draft      Access Control Model        14 July 2000
 
-          Internet-Draft      Access Control Model       10 March 2000
 
 
+access control operations.  An API (in a separate document)
+is needed for the extended operation getEffectiveAccess.  A
+separate requirements document for access control exists
+[REQTS].  The access control model used the requirements
+documents as a guideline for the development of this
+specification and are reflected in this specification to the
+extent that the working group could agree on an access
+control model.
 
-             directory service. It includes a description of the
-             model, the LDAP controls, and the extended operations to
-             the LDAP protocol.  The current LDAP APIs are sufficient
-             for most access control operations.  An API (in a
-             separate document) is needed for the extended operation
-             getEffectiveAccess and specifyCredentials.
 
-             The keywords "MUST", "SHOULD", and "MAY" used in this
-             document are to be interpreted as described in
-             [Bradner97].
+The key words "MUST", "MUST NOT", "REQUIRED", "SHALL",
+"SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED",  and
+"MAY" used in this document are to be interpreted as
+described in [Bradner97].
 
 
 
-          1.  Introduction
+1.  Introduction
 
-             The ability to securely access (replicate and distribute)
-             directory information throughout the network is necessary
-             for successful deployment.  LDAP's acceptance as an
-             access protocol for directory information is driving the
-             need to provide an access control model definition for
-             LDAP directory content among servers within an enterprise
-             and the Internet.  Currently LDAP does not define an
-             access control model, but one is needed to ensure
-             consistent secure access across heterogeneous LDAP
-             implementations. The major objective is to provide a
-             simple, but secure, highly efficient access control model
-             for LDAP while also providing the appropriate flexibility
-             to meet the needs of both the Internet and enterprise
-             environments and policies.  This document defines the
-             model and the protocol extensions (controls and extended
-             operations).
+The ability to securely access (replicate and distribute)
+directory information throughout the network is necessary
+for successful deployment.  LDAP's acceptance as an access
+protocol for directory information is driving the need to
+provide an access control model definition for LDAP
+directory content among servers within an enterprise and the
+Internet.  Currently LDAP does not define an access control
+model, but one is needed to ensure consistent secure access,
+replication, and management across heterogeneous LDAP
+implementations. The major objective is to provide a simple,
+usable, and implementable, but secure and efficient access
+control model for LDAP while also providing the appropriate
+flexibility to meet the needs of both the Internet and
+enterprise environments and policies.  This document defines
+the model and the protocol extensions (controls and extended
+operations).
 
+This draft does not (and cannot) fully specify the behavior
+of the Access Control Model in a distributed environment
+(e.g. propagating access control information across servers
+and ACI administration) because there is no LDAP standard
+defining how to distribute directory data between LDAP
+servers.  The behavior of the Access Control Model in
+distributed environments is beyond the scope of this draft.
 
-          2.  Overview
 
-             Access Control mechanisms evaluate requests for access to
-             protected resources and make decisions about whether
-             those requests should be granted or denied.  In order to
-             make a grant/deny decision about a request for access to
-             a protected resource, an access control mechanism needs
-             to evaluate policy data.  This policy data describes
-             security-relevant characteristics of the requesting
-             subject and the rules which govern the use of the target
-             object.
 
+2.  The LDAPv3 Access Control Model
 
+Access Control mechanisms evaluate requests for access to
+protected resources and make decisions about whether those
+requests should be granted or denied.  In order to make a
 
 
-          Stokes, Byrne, Blakley   Expires 10 September 2000        [Page 2]
 
+Stokes, et al      Expires 14 January 2001          [Page 2]
+\f
 
 
 
 
+Internet-Draft      Access Control Model        14 July 2000
 
-          Internet-Draft      Access Control Model       10 March 2000
 
 
+grant/deny decision about a request for access to a
+protected resource, an access control mechanism needs to
+evaluate policy data.  This policy data describes security-
+relevant characteristics of the requesting subject and the
+rules which govern the use of the target object.
 
-             The access control model defines
+No mechanism is defined in this document for storage of
+access control information at the server beyond indicating
+that the attribute holding access control information is an
+operational attribute.
 
-                - A wire protocol for interoperability:  The existing
-                  LDAP protocol flows for add, delete, modify, and
-                  search are used to manipulate access control
-                  information.  There is an additional LDAP control
-                  and extended protocol operation defined,
-                  getEffectiveRights, to further help management of
-                  access control information.
+The access control mechanisms specified in this document are
+neutral with respect to policy inheritance mechanisms,
+explicit vs. implicit denial, and group nesting.
 
-                - A set of access control information (ACI) attributes
-                  for application portability:  These attributes are
-                  used as input to the LDAP APIs so access control
-                  information can be addressed uniformly independent
-                  of how that information is addressed and stored at
-                  the server. These same attributes appear in LDIF
-                  output for interchange of access control
-                  information.
+The access control model defines
 
-                - A set of attributes to identity the access control
-                  mechanisms supported by a server and in a given part
-                  of the namespace.
+   - What flows on the wire for interoperability
 
-             Encoding of access control information on the wire is per
-             the LDAPv3 specifications.
+     The existing LDAP protocol flows for ldap operations
+     are used to manipulate access control information.  A
+     set of permissions and their semantics with respect to
+     ldap operations is defined.  The permissions parallel
+     the types of ldap operations defined.  What is
+     transmitted is exactly what is read back.  Encoding of
+     access control information on the wire is per the
+     LDAPv3 specifications.
 
-             The instantiation of an access control model at the
-             directory server is not defined in this document.
+     There is an additional LDAP control and extended
+     protocol operation defined, getEffectiveRights.  LDAP
+     clients use the control and extended operation to
+     manage and administer access control policy enforced by
+     LDAP servers.
 
-             No mechanisms are defined in this document to control
-             access to access control information or for storage of
-             access control information at the server; this is vendor
-             dependent.
+     Servers may store access control information in any way
+     they choose. In particular, servers may use the access
+     control mechanisms of their datastores to store and
+     enforce LDAP access control, or they may implement
+     access control managers external to their datastores.
+     Datastores and external access control managers MAY
+     implement any access control rule syntax and semantics
+     they choose, but the semantics MUST be compatible with
+     those defined in the section titled "Operational
+     Semantics of Access Control Operations".
 
-             A separate requirements document for access control
-             exists.  The access control model used the requirements
-             documents as a guideline for the development of this
-             specification and are reflected in this specification to
-             the extent that the working group could agree on an
-             access control model.
+   - Attributes and classes for application portability of
+     access control information
 
+     An access control information attribute (ldapACI) for
+     application portability:  This attribute is used as
+     input to the LDAP APIs so access control information
 
 
 
+Stokes, et al      Expires 14 January 2001          [Page 3]
+\f
 
 
 
 
-          Stokes, Byrne, Blakley   Expires 10 September 2000        [Page 3]
+Internet-Draft      Access Control Model        14 July 2000
 
 
 
+     can be addressed uniformly independent of how that
+     information is addressed and stored at the server.
+     This same attribute appears in LDIF output for
+     interchange of access control information.
 
+     An access control information subentry class
+     (ldapACISubEntry) and a set of attributes
+     (supportedAccessControlSchemes which is used in the
+     rootDSE and accessControlSchemes which is used in the
+     subentry ldapACISubEntry) to identity the access
+     control mechanisms supported by a server and in a given
+     part of the namespace, respectively.
 
+   - An attribute in the rootDSE, discloseOnError, to
+     control whether it is permissible for the server to
+     return the name of an entry or attribute in an error
+     (or empty set) operation result.  This closes a hole on
+     the ability to discover information you are not
+     authorized to discover.
 
-          Internet-Draft      Access Control Model       10 March 2000
+   - A mechanism to control access to access control
+     information:  The access control information attribute,
+     ldapACI, is used to control access to access control
+     information (controls access to itself).  How to get an
+     initial ldapACI in the directory is server specific and
+     beyond the scope of this model.
 
+Servers can support multiple access control mechanisms, but
+MUST be capable of supporting the LDAP Mechanism in the DIT
+scoped by the rootDSE (entire server's DIT) for that server
+and SHOULD be capable of supporting the LDAP mechanism in an
+arbitrary part (subtree) of the DIT.
 
+The accessControlSchemes attribute in the ldapACISubEntry
+indicates which access control mechanism is in effect for
+the scope of that ldapACISubEntry.  The
+supportedAccessControlSchemes attribute in the rootDSE
+indicates which acess control mechanisms are supported by
+the server; those mechanisms are in effect in that server's
+DIT unless overridden by a mechanism defined in a
+ldapACISubEntry elsewhere in that DIT.
 
-          3.  Terminology
+Changing the value(s) of either the
+supportedAccessControlSchemes or accessControlSchemes
+attributes changes the mechanism(s) in effect for the scope
+of those attributes (where scope is either that of the
+rootDSE or ldapACISubEntry).
 
-             An "access control list" contains the access control
-             policy information controlling access to an object or
-             collection of objects.  An access control list consists
-             of a set of access control list entries.
+Through the use of the mechanism rootDSE attribute and
+ldapACI subentry, it is possible to run multiple mechanisms
+in either the same subtree or separate subtrees.  If two
 
-             An "access control list entry" defines a single subject
-             security attribute's granted rights for the objects
-             governed by the access control list to which it belongs.
 
-             The "access control information" (aci) for an object or a
-             collection of objects defines which subject security
-             attributes entitle a subject to which granted rights.
-             The access control information for an object may be
-             stored in an access control list.
 
-             An "access decision" is a boolean-valued function which
-             answers the question: "can the subject with these subject
-             security attributes perform this operation on this
-             object?"
+Stokes, et al      Expires 14 January 2001          [Page 4]
+\f
 
-             An "access decision function" is an algorithm which makes
-             an access decision based on subject security attributes,
-             access control information, an object identifier, and an
-             operation name (possibly augmented by additional
-             contextual information).
 
-             An "access decision function interface" is a programmatic
-             interface through which applications can request an
-             access decision.
 
-             An "access identity" is an identity which is used by an
-             access decision function to make an access decision.
 
-             An "audit identity" is an identity which does not, in the
-             absence of additional information, enable a party
-             receiving and examining it to determine which subject it
-             belongs to.
+Internet-Draft      Access Control Model        14 July 2000
 
-             A "credential" is a collection of subject security
-             attributes.
 
-             "effective rights" are the complete set of rights a
-             subject is entitled to based on all access control lists
 
+mechanisms are run in the same subtree, it is desirable that
+the result be the same independent of mechanism, but
+definition and discussion of this is beyond the scope of
+this model.
 
 
-          Stokes, Byrne, Blakley   Expires 10 September 2000        [Page 4]
 
+3.  Access Control Mechanism Attributes
 
+Two attributes are defined to identify which access control
+mechanisms are supported by a given server and by a given
+subtree:  supportedAccessControlSchemes and
+accessControlSchemes.  (We chose these names based on the
+X.500 attribute, AccessControlScheme which is single-valued
+and defined in X.501).
 
 
+3.1  Root DSE Attribute for Access Control Mechanism
 
+The server advertises which access control mechanisms it
+supports by inclusion of the 'supportedAccessControlSchemes'
+attribute in the root DSE.  This attribute is a list of
+OIDs, each of which identify an access control mechanism
+supported by the server.  By default, these are also the
+mechanisms in effect in subtrees beneath the root in that
+server unless overridden by a ldapACISubEntry (see section
+"Subentry Class Access Control Mechanism").
 
-          Internet-Draft      Access Control Model       10 March 2000
+ (<OID to be assigned>
+    NAME      'supportedAccessControlSchemes'
+    DESC      list of access control mechanisms supported
+                by this directory server
+    SYNTAX    LDAPOID
+    USAGE     dSAOperation
+ )
 
+The access control mechanism defined is:
+     LDAPv3     <OID to be assigned>
 
+Other vendor access control mechanisms MAY be defined (by
+OID) and are the responsibility of those vendors to provide
+the definition and OID.
 
-             which apply to a specific object and based on all of the
-             subject's security attributes.
 
-             "granted rights" are the complete set of rights an access
-             control list entitles a subject to based on a specific
-             subject security attribute.
+3.2  Root DSE Attribute for Control of Disclosing Errors
 
-             A "group" is a privilege attribute asserting a subject's
-             membership in the collection of subjects whose name is
-             that of the group.
+The server specifies whether it is permissible for the name
+of an entry or attribute to be disclosed in an error (or
+empty) operation result.  This rootDSE attribute is
+discloseOnError.  The default for discloseOnError is false
+(0) or not to disclose on error.  The lack of this attribute
 
-             An "identity" is a subject security attribute which is
-             unique to a single subject.
 
-             A "privilege attribute" is a subject security attribute
-             which may be shared by several subjects.
 
-             "required rights" are the complete set of rights needed
-             to authorize a requester to perform a specific operation
-             on an object of a specific type.
+Stokes, et al      Expires 14 January 2001          [Page 5]
+\f
 
-             A "right" is the basic unit of access control
-             administration.  For each object type in an information
-             system, a security administrator defines a set of
-             required rights for each operation.  For each object in
-             the system, a security administrator defines a set of
-             granted rights for each subject security attribute.  When
-             an access decision is required, an access decision
-             function checks to make sure that the requester's subject
-             security attributes have been granted all required rights
-             needed to perform the requested operation on the
-             specified target object.
 
-             A "role" is a privilege attribute asserting a subject's
-             organizational position and entitlement to perform the
-             operations appropriate to that organizational position.
 
-             A "subject' is an entity which initiate actions in an
-             information system.
 
-             A "subject security attribute" is a defined property
-             which is used by a security policy evaluation system to
-             make policy decisions.
+Internet-Draft      Access Control Model        14 July 2000
 
 
 
+in the rootDSE is interpreted as the default.
 
+ (<OID to be assigned>
+    NAME      'discloseOnError'
+    DESC      specify whether to return the name of an
+                entry or attribute in an error (or
+                empty) operation result; 0=do not
+                disclose (default); 1=disclose
+    SYNTAX    LDAPString
+    USAGE     dSAOperation
 
-          Stokes, Byrne, Blakley   Expires 10 September 2000        [Page 5]
 
+3.3  Subentry Class Access Control Mechanism
 
+A given naming context MUST provide information about which
+access control mechanisms are in effect for that portion of
+the namespace.  This information is contained in a subentry
+(ldapACISubEntry class), derived from [SUBENTRY].
+ldapACISubEntry MAY be used to define the scope of an access
+control mechanism.  The value(s) held in the rootDSE
+attribute, supportedAccessControlSchemes, are the mechanisms
+in effect in subtrees beneath the root in that server unless
+overridden in a ldapACISubEntry further down the tree held
+by that server.  The scope of that ldapACISubEntry is to the
+end of the subtree held by that server or until another
+ldapACISubEntry is encountered in that subtree held by that
+server.  The ldapACISubEntry class is defined as:
 
 
+ ( <OID to be assigned>
+     NAME   'ldapACISubEntry'
+     DESC   'LDAP ACI Subentry class'
+     SUP    ldapSubEntry STRUCTURAL
+     MUST   ( accessControlSchemes )
+ )
 
+The accessControlSchemes attribute MUST be in each ldap
+access control subentry entry associated with a naming
+context whose access control mechanism is different from
+adjacent naming contexts supported by that directory server.
+accessControlSchemes lists the values (list of OIDs) that
+define the access control mechanisms in effect for the scope
+of that ldap access control subentry.  Although, in general,
+this attribute will define only a single mechanism (single
+value), more than one mechanism MAY be in effect for the
+scope of that subentry.
 
-          Internet-Draft      Access Control Model       10 March 2000
+ (<OID to be assigned>
+    NAME      'accessControlSchemes'
+    DESC      list of access control mechanisms supported
+                in this subtree
 
 
 
-          4.  The Model
+Stokes, et al      Expires 14 January 2001          [Page 6]
+\f
 
-             The access control mechanism described in this draft
-             addresses these activities:
 
-                - Definition of subject security attributes
-                  information
 
-                - Definition of access control policy
 
-                - Retrieval of subject security attributes
+Internet-Draft      Access Control Model        14 July 2000
 
-                - Retrieval of effective access rights
 
-                - Externalization of access control policy information
 
-          4.1  Access Control Information Model
+    SYNTAX    LDAPOID
+    USAGE     dSAOperation
+ )
 
-             This document does not define formats for storage of
-             access control information; it does define the
-             operational semantics of access control operations.
 
 
+4.  The Access Control Information Attribute (ldapACI)
 
+The access control information attribute, ldapACI, is
+defined as:
 
+ (<OID to be assigned>
+   NAME      'ldapACI'
+   DESC      'ldap access control information'
+   EQUALITY  caseIgnoreMatch
+   SYNTAX    directoryString
+   USAGE     directoryOperation
+ )
 
+The intent of the attribute definition is to design a common
+interchange format.  Any given LDAP server should be able to
+translate the below defined attribute into meaningful
+operation requests. Each server should be able to understand
+the attribute; there should not be any ambiguity into what
+any part of the syntax means.
 
+While the end goal is to have a common behavior model
+between different LDAP server implementations, the attribute
+definition alone will not ensure identical ACL processing
+behavior between servers.  The semantics of how a server
+interprets the ACI syntax are defined in the "Operational
+Semantics of Access Control" section of this document.
+Additionally, while the server must recognize and act on the
+attribute when received over the wire, there are no
+requirements for the server to physically store this
+attribute.
 
+The attribute definition maintains an assumption that the
+receiving server supports inheritance within the security
+model. If the server does not support inheritance, the
+receiving server must expand any inherited information based
+on the scope flag.  If the server does not support partial
+inheritance and both the entry and subtree scope are used,
+then entry is the prevailing scope.  (It is possible for two
+values in the ldapACI attribute to have different scopes
+given the syntax of ldapACI; one might contain 'entry' and
+another might contain 'subtree'.  This implies that some
+ldapACI values inherit down the DIT and othersdo not - hence
+partial inheritance of the ldapACI attribute.)
 
+The attribute is defined so access control information (ACI)
 
 
 
+Stokes, et al      Expires 14 January 2001          [Page 7]
+\f
 
 
 
 
+Internet-Draft      Access Control Model        14 July 2000
 
 
 
+can be addressed in a server independent of server
+implementation.  This attribute is used in typical LDAP APIs
+and in LDIF output of ACI. This attribute may be queried or
+set on all directory objects.  The BNF and definitions are
+given below.
 
 
+4.1  The BNF
 
 
+4.1.1  ACI String Representation
 
+ Values of this syntax are encoded according to the
+ following BNF which follows the BNF encoding
+ conventions described in [ABNF]:
 
+ ldapACI = scope "#" rights "#" attr "#" subject
 
+ scope = "entry" / "subtree"
 
+ rights = (("grant:" / "deny:") permissions) /
+          ("grant:" permissions ";deny:" permissions)
 
         Stokes, Byrne, Blakley   Expires 10 September 2000        [Page 6]
permissions = [permission *("," permission)]
 
+ permission = "a" / ; add
+              "d" / ; delete
+              "e" / ; export
+              "i" / ; import
+              "n" / ; renameDN
+              "b" / ; browseDN
+              "t" / ; returnDN
+              "r" / ; read
+              "s" / ; search
+              "w" / ; write (mod-add)
+              "o" / ; obliterate (mod-del)
+              "c" / ; compare
+              "m" / ; make
 
+ attr = "[all]" / "[entry]" / (attribute *("," attribute))
 
+ attribute = ; OID syntax (1.3.6.1.4.1.1466.115.121.1.38)
+             ;     from [ATTR]
 
+ subject = ["authnLevel:" authnLevel ":"]
+             (("authzID-" authzID) /
+             ("role:" dn) /
+             ("group:" dn) /
+             ("subtree:" dn) /
+             ("ipAddress:" ipAddress) /
+             "public:" /
 
 
-          Internet-Draft      Access Control Model       10 March 2000
 
+Stokes, et al      Expires 14 January 2001          [Page 8]
+\f
 
 
-             The diagram below illustrates the componentry of a LDAP
-             system and the placement of the function specified in
-             this draft.
 
-                   +-------------+
-                   | Application |<--attrs to address ACI
-                   +-------------+    - ldapACI
-                     +--------+       - policyOwner
-                     | LDAP   |
-                     | Client |
-                     +--------+
-                         |
-                         | <-- LDAP control
-                         |       - getEffectiveAccess
-                         |
-                         | <-- LDAP extended operation
-                         |       - getEffectiveAccess
-                         v
-              +-----------------------------+
-              |   LDAP Server (e.g. SLAPD)  |
-              +-----------------------------+
-                    .               |
-                    .               |
-                    .               |
-                    .               |
-                    v               v
-              +----------+   +-----------+
-              | Access   |   |           |<-attrs to define
-              | Control  |<--| Datastore |  access control mechanisms
-              | Manager  |   |           |   - supportedACIMechanisms
-              +----------+   +-----------+   - aCIMechanisms
 
-             LDAP clients use the control and extended operation
-             specified in this document to administer access control
-             policy enforced by LDAP servers.  Servers may store
-             access control information in any way they choose. In
-             particular, servers may use the access control mechanisms
-             of their datastores to store and enforce LDAP access
-             control, or they may implement access control managers
-             external to their datastores.  Datastores and external
-             access control managers may implement any access control
-             rule syntax and semantics they choose, as long as the
-             semantics are compatible with that defined in the section
-             titled "Operational Semantics of Access Control
-             Operations".
+Internet-Draft      Access Control Model        14 July 2000
 
 
 
-          Stokes, Byrne, Blakley   Expires 10 September 2000        [Page 7]
+             "this:")
 
+ authnLevel = "any" /
+              "simple" /
+              sasl
 
+ sasl = "sasl:"
+        ("any" /
+        mechanism)
 
+ mechanism = ; sasl mechanism from 4.2 of [LDAPv3]
 
+ authzID = ; authzID from [AuthMeth] repeated below
+           ;    for convenience
 
+ authzId = dnAuthzId / uAuthzId
 
-          Internet-Draft      Access Control Model       10 March 2000
+ ; distinguished-name-based authz id.
+ dnAuthzId  = "dn:" dn
 
+ dn = utf8string ; with syntax defined in [UTF]
 
+ ; unspecified userid, UTF-8 encoded.
+ uAuthzId   = "u:" userid
+ userid     = utf8string ; syntax unspecified
 
-             The access control administration mechanisms specified in
-             this document are neutral with respect to policy
-             inheritance mechanisms, explicit vs.  implicit denial,
-             and group nesting.
+ ipAddress = printableString
+               ; dotted decimal form (e.g. 10.0.0.6)
+               ; or use wildcards such as 12.3.45.* to
+               ;    specify a specific subnetwork
+               ; or 123.45.6.*+255.255.255.115 to
+               ;    specify a subnetmask
+               ; or use a wildcard domain name such as
+               ;    *.airius.com to specify a specific
+               ;    DNS domain
 
+ printableString ; printableString syntax from [ATTR]
 
-          5.  Access Control Mechanism Attributes
 
-             There are several attributes defined associated with
-             access control.  Two attributes are defined to identify
-             which access control mechanisms are supported by a given
-             server and by a given subtree:  supportedACIMechanisms
-             and aCIMechanisms.
+Note that the colon following the "public" and "this"
+subject options exist only to simplify string parsing.
 
+Note also that per [AuthMeth], authzID may be expanded in
+the future.
 
-          5.1  Root DSE Attribute for Access Control Mechanism
+See section titled 'ACI Examples' for examples of the string
+representation.
 
-             The server advertises which access control mechanisms it
-             supports by inclusion of the 'supportedACIMechanisms'
-             attribute in the root DSE.  This attribute is a list of
-             OIDs, each of which identify an access control mechanism
-             supported by the server.
 
-              (<OID to be assigned>
-                 NAME      'supportedACIMechanisms'
-                 DESC      list of access control mechanisms supported
-                             by this directory server
-                 SYNTAX    LDAPOID
-                 USAGE     dSAOperation
-              )
 
-             The access control mechanism defined is:
-                  LDAPv3     <OID to be assigned>
 
-             Other vendor access control mechanisms can be defined (by
-             OID) and are the responsibility of those vendors to
-             provide the definition and OID.
 
 
-          5.2  Subschema Attribute for Access Control Mechanism
 
-             A given naming context must provide information about
-             which access control mechanisms are in effect for that
-             portion of the namespace.  The following attribute must
-             be in each subschema entry associated with a naming
+Stokes, et al      Expires 14 January 2001          [Page 9]
+\f
 
 
 
-          Stokes, Byrne, Blakley   Expires 10 September 2000        [Page 8]
 
+Internet-Draft      Access Control Model        14 July 2000
 
 
 
+4.1.2  ACI Binary Representation
 
+ The following ASN.1 data type is used to represent this
+ syntax when transferred in binary form:
 
-          Internet-Draft      Access Control Model       10 March 2000
+ ldapACI ::= SEQUENCE {
+      scope      ENUMERATED {
+            entry       (0),
+            subtree     (1) },
+      rights     SEQUENCE OF CHOICE {
+            grant       [0] Permissions,
+            deny        [1] Permissions },
+      attr       CHOICE {
+            all         [0] NULL,
+            entry       [1] NULL,
+            attributes  [2] SEQUENCE OF Attribute },
+      subject    SEQUENCE {
+         authnLevel   CHOICE {
+            any      [0] NULL,
+            simple   [1] NULL,
+            sasl     [2] CHOICE {
+               any       [0] NULL,
+               mechanism [1] LDAPString -- from [LDAPv3]
+            }
+         },
+      subject    CHOICE {
+            dn          [0] DN,
+            user              [1] utf8String
+            role        [1] DN,
+            group       [2] DN,
+            subtree     [3] DN,
+            ipAddress   [4] IPAddress,
+            public      [6] NULL,
+            this        [7] NULL }, } -- may be expanded
+                                          per [AuthMeth]
 
+   Permissions ::= SEQUENCE OF ENUMERATED {
+      add        (0),
+      delete     (1),
+      export     (2),
+      import     (3),
+      renameDN   (4),
+      browseDN   (5),
+      returnDN   (6),
+      read       (7),
+      search     (8),
+      write      (9),
+      obliterate (10),
+      compare    (11),
+      make       (12) }
 
 
-             context whose access control mechanism is different from
-             adjacent naming contexts supported by that directory
-             server.
 
-             aCIMechanisms lists the values (list of OIDs) that
-             defines the access control mechanism in effect for the
-             scope of that subschema entry.  More than one mechanism
-             may be in effect for the scope of that subschema entry.
 
-              (<OID to be assigned>
-                 NAME      'aCIMechanisms'
-                 DESC      list of access control mechanisms supported
-                             in this subtree
-                 SYNTAX    LDAPOID
-                 USAGE     dSAOperation
-              )
+Stokes, et al      Expires 14 January 2001         [Page 10]
+\f
 
 
 
-          6.  Access Control Information Attributes
 
+Internet-Draft      Access Control Model        14 July 2000
 
-             The intent of the following attribute definitions is to
-             design a common interchange format.  Any given LDAP
-             server should be able to translate the below defined
-             attributes into a meaningful operation requests. Each
-             server should be able to understand the attributes; there
-             should not be any ambiguity into what any part of the
-             syntax means.
 
-             While the end goal is to have a common behavior model
-             between different LDAP server implementations, the
-             attribute definition alone will not ensure identical ACL
-             processing behavior between servers.  The semantics of
-             how a server interprets the ACI syntax are defined in the
-             "Operational Semantics of Access Control' section of this
-             document.  Additionally, while the server must recognize
-             and act on the attribute when received over the wire,
-             there are no requirements for the server to physically
-             store this attribute.
 
-             The attribute definition maintains an assumption that the
-             receiving server supports inheritance within the security
-             model. If the server does not support inheritance, the
-             receiving server must expand any inherited information
+   Attribute ::= AttributeType -- from [LDAPv3]
 
+   IPAddress ::= PrintableString -- (e.g. 10.0.0.6)
 
 
-          Stokes, Byrne, Blakley   Expires 10 September 2000        [Page 9]
 
+4.2  The Components of ldapACI Attribute
 
+This section defines components that comprise the access
+control information attribute, ldapACI.
 
 
+4.2.1  Scope
 
+Two scopes for access control information are defined:
 
-          Internet-Draft      Access Control Model       10 March 2000
+   - entry - the access control information in the ldapACI
+     attribute applies only to the entry in which it is
+     contained
 
+   - subtree - the access control information in the ldapACI
+     attribute applies to each entry down the subtree unless
+     it is overridden by an entry-specific ldapACI whose
+     values are more specific.
 
+Use of prescriptive ACIs and scoping via use of a
+ldapACISubEntry is outside the scope of this document.
 
-             based on the scope flag.  If the server does not support
-             partial inheritance and both the entry and subtree scope
-             are used, then entry is the prevailing scope.
 
-             Two attributes are defined so access control information
-             (ACI) can be addressed in a server independent of server
-             implementation.  These attributes are used in typical
-             LDAP APIs and in LDIF output of ACI. These two attributes
-             may be queried or set on all directory objects:  ldapACI
-             and policyOwner.  Their BNF and definitions are defined
-             below.
+4.2.2  Access Rights and Permissions
 
+Access rights can apply to an entire object or to attributes
+of the object. Access can be granted or denied.  Either or
+both of the actions "grant" | "deny"  may be used when
+creating or updating ldapACI.
 
-          6.1  The BNF
+Each of the LDAP access permissions are discrete. One
+permission does not imply another permission.  The
+permissions which apply to attributes and the entry parallel
+the type of ldap operations that can be performed.
 
-          < ldapACI > ::= < acl entry syntax >
+Permissions which apply to attributes:
 
-          < acl entry syntax > ::= <familyOID> + '#' + <scope > + '#'
-                             + < rights >  + '#' + < dnType >
-                             + '#' + < subjectDn >
+   r   Read        Read attribute values
+   w   Write       Modify-add values
+   o   Obliterate  Modify-delete values
+   s   Search      Search entries with specified attributes
+   c   Compare     Compare attributes
+   m   Make        Make attributes on a new entry below
+                     this entry
 
-          < policyOwner > ::= < familyOid > + '#' + <scope >
-                             + '#' +< dnType > + '#' + < subjectDn >
 
-          < subjectDn > ::= < printable string > | "public" | "this"
 
-          < familyOid > ::= < oid >
 
-          <scope > ::= "entry"  | "subtree"
+Stokes, et al      Expires 14 January 2001         [Page 11]
+\f
 
-          < dnType > ::= "access-id" | "role" | "group" | "subtree"
-                       | "ipAddress" | "kerberosID"
-                       | <printableString>
 
-          < kerberosID > ::= < userID > + '@' + < realm >
 
-          < userID > ::= < printableString >
 
-          < realm > ::= < printableString >
+Internet-Draft      Access Control Model        14 July 2000
 
-          < rights > ::= "grant" + ';' + <permissions> + ';'+<attr>
-             | "deny" + ';' + <permissions> + ';'+<attr> |
-             "grant"+';'+<permissions>+';'+"deny"+';'+<permissions>+';'+<attr>
 
-          < permissions > ::= [ ] | [ <permission>
 
+  1.  r  Read
 
+      If granted, permits attributes and values to be
+      returned in a read or search operation.
 
-          Stokes, Byrne, Blakley   Expires 10 September 2000         [Page 10]
+  2.  w  Write
 
+      If granted, permits attributes and values to be added
+      in a modify operation.
 
+  3.  o  Obliterate
 
+      If granted, permits attributes and values to be
+      deleted in a modify operation.
 
+  4.  s  Search
 
+      If granted, permits attributes and values to be
+      included in a search operation.
 
-          Internet-Draft      Access Control Model       10 March 2000
+  5.  c  Compare
 
+      If granted, permites attributes and value to be used
+      in a compare operation.
 
+  6.  m  Make
 
-                              + [ ',' + <permission> ] ]*
+      The attribute permission "m" is required for all
+      attributes that are placed on an object when it is
+      created. Just as the "w" and "o" permissions are used
+      in the Modify operation, the "m" permission is used in
+      the Add operation. Additionally, note that "w" and "o"
+      have no bearing on the Add operation and "m" has no
+      bearing on the Modify operation.  Since a new object
+      does not yet exist, the "a" and "m" permissions needed
+      to create it must be granted on the new object's
+      parent. This differs from "w" and "o" which must be
+      granted on the object being modified. The "m"
+      permission is distinct and separate from the "w" and
+      "o" permissions so that there is no conflict between
+      the permissions needed to add new children to an entry
+      and the permissions needed to modify existing children
+      of the same entry.
 
-          < attr > ::= ["collection" + ':' + [ "[all]" | "[entry]"
-                            | <printableString>] ]
-                            | ["attribute" + ':' <printableString>]
+Note:  Modify-replace values of an attribute requires "w"
+and "o" permission.
 
-          < permission > ::= "a" | "d" | "r" | "s" | "w" |
-                             "c" | "e" | "b"
+Permissions that apply to an entire entry:
 
-          These are the permissions defined for the IETF LDAP family
-          OID.
-               "a" corresponds to add
-               "d" corresponds to delete
-               "r" corresponds to read
-               "s" corresponds to search
-               "w" corresponds to write
-               "c" corresponds to compare
-               "e" corresponds to editDN
-               "b" corresponds to browseDN
 
+   a    Add        Add an entry below this entry
 
-          6.2  Other Defined Parameters
 
-             This section defines additional parameters that are used
-             in the two attributes that address access control
-             information.
 
+Stokes, et al      Expires 14 January 2001         [Page 12]
+\f
 
-          6.2.1  Families and Rights
 
-             The familyOID tells what permission set etc. will follow
-             in the string. This allows a different permission set,
-             scope etc.,  but with the same syntax.
 
-             The following family is defined:
-                  IETF-LDAPv3     <OID to be assigned>
 
-             Other families can be defined (by OID).  It is the
-             responsibility of those parties to provide the definition
-             and OID.
+Internet-Draft      Access Control Model        14 July 2000
 
 
-          6.2.1.1  IETF-LDAPv3 Family
 
-             Access rights can apply to an entire object or to
+   d    Delete     Delete this entry
+   e    Export     Export entry & subordinates to new
+                      location
+   i    Import     Import entry & subordinates from some
+                      location
+   n    RenameDN   Rename an entry's DN
+   b    BrowseDN   Browse an entry's DN
+   t    ReturnDN   Allows DN of entry to be disclosed in
+                      an operation result
 
 
+  1.  a  Add
 
-          Stokes, Byrne, Blakley   Expires 10 September 2000         [Page 11]
+      If granted, permits creation of an entry in the DIT
+      subject to control on all attributes and values to be
+      placed in the new entry at time of creation.  In order
+      to add an entry, permission must also be granted to
+      add at least the mandatory attributes.
 
+  2.  d  Delete
 
+      If granted, permits the entry to be removed from the
+      DIT regardless of controls on attributes within the
+      entry.
 
+  3.  e  Export
 
+      If granted, permits an entry and its subordinates (if
+      any) to be exported; that is, removed from the current
+      location and placed in a new location subject to the
+      granting of suitable permission at the destination.
+      If the last RDN is changed, Rename is also required at
+      the current location. In order to export an entry or
+      its subordinates, there are no prerequisite
+      permissions to contained attributed, including the RDN
+      attributes; this is true even when the operation
+      causes new attribute values to be added or removed as
+      the result of the changes of RDN.
 
+  4.  i  Import
 
-          Internet-Draft      Access Control Model       10 March 2000
+      If granted, permits an entry and its suordinates (if
+      any) to be imported; that is, removed from some other
+      location and placed a t the location to which the
+      permission applies subject to the granting of suitable
+      permissions at the source location.  In order to
+      import an entry or its subordinates, there are no
+      prerequisite permissions to contained attributed,
+      including the RDN attributes; this is true even when
+      the operation causes new attribute values to be added
+      or removed as the result of the changes of RDN.
 
 
 
-             attributes of the object.  Each of the LDAP access rights
-             are discrete. One permission does not imply another
-             permission.  The rights which apply to attributes and the
-             entry parallel the type of ldap operations that can be
-             performed.
+Stokes, et al      Expires 14 January 2001         [Page 13]
+\f
 
-             Rights which apply to attributes:
 
-                r   Read     Read attribute values
-                w   Write    Write attribute values
-                s   Search   Search entries with specified attributes
-                c   Compare  Compare attributes
 
-             Rights that apply to an entire entry:
 
-                a    Add      Add an entry below this entry
-                d    Delete   Delete this entry
-                e    EditDN   Edit an entry's DN
-                b    BrowseDN Browse an entry's DN
+Internet-Draft      Access Control Model        14 July 2000
 
-             When searching, the ldap search filter specifies the
-             returned set of attributes.  To do the search, browse (b)
-             must be set for the entry (you can search only entries
-             that you have permission to search so you can't discover
-             things you don't have permission to) and search (s) must
-             be set for all attributes used in the filter if you are
-             testing for existence, otherwise search (s) and read (r)
-             must be set for all attributes used in the filter because
-             the filter specifies a test for other than existence.
-             For a search to return attribute names only, search (s)
-             must be set for the attribute.  For a search to return
-             attribute names and values, search (s) and read (r) must
-             be set for the attribute.  Search (s) implies knowledge
-             of the attribute; read (r) implies knowledge of the
-             value.
 
 
-          6.2.2  DN Types
+  5.  n  RenameDN
 
-             The following DN Types strings are defined and MUST be
-             supported:
+      Granting Rename is necessary for an entry to be
+      renamed with a new RDN, taking into account
+      consequential changes to the distinguished names of
+      subordinate entries, if any; if the name of the
+      superior is unchanged, the grant is sufficient.  In
+      order to rename an entry, there are no prerequisite
+      permissions to contained attributed, including the RDN
+      attributes; this is true even when the operation
+      causes new attribute values to be added or removed as
+      the result of the changes of RDN.
 
-                - access-id
+  6.  b  BrowseDN
 
+      If granted, permits entries to be accessed using
+      directory operations which do not explicitly provide
+      the name of the entry.
 
+  7.  t  ReturnDN
 
+      If granted, allows the distinguished name of the entry
+      to be disclosed in the operation result.
 
+All permissions (for grant and deny) for an attribute/entry
+and a given subject MUST be contained within one ldapACI
+value, i.e. (in abbreviated form)
 
-          Stokes, Byrne, Blakley   Expires 10 September 2000         [Page 12]
+ ldapACI:  ...grant OID.attr1 subjectA
+ ldapACI:  ...deny OID.attr1 subjectA
 
+must be ldapACI:  ...grant ... deny... OID.attr1 subjectA
 
+Using the defined BNF it is possible for the permission
+string to be empty. The ACI
 
+ ldapACI: subtree#grant#OID.attr1#group:cn=Dept XYZ,c=US
 
+ ldapACI: subtree#grant:r,s#[all]#group:cn=Dept XYZ,c=US
 
+means that this group (Dept XYZ) is granted permission to
+read and search all attributes except OID.attr1 because
+OID.attr1 is more specific than "[all]".
 
-          Internet-Draft      Access Control Model       10 March 2000
 
+4.2.3  Attributes
 
+Attribute describes an attribute name in the form of a
+dotted decimal OID for that <attr>. If the string (OID)
+refers to an attribute not defined in the given server's
+schema, the server SHOULD report an error. "[entry]" means
 
-                - group
 
-                - role
 
-             The following DN Types strings are defined and SHOULD be
-             supported:
+Stokes, et al      Expires 14 January 2001         [Page 14]
+\f
 
-                - ipAddress
 
-                - kerberosID
 
-             An access-id is a non-collection (non-group and non-role
-             objects) DN that can be authenticated.
 
-             groupOfNames and groupOfUniqueNames (or subclasses from
-             those object classes) must be recognized as a collection
-             object.  This aids in interoperability during
-             replication.
+Internet-Draft      Access Control Model        14 July 2000
 
 
-             Other parties can (and will) define other DN Types.  It
-             is the responsibility of those parties to provide the
-             definition.
 
-          6.3  Basic ACI Attribute (ldapACI)
+the permissions apply to the entire object. This could mean
+actions such as delete the object, or add a child object.
+"[all]" means the permission set apply to all attributes of
+the entry.
 
-              (<OID to be assigned>
-                NAME      'ldapACI'
-                DESC      'ldap access control information'
-                EQUALITY  caseIgnoreMatch
-                SYNTAX    directoryString
-                USAGE     directoryOperation
-              )
+If the keyword "[all]" and another attribute are both
+specified within an ACI, the more specific permission set
+for the attribute overrides the less specific permission set
+for "[all]".
 
-             Within the access control syntax, the family OID
-             describes the permissions, dnType, subjectDn and scope
-             that will be found in the following string. If the OID
-             within the ldapACI attribute is listed as other than the
-             IETF-LDAPv3 family OID, the syntax is the same, but one
-             or more of the scope, dnType, subjectDn or permissions
-             may vary from the defined syntax.
 
-             Within the access control syntax, there is a string which
-             describes the rights. This is a composite of the
-             permissions and resources to which the subject is being
+4.2.4  Subjects and Associated Authentication
 
+The following subjects are defined and MUST be supported:
 
+   - authzID, defined per [authmeth]
 
-          Stokes, Byrne, Blakley   Expires 10 September 2000         [Page 13]
+   - group, defined as the distinguished name of a
+     groupOfNames or groupOfUniqueNames entry
 
+   - role
 
+   - subtree, defined as the distinguished name of a non-
+     leaf node in the DIT
 
+   - ipAddress,
 
+   - public, defined as public access
 
+   - this, defined as the user whose name matches that of
+     the entry being accessed
 
-          Internet-Draft      Access Control Model       10 March 2000
+Other parties MAY define other subjects.  It is the
+responsibility of those parties to provide the definition.
 
+A subject may be qualified by the type of authentication
+required for access to a given attribute(s) or entry.  If no
+authnLevel is present, then no specific type of
+authentication is additionally required for access.  If
+authnLevel is specified, then that type of authentication is
+additionally required for access.  The authnLevels parallel
+the authentication mechanisms specified for LDAPv3:  simple,
+SASL (any type of SASL mechanism), and a SASL-specific
+mechanism.  The authnLevel of is not an acceptable mechanism
+for this case) as part of obtaining access.
 
 
-             granted or denied access. The set of permissions is
-             fixed. Either or both of the actions "grant" | "deny"
-             may be used when creating or updating ldapACI.
+4.3  Grant/Deny Evaluation Rules
 
-             <attr> describes either an attribute name or an attribute
-             collection.  The keyword attribute indicates that the
-             following printable string refers to an attribute name.
-             If the string refers to an attribute not defined in the
-             given server's schema, the server SHOULD report an error.
-             The keyword "collection" indicates that the string that
-             follows describes a group of attributes.  The method for
-             grouping attributes is server specific.  Another option
-             for the collection printable string is "[entry]". This is
-             provided to describe permissions which apply to an entire
-             object. This could mean actions such as delete the
-             object, or add a child object. The third option for a
-             collection is "[all]" which means the permission set
-             should apply to all attributes.  Even if the server does
-             not support attribute grouping, it MUST recognize the
-             "[all]" and "[entry]" keywords.  If the server receives
-             an unrecognized attribute collection name, the server
-             SHOULD return an error.  If the server supports grouping,
-             the grouping is server and implementation specific.
+The decision whether to grant or deny a client access to a
+particular piece of information is based on several pieces
 
-             If the keyword "[all]" and another attribute are both
-             specified within an aci, the more specific permission set
-             for the attribute overrides the less specific permission
-             set for "[all]".
 
-             All permissions (for grant and deny) for an attribute and
-             a given DN MUST be contained within one ldapACI value,
-             i.e. (in abbreviated form)
 
-              ldapACI:  ...grant attr1 DN1
-              ldapACI:  ...deny attr1 DN1
+Stokes, et al      Expires 14 January 2001         [Page 15]
+\f
 
-             must be ldapACI:  ...grant ... deny... attr1 DN1
 
-             Using the defined BNF it is possible for the permission
-             string to be empty. The ACI
 
-              ldapACI: 1.2.3.4#subtree#grant;;
-                         attribute:attr1#group#cn=Dept XYZ,c=US
 
-              ldapACI: 1.2.3.4#subtree#grant;r,s;
+Internet-Draft      Access Control Model        14 July 2000
 
 
 
-          Stokes, Byrne, Blakley   Expires 10 September 2000         [Page 14]
+of information found within the ldapaci value.  Throughout
+the decision making process, there are guiding principals.
 
+   - Specificity: More specific policies MUST override less
+     specific ones (e.g. individual user entry in ACI takes
+     precedence over group entry).
 
+   - Deny takes precedence over Grant.
 
+   - When there are conflicting ACI values, deny takes
+     precedence over grant.
 
+   - Deny is the default when there is no access control
+     information.
 
+Precendence of Scope Types (highest to lowest)
 
-          Internet-Draft      Access Control Model       10 March 2000
+   - entry
 
+   - subtree
 
+Precedence of Subjects within a Scope (highest to lowest):
 
-                         collection:[all]#group#cn=Dept XYZ,c=US
+   - ipAddress
 
-             means that this group (Dept XYZ) is granted permission to
-             read and search all attributes except attr1 because attr1
-             is more specific than "[all]".
+   - authzID, this
 
+   - group, role, this, public
 
-          6.3.1  LDAP Operations
+   - subtree, public
 
-             The attributes which are defined for access control
-             interchange may be used in all LDAP operations.
+Although other types MAY be defined given the BNF, use of
+the well-known types aids in interoperability and
+operational consistency.
 
-             Within the ldapmodify-delete operation, the entire acl
-             may be deleted by specifying
+Access Decision algorithm:
 
-              dn: cn = some Entry
-              changetype: modify
-              delete: ldapACI
+  1.  Determine all the ldapACI values which could apply to
+      the target DN which is being accessed.  This is the DN
+      of the entry which is being queried in a search,
+      modified, deleted, etc.  When determining all the
+      ldapACI values, the scope field should be used. All
+      ldapACI values with a scope of 'entry' take precedence
+      over ldapACI values with a scope of 'subtree'.
 
-             In this case, the entry would then inherit its ACI from
-             some other node in the tree depending on the server
-             inheritance model.
+  2.  Determine which ldapACI (of the set determined in step
+      1) apply to the bound DN.  This is determined by
+      looking at the subject (combination of subject type
+      and subject value) and bind type.  If no bind is in
+      effect (this is possible in ldapv3), then treat this
+      lack of bind as if bound as anonymous.  Start with the
 
-             Similarly, if all values of ldapACI are deleted, then the
-             access control information for that entry is defined by
-             that implementation's inheritance model.
 
 
-          6.3.2  Grant/Deny Evaluation Rules
+Stokes, et al      Expires 14 January 2001         [Page 16]
+\f
 
-             More specific policies must override less specific ones
-             (e.g. individual user entry in ACI takes precedence over
-             group entry).
 
-             Deny takes precedence over Grant. When there are
-             conflicting ACI values, deny takes precedence over grant.
-             Deny is the default when there is no access control
-             information.
 
-             Precendence of Scope Types (highest to lowest)
 
-                - entry
+Internet-Draft      Access Control Model        14 July 2000
 
-                - subtree
 
 
+      most specific subject type.  If at any time, at least
+      one ldapACI value exists for a specificity level, then
+      processing stops; the exception here is 'this' because
+      this may also be combined with group to use power of
+      'this'.   Evaluation should take place on set of
+      ldapACI values which are all of the same specificity
+      level.  Subjects of the same precedence are combined
+      using union semantics.
 
+  3.  Evaluate the remaining ldapACI values and determine a
+      grant/deny decision.  If conflicting ldapACI value
+      exists for the same attribute, or attributes (i.e. one
+      ldapACI grants permission and another denies
+      permission), then deny takes precedence over grant.
+      For example, if one is granted permission to
+      "objectclass" in one ldapACI value by being a member
+      of group cn=Admin, and denied permission by being a
+      member of cn = NontrustedAdmins, then the bound user
+      would not receive permission to objectclass.
 
-          Stokes, Byrne, Blakley   Expires 10 September 2000         [Page 15]
+      The rule of specificity also applies to the
+      attributes. If one is denied permission to "[ all ]"
+      attributes, but granted permission to "objectclass"
+      then the more specific value of  "objectclass" takes
+      precedence over the less specific value of "[ all ] ".
+      In this case the user would be granted permission to
+      "objectclass" but denied permission to all other
+      attributes.
 
 
 
+5.  Required Permissions for each LDAP Operation
 
+This section defines the required permissions for each LDAP
+operation but even if these requirements are satisfied the
+server MAY refuse to carry out the operation due to other
+implementation specific security considerations. For
+example, a server may refuse to modify an entry because the
+database where that entry resides is in read only mode.
+Another example might be that although the access control is
+available to the userPassword attribute a server may refuse
+modifications due to some server specific policy governing
+access to passwords.
 
+Here, we specify the rights required by a user when
+performing an LDAP operation in terms of the LDAP
+permissions specified in section 6.1.  Recall that  "a, d,
+e, i, n, b,t" are permissions that apply to entries as a
+whole while permissions "r, s, w, o, c, m" apply to
+attributes within entries.
 
-          Internet-Draft      Access Control Model       10 March 2000
 
 
 
-             Precedence of Privilege Attribute dnTypes within a scope
-             (highest to lowest):
+Stokes, et al      Expires 14 January 2001         [Page 17]
+\f
 
-                - ipAddress
 
-                - access-id, kerberosID (both same precedence)
 
-                - group
 
-                - role
+Internet-Draft      Access Control Model        14 July 2000
 
-                - subtree
 
-             Although other types can be defined given the BNF, use of
-             the well-known types aids in interoperability and
-             operational consistency.
 
+Required permissions for LDAP extended operations and LDAP
+controls are beyond the scope of this draft.
 
-          6.4  Policy Owner Attribute (policyOwner)
+There is a requirement that a user should not be able to
+infer the existence of data in the Directory, if the user
+does not have the required access rights to that data.  An
+example of this requirement would be in a hosting
+environment where you would not want any users from the coke
+subtree to be able to even discover that the pepsi tree was
+hosted on the same server.  This "discloseOnError" feature
+will be set once for server in the rootDSE advertised by the
+attribute discloseOnError.  The default for discloseOnError
+is false (0).  The lack of this attribute in the rootDSE is
+interpreted as the default.  The details of its effects are
+addressed below, operation by operation.
 
-              (<OID to be assigned>
-                 NAME      'policyOwner'
-                 DESC      'Policy Owner Access Control Information'
-                 EQUALITY  caseIgnoreMatch
-                 SYNTAX    directoryString
-                 USAGE     directoryOperation
-              )
+For the following, assume that the authorization identity of
+the user doing the operation is authzID.
 
-             Policy ownership controls administrative subdomains. It
-             can also control who has permission to set / change acls
-             for implementations that do not have ACI controlling
-             access to itself.   If there are multiple policy owners
-             it is implementation specific as to the behavior of
-             whether policy owner #1 can override policy owner # 2.
 
-             The syntax for policyOwner includes the 'scope' flag.
-             Servers which do not support inheritance must expand the
-             policyOwner inheritance similar to the expansion of the
-             ACI.  The scope and any inheritance hierarchy for policy
-             ownership is distinct from any inheritance hierarchy
-             defined for ACI values.
+5.1  Bind Operation
 
-             If the policy owner is not specified for any object in
-             the tree, behavior is implementation defined. For
-             instance, if no object anywhere in the tree has a policy
+This draft does not require any permissions to allow a bind
+operation to proceed.
 
 
+5.2  Search Operation
 
-          Stokes, Byrne, Blakley   Expires 10 September 2000         [Page 16]
+Recall that the parameters of the Search operation per RFC
+2251 [LDAPv3] Section 4.5 are:
 
+   SearchRequest ::= [APPLICATION 3] SEQUENCE {
+        baseObject      LDAPDN,
+        scope           ENUMERATED {
+                baseObject              (0),
+                singleLevel             (1),
+                wholeSubtree            (2) },
+        derefAliases    ENUMERATED {
+                neverDerefAliases       (0),
+                derefInSearching        (1),
+                derefFindingBaseObj     (2),
+                derefAlways             (3) },
+        sizeLimit       INTEGER (0 .. maxInt),
+        timeLimit       INTEGER (0 .. maxInt),
+        typesOnly       BOOLEAN,
+        filter          Filter,
+        attributes      AttributeDescriptionList }
 
+Suppose a server is processing a search request from user
+authzID with parameters as above and is processing the entry
+with dn candidateDN to decide if it may be returned or not.
 
 
 
+Stokes, et al      Expires 14 January 2001         [Page 18]
+\f
 
-          Internet-Draft      Access Control Model       10 March 2000
 
 
 
-             owner, then the server could simply assert that the 'root
-             DN' is considered the policy owner for all objects. An
-             alternate approach might be that the implementation
-             defines the entryDN to be the policy owner.
+Internet-Draft      Access Control Model        14 July 2000
 
 
-          6.5  ACI Examples
 
-             The examples use a family OID = 1.2.3.4
+Then the permissions required by authzID that need to be
+evaluated are as follows:
 
 
-          6.5.1  Attribute Definition
+  1.  permission "b" to the entry candidateDN
 
-             The following two examples show an administrative
-             subdomain being established. The first example shows a
-             single user being assigned the policyOwner for the entire
-             domain. The second example shows a group of IDs assigned
-             to the policy Owner.
+      If this permission is not granted then the dn
+      candidateDN MUST not be returned nor any attribute
+      type nor attribute value from this entry.
 
-             policyOwner: 1.2.3.4#subtree#access-id#cn=Hoyt
+      If this permission is granted then the dn candidateDN
+      MAY be returned.
 
-             policyOwner: 1.2.3.4#subtree#group#cn=System
-             Owners,o=Company
+      Note: The idea of the "b" permission is to say "a user
+      has discovery rights" at a certain entry in the
+      directory.  Assuming that the further required
+      permissions below are satisfied then having "b" right
+      is enough to allow the server to return candidateDN.
+      Of course candidateDN contains in it's components,
+      attributes and attribute values for all the ancestors
+      of candidateDN.  This can lead to the slightly odd
+      situation that we can discover the naming attribute of
+      an entry and that attribute's value by virtue of
+      having the required searching permissions to it's
+      child but not by searching the entry directly.
 
-             The next example shows a ldapACI attribute where a group
-             "cn=Dept XYZ, c=US" is being given permissions to read,
-             search and compare attribute attr1. The permission
-             applies to the entire subtree below the node containing
-             this ACI.
+  2.  permission "s" to each attribute appearing in a
+      presence test during the evaluation of the search
+      filter.  permission "r" to each attribute appearing in
+      non-presence tests (see rfc1960, section 3:
+      equalityMatch, substrings, greaterOrEquial,
+      lessOrEqual, present, approxMatch, extensibleMatch)
+      during the evaluation of the search filter.
 
-              ldapACI:1.2.3.4#subtree#grant;r,s,c;
-                   attribute:attr1#group#cn=Dept XYZ,c=US
+      The above statement covers the case where the
+      attributes are being evaluated as part of an
+      extensibleMatch (RFC 2251 section 4.5.1) which appears
+      in the filter.  In the case where the dnAttributes
+      field of the extensibleMatch is true then we do not
+      require any access checks to the attributes of the dn
+      candidateDN as access to these is taken to be granted
+      by the "b" permission, which has already been required
+      above.
 
-             The next example shows an ACI attribute where a role
-             "cn=SysAdmins,o=Company"  is being given permissions to
-             add objects below this node and read, search, and compare
-             attributes attr2 and attr3. The permission applies to the
-             entire subtree below the node containing this ACI.
+      If there is an attribute in a filter element to which
+      the required permission is not granted then that
+      filter element evaluates to "Undefined" of the three-
+      valued-logic of X.511(93).
 
-              ldapACI: 1.2.3.4#subtree#grant;a;
-                         collection:[entry]#role#cn=SysAdmins,o=Company
+      Note A: Although both "r" and "s" permissions will
+      typically be granted to attributes we keep both
 
-              ldapACI: 1.2.3.4#subtree#grant;r,s,c;
-                         attribute:attr2#role#cn=SysAdmins,o=Company
 
 
+Stokes, et al      Expires 14 January 2001         [Page 19]
+\f
 
 
-          Stokes, Byrne, Blakley   Expires 10 September 2000         [Page 17]
 
 
+Internet-Draft      Access Control Model        14 July 2000
 
 
 
+      permissions as there are cases where the distinction
+      is useful.  For example, the ability to grant the
+      right to discover that a user entry contains a
+      userPassword attribute, but not to read it's value
+      ("s" but not "r").  The converse, granting "r" but not
+      "s" permission is less easy to motivate.
 
-          Internet-Draft      Access Control Model       10 March 2000
+      Note B: There is an unusual behaviour with respect to
+      naming attributes illustrated in the following
+      example:
 
+      Suppose I have "b" rights to cn=fred,o=sun.com and "r"
+      rights to attribute objectclass but not "r" rights to
+      cn then with search filter (objectclass=*) I get back
+      the dn and objectclass (and so can see the value of
+      cn), but with a search filter of (cn=fred) I do not
+      get anything.
 
+  3.  permission "r" to each attribute in the attribute list
 
-              ldapACI: 1.2.3.4#subtree#grant;r,s,c;
-                 attribute:attr3#role#cn=SysAdmins,o=Company
+      AttributeDescriptionList (or all attributes in the
+      entry candidateDN if AttributeDescriptionList is *)
+      whose type and/or value will be returned.
 
+      Note: The presence of an attribute in an entry is only
+      ever volunteered by the server if "r" permission is
+      granted to it, though a user may infer the presence of
+      an attribute with "s" permission by using a presence
+      test on that attribute in the search filter.
 
-          6.5.2  Modifying the ldapACI Values
+  4.  permission "t" to the entry candidateDN
 
-          Modify-Replace works as defined in the ldap oepration
-          modify. If the attribute value does not exist, create the
-          value. If the attribute does exist, replace the value.  If
-          the ldapACI value is replaced, all ldapACI values are
-          replaced.
+      If this permission is not granted then the dn
+      candidateDN MUST NOT be returned. If the server knows
+      of an alias for the entry, this alias may be returned
+      instead. If no alias name is available then the entry
+      candidateDN MUST be omitted from the search results.
 
-          A given ldapACI for an entry:
 
-           ldapACI: 1.2.3.4#subtree#deny;r,w;
-                      collection:[all]#group#cn=Dept ABC
+  5.  Disclose on error for the Search operation
 
-           ldapACI: 1.2.3.4#subtree#grant;r;
-                      attribute:attr1#group#cn=Dept XYZ
+      If every entry in the scope of the search fails to
+      satisfy item 1 (browse right on the candidate entry)
+      or item 2 (right to use the filter on that entry) and
+      if discloseOnError is not granted to the baseObject
+      entry then the operation MUST fail with a "no such
+      object error" and the matchedDN of the LDAPResult MUST
+      be set to "". If every entry in the scope of the
+      search fails to satisfy items 1 or 2 above and
+      discloseOnError is granted to the baseObject then the
+      empty set of results is returned.
 
-          perform the following change:
 
-            dn: cn=someEntry
-            changetype: modify
-            replace: ldapACI
-            ldapACI: 1.2.3.4#subtree#grant;r,w;
-                       collection:[all];#group#cn=Dept LMN
 
-          The resulting ACI is:
+Stokes, et al      Expires 14 January 2001         [Page 20]
+\f
 
-          ldapACI: 1.2.3.4#subtree#grant;r,w;
-                     collection:[all];#group#cn=Dept LMN
 
-          ( ldapACI values for Dept XYZ and ABC are lost through the
-          replace )
 
-          During an ldapmodify-add, if the ACI does not exist, the
-          create the ACI with the specific ldapACI value(s).  If the
-          ACI does exist, then add the specified values to the given
-          ldapACI.  For example a given ACI:
 
-          ldapACI: 1.2.3.4#subtree#grant;r,w;
-                     collection:[all]#group#cn=Dept XYZ
+Internet-Draft      Access Control Model        14 July 2000
 
-          with a modification:
 
 
+5.3  Modify Operation
 
-          Stokes, Byrne, Blakley   Expires 10 September 2000         [Page 18]
+Recall that the parameters of the Modify operation per
+RFC2251 [LDAPv3] Section 4.6 are:
 
+   ModifyRequest ::= [APPLICATION 6] SEQUENCE {
+        object          LDAPDN,
+        modification    SEQUENCE OF SEQUENCE {
+                operation  ENUMERATED {
+                                   add     (0),
+                                   delete  (1),
+                                   replace (2) },
+                modification    AttributeTypeAndValues } }
 
 
+   AttributeTypeAndValues ::= SEQUENCE {
+        type    AttributeDescription,
+        vals    SET OF AttributeValue }
 
+Then the permissions required by authzID that need to be
+evaluated are as follows:
 
 
-          Internet-Draft      Access Control Model       10 March 2000
+  1.  permission "w" to each attribute being added to object
 
+      If this permission is not granted to such an
+      attribute, then the operation MUST fail.  In this
+      case, if discloseOnError is not granted to the entry
+      then "no such object" error is returned; if
+      discloseOnError is granted to the entry and a
+      duplicate attribute value is being added then
+      "attribute value already exists" error is returned; if
+      discloseOnError is granted to the entry and no
+      duplicate value is being added then an "insufficient
+      access" error is returned.
 
+  2.  permission "o" to each attribute for which a value is
+      being deleted from object
 
-            dn: cn=someEntry
-            changetype: modify
-            add: ldapACI
-            ldapACI: 1.2.3.4#subtree#grant;r;
-                   attribute:attr1#group#cn=Dept XYZ
+      If this permission is not granted to such an attribute
+      then the operation MUST fail.  In this case, if
+      discloseOnError is not granted to the entry then "no
+      such object" error is returned; if discloseOnError is
+      granted to the entry and the attribute or one of the
+      values to be deleted does not exist then a "no such
+      attribute or value" error is returned; if
+      discloseOnError is granted to the entry and the
+      attribute and all values specified to be deleted exist
+      then an "insufficient access" error is returned.
 
-          would yield an multi-valued aci of:
 
-           ldapACI: 1.2.3.4#subtree#grant;r,w;
-                      collection:[all]#group#cn=Dept XYZ
 
-           ldapACI: 1.2.3.4#subtree#grant;r;
-                      attribute:attr1#group#cn=Dept XYZ
 
-          To delete a particular ACI value, use the regular ldapmodify
-          - delete syntax
 
-          Given an ACI of:
+Stokes, et al      Expires 14 January 2001         [Page 21]
+\f
 
-           ldapACI: 1.2.3.4#subtree#grant;r,w;
-                      collection:[all]#group#cn=Dept XYZ
-           ldapACI: 1.2.3.4#subtree#grant;r;
-                      attribute:attr1#group#cn=Dept XYZ
 
-            dn: cn = some Entry
-            changetype: modify
-            delete: ldapACI
-            ldapACI: 1.2.3.4#subtree#grant;r;
-                       attribute:attr1#group#cn=Dept XYZ
 
-          would yield a remaining ACI on the server of
 
-          ldapACI: 1.2.3.4#subtree#grant;r,w;
-                     collection:[all]#group#cn=Dept XYZ
+Internet-Draft      Access Control Model        14 July 2000
 
 
-          6.5.3  Evaluation
 
-             These examples assume that the ldapACI entries listed in
-             each example are the only ACI which applies to the entry
-             in question; if backing-store ACI also exists, the
-             effective policy may be different from that listed in
-             each example.  See section 7 for a discussion of the
-             semantics of ldapACI entries when backing-store ACI
-             administration is also used.
+  3.  permissions "o" and "w" to each attribute being
+      replaced in object
 
+      If one of these these permissions is not granted to
+      such an attribute then the operation MUST fail.  In
+      this case, if discloseOnError is not granted to the
+      entry then a "no such object" error is returned; if
+      discloseOnError is granted to the entry then
+      "insufficient access" error is returned.
 
 
-          Stokes, Byrne, Blakley   Expires 10 September 2000         [Page 19]
+5.4  Add Operation
 
+Recall that the parameters of the Add operation per RFC2251
+[LDAPv3] Section 4.7 are:
 
+   AddRequest ::= [APPLICATION 8] SEQUENCE {
+        entry           LDAPDN,
+        attributes      AttributeList }
 
 
+   AttributeList ::= SEQUENCE OF SEQUENCE {
+        type    AttributeDescription,
+        vals    SET OF AttributeValue }
 
+Then the permissions required by authzID that need to be
+evaluated are as follows:
 
-          Internet-Draft      Access Control Model       10 March 2000
+      permission "a" to the parent of entry
 
+      The access rights required for the creation of a root
+      entry in the Directory are beyond the scope of this
+      document.  They will be vendor specific.
 
+  1.  permission "m" to the parent of entry for each
+      attribute being added to entry
 
-             Assume cn=jsmith is a member of group cn=G1.  Assume
-             cn=jsmith is a member of group cn=G2.
+If any of these permissions are not granted then the
+operation MUST fail.  In this case if discloseOnError is on
+and the entry to be added does not already exist then
+"insufficient access" is returned.  If it does exist then
+"Entry already exists" is returned.  If discloseOnError is
+off then "No such object" is returned (meaning the parent
+object).
 
-              Example #1
-              dn: o=XYZ, c=US
-              ldapACI: 1.2.3.4#subtree#grant;r;attribute:attr1;
-                         #access-id#cn=jsmith,ou=ABC,o=XYZ,c=US
-              ldapACI: 1.2.3.4#subtree#grant;w;attribute:attr1;
-                         #group#cn=G1,ou=ABC,o=XYZ,c=US
+If they are all granted then the operation MAY proceed.
 
-              What rights does cn=jsmith have to attr1 of o=XYZ,c=US?
-              Read (r) access; access-id is higher precedence than
-              group.
+Note: We require "m" permission to each attribute to prevent
+an entry from aquiring "unintended" rights (via group or
+role membership),  to stop a "rogue" ACI being added that
+would prevent even admins deleting the entry and general
 
 
-              Example #2
-              dn: o=XYZ, c=US
-              ldapACI: 1.2.3.4#subtree#grant;r;attribute:attr2;
-                         #group#cn=G1,ou=ABC,o=XYZ,c=US
-              ldapACI: 1.2.3.4#subtree#grant;w;attribute:attr2;
-                         #group#cn=G2,ou=ABC,o=XYZ,c=US
 
-              What rights does cn=jsmith have to attr2 of o=XYZ,c=US?
-              Read-write (r,w) access; ACI is combined because both
-              dnTypes (group) have same precedence.
+Stokes, et al      Expires 14 January 2001         [Page 22]
+\f
 
 
-              Example #3
-              dn: o=XYZ, c=US
-              ldapACI: 1.2.3.4#subtree#grant;r,w;attribute:attr3;
-                         #group#cn=G1,ou=ABC,o=XYZ,c=US
-              ldapACI: 1.2.3.4#subtree#deny;w;attribute:attr3;
-                         #group#cn=G2,ou=ABC,o=XYZ,c=US
 
-              What rights does cn=jsmith have to attr3 of o=XYZ, c=US?
-              Read access; write is denied (deny has precedence over
-              grant).
 
+Internet-Draft      Access Control Model        14 July 2000
 
-              Example #4
-              dn: o=XYZ, c=US
-              ldapACI: 1.2.3.4#subtree#grant;w;attribute:attr4;
-                         #access-id#cn=jsmith,ou=ABC,o=XYZ,c=US
-              ldapACI: 1.2.3.4#subtree#grant;r;attribute:attr4;
-                         #subtree#ou=ABC,ou=XYZ,c=US
 
 
+consistency with the MODIFY operation.
 
-          Stokes, Byrne, Blakley   Expires 10 September 2000         [Page 20]
+Note: The access rights required for the creation of the
+first entry in the directory are beyond the scope of this
+document.
 
 
+5.5  Delete Operation
 
+Recall that the parameters of the Delete operation per
+RFC2251 [LDAPv3] Section 4.10 are:
 
+    DelRequest ::= [APPLICATION 10] LDAPDN
 
+Then the permissions required by authzID that need to be
+evaluated are as follows:
 
-          Internet-Draft      Access Control Model       10 March 2000
 
+  1.  permission "d" to the entry in the Delete request
 
+If this permission is not granted, then the operation MUST
+fail.  In this case if discloseOnError is on and the entry
+to be deleted exists then "insufficient access" is returned.
+If it does not exist then "No such Object" is returned.  If
+discloseOnError is off then "No such object" is returned
+(meaning the parent object).
 
-              What rights does cn=jsmith have to attr4 of o=XYZ, c=US?
-              Write (w); rights given to an access-id take precedence
-              over those given to a subtree.
+If this permission is granted, then the operation MAY
+proceed.
 
+Note: One could also require the "o" permission to be
+granted to allow the operation to proceed, but customer
+experience has shown that the requirement of the additional
+permission is not useful nor expected, and X.500 requires
+only the "d" permission.
 
 
+5.6  Modify DN Operation
 
-          7.  Operational Semantics of Access Control Operations
+Recall that the parameters of the Modify DN operation per
+RFC2251 [LDAPv3] Section 4.6 are:
 
-             The semantics of access control operations described in
-             this document are defined operationally in terms of
-             "histories".  A history is a sequence of actions (x1, x2,
-             ..., xN).
+   ModifyDNRequest ::= [APPLICATION 12] SEQUENCE {
+        entry           LDAPDN,
+        newrdn          RelativeLDAPDN,
+        deleteoldrdn    BOOLEAN,
+        newSuperior     [0] LDAPDN OPTIONAL }
 
+Then the permissions required by authzID that need to be
+evaluated are as follows:
 
-          7.1  Types of actions
 
-             We consider five types of actions:
 
-                - LDAP Access Control Policy Update actions:
-                  invocations of ldap modify when used to add, delete,
-                  or replace the aci attribute; invocations of ldap
-                  add when used to add an entry with an aci attribute.
-                  A LDAP Access Control Policy Update action may
-                  replace the policy (by completely replacing the aci
-                  attribute with new policy information) or it may
-                  grant or deny specific rights while leaving others
-                  unaffected.
 
-                - LDAP Access Control Policy Query operations:
-                  invocations of ldap search when used to retrieve the
-                  aci attribute; invocations of ldap search with the
-                  getEffectiveRightsRequest control; invocations of
-                  the ldapGetEffectiveRightsRequest extended
-                  operation.
+Stokes, et al      Expires 14 January 2001         [Page 23]
+\f
 
-                - Datastore Access Control Policy Update Actions: any
-                  operation implemented by the server which LDAP is
-                  using as its datastore which changes the access
-                  policy enforced with respect to attempts to access
-                  LDAP directory entries and their attributes.
 
-                - LDAP Access Request operations: invocations of LDAP
-                  entry or attribute access operations (Read, Update,
-                  Search, Compare, etc...).
 
 
+Internet-Draft      Access Control Model        14 July 2000
 
-          Stokes, Byrne, Blakley   Expires 10 September 2000         [Page 21]
 
 
+  1.  If newSuperior is not present (ie. only the RDN is
+      being renamed) then permission "n" to entry is
+      required.
 
+  2.  If newSuperior is present then permission "e" to entry
+      and permission "i" to newSuperior are required.
 
+If any of these permissions are not granted then the
+operation MUST fail.  In this case, if discloseOnError is on
+then an "insufficient access error" is returned.  Otherwise,
+"No  such object" is returned.
 
+If they are all granted then the operation MAY proceed.
 
-          Internet-Draft      Access Control Model       10 March 2000
+Note A: We do not require any additional permissions in the
+case where deleteoldrdn is TRUE.
 
+Note B: These permissions allow the naming attribute of an
+entry (or entries) to be changed even though "o" and "w"
+permissions are not available on the entry.  Distinguishing
+the permissions like this allows us to grant permissions for
+the ModifyDN operation, but not the Modify operation and
+vice versa.
 
 
-                - Other operations: anything else, including Datastore
-                  operations which do not change the access policy
-                  enforced by the server.
+5.7  Compare Operation
 
+Recall that the parameters of the Compare operation per
+RFC2251 [LDAPv3] Section 4.10 are:
 
-          7.2  Semantics of Histories
+   CompareRequest ::= [APPLICATION 14] SEQUENCE {
+        entry           LDAPDN,
+        ava             AttributeValueAssertion }
 
-             The semantics of histories are defined as follows:
+Then the permissions required by authzID that need to be
+evaluated are as follows:
 
-                - LDAP Update (Replace), LDAP Query
 
-                  The Query will show that the subject has all rights
-                  granted by the Update operation, and no rights not
-                  granted by the Update operation.
+  1.  permission "c" to the attribute in entry on which the
+      comparison is being made.
 
-                - LDAP Update (Grant), LDAP Query
+If any of these permissions are not granted then the
+operation MUST fail.  In this case, if discloseOnError is on
+then an "insufficient access error" is returned.  Otherwise,
+"No  such object" is returned.
 
-                  The Query will show that the subject has all rights
-                  granted by the Update operation.  The Query may show
-                  that the subject also has other rights not granted
-                  by the Update operation, depending on the policy in
-                  force before the Update operation.
+If they are all granted then the operation MAY proceed.
 
-                - LDAP Update (Deny), LDAP Query
 
-                  The Query will show that the subject does not have
-                  any right denied by the Update operation.  The Query
-                  may show that the subject has rights not denied by
-                  the Update operation, depending on the policy in
-                  force before the Update operation.
 
-                - LDAP Update (Replace), LDAP Access Request
 
-                  The Request will succeed if it requires only rights
-                  granted to the requesting subject by the Update
-                  operation.  The Request will fail if it requires any
-                  right not granted by the Update operation.
 
-                - LDAP Update (Grant), LDAP Access Request
 
-                  The Request will succeed if it requires only rights
-                  granted to the requesting subject by the Update
-                  operation.  The Request may succeed if it requires
-                  rights not granted by the Update operation,
-                  depending on the policy in force before the Update
 
+Stokes, et al      Expires 14 January 2001         [Page 24]
+\f
 
 
-          Stokes, Byrne, Blakley   Expires 10 September 2000         [Page 22]
 
 
+Internet-Draft      Access Control Model        14 July 2000
 
 
 
+5.8  Abandon Operation
 
-          Internet-Draft      Access Control Model       10 March 2000
+Recall that the parameters of the Abandon operation per
+RFC2251 [LDAPv3] Section 4.6 are:
 
+   AbandonRequest ::= [APPLICATION 16] MessageID
 
+authzID always has the right to send an Abandon Operation
+for an operation he previously initiated.
 
-                  operation.
 
-                - LDAP Update (Deny), LDAP Access Request
+5.9  Extended Operation
 
-                  The Request will fail if it requires any right
-                  denied to the requesting subject by the Update
-                  operation.  If the Request requires only rights
-                  which were not denied by the Update operation, it
-                  may succeed, depending on the policy in force before
-                  the Update operation.
+Recall that the parameters of the Extended operation per
+RFC2251 [LDA{v3] Section 4.12 are:
 
-                - LDAP Update (Replace), Other, LDAP Query
+   ExtendedRequest ::= [APPLICATION 23] SEQUENCE {
+        requestName      [0] LDAPOID,
+        requestValue     [1] OCTET STRING OPTIONAL }
 
-                  The Query will show that the subject has all rights
-                  granted by the Update operation, and no rights not
-                  granted by the Update operation.
+The access required for an Extended Operation is beyond the
+scope of this document.  The required access will normally
+be defined by the implementor of the extended request.
 
-                - LDAP Update (Grant), Other, LDAP Query
 
-                  The Query will show that the subject has all rights
-                  granted by the Update operation.  The Query may show
-                  that the subject also has other rights not granted
-                  by the Update operation, depending on the policy in
-                  force before the Update operation.
 
-                - LDAP Update (Deny), Other, LDAP Query
+6.  Required Permissions for Handling Aliases and References
 
-                  The Query will show that the subject does not have
-                  any right denied by the Update operation.  The Query
-                  may show that the subject has rights not denied by
-                  the Update operation, depending on the policy in
-                  force before the Update operation.
 
-                - LDAP Update (Replace), Other, LDAP Access Request
+Use of aliases and referrals are part of LDAPv3.  However,
+neither is particularly well-defined.  Alias
+objects/attributes are defined in RFC 2256 as derived from
+X.500, but LDAPv3 does not explicitly define its semantics
+or behavior.  X.500 does define alias semantics and behavior
+with respect to access control; we define its behavior in
+LDAPv3 based on the X.511, section 7.11.1.  Referrals and
+knowledge information are still under design in LDAPv3; they
+are defined in X.500, however, X.500 punts on their
+semantics and behavior with respect to access control.  We
+define their semantics and behavior in LDAPv3 in terms that
+should be independent of the future LDAPv3 definition of
+referrals and knowledge information.
 
-                  The Request will succeed if it requires only rights
-                  granted to the requesting subject by the Update
-                  operation.  The Request will fail if it requires any
-                  right not granted by the Update operation.
 
-                - LDAP Update (Grant), Other, LDAP Access Request
+6.1  ACI Distribution
 
-                  The Request will succeed if it requires only rights
-                  granted to the requesting subject by the Update
-                  operation.  The Request may succeed if it requires
+Currently there is no LDAP standard defining how to
+distribute directory data between LDAP servers. Consequently
+this draft cannot fully specify the behavior of the Access
+Control Model in a distributed environment. The case of
+distribution via referrals is treated in the "Referrals"
 
 
 
-          Stokes, Byrne, Blakley   Expires 10 September 2000         [Page 23]
+Stokes, et al      Expires 14 January 2001         [Page 25]
+\f
 
 
 
 
+Internet-Draft      Access Control Model        14 July 2000
 
 
-          Internet-Draft      Access Control Model       10 March 2000
 
+section below. In the case of chaining (where one LDAP
+server forwards a request to another on behalf of a client)
+then it is server specific how the access control model
+behaves in this environment. Similarly it is server specific
+how the server determines whether the chaining of an
+operation is permitted in the first place. For example, the
+implementation may choose to regard the local naming context
+and the remote subordinate naming context as seperate Access
+Control Specific Areas, or it may regard the DIT as one
+Access Control Specific Area and implement mechanisms to
+propagate access control information between the two
+servers. The behavior of the Access Control Model in
+distributed environments such as these is beyond the scope
+of this draft.
 
 
-                  rights not granted by the Update operation,
-                  depending on the policy in force before the Update
-                  operation.
+6.2  Aliases
 
-                - LDAP Update (Deny), Other, LDAP Access Request
+There are two things to protect with respect to aliases:
+the real name of the aliased object and the location of the
+server holding it.
 
-                  The Request will fail if it requires any right
-                  denied to the requesting subject by the Update
-                  operation.  If the Request requires only rights
-                  which were not denied by the Update operation, it
-                  may succeed, depending on the policy in force before
-                  the Update operation.
+If alias de-referencing is required in the process of
+locating a target entry, no specifc permissions are
+necessary for alias de-referencing to take place. Access
+control is enforced at the object pointed to by the alias.
 
-                - LDAP Update (Replace), Datastore Policy Update, LDAP
-                  Query
+If alias de-referencing would result in a
+continuationReference (e.g. from a search operation), then
+browse permission is required to the alias entry and read
+permission is required to the 'aliasedObjectName' attribute.
+Requiring these permission closes the hole of discovery.
 
-                  The result of the Query is not defined.
 
-                - LDAP Update (Grant), Datastore Policy Update, LDAP
-                  Query
+6.3  Referrals
 
-                  The result of the Query is not defined.
+If a referral is to be followed, no specifc permissions are
+necessary for the ldap client to follow the referral. Access
+control is enforced at the referenced object.  If a referral
+is returned, then browse is required on the entry and read
+permission is required to the attribute containing the
+referral (we cannot name this attribute exactly today
+because there are no RFCs on this - only drafts). If the
+server implements a default referral, then no special
+permissions are required to read and return that referral.
+Requiring these permissions closes the hole of discovery.
+In the default case, it is assumed that a default referral
+is public.
 
-                - LDAP Update (Deny), Datastore Policy Update, LDAP
-                  Query
 
-                  The result of the Query is not defined.
 
-                - LDAP Update (Replace), Datastore Policy Update, LDAP
-                  Access Request
 
-                  The result of the Access Request is not defined.
 
-                - LDAP Update (Grant), Datastore Policy Update, LDAP
-                  Access Request
 
-                  The result of the Access Request is not defined.
+Stokes, et al      Expires 14 January 2001         [Page 26]
+\f
 
-                - LDAP Update (Deny), Datastore Policy Update, LDAP
-                  Access Request
 
-                  The result of the Access Request is not defined.
 
 
+Internet-Draft      Access Control Model        14 July 2000
 
 
 
+7.  Controlling Access to Access Control Information
 
-          Stokes, Byrne, Blakley   Expires 10 September 2000         [Page 24]
+The ldapACI attribute is used to specify control for who has
+permission to set/change access control information
+(ldapACI).  The ldapACI attribute/OID is just another
+attribute described with a scope, set of rights and
+permissions, and subject as a value of the ldapACI
+attribute.  (See the example in the "ACI Examples" section).
 
+If the policy for controlling the ldapACI attribute is not
+specified for any object in the tree, behavior is
+implementation defined. For instance, if no object anywhere
+in the tree defines the access for ldapACI within the
+ldapACI attribute, then the server could simply assert that
+the 'root DN' is considered the policy owner (controller for
+controlling access control) for all objects.
 
 
 
+8.  ACI Examples
 
+Note that in the examples, the form "OID.<attrname>" refers
+to the OID in dotted decimal form for the attribute
+<attrname>.  This shorthand notation is used only for the
+examples.  In implementation, the dotted decimal form of the
+OID is used.
 
-          Internet-Draft      Access Control Model       10 March 2000
 
+8.1  Attribute Definition
 
+The following examples show the access required to control
+access to the ldapACI attribute.  The first example shows
+controlling the access control on an individual entry and
+its attributes.  The second example shows controlling the
+access control on a subtree.
 
-          8.  Access Control Parameters for LDAP Controls & Extended
-          Operations
+ ldapACI: entry#grant:r,w#
+    OID.ldapACI#authnLevel:any:role:cn=aciAdmin
 
-             This section defines the parameters used in the access
-             control LDAP controls and extended operations in this
-             document.
+ ldapACI: subtree#grant:r,w#
+    OID.ldapACI#authnLevel:any:role:cn=aciAdmin
 
-             targetDN specifies the initial directory entry in DN
-             syntax on which the control or extended operation is
-             performed.
+The next example shows a ldapACI attribute where a group
+"cn=Dept XYZ, c=US" is being given permissions to read,
+search, and compare attribute attr1. The permission applies
+to the entire subtree below the node containing this ACI.
+Authentication of a specified type is not required.
 
-             whichObject specifies whether the access control
-             information (in the get effective rights control) which
-             is retrieved is for the target directory entry (ENTRY) or
-             the target directory entry and its subtree (SUBTREE).
+ ldapACI:subtree#grant;r,s,c#
+      OID.attr1#group:cn=Dept XYZ,c=US
 
-             family specifies the family OID that will be retrieved
-             for the get effective rights control or extended
-             operation performed.  A family has a defined set of
-             rights, among other things.
 
-             rights in the get effective rights control or extended
-             operation response is of the form specified in the BNF
-             for <rights>.
 
-             dnType speficies the type of subject security attribute.
-             Defined types are specified in the BNF.
 
-             subjectDN is a LDAP string that defines the subject or
-             value of the dnType.  The subjectDN may be a DN or
-             another string such as IPAddress (dotted-decimal string
-             representation) on which access control is get/set.  If
-             the subject is an entry in the directory, then the syntax
-             of the LDAP string is DN.  The well-known subjectDNs
-             strings are defined
+Stokes, et al      Expires 14 January 2001         [Page 27]
+\f
 
-                - public - meaning public access for all users
 
-                - this - meaning the user whose name matches the entry
-                  being accessed
 
-                - *  - meaning everyone who has access to the entry
 
+Internet-Draft      Access Control Model        14 July 2000
 
 
 
+The next example shows an ACI attribute where a role
+"cn=SysAdmins,o=Company" is being given permissions to add
+objects below this node and read, search, and compare
+attributes attr2 and attr3. The permission applies to the
+entire subtree below the node containing this ACI.
 
+ ldapACI: subtree#grant:a#
+            [entry]#role:cn=SysAdmins,o=Company
 
-          Stokes, Byrne, Blakley   Expires 10 September 2000         [Page 25]
+ ldapACI: subtree#grant:r,s,c#
+            OID.attr2#role:cn=SysAdmins,o=Company
 
+ ldapACI: subtree#grant:r,s,c#
+            OID.attr3#role:cn=SysAdmins,o=Company
 
 
+8.2  Modifying the ldapACI Values
 
+Modify-Replace works as defined in the ldap operation
+modify. If the attribute value does not exist, create the
+value. If the attribute does exist, replace the value.  If
+the ldapACI value is replaced, all ldapACI values are
+replaced.
 
+A given ldapACI for an entry:
 
-          Internet-Draft      Access Control Model       10 March 2000
+ ldapACI: subtree#deny:r,w#[all]#group:cn=Dept ABC
 
+ ldapACI: subtree#grant:r#OID.attr1#group:cn=Dept XYZ
 
+perform the following change:
 
-          9.  Access Control Information (ACI) Controls
+  dn: cn=someEntry
+  changetype: modify
+  replace: ldapACI
+  ldapACI: subtree#grant:r,w#[all]#group:cn=Dept LMN
 
-             The access control information controls provide a way to
-             manipulate access control information in conjunction with
-             a LDAP operation.  One LDAP control is defined.  This
-             control allows access control information to be get/set
-             while manipulating other directory information for that
-             entry.  The control is:
+The resulting ACI is:
 
-                - getEffectiveRights to obtain the effective rights
-                  for a given directory entry(s) for a given subject
-                  during a ldap_search operation
+ldapACI: subtree#grant:r,w#[all]#group:cn=Dept LMN
 
-          9.1  getEffectiveRights Control
+( ldapACI values for Dept XYZ and ABC are lost through the
+replace )
 
+During an ldapmodify-add, if the ACI does not exist, the
+create the ACI with the specific ldapACI value(s).  If the
+ACI does exist, then add the specified values to the given
+ldapACI.  For example a given ACI:
 
-          9.1.1  Request Control
+ldapACI: subtree#grant:r,w#[all]#group:cn=Dept XYZ
 
-             This control may only be included in the ldap_search
-             message as  part of the controls  field  of the
-             LDAPMessage, as  defined in  Section  4.1.12 of [LDAPv3].
 
-             The controlType is set to <OID to be assigned>. The
-             criticality MAY be either TRUE or FALSE (where absent is
-             also equivalent to FALSE) at the client's option.  The
-             controlValue is an OCTET STRING, whose value is the BER
-             encoding of a value of the following SEQUENCE:
 
-              getEffectiveRightsRequest ::= SEQUENCE {
-                effectiveRightsRequest   SEQUENCE OF SEQUENCE {
-                    family        LDAPOID | "*",
-                    whichObject   ENUMERATED {
-                                  LDAP_ENTRY (1),
-                                  LDAP_SUBTREE (2)
-                                  },
-                    dnType        "access-id"|"group"|"role"|
-                                    "ipAddress"|"kerberosID"|
-                                    <printableString> | "*",
-                    subjectDN     LDAPString | "public" |
-                                    "this" |  "*"
-                    }
-              }
 
-             The effectiveRightsRequest is a set of sequences that
-             state the whichObject (entry or entry plus subtree) and
+Stokes, et al      Expires 14 January 2001         [Page 28]
+\f
+
+
+
+
+Internet-Draft      Access Control Model        14 July 2000
+
+
+
+with a modification:
+
+  dn: cn=someEntry
+  changetype: modify
+  add: ldapACI
+  ldapACI: subtree#grant:r#OID.attr1#group:cn=Dept XYZ
+
+would yield an multi-valued ACI of:
+
+ ldapACI: subtree#grant:r,w#[all]#group:cn=Dept XYZ
+
+ ldapACI: subtree#grant:r#OID.attr1#group:cn=Dept XYZ
+
+To delete a particular ACI value, use the regular ldapmodify
+- delete syntax
+
+Given an ACI of:
+
+ ldapACI: subtree#grant:r,w#[all]#group:cn=Dept XYZ
+ ldapACI: subtree#grant:r#OID.attr1#group:cn=Dept XYZ
+
+  dn: cn = some Entry
+  changetype: modify
+  delete: ldapACI
+  ldapACI: subtree#grant:r#OID.attr1#group:cn=Dept XYZ
+
+would yield a remaining ACI on the server of
+
+ldapACI: subtree#grant:r,w#[all]#group:cn=Dept XYZ
+
+The attributes which are defined for access control
+interchange may be used in all LDAP operations.
+
+Within the ldapmodify-delete operation, the entire acl may
+be deleted by specifying
+
+ dn: cn = some Entry
+ changetype: modify
+ delete: ldapACI
+
+In this case, the entry would then inherit its ACI from some
+other node in the tree depending on the server inheritance
+model.
+
+Similarly, if all values of ldapACI are deleted, then the
+access control information for that entry is defined by that
+implementation's inheritance model.
+
+
+
+
+
+
+
+Stokes, et al      Expires 14 January 2001         [Page 29]
+\f
+
+
+
+
+Internet-Draft      Access Control Model        14 July 2000
+
+
+
+8.3  Evaluation
+
+These examples assume that the ldapACI entries listed in
+each example are the only ACI which applies to the entry in
+question; if backing-store ACI also exists, the effective
+policy may be different from that listed in each example.
+See section 10 for a discussion of the semantics of ldapACI
+entries when backing-store ACI administration is also used.
+
+Assume cn=jsmith is a member of group cn=G1.  Assume
+cn=jsmith is a member of group cn=G2.
+
+ Example #1
+ dn: o=XYZ, c=US
+ ldapACI: subtree#grant:r#attr1
+            #authzID-dn:cn=jsmith,ou=ABC,o=XYZ,c=US
+ ldapACI: subtree#grant:w#attr1
+            #group:cn=G1,ou=ABC,o=XYZ,c=US
+
+ What rights does cn=jsmith have to attr1 of o=XYZ,c=US?
+ Read (r) access; authzID is higher precedence than
+ group.
+
+
+ Example #2
+ dn: o=XYZ, c=US
+ ldapACI: subtree#grant:r#attr2
+            #group:cn=G1,ou=ABC,o=XYZ,c=US
+ ldapACI: subtree#grant:w#attr2
+            #group:cn=G2,ou=ABC,o=XYZ,c=US
+
+ What rights does cn=jsmith have to attr2 of o=XYZ,c=US?
+ Read-write (r,w) access; ACI is combined because both
+ subjects (group) have same precedence.
+
+
+ Example #3
+ dn: o=XYZ, c=US
+ ldapACI: subtree#grant:r,w#attr3
+            #group:cn=G1,ou=ABC,o=XYZ,c=US
+ ldapACI: subtree#deny:w#attr3#group:cn=G2,ou=ABC,o=XYZ,c=US
+
+ What rights does cn=jsmith have to attr3 of o=XYZ, c=US?
+ Read access; write is denied (deny has precedence over
+ grant).
+
+
+ Example #4
+ dn: o=XYZ, c=US
+ ldapACI: subtree#grant:w#attr4
+            #authzID-dn:cn=jsmith,ou=ABC,o=XYZ,c=US
+
+
+
+Stokes, et al      Expires 14 January 2001         [Page 30]
+\f
+
+
+
+
+Internet-Draft      Access Control Model        14 July 2000
+
+
+
+ ldapACI: subtree#grant:r#attr4#subtree:ou=ABC,ou=XYZ,c=US
+
+ What rights does cn=jsmith have to attr4 of o=XYZ, c=US?
+ Write (w); rights given to an authzID take precedence
+ over those given to a subtree.
+
+
+ Example #5
+ dn: o=XYZ, c=US
+ ldapACI: subtree#grant:m#OID.attr5
+            #authzID-dn:cn=jsmith,o=ABC,c=US
+ ldapACI: subtree#grant:m#OID.cn
+            #authzID-dn:cn=jsmith,o=ABC,c=US
+ ldapACI: subtree#grant:m#OID.sn
+            #authzID-dn:cn=jsmith,o=ABC,c=US
+ ldapACI: subtree#grant:a#[entry]
+            #authzID-dn:#cn=jsmith,o=ABC,c=US
+
+ What rights does cn=jsmith have to o=XYZ, c=US?
+ Make(m) on attributes attr5, cn, and sn and Add(a)
+ on the entry.  These are the minimal yet sufficient
+ permissions to create a new object,
+ cn=New, o=XYZ, c=US with values for the attr5, cn,
+ and sn attributes.  This example illustrates how the
+ "m" permission can be used to limit the attributes
+ that can be created on a new entry.
+
+ Example #6
+ dn: c=US
+ ldapACI: subtree#grant:m#[all]#subtree:c=US
+ dn: o=XYZ, c=US
+ ldapACI: subtree#grant:a#[entry]#
+            authzID-dn:cn=jsmith,o=ABC,c=US
+
+ What rights does cn=jsmith have to o=XYZ, c=US?
+ Make(m) on attributes all attributes and Add(a) on the
+ entry. These are sufficient permissions to create a new
+ object, cn=New, o=XYZ, c=US with values any desired
+ attributes.  For administrators who do not wish to limit
+ the attributes that can be created on new entries, this
+ example shows how a single ldapACI at the top of the
+ domain solves the problem.
+
+
+
+9.  Operational Semantics of Access Control Operations
+
+The semantics of access control operations described in this
+document are defined operationally in terms of "histories".
+A history is a sequence of actions (x1, x2, ..., xN).
+
+
+
+
+Stokes, et al      Expires 14 January 2001         [Page 31]
+\f
+
+
+
+
+Internet-Draft      Access Control Model        14 July 2000
+
+
+
+9.1  Types of actions
+
+We consider five types of actions:
+
+   - LDAP Access Control Policy Update actions: invocations
+     of ldap modify when used to add, delete, or replace the
+     aci attribute; invocations of ldap add when used to add
+     an entry with an aci attribute.  A LDAP Access Control
+     Policy Update action may replace the policy (by
+     completely replacing the aci attribute with new policy
+     information) or it may grant or deny specific rights
+     while leaving others unaffected.
+
+   - LDAP Access Control Policy Query operations:
+     invocations of ldap search when used to retrieve the
+     aci attribute; invocations of ldap search with the
+     getEffectiveRightsRequest control; invocations of the
+     ldapGetEffectiveRightsRequest extended operation.
+
+   - Datastore Access Control Policy Update Actions: any
+     operation implemented by the server which LDAP is using
+     as its datastore which changes the access policy
+     enforced with respect to attempts to access LDAP
+     directory entries and their attributes.
+
+   - LDAP Access Request operations: invocations of LDAP
+     entry or attribute access operations (Read, Update,
+     Search, Compare, etc...).
+
+   - Other operations: anything else, including Datastore
+     operations which do not change the access policy
+     enforced by the server.
+
+
+9.2  Semantics of Histories
+
+The semantics of histories are defined as follows:
+
+   - LDAP Update (Replace), LDAP Query
+
+     The Query will show that the subject has all rights
+     granted by the Update operation, and no rights not
+     granted by the Update operation.
+
+   - LDAP Update (Grant), LDAP Query
+
+     The Query will show that the subject has all rights
+     granted by the Update operation.  The Query may show
+     that the subject also has other rights not granted by
+     the Update operation, depending on the policy in force
+     before the Update operation.
+
+
+
+Stokes, et al      Expires 14 January 2001         [Page 32]
+\f
+
 
 
 
-          Stokes, Byrne, Blakley   Expires 10 September 2000         [Page 26]
+Internet-Draft      Access Control Model        14 July 2000
 
 
 
+   - LDAP Update (Deny), LDAP Query
 
+     The Query will show that the subject does not have any
+     right denied by the Update operation.  The Query may
+     show that the subject has rights not denied by the
+     Update operation, depending on the policy in force
+     before the Update operation.
 
+   - LDAP Update (Replace), LDAP Access Request
 
-          Internet-Draft      Access Control Model       10 March 2000
+     The Request will succeed if it requires only rights
+     granted to the requesting subject by the Update
+     operation.  The Request will fail if it requires any
+     right not granted by the Update operation.
 
+   - LDAP Update (Grant), LDAP Access Request
 
+     The Request will succeed if it requires only rights
+     granted to the requesting subject by the Update
+     operation.  The Request may succeed if it requires
+     rights not granted by the Update operation, depending
+     on the policy in force before the Update operation.
 
-             specifics of the control request to be performed.  One or
-             more family can be be obtained for a given subjectDN ad
-             dnType.  A "*" in the family field indicates that the
-             rights for all families defined for the subjectDN /
-             dnType are to be returned.  A "*" in the dnType field
-             specifies that all DN types are to be used in returning
-             the effective rights.  This control is applied to the
-             filter and scope set by the ldap_search operation, i.e.
-             base, one-level, subtree.  So the attributes/values
-             returned are defined by the ldap_search operation.
+   - LDAP Update (Deny), LDAP Access Request
 
-          9.1.2  Response Control
+     The Request will fail if it requires any right denied
+     to the requesting subject by the Update operation.  If
+     the Request requires only rights which were not denied
+     by the Update operation, it may succeed, depending on
+     the policy in force before the Update operation.
 
-             This control is included in the ldap_search_response
-             message as part of the controls field of the LDAPMessage,
-             as defined in Section 4.1.12 of [LDAPv3].
+   - LDAP Update (Replace), Other, LDAP Query
 
-             The controlType is set to <OID to be assigned>. There is
-             no need to set the criticality on the response.  The
-             controlValue is an OCTET STRING, whose value is the BER
-             encoding of a value of the following SEQUENCE:
+     The Query will show that the subject has all rights
+     granted by the Update operation, and no rights not
+     granted by the Update operation.
 
-              getEffectiveRightsResponse ::= {
-                result  ENUMERATED {
-                   success                       (0),
-                   operationsError               (1),
-                   unavailableCriticalExtension (12),
-                   noSuchAttribute              (16),
-                   undefinedAttributeType       (17),
-                   invalidAttributeSyntax       (21),
-                   insufficientRights           (50),
-                   unavailable                  (52),
-                   unwillingToPerform           (53),
-                   other                        (80)
-                   }
-              }
+   - LDAP Update (Grant), Other, LDAP Query
 
-             The effective rights returned are returned with each
-             entry returned by the search result.  The control
-             response for ldap_search is:
+     The Query will show that the subject has all rights
+     granted by the Update operation.  The Query may show
+     that the subject also has other rights not granted by
+     the Update operation, depending on the policy in force
+     before the Update operation.
 
-              PartialEffectiveRightsList ::= SEQUENCE OF SEQUENCE {
-                 family        LDAPOID,
-                 rights        <see <rights> in BNF>,
-                 whichObject   ENUMERATED {
+   - LDAP Update (Deny), Other, LDAP Query
 
+     The Query will show that the subject does not have any
+     right denied by the Update operation.  The Query may
+     show that the subject has rights not denied by the
+     Update operation, depending on the policy in force
 
 
-          Stokes, Byrne, Blakley   Expires 10 September 2000         [Page 27]
 
+Stokes, et al      Expires 14 January 2001         [Page 33]
+\f
 
 
 
 
+Internet-Draft      Access Control Model        14 July 2000
 
-          Internet-Draft      Access Control Model       10 March 2000
 
 
+     before the Update operation.
 
-                                   LDAP_ENTRY (1),
-                                   LDAP_SUBTREE (2)
-                                   },
-                 dnType        "access-id"|"group"|
-                                "role"|"ipAddress"|
-                                "kerberosID"|
-                                <printableString> |
-                                "*",
-                 subjectDN     LDAPString | "public" |
-                                    "this" | "*"
-              }
+   - LDAP Update (Replace), Other, LDAP Access Request
 
-             Although this extends the search operation, there are no
-             incompatibilities between versions.  LDAPv2 cannot send a
-             control, hence the above structure cannot be returned to
-             a LDAPv2 client.  A LDAPv3 client cannot send this
-             request to a LDAPv2 server.  A LDAPv3 server not
-             supporting this control cannot return the additional
-             data.
+     The Request will succeed if it requires only rights
+     granted to the requesting subject by the Update
+     operation.  The Request will fail if it requires any
+     right not granted by the Update operation.
 
-          9.1.3  Client-Server Interaction
+   - LDAP Update (Grant), Other, LDAP Access Request
 
-             The getEffectiveRightsRequest control requests the rights
-             that MUST be in effect for requested directory
-             entry/attribute based on the subject DN.  The server that
-             consumes the search operation looks up the rights for the
-             returned directory information based on the subject DN
-             and returns that rights information.
+     The Request will succeed if it requires only rights
+     granted to the requesting subject by the Update
+     operation.  The Request may succeed if it requires
+     rights not granted by the Update operation, depending
+     on the policy in force before the Update operation.
 
-             There are six possible scenarios that may occur as a
-             result of the getEffectiveRights control being included
-             on the search request:
+   - LDAP Update (Deny), Other, LDAP Access Request
 
+     The Request will fail if it requires any right denied
+     to the requesting subject by the Update operation.  If
+     the Request requires only rights which were not denied
+     by the Update operation, it may succeed, depending on
+     the policy in force before the Update operation.
 
-               1.  If the server does not support this control and the
-                   client specified TRUE for the control's criticality
-                   field, then the server MUST return
-                   unavailableCriticalExtension as a return code in
-                   the searchResponse message and not send back any
-                   other results.  This behavior is specified in
-                   section 4.1.12 of [LDAPv3].
+   - LDAP Update (Replace), Datastore Policy Update, LDAP
+     Query
 
-               2.  If the server does not support this control and the
-                   client specified FALSE for the control's
-                   criticality field, then the server MUST ignore the
+     The result of the Query is not defined.
 
+   - LDAP Update (Grant), Datastore Policy Update, LDAP
+     Query
 
+     The result of the Query is not defined.
 
-          Stokes, Byrne, Blakley   Expires 10 September 2000         [Page 28]
+   - LDAP Update (Deny), Datastore Policy Update, LDAP Query
 
+     The result of the Query is not defined.
 
+   - LDAP Update (Replace), Datastore Policy Update, LDAP
+     Access Request
 
+     The result of the Access Request is not defined.
 
+   - LDAP Update (Grant), Datastore Policy Update, LDAP
+     Access Request
 
+     The result of the Access Request is not defined.
 
-          Internet-Draft      Access Control Model       10 March 2000
+   - LDAP Update (Deny), Datastore Policy Update, LDAP
+     Access Request
 
 
 
-                   control and process the request as if it were not
-                   present.  This behavior is specified in section
-                   4.1.12 of [LDAPv3].
+Stokes, et al      Expires 14 January 2001         [Page 34]
+\f
 
-               3.  If the server supports this control but for some
-                   reason such as cannot process specified family and
-                   the client specified TRUE for the control's
-                   criticality field, then the server SHOULD do the
-                   following: return unavailableCriticalExtension as a
-                   return code in the searchResult message.
 
-               4.  If the server supports this control but for some
-                   reason such as cannot process specified family and
-                   the client specified FALSE for the control's
-                   criticality field, then the server should process
-                   as 'no rights returned for that family' and include
-                   the result Unavailable in the
-                   getEffectiveRightsResponse control in the
-                   searchResult message.
 
-               5.  If the server supports this control and can return
-                   the rights per the family information, then it
-                   should include the getEffectiveRightsResponse
-                   control in the searchResult message with a result
-                   of success.
 
-               6.  If the search request failed for any other reason,
-                   then the server SHOULD omit the
-                   getEffectiveRightsResponse control from the
-                   searchResult message.
+Internet-Draft      Access Control Model        14 July 2000
 
-             The client application is assured that the correct rights
-             are returned for scope of the search operation if and
-             only if the getEffectiveRightsResponse control returns
-             the rights.  If the server omits the
-             getEffectiveRightsResponse control from the searchResult
-             message, the client SHOULD assume that the control was
-             ignored by the server.
 
-             The getEffectiveRightsResponse control, if included by
-             the server in the searchResponse message, should have the
-             getEffectiveRightsResult set to either success if the
-             rights are returned or set to the appropriate error code
-             as to why the rights could not be returned.
 
+     The result of the Access Request is not defined.
 
 
 
-          Stokes, Byrne, Blakley   Expires 10 September 2000         [Page 29]
+10.  Access Control Parameters for LDAP Controls & Extended
+Operations
 
+This section defines the parameters used in the access
+control LDAP controls and extended operations in this
+document.
 
+targetDN specifies the initial directory entry in DN syntax
+on which the control or extended operation is performed.
 
+whichObject specifies whether the access control information
+(in the get effective rights control) which is retrieved is
+for the target directory entry (ENTRY) or the target
+directory entry and its subtree (SUBTREE).
 
+rights in the get effective rights control or extended
+operation response is of the form specified in the BNF for
+<rights>.
 
+subject is a LDAP string that defines the subject.  Access
+control is get/set on a subject.  The syntax of the subject
+is the same as the subject field in the BNF.
 
-          Internet-Draft      Access Control Model       10 March 2000
 
 
+11.  Access Control Information (ACI) Controls
 
-             The server may not be able to return a right because it
-             may not exist in that directory object's attribute; in
-             this case, the rights request is ignored with success.
+The access control information controls provide a way to
+manipulate access control information in conjunction with a
+LDAP operation.  One LDAP control is defined.  This control
+allows access control information to be retrieved while
+manipulating other directory information for that entry.
+The control is:
 
+   - getEffectiveRights to obtain the effective rights for a
+     given directory entry(s) for a given subject during a
+     ldap_search operation
 
-          10.  Access Control Extended Operation
+11.1  getEffectiveRights Control
 
-             An extended operation, get effective rights, is defined
-             to obtain the effective rights for a given directory
-             entry for a given subject.  This operation may help with
-             the management of access control information independent
-             of manipulating other directory information.
 
+11.1.1  Request Control
 
-          10.1  LDAP Get Effective Rights Operation
+This control may only be included in the ldap_search
+message as  part of the controls  field  of the
+LDAPMessage, as  defined in  Section  4.1.12 of [LDAPv3].
 
-             ldapGetEffectiveRightsRequest ::= [APPLICATION 23]
-             SEQUENCE {
-                requestName      [0] <OID to be assigned>,
-                requestValue     [1] OCTET STRING OPTIONAL }
 
-                where
 
-                requestValue ::= SEQUENCE {
-                   targetDN  LDAPDN,
-                   updates   SEQUENCE OF SEQUENCE {
-                               family        LDAPOID | "*",
-                               whichObject   ENUMERATED {
-                                               LDAP_ENTRY (1),
-                                               LDAP_SUBTREE (2)
-                                               },
-                               attr SEQUENCE {
-                                  attr   <see <attr> in BNF >
+
+Stokes, et al      Expires 14 January 2001         [Page 35]
+\f
+
+
+
+
+Internet-Draft      Access Control Model        14 July 2000
+
+
+
+The controlType is set to <OID to be assigned>. The
+criticality MAY be either TRUE or FALSE (where absent is
+also equivalent to FALSE) at the client's option.  The
+controlValue is an OCTET STRING, whose value is the BER
+encoding of a value of the following SEQUENCE:
+
+ getEffectiveRightsRequest ::= SEQUENCE {
+   effectiveRightsRequest   SEQUENCE OF SEQUENCE {
+       whichObject   ENUMERATED {
+                     LDAP_ENTRY (1),
+                     LDAP_SUBTREE (2)
+                     },
+       subject       <see <subject > in BNF> | "*"
+       }
+ }
+
+The effectiveRightsRequest is a set of sequences that state
+the whichObject (entry or entry plus subtree) and specifics
+of the control request to be performed. A "*" in the subject
+field specifies that all DN types are to be used in
+returning the effective rights.  This control is applied to
+the filter and scope set by the ldap_search operation, i.e.
+base, one-level, subtree.  So the attributes/values returned
+are defined by the ldap_search operation.
+
+11.1.2  Response Control
+
+This control is included in the ldap_search_response message
+as part of the controls field of the LDAPMessage, as defined
+in Section 4.1.12 of [LDAPv3].
+
+The controlType is set to <OID to be assigned>. There is no
+need to set the criticality on the response.  The
+controlValue is an OCTET STRING, whose value is the BER
+encoding of a value of the following SEQUENCE:
+
+ getEffectiveRightsResponse ::= {
+   result  ENUMERATED {
+      success                       (0),
+      operationsError               (1),
+      unavailableCriticalExtension (12),
+      noSuchAttribute              (16),
+      undefinedAttributeType       (17),
+      invalidAttributeSyntax       (21),
+      insufficientRights           (50),
+      unavailable                  (52),
+      unwillingToPerform           (53),
+      other                        (80)
+      }
+ }
+
+
+
+
+Stokes, et al      Expires 14 January 2001         [Page 36]
+\f
+
+
+
+
+Internet-Draft      Access Control Model        14 July 2000
+
+
+
+The effective rights returned are returned with each entry
+returned by the search result.  The control response for
+ldap_search is:
+
+ PartialEffectiveRightsList ::= SEQUENCE OF SEQUENCE {
+    rights        <see <rights> in BNF>,
+    whichObject   ENUMERATED {
+                      LDAP_ENTRY (1),
+                      LDAP_SUBTREE (2)
+                      },
+    subject       < see <subject> in BNF >
+ }
+
+Although this extends the search operation, there are no
+incompatibilities between versions.  LDAPv2 cannot send a
+control, hence the above structure cannot be returned to a
+LDAPv2 client.  A LDAPv3 client cannot send this request to
+a LDAPv2 server.  A LDAPv3 server not supporting this
+control cannot return the additional data.
+
+11.1.3  Client-Server Interaction
+
+The getEffectiveRightsRequest control requests the rights
+that MUST be in effect for requested directory
+entry/attribute based on the subject DN.  The server that
+consumes the search operation looks up the rights for the
+returned directory information based on the subject DN and
+returns that rights information.
+
+There are six possible scenarios that may occur as a result
+of the getEffectiveRights control being included on the
+search request:
+
+
+  1.  If the server does not support this control and the
+      client specified TRUE for the control's criticality
+      field, then the server MUST return
+      unavailableCriticalExtension as a return code in the
+      searchResponse message and not send back any other
+      results.  This behavior is specified in section 4.1.12
+      of [LDAPv3].
+
+  2.  If the server does not support this control and the
+      client specified FALSE for the control's criticality
+      field, then the server MUST ignore the control and
+      process the request as if it were not present.  This
+      behavior is specified in section 4.1.12 of [LDAPv3].
+
+  3.  If the server supports this control but for some
+      reason such as cannot process specified family and the
+      client specified TRUE for the control's criticality
+
+
+
+Stokes, et al      Expires 14 January 2001         [Page 37]
+\f
+
+
+
+
+Internet-Draft      Access Control Model        14 July 2000
+
+
+
+      field, then the server SHOULD do the following: return
+      unavailableCriticalExtension as a return code in the
+      searchResult message.
+
+  4.  If the server supports this control but for some
+      reason such as cannot process specified family and the
+      client specified FALSE for the control's criticality
+      field, then the server should process as 'no rights
+      returned for that family' and include the result
+      Unavailable in the getEffectiveRightsResponse control
+      in the searchResult message.
+
+  5.  If the server supports this control and can return the
+      rights per the family information, then it should
+      include the getEffectiveRightsResponse control in the
+      searchResult message with a result of success.
+
+  6.  If the search request failed for any other reason,
+      then the server SHOULD omit the
+      getEffectiveRightsResponse control from the
+      searchResult message.
+
+The client application is assured that the correct rights
+are returned for scope of the search operation if and only
+if the getEffectiveRightsResponse control returns the
+rights.  If the server omits the getEffectiveRightsResponse
+control from the searchResult message, the client SHOULD
+assume that the control was ignored by the server.
+
+The getEffectiveRightsResponse control, if included by the
+server in the searchResponse message, should have the
+getEffectiveRightsResult set to either success if the rights
+are returned or set to the appropriate error code as to why
+the rights could not be returned.
+
+The server may not be able to return a right because it may
+not exist in that directory object's attribute; in this
+case, the rights request is ignored with success.
+
+
+12.  Access Control Extended Operation
+
+An extended operation, get effective rights, is defined to
+obtain the effective rights for a given directory entry for
+a given subject.  This operation may help with the
+management of access control information independent of
+manipulating other directory information.
+
+
+
+
+
+
+
+Stokes, et al      Expires 14 January 2001         [Page 38]
+\f
+
+
+
+
+Internet-Draft      Access Control Model        14 July 2000
+
+
+
+12.1  LDAP Get Effective Rights Operation
+
+ldapGetEffectiveRightsRequest ::= [APPLICATION 23] SEQUENCE
+{
+   requestName      [0] <OID to be assigned>,
+   requestValue     [1] OCTET STRING OPTIONAL }
+
+   where
+
+   requestValue ::= SEQUENCE {
+      targetDN  LDAPDN,
+      updates   SEQUENCE OF SEQUENCE {
+                  whichObject   ENUMERATED {
+                                  LDAP_ENTRY (1),
+                                  LDAP_SUBTREE (2)
                                   },
-                               dnType        "access-id"|"group"|
-                                               "role"|"ipAddress"|
-                                               "kerberosID"|
-                                               <printableString> |
-                                               "*",
-                               subjectDN     LDAPString | "public" |
-                                               "this" | "*"
-                               }
-                   }
+                  attr SEQUENCE {
+                     attr   <see <attr> in BNF >
+                     },
+                  subject   < see <subject> in BNF > | "*"
+                  }
+      }
+
+
+The requestName is a dotted-decimal representation of the
+OBJECT IDENTIFIER corresponding to the request. The
+requestValue is information in a form defined by that
+request, encapsulated inside an OCTET STRING.
+
+The server will respond to this with an LDAPMessage
+containing the ExtendedResponse which is a rights list.
+
+ldapGetEffectiveRightsResponse ::= [APPLICATION 24] SEQUENCE
+{
+   COMPONENTS OF LDAPResult,
+   responseName     [10] <OID to be assigned> OPTIONAL,
+   effectiveRights  [11] OCTET STRING OPTIONAL }
+
+   where
+
+   effectiveRights ::= SEQUENCE OF SEQUENCE {
+      rights        <see <rights> in BNF>,
+      whichObject   ENUMERATED {
+                       LDAP_ENTRY (1),
+                       LDAP_SUBTREE (2)
+                       },
+      subject       < see <subject> in BNF >
+   }
+
+If the server does not recognize the request name, it MUST
+return only the response fields from LDAPResult, containing
+
+
+
+Stokes, et al      Expires 14 January 2001         [Page 39]
+\f
+
+
+
+
+Internet-Draft      Access Control Model        14 July 2000
+
+
+
+the protocolError result code.
+
+
+
+13.  Security Considerations
+
+This document proposes protocol elements for transmission of
+security policy information.  Security considerations are
+discussed throughout this draft.  Because subject security
+attribute information is used to evaluate decision requests,
+it is security-sensitive information and must be protected
+against unauthorized modification whenever it is stored or
+transmitted.
+
+Interaction of access control with other directory functions
+(other than the ones defined in this document) are not
+defined in this document, but instead in the documents where
+those directory functions are defined.  For example, the
+directory replication documents should address the
+interaction of access control with the replication function.
+
+
+
+14.  References
+
+[LDAPv3] M. Wahl, T. Howes, S. Kille, "Lightweight Directory
+Access Protocol (v3)", RFC 2251, December 1997.
+
+[ECMA] ECMA, "Security in Open Systems: A Security
+Framework" ECMA TR/46, July 1988.
 
+[REQTS] Stokes, Byrne, Blakley, "Access Control Requirements
+for LDAP", RFC 2820, May 2000.
 
+[ATTR] M.Wahl, A, Coulbeck, T. Howes, S. Kille, "Lightweight
+Directory Access Protocol (v3)": Attribute Syntax
+Definitions, RFC 2252, December 1997.
 
+[UTF] M. Wahl, S. Kille, "Lightweight Directory Access
+Protocol (v3)": A UTF-8 String Representation of
+Distinguished Names", RFC 2253, December 1997.
 
+[Bradner97] Bradner, Scott, "Key Words for use in RFCs to
+Indicate Requirement Levels", RFC 2119.
 
-          Stokes, Byrne, Blakley   Expires 10 September 2000         [Page 30]
+[AuthMeth] Wahl, M., Alvestrand, H., Hodges, J. and R.
+Morgan, "Authentication Methods for LDAP", RFC 2829, May
+2000.
 
+[ABNF] D. Crocker, P. Overell, "Augmented BNF for Syntax
+Specifications: ABNF", RFC 2234, November 1997.
 
 
 
+Stokes, et al      Expires 14 January 2001         [Page 40]
+\f
 
 
-          Internet-Draft      Access Control Model       10 March 2000
 
 
+Internet-Draft      Access Control Model        14 July 2000
 
-             The requestName is a dotted-decimal representation of the
-             OBJECT IDENTIFIER corresponding to the request. The
-             requestValue is information in a form defined by that
-             request, encapsulated inside an OCTET STRING.
 
-             The server will respond to this with an LDAPMessage
-             containing the ExtendedResponse which is a rights list.
 
-             ldapGetEffectiveRightsResponse ::= [APPLICATION 24]
-             SEQUENCE {
-                COMPONENTS OF LDAPResult,
-                responseName     [10] <OID to be assigned> OPTIONAL,
-                effectiveRights  [11] OCTET STRING OPTIONAL }
+ACKNOWLEDGEMENT
 
-                where
+This is to acknowledge the numerous companies and individuals who have
+contributed their valuable help and insights to the development of this
+specification.
 
-                effectiveRights ::= SEQUENCE OF SEQUENCE {
-                   family        LDAPOID,
-                   rights        <see <rights> in BNF>,
-                   whichObject   ENUMERATED {
-                                    LDAP_ENTRY (1),
-                                    LDAP_SUBTREE (2)
-                                    },
-                   dnType        "access-id"|"group"|"role"|
-                                    "ipAddress"|"kerberosID"|
-                                    <printableString>,
-                   subjectDN     LDAPString | "public" | "this"
-                }
 
-             If the server does not recognize the request name, it
-             MUST return only the response fields from LDAPResult,
-             containing the protocolError result code.
+AUTHOR(S) ADDRESS
 
+ Ellen Stokes                       Bob Blakley
+ Tivoli Systems                     Tivoli Systems
+ 6300 Bridgepoint Parkway           6300 Bridgepoint Parkway
+ Austin, TX 78731                   Austin, TX 78731
+ USA                                USA
+ mail-to: estokes@tivoli.com        mail-to: blakley@tivoli.com
+ phone: +1 512 436 9098             phone: +1 512 436 1564
+ fax:   +1 512 436 1199             fax:   +1 512 436 1199
 
 
-          11.  Security Considerations
+ Debbie Rinkevich                   Robert Byrne
+ IBM                                Sun Microsystems
+ 11400 Burnet Rd                    29 Chemin du Vieux Chene
+ Austin, TX 78758                   Meylan ZIRST 38240
+ USA                                France
+ mail-to: djbrink@us.ibm.com        mail-to: rbyrne@france.sun.com
+ phone: +1 512 838 1960             phone: +33 (0)4 76 41 42 05
+ fax:   +1 512 838 8597
 
-             This document proposes protocol elements for transmission
-             of security policy information.  Security considerations
-             are discussed throughout this draft.  Because subject
-             security attribute information is used to evaluate
-             decision requests, it is security-sensitive information
-             and must be protected against unauthorized modification
-             whenever it is stored or transmitted.
 
 
 
 
-          Stokes, Byrne, Blakley   Expires 10 September 2000         [Page 31]
 
 
 
 
 
 
-          Internet-Draft      Access Control Model       10 March 2000
 
 
 
-          12.  References
 
-             [LDAPv3] M. Wahl, T. Howes, S. Kille, "Lightweight
-             Directory Access Protocol (v3)", RFC 2251, December 1997.
 
-             [ECMA] ECMA, "Security in Open Systems: A Security
-             Framework" ECMA TR/46, July 1988
 
-             [REQTS] Stokes, Byrne, Blakley, "Access Control
-             Requirements for LDAP", INTERNET-DRAFT <draft-ietf-
-             ldapext-acl-reqts-03.txt>, February 2000.
 
-             [ATTR] M.Wahl, A, Coulbeck, T. Howes, S. Kille,
-             "Lightweight Directory Access Protocol (v3)": Attribute
-             Syntax Definitions, RFC 2252, December 1997.
 
-             [UTF] M. Wahl, S. Kille, "Lightweight Directory Access
-             Protocol (v3)": A UTF-8 String Representation of
-             Distinguished Names", RFC 2253, December 1997.
 
-             [Bradner97] Bradner, Scott, "Key Words for use in RFCs to
-             Indicate Requirement Levels", RFC 2119.
 
 
-          AUTHOR(S) ADDRESS
 
-              Ellen Stokes                       Bob Blakley
-              IBM                                Dascom
-              11400 Burnet Rd                    5515 Balcones Drive
-              Austin, TX 78758                   Austin, TX 78731
-              USA                                USA
-              mail-to: stokes@austin.ibm.com     mail-to: blakley@dascom.com
-              phone: +1 512 838 3725             phone: +1 512 458 4037  ext 5012
-              fax:   +1 512 838 8597             fax:   +1 512 458 237
 
 
-              Debbie Byrne
-              IBM
-              11400 Burnet Rd
-              Austin, TX 78758
-              USA
-              mail-to: djbyrne@us.ibm.com
-              phone: +1 512 838 1960
-              fax:   +1 512 838 8597
 
 
+Stokes, et al      Expires 14 January 2001         [Page 41]
+\f
 
 
-          Stokes, Byrne, Blakley   Expires 10 September 2000         [Page 32]
 
 
+Internet-Draft      Access Control Model        14 July 2000
 
 
 
 
-          Internet-Draft      Access Control Model       10 March 2000
 
 
 
 
 
 
-          Stokes, Byrne, Blakley   Expires 10 September 2000         [Page 33]
 
 
+Stokes, et al      Expires 14 January 2001         [Page 42]
+\f
 
 
 
 
 
 
-                                    CONTENTS
+                          CONTENTS
 
 
          1.  Introduction.......................................   2
+ 1.  Introduction.......................................   2
 
          2.  Overview...........................................   2
2.  The LDAPv3 Access Control Model....................   2
 
-           3.  Terminology........................................   4
+ 3.  Access Control Mechanism Attributes................   5
+     3.1   Root DSE Attribute for Access Control
+           Mechanism....................................   5
+     3.2   Root DSE Attribute for Control of Disclosing
+           Errors.......................................   5
+     3.3   Subentry Class Access Control Mechanism......   6
 
-           4.  The Model..........................................   6
-               4.1   Access Control Information Model.............   6
+ 4.  The Access Control Information Attribute
+     (ldapACI)..........................................   7
+     4.1   The BNF......................................   8
+           4.1.1   ACI String Representation   8
+           4.1.2   ACI Binary Representation  10
+     4.2   The Components of ldapACI Attribute..........  11
+           4.2.1   Scope  11
+           4.2.2   Access Rights and Permissions  11
+           4.2.3   Attributes  14
+           4.2.4   Subjects and Associated
+                   Authentication  15
+     4.3   Grant/Deny Evaluation Rules..................  15
 
-           5.  Access Control Mechanism Attributes................   8
-               5.1   Root DSE Attribute for Access Control
-                     Mechanism....................................   8
-               5.2   Subschema Attribute for Access Control
-                     Mechanism....................................   8
+ 5.  Required Permissions for each LDAP Operation.......  17
+     5.1   Bind Operation...............................  18
+     5.2   Search Operation.............................  18
+     5.3   Modify Operation.............................  21
+     5.4   Add Operation................................  22
+     5.5   Delete Operation.............................  23
+     5.6   Modify DN Operation..........................  23
+     5.7   Compare Operation............................  24
+     5.8   Abandon Operation............................  25
+     5.9   Extended Operation...........................  25
 
-           6.  Access Control Information Attributes..............   9
-               6.1   The BNF......................................  10
-               6.2   Other Defined Parameters.....................  11
-                     6.2.1  Families and Rights  11
-                     6.2.2  DN Types  12
-               6.3   Basic ACI Attribute (ldapACI)................  13
-                     6.3.1  LDAP Operations  15
-                     6.3.2  Grant/Deny Evaluation Rules  15
-               6.4   Policy Owner Attribute (policyOwner).........  16
-               6.5   ACI Examples.................................  17
-                     6.5.1  Attribute Definition  17
-                     6.5.2  Modifying the ldapACI Values  18
-                     6.5.3  Evaluation  19
+ 6.  Required Permissions for Handling Aliases and
+     References.........................................  25
+     6.1   ACI Distribution.............................  25
+     6.2   Aliases......................................  26
+     6.3   Referrals....................................  26
 
-           7.  Operational Semantics of Access Control
-               Operations.........................................  21
-               7.1   Types of actions.............................  21
-               7.2   Semantics of Histories.......................  22
+ 7.  Controlling Access to Access Control
+     Information........................................  27
 
-           8.  Access Control Parameters for LDAP Controls &
-               Extended Operations................................  25
+ 8.  ACI Examples.......................................  27
+     8.1   Attribute Definition.........................  27
+     8.2   Modifying the ldapACI Values.................  28
+     8.3   Evaluation...................................  30
 
-           9.  Access Control Information (ACI) Controls..........  26
-               9.1   getEffectiveRights Control...................  26
-                     9.1.1  Request Control  26
-                     9.1.2  Response Control  27
-                     9.1.3  Client-Server Interaction  28
 
 
+                           - i -
 
-                                     - i -
 
 
 
 
 
 
+ 9.  Operational Semantics of Access Control
+     Operations.........................................  31
+     9.1   Types of actions.............................  32
+     9.2   Semantics of Histories.......................  32
 
-          10.  Access Control Extended Operation..................  30
-               10.1  LDAP Get Effective Rights Operation..........  30
+10.  Access Control Parameters for LDAP Controls &
+     Extended Operations................................  35
 
-          11.  Security Considerations............................  31
+11.  Access Control Information (ACI) Controls..........  35
+     11.1  getEffectiveRights Control...................  35
+           11.1.1  Request Control  35
+           11.1.2  Response Control  36
+           11.1.3  Client-Server Interaction  37
 
-          12.  References.........................................  32
+12.  Access Control Extended Operation..................  38
+     12.1  LDAP Get Effective Rights Operation..........  39
 
+13.  Security Considerations............................  40
 
+14.  References.........................................  40
 
 
 
 
 
 
+                           - ii -
 
 
 
 
 
 
-                                     - ii -
 
 
 
 
 
+Full Copyright Statement
 
+Copyright (C) The Internet Society (2000).á All Rights
+Reserved.
 
+This document and translations of it may be copied and
+furnished to others, and derivative works that comment on or
+otherwise explain it or assist in its implementation may be
+prepared, copied, published and distributed, in whole or in
+part, without restriction of any kind, provided that the
+above copyright notice and this paragraph are included on
+all such copies and derivative works.á However, this
+document itself may not be modified in any way, such as by
+removing the copyright notice or references to the Internet
+Society or other Internet organizations, except as needed
+for the purpose of developing Internet standards in which
+case the procedures for copyrights defined in the Internet
+Standards process must be followed, or as required to
+translate it into languages other than English.
 
+The limited permissions granted above are perpetual and will
+not be revoked by the Internet Society or its successors or
+assigns.
 
+This document and the information contained herein is
+provided on an "AS IS" basis and THE INTERNET SOCIETY AND
+THE INTERNET ENGINEERING TASK FORCE DISCLAIMS 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.
 
 
-          Full Copyright Statement
 
-          Copyright (C) The Internet Society (1999).á All Rights
-          Reserved.
 
-          This document and translations of it may be copied and
-          furnished to others, and derivative works that comment on or
-          otherwise explain it or assist in its implementation may be
-          prepared, copied, published and distributed, in whole or in
-          part, without restriction of any kind, provided that the
-          above copyright notice and this paragraph are included on
-          all such copies and derivative works.á However, this
-          document itself may not be modified in any way, such as by
-          removing the copyright notice or references to the Internet
-          Society or other Internet organizations, except as needed
-          for the purpose of developing Internet standards in which
-          case the procedures for copyrights defined in the Internet
-          Standards process must be followed, or as required to
-          translate it into languages other than English.
 
-          The limited permissions granted above are perpetual and will
-          not be revoked by the Internet Society or its successors or
-          assigns.
 
-          This document and the information contained herein is
-          provided on an "AS IS" basis and THE INTERNET SOCIETY AND
-          THE INTERNET ENGINEERING TASK FORCE DISCLAIMS 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.
 
 
 
 
 
 
-                                    - iii -
+                          - iii -
 
 
 
index 3fb0d19a6df4ceea14e6836f6d0cc91e9b3d34ab..12a176963ebd5cfbd6e9cf2ab08648f9a7ac1ad5 100644 (file)
@@ -1,7 +1,7 @@
 INTERNET-DRAFT                                         Michael P. Armijo
-<draft-ietf-ldapext-locate-02.txt>                          Levon Esibov
-April, 2000                                                   Paul Leach
-Expires: October, 2000                             Microsoft Corporation
+<draft-ietf-ldapext-locate-03.txt>                          Levon Esibov
+July, 2000                                                    Paul Leach
+Expires: January, 2001                             Microsoft Corporation
                                                             R.L. Morgan
                                                University of Washington
 
@@ -29,7 +29,7 @@ Status of this Memo
    http://www.ietf.org/shadow.html.
 
    Distribution of this memo is unlimited.  It is filed as <draft-
-   ietf-ldapext-locate-02.txt>, and expires on October 15, 2000.  
+   ietf-ldapext-locate-03.txt>, and expires on January 14, 2001.  
    Please send comments to the authors.
 
 
@@ -89,17 +89,31 @@ Status of this Memo
 
    This section defines a method of converting a DN into a DNS domain
    name for use in the server location method described below.  Some
-   DNs cannot be converted into a domain name.
+   DNs cannot be converted into a domain name.  Converted DNs result 
+   in a fully qualified domain name.
 
    The output domain name is initially empty.  For each RDN component
-   of the DN, beginning with the first, if the attribute type is "DC",
-   then the attribute value is used as a domain name component (label).
+   of the DN, beginning with the rightmost and working left, if the 
+   attribute type is "DC", then the attribute value is used as a domain 
+   name component (label).
    The first such value becomes the most significant (i.e., rightmost)
    domain name component, and successive values occupy less significant
    positions (i.e., extending leftward), in order.  If the attribute
-   type is not "DC", then processing stops.  If the first RDN component
+   type is not "DC", then processing stops.  If the final RDN component
    of the DN is not of type "DC" then the DN cannot be converted to a
-   domain name.
+   domain name. 
+
+   For DN:
+
+   cn=John Doe,ou=accounting,dc=example,dc=net
+
+   The client would convert the DC components as defined above into 
+   DNS name:
+
+   example.net.
+
+   The determined DNS name will be submitted as a DNS query using the 
+   algorithm defined in section 4.
 
 
 4. Locating LDAP servers through DNS
@@ -114,11 +128,13 @@ Status of this Memo
       _<Service>._<Proto>.<Domain>
 
    where <Service> is always "ldap", and <Proto> is a protocol that can
-   be either "udp" or "tcp".  <Domain> is the domain name formed by
-   converting the DN of a naming context mastered by the LDAP Server
-   into a domain name using the algorithm in Section 2.  Note that
-   "ldap" is the symbolic name for the LDAP service in Assigned
-   Numbers[6], as required by [5].
+   be either "udp" or "tcp".  "_ldap._tcp" applies to services 
+   compatible with LDAPv2 [7] or LDAPv3 [1].  "_ldap._udp" 
+   applies to services compatible with CLDAP [8].  <Domain> is 
+   the domain name formed by converting the DN of a naming context 
+   mastered by the LDAP Server into a domain name using the algorithm in 
+   Section 3.  Note that "ldap" is the symbolic name for the LDAP service 
+   in Assigned Numbers[6], as required by [5].
 
    Presence of such records enables clients to find the LDAP servers
    using standard DNS query [4].  A client (or server) seeking an LDAP
@@ -139,8 +155,10 @@ Status of this Memo
       _ldap._tcp.example.net.   IN       SRV  0 0 389 phoenix.example.net.
 
    The set of returned records may contain multiple records in the case
-   where multiple LDAP servers serve the same domain.
-
+   where multiple LDAP servers serve the same domain.  If there are no 
+   matching SRV records available for the converted DN the client SHOULD 
+   NOT attempt to 'walk the tree' by removing the least significant 
+   portion of the constructed fully qualified domain name.
 
 
 5. Security Considerations
@@ -173,8 +191,14 @@ Status of this Memo
    [6]  Reynolds, J. and J. Postel, "Assigned Numbers", STD 2, RFC
         1700, October 1994.
 
+   [7]  Yeong, W., Howes, T. and Kille, S.,  "Lightweight Directory Access 
+        Protocol",  RFC 1777, March 1995
+
+   [8]  Young, A., "Connection-less Lightweight Directory Access Protocol",
+        RFC 1798, June 1995
+
 
-6. Authors' Addresses
+7. Authors' Addresses
 
    Michael P. Armijo
    One Microsoft Way
@@ -201,5 +225,7 @@ Status of this Memo
    EMail: rlmorgan@washington.edu
    URI:   http://staff.washington.edu/rlmorgan/
 
-   Expires October, 2000
+   Expires January, 2001
+
+
 
index 5bbe7926983bc0b5280f6fdad9f445d3076f4023..d35e2ff6665f12234949fcda01062619fd598338 100644 (file)
-Internet-Draft                                      David Chadwick
-LDAPExt WG                                         University of Salford
-Intended Category: Standards Track                     Sean Mullan
-                                                                  Sun
-Microsystems
-Expires: 8 March 2000                             8 September 1999
-
-Returning Matched Values with LDAPv3
-<draft-ietf-ldapext-matchedval-01.txt>
-
-STATUS OF THIS MEMO
-
-This document is an Internet-Draft and is in full conformance with
-all the provisions of Section 10 of RFC2026.
-
-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 expires on 8 March 2000. Comments and suggestions
-on this document are encouraged. Comments on this document should be
-sent to the LDAPExt working group discussion list:
-                ietf-ldapext@netscape.com
-or directly to the authors.
-
-ABSTRACT
-
-This document describes a control for the Lightweight Directory
-Access Protocol v3 that is used to return a subset of attribute
-values from an entry, specifically, only those values that
-contributed to the search filter evaluating to TRUE. Without support
-for this control, a client must retrieve all of an attribute's values
-and search for specific values locally.
-
-1. Introduction
-
-When reading an attribute from an entry using LDAP v2 [1] or LDAPv3
-[2], it is normally only possible to read either the attribute type,
-or the attribute type and all its values. It is not possible to
-selectively read just a few of the attribute values. If an attribute
-holds many values, for example, the userCertificate attribute, or the
-subschema publishing operational attributes objectClasses and
-attributeTypes [3], then it may be desirable for the user to be able
-to selectively retrieve a subset of the values, specifically, those
-attribute values that match the selection criteria as specified by
-the user in the filter. Without the control specified in this
-[ID/standard] a client must read all of the attribute's values and
-filter out the unwanted values, necessitating the client to implement
-the matching rules. It also requires the client to potentially read
-and process many irrelevant values, which can be inefficient if the
-values are large or complex, or there are many values stored per
-attribute.
-
-This Internet Draft specifies an LDAPv3 control to enable a user to
-return only those values that matched (i.e. returned TRUE to) one or
-more elements of the Search filter. This control can be especially
-useful when used in conjunction with extensible matching rules that
-match on one or more components of complex binary attribute values.
-
-The control has been described in such a way as to be fully
-compatible with the matchedValuesOnly boolean of the X.500 DAP [4]
-Search argument, as amended in the latest version [6].
-
-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 RFC 2119 [5].
-
-2. The matchedValuesOnly Control
-
-The matchedValuesOnly control MAY be critical or non-critical as
-determined by the user. It is only applicable to the Search
-operation, and SHALL be ignored by the server if it is present on any
-other LDAP operation (even if marked critical on such operations).
-
-The object identifier for this control is 1.2.826.0.1.3344810.2.2
-
-The controlValue is absent.
-
-If the server supports this control, the server MUST make use of the
-control as follows:
-
-(1) If the typesOnly parameter of the Search Request is TRUE,
-the control has no effect and the Search Request SHOULD be
-processed as if the control had not been specified.
-
-(2) If the attributes parameter of the Search Request consists
-of a list containing only the attribute with OID "1.1"
-(specifying that no attributes are to be returned), the control
-has no effect and the Search Request SHOULD be processed as if
-the control had not been specified.
-
-(3) For each attribute listed in the attributes parameter of the
-Search Request, the server MUST apply the control as follows:
-
-i) Every attribute value that evaluates TRUE against one or
-more filters, excluding the ignored filters (see below),
-is logically marked by the server as contributing to the
-filter matching.
-ii) Attributes that have no values marked as contributing,
-have all their values returned to the user.
-iii) Attributes that have one or more values marked as
-contributing have only the contributing values returned to
-the user, whilst the other values of the same attribute
-(if there are any) are not returned.
-
-Certain filters are ignored for the purposes of marking the attribute
-values as contributing. These are:
-
-the Ã´presentö filter, since this filter does not test against
-any attribute values;
-the Ã´notö filter, since this would have the effect of marking
-all the attribute values except the one(s) that matched the
-non-negated filter.
-
-3. Relationship to X.500
-
-The matchedValuesOnly control defined in this document is derived
-from the matchedValuesOnly boolean parameter of the X.511 (93) DAP
-Search operation [4]. Note however that in X.511 (93), the
-matchedValuesOnly parameter is ignored when used with an "equality"
-match FilterItem, and so the user must use the extensibleMatch filter
-along with the equality matching rule if only matched values are
-wanted with equality matching. This slightly spurious equality match
-restriction has been removed from the 2000 version of X.511 [6]. For
-LDAP servers acting as a gateway to an X.500 directory, the matched
-valuesOnly control can be directly mapped onto the X.511
-matchedValuesOnly Search parameter as follows:
-
-(1) If the matchedValuesOnly control is specified, the
-matchedValuesOnly DAP parameter MUST be set to true. If the
-control criticality value is TRUE then bit 17 of the DAP
-criticalExtensions MUST be set.
-
-(2) If an equality matching rule is specified in the filter of
-the LDAPv3 search operation, then if operating with a pre-2000
-edition DSA, the corresponding equality FilterItem contained in
-the X.511 filter parameter MUST NOT be used, but rather the
-extensibleMatch filter item MUST be used instead (the assertion
-consisting of the equality matching rule, the attribute type to
-match on, and the asserted value). When operating with DSAs
-that support the 2000 DAP enhancement, the equality FilterItem
-MAY be used.
-
-4. Examples
-
-(1) The first example simply shows how the control can be used to
-selectively read a subset of attribute values.
-
-The entry below represents a groupOfNames object class containing
-several members from different organizations.
-
-cn: Cross Organizational Standards Body
-member: cn=joe, o=acme
-member: cn=alice, o=acme
-member: cn=bob, o=foo
-member: cn=sue, o=bar
-
-An LDAP search operation is specified with a baseObject set to the
-DN of the entry, a baseObject scope, a filter set to
-"member=*o=acme", and the list of attributes to be returned set to
-"member". In addition, a matchedValuesOnly control is attached to the
-search request.
-
-The search results returned by the server would consist of the
-following entry:
-
-cn: Cross Organizational Standards Body
-member: cn=joe, o=acme
-member: cn=alice, o=acme
-
-(2) The second example shows how the control has no effect on
-attributes that do not participate in the search filter.
-
-The entries below represent inetOrgPerson [7] object classes located
-below some distinguished name in the directory.
-
-cn: Sean Mullan
-mail: sean.mullan@sun.com
-mail: mullan@east.sun.com
-telephoneNumber: +1 781 442 0926
-telephoneNumber: 555-9999
-
-cn: David Chadwick
-mail: d.w.chadwick@salford.ac.uk
-
-An LDAP search operation is specified with a baseObject set to the
-DN of the entry, a subtree scope, a filter set to
-"(|(mail=sean.mullan@sun.com)(mail=d.w.chadwick@salford.ac.uk))", and
-the list of attributes to be returned set to "mail telephoneNumber".
-In addition, a matchedValuesOnly control is attached to the search
-request.
-
-The search results returned by the server would consist of the
-following entries:
-
-cn: Sean Mullan
-mail: sean.mullan@sun.com
-telephoneNumber: +1 781 442 0926
-telephoneNumber: 555-9999
-
-cn: David Chadwick
-mail: d.w.chadwick@salford.ac.uk
-
-Note that the control has no effect on the values returned for the
-"telephoneNumber" attribute (all of the values are returned), since
-it did not participate in the search filter.
-
-5. Security Considerations
-
-This Internet Draft does not discuss security issues at all.
-
-Note that attribute values MUST only be returned if the access
-controls applied by the LDAP server allow them to be returned, and in
-this respect the effect of the matchedValuesOnly control is of no
-consequence.
-
-Note that the matchedValuesOnly control may have a positive effect on
-the deployment of public key infrastructures. Certain PKI operations,
-like searching for specific certificates, become more practical (when
-combined with X.509 certificate matching rules at the server) and
-more scalable, since the control avoids the downloading of
-potentially large numbers of irrelevant certificates which would have
-to be processed and filtered locally (which in some cases is very
-difficult to perform).
-
-6. Copyright
-
-Copyright (C) The Internet Society (date). All Rights Reserved.
-
-This document and translations of it may be copied and furnished to
-others, and derivative works that comment on or otherwise explain it
-or assist in its implementation may be prepared, copied, published
-and distributed, in whole or in part, without restriction of any
-kind, provided that the above copyright notice and this paragraph are
-included on all such copies and derivative works.  However, this
-document itself may not be modified in any way, such as by removing
-the copyright notice or references to the Internet Society or other
-Internet organizations, except as needed for the purpose of
-developing Internet standards in which case the procedures for
-copyrights defined in the Internet Standards process must be
-followed, or as required to translate it into languages other than
-English.
-
-The limited permissions granted above are perpetual and will not be
-revoked by the Internet Society or its successors or assigns.
-
-This document and the information contained herein is provided on an
-"AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
-TASK FORCE DISCLAIMS 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.
-
-7. References
-
-[1] Yeong, W., Howes, T., and Kille, S. "Lightweight Directory Access
-Protocol", RFC 1777, March 1995.
-[2] M. Wahl, T. Howes, S. Kille, "Lightweight Directory Access
-Protocol (v3)", Dec. 1997, RFC 2251
-[3] M. Wahl, A. Coulbeck, T. Howes, S. Kille, Ã´Lightweight Directory
-Access Protocol (v3): Attribute Syntax Definitionsö, RFC 2252, Dec
-1997
-[4] ITU-T Rec. X.511, "The Directory: Abstract Service Definition",
-1993.
-[5] S.Bradner. "Key words for use in RFCs to Indicate Requirement
-Levels", RFC 2119, March 1997.
-[6] Ã´FPDAMs to ISO/IEC 9594 Parts 1, 2, 3, 4, 5, 6, 7 and 9 to
-support the ITU-T Rec. F.510 "Automated Directory Assistance, White
-Pages Service Definitions"ö, Collaborative ITU-T/SG7/Q15 and
-JTC1/SC6/WG7 OSI Directory Meeting 7-15 April 1999, Orlando, USA
-[7] M. Smith. "Definition of the inetOrgPerson LDAP Object Class",
-Internet Draft <draft-smith-ldap-inetorgperson-03.txt>, April 1999.
-
-8. Authors Addresses
-
-David Chadwick
-IS Institute
-University of Salford
-Salford M5 4WT
-England
-
-Email: d.w.chadwick@salford.ac.uk
-
-Sean Mullan
-Sun Microsystems Laboratories
-One Network Drive
-Burlington
-MA 01803-0902
-USA
-
-Tel:  +1 781 442-0926           Fax:  +1 781 442-1692
-Email: sean.mullan@sun.com
-
-Internet-Draft  Returning Matched Values with LDAPv3 8 September 1999
-
-5
+Internet-Draft                                      David Chadwick\r
+LDAPExt WG                                        University of Salford      \r
+Intended Category: Standards Track                     Sean Mullan\r
+                                                                 Sun Microsystems\r
+Expires: 1 January 2001                             1 July 2000\r
+\r
+\r
+Returning Matched Values with LDAPv3\r
+<draft-ietf-ldapext-matchedval-02.txt>\r
+\r
+\r
+STATUS OF THIS MEMO\r
+\r
+This document is an Internet-Draft and is in full conformance with \r
+all the provisions of Section 10 of RFC2026.\r
+\r
+Internet-Drafts are working documents of the Internet Engineering \r
+Task Force (IETF), its areas, and its working groups. Note that other\r
+groups may also distribute working documents as Internet-Drafts.\r
+\r
+Internet-Drafts are draft documents valid for a maximum of six months\r
+and may be updated, replaced, or obsoleted by other documents at any\r
+time. It is inappropriate to use Internet-Drafts as reference \r
+material or to cite them other than as "work in progress."\r
+\r
+The list of current Internet-Drafts can be accessed at\r
+http://www.ietf.org/ietf/1id-abstracts.txt.\r
+\r
+The list of Internet-Draft Shadow Directories can be accessed at\r
+http://www.ietf.org/shadow.html.\r
+\r
+This Internet-Draft expires on 1 January 2001. Comments and \r
+suggestions on this document are encouraged. Comments on this \r
+document should be sent to the LDAPExt working group discussion list:\r
+                ietf-ldapext@netscape.com\r
+or directly to the authors.\r
+\r
+\r
+ABSTRACT\r
+\r
+This document describes a control for the Lightweight Directory \r
+Access Protocol v3 that is used to return a subset of attribute \r
+values from an entry, specifically, only those values that match a \r
+"values return" filter. Without support for this control, a client \r
+must retrieve all of an attribute's values and search for specific \r
+values locally.\r
+\r
+\r
+1. Introduction\r
+\r
+When reading an attribute from an entry using LDAP v2 [1] or LDAPv3 \r
+[2], it is normally only possible to read either the attribute type, \r
+or the attribute type and all its values. It is not possible to \r
+selectively read just a few of the attribute values. If an attribute \r
+holds many values, for example, the userCertificate attribute, or the \r
+subschema publishing operational attributes objectClasses and \r
+attributeTypes [3], then it may be desirable for the user to be able \r
+to selectively retrieve a subset of the values, specifically, those \r
+attribute values that match some user defined selection criteria. \r
+Without the control specified in this [ID/standard] a client must \r
+read all of the attribute's values and filter out the unwanted \r
+values, necessitating the client to implement the matching rules. It \r
+also requires the client to potentially read and process many \r
+irrelevant values, which can be inefficient if the values are large \r
+or complex, or there are many values stored per attribute.\r
+\r
+This Internet Draft specifies an LDAPv3 control to enable a user to \r
+return only those values that matched (i.e. returned TRUE to) one or \r
+more elements of a newly defined "values return" filter. This control \r
+can be especially useful when used in conjunction with extensible \r
+matching rules that match on one or more components of complex binary \r
+attribute values.\r
+\r
+The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",  \r
+"SHOULD", "SHOULD NOT", "RECOMMENDED",  "MAY", and "OPTIONAL" in this \r
+document are to be interpreted as described in RFC 2119 [5].\r
+\r
+\r
+2. The valuesReturnFilter Control\r
+\r
+The valuesReturnFilter control MAY be critical or non-critical as \r
+determined by the user. It is only applicable to the Search \r
+operation, and SHALL be ignored by the server if it is present on any \r
+other LDAP operation (even if marked critical on such operations).\r
+\r
+The object identifier for this control is 1.2.826.0.1.3344810.2.3\r
+\r
+\r
+The controlValue is \r
+\r
+        ValuesReturnFilter ::= SEQUENCE OF SimpleFilterItem\r
+\r
+        SimpleFilterItem ::= CHOICE {\r
+                equalityMatch   [3] AttributeValueAssertion,\r
+                substrings      [4] SubstringFilter,\r
+                greaterOrEqual  [5] AttributeValueAssertion,\r
+                lessOrEqual     [6] AttributeValueAssertion,\r
+                present         [7] AttributeDescription,\r
+                approxMatch     [8] AttributeValueAssertion,\r
+                extensibleMatch [9] SimpleMatchingAssertion }\r
+\r
+         SimpleMatchingAssertion ::= SEQUENCE {\r
+                matchingRule    [1] MatchingRuleId OPTIONAL,\r
+                type            [2] AttributeDescription OPTIONAL,\r
+                matchValue      [3] AssertionValue}\r
+\r
+All the above data types have their standard meanings as defined in \r
+[2].\r
+\r
+If the server supports this control, the server MUST make use of the \r
+control as follows:\r
+\r
+(1) The Search Filter is first executed in order to determine \r
+which entries satisfy the Search criteria. The control has no \r
+impact on this step.\r
+\r
+(2) If the typesOnly parameter of the Search Request is TRUE, \r
+the control has no effect and the Search Request SHOULD be \r
+processed as if the control had not been specified.\r
+\r
+(3) If the attributes parameter of the Search Request consists \r
+of a list containing only the attribute with OID "1.1" \r
+(specifying that no attributes are to be returned), the control \r
+has no effect and the Search Request SHOULD be processed as if \r
+the control had not been specified.\r
+\r
+(4) For each attribute listed in the attributes parameter of the \r
+Search Request, the server MUST apply the control as follows:\r
+\r
+i) Every attribute value that evaluates TRUE against one or \r
+more elements of the ValuesReturnFilter is placed in the \r
+SearchResultEntry.\r
+ii) Every attribute value that evaluates FALSE or undefined \r
+against all elements of the ValuesReturnFilter is not \r
+placed in the SearchResultEntry. An attribute that has no \r
+values selected is returned with an empty set of vals.\r
+\r
+Editor's Note. There is possibly a more efficient but slightly more \r
+complex way of achieving the value filtering. An alternative is to \r
+remove the 'present' SimpleFilterItem (which obviously evaluates true \r
+for every attribute value of the 'present' attribute description), \r
+and to say that any attribute whose type is not mentioned in the \r
+ValuesReturnFilter is not filtered and has all its attribute values \r
+returned. Comments please.\r
+\r
+\r
+3. Relationship to X.500\r
+\r
+The control is a superset of the matchedValuesOnly boolean of the \r
+X.500 DAP [4] Search argument, as amended in the latest version [6].\r
+Close examination of the matchedValuesOnly boolean by the LDAPExt \r
+group revealed ambiguities and complexities in the MVO boolean that \r
+could not easily be resolved. For example, are only those attribute \r
+values that contributed to the overall truth of the filter governed \r
+by the MVO boolean, or all values of attributes in the filter \r
+governed by the MVO boolean, even if the filter item containing the \r
+attribute evaluated to false. For this reason the LDAP group decided \r
+to replace the MVO boolean with a simple filter that removes any \r
+uncertainty as to whether an attribute value has been selected or \r
+not. \r
+\r
+\r
+4. Examples\r
+\r
+(1) The first example simply shows how the control can be used to \r
+selectively read a subset of attribute values. \r
+\r
+The entry below represents a groupOfNames object class containing \r
+several members from different organizations.\r
+\r
+cn: Cross Organizational Standards Body\r
+member: cn=joe,o=acme\r
+member: cn=alice,o=acme\r
+member: cn=bob,o=foo\r
+member: cn=sue,o=bar\r
+\r
+An LDAP search operation is specified with a baseObject set to the\r
+DN of the entry, a baseObject scope, a filter set to \r
+"member=*o=acme", and the list of attributes to be returned set to \r
+"member". In addition, a ValuesReturnFilter control is set to \r
+"member=*o=acme".\r
+\r
+The search results returned by the server would consist of the \r
+following entry:\r
+\r
+cn: Cross Organizational Standards Body\r
+member: cn=joe, o=acme\r
+member: cn=alice, o=acme\r
+\r
+\r
+(2) The second example shows how the control can be set to match on \r
+attributes that are (mail) and are not (telephoneNumber) part of the \r
+search filter. It also shows how a user can filter some attribute \r
+values (mail) and not others (telephoneNumber).\r
+\r
+The entries below represent inetOrgPerson [7] object classes located\r
+below some distinguished name in the directory.\r
+\r
+cn: Sean Mullan\r
+mail: sean.mullan@sun.com\r
+mail: mullan@east.sun.com\r
+telephoneNumber: +1 781 442 0926\r
+telephoneNumber: 555-9999\r
+\r
+cn: David Chadwick\r
+mail: d.w.chadwick@salford.ac.uk\r
+\r
+An LDAP search operation is specified with a baseObject set to the\r
+DN of the entry, a subtree scope, a filter set to \r
+"(|(mail=sean.mullan@sun.com)(mail=d.w.chadwick@salford.ac.uk))", and \r
+the list of attributes to be returned set to "mail telephoneNumber". \r
+In addition, a ValuesReturnFilter control is set to \r
+"mail=sean.mullan@sun.com, mail=d.w.chadwick@salford.ac.uk, \r
+telephoneNumber=*"\r
+\r
+The search results returned by the server would consist of the \r
+following entries:\r
+\r
+cn: Sean Mullan\r
+mail: sean.mullan@sun.com\r
+telephoneNumber: +1 781 442 0926\r
+telephoneNumber: 555-9999\r
+\r
+cn: David Chadwick\r
+mail: d.w.chadwick@salford.ac.uk\r
+\r
+Note that the control has no effect on the values returned for the \r
+"telephoneNumber" attribute (all of the values are returned), since \r
+the control specified that all values should be returned.\r
+\r
+(3) The third example shows how one might retrieve a single attribute \r
+type schema definition for the "gunk" attribute with OID 1.2.3.4.5\r
+\r
+Assume the subschema subentry is held somewhere below the root entry \r
+with RDN "subschema subentry", and this holds an attributeTypes \r
+operational attribute holding the descriptions of the 35 attributes \r
+known to this server (each description is held as a single attribute \r
+value of the attributeTypes attribute). \r
+\r
+cn: subschema subentry\r
+objectClass: subschema\r
+attributeTypes: ( 2.5.4.3 NAME 'cn' SUP name )\r
+attributeTypes: ( 2.5.4.6 NAME 'c' SUP name SINGLE-VALUE )\r
+attributeTypes: ( 2.5.4.0 NAME 'objectClass' EQUALITY \r
+objectIdentifierMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )\r
+attributeTypes: ( 2.5.18.2 NAME 'modifyTimestamp' EQUALITY \r
+generalizedTimeMatch ORDERING generalizedTimeOrderingMatch\r
+SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 SINGLE-VALUE NO-USER-\r
+MODIFICATION USAGE directoryOperation )\r
+attributeTypes: ( 2.5.21.6 NAME 'objectClasses' EQUALITY \r
+objectIdentifierFirstComponentMatch SYNTAX \r
+1.3.6.1.4.1.1466.115.121.1.37 USAGE directoryOperation )\r
+attributeTypes: ( 1.2.3.4.5 NAME 'gunk' EQUALITY caseIgnoreMatch  \r
+SUBSTR caseIgnoreSubstringsMatch SYNTAX \r
+1.3.6.1.4.1.1466.115.121.1.44{64} )\r
+attributeTypes: ( 2.5.21.5 NAME 'attributeTypes' EQUALITY \r
+objectIdentifierFirstComponentMatch SYNTAX \r
+1.3.6.1.4.1.1466.115.121.1.3 USAGE directoryOperation )\r
+\r
+plus another 28 - you get the idea.\r
+\r
+\r
+The user creates an LDAP search operation with a baseObject set to \r
+root, a subtree scope, a filter set to "objectClass=subschema", the \r
+list of attributes to be returned set to "attributeTypes", and the \r
+ValuesReturnFilter set to "attributeTypes=1.2.3.4.5"\r
+\r
+The search result returned by the server would consist of the \r
+following entry:\r
+\r
+cn: subschema subentry\r
+attributeTypes: ( 1.2.3.4.5 NAME 'gunk' EQUALITY caseIgnoreMatch  \r
+SUBSTR caseIgnoreSubstringsMatch SYNTAX \r
+1.3.6.1.4.1.1466.115.121.1.44{64} )\r
+\r
+(4) The final example shows how the control can be set to match on \r
+attributes that are not part of the search filter. For example, \r
+searching for all entries that have an email address in the\r
+sun.com domain, and returning the telephone number for any attribute\r
+values that start with "555". \r
+\r
+The entries below represent inetOrgPerson [7] object classes located\r
+below some distinguished name in the directory.\r
+\r
+cn: Sean Mullan\r
+mail: sean.mullan@sun.com\r
+mail: mullan@east.sun.com\r
+telephoneNumber: +1 781 442 0926\r
+telephoneNumber: 555-9999\r
+\r
+cn: David Chadwick\r
+mail: d.w.chadwick@salford.ac.uk\r
+\r
+An LDAP search operation is specified with a baseObject set to the\r
+DN of the entry, a subtree scope, a filter set to "mail=*sun.com", \r
+and the list of attributes to be returned set to "telephoneNumber". \r
+In addition, a ValuesReturnFilter control is set to\r
+"telephoneNumber=555*"\r
+\r
+The search results returned by the server would consist of the \r
+following entry:\r
+\r
+cn: Sean Mullan\r
+telephoneNumber: 555-9999\r
+\r
+\r
+5. Security Considerations\r
+\r
+This Internet Draft does not discuss security issues at all. \r
+\r
+Note that attribute values MUST only be returned if the access \r
+controls applied by the LDAP server allow them to be returned, and in \r
+this respect the effect of the ValuesReturnFilter control is of no \r
+consequence.\r
+\r
+Note that the ValuesReturnFilter control may have a positive effect \r
+on the deployment of public key infrastructures. Certain PKI \r
+operations, like searching for specific certificates, become more \r
+practical (when combined with X.509 certificate matching rules at the \r
+server) and more scalable, since the control avoids the downloading \r
+of potentially large numbers of irrelevant certificates which would \r
+have to be processed and filtered locally (which in some cases is \r
+very difficult to perform).\r
+\r
+\r
+6. Acknowledgements\r
+\r
+The authors would like to thank members of the LDAPExt list for their \r
+constructive comments on earlier versions of this draft, and in \r
+particular to Harald Alvestrand who first suggested having an \r
+attribute return filter and Bruce Greenblatt who first proposed a \r
+syntax for this control.\r
+\r
+7. Copyright\r
+\r
+Copyright (C) The Internet Society (date). All Rights Reserved.\r
+\r
+This document and translations of it may be copied and furnished to \r
+others, and derivative works that comment on or otherwise explain it \r
+or assist in its implementation may be prepared, copied, published \r
+and distributed, in whole or in part, without restriction of any \r
+kind, provided that the above copyright notice and this paragraph are \r
+included on all such copies and derivative works.  However, this \r
+document itself may not be modified in any way, such as by removing \r
+the copyright notice or references to the Internet Society or other \r
+Internet organizations, except as needed for the purpose of \r
+developing Internet standards in which case the procedures for \r
+copyrights defined in the Internet Standards process must be \r
+followed, or as required to translate it into languages other than \r
+English.\r
+\r
+The limited permissions granted above are perpetual and will not be \r
+revoked by the Internet Society or its successors or assigns.\r
+\r
+This document and the information contained herein is provided on an \r
+"AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING \r
+TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING \r
+BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION \r
+HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF \r
+MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.\r
+\r
+\r
+8. References\r
+\r
+[1] Yeong, W., Howes, T., and Kille, S. "Lightweight Directory Access \r
+Protocol", RFC 1777, March 1995.\r
+[2] M. Wahl, T. Howes, S. Kille, "Lightweight Directory Access  \r
+Protocol (v3)", Dec. 1997, RFC 2251\r
+[3] M. Wahl, A. Coulbeck, T. Howes, S. Kille, "Lightweight Directory \r
+Access Protocol (v3): Attribute Syntax Definitions", RFC 2252, Dec \r
+1997\r
+[4] ITU-T Rec. X.511, "The Directory: Abstract Service Definition", \r
+1993.\r
+[5] S.Bradner. "Key words for use in RFCs to Indicate Requirement \r
+Levels", RFC 2119, March 1997.\r
+[6] ISO/IEC 9594 / ITU-T Rec X.511 (2000) The Directory: Abstract \r
+Service Definition.\r
+[7] M. Smith. "Definition of the inetOrgPerson LDAP Object Class", \r
+Internet Draft <draft-smith-ldap-inetorgperson-03.txt>, April 1999.\r
+\r
+\r
+9. Authors Addresses\r
+\r
+David Chadwick\r
+IS Institute\r
+University of Salford\r
+Salford M5 4WT \r
+England\r
+\r
+Email: d.w.chadwick@salford.ac.uk\r
+\r
+\r
+Sean Mullan                    \r
+Sun Microsystems\r
+East Point Business Park\r
+Dublin 3\r
+Ireland\r
+Tel: +353 1 853 0655\r
+Email: sean.mullan@sun.com\r
+\r
+Internet-Draft   Returning Matched Values with LDAPv3     1 July 2000\r
+\r
+\r
+1\r
+\r
diff --git a/doc/drafts/draft-ietf-ldapext-namedref-xx.txt b/doc/drafts/draft-ietf-ldapext-namedref-xx.txt
deleted file mode 100644 (file)
index 05bb5cb..0000000
+++ /dev/null
@@ -1,774 +0,0 @@
-IETF LDAPEXT Working Group                   Christopher Lukas [Editor]
-INTERNET-DRAFT                                   Internet Scout Project
-                                                              Tim Howes
-                                          Netscape Communications Corp.
-                                                     Michael Roszkowski
-                                                 Internet Scout Project
-                                                          Mark C. Smith
-                                          Netscape Communications Corp.
-                                                              Mark Wahl
-                                                    Critial Angle, Inc.
-                                                              June 1999
-
-
-                  Named Referrals in LDAP Directories
-                  <draft-ietf-ldapext-namedref-00.txt>
-
-
-
-1.  Status of this Memo
-
-This document is an Internet-Draft and is in full conformance with all
-provisions of Section 10 of RFC2026.
-
-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.
-
-Distribution of this document is unlimited.  Please send comments to the
-authors or the LDAPEXT mailing list, ietf-ldapext@netscape.com.
-
-Copyright Notice: Copyright (C) The Internet Society (1999). All Rights
-Reserved.
-
-This draft is a revision of a draft formerly published as draft-ietf-
-ldapext-referral-00.txt.
-
-This draft expires December 6, 1999.
-
-
-
-Howes, et al.          IETF LDAPEXT Working Group               [Page 1]
-
-
-
-
-
-INTERNET-DRAFT           LDAPv3 Named Referrals               March 1999
-
-
-2.  Abstract
-
-This document defines a "ref" attribute and associated "referral" object
-class for representing generic knowledge information in LDAP directories
-[RFC2251]. The attribute uses URIs [RFC1738] to represent knowledge,
-enabling LDAP and non-LDAP services alike to be referenced.  The object
-class can be used to construct entries in an LDAP directory containing
-references to other directories or services. This document also defines
-procedures directory servers should follow when supporting these schema
-elements and when responding to requests for which the directory server
-does not contain the requested object but may contain some knowledge of
-the location of the requested object.
-
-3.  Background and intended usage
-
-The broadening of interest in LDAP directories beyond their use as front
-ends to X.500 directories has created a need to represent knowledge
-information in a more general way. Knowledge information is information
-about one or more servers maintained in another server, used to link
-servers and services together.
-
-This document defines a general method of representing knowledge infor-
-mation in LDAP directories, based on URIs.
-
-The key words "MUST", "SHOULD", and "MAY" used in this document are to
-be interpreted as described in [RFC2119].
-
-4.  The ref attribute type
-
-This section defines the ref attribute type for holding general
-knowledge reference information.
-
-( 2.16.840.1.113730.3.1.34 NAME 'ref' DESC 'URL reference'
-  EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
-  USAGE distributedOperation )
-
-The ref attribute type has IA5 syntax and is case sensitive.  The ref
-attribute is multivalued. Values placed in the attribute MUST conform to
-the specification given for the labeledURI attribute defined in
-[RFC2079].  The labeledURI specification defines a format that is a URI,
-optionally followed by whitespace and a label. This document does not
-make use of the label portion of the syntax. Future documents MAY enable
-new functionality by imposing additional structure on the label portion
-of the syntax as it appears in the ref attribute.
-
-If the URI contained in the ref attribute refers to an LDAPv3 server, it
-must be in the LDAP URI format described in [RFC2255].
-
-
-
-
-Howes, et al.          IETF LDAPEXT Working Group               [Page 2]
-
-
-
-
-
-INTERNET-DRAFT           LDAPv3 Named Referrals               March 1999
-
-
-When returning a referral result, the server must not return the label
-portion of the labeledURI as part of the referral. Only the URI portion
-of the ref attribute should be returned.
-
-5.  Use of the ref attribute
-
-One usage of the ref attribute is defined in this document. Other uses
-of the ref attribute MAY be defined in subsequent documents, or by bila-
-teral agreement between cooperating clients and servers.
-
-Except when the manageDsaIT control (documented in section 8 of this
-document) is present in the operation request, the ref attribute is not
-visible to clients, except as its value is returned in referrals or con-
-tinuation references.
-
-If the manageDsaIT control is not set, and the entry named in a request
-contains the ref attribute, and the entry is not the root DSE, the
-server returns an LDAPResult with the resultCode field set to "referral"
-and the referral field set to contain the value(s) of the ref attribute
-minus any optional trailing whitespace and labels that might be present.
-
-If the manageDsaIT control is not set, and an entry containing the ref
-attribute is in the scope of a one level or subtree search request, the
-server returns a SearchResultReference for each such entry containing
-the value(s) of the entry's ref attribute.
-
-When the manageDsaIT control is present in a request, the server will
-treat an entry containing the ref attribute as an ordinary entry, and
-the ref attribute as an ordinary attribute, and the server will not
-return referrals or continuation references corresponding to ref attri-
-butes.
-
-The following sections detail these usages of the ref attribute.
-
-5.1.  Named reference
-
-This use of the ref attribute is to facilitate distributed name resolu-
-tion or search across multiple servers. The ref attribute appears in an
-entry named in the referencing server. The value of the ref attribute
-points to the corresponding entry maintained in the referenced server.
-
-While the distinguished name in a value of the ref attribute is typi-
-cally that of an entry in a naming context below the naming context held
-by the referencing server, it is permitted to be the distinguished name
-of any entry.  If the ref attribute is multi-valued all the DNs in the
-values of the ref attribute SHOULD have the same value.  It is the
-responsibility of clients to not loop repeatedly if a naming loop is
-present in the directory.  Administrators SHOULD avoid configuring
-
-
-
-Howes, et al.          IETF LDAPEXT Working Group               [Page 3]
-
-
-
-
-
-INTERNET-DRAFT           LDAPv3 Named Referrals               March 1999
-
-
-naming loops using referrals.
-
-Clients SHOULD perform at least simple "depth-of-referral count" loop
-detection by incrementing a counter each time a new set of referrals is
-received. Clients MAY perform more sophisticated loop detection, for
-example not chasing the same URI twice.
-
-If an entry containing the ref attribute is immediately subordinate to
-the base object named in a one level search request, then the referring
-server MUST include a scope of "base" in any LDAP URIs returned in the
-corresponding SearchResultReference.
-
-5.1.1.  Scenarios
-
-The following sections contain specifications of how the ref attribute
-should be used in different scenarios followed by examples that illus-
-trate that usage. The scenarios described consist of referral operation
-when finding a base or target object, referral operation when performing
-a one level search, and referral operation when performing a subtree
-search.
-
-It is to be noted that, in this document, a search operation is concep-
-tually divided into two distinct, sequential phases: (1) finding the
-base object where the search is to begin, and (2) performing the search
-itself. The operation of the server with respect to referrals in phase
-(1) is almost identical to the operation of the server while finding the
-target object for a non-search operation.
-
-It is to also be noted that multiple ref attributes are allowed in any
-entry and, where these sections refer to a single ref attribute, multi-
-ple ref attributes may be substituted and should be processed and
-returned as a group in an LDAPResult or search result in the same way as
-described for a single attribute. The order of the returned continuation
-references within a result is not defined.
-
-
-5.1.1.1.  Example configuration
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Howes, et al.          IETF LDAPEXT Working Group               [Page 4]
-
-
-
-
-
-INTERNET-DRAFT           LDAPv3 Named Referrals               March 1999
-
-
-       |------------------------------------------------------------|
-       |                    Server A                                |
-       | dn: o=abc,c=us                dn: o=xyz,c=us               |
-       | o: abc                        o: xyz                       |
-       | ref: ldap://hostB/o=abc,c=us  ref: ldap://hostD/o=xyz,c=us |
-       | ref: ldap://hostC/o=abc,c=us  objectclass: referral        |
-       | objectclass: referral         objectclass: extensibleObject|
-       | objectclass: extensibleObject                              |
-       |____________________________________________________________|
-
-  |---------------------| |---------------------| |---------------------|
-  |       Server B      | |       Server D      | |      Server C       |
-  | dn: o=abc,c=us      | | dn: o=xyz,c=us      | | dn: o=abc,c=us      |
-  | o: abc              | | o: xyz              | | o: abc              |
-  | other attributes... | | other attributes... | | other attributes... |
-  |_____________________| |_____________________| |_____________________|
-
-In this example, Server A holds references for two entries: "o=abc,c=us"
-and "o=xyz,c=us". For the "o=abc,c=us" entry, Server A holds two refer-
-ences, one to Server B and one to Server C.  The entries referenced are
-replicas of each other. For the "o=xyz,c=us" entry, Server A holds a
-single reference to the entry contained in Server D.
-
-In the following protocol interaction examples, the client has contacted
-Server A.  Server A holds the naming context "c=us".
-
-5.1.1.2.  Base or target object considerations
-
-As previously described, the process of generating referrals for a
-search can be described in two phases. The first, which is described in
-this section, is generating referrals based on the base object specified
-in the search. This process is identical to the process of generating
-referrals based on the target object while processing other operations
-(modify, add, delete, modify DN, and compare) with the sole exception
-that for these other operations, the DN in the referral must be modified
-in some cases.
-
-If a client requests any of these operations, there are four cases that
-the server must handle with respect to the base or target object speci-
-fied in the request.
-
-Case 1: The base or target object is not held by the server and is not
-subordinate to any object held by the server with a ref attribute.
-
-The handling of this case is described in section 6.
-
-Case 2: The base or target object is held by the server and contains a
-ref attribute
-
-
-
-Howes, et al.          IETF LDAPEXT Working Group               [Page 5]
-
-
-
-
-
-INTERNET-DRAFT           LDAPv3 Named Referrals               March 1999
-
-
-In this case, if the type of operation requested is a search or the URI
-contained in the ref attribute of the requested base object is NOT an
-LDAP URI as defined in [RFC2255], the server should return the URI value
-contained in the ref attribute of the base object whose DN is the DN
-requested by the client as the base for the operation.
-
-Example:
-
-If the client issues a search in which the base object is "o=xyz,c=us",
-server A will return
-
-        SearchResultDone "referral" {
-         ldap://hostD/o=xyz,c=us
-        }
-
-If the type of operation requested is not a search and the URI contained
-in the ref attribute of the requested target object is an LDAP URI
-[RFC2255], the server should return a modified form of this URL. The
-returned URL must have only the protocol, host, port, and trailing "/"
-portion of the URL contained in the ref attribute. The server should
-strip any dn, attributes, scope, and filter parts of the URL.
-
-Example:
-
-If the client issues a modify request for the target object of
-"o=abc,c=us", server A will return
-
-        ModifyResponse "referral" {
-         ldap://hostB/
-         ldap://hostC/
-        }
-
-Case 3: The base or target object is not held by the server, but is
-subordinate to an object with a ref attribute held by the server.
-
-
-If a client requests an operation for which the base or target object is
-not held by the server, but is subordinate to one or more objects with a
-ref attribute held by the server, the server must return the referral
-from the superior held object nearest to the requested base or target
-object. Nearest superior object with a referral, in this document, means
-an object superior to the base or target object with the DN that has the
-most attribute values in common with the DN of the base or target object
-and contains a ref attribute.
-
-The process of finding the nearest superior object can be envisioned as
-walking up the locally held part of the DIT from the requested base or
-target object checking each superior object until either an object with
-
-
-
-Howes, et al.          IETF LDAPEXT Working Group               [Page 6]
-
-
-
-
-
-INTERNET-DRAFT           LDAPv3 Named Referrals               March 1999
-
-
-a ref attribute is found or the top-most locally held object is reached.
-Once possible implementation of this algorithm is as follows:
-
-  1. Remove the leftmost attribute/value pair from the DN of the
-     requested base or target object.
-  2. If the remaining DN represents a locally held object that contains
-     a ref attribute, that object is the nearest superior object with a
-     referral. Stop and process the referral as described below.
-  3. If the remaining DN is the root of the locally held part of the
-     DIT, stop and proceed as described in section 6.
-  4. Continue with step 1.
-
-Once the nearest superior object has been identified, if the referral
-contained in that object is not an LDAP URI [RFC2255], it should be
-returned as-is.  If the referral is an LDAP URI, the referral must be
-modified, regardless of the type of operation, as case 2 describes for a
-non-search requuest. That is, the dn, attributes, scope, and filter
-parts of the URL must be stripped from the referral and the referral
-returned.
-
-Example:
-
-If the client issues an add request where the target object has a DN of
-"cn=Chris Lukas,o=abc,c=us", server A will return
-
-        AddResponse "referral" {
-         ldap://hostB/
-         ldap://hostC/
-        }
-
-
-
-
-5.1.1.3.  Search with one level scope
-
-For search operations, once the base object has been found and deter-
-mined not to contain a ref attribute, the search may progress. Any
-entries matching the filter and scope of the search that do NOT contain
-a ref attribute are returned to the client normally as described in
-[RFC2251]. Any entries matching the filter and one level scope that do
-contain a ref attribute must be returned as referrals as described here.
-
-If a matching entry contains a ref attribute and the URI contained in
-the ref attribute is NOT an LDAP URI [RFC2255], the server should return
-the URI value contained in the ref attribute of that entry in a Sear-
-chResultReference.
-
-If a matching entry contains a ref attribute in the LDAP URI syntax
-
-
-
-Howes, et al.          IETF LDAPEXT Working Group               [Page 7]
-
-
-
-
-
-INTERNET-DRAFT           LDAPv3 Named Referrals               March 1999
-
-
-[RFC2255], the URL from the ref attribute must be modified before it is
-returned by adding or substituting a "base" scope into the URL. If the
-URL does not contain a scope specifier, the "base" scope specifier must
-be added. If the URL does contain a scope specifier, the existing scope
-specifier must be replaced by the "base" scope.
-
-Example:
-
-If a client requests a one level search of "c=US" then, in addition to
-any entries one level below the "c=US" naming context matching the
-filter (shown below as "... SearchResultEntry responses ..."), the
-server will also return referrals modified to include the "base" scope
-to maintain the one level search semantics.
-
-The order of the SearchResultEntry responses and the SearchResultRefer-
-ence responses is undefined. One possible sequence is shown.
-
-        ... SearchResultEntry responses ...
-
-        SearchResultReference {
-         ldap://hostB/o=abc,c=us??base
-         ldap://hostC/o=abc,c=us??base
-        }
-
-        SearchResultReference {
-         ldap://hostD/o=xyz,c=us??base
-        }
-
-        SearchResultDone "success"
-
-
-5.1.1.4.  Search with subtree scope
-
-For a search operation with a subtree scope, once the base object has
-been found, the search progresses. As with the one level search, any
-entries matching the filter and scope of the search that do NOT contain
-a ref attribute are returned to the client normally as described in
-[RFC2251].
-
-If an entry matching the requested scope and filter contains a ref
-attribute, the server should return the URI value in a SearchResul-
-tReference.
-
-Example:
-
-If a client requests a subtree search of "c=us", then in addition to any
-entries in the "c=us" naming context which match the filter, Server A
-will also return two continuation references. As described in the
-
-
-
-Howes, et al.          IETF LDAPEXT Working Group               [Page 8]
-
-
-
-
-
-INTERNET-DRAFT           LDAPv3 Named Referrals               March 1999
-
-
-preceding section, the order of the responses is not defined.
-
-One possible response might be:
-
-        ... SearchResultEntry responses ...
-
-        SearchResultReference {
-         ldap://hostB/o=abc,c=us
-         ldap://hostC/o=abc,c=us
-        }
-
-        SearchResultReference {
-         ldap://hostD/o=xyz,c=us
-        }
-
-        SearchResultDone "success"
-
-
-6.  Superior Reference
-
-An LDAP server may be configured to return a superior reference in the
-case where the server does not hold either the requested base object or
-an object containing a ref attribute that is superior to that base
-object.
-
-An LDAP server's root DSE MAY contain a ref attribute. The values of the
-ref attribute in the root DSE that are LDAP URIs SHOULD NOT contain any
-dn part, just the host name and optional port number.
-
-If the LDAP server's root DSE contains a ref attribute and a client
-requests an object not held by the server and not subordinate to any
-held object, the server must return the URI component of the values in
-the ref attribute of the root DSE as illustrated in the example.
-
-If the LDAP server's root DSE does not contain a ref attribute, the
-server may return one or more references that the server determines via
-a method not defined in this document to be appropriate.
-
-The default reference may be to any server that might contain more
-knowledge of the namespace than the responding server. In particular,
-the client must not expect the superior reference to be identical from
-session to session as the reference may be dynamically created by the
-server based on the details of the query submitted by the client.
-
-When the server receives an operation for which the base or target entry
-of the request is not contained in or subordinate to any naming context
-held by the server or a referral entry, the server will return an
-LDAPResult with the resultCode set to "referral", and with the referral
-
-
-
-Howes, et al.          IETF LDAPEXT Working Group               [Page 9]
-
-
-
-
-
-INTERNET-DRAFT           LDAPv3 Named Referrals               March 1999
-
-
-field filled with a referral that the server has determined to be
-appropriate.
-
-Example:
-
-If a client requests a subtree search of "c=de" from server A in the
-example configuration, and server A has the following ref attribute
-defined in it's root DSE:
-
-      ref: ldap://hostG/
-
-then server A will return
-
-        SearchResultDone "referral" {
-         ldap://hostG/
-        }
-
-
-7.  The referral object class
-
-The referral object class is defined as follows.
-
-( 2.16.840.1.113730.3.2.6 NAME 'referral' SUP top STRUCTURAL
-  MAY ( ref ) )
-
-The referral object class is a subclass of top and may contain the
-referral attribute. The referral object class should, in general, be
-used in conjunction with the extensibleObject object class to support
-the naming attributes used in the entry's distinguished name.
-
-Servers must support the ref attribute through use of the referral
-object class. Any named reference must be of the referral object class
-and will likely also be of the extensibleObject object class to support
-naming and use of other attributes.
-
-8.  The manageDsaIT control
-
-A client MAY specify the following control when issuing a search, com-
-pare, add, delete, modify, or modifyDN request or an extended operation
-for which the control is defined.
-
-The control type is 2.16.840.1.113730.3.4.2.  The control SHOULD be
-marked as critical.  There is no value; the controlValue field is
-absent.
-
-This control causes entries with the "ref" attribute to be treated as
-normal entries, allowing clients to read and modify these entries.
-
-
-
-
-Howes, et al.          IETF LDAPEXT Working Group              [Page 10]
-
-
-
-
-
-INTERNET-DRAFT           LDAPv3 Named Referrals               March 1999
-
-
-This control is not needed if the entry containing the referral attri-
-bute is one used for directory administrative purposes, such as the root
-DSE, or the server change log entries.  Operations on these entries
-never cause referrals or continuation references to be returned.
-
-9.  Relationship to X.500 Knowledge References
-
-The X.500 standard defines several types of knowledge references, used
-to bind together different parts of the X.500 namespace. In X.500,
-knowledge references can be associated with a set of unnamed entries
-(e.g., a reference, associated with an entry, to a server containing the
-descendants of that entry).
-
-This creates a potential problem for LDAP clients resolving an LDAPv3
-URL referral referring to an LDAP directory back-ended by X.500.  Sup-
-pose the search is a subtree search, and that server A holds the base
-object of the search, and server B holds the descendants of the base
-object. The behavior of X.500(1993) subordinate references is that the
-base object on server A is searched, and a single continuation reference
-is returned pointing to all of the descendants held on server B.
-
-An LDAP URI only allows the base object to be specified.  It is not pos-
-sible using standard LDAP URIs to indicate a search of several entries
-whose names are not known to the server holding the superior entry.
-
-X.500 solves this problem by having two fields, one indicating the pro-
-gress of name resolution and the other indicating the target of the
-search. In the above example, name resolution would be complete by the
-time the query reached server B, indicating that it should not refer the
-request.
-
-This document does not address this problem.  This problem will be
-addressed in separate documents which define the changes to the X.500
-distribution model and LDAPv3 extensions to indicate the progress of
-name resolution.
-
-10.  Security Considerations
-
-This document defines mechanisms that can be used to "glue" LDAP (and
-other) servers together. The information used to specify this glue
-information should be protected from unauthorized modification.  If the
-server topology information itself is not public information, the infor-
-mation should be protected from unauthorized access as well.
-
-Clients should use caution when re-using credentials while following
-referrals as the client may be directed to any server which may or may
-not respect or use those credentials appropriately.
-
-
-
-
-Howes, et al.          IETF LDAPEXT Working Group              [Page 11]
-
-
-
-
-
-INTERNET-DRAFT           LDAPv3 Named Referrals               March 1999
-
-
-11.  References
-
-[RFC1738]
-    Berners-Lee, T., Masinter, L., and McCahill, M., "Uniform Resource
-    Locators (URL)", RFC 1738, CERN, Xerox Corporation, University of
-    Minnesota, December 1994.
-
-[RFC2079]
-    M. Smith, "Definition of an X.500 Attribute Type and an Object Class
-    to Hold Uniform Resource Identifiers (URIs)", RFC 2079, January
-    1997.
-
-[RFC2119]
-    S. Bradner, "Key Words for use in RFCs to Indicate Requirement Lev-
-    els", RFC 2119, March 1997. (Format: TXT=4723 bytes) (Also BCP0014)
-    (Status: BEST CURRENT PRACTICE)
-
-[RFC2251]
-    M. Wahl, T. Howes, S. Kille, "Lightweight Directory Access Protocol
-    (v3)", RFC 2251, December 1997.
-
-[RFC2255]
-    T. Howes, M. Smith, "The LDAP URL Format", RFC 2255, December, 1997.
-    (Format: TXT=20685 bytes) (Status: PROPOSED STANDARD)
-
-[X500]
-    ITU-T Rec. X.501, "The Directory: Models", 1993.
-
-12.  Author's Address
-
-Tim Howes
-Netscape Communications Corp.
-501 E. Middlefield Rd.
-Mailstop MV068
-Mountain View, CA 94043
-USA
-+1 650 937-3419
-EMail: howes@netscape.com
-
-Christopher E. Lukas
-Internet Scout Project
-Computer Sciences Dept.
-University of Wisconsin-Madison
-1210 W. Dayton St.
-Madison, WI 53706
-USA
-EMail: lukas@cs.wisc.edu
-
-
-
-
-Howes, et al.          IETF LDAPEXT Working Group              [Page 12]
-
-
-
-
-
-INTERNET-DRAFT           LDAPv3 Named Referrals               March 1999
-
-
-Michael Roszkowski
-Internet Scout Project
-Computer Sciences Dept.
-University of Wisconsin-Madison
-1210 W. Dayton St.
-Madison, WI 53706
-USA
-EMail:  mfr@cs.wisc.edu
-
-Mark C. Smith
-Netscape Communications Corp.
-501 E. Middlefield Rd.
-Mailstop MV068
-Mountain View, CA 94043
-USA
-EMail:  mcs@netscape.com
-
-Mark Wahl
-Innosoft International, Inc.
-8911 Capital of Texas Hwy #4140
-Austin TX 78759
-EMail: M.Wahl@innosoft.com
-
-
-This draft expires December 6, 1999.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Howes, et al.          IETF LDAPEXT Working Group              [Page 13]
-
-
diff --git a/doc/drafts/draft-ietf-ldapext-refer-xx.txt b/doc/drafts/draft-ietf-ldapext-refer-xx.txt
new file mode 100644 (file)
index 0000000..184e801
--- /dev/null
@@ -0,0 +1,728 @@
+IETF LDAPEXT Working Group                                Roland Hedberg
+Internet-Draft                                                 Catalogix
+Expires: January 12, 2000                                  July 12, 2000
+                                                         
+
+
+
+
+                    Referrals in LDAP Directories
+                  <draft-ietf-ldapext-refer-00.txt>
+
+
+
+
+Status of this Memo
+
+   This document is an Internet-Draft and is in full conformance with
+   all provisions of Section 10 of RFC2026.
+
+   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 January 12, 2000.
+
+Copyright Notice
+
+   Copyright (C) The Internet Society (2000). All Rights Reserved.
+                         
+
+
+
+
+
+
+
+
+
+
+
+Hedberg           Expires September 30, 2000                   [Page 1]
+
+Internet-Draft    LDAP Knowledge references                   July 2000
+
+Abstract
+
+   This document defines two reference attributes and associated "referral"
+   object class for representing generic knowledge information in LDAP
+   directories [RFC2251].
+   The attribute uses URIs [RFC1738] to represent knowledge,
+   enabling LDAP and non-LDAP services alike to be referenced.
+   The object class can be used to construct entries in an LDAP directory
+   containing references to other directories or services. This document
+   also defines procedures directory servers should follow when supporting
+   these schema elements and when responding to requests for which the
+   directory server does not contain the requested object but may contain
+   some knowledge of the location of the requested object.
+
+
+1.  Background and intended usage
+
+   The broadening of interest in LDAP directories beyond their use as front
+   ends to X.500 directories has created a need to represent knowledge
+   information in a more general way. Knowledge information is information
+   about one or more servers maintained in another server, used to link
+   servers and services together.
+                     
+   This document is based on the following basic assumptions:
+
+   - several naming domains
+   The usage of LDAP as a access protocol to other than X.500 servers has
+   created islands of directory service systems containing one or more
+   LDAP servers. Each of these islands are free to pick their own naming
+   domain. And that they also do; some use the old country,organization,
+   organizationalUnit naming scheme[X.521], some use the newer domain name
+   based naming scheme but these two are in no way the only ones in use. The
+   existence of several naming domains are in itself no real problem as
+   long as they produce unique names for the objects in the directory.
+   Still naming schemes like the domain name based one, might easily create
+   non-continues naming structures because some toplevel domain names
+   might no find organizations that are interested and/or willing
+   to manage them. Therefor tree transversal might not longer be possible
+   except in parts of the whole tree.
+      
+   - authoritive structure vs directory structure
+   In some instances even if a part of the tree is delegated to one
+   organization, the organization doing the delegation might want to
+   remain as the authority for the baseobject of the delegated tree.
+
+   - support for onelevel searches
+   At points in the tree where the responsibility for all or almost all
+   of the children of a object is delegated to different organizations
+   and resides in different directory servers a one-level search is not
+   very efficient if not supported by special facilities in the directory
+   as such.
+
+Hedberg           Expires September 30, 2000                    [Page 2]
+
+Internet-Draft    LDAP Knowledge references                   July 2000
+
+   -- directory server discovery
+   LDAP servers that do not use dc nameing or are not registered with
+   SRV records in the DNS are very hard to find.
+
+   This document defines a general method of representing knowledge
+   information in LDAP directories, based on URIs.
+   Two types of knowledge reference are defined: refer and subRefer.
+
+   The key words "MUST", "SHOULD", and "MAY" used in this document are to
+   be interpreted as described in [RFC2119].
+
+2. Knowledge references
+
+2.1 The refer attribute
+
+   ( 1.2.752.17.1.100
+     NAME 'refer'
+     DESC 'URL reference'
+     EQUALITY caseExactIA5Match
+     SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
+     USAGE distributedOperation )
+
+   The refer attribute type has IA5 syntax and is case sensitive.
+   It is multivalued. Values placed in the attribute MUST conform to the
+   specification given for the labeledURI attribute as defined in [RFC2079].
+
+   The labeledURI specification defines a format that is a URI,
+   optionally followed by whitespace and a label. This document does not
+   make use of the label portion of the syntax. Future documents MAY enable
+   new functionality by imposing additional structure on the label portion
+   of the syntax as it appears in a refer attribute.
+   If the URI contained in a refer attribute refers to an LDAP
+   server, it must be in the LDAP URI format described in [RFC2255].
+
+   When returning a referral result, the server must not return the label
+   portion of the labeledURI as part of the referral. Only the URI portion
+   of the refer attributes should be returned.
+
+   The refer attribute can be further specified by the use of options as
+   defined in section 4.1.5 of [RFC2251]. This document defines five
+   options and their use. Future documents might defined other options.
+
+   The options defined are:
+  "me", "sup", "cross", "nssr" and "sub" .
+
+   'refer;me' is used to hold the reference of this server, and is always
+   held in the root DSE
+
+   'refer;sup' is used to hold the reference of a server superior to this
+   one in this global LDAP naming domain e.g. a server holding the dc=com,
+   dc=se, or the c=se node. The 'refer;sup' is always held in the root DSE.
+
+Hedberg           Expires September 30, 2000                    [Page 3]
+
+Internet-Draft    LDAP Knowledge references                   July 2000
+
+   'refer;cross' indicates that this is a cross reference pointing to another
+   naming context within or outside this global LDAP naming domain.
+
+   'refer;sub' indicates that this is a subordinate reference pointing to
+   a subordinate naming context in this global LDAP naming domain.
+
+   'refer;nssr' indicates that this is a non-specific subordinate reference
+   pointing to a subordinate naming context in this global LDAP naming domain.
+
+
+3. Use of the knowledge attribute
+
+   Except when the manageDsaIT control (documented in section 6 of this
+   document) is present in the operation request, the refer attribute is not
+   visible to clients, except as its value is returned in referrals or con-
+   tinuation references.
+
+   If the manageDsaIT control is not set, and the entry named in a request
+   contains the refer attribute, and the entry is not the root DSE, the
+   server returns an LDAPResult with the resultCode field set to "referral"
+   and the referral field set to contain the value(s) of the refer attribute
+   minus any optional trailing whitespace and labels that might be present.
+
+   If the manageDsaIT control is not set, and an entry containing the ref
+   attribute is in the scope of a one level or subtree search request, the
+   server returns a SearchResultReference for each such entry containing
+   the value(s) of the entry's refer attribute.
+
+   When the manageDsaIT control is present in a request, the server will
+   treat an entry containing the refer attribute as an ordinary entry, and
+   the refer attribute as an ordinary attribute, and the server will not
+   return referrals or continuation references corresponding to refer
+   attributes.
+
+
+4 Behaviour specification
+
+4.1 Name resolution for any operation
+
+   Clients SHOULD perform at least simple "depth-of-referral count" loop
+   detection by incrementing a counter each time a new set of referrals is
+   received. (The maximum value for this count SHOULD be twice the number
+   of RDNs in the target object less one, to allow for ascending and
+   descending the DIT.) Clients MAY perform more sophisticated loop
+   detection, for example not chasing the same referral twice.
+
+   Case 1: The target entry is not held by the server and is
+   superior to some entry held by the server.
+
+   If the server DSE contains a "refer;sup" attribute then
+   the server will return an LDAPResult with the result code field set
+
+Hedberg           Expires September 30, 2000                    [Page 4]
+
+Internet-Draft    LDAP Knowledge references                   July 2000
+
+   to referral, and the referral field set to contain the value(s) of
+   the "refer;sup" attribute minus any optional trailing whitespace and
+   labels that might be present.
+
+   Case 2: The target entry is not held by the server and is
+   subordinate to some entry, held by the server, that contains a
+   refer attribute.
+
+   The server will return an LDAPResult with the result code field set
+   to referral, and the referral field set to contain the value(s) of
+   the refer attribute minus any optional trailing whitespace and labels
+   that might be present.
+
+   Case 3: The target entry is held by the server and contains a
+   refer attribute without the 'nssr' option.
+
+   The server will return an LDAPResult with the result code field set
+   to referral, and the referral field set to contain the value(s) of
+   the refer attribute minus any optional trailing whitespace and labels
+   that might be present.
+
+   Case 4: The target entry is not held by the server, and is not
+   subordinate or superior to any object held by the server.
+
+   If the server contains a "refer;cross" attribute
+   in the root DSE with a baseobject that is either the same or
+   superior to the target entry then
+   the server will return an LDAPResult with the result code field set
+   to referral, and the referral field set to contain the value(s) of
+   these refer attributes minus any optional trailing whitespace and labels
+   that might be present.
+
+
+4.2 Search evaluation
+
+   For search operations, once the base object has been found and
+   determined NOT to contain a refer attribute without the 'nssr'
+   option, the search may progress.
+
+4.2.1 base-level
+
+   If the entry matches the filter and does NOT contain a refer attribute
+   it will be returned to the client as described in [RFC2251].
+   If the entry matches the filter contains a refer attribute without
+   the 'nssr' option it will be returned as a referral as described here.
+
+   If a matching entry contains a refer attribute and the URI
+   contained in the refer attribute is NOT an LDAP URI [RFC2255],
+   the server should return the URI value contained in the refer
+   attribute of that entry in a SearchResultReference.
+        
+
+Hedberg           Expires September 30, 2000                    [Page 5]
+
+Internet-Draft    LDAP Knowledge references                   July 2000
+
+
+   If a matching entry contains a refer attribute in the LDAP
+   URI syntax, the server will return an SearchResultReference
+   containing the value(s) of the refer attribute minus any optional
+   trailing whitespace and labels that might be present.
+   The URL from the refer attribute must be modified before it is
+   returned by adding or substituting a "base" scope into the URL. If the
+   URL does not contain a scope specifier, the "base" scope specifier must
+   be added. If the URL does contain a scope specifier, the existing scope
+   specifier must be replaced by the "base" scope.
+
+4.2.2 One-level
+
+   Any entries matching the filter and one level scope that
+   do NOT contain a refer attribute are returned to the client normally as
+   described in [RFC2251]. Any entries matching the filter and one level
+   scope that contains a refer attribute without the 'nssr' option must
+   be returned as referrals as described here.
+
+   If a matching entry contains a refer attribute and the URI
+   contained in the refer attribute is NOT an LDAP URI [RFC2255],
+   the server should return the URI value contained in the refer
+   attribute of that entry in a SearchResultReference.
+        
+   If a matching entry contains a refer attribute in the LDAP
+   URI syntax, the server will return an SearchResultReference
+   containing the value(s) of the refer attribute minus any optional
+   trailing whitespace and labels that might be present.
+   The URL from the refer attribute must be modified before it is
+   returned by adding or substituting a "base" scope into the URL. If the
+   URL does not contain a scope specifier, the "base" scope specifier must
+   be added. If the URL does contain a scope specifier, the existing scope
+   specifier must be replaced by the "base" scope.
+
+4.2.3 Subtree search evaluation
+
+   Any entries, held by the server, matching the filter and
+   subtree scope that do NOT contain a refer attribute or contains
+   a refer attribute with the 'nssr' option are
+   returned to the client normally as described in [RFC2251].
+   Any entries matching the subtree scope and containing a refer
+   attribute must be returned as referrals as described here.
+
+   If a matching entry contains a refer attribute and the URI
+   contained in that attribute is NOT an LDAP URI [RFC2255],
+   the server should return the URI value contained in the refer
+   attribute of that entry in a SearchResultReference.
+
+
+
+
+Hedberg           Expires September 30, 2000                    [Page 6]
+
+Internet-Draft    LDAP Knowledge references                   July 2000
+
+   If a matching entry contains a refer attribute in the LDAP
+   URI syntax, the server will return an SearchResultReference
+   containing the value(s) of the refer attribute minus any
+   optional trailing whitespace and labels that might be present.
+
+   N.B. in subtree search evaluation a entry containing a 
+   refer attribut with the 'nssr' option might appear twice in the
+   result, first as a entry and then as a reference. A client
+   following all references might therefore end up with a resultset
+   containing two representations of the same entry, one from the
+   server getting the original query and one from the server 
+   that the 'nssr' reference points to.
+
+
+5. The referral object class
+
+   The referral object class is defined as follows.
+
+   ( 1.2.752.17.2.10
+     NAME 'referral'
+     SUP top
+     STRUCTURAL
+     MAY ( refer ) )
+
+   The referral object class is a subclass of top and may contain the
+   refer attribute. The referral object class should, in general,
+   be used in conjunction with the extensibleObject object class to support
+   the naming attributes used in the entry's distinguished name.
+
+   Servers must support the refer attributes through use of the
+   referral object class. Any named reference must be of the referral
+   object class and will likely also be of the extensibleObject object
+   class to support naming and use of other attributes.
+
+
+6. The manageDsaIT control
+
+   A client MAY specify the following control when issuing a search, com-
+   pare, add, delete, modify, or modifyDN request.
+
+   The control type is 2.16.840.1.113730.3.4.2.  The control SHOULD be
+   marked as critical.  There is no value; the controlValue field is
+   absent.
+
+   This control causes entries with the knowledge reference attributes to be
+   treated as normal entries, allowing clients to read and modify these entries.
+
+
+
+
+
+
+Hedberg           Expires September 30, 2000                    [Page 7]
+
+Internet-Draft    LDAP Knowledge references                   July 2000
+
+
+7. Superior Reference
+
+   This document defines two types of knowledge references that point to
+   parts of the naming context that is above of beyone the part held by a server.
+   The 'sup' option when referring to a LDAP server that holds a
+   naming context that is closer to the root of the same naming context and
+   'other' when referring to a LDAP server that holds a naming
+   context that belongs to a different naming domain then the one the
+   server belongs to.
+
+   Thus if the server receives a request for an operation where the
+   target entry is a entry closer to the root than the naming
+   context held the server and if the server holds a 'refer;sup' attribute
+   in the DSE, then the server MUST return an LDAPResult with the result
+   code field set to referral, and the referral field set to contain the
+   value(s) of the 'refer;sub' attribute minus any optional trailing
+   whitespace and labels that might be present.
+
+   On the other hand if the server receives a request for an operation
+   where the target entry is a entry that belongs to a other naming domain
+   and if there is any 'refer;other' attributes in the DSE with a base entry
+   that belongs to the same naming domain as the target entry and is
+   closer to the root then the target entry, then the server SHOULD return
+   an LDAPResult with the result code field set to referral, and the referral
+   field set to contain the value(s) of the 'refer;other' attribute minus
+   any optional trailing hitespace and labels that might be present.
+
+
+8. Security Considerations
+
+   This document defines mechanisms that can be used to "glue" LDAP (and
+   other) servers together. The information used to specify this glue
+   information should be protected from unauthorized modification.  If the
+   server topology information itself is not public information, the
+   information should be protected from unauthorized access as well.
+
+
+9. References
+
+   [RFC1738]
+    Berners-Lee, T., Masinter, L., and McCahill, M., "Uniform Resource
+    Locators (URL)", RFC 1738, CERN, Xerox Corporation, University of
+    Minnesota, December 1994,
+
+   [RFC2079]
+    M. Smith, "Definition of an X.500 Attribute Type and an Object Class
+    to Hold Uniform Resource Identifiers (URIs)", RFC 2079, January
+    1997.
+
+
+
+Hedberg           Expires September 30, 2000                    [Page 8]
+
+Internet-Draft    LDAP Knowledge references                   July 2000
+
+
+   [RFC2119]
+    S. Bradner, "Key Words for use in RFCs to Indicate Requirement Lev-
+    els", RFC 2119, March 1997. (Format: TXT=4723 bytes) (Also BCP0014)
+    (Status: BEST CURRENT PRACTICE)
+
+   [RFC2251]
+    M. Wahl, T. Howes, S. Kille, "Lightweight Directory Access Protocol
+    (v3)", RFC 2251, December 1997.  1997.
+
+   [RFC2255]
+    T. Howes, M. Smith, "The LDAP URL Format", RFC 2255, December, 1997.
+    (Format: TXT=20685 bytes) (Status: PROPOSED STANDARD)
+
+   [X500]
+    ITU-T Rec. X.501, "The Directory: Models", 1993.
+
+   [X521]
+    ITU-T Rec. X.521, "---------------------", 1993.
+
+
+12. Acknowledgements
+
+   This draft is heavily based on the previous drafts on knowledge
+   references in LDAP written by Christopher Lukas, Tim Howes,
+   Michael Roszkowski, Mark C. Smith, Mark Wahl and David Chadwick.
+   Peter Valkenburg and Henny Bekker has also made valueable
+   contributions.
+
+
+13. Authors Address
+
+   Roland Hedberg
+   Catalogix
+   Dalsveien 53
+   0775 Oslo
+   Norway
+   EMail: Roland@catalogix.se
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Hedberg           Expires September 30, 2000                    [Page 9]
+
+Internet-Draft    LDAP Knowledge references                   July 2000
+
+
+   Appendix A
+
+   Example of usage.
+   Information stored in a server.
+
+     dn:
+     objectclass: referral
+     refer;me: ldap://hostCAT/dc=cat,dc=se
+     refer;sup: ldap://hostSE/dc=se
+     refer;cross: ldap://hostNO/dc=no
+     refer;cross: ldap://hostNL/c=nl
+   
+     dn: dc=cat,dc=se
+     objectclass: domain
+     dc: cat
+   
+     dn: dc=one,dc=cat,dc=se
+     objectclass: extendedObject
+     objectclass: referral
+     refer;nssr: ldap://hostCAT1/dc=one,dc=cat,dc=se
+     ou: one
+     l: umea
+   
+     dc: dc=two,dc=cat,dc=se
+     objectclass: referral
+     objectclass: extendedObject
+     refer;sub: ldap://hostCAT2/dc=two,dc=cat,dc=se
+   
+     dn: dc=three,dc=cat,dc=se
+     objectclass: referral
+     objectclass: extendedObject
+     refer;cross: ldap://hostCAT3/dc=cat,dc=nl
+   
+     dc: dc=four,dc=cat,dc=se
+     objectclass: domain
+     objectclass: extendedObject
+     ou: four
+     l: umea
+
+
+
+
+
+
+
+
+
+
+
+
+
+Hedberg           Expires September 30, 2000                    [Page 10]
+
+Internet-Draft    LDAP Knowledge references                   July 2000
+
+
+   ==========================================
+      A number of descriptive cases
+   ==========================================
+
+   case 1: One-level search, target object on the server
+     search
+       baseobject: dc=cat,dc=se
+       scope:      onelevel
+       filter:     (objectclass=*)
+       attributes: ou
+
+     returns
+       searchResultEntry {
+         dn: dc=one,dc=cat,dc=se
+         ou: one
+       }
+       searchResultReference {
+         ldapurl: ldap://hostCAT2/dc=two,dc=cat,dc=se
+       }
+       searchResultReference {
+         ldapurl: ldap://hostCAT3/dc=cat,dc=nl
+       }
+       searchResultEntry {
+         dn: dc=four,dc=cat,dc=se
+         ou: four
+       }
+       searchResultDone {
+         resultCode: success
+       }
+
+   case 2: Subtree search, target object on the server
+     search
+       baseobject: dc=cat,dc=se
+       scope:      subtree
+       filter:     (objectclass=*)
+       attributes: ou
+   
+     returns
+       searchResultEntry {
+         dn: dc=one,dc=cat,dc=se
+         ou: one
+       }
+       searchResultReference {
+         ldapurl: ldap://hostCAT1/dc=one,dc=cat,dc=se
+       }
+       searchResultReference {
+         ldapurl: ldap://hostCAT2/dc=two,dc=cat,dc=se
+       }
+
+
+
+Hedberg           Expires September 30, 2000                  [Page 11]
+
+Internet-Draft    LDAP Knowledge references                   July 2000
+
+
+       searchResultReference {
+         ldapurl: ldap://hostCAT3/dc=cat,dc=nl
+       }
+       searchResultEntry {
+         dn: dc=four,dc=cat,dc=se
+         ou: four
+       }
+       searchResultDone {
+         resultCode: success
+       }
+
+   case 3: base search, target entry contains a 'refer;nssr' attribute
+     search
+       baseobject: dc=one,dc=cat,dc=se
+       scope:      base
+       filter:     (objectclass=*)
+       attributes: ou
+   
+     returns
+       searchResultEntry {
+         dn: dc=one,dc=cat,dc=se
+         ou: four
+       }
+       searchResultDone {
+         resultCode: success
+       }
+
+   case 4: base search, target entry contains a 'refer;sub' attribute
+     search
+       baseobject: dc=two,dc=cat,dc=se
+       scope:      base
+       filter:     (objectclass=*)
+       attributes: ou
+
+     returns
+       searchResultDone {
+         resultCode: referral
+         matchedDN: dc=two,dc=cat,dc=se
+         referral: ldap://hostCAT2/dc=two,dc=cat,dc=se
+       }
+
+
+
+
+
+
+
+
+
+
+
+Hedberg           Expires September 30, 2000                    [Page 12]
+
+Internet-Draft    LDAP Knowledge references                   July 2000
+
+
+  case 5: one-level search, target entry contains a 'refer;nssr' attribute
+     search
+       baseobject: dc=one,dc=cat,dc=se
+       scope:      onelevel
+       filter:     (objectclass=*)
+       attributes: ou
+   
+       searchResultDone {
+         resultCode: referral
+         matchedDN: dc=one,dc=cat,dc=se
+         referral: ldap://hostCAT1/dc=one,dc=cat,dc=nu
+       }
+   
+  case 6: Search on area above the baseobject of the server
+     search
+       baseobject: dc=pi,dc=se
+       scope:      subtree
+       filter:     (objectclass=*)
+       attributes: ou
+   
+     returns
+       searchResultDone {
+         resultCode: referral
+         matchedDN:  dc=se
+         referral:   ldap://hostSE/dc=se
+      }
+
+
+
+  case 7: Search on area beyond, but not below the baseobject
+        of the server
+     search
+       baseobject: o=surfnet,c=nl
+       scope:      base
+       filter:     (objectclass=*)
+   
+     returns
+       searchResultDone {
+         resultCode: referral
+         matchedDN:  c=nl
+         referral:   ldap://hostNL/c=NL
+       }
+
+
+
+
+
+
+
+
+
+Hedberg           Expires September 30, 2000                    [Page 13]
+
index f715b9464c3e61dd4ee3db8226886bf4ecd445af..aa8306bf4a8a6994effbbd97301858f93ddc7c56 100644 (file)
-INTERNET-DRAFT
-draft-ietf-ldup-subentry-01.txt
-                                                               Ed Reed
-                                                          Novell, Inc.
-                                                       August 29, 1999
 
-                         LDAP Subentry Schema
 
 
-1. Status of this Memo
 
-This document is an Internet-Draft and is in full conformance with all
-provisions of Section 10 of RFC2026.
 
-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."
+INTERNET-DRAFT 
+draft-ietf-ldup-subentry-03.txt 
+                                                    Ed Reed 
+                                        Reed-Matthews, Inc. 
+                                              July 13, 2000 
+                                                            
+LDAP Subentry Schema 
 
-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.
+1. Status of this Memo 
 
-This Internet-Draft expires on February 29, 1999.
+This document is an Internet-Draft and is in full 
+conformance with all provisions of Section 10 of RFC2026. 
+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 expires on January 13, 2001. 
 
 
-2. Abstract
+2. Abstract 
 
-This document describes an object class called ldapSubEntry which MAY
-be used to indicate operations and management related entries in the
-directory, called LDAP Subentries.  This version of this document is
-updated with an assigned OID for the ldapSubEntry object class.
+This document describes an object class called ldapSubEntry 
+which MAY be used to indicate operations and management 
+related entries in the directory, called LDAP Subentries.  
+This version of this document is updated with an assigned 
+OID for the ldapSubEntry object class. 
 
-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 RFC 2119 [RFC2119]. The
-sections below reiterate these definitions and include some additional
-ones.
+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 RFC 2119 [RFC2119]. The sections below 
+reiterate these definitions and include some additional 
+ones. 
 
 
+Reed .                                                       [Page 1] 
+                       Expires January 13, 2001 \f
 
 
+INTERNET-DRAFT                                           13 July 2000 
+                   LDAP Subentry Schema 
 
+3. Definition 
 
-Reed                                                         [Page 1]
-                      Expires February 29, 2000\f
 
+3.1 ldapSubEntry Class 
 
-INTERNET-DRAFT                                         29 August 1999
-                         LDAP Subentry Schema
+( 2.16.840.1.113719.2.142.6.1.1 NAME 'ldapSubEntry'  
+   DESC 'LDAP Subentry class, version 1'  
+     SUP top STRUCTURAL  
+     MAY ( cn ) )  
 
-3. Definition
+The class ldapSubEntry is intended to be used as a super- 
+class when defining other structural classes to be used 
+as LDAP Subentries, and as the structural class to which 
+Auxiliary classes may be added for application specific 
+subentry information.  Where possible, the use of Auxiliary 
+classes to extend ldapSubEntries is strongly preferred. 
+The presence of ldapSubEntry in the list of super-classes 
+of an entry in the directory makes that entry an LDAP 
+Subentry.  Object classes derived from ldapSubEntry are 
+themselves considered ldapSubEntry classes, for the purpose 
+of this discussion. 
 
+LDAP Subentries MAY be named by their commonName attribute 
+[LDAPv3].  Other naming attributes are also permitted. 
 
-3.1 ldapSubEntry Class
+LDAP Subentries MAY be containers, unlike their [X.501] 
+counterparts. 
 
-( 2.16.840.1.113719.2.142.6.1.1 NAME 'ldapSubEntry'
-   DESC 'LDAP Subentry class, version 1'
-     SUP top STRUCTURAL
-     MUST ( cn ) )
+LDAP Subentries MAY be contained by, and will usually be 
+located in the directory information tree immediately 
+subordinate to, administrative points and/or naming 
+contexts.  Further (unlike X.500 subentries), LDAP 
+Subentries MAY be contained by other LDAP Subentries (the 
+way organizational units may be contained by other 
+organizational units).  Deep nestings of LDAP Subentries 
+are discouraged, but not prohibited. 
+
+LDAP Subentries SHOULD be treated as "operational objects" 
+in much the same way that "operational attributes" are not 
+regularly provided in search results and read operations 
+when only user attributes are requested).    
+
+LDAP servers SHOULD implement the following special 
+handling of ldapSubEntry entries: 
+
+a) search operations which include a matching criteria 
+"objectclass=ldapSubEntry" MUST include entries derived 
+
+Reed .                                                       [Page 2] 
+                       Expires January 13, 2001 
\f
+
+
+INTERNET-DRAFT                                           13 July 2000 
+                   LDAP Subentry Schema 
+
+from the ldapSubEntry class in the scope of their 
+operations;   
+
+b) search operations which do not include a matching 
+criteria "objectclass=ldapSubEntry" MUST IGNORE entries 
+derived from the ldapSubEntry class, and exclude them from 
+the scope of their operations. 
+
+The combination of SHOULD and MUST in the special handling 
+instructions, above, are meant to convey this:  Servers 
+SHOULD support this special handling, and if they do they 
+MUST do it as described, and not some other way. 
 
-The class ldapSubEntry is intended to be used as a super class when
-defining other structural classes to be used as LDAP Subentries.  The
-presence of ldapSubEntry in the list of super-classes of an entry in
-the directory makes that entry an LDAP Subentry.  Object classes
-derived from ldapSubEntry are themselves considered ldapSubEntry
-classes, for the purpose of this discussion.
 
-LDAP Subentries MAY be named by their commonName attribute [LDAPv3].
-Other naming attributes are also permitted.
 
-LDAP Subentries MAY be containers, unlike their [X.501] counterparts.
+4. Security Considerations 
 
-LDAP Subentries MAY be contained by, and will usually be located in
-the directory information tree immediately subordinate to,
-administrative points and/or naming contexts [LDUPINFO].  Further
-(unlike X.500 subentries), LDAP Subentries MAY be contained by other
-LDAP Subentries (the way organizational units may be contained by
-other organizational units).  Deep nestings of LDAP Subentries are
-discouraged, but not prohibited.
+LDAP Subentries will frequently be used to hold data which 
+reflects either the actual or intended behavior of the 
+directory service.  As such, permission to read such 
+entries MAY need to be restricted to authorized users.  
+More importantly, IF a directory service treats the 
+information in an LDAP Subentry as the authoritative source 
+of policy to be used to control the behavior of the 
+directory, then permission to create, modify, or delete 
+such entries MUST be carefully restricted to authorized 
+administrators. 
 
-LDAP Subentries SHOULD be treated as "operational objects" in much the
-same way that "operational attributes" are not regularly provided in
-search results and read operations when only user attributes are
-requested).
 
-LDAP servers SHOULD implement the following special handling of
-ldapSubEntry entries:
 
-a) search operations which include a matching criteria
-"objectclass=ldapSubEntry" MUST include entries derived from the
-ldapSubEntry class in the scope of their operations;
+5. References 
+
+[LDAPv3] S. Kille, M. Wahl, and T. Howes, "Lightweight 
+Directory Access Protocol (v3)", RFC 2251, December 1997 
+
+[X.501] ITU-T Rec. X.501, "The Directory: Models", 1993 
+
 
-b) search operations which do not include a matching criteria
-"objectclass=ldapSubEntry" MUST IGNORE entries derived from the
-ldapSubEntry class, and exclude them from the scope of their
-operations.
 
+6. Copyright Notice 
 
+Copyright (C) The Internet Society (1999). All Rights 
+Reserved.  
+This document and translations of it may be copied and 
+furnished to others, and derivative works that comment on 
+or otherwise explain it or assist in its implementation may 
+be prepared, copied, published and distributed, in whole or 
 
-Reed                                                         [Page 2]
-                      Expires February 29, 2000\f
+Reed .                                                       [Page 3] 
+                       Expires January 13, 2001 
\f
 
 
-INTERNET-DRAFT                                         29 August 1999
-                         LDAP Subentry Schema
+INTERNET-DRAFT                                           13 July 2000 
+                   LDAP Subentry Schema 
 
-The combination of SHOULD and MUST in the special handling
-instructions, above, are meant to convey this:  Servers SHOULD support
-this special handling, and if they do they MUST do it as described,
-and not some other way.
+in part, without restriction of any kind, provided that the 
+above copyright notice and this paragraph are included on 
+all such copies and derivative works. However, this 
+document itself may not be modified in any way, such as by 
+removing the copyright notice or references to the Internet 
+Society or other Internet organizations, except as needed 
+for the purpose of developing Internet standards in which 
+case the procedures for copyrights defined in the Internet 
+Standards process must be followed, or as required to 
+translate it into languages other than English. 
+The limited permissions granted above are perpetual and 
+will not be revoked by the Internet Society or its 
+successors or assigns. 
+This document and the information contained herein is 
+provided on an "AS IS" basis and THE INTERNET SOCIETY AND 
+THE INTERNET ENGINEERING TASK FORCE DISCLAIMS 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." 
 
 
+7. Acknowledgements 
 
-4. Security Considerations
+The use of subEntry object class to store Replica and 
+Replication Agreement information is due primarily to the 
+lucid explanation by Mark Wahl, Innosoft, of how they could 
+be used and extended. 
+The IETF takes no position regarding the validity or scope 
+of any intellectual property 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; neither does it represent that it has made any 
+effort to identify any such rights. Information on the 
+IETF's procedures with respect to rights in standards-track 
+and standards-related documentation can be found in BCP-11. 
+Copies of claims of rights made available for publication 
+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 
+implementors or users of this specification can be obtained 
+from the IETF Secretariat. 
 
-LDAP Subentries will frequently be used to hold data which reflects
-either the actual or intended behavior of the directory service.  As
-such, permission to read such entries MAY need to be restricted to
-authorized users.  More importantly, IF a directory service treats the
-information in an LDAP Subentry as the authoritative source of policy
-to be used to control the behavior of the directory, then permission
-to create, modify, or delete such entries MUST be carefully restricted
-to authorized administrators.
 
+Reed .                                                       [Page 4] 
+                       Expires January 13, 2001 
\f
 
 
-5. References
+INTERNET-DRAFT                                           13 July 2000 
+                   LDAP Subentry Schema 
 
-[LDUPINFO] _ E. Reed, "LDUP Replication Information Model", draft-
-ietf-ldup-infomod-01.txt
+The IETF invites any interested party to bring to its 
+attention any copyrights, patents or patent applications, 
+or other proprietary rights which may cover technology that 
+may be required to practice this standard. Please address 
+the information to the IETF Executive Director. 
 
-[LDAPv3] S. Kille, M. Wahl, and T. Howes, "Lightweight Directory
-Access Protocol (v3)", RFC 2251, December 1997
 
-[X.501] ITU-T Rec. X.501, "The Directory: Models", 1993
+8. Author's Address 
 
+     Edwards E. Reed 
+     Reed-Matthews, Inc. 
+     1064 E 140 North 
+     Lindon, UT  84042 
+     USA 
+     E-mail: eer@oncalldba.com  
+      
+     LDUP Mailing List: ietf-ldup@imc.org  
+     LDAPEXT Mailing List: ietf-ldapext@netscape.com 
 
 
-6. Copyright Notice
 
-Copyright (C) The Internet Society (1999). All Rights Reserved.
 
-This document and translations of it may be copied and furnished to
-others, and derivative works that comment on or otherwise explain it
-or assist in its implementation may be prepared, copied, published and
-distributed, in whole or in part, without restriction of any kind,
-provided that the above copyright notice and this paragraph are
-included on all such copies and derivative works. However, this
-document itself may not be modified in any way, such as by removing
-the copyright notice or references to the Internet Society or other
-Internet organizations, except as needed for the purpose of developing
-Internet standards in which case the procedures for copyrights defined
-in the Internet Standards process must be followed, or as required to
-translate it into languages other than English.
 
-Reed                                                         [Page 3]
-                      Expires February 29, 2000\f
 
 
-INTERNET-DRAFT                                         29 August 1999
-                         LDAP Subentry Schema
 
 
-The limited permissions granted above are perpetual and will not be
-revoked by the Internet Society or its successors or assigns.
 
-This document and the information contained herein is provided on an
-"AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
-TASK FORCE DISCLAIMS 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."
 
 
-7. Acknowledgements
 
-The use of subEntry object class to store Replica and Replication
-Agreement information is due primarily to the lucid explanation by
-Mark Wahl, Innosoft, of how they could be used and extended.
 
-The IETF takes no position regarding the validity or scope of any
-intellectual property 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; neither does it represent that it has made any
-effort to identify any such rights. Information on the IETF's
-procedures with respect to rights in standards-track and standards-
-related documentation can be found in BCP-11. Copies of claims of
-rights made available for publication 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 implementors or users of this specification can be obtained from
-the IETF Secretariat.
 
-The IETF invites any interested party to bring to its attention any
-copyrights, patents or patent applications, or other proprietary
-rights which may cover technology that may be required to practice
-this standard. Please address the information to the IETF Executive
-Director.
 
 
-8. Author's Address
 
-     Edwards E. Reed
-     Novell, Inc.
-     122 E 1700 S
-     Provo, UT   84606
-     USA
-     E-mail: Ed_Reed@Novell.com
 
 
-Reed                                                         [Page 4]
-                      Expires February 29, 2000\f
 
 
-INTERNET-DRAFT                                         29 August 1999
-                         LDAP Subentry Schema
 
-     LDUP Mailing List: ietf-ldup@imc.org
 
 
 
@@ -232,45 +281,6 @@ INTERNET-DRAFT                                         29 August 1999
 
 
 
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Reed                                                         [Page 5]
-                      Expires February 29, 2000\f
+Reed .                                                       [Page 5] 
+                       Expires January 13, 2001 
\f
index 91f24cfadb093ed70a85fc767cada60d096291cc..cb49fddafb1277454bcfc7ba88e6d08a967b9e8f 100644 (file)
@@ -1,13 +1,19 @@
+
+
+
+
+
+
 INTERNET-DRAFT                                                S. Legg
-draft-ietf-ldup-urp-02.txt                                    Telstra
+draft-ietf-ldup-urp-03.txt                        Adacel Technologies
                                                              A. Payne
-                                               PricewaterhouseCoopers
-                                                     October 22, 1999
+                                                              Telstra
+                                                        June 29, 2000
 
 
                  LDUP Update Reconciliation Procedures
 
-    Copyright (C) The Internet Society (1999). All Rights Reserved.
+    Copyright (C) The Internet Society (2000). All Rights Reserved.
 
    Status of this Memo
 
@@ -35,27 +41,26 @@ draft-ietf-ldup-urp-02.txt                                    Telstra
    of this document is unlimited.  Comments should be sent to the LDUP
    Replication mailing list <ldup@imc.org> or to the authors.
 
-   This Internet-Draft expires on 22 April 2000.
+   This Internet-Draft expires on 29 December 2000.
 
    1. Abstract
 
-   This document describes the procedures used by directory servers to
-   reconcile updates performed by autonomously operating directory
-   servers in a distributed, replicated directory service.
-
-
-
-
+   This document describes the procedures used by LDAP [LDAPv3] or X.500
+   [X500] directory servers to reconcile updates performed by
+   autonomously operating directory servers in a distributed, replicated
+   directory service.
 
+   The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
+   "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and  "OPTIONAL" in this
 
 
-Legg & Payne             Expires 22 April 2000                  [Page 1]
 
+Legg & Payne            Expires 29 December 2000                [Page 1]
+\f
+INTERNET-DRAFT   LDUP Update Reconciliation Procedures     June 29, 2000
 
 
-
-
-INTERNET-DRAFT   LDUP Update Reconciliation Procedures  October 22, 1999
+   document are to be interpreted as described in RFC 2119 [RFC2119].
 
 
    2. Table of Contents
@@ -71,196 +76,189 @@ INTERNET-DRAFT   LDUP Update Reconciliation Procedures  October 22, 1999
    5. Replication Procedures                                            6
    5.1  Processing LDAP, DAP or DSP Operations on the DIT               6
    5.1.1  Add Entry                                                     7
-   5.1.2  Remove Entry                                                  7
-   5.1.3  Modify Entry                                                  7
-   5.1.4  Modify DN                                                     9
-   5.2  Generating Replication Primitives                               9
-   5.3  Processing Replication Primitives on the DIT                   11
-   5.3.1  Saving Deletion Records                                      12
-   5.3.2  Glue Entries                                                 13
-   5.3.3  Generating Change Sequence Numbers                           13
-   5.3.4  Comparison of Attribute Values                               14
-   5.3.5  Entry Naming                                                 14
-   5.3.6  Processing Add Attribute Value Primitive                     17
-   5.3.7  Processing Remove Attribute Value Primitive                  17
-   5.3.8  Processing Remove Attribute Primitive                        19
-   5.3.9  Processing Add Entry Primitive                               19
-   5.3.10  Processing Remove Entry Primitive                           20
-   5.3.11  Processing Move Entry Primitive                             21
-   5.3.12  Processing Rename Entry Primitive                           22
-   6. Security Considerations                                          23
-   7. Acknowledgements                                                 23
-   8. References                                                       23
-   9. Intellectual Property Notice                                     23
-   10. Copyright Notice                                                24
-   11. Authors' Address                                                25
-   12. Appendix A - Changes From Previous Drafts                       25
-   12.1 Changes in Draft 01                                            25
-   12.2 Changes in Draft 02                                            26
-   13. Appendix B - Open Issues                                        26
+   5.1.2  Remove Entry                                                  8
+   5.1.3  Modify Entry                                                  8
+   5.1.4  Modify DN                                                    10
+   5.2  Generating Replication Primitives                              10
+   5.3  Processing Replication Primitives on the DIT                   12
+   5.3.1  Saving Deletion Records                                      13
+   5.3.2  Glue Entries                                                 14
+   5.3.3  Generating Change Sequence Numbers                           14
+   5.3.4  Comparison of Attribute Values                               15
+   5.3.5  Entry Naming                                                 15
+   5.3.6  Processing Add Attribute Value Primitive                     18
+   5.3.7  Processing Remove Attribute Value Primitive                  19
+   5.3.8  Processing Remove Attribute Primitive                        20
+   5.3.9  Processing Add Entry Primitive                               20
+   5.3.10  Processing Remove Entry Primitive                           21
+   5.3.11  Processing Move Entry Primitive                             22
+   5.3.12  Processing Rename Entry Primitive                           23
+   6. Security Considerations                                          24
+   7. Acknowledgements                                                 25
+   8. References                                                       25
+   9. Intellectual Property Notice                                     26
+   10. Copyright Notice                                                26
+   11. Authors' Addresses                                              27
 
 
    3. Introduction
 
-   Each DAP, LDAP or DSP operation successfully performed by a DSA is
-   subsequently reported to other DSAs with which it has a replication
-   agreement as a set of one or more simple timestamped replication
-   primitives.  These primitives reflect the intended final state of an
-
-
-
-Legg & Payne             Expires 22 April 2000                  [Page 2]
+   Each DAP, LDAP or DSP operation successfully performed by a directory
+   server is subsequently reported to other directory servers with which
+   it has a replication agreement as a set of one or more simple
+   timestamped replication primitives.  These primitives reflect the
+   intended final state of an update operation rather than the specific
 
 
 
+Legg & Payne            Expires 29 December 2000                [Page 2]
+\f
+INTERNET-DRAFT   LDUP Update Reconciliation Procedures     June 29, 2000
 
 
-INTERNET-DRAFT   LDUP Update Reconciliation Procedures  October 22, 1999
+   changes required to achieve that state.
 
+   A directory server will receive replication primitives from its
+   various agreement partners according to the agreement schedules.
+   Those primitives MUST be reconciled with the current directory server
+   contents.  In broad outline, received replication primitives are
+   compared to the timestamp information associated with the directory
+   data item being operated on.  If the primitive has a more recent
+   timestamp a change in the directory contents is made (which may
+   involve only the revision of the timestamp).  If the directory server
+   has other replication agreements then the change will be reflected in
+   primitives sent during replication sessions for those other
+   agreements.  If the primitive has an older timestamp it is no longer
+   relevant and is simply ignored.
 
-   update operation rather than the specific changes required to achieve
-   that state.
-
-   A DSA will receive replication primitives from its various agreement
-   partners according to the agreement schedules. Those primitives must
-   be reconciled with the current DSA contents.  In broad outline,
-   received replication primitives are compared to the timestamp
-   information associated with the directory data item being operated
-   on. If the primitive has a more recent timestamp a change in the
-   directory contents is made (which may involve only the revision of
-   the timestamp). If the DSA has other replication agreements then the
-   change will be reflected in primitives sent during replication
-   sessions for those other agreements.  If the primitive has an older
-   timestamp it is no longer relevant and is simply ignored.
-
-   The update reconciliation procedures are designed to produce a
-   consistent outcome at all participating DSAs regardless of the order
-   in which the primitives are received. The primitives can also be
-   safely replayed in the event that an exchange of replication
-   information with another DSA is interrupted. This greatly simplifies
-   the recovery mechanisms required in the replication protocol.
+   The Update Reconciliation Procedures are designed to produce a
+   consistent outcome at all participating directory servers regardless
+   of the order in which the primitives are received and processed.  The
+   primitives can also be safely replayed in the event that an exchange
+   of replication information with another directory server is
+   interrupted.  This greatly simplifies the recovery mechanisms
+   required in the replication protocol.
 
    4. Model Extensions
 
    This section describes the extensions to the data model required to
-   effect multiple master replication.
+   effect multi-master replication.
 
    4.1 Unique Identifier
 
    A Unique Identifier is associated with each entry in the global DIT.
-   This Unique Identifier must be globally unique for all time in the
-   Directory. This can be achieved by defining a unique DSA prefix for
-   each DSA and then ensuring that the suffix of the Unique Identifier
-   is locally unique.
+   This Unique Identifier MUST be globally unique for all time in the
+   Directory.  This can be achieved by defining a unique prefix for each
+   directory server and then ensuring that the suffix of the Unique
+   Identifier is locally unique.
+
+   The Unique Identifier for an entry is held in the entryUUID
+   operational attribute.
 
-   Some pre-allocated global Unique Identifier values will be used to
+   Some pre-allocated global Unique Identifier values are used to
    indicate the X.500 global root entry, and the Lost & Found entry (see
    Section 4.4).
 
    4.2 Timestamps & Existence
 
    The timestamp for a replication primitive or directory data item is
-   in the form of a Change Sequence Number (CSN). The components of the
+   in the form of a Change Sequence Number (CSN).  The components of the
    CSN are, from most significant to least significant, a time in
-   seconds, a change count, a Replica Identifier and a modification
-   number.  Notionally a CSN is associated with an entry's Relative
-   Distinguished Name (the Name CSN), the reference to its superior
-   entry (the Parent CSN) and each of its attribute values (including
-
-
-
-Legg & Payne             Expires 22 April 2000                  [Page 3]
 
 
 
+Legg & Payne            Expires 29 December 2000                [Page 3]
+\f
+INTERNET-DRAFT   LDUP Update Reconciliation Procedures     June 29, 2000
 
 
-INTERNET-DRAFT   LDUP Update Reconciliation Procedures  October 22, 1999
-
-
-   the distinguished values), to record the time of the most recent
-   action on that part of the entry.
+   seconds, a change count, a Replica Identifier and a modification
+   number.  Notionally a CSN is associated with an entry's Relative
+   Distinguished Name (the Name CSN), the reference to its superior
+   entry (the Parent CSN) and each of its attribute values (including
+   the distinguished values and operational attribute values), to record
+   the time of the most recent action on that part of the entry.
 
    The entry itself has a CSN (the Entry CSN) asserting the most recent
    time at which the entry was added.  An entry is permitted to be
-   removed and then re-added at one or more DSAs.  In this context re-
-   adding an entry means reusing the Unique Identifier of a removed
-   entry and does not refer to the case of reusing the RDN of a removed
-   entry. The reuse of a Unique Identifier can arise by the explicit
-   action of a directory administrator to restore an entry that was
-   mistakenly removed.  The mechanism by which an administrator adds an
-   entry with a reused Unique Identifier is outside the scope of the
+   removed and then re-added at one or more directory servers.  In this
+   context re-adding an entry means reusing the Unique Identifier of a
+   removed entry and does not refer to the case of reusing the RDN of a
+   removed entry.  The reuse of a Unique Identifier can arise by the
+   explicit action of a directory administrator to restore an entry that
+   was mistakenly removed.  The mechanism by which an administrator adds
+   an entry with a reused Unique Identifier is outside the scope of the
    X.500 and LDAP standards since the Unique Identifier of an entry is
-   not a user modifiable attribute. Note that from the perspective of a
-   consumer DSA of a partial area of replication an entry may appear to
-   be removed and added several times because modifications to the entry
-   change whether the entry satisfies the replication agreement
-   specification for the area of replication.
+   not a user modifiable attribute.  Note that from the perspective of a
+   consumer directory server of a partial area of replication, an entry
+   may appear to be removed and added several times because
+   modifications to the entry change whether the entry satisfies the
+   replication agreement specification for the area of replication.
 
    Additionally, a deletion record is kept for each of the recently
-   deleted entries, attributes, or attribute values. The deletion record
-   contains a CSN and asserts that the associated directory object no
-   longer existed at the particular time.
+   deleted entries (entry deletion records), attributes (attribute
+   deletion records), or attribute values (value deletion records).  A
+   deletion record contains a CSN and asserts that the associated
+   directory object no longer existed at the particular time.
 
    4.3 Replication Primitives
 
    Each update operation performed on an entry in a part of the DIT
-   subject to one or more replication agreements must be subsequently
-   reported as replication primitives to the replication partner DSAs of
-   those agreements.  The collection of primitives sent by a DSA to a
-   replication partner may reflect both the results of locally processed
-   user update requests and also of replicated updates received from
-   other DSAs.  A single update operation will decompose in one or more
-   primitives.
+   subject to one or more replication agreements MUST be subsequently
+   reported as replication primitives to the replication partner
+   directory servers of those agreements.  The collection of primitives
+   sent by a directory server to a replication partner will reflect both
+   the results of locally processed user update requests and also of
+   replicated updates received from other directory servers.  A single
+   update operation will decompose into one or more primitives.
 
    Common to all update primitives is an entry identifier argument, uid,
    containing the Unique Identifier of the target entry of the change,
    and a CSN argument, csn, to indicate the time of the change.  In the
    case of adding a new entry, the Unique Identifier for the entry is
-   allocated by the DSA in the course of processing the operation.
-   Additional arguments are present depending on the type of replication
-   primitive.
-
-   The p-add-entry(uid, csn, superior, rdn) primitive is used to add a
-   new entry with minimal contents.  The superior argument contains the
-   Unique Identifier of the immediate superior entry of the added entry.
-   The rdn argument contains the Relative Distinguished Name of the
-   added entry.
-
-
-
-Legg & Payne             Expires 22 April 2000                  [Page 4]
+   allocated by the directory server in the course of processing the
+   operation.  Additional arguments are present depending on the type of
+   replication primitive.
 
 
 
 
+Legg & Payne            Expires 29 December 2000                [Page 4]
+\f
+INTERNET-DRAFT   LDUP Update Reconciliation Procedures     June 29, 2000
 
-INTERNET-DRAFT   LDUP Update Reconciliation Procedures  October 22, 1999
 
+   The p-add-entry(uid, csn, superior, rdn) primitive is used to
+   describe the addition of a new entry with minimal contents.  The
+   superior argument contains the Unique Identifier of the immediate
+   superior entry of the added entry.  The rdn argument contains the
+   Relative Distinguished Name of the added entry.
 
-   The p-move-entry(uid, csn, superior) primitive is used to change the
-   immediate superior of an entry.  The superior argument contains the
-   Unique Identifier of the new superior entry.
+   The p-move-entry(uid, csn, superior) primitive is used to describe
+   the moving of an entry to a new immediate superior in the DIT.  The
+   superior argument contains the Unique Identifier of the new superior
+   entry.
 
-   The p-rename-entry(uid, csn, rdn) primitive is used to change the
-   Relative Distinguished Name of an entry.  The rdn argument contains
-   the new RDN for the entry.
+   The p-rename-entry(uid, csn, rdn) primitive is used to describe a
+   change to the Relative Distinguished Name of an entry.  The rdn
+   argument contains the new RDN for the entry.
 
-   The p-remove-entry(uid, csn) primitive is used to remove an entry.
+   The p-remove-entry(uid, csn) primitive is used to describe the
+   removal of an entry.
 
    The p-add-attribute-value(uid, csn, type, value) primitive is used to
-   add a single attribute value to an entry.  The type argument contains
-   the attribute type of the value and the value argument contains the
-   attribute value.
+   describe the addition of a single attribute value to an entry.  The
+   type argument contains the attribute type of the value and the value
+   argument contains the attribute value.
 
    The p-remove-attribute-value(uid, csn, type, value) primitive is used
-   to remove a single attribute value from an entry.  The type argument
-   contains the attribute type of the value and the value argument
-   contains the attribute value.
+   to describe the removal of a single attribute value from an entry.
+   The type argument contains the attribute type of the value and the
+   value argument contains the attribute value.
 
-   The p-remove-attribute(uid, csn, type) primitive is used to remove
-   all values of an attribute from an entry.  The type argument contains
-   the attribute type to be removed.
+   The p-remove-attribute(uid, csn, type) primitive is used to describe
+   the removal of all values of an attribute from an entry.  The type
+   argument contains the removed attribute type.
 
    These primitives reflect the intended final state of an update
    operation rather than the specific changes required to achieve that
@@ -268,45 +266,41 @@ INTERNET-DRAFT   LDUP Update Reconciliation Procedures  October 22, 1999
 
    4.4 Lost & Found
 
-   Each connected set of mastering DSAs have a Lost & Found entry
-   nominated. As a result of conflicting updates at two or more master
-   DSAs, an entry may be left with a reference to a non-existent
-   superior entry.  Such an entry is called an orphaned entry. When this
-   situation arises, the DSA creates a glue entry for the missing
-   superior entry. This glue entry is made a subordinate of the Lost &
-   Found entry and the orphaned entry becomes a subordinate of the glue
-   superior entry (see Section 5.3.2).  Entries that exist in the Lost &
-   Found subtree may still be modified by actions of the replication
-   protocol since entries are identified by Unique Identifiers in the
-   protocol, independent of their positioning in the global DIT.
-
-   Entries will also be explicitly moved to become immediate
-   subordinates of the Lost & Found entry to prevent the formation of a
-   loop in the superior-subordinate relationships in the DIT. This
-   situation can only arise through conflicting move entry operations at
-   two or more master DSAs.
-
-
-
+   As a result of conflicting updates at two or more master directory
+   servers, an entry may be left with a reference to a non-existent
+   superior entry.  Such an entry is called an orphaned entry.  When
+   this situation arises, the directory server creates a glue entry for
+   the missing superior entry.  This glue entry is made a subordinate of
+   the specially nominated Lost & Found entry and the orphaned entry
+   becomes a subordinate of the glue superior entry (see Section 5.3.2).
+   Entries that exist in the Lost & Found subtree can still be modified
+   by actions of the replication protocol since entries are identified
+   by Unique Identifiers in the protocol, independent of their
 
-Legg & Payne             Expires 22 April 2000                  [Page 5]
 
 
+Legg & Payne            Expires 29 December 2000                [Page 5]
+\f
+INTERNET-DRAFT   LDUP Update Reconciliation Procedures     June 29, 2000
 
 
+   positioning in the global DIT.
 
-INTERNET-DRAFT   LDUP Update Reconciliation Procedures  October 22, 1999
-
+   Entries will also be explicitly moved to become immediate
+   subordinates of the Lost & Found entry to prevent the formation of a
+   loop in the superior-subordinate relationships in the DIT.  This
+   situation can only arise through conflicting move entry operations at
+   two or more master directory servers.
 
-   Entries that exist under the Lost & Found entry may be returned to a
-   suitable position in the DIT by an administrator or user with
-   appropriate access rights.
+   Entries that exist under the Lost & Found entry are able to be
+   returned to a suitable position in the DIT by an administrator or
+   user with appropriate access rights.
 
    5. Replication Procedures
 
    The procedures defined in this section ensure the consistent and
    correct application of the results of DAP, LDAP or DSP operations
-   across all multi-master replication DSAs.
+   across all replicating directory servers.
 
    5.1 Processing LDAP, DAP or DSP Operations on the DIT
 
@@ -315,7 +309,7 @@ INTERNET-DRAFT   LDUP Update Reconciliation Procedures  October 22, 1999
    CSNs on an entry or its contents, and create zero, one or more
    deletion records referencing the entry or its contents.  The CSNs and
    deletion records generated from an operation are atomic with that
-   operation. That is, either the operation succeeds, the CSNS are
+   operation.  That is, either the operation succeeds, the CSNs are
    revised and the deletion records are stored, or the operation fails,
    no CSNs are revised and no deletion records are stored.  In all
    cases, all current error conditions (i.e. reasons for rejecting an
@@ -324,104 +318,112 @@ INTERNET-DRAFT   LDUP Update Reconciliation Procedures  October 22, 1999
    At some later time, possibly immediately following the update or
    concurrently with it, the CSNs on entry contents and deletion records
    are used to generate the replication primitives that will report the
-   update to other DSAs via a replication session.
+   update to other directory servers via a replication session.
 
-   All the CSNs generated from a single update operation must use the
+   All the CSNs generated from a single update operation MUST use the
    same time, change count and Replica Identifier.  The modification
-   number is permitted to vary but must be assigned such that when the
+   number is permitted to vary but MUST be assigned such that when the
    CSNs resulting from the operation, including those in the deletion
    records, are compared to the CSNs resulting from any other operation
    they are all strictly greater than or all strictly less than those
    other CSNs (i.e.  in a global CSN ordering of the primitives
-   resulting from all operations the primitives of each operation must
+   resulting from all operations the primitives of each operation MUST
    be contiguous in that ordering).  In order for the update to be
-   consistently applied when replicated to other DSAs the CSNs generated
-   during that update must generally be greater than any pre-existing
-   CSNs on the updated entry's contents. It is expected that DSAs will
-   normally use the current time according to their system clocks in
-   generating the CSNs for an operation. However in an environment where
-   DSA clocks are not necessarily synchronized the current time may be
-   older than existing CSNs on entry contents. The constraints the new
-   CSNs must satisfy with respect to pre-existing CSNs on entry data are
-   covered in the sections on each type of update operation. The current
-   LDUP architecture draft [LDUP Model] requires client update
-   operations to be rejected if the current time does not satisfy the
+   consistently applied when replicated to other directory servers the
+   CSNs generated during that update must generally be greater than any
+   pre-existing CSNs on the updated entry's contents.  It is expected
 
 
 
-Legg & Payne             Expires 22 April 2000                  [Page 6]
+Legg & Payne            Expires 29 December 2000                [Page 6]
+\f
+INTERNET-DRAFT   LDUP Update Reconciliation Procedures     June 29, 2000
 
 
+   that directory servers will normally use the current time according
+   to their system clocks in generating the CSNs for an operation.
+   However in an environment where directory server clocks are not
+   necessarily synchronized the current time may be older than existing
+   CSNs on entry contents.  The constraints the new CSNs MUST satisfy
+   with respect to pre-existing CSNs on entry data are covered in the
+   sections on each type of update operation.  The Update Reconciliation
+   Procedures allow a directory server to generate CSNs in advance of
+   its current time to satisfy the constraints and proceed with the
+   update.
 
+   The LDUP Update Vector mechanism imposes the additional constraint
+   that the CSN generated for an update operation MUST also be greater
+   than the highest CSN generated by the directory server that has
+   already been seen by any other directory server.  An implementation
+   that generates successively greater CSNs for each operation will
+   satisfy this constraint.
 
+   The following sections describe the additional actions carried out in
+   processing each standard type of update operation in order to support
+   replication.  If a directory server implementation supports other
+   non-standard update operations or alternative non-directory update
+   protocols then, in so far as these operations alter replicated
+   directory data, the implementation MUST generate and apply CSNs and
+   deletion records that accurately reflect any change.
 
-INTERNET-DRAFT   LDUP Update Reconciliation Procedures  October 22, 1999
+   A directory server implementation may also perform implicit updates
+   in response to user update requests, e.g. to maintain the referential
+   integrity of distinguished names.  Appropriate CSNs and deletion
+   records for these changes MUST also be generated.
 
+   A detailed description of the replication processing for these other
+   types of update is beyond the scope of this document.
 
-   constraints on the generation of the CSNs.  As written, URP allows a
-   DSA to generate CSNs in advance of its current time to satisfy the
-   constraints and proceed with the update.
 
-   The LDUP Update Vector mechanism imposes the additional constraint
-   that the CSN generated for an update operation must also be greater
-   than the highest CSN generated by the DSA that has already been seen
-   by any other DSA. An implementation that generates successively
-   greater CSNs for each operation will satisfy this constraint.
+   5.1.1 Add Entry
+
+   The LDAP Add operation [LDAPv3] or DAP addEntry operation [X511] is
+   used to add a leaf entry to the DIT.  A successful request will
+   generate a CSN for the entry.  The CSN on the entry's RDN, the CSN on
+   the entry's superior reference, and the CSN on each distinguished and
+   non-distinguished value added to the entry by the add entry operation
+   are set to this same value.  The affected values include any
+   operational attribute values automatically generated by the directory
+   server, e.g. creatorsName and createTimestamp.  Note that the value
+   of the createTimestamp attribute does not necessarily correspond to
+   the time component of the CSN associated with that value.
+
 
-   The following sections describe the additional actions to support
-   replication carried out in processing each particular type of update
-   operation.
 
-   5.1.1 Add Entry
 
-   The LDAP Add operation or DAP addEntry operation is used to add a
-   leaf entry to the DIT.  A successful request will generate a CSN for
-   the entry.  The CSN on the entry's RDN, the CSN on the entry's
-   superior reference, and the CSN on each distinguished and non-
-   distinguished value added to the entry by the add entry operation are
-   set to this same value.  The affected values include any operational
-   attributes automatically generated by the DSA.
+Legg & Payne            Expires 29 December 2000                [Page 7]
+\f
+INTERNET-DRAFT   LDUP Update Reconciliation Procedures     June 29, 2000
+
 
    The Unique Identifier generated for an entry created by a user
    request is required to be globally unique for all time, so there
-   cannot be a pre-existing entry deletion record for the same Unique
-   Identifier.  However it is recognized that, in practice, Directory
+   ought not be a pre-existing entry deletion record for the same Unique
+   Identifier.  However it is recognized that, in practice, directory
    administrators may need to restore a deleted entry using its original
    Unique Identifier (the mechanism used to achieve this is undefined
-   and outside the scope of this specification). In this case the CSN
-   for the entry must be generated such that it is greater than or equal
-   to the CSN of any existing entry, attribute or value deletion records
-   and greater than any of the CSNs contained in an existing glue entry,
-   for the same Unique Identifier.
+   and outside the scope of this specification).  In this case the CSN
+   for the entry MUST be generated such that it is greater than or equal
+   to the CSN of any existing entry, attribute or value deletion
+   records, and greater than any of the CSNs contained in an existing
+   glue entry, for the same Unique Identifier.
 
    5.1.2 Remove Entry
 
-   The LDAP Delete operation or DAP removeEntry operation is used to
-   remove a leaf entry from the DIT. If the request succeeds then an
-   entry deletion record is stored containing the Unique Identifier of
-   the removed entry.  The CSN for the entry deletion record must be
-   generated such that it is greater than the entry CSN of the removed
-   entry.
+   The LDAP Delete operation [LDAPv3] or DAP removeEntry operation
+   [X511] is used to remove a leaf entry from the DIT.  If the request
+   succeeds then an entry deletion record is stored containing the
+   Unique Identifier of the removed entry.  The CSN for the entry
+   deletion record MUST be generated such that it is greater than the
+   entry CSN of the removed entry.
 
    5.1.3 Modify Entry
 
-   The LDAP Modify operation (ModifyRequest) or DAP modifyEntry
-
-
-
-Legg & Payne             Expires 22 April 2000                  [Page 7]
-
-
-
-
-
-INTERNET-DRAFT   LDUP Update Reconciliation Procedures  October 22, 1999
-
-
-   operation is used to perform a series of one or more modifications to
-   an entry.  If the request succeeds then zero, one or more new values
-   with CSNs are added to the entry contents, and zero, one or more
-   value or attribute deletion records are stored.
+   The LDAP Modify operation (ModifyRequest) [LDAPv3] or DAP modifyEntry
+   operation [X511] is used to perform a series of one or more
+   modifications to an entry.  If the request succeeds then zero, one or
+   more new values with CSNs are added to the entry contents, and zero,
+   one or more value or attribute deletion records are stored.
 
    The modifications described by the modification argument of the LDAP
    ModifyRequest have the following additional effects:
@@ -442,8 +444,16 @@ INTERNET-DRAFT   LDUP Update Reconciliation Procedures  October 22, 1999
    The modifications described by the changes argument of the X.500
    modifyEntry operation have the following additional effects:
 
+
+
+
+Legg & Payne            Expires 29 December 2000                [Page 8]
+\f
+INTERNET-DRAFT   LDUP Update Reconciliation Procedures     June 29, 2000
+
+
       a) The addAttribute and addValues alternatives associate a CSN
-      with each of the added attribute values. These two alternatives
+      with each of the added attribute values.  These two alternatives
       are equivalent from the point of view of URP since there is no CSN
       associated specifically with the attribute type.
 
@@ -460,100 +470,116 @@ INTERNET-DRAFT   LDUP Update Reconciliation Procedures  October 22, 1999
       e) The resetValues alternative generates a value deletion record
       for each value actually removed.
 
-   The CSNs generated by a modify operation must be greater than the CSN
+   A successful ModifyRequest or modifyEntry operation will also result
+   in changes to operational attributes of the entry.  Like the explicit
+   modifications to user attributes, CSNs are given to new operational
+   attribute values and deletion records are stored for operational
+   attribute values that are removed.  The processing in each case
+   depends on the semantics of the particular operational attribute type
+   and can be deduced by considering an equivalent explicit modification
+   request.  In particular, the revision of the modifyTimestamp and
+   modifiersName attributes is treated like the ModifyRequest replace
+   alternative.  Note that the value of the modifyTimestamp attribute
+   does not necessarily correspond to the time component of the CSN
+   associated with that value.  The entryUUID operational attribute
+   SHALL NOT be modified.  Consequently attribute and value deletion
+   records for the entryUUID attribute type are never generated.
+
+   The CSNs generated by a modify operation MUST be greater than the CSN
    of any pre-existing attribute value that is removed, greater than or
    equal to the CSN of any pre-existing attribute deletion record or
    value deletion record applying to an added attribute value, and
    greater than or equal to the CSN of the entry.
 
-
-
-
-Legg & Payne             Expires 22 April 2000                  [Page 8]
-
-
-
-
-
-INTERNET-DRAFT   LDUP Update Reconciliation Procedures  October 22, 1999
-
-
    A further constraint applies to the modification number component of
    the CSNs generated by a single modify operation.  The CSN generated
-   for an added attribute value must be greater than or equal to the CSN
+   for an added attribute value MUST be greater than or equal to the CSN
    on any applicable value deletion record or attribute deletion record
    already created by this same operation.  This constraint is satisfied
    if the same modification number is used in all the CSNs generated by
    a single modify operation, or if the CSNs generated as the sequence
    of modifications in the operation are applied in order use
    monotonically increasing modification numbers.  The modification
+
+
+
+Legg & Payne            Expires 29 December 2000                [Page 9]
+\f
+INTERNET-DRAFT   LDUP Update Reconciliation Procedures     June 29, 2000
+
+
    numbers need not be consecutive in this case.
 
    Whenever a new value is added to the entry contents any value
    deletion record for the same entry, attribute type and attribute
-   value may be discarded.
+   value MAY be discarded.
 
    5.1.4 Modify DN
 
-   The LDAP Modify DN operation and DAP modifyDN operation are used to
-   change the Relative Distinguished Name of an entry and/or to move an
-   entry to a new superior in the DIT.  If the entry is moved to a new
-   superior in the DIT then the CSN on the entry's superior reference is
-   replaced.  If the entry's RDN is changed then the CSN on the entry's
-   RDN is replaced.  A value deletion record is stored for each of the
-   formally distinguished attribute values removed from the entry as a
-   consequence of the deleteOldRDN (modifyDN) flag or deleteoldrdn
-   (ModifyDNRequest) flag being set.
+   The LDAP Modify DN operation [LDAPv3] and DAP modifyDN operation
+   [X511] are used to change the Relative Distinguished Name of an entry
+   and/or to move an entry to a new superior in the DIT.  If the entry
+   is moved to a new superior in the DIT then the CSN on the entry's
+   superior reference is replaced.  If the entry's RDN is changed then
+   the CSN on the entry's RDN is replaced.  A value deletion record is
+   stored for each of the formally distinguished attribute values
+   removed from the entry as a consequence of the deleteOldRDN parameter
+   (modifyDN) or deleteoldrdn parameter (ModifyDNRequest) being set to
+   true.  An entryUUID attribute value that is made non-distinguished
+   SHALL NOT be removed from the entry regardless of the deleteOldRDN or
+   deleteoldrdn flag and SHALL NOT have a corresponding value deletion
+   record.
 
    If the CSN on the entry's superior reference is revised then the new
-   value must be greater than the previous value.  If the CSN on the
-   entry's RDN is revised then the new value must be greater than the
+   value MUST be greater than the previous value.  If the CSN on the
+   entry's RDN is revised then the new value MUST be greater than the
    previous value of the CSN on the RDN.  The CSNs for any value
-   deletion records must be greater than the CSNs on the removed
+   deletion records MUST be greater than the CSNs on the removed
    attribute values.
 
    5.2 Generating Replication Primitives
 
-   Each time a replication session is invoked, the supplier DSA must
-   generate and send replication primitives for updates known to the
-   supplier but not yet known to the consumer DSA. The supplier uses the
-   Update Vector of the consumer to determine what to send.
-   Conceptually, the supplier scans all the glue and non-glue entries
-   and deletion records covered by the replication agreement with the
-   consumer and generates primitives where the CSNs held by the supplier
-   are greater than the CSN for the corresponding identified replica in
-   the consumer's Update Vector.
+   Each time a replication session is invoked, the supplier directory
+   server generates and sends replication primitives for updates known
+   to the supplier but not yet known to the consumer directory server.
+   The supplier uses the Update Vector of the consumer to determine what
+   to send.  Conceptually, the supplier scans all the glue and non-glue
+   entries and deletion records covered by the replication agreement
+   with the consumer and generates primitives where the CSNs held by the
+   supplier are greater than the CSN for the corresponding identified
+   replica in the consumer's Update Vector.  No replication primitives
+   are generated for entries or entry contents that are outside the
+   scope of the replication agreement.
 
    A p-add-entry primitive is generated for each entry whose entry CSN
    is greater than the Update Vector CSN for the same replica.  The
+   superior argument of the p-add-entry primitive contains the Unique
+   Identifier of the immediate superior entry of the added entry.  The
+   rdn argument of the p-add-entry primitive contains the Relative
 
 
 
-Legg & Payne             Expires 22 April 2000                  [Page 9]
-
-
-
-
-
-INTERNET-DRAFT   LDUP Update Reconciliation Procedures  October 22, 1999
+Legg & Payne            Expires 29 December 2000               [Page 10]
+\f
+INTERNET-DRAFT   LDUP Update Reconciliation Procedures     June 29, 2000
 
 
-   superior argument of the p-add-entry primitive contains the Unique
-   Identifier of the immediate superior entry of the added entry.  The
-   rdn argument of the p-add-entry primitive contains the Relative
-   Distinguished Name of the created entry except that the Unique
-   Identifier, if distinguished, is always omitted from the RDN.  The
-   superior and rdn arguments are provided even if the CSN on the
-   superior reference or the RDN are greater than the CSN on the entry.
+   Distinguished Name of the created entry except that the value of the
+   entryUUID attribute, if distinguished, is always omitted from the
+   RDN.  The superior and rdn arguments are provided even if the CSN on
+   the superior reference or the RDN are greater than the CSN on the
+   entry.
 
    A p-add-attribute-value primitive is generated for each distinguished
    value that has a CSN greater than the Update Vector CSN for the same
-   replica and greater than the CSN on the RDN of its entry, and for
-   each non-distinguished value that has a CSN greater than the Update
-   Vector CSN for the same replica.  The p-add-attribute-value primitive
-   uses the CSN of the corresponding value.  There are no separate
-   primitives generated for the distinguished values that have the same
-   CSN as the CSN on their entry's RDN.
+   replica and greater than the CSN on the RDN of its entry.  A p-add-
+   attribute-value primitive is generated for each non-distinguished
+   value that has a CSN greater than the Update Vector CSN for the same
+   replica.  The values of operational attributes are treated in the
+   same way as the values of user attributes.  The p-add-attribute-value
+   primitive uses the CSN of the corresponding value.  There are no
+   separate primitives generated for the distinguished values that have
+   the same CSN as the CSN on their entry's RDN.
 
    If the CSN on an entry's RDN is greater than the Update Vector CSN
    for the same replica and greater than the CSN on the entry then a p-
@@ -565,8 +591,8 @@ INTERNET-DRAFT   LDUP Update Reconciliation Procedures  October 22, 1999
    Update Vector CSN for the same replica and greater than the CSN on
    the entry then a p-move-entry primitive is generated.  The CSN for
    this primitive is the CSN on the entry's superior reference and the
-   superior argument of the contains the Unique Identifier of the
-   immediate superior entry.
+   superior argument contains the Unique Identifier of the immediate
+   superior entry.
 
    A p-remove-attribute-value primitive is generated for each value
    deletion record having a CSN greater than the Update Vector CSN for
@@ -583,51 +609,48 @@ INTERNET-DRAFT   LDUP Update Reconciliation Procedures  October 22, 1999
    replica.  The primitive uses exactly the same arguments as the entry
    deletion record.
 
-   Rather than scanning the DIT, an implementation may choose to
+   Rather than scanning the DIT, an implementation MAY choose to
    generate replication primitives as the user update requests are being
    processed and put these primitives into a replication log in
 
 
 
-Legg & Payne             Expires 22 April 2000                 [Page 10]
-
-
-
-
-
-INTERNET-DRAFT   LDUP Update Reconciliation Procedures  October 22, 1999
+Legg & Payne            Expires 29 December 2000               [Page 11]
+\f
+INTERNET-DRAFT   LDUP Update Reconciliation Procedures     June 29, 2000
 
 
    preparation for sending during the next replication session.  Any
    replication primitives generated from an operation in this way MUST
-   be atomic with that operation. That is, either the operation
+   be atomic with that operation.  That is, either the operation
    succeeds, and primitives are added to the replication log, or the
    operation fails, and no primitives are added to the log.  The
-   replication log may be filtered prior to sending to eliminate any
-   primitives that are superseded by later primitives in the log, and
-   any primitives having CSNs less than or equal to the relevant CSNs
-   contained in a consumer DSA's Update Vector.
+   replication log MAY be filtered prior to sending to eliminate any
+   primitives that are superseded by later primitives in the log, and to
+   eliminate any primitives having CSNs less than or equal to the
+   relevant CSNs contained in a consumer directory server's Update
+   Vector.
 
    In a log based implementation, the p-add-attribute-value primitive
    supersedes a p-remove-attribute-value primitive for the same entry,
-   attribute type, attribute value and equal or older CSN. It supersedes
-   another p-add-attribute-value primitive for the same entry, attribute
-   type, attribute value and older CSN.
+   attribute type, attribute value and equal or older CSN.  It
+   supersedes another p-add-attribute-value primitive for the same
+   entry, attribute type, attribute value and older CSN.
 
    The p-remove-attribute-value primitive supersedes a p-add-attribute-
    value primitive for the same entry, attribute type, attribute value
-   and older CSN. It supersedes another p-remove-attribute-value
+   and older CSN.  It supersedes another p-remove-attribute-value
    primitive for the same entry, attribute type, attribute value and
    equal or older CSN.
 
    The p-remove-attribute primitive supersedes a p-add-attribute-value
-   primitive for the same entry, attribute type and older CSN. It
+   primitive for the same entry, attribute type and older CSN.  It
    supersedes a p-remove-attribute-value or another p-remove-attribute
    primitive for the same entry, attribute type and equal or older CSN.
 
    The p-remove-entry primitive supersedes a p-add-attribute-value, p-
    add-entry, p-move-entry or p-rename-entry primitive for the same
-   entry and older CSN. It supersedes a p-remove-attribute-value or p-
+   entry and older CSN.  It supersedes a p-remove-attribute-value or p-
    remove-attribute or another p-remove-entry primitive for the same
    entry and equal or older CSN.
 
@@ -636,87 +659,84 @@ INTERNET-DRAFT   LDUP Update Reconciliation Procedures  October 22, 1999
 
    5.3 Processing Replication Primitives on the DIT
 
-   Each replication primitive received from another DSA during a
-   replication session is processed against the DIT.
+   Each replication primitive received from another directory server
+   during a replication session that is within the scope of the
+   replication agreement is processed against the DIT.  Replication
+   primitives outside the scope of the replication agreement are
+   rejected.
 
    This section defines some commonly used sub-procedures and the
-   algorithms for processing each of the primitives. Components of
-   primitives, entries, attributes and values are referenced with the .
-   operator. In particular the notation X.csn refers to the CSN of the
-   directory object X. The operators, < and > when applied to CSNs, use
-   the convention of CSNs becoming greater with the progression of time,
-   so older CSNs are less than younger CSNs.  In the case where the CSN
-
-
+   algorithms for processing each of the primitives.  These algorithms
+   are not intended to be implemented verbatim but instead describe the
 
-Legg & Payne             Expires 22 April 2000                 [Page 11]
 
 
+Legg & Payne            Expires 29 December 2000               [Page 12]
+\f
+INTERNET-DRAFT   LDUP Update Reconciliation Procedures     June 29, 2000
 
 
+   behaviour an LDUP implementation MUST exhibit externally.
+   Alternative equivalent processing logic is permitted.
 
-INTERNET-DRAFT   LDUP Update Reconciliation Procedures  October 22, 1999
-
-
-   for object X has been discarded through the purging mechanism, X.csn
-   is assumed to have the least possible CSN value. In some of the
-   procedures a CSN will be explicitly purged. An implementation may
-   instead keep the CSN but set it to some value that is old enough for
-   it to be eligible for purging (e.g. the least possible CSN value)
-   without affecting the correctness of the procedures.
+   Components of primitives, entries, attributes and values are
+   referenced with the `.' operator.  In particular the notation X.csn
+   refers to the CSN of the directory object X.  The operators, < and >
+   when applied to CSNs, use the convention of CSNs becoming greater
+   with the progression of time, so older CSNs are less than younger
+   CSNs.  In the case where the CSN for object X has been discarded
+   through the purging mechanism, X.csn is assumed to have the least
+   possible CSN value.  In some of the procedures a CSN will be
+   explicitly purged.  An implementation MAY instead keep the CSN but
+   set it to some value that is old enough for it to be eligible for
+   purging (e.g. the least possible CSN value) without affecting the
+   correctness of the procedures.
 
    For an entry, E, the notation E.rdn refers to the entry's Relative
    Distinguished Name, E.dn refers to the entry's Distinguished Name,
    and E.superior refers to the Unique Identifier of the entry's
    superior in the DIT.
 
-
    5.3.1 Saving Deletion Records
 
-   It is necessary for a DSA to remember that some entry, attribute or
-   attribute value has been deleted, for a period after the processing
-   of the update operation or primitive causing the deletion. These
-   records are called deletion records in the sections that follow and
-   are of three kinds: entry deletion records, attribute deletion
-   records and value deletion records.
-
-   Value deletion records result from, and have the same parameters as,
-   the p-remove-attribute-value primitive. The StoreValueDeletion
-   procedure creates a value deletion record from the actual arguments
-   and stores it for later access by the various primitive processing
-   procedures. When an attribute value is added to an entry, a value
-   deletion record for the same entry, attribute type and value, and
-   with an older CSN, may be discarded.
-
-   Attribute deletion records result from, and have the same parameters
-   as, the p-remove-attribute primitive. The StoreAttributeDeletion
-   procedure creates an attribute deletion record from the actual
-   arguments and stores it for later access. When an attribute deletion
-   record is stored any value deletion records for the same entry and
-   attribute type, and with equal or older CSNs, may be discarded.
-
-   Entry deletion records result from, and have the same parameters as,
-   the p-remove-entry primitive. The StoreEntryDeletion procedure
-   creates an entry deletion record from the actual arguments and stores
-   it for later access. When an entry deletion record is stored any
-   value deletion records and attribute deletion records for the same
-   entry, and with equal or older CSNs, may be discarded.
-
-   Since the deletion records have the same components as their
-   associated remove primitives an implementation may choose to use the
-   same internal structures for both.
-
+   It is necessary for a directory server to store deletion records to
+   remember that some entry, attribute or attribute value has been
+   deleted, for a period after the processing of the update operation or
+   replication primitive causing the deletion.
 
+   Value deletion records have the same parameters as the p-remove-
+   attribute-value primitive.  The StoreValueDeletion procedure creates
+   a value deletion record from the actual arguments and stores it for
+   later access by the various primitive processing procedures.  When an
+   attribute value is added to an entry, a value deletion record for the
+   same entry, attribute type and value, and with an older CSN, MAY be
+   discarded.
 
+   Attribute deletion records have the same parameters as the p-remove-
+   attribute primitive.  The StoreAttributeDeletion procedure creates an
+   attribute deletion record from the actual arguments and stores it for
+   later access.  When an attribute deletion record is stored any value
+   deletion records for the same entry and attribute type, and with
+   equal or older CSNs, MAY be discarded.
 
-Legg & Payne             Expires 22 April 2000                 [Page 12]
+   Entry deletion records have the same parameters as the p-remove-entry
+   primitive.  The StoreEntryDeletion procedure creates an entry
+   deletion record from the actual arguments and stores it for later
+   access.  When an entry deletion record is stored any value deletion
+   records and attribute deletion records for the same entry, and with
 
 
 
+Legg & Payne            Expires 29 December 2000               [Page 13]
+\f
+INTERNET-DRAFT   LDUP Update Reconciliation Procedures     June 29, 2000
 
 
-INTERNET-DRAFT   LDUP Update Reconciliation Procedures  October 22, 1999
+   equal or older CSNs, MAY be discarded.
 
+   Since the deletion records have the same components as their
+   associated remove primitives an implementation MAY choose to use the
+   same internal structures for both.
 
    5.3.2 Glue Entries
 
@@ -726,84 +746,82 @@ INTERNET-DRAFT   LDUP Update Reconciliation Procedures  October 22, 1999
    re-added.  In these cases a glue entry is created for the Unique
    Identifier to preserve relevant updates in the event that a p-add-
    entry primitive with an older CSN is later received for the same
-   entry. A glue entry is upgraded to a normal entry by a subsequent p-
-   add-entry primitive.
+   entry.  A glue entry is upgraded to a normal entry by a subsequent
+   p-add-entry primitive.
 
    A glue entry with no subordinate entries and containing only CSNs (on
-   itself or its component parts) that are eligible to be purged
-   (according to the Purge Vector in LDUP, or the Oldest Time in DMRP)
-   may be removed. A glue entry is discarded if its contents are
-   completely superseded by another p-remove-entry primitive.
+   itself or its component parts) that are eligible to be purged MAY be
+   removed.  A glue entry is discarded if its contents are completely
+   superseded by another p-remove-entry primitive.
 
    The CreateGlueEntry function is called when required to create a glue
-   entry as a subordinate of Lost & Found. CreateGlueEntry takes a
+   entry as a subordinate of Lost & Found.  CreateGlueEntry takes a
    single parameter which is the Unique Identifier for the glue entry.
-   The Unique Identifier also becomes the RDN for the glue entry. No
-   CSNs are associated with the entry, the entry's superior reference,
-   or the entry's name (or equivalently they are set to the least
-   possible CSN value).
+   The Unique Identifier, in the form of the entryUUID attribute, also
+   becomes the RDN for the glue entry.  No CSNs are associated with the
+   entry, the entry's superior reference, or the entry's name (or
+   equivalently they are set to the least possible CSN value).
 
    5.3.3 Generating Change Sequence Numbers
 
    There are circumstances where conflicts arise in the processing of a
-   replication primitive. It is necessary in these cases for the DSA
-   processing the primitives to make corrective changes and emit
-   additional primitives to ensure that all other DSAs reach the same
-   consistent state. The GenerateNextCSN function is used to obtain a
-   CSN for the corrective change.  An implementation that generates
-   replication primitives as the user update requests are being
-   processed and puts them into a replication log must take the
-   additional step of creating a primitive to convey the corrective
-   change to other DSAs. Implementations that generate primitives by
-   scanning entries will pick up the corrective change automatically.
-
-   As is the case for CSNs generated from DAP, DSP or LDAP operations, a
-   CSN is typically generated from the current clock time of the DSA.
-   The conditions imposed for the correct operation of the LDUP Update
-   Vector must also be satisfied.
-
-   GenerateNextCSN takes a single CSN parameter. In addition to all
-   other conditions the CSN generated by the function must be greater
-   than this parameter. Since the CSN parameter passed to
-   GenerateNextCSN is always an actual CSN from some directory object
+   replication primitive.  It is necessary in these cases for the
+   directory server processing the primitives to make corrective changes
+   and emit additional primitives to ensure that all other directory
+   servers reach the same consistent state.  The GenerateNextCSN
+   function is used to obtain a CSN for the corrective change.  An
+   implementation that generates replication primitives as the user
+   update requests are being processed and puts them into a replication
+   log MUST take the additional step of creating a primitive to convey
+   the corrective change to other directory servers.  Implementations
+   that generate primitives by scanning entries will pick up the
+   corrective change automatically.
 
+   As is the case for CSNs generated from DAP, DSP or LDAP operations,
+   the CSN for the corrective change is typically generated from the
+   current clock time of the directory server.  The conditions imposed
 
 
-Legg & Payne             Expires 22 April 2000                 [Page 13]
 
+Legg & Payne            Expires 29 December 2000               [Page 14]
+\f
+INTERNET-DRAFT   LDUP Update Reconciliation Procedures     June 29, 2000
 
 
+   for the correct operation of the LDUP Update Vector MUST also be
+   satisfied.
 
-
-INTERNET-DRAFT   LDUP Update Reconciliation Procedures  October 22, 1999
-
-
-   stored in the local DSA, an implementation may choose to allocate
-   CSNs from an incrementing internal CSN register that is reset after
-   each replication session to a value greater than the largest CSN seen
-   so far, and thereby be safely able to disregard the parameter to
-   GenerateNextCSN.
+   GenerateNextCSN takes a single CSN parameter.  In addition to all
+   other conditions, the CSN generated by the function MUST be greater
+   than this parameter.  Since the CSN parameter passed to
+   GenerateNextCSN is always an actual CSN from some directory object
+   stored in the local directory server, an implementation MAY choose to
+   allocate CSNs from an incrementing internal CSN register that is
+   reset after each replication session to a value greater than the
+   largest CSN seen so far, and thereby be safely able to disregard the
+   parameter to GenerateNextCSN.
 
    5.3.4 Comparison of Attribute Values
 
    Values in primitives, in deletion records or in entries are compared
    using the equality matching rule for the associated attribute type
-   where that type is permitted to be multi-valued. This means that two
+   where that type is permitted to be multi-valued.  This means that two
    values that are considered equal may nonetheless have minor
-   differences. For example, two commonName values may be equal, but use
-   different letter case and have different numbers of leading or
-   trailing spaces. Whenever a CSN for some value is refreshed the value
-   is also refreshed using the exact value from the primitive so that
-   all DSAs use exactly the same representation for the value.
+   differences.  For example, two commonName values may be equal, but
+   use different letter case and have different numbers of leading or
+   trailing spaces.  Whenever a CSN for some value is refreshed the
+   value is also refreshed using the exact value from the primitive so
+   that all directory servers use exactly the same representation for
+   the value.
 
    Compared values for a single-valued attribute type are all considered
    to be equal even though they may be significantly different according
-   to that attribute type's equality matching rule. In effect the
-   equality operator, '=', in the following procedures is
+   to that attribute type's equality matching rule.  In effect the
+   equality operator, `=', in the following procedures is
    unconditionally true when used to compare values of a single-valued
    attribute type.  Whenever a CSN for the value of a single-valued
    attribute is refreshed the value is also refreshed using the value
-   from the primitive. One significant consequence is that an entry
+   from the primitive.  One significant consequence is that an entry
    whose RDN contains a value of a single-valued attribute type is
    effectively renamed by a p-add-attribute-value primitive with a more
    recent value for the attribute type.
@@ -814,42 +832,38 @@ INTERNET-DRAFT   LDUP Update Reconciliation Procedures  October 22, 1999
 
    5.3.5 Entry Naming
 
-   Independent changes at two or more DSAs can lead to the situation of
-   two distinct entries having the same name. The procedure,
-   CheckUniqueness(E, S, R), takes an entry and determines whether it is
-   uniquely named.  If not, it disambiguates the names of the entries by
-   adding the Unique Identifier of each of the conflicting entries to
-   their own RDN.
-
-   The procedure CheckUniqueness is called in each circumstance where
-   the Relative Distinguished Name of an entry might conflict with
-   another entry, either because the entry has been renamed or because
-   it has been moved to a new superior.  An entry can be renamed
-   directly by a p-rename-entry primitive, or as a side-effect of other
+   Independent changes at two or more directory servers can lead to the
+   situation of two distinct entries having the same name.  The
+   procedure, CheckUniqueness(E, S, R), takes an entry and determines
+   whether it is uniquely named.  If not, it disambiguates the names of
 
 
 
-Legg & Payne             Expires 22 April 2000                 [Page 14]
+Legg & Payne            Expires 29 December 2000               [Page 15]
+\f
+INTERNET-DRAFT   LDUP Update Reconciliation Procedures     June 29, 2000
 
 
+   the entries by adding the Unique Identifier (i.e. the entryUUID
+   attribute) of each of the conflicting entries to their own RDN.
 
-
-
-INTERNET-DRAFT   LDUP Update Reconciliation Procedures  October 22, 1999
-
-
+   The procedure CheckUniqueness is called in each circumstance where
+   the Relative Distinguished Name of an entry might conflict with
+   another entry, either because the entry has been renamed or because
+   it has been moved to a new superior.  An entry can be renamed
+   directly by a p-rename-entry primitive, or as a side-effect of other
    primitives causing changes to distinguished values.  While each move
    or rename of an entry potentially causes a conflict with some other
    entry already having the new Distinguished Name, it also potentially
-   removes a previous conflict on the old Distinguished Name.  The
-   enable the CheckUniqueness function to remove the Unique Identifier
-   from an entry's RDN when it is no longer needed the old name for an
-   entry is passed through the second and third parameters. The
-   parameter, S, is the Unique Identifier of the old superior entry of
-   E, and the parameter, R, is the old RDN of E. CheckUniqueness needs
-   to ignore distinguished UniqueIdentifiers when comparing entry RDNs.
-   The function BaseRDN(rdn) returns its argument minus any
-   distinguished UniqueIdentifiers to support these comparisons.
+   removes a previous conflict on the old Distinguished Name.  To enable
+   the CheckUniqueness function to remove the Unique Identifier from an
+   entry's RDN when it is no longer needed, the old name for an entry is
+   passed through the second and third parameters.  The parameter, S, is
+   the Unique Identifier of the old superior entry of E, and the
+   parameter, R, is the old RDN of E. CheckUniqueness ignores
+   distinguished entryUUID values when comparing entry RDNs.  The
+   function BaseRDN(rdn) returns its argument minus any distinguished
+   entryUUID values, to support these comparisons.
 
    CheckUniqueness(E, S, R)
       {
@@ -867,45 +881,42 @@ INTERNET-DRAFT   LDUP Update Reconciliation Procedures  October 22, 1999
          }
       }
 
-   Because updates are performed in isolation at multiple DSAs in a
-   multimaster configuration it is possible to encounter a situation
-   where there is a request to delete a distinguished value in an entry.
-   The recommended practice in these circumstances is to remove the
-   distinguished value and call CheckUniqueness to correct any resulting
-   name conflicts.  An implementation may instead reassert the existence
-   of the distinguished value with a more recent CSN to avoid altering
-   the entry's RDN. This option is only available to updatable replicas.
-   Read-only replicas MUST remove the distinguished value.  The function
-   ProtectDistinguished() returns true for an updatable part of the DIT
-   in an DSA that implements this option, and false otherwise.  DSAs
-   exercising this option must generate p-add-attribute-value primitive
-   so that other DSAs are guaranteed to also reassert the distinguished
-   value.  DSAs that implement the option will correctly interwork with
-   servers that do not.
-
-   The primitives p-add-entry and p-rename-entry contain common elements
-   that are applied to the Relative Distinguished Name of an entry in
-   the same way. This common processing is described in the RenameEntry
-
-
-
-Legg & Payne             Expires 22 April 2000                 [Page 15]
+   Because updates are performed in isolation at multiple directory
+   servers in a multimaster configuration it is possible to encounter a
+   situation where there is a request to delete a distinguished value in
+   an entry.  The recommended practice in these circumstances is to
+   remove the distinguished value and call CheckUniqueness to correct
+   any resulting name conflicts.  An implementation MAY instead reassert
+   the existence of the distinguished value with a more recent CSN to
+   avoid altering the entry's RDN.  This option is only available to
+   updatable replicas.  Read-only replicas MUST remove the distinguished
+   value.  The function ProtectDistinguished() returns true for an
+   updatable part of the DIT in a directory server that implements this
 
 
 
+Legg & Payne            Expires 29 December 2000               [Page 16]
+\f
+INTERNET-DRAFT   LDUP Update Reconciliation Procedures     June 29, 2000
 
 
-INTERNET-DRAFT   LDUP Update Reconciliation Procedures  October 22, 1999
+   option, and false otherwise.  directory servers exercising this
+   option MUST generate a p-add-attribute-value primitive so that other
+   directory servers are guaranteed to also reassert the distinguished
+   value.  Directory servers that implement the option will correctly
+   interwork with servers that do not.
 
-
-   procedure. The parameters to this procedure are the entry, E, and the
-   p-add-entry or p-rename-entry primitive specifying the new RDN. The
-   procedure assumes that the entry does not currently contain any
-   distinguished values. It is the responsibility of the calling
+   The primitives p-add-entry and p-rename-entry contain common elements
+   that are applied to the Relative Distinguished Name of an entry in
+   the same way.  This common processing is described in the RenameEntry
+   procedure.  The parameters to this procedure are the entry, E, and
+   the p-add-entry or p-rename-entry primitive specifying the new RDN.
+   The procedure assumes that the entry does not currently contain any
+   distinguished values.  It is the responsibility of the calling
    procedure to first reset any pre-existing distinguished values to
    non-distinguished.  The procedure then resets the CSNs and sets the
    distinguished flags for existing values and adds distinguished values
-   if necessary. The CSN for the entry's RDN, as distinct from the CSNs
+   if necessary.  The CSN for the entry's RDN, as distinct from the CSNs
    on each of the distinguished values making up the RDN, is also set.
 
    RenameEntry(E, P)
@@ -937,6 +948,14 @@ INTERNET-DRAFT   LDUP Update Reconciliation Procedures  October 22, 1999
             V.csn := GenerateNextCSN(V.csn)
             }
          ELSE IF no attribute deletion record (uid, type, csn) exists
+
+
+
+Legg & Payne            Expires 29 December 2000               [Page 17]
+\f
+INTERNET-DRAFT   LDUP Update Reconciliation Procedures     June 29, 2000
+
+
                where (uid = P.uid AND type = N.type AND csn > P.csn)
             AND no value deletion record (uid, type, value, csn) exists
                where (uid = P.uid AND type = N.type AND
@@ -946,27 +965,16 @@ INTERNET-DRAFT   LDUP Update Reconciliation Procedures  October 22, 1999
             add V to E as a distinguished value
             V.csn := P.csn
             }
-
-
-
-Legg & Payne             Expires 22 April 2000                 [Page 16]
-
-
-
-
-
-INTERNET-DRAFT   LDUP Update Reconciliation Procedures  October 22, 1999
-
-
       E.rdn.csn := P.csn
       }
 
 
    5.3.6 Processing Add Attribute Value Primitive
 
-   This section describes the algorithm for processing the p-add-
-   attribute-value (P.uid, P.type, P.value, P.csn) primitive, which is
-   responsible for adding a single attribute value.
+   This section details the algorithm for processing the p-add-
+   attribute-value (P.uid, P.type, P.value, P.csn) primitive, which
+   describes the addition of a single attribute value.  If P.type is the
+   entryUUID attribute type then the primitive MUST be rejected.
 
       IF no value deletion record (uid, type, value, csn) exists where
             (uid = P.uid AND type = P.type
@@ -996,31 +1004,25 @@ INTERNET-DRAFT   LDUP Update Reconciliation Procedures  October 22, 1999
                {
                V := P.value
                Add V to E as a non-distinguished attribute value
-               V.csn := P.csn
-               }
-         }
-
-
-   5.3.7 Processing Remove Attribute Value Primitive
-
-   This section describes the algorithm for processing the p-remove-
-   attribute-value (P.uid, P. type, P.value, P.csn) primitive, which is
-   responsible for removing a single attribute value. A value that is
 
 
 
-Legg & Payne             Expires 22 April 2000                 [Page 17]
-
-
+Legg & Payne            Expires 29 December 2000               [Page 18]
+\f
+INTERNET-DRAFT   LDUP Update Reconciliation Procedures     June 29, 2000
 
 
+               V.csn := P.csn
+               }
+         }
 
-INTERNET-DRAFT   LDUP Update Reconciliation Procedures  October 22, 1999
 
+   5.3.7 Processing Remove Attribute Value Primitive
 
-   distinguished is tagged as distinguished-not-present rather than
-   being immediately removed. Such a value will be physically removed
-   when it becomes non-distinguished.
+   This section details the algorithm for processing the p-remove-
+   attribute-value (P.uid, P.type, P.value, P.csn) primitive, which
+   describes the removal of a single attribute value.  If P.type is the
+   entryUUID attribute type then the primitive MUST be rejected.
 
       IF no value deletion record (uid, type, value, csn) exists
             where (uid = P.uid AND type = P.type AND
@@ -1058,34 +1060,30 @@ INTERNET-DRAFT   LDUP Update Reconciliation Procedures  October 22, 1999
                   StoreValueDeletion (P.uid, P.type, P.value, P.csn)
             }
          ELSE
-            StoreValueDeletion (P.uid, P.type, P.value, P.csn)
-
-   The presence of a younger deletion record for the entry, attribute or
-   value provides a convenient test for whether the p-remove-attribute-
-   value primitive needs to be processed at all. If the value exists to
-   be removed then there cannot be a deletion record affecting it that
-   has a younger CSN. If there is a younger deletion record than the
-   primitive then there cannot be an older value to remove.
-
 
 
-Legg & Payne             Expires 22 April 2000                 [Page 18]
-
 
+Legg & Payne            Expires 29 December 2000               [Page 19]
+\f
+INTERNET-DRAFT   LDUP Update Reconciliation Procedures     June 29, 2000
 
 
+            StoreValueDeletion (P.uid, P.type, P.value, P.csn)
 
-INTERNET-DRAFT   LDUP Update Reconciliation Procedures  October 22, 1999
+   The presence of a younger deletion record for the entry, attribute or
+   value provides a convenient test for whether the p-remove-attribute-
+   value primitive needs to be processed at all.  If the value exists to
+   be removed then there cannot be a deletion record affecting it that
+   has a younger CSN.  If there is a younger deletion record than the
+   primitive then there cannot be an older value to remove.
 
 
    5.3.8 Processing Remove Attribute Primitive
 
-   This section describes the algorithm for processing the p-remove-
-   attribute (P.uid, P.type, P.csn) primitive, which is responsible for
-   removing all attribute values of P.type. Values that are
-   distinguished are tagged as distinguished-not-present rather than
-   being immediately removed. Such values will be physically removed
-   when they become non-distinguished.
+   This section details the algorithm for processing the p-remove-
+   attribute (P.uid, P.type, P.csn) primitive, which describes the
+   removal of all attribute values of P.type.  If P.type is the
+   entryUUID attribute type then the primitive MUST be rejected.
 
       IF no attribute deletion record (uid, type, csn) exists
             where (uid = P.uid AND type = P.type AND csn >= P.csn)
@@ -1117,36 +1115,36 @@ INTERNET-DRAFT   LDUP Update Reconciliation Procedures  October 22, 1999
 
    5.3.9 Processing Add Entry Primitive
 
-   This section describes the algorithm for processing the p-add-entry
-   (P.uid, P.superior, P.rdn, P.csn) primitive, which is responsible for
-   adding an entry.  The CSN on an entry records the time of the latest
-   p-add-entry primitive for the Unique Identifier.  In normal
-   circumstances there will only ever be one p-add-entry primitive
-   associated with an entry.  The entry CSN may be discarded when it
-   becomes eligible to be purged according to the Purge Vector.
-
-      IF no entry deletion record (uid, csn) exists where
-
-
+   This section details the algorithm for processing the p-add-entry
 
-Legg & Payne             Expires 22 April 2000                 [Page 19]
 
 
+Legg & Payne            Expires 29 December 2000               [Page 20]
+\f
+INTERNET-DRAFT   LDUP Update Reconciliation Procedures     June 29, 2000
 
 
+   (P.uid, P.superior, P.rdn, P.csn) primitive, which describes the
+   addition of an entry.  The CSN on an entry records the time of the
+   latest p-add-entry primitive for the Unique Identifier.  In normal
+   circumstances there will only ever be one p-add-entry primitive
+   associated with an entry.  The entry CSN MAY be discarded when it
+   becomes eligible to be purged according to the Purge Vector.
 
-INTERNET-DRAFT   LDUP Update Reconciliation Procedures  October 22, 1999
-
-
+      IF no entry deletion record (uid, csn) exists where
            (uid = P.uid AND csn > P.csn)
          IF entry, E, with uid = P.uid exists
             {
             IF P.csn > E.csn
                {
+               R := E.rdn
+               S := E.superior
                E.csn := P.csn
-               FOREACH attribute value, V, in E
-                  IF V.csn < P.csn
-                     remove value V
+               FOREACH attribute type, T, in E, except entryUUID
+                  FOREACH attribute value, V, of type T
+                     IF V.csn < P.csn
+                        remove value V
+               CheckUniqueness(E, S, R)
                process P according to
                   p-rename-entry(P.uid, P.rdn, P.csn)
                process P according to
@@ -1170,14 +1168,22 @@ INTERNET-DRAFT   LDUP Update Reconciliation Procedures  October 22, 1999
 
    5.3.10 Processing Remove Entry Primitive
 
-   This section describes the algorithm for processing the p-remove-
-   entry (P.uid, P.csn) primitive, which is responsible for removing an
-   entry.  If the target entry has attribute values with CSNs greater
-   than the primitive's CSN, a superior reference with a greater CSN, or
-   if it has any subordinate entries, it becomes a glue entry instead of
-   being removed.  Unless it has a CSN for its superior reference that
-   is greater than the CSN of the p-remove-entry it is also moved to
-   Lost & Found.
+   This section details the algorithm for processing the p-remove-entry
+   (P.uid, P.csn) primitive, which describes the removal of an entry.
+   If the target entry has attribute values with CSNs greater than the
+   primitive's CSN, a superior reference with a greater CSN, or if it
+
+
+
+Legg & Payne            Expires 29 December 2000               [Page 21]
+\f
+INTERNET-DRAFT   LDUP Update Reconciliation Procedures     June 29, 2000
+
+
+   has any subordinate entries, it becomes a glue entry instead of being
+   removed.  It is also moved to Lost & Found, unless it has a CSN for
+   its superior reference that is greater than the CSN of the p-remove-
+   entry.
 
       IF no entry deletion record (uid, csn) exists
             where (uid = P.uid AND csn >= P.csn)
@@ -1186,18 +1192,6 @@ INTERNET-DRAFT   LDUP Update Reconciliation Procedures  October 22, 1999
             IF P.csn > E.csn
                {
                IF E.superior.csn >= P.csn
-
-
-
-Legg & Payne             Expires 22 April 2000                 [Page 20]
-
-
-
-
-
-INTERNET-DRAFT   LDUP Update Reconciliation Procedures  October 22, 1999
-
-
                   OR any value, V, with csn >= P.csn exists
                   OR E has subordinates
                   {
@@ -1212,9 +1206,10 @@ INTERNET-DRAFT   LDUP Update Reconciliation Procedures  October 22, 1999
                      }
                   IF E.rdn.csn < P.csn
                      purge E.rdn.csn
-                  FOREACH attribute value, V, in E
-                     IF V.csn < P.csn
-                        remove value V
+                  FOREACH attribute type, T, in E, except entryUUID
+                     FOREACH attribute value, V, of type T
+                        IF V.csn < P.csn
+                           remove value V
                   CheckUniqueness(E, S, R)
                   }
                ELSE
@@ -1228,11 +1223,20 @@ INTERNET-DRAFT   LDUP Update Reconciliation Procedures  October 22, 1999
 
    5.3.11 Processing Move Entry Primitive
 
-   This section describes the algorithm for processing the p-move-entry
-   (P.uid, P.superior,  P.csn) primitive, which is responsible for
-   moving an entry. If the new superior specified by the primitive does
-   not exist or is a direct or indirect subordinate of the entry being
-   moved then the entry is moved to Lost & Found instead.
+   This section details the algorithm for processing the p-move-entry
+   (P.uid, P.superior,  P.csn) primitive, which describes the moving of
+   an entry to a new immediate superior in the DIT.  If the new superior
+   specified by the primitive does not exist, or is a direct or indirect
+   subordinate of the entry being moved, then the entry is moved to Lost
+
+
+
+Legg & Payne            Expires 29 December 2000               [Page 22]
+\f
+INTERNET-DRAFT   LDUP Update Reconciliation Procedures     June 29, 2000
+
+
+   & Found instead.
 
       IF no entry deletion record (uid, csn) exists
             where (uid = P.uid AND csn > P.csn)
@@ -1246,18 +1250,6 @@ INTERNET-DRAFT   LDUP Update Reconciliation Procedures  October 22, 1999
             IF entry, S, with uid = P.superior does not exist
                S := CreateGlueEntry(P.superior)
             IF S is not in the subtree of E
-
-
-
-Legg & Payne             Expires 22 April 2000                 [Page 21]
-
-
-
-
-
-INTERNET-DRAFT   LDUP Update Reconciliation Procedures  October 22, 1999
-
-
                {
                E.superior := P.superior
                E.superior.csn = P.csn
@@ -1274,13 +1266,13 @@ INTERNET-DRAFT   LDUP Update Reconciliation Procedures  October 22, 1999
 
    5.3.12 Processing Rename Entry Primitive
 
-   This section describes the algorithm for processing the p-rename-
-   entry (P.uid, P.rdn, P.csn) primitive, which changes the Relative
-   Distinguished Name of an entry.  A p-rename-entry primitive that is
-   older than current name of an entry is not simply ignored since it
-   may contain attribute values that would have been added to the entry
-   had the primitives arrived in CSN order.  These extra values would
-   now be non-distinguished.
+   This section details the algorithm for processing the p-rename-entry
+   (P.uid, P.rdn, P.csn) primitive, which describes a change to the
+   Relative Distinguished Name of an entry.  A p-rename-entry primitive
+   that is older than current name of an entry is not simply ignored
+   since it may contain attribute values that would have been added to
+   the entry had the primitives arrived in CSN order.  These extra
+   values would now be non-distinguished.
 
       IF no entry deletion record (uid, csn) exists
          where (uid = P.uid AND csn >= P.csn)
@@ -1292,6 +1284,14 @@ INTERNET-DRAFT   LDUP Update Reconciliation Procedures  October 22, 1999
             R := E.rdn
             FOREACH distinguished attribute value, V, in entry E
                make V non-distinguished
+
+
+
+Legg & Payne            Expires 29 December 2000               [Page 23]
+\f
+INTERNET-DRAFT   LDUP Update Reconciliation Procedures     June 29, 2000
+
+
             RenameEntry(E, P)
             CheckUniqueness(E, E.superior, R)
             }
@@ -1306,18 +1306,6 @@ INTERNET-DRAFT   LDUP Update Reconciliation Procedures  October 22, 1999
                      replace V with N.value if they are not identical
                      V.csn := P.csn
                      }
-
-
-
-Legg & Payne             Expires 22 April 2000                 [Page 22]
-
-
-
-
-
-INTERNET-DRAFT   LDUP Update Reconciliation Procedures  October 22, 1999
-
-
                   }
                ELSE
                   {
@@ -1340,14 +1328,59 @@ INTERNET-DRAFT   LDUP Update Reconciliation Procedures  October 22, 1999
 
    6. Security Considerations
 
-   [To be supplied]
+   The procedures described in this document are not subject to access
+   controls on the directory data items being modified.  Specifically,
+   the update primitives received from a peer replica are applied
+   without regard for access controls.  This is necessary so that access
+   control information can also be replicated.  An LDUP enabled server
+   entering into a multi-master replication agreement with a peer server
+   is enabling joint authority and responsibility for some part of the
+   directory data.  A replica must trust that the other replicas are
+   properly enforcing access controls on user update requests, but this
+   trust extends only as far as described by the replication agreements
+   currently in place.  The replication agreement acts as a surrogate
+   for access controls between peer replicas.  Replication primitives
+
+
+
+Legg & Payne            Expires 29 December 2000               [Page 24]
+\f
+INTERNET-DRAFT   LDUP Update Reconciliation Procedures     June 29, 2000
+
+
+   that are outside the scope of the agreement are rejected.
+
+   Authentication of peer replica LDUP sessions and the security of the
+   exchange of replication primitives through the LDUP protocol are
+   outside the scope of this document and are described elsewhere.
+
+   Simultaneous updates at different replicas can result in two entries,
+   corresponding to two different real world entities, having the same
+   distinguished name.  The Update Reconciliation Procedures
+   disambiguate these two names by appending the respective Unique
+   Identifiers to the entries' RDNs.  This action will disable any
+   access controls based on an entry's specific DN or RDN.  Disabling
+   such an access control may have the effect of granting a permission
+   that was explicitly denied.  Since a Unique Identifier is required to
+   be globally unique for all time, appending a Unique Identifier to the
+   RDN cannot unintentionally enable access controls applying to a
+   different real world entity.
+
+   It is sufficient when disambiguating entry RDNs to append the UID to
+   only one of a pair of entries ending up with the same name.  The
+   Update Reconciliation Procedures require both entries to have their
+   UID appended to minimize the chance that either entry will gain
+   permissions intended for the other.  This is based on the assumption
+   that most access controls will grant permissions rather than deny
+   permissions.
 
 
    7. Acknowledgements
 
-   The authors would like to thank Suellen Faulks, Tony Robertson and
-   Mark Ennis from Telstra Research Laboratories who contributed to the
-   design and verification of the procedures described in this document.
+   The authors would like to thank Suellen Faulks and Tony Robertson
+   from Telstra and Mark Ennis from Adacel Technologies who contributed
+   to the design and verification of the procedures described in this
+   document.
 
    The authors would also like to thank the members of the LDUP
    architecture group for their input into the refinement of the design.
@@ -1355,29 +1388,36 @@ INTERNET-DRAFT   LDUP Update Reconciliation Procedures  October 22, 1999
 
    8. References
 
-   [LDUP Model] - E. Reed, "LDUP Replication Architecture", Internet
-   Draft, draft-merrells-ldup-model-01.txt, November 1998.
-
-   [BCP-11] - R. Hovey, S. Bradner, "The Organizations Involved in the
-   IETF Standards Process", BCP 11, RFC 2028, October 1996.
-
+   [RFC2119] - S. Bradner, "Key words for use in RFCs to Indicate
+   Requirement Levels", RFC 2119.
 
-   9. Intellectual Property Notice
+   [LDAPv3] - M. Wahl, S. Kille, T. Howes, "Lightweight Directory Access
+   Protocol (v3)", RFC 2251, December 1997.
 
-   The IETF takes no position regarding the validity or scope of any
-   intellectual property or other rights that might be claimed to
+   [X500] - ITU-T Recommendation X.500 (08/97) | ISO/IEC 9594-1:1998,
+   Information Technology - Open Systems Interconnection - The
 
 
 
-Legg & Payne             Expires 22 April 2000                 [Page 23]
+Legg & Payne            Expires 29 December 2000               [Page 25]
+\f
+INTERNET-DRAFT   LDUP Update Reconciliation Procedures     June 29, 2000
 
 
+   Directory:  Overview of concepts, models and services
 
+   [X511] - ITU-T Recommendation X.511 (08/97) | ISO/IEC 9594-3:1998,
+   Information Technology - Open Systems Interconnection - The
+   Directory:  Abstract service definition
 
+   [BCP-11] - R. Hovey, S. Bradner, "The Organizations Involved in the
+   IETF Standards Process", BCP 11, RFC 2028, October 1996.
 
-INTERNET-DRAFT   LDUP Update Reconciliation Procedures  October 22, 1999
 
+   9. Intellectual Property Notice
 
+   The IETF takes no position regarding the validity or scope of any
+   intellectual property 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; neither does it represent that it
@@ -1399,7 +1439,7 @@ INTERNET-DRAFT   LDUP Update Reconciliation Procedures  October 22, 1999
 
    10. Copyright Notice
 
-      Copyright (C) The Internet Society (1999). All Rights Reserved.
+      Copyright (C) The Internet Society (2000). All Rights Reserved.
 
    This document and translations of it may be copied and furnished to
    others, and derivative works that comment on or otherwise explain it
@@ -1412,6 +1452,14 @@ INTERNET-DRAFT   LDUP Update Reconciliation Procedures  October 22, 1999
    Internet organizations, except as needed for the purpose of
    developing Internet standards in which case the procedures for
    copyrights defined in the Internet Standards process must be
+
+
+
+Legg & Payne            Expires 29 December 2000               [Page 26]
+\f
+INTERNET-DRAFT   LDUP Update Reconciliation Procedures     June 29, 2000
+
+
    followed, or as required to translate it into languages other than
    English.
 
@@ -1426,38 +1474,26 @@ INTERNET-DRAFT   LDUP Update Reconciliation Procedures  October 22, 1999
    MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
 
 
-
-
-
-Legg & Payne             Expires 22 April 2000                 [Page 24]
-
-
-
-
-
-INTERNET-DRAFT   LDUP Update Reconciliation Procedures  October 22, 1999
-
-
-   11. Authors' Address
+   11. Authors' Addresses
 
    Steven Legg
-   Telstra Research Laboratories
-   770 Blackburn Road
-   Clayton, Victoria 3168
+   Adacel Technologies Ltd.
+   250 Bay Street
+   Brighton, Victoria 3186
    AUSTRALIA
 
-   Phone: +61 3 9253 6771
-     Fax: +61 3 9253 6485
-   EMail: s.legg@trl.telstra.com.au
+   Phone: +61 3 8530 7808
+     Fax: +61 3 9596 2960
+   EMail: steven.legg@adacel.com.au
 
    Alison Payne
-   PricewaterhouseCoopers
-   St Jakobs Strasse 25
-   CH-4002 Basel
-   SWITZERLAND
+   Telstra
+   21/242 Exhibition Street
+   Melbourne, Victoria 3000
+   AUSTRALIA
 
-   Phone: +41-79-458 4177
-   EMail: alison.b.payne@ch.pwcglobal.com
+   Phone: +61 3 9634 4628
+   EMail: alison.payne@team.telstra.com
 
    12. Appendix A - Changes From Previous Drafts
 
@@ -1471,14 +1507,22 @@ INTERNET-DRAFT   LDUP Update Reconciliation Procedures  October 22, 1999
 
    The semantics of re-added entries has been simplified so that only
    changes after the latest re-add are preserved instead of all those
-   after the earliest re-add. This eliminates the need for Addition CSNs
-   in the entry.  It is anticipated that new replication primitives will
-   be introduced to manage entries that come and go from partial
+   after the earliest re-add.  This eliminates the need for Addition
+
+
+
+Legg & Payne            Expires 29 December 2000               [Page 27]
+\f
+INTERNET-DRAFT   LDUP Update Reconciliation Procedures     June 29, 2000
+
+
+   CSNs in the entry.  It is anticipated that new replication primitives
+   will be introduced to manage entries that come and go from partial
    replicas instead of using p-add-entry and p-remove-entry.
 
    Orphaned entries are no longer moved directly to Lost & Found.
    Instead a glue entry is created in Lost & Found for the missing
-   superior and the orphaned entry becomes a subordinate of that. This
+   superior and the orphaned entry becomes a subordinate of that.  This
    change eliminates the need for explicit propagated primitives for
    moving orphaned entries to Lost & Found.
 
@@ -1486,18 +1530,6 @@ INTERNET-DRAFT   LDUP Update Reconciliation Procedures  October 22, 1999
    primitives.  There are no longer any references to saved primitives
    though the functionality is still present.
 
-
-
-
-Legg & Payne             Expires 22 April 2000                 [Page 25]
-
-
-
-
-
-INTERNET-DRAFT   LDUP Update Reconciliation Procedures  October 22, 1999
-
-
    The procedures for processing received replication primitives have
    been rearranged to follow a more consistent pattern where the
    presence of deletion records is tested first.
@@ -1508,31 +1540,71 @@ INTERNET-DRAFT   LDUP Update Reconciliation Procedures  October 22, 1999
    edition of X.500 so references to the proposed X.500 multimaster
    replication protocol have been removed.
 
-   The treatment of distinguished values has been simplified. Previously
-   an attempt to remove a distinguished value caused the value to be
-   tagged distinguished-not-present. Now the distinguished value is
-   removed, and if necessary, the Unique Identifier is made
-   distinguished to avoid an empty RDN. Optionally, the value to be
+   The treatment of distinguished values has been simplified.
+   Previously an attempt to remove a distinguished value caused the
+   value to be tagged distinguished-not-present.  Now the distinguished
+   value is removed, and if necessary, the Unique Identifier is made
+   distinguished to avoid an empty RDN.  Optionally, the value to be
    removed can be reasserted by emitting an explicit p-add-attribute-
    value primitive.
 
-   The current draft is more implementation neutral. A replication log
+   The current draft is more implementation neutral.  A replication log
    no longer figures prominently in the specification.  The previous
    descriptions had the user updates generating replication primitives,
    which in turn were used to determine the CSNs and deletion records.
    The new descriptions have user updates generating CSNs and deletion
    records and the primitives are subsequently generated from them.
 
-   13. Appendix B - Open Issues
+   12.3 Changes in Draft 03
+
+   The draft has been edited to make use of the key words "MUST",
+   "SHOULD", "MAY", etc.
+
+   The treatment of server maintained operational attributes has been
+   clarified.
+
+   An extra CheckUniqueness call has been added to the procedure for
+
+
+
+Legg & Payne            Expires 29 December 2000               [Page 28]
+\f
+INTERNET-DRAFT   LDUP Update Reconciliation Procedures     June 29, 2000
+
+
+   processing the p-add-entry primitive (Section 5.3.9) to cover the
+   case where an entry is re-added.  A loop through all of the values of
+   an entry in the p-add-entry and p-remove-entry processing has been
+   altered to explicitly skip the entryUUID operational attribute.  No
+   other changes have been made to the behaviour of the Update
+   Reconciliation Procedures from Draft 02.
+
+   The list of references has been expanded.
+
+   The Security Considerations section has been added.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
 
-   The precise location of the Lost & Found entry has not yet been
-   decided.
 
-   Extensions to the algorithms to properly deal with partial replicas
-   are still to be decided.
 
-   The draft needs some editing to use MAY, MUST, etc, in the proper
-   way.
 
 
 
@@ -1549,6 +1621,7 @@ INTERNET-DRAFT   LDUP Update Reconciliation Procedures  October 22, 1999
 
 
 
-Legg & Payne             Expires 22 April 2000                 [Page 26]
 
 
+Legg & Payne            Expires 29 December 2000               [Page 29]
+\f
diff --git a/doc/drafts/draft-zeilenga-ldap-authpasswd-xx.txt b/doc/drafts/draft-zeilenga-ldap-authpasswd-xx.txt
new file mode 100644 (file)
index 0000000..a4ae8e5
--- /dev/null
@@ -0,0 +1,501 @@
+INTERNET-DRAFT                                      Kurt D. Zeilenga
+Intended Category: Standard Track                   OpenLDAP Foundation
+Expires: 11 January 2001                            11 July 2000
+
+
+                  LDAP Authentication Password Attribute
+                 <draft-zeilenga-ldap-authpasswd-03.txt>
+
+
+
+1. Status of this Memo
+
+  This document is an Internet-Draft and is in full conformance with all
+  provisions of Section 10 of RFC2026.
+
+  This document is intended to be, after appropriate review and
+  revision, submitted to the RFC Editor as a Standard Track document.
+  Distribution of this memo is unlimited.  Technical discussion of this
+  document will take place on the IETF LDAP Extension Working Group
+  mailing list <ietf-ldapext@netscape.com>.  Please send editorial
+  comments directly to the author <Kurt@OpenLDAP.org>.
+
+  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.
+
+  Copyright 2000, The Internet Society.  All Rights Reserved.
+
+  Please see the Copyright section near the end of this document for
+  more information.
+
+
+2. Abstract
+
+  This document describes schema for storing information in support of
+  user/password authentication in a LDAP [RFC2251] directory.  The
+  document defines the authPassword attribute type and related schema.
+  The attribute type is used to store values derived from the user's
+  password(s) (commonly using cryptographic strength one-way hash).
+  authPassword is intended to used instead of clear text password
+
+
+
+Zeilenga                                                        [Page 1]
+\f
+INTERNET-DRAFT              LDAP AuthPasswd                 11 July 2000
+
+
+  storage mechanisms such as userPassword [RFC2256].  The values of
+  authPassword may be used to support both LDAP "simple" and SASL
+  [RFC2222] password authentication mechanisms [RFC2829].
+
+  The key words ``MUST'', ``MUST NOT'', ``REQUIRED'', ``SHALL'', ``SHALL
+  NOT'', ``SHOULD'', ``SHOULD NOT'', ``RECOMMENDED'',  and ``MAY'' in
+  this document are to be interpreted as described in RFC 2119
+  [RFC2119].
+
+
+3. Background and Intended Use
+
+  The userPassword attribute type [RFC 2256] is intended be used to used
+  to support the LDAP [RFC2251] "simple" bind operation.  However,
+  values of userPassword must be clear text passwords.  It is often
+  desirable to store values derived from the user's password(s) instead
+  of actual passwords.
+
+  The authPassword attribute type is intended to be used to store
+  information used to implement password based authentication.  The
+  attribute type may be used by LDAP servers to implement user/password
+  authentication operations [RFC2829] such "simple" and SASL [RFC2222] /
+  DIGEST-MD5 [RFC2831].
+
+  The attribute type supports multiple storage schemes.  A matching rule
+  is provided for use with extensible search filters to allow clients to
+  assert that a clear text password "matches" one of the attribute's
+  values.  Storage schemes often use of cryptographic strength one-way
+  hashing.
+
+  This attribute may be used in conjunction with server side password
+  generation mechanisms (such as [PW-EXOP]).
+
+  Access to this attribute may governed by administrative controls such
+  as those which implement password change policies.
+
+
+4. Schema Definitions
+
+  The following schema definitions are described in terms of LDAPv3
+  Attribute Syntax Definitions [RFC2252] with specific syntax detailed
+  using Augmented BNF [RFC2234].
+
+  Editor's Note: object identifiers (OIDs) will be assigned before this
+                 document is published as an RFC.
+
+4.1. authPasswordSyntax
+
+
+
+
+Zeilenga                                                        [Page 2]
+\f
+INTERNET-DRAFT              LDAP AuthPasswd                 11 July 2000
+
+
+    ( authPasswordSyntaxOID
+      DESC 'authentication password syntax' )
+
+  Values of this syntax are encoded according to the following BNF:
+
+    authPasswordValue = w scheme s [authInfo] s authValue w
+    scheme = <an IA5 string of uppercase letters, numbers,
+             and "-", "_", and "/">
+    authInfo = schemeSpecificValue
+    authValue = schemeSpecfiicValue
+    schemeSpecificValue = <an IA5 printable string
+                          not containing "$" or " ">
+    s = w sep w
+    w = *sp
+    sep = "$" ; an IA5 dollar sign (36)
+    sp = " "     ; an IA5 space (20)
+
+  where scheme describes the storage mechanism, authInfo and authValue
+  are a scheme specific.  The authInfo field is often a base64 encoded
+  salt.  The authValue field is often a base64 encoded value derived
+  from a user's password(s). Values of this attribute are case
+  sensitive.
+
+  This document describes a number of schemes, as well as requirements
+  for the scheme naming, in section 5.
+
+
+4.2. authPasswordMatch
+
+    ( authPasswordMatchOID
+      NAME 'authPasswordMatch'
+      DESC 'authentication password matching rule'
+      SYNTAX 1.3.6.1.4.1.1466.115.121.1.40{128} )
+
+  This matching rule allows a client to assert that a password matches
+  values of authPasswordSyntax using an extensibleMatch filter
+  component.  Each value is matched per its scheme.  The assertion is
+  TRUE if one or more attribute values matches the asserted value, FALSE
+  if all values do not matches, and Undefined otherwise.
+
+  Servers which support use of this matching rule SHOULD publish
+  appropriate matchingRuleUse values per [RFC2252], 4.4.
+
+  Transfer of authPasswordMatch assertion values is strongly discouraged
+  where the underlying transport service cannot guarantee
+  confidentiality and may result in disclosure of the values to
+  unauthorized parties.
+
+
+
+
+Zeilenga                                                        [Page 3]
+\f
+INTERNET-DRAFT              LDAP AuthPasswd                 11 July 2000
+
+
+4.3. supportedAuthPasswordSchemes
+
+    ( supportedAuthPasswordSchemesOID
+      NAME 'supportedAuthPasswordSchemes'
+      DESC 'supported password storage schemes'
+      EQUALITY caseExactIA5Match
+      SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{32}
+      USAGE dSAOperation )
+
+  The values of this attribute are names of supported authentication
+  password schemes which the server supports.  The syntax of a scheme
+  name is described in section 4.1.  This attribute may only be present
+  in the root DSE.  If the server does not support any mechanisms this
+  attribute will not be present.
+
+
+4.4. authPassword
+
+    ( authPasswordOID NAME 'authPassword'
+      SYNTAX authPasswordSyntaxOID )
+
+  The values of this attribute are representative of the user's
+  password(s) and conform to the authPasswordSyntax described in 4.1.
+  The values of this attribute may be used for authentication purposes.
+
+  This attribute type is defined without any built-in matching rules.
+  The absence of an EQUALITY matching rules disallows modification of
+  individual values.
+
+  Transfer of authPassword values is strongly discouraged where the
+  underlying transport service cannot guarantee confidentiality and may
+  result in disclosure of the values to unauthorized parties.
+
+
+4.5. authPasswordObject
+
+    ( authPasswordObjectOID NAME 'authPasswordObject'
+      DESC 'authentication password mix in class'
+      MAY 'authPassword'      AUXILIARY )
+
+  Entries of this object class may contain authPassword attribute types.
+
+
+5. Schemes
+
+  This section describes the "MD5", "SHA1", and "SASL/DIGEST-MD5".
+  Other schemes may be defined by other documents.  Schemes starting
+  with string "SASL/" indicate association with a SASL mechanism.
+
+
+
+Zeilenga                                                        [Page 4]
+\f
+INTERNET-DRAFT              LDAP AuthPasswd                 11 July 2000
+
+
+  Schemes which are not described by standard track documents SHOULD be
+  named with a leading "X-" or, if associated with a SASL mechanism,
+  "SASL/X-" to indicate they are a private or implementation specific
+  mechanism, or may be named using the dotted-decimal representation
+  [RFC2252] of an OID assigned to the mechanism.
+
+
+5.1. MD5 scheme
+
+  The MD5 [RFC1321] scheme name is "MD5".
+
+  The authValue is the base64 encoding of an MD5 digest of the
+  concatenation the user password and optional salt.  The base64
+  encoding of the salt is provided in the authInfo field.
+  Implementations of this scheme must support salts up to 128-bit in
+  length.  Use with a 64-bit or larger salt is RECOMMENDED.
+
+  Example:
+    Given a user "joe" who's password is "mary" and a salt of "salt",
+    the authInfo field would be the base64 encoding of "salt" and the
+    authValue field would be the base64 encoding of the MD5 digest of
+    "marysalt".
+
+  A match against an asserted password and an attribute value of this
+  scheme SHALL be true if and only if the MD5 digest of concatenation of
+  the asserted value and the salt is equal to the MD5 digest contained
+  in AuthValue.  The match SHALL be undefined if the server is unable to
+  complete the equality test for any reason.  Otherwise the match SHALL
+  be false.
+
+  Values of this scheme SHOULD only be used to implement simple
+  user/password authentication.
+
+  It is RECOMMENDED that values of this scheme be protected as if they
+  were clear text passwords.
+
+
+5.2. SHA1 scheme
+
+  The SHA1 [SHA1] scheme name is "SHA1".
+
+  The authValue is the base64 encoding of an SHA1 digest of the
+  concatenation the user password and the optional salt.  The base64
+  encoding of the salt is provided in the authInfo field.
+  Implementations of this scheme must support salts up to 128-bit in
+  length.  Use with a 64-bit or larger salt is RECOMMENDED.
+
+  Example:
+
+
+
+Zeilenga                                                        [Page 5]
+\f
+INTERNET-DRAFT              LDAP AuthPasswd                 11 July 2000
+
+
+    Given a user "joe" who's password is "mary" and a salt of "salt",
+    the authInfo field would be the base64 encoding of "salt" and the
+    authValue field would be the base64 encoding of the SHA1 digest of
+    "marysalt".
+
+  A match against an asserted password and an attribute value of this
+  scheme SHALL be true if and only if the SHA1 digest of concatenation
+  of the asserted value and the salt is equal to the SHA1 digest
+  contained in AuthValue.  The match SHALL be undefined if the server is
+  unable to complete the equality test for any reason.  Otherwise the
+  match SHALL be false.
+
+  Values of this scheme SHOULD only be used to implement simple
+  user/password authentication.
+
+  It is RECOMMENDED that values of this scheme be protected as if they
+  were clear text passwords.
+
+
+5.3. DIGEST-MD5 scheme
+
+  The DIGEST-MD5 scheme name is "SASL/DIGEST-MD5".
+
+  The authValue is the base64 encoding of
+    H( { username-value, ":", realm-value, ":", passwd } )
+
+  and authInfo is the base64 encoding of
+    { username-value, ":", realm-value }
+
+  as defined by RFC2831.
+
+  Example:
+    Given a user "joe" within the realm "localhost" who's password is
+    "mary", the info field would be the base64 encoding of
+    "joe:localhost" and the authValue field would be the base64 encoding
+    of the MD5 digest of "joe:localhost:mary".
+
+  Values of this scheme SHOULD only be used to implement the
+  SASL/DIGEST-MD5 as described by the Authentication Methods for LDAP
+  [RFC2829].  A simple password assertion against a value of this scheme
+  SHALL be considered undefined.
+
+  Values of this scheme MUST be protected as if it the values were clear
+  text passwords per reasons detailed in DIGEST-MD5, Section 3.9,
+  "Storing Passwords."
+
+
+6. Implementation Issues
+
+
+
+Zeilenga                                                        [Page 6]
+\f
+INTERNET-DRAFT              LDAP AuthPasswd                 11 July 2000
+
+
+  For implementations of this specification:
+
+    Servers MAY restrict which schemes are used in conjunction with a
+    particular authentication process but SHOULD use all values of
+    selected schemes.  If the asserted password matches any of the
+    stored values, the asserted password SHOULD be considered valid.
+    Servers MAY use other authentication storage mechanisms, such as
+    userPassword or an external password store, in conjunction with
+    authPassword to support the authentication process.
+
+    Servers that support simple bind MUST support the MD5 scheme and
+    SHOULD support the SHA1 scheme.
+
+    Servers SHOULD not publish values of authPassword nor allow
+    operations which expose authPassword or AuthPasswordMatch values to
+    unless confidentiality protection is in place.
+
+    Clients SHOULD not initiate operations which provide or request
+    values of authPassword or make authPasswordMatch assertions unless
+    confidentiality protection is in place.
+
+    Clients SHOULD not assume that a successful AuthPasswordMatch,
+    whether by compare or search, is sufficient to gain directory
+    access.  The bind operation MUST be used to authentication to the
+    directory.
+
+
+7. Security Considerations
+
+  This document describes how authentication information may be stored
+  in a directory.  Authentication information must be adequately
+  protected as unintended disclosure will allow attackers to gain
+  immediate access to the directory as described by [RFC2829].
+
+  Values of authPassword SHOULD be protected as if they were clear text
+  passwords.  When values are transferred, privacy protections, such as
+  IPSEC or TLS, SHOULD be in place.
+
+  Clients SHOULD use strong authentication mechanisms [RFC2829].
+
+  AuthPasswordMatch matching rule allows applications to test the
+  validity of a user password and, hence, may be used to mount a
+  dictionary attack.  Servers SHOULD take appropriate measures to
+  protect the directory from such attacks.
+
+  Some password schemes may require CPU intensive operations.  Servers
+  SHOULD take appropriate measures to protect against Denial of Service
+  attacks.
+
+
+
+Zeilenga                                                        [Page 7]
+\f
+INTERNET-DRAFT              LDAP AuthPasswd                 11 July 2000
+
+
+  AuthPassword does not restrict an authentication identity to a single
+  password.  An attacker who gains write access to this attribute may
+  store additional values without disabling the user's true password(s).
+  Use of policy aware clients and servers is RECOMMENDED.
+
+  The level of protection offered against various attacks differ from
+  scheme to scheme.  It is RECOMMENDED that servers support scheme
+  selection as a configuration item.  This allows for a scheme to be
+  easily disabled if a significant security flaw is discovered.
+
+
+8. Copyright
+
+  Copyright 2000, The Internet Society.  All Rights Reserved.
+
+  This document and translations of it may be copied and furnished to
+  others, and derivative works that comment on or otherwise explain it
+  or assist in its implementation may be prepared, copied, published and
+  distributed, in whole or in part, without restriction of any kind,
+  provided that the above copyright notice and this paragraph are
+  included on all such copies and derivative works.  However, this
+  document itself may not be modified in any way, such as by removing
+  the copyright notice or references to the Internet Society or other
+  Internet organizations, except as needed for the  purpose of
+  developing Internet standards in which case the procedures for
+  copyrights defined in the Internet Standards process must be followed,
+  or as required to translate it into languages other than English.
+
+  The limited permissions granted above are perpetual and will not be
+  revoked by the Internet Society or its successors or assigns.
+
+  This document and the information contained herein is provided on an
+  "AS IS" basis and THE AUTHORS, THE INTERNET SOCIETY, AND THE INTERNET
+  ENGINEERING TASK FORCE DISCLAIMS 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.
+
+
+9. Acknowledgment
+
+  This document borrows from a number of IETF documents and is based
+  upon input from the IETF LDAPext working group.
+
+
+10. Bibliography
+
+  [RFC1321] R. Rivest, "The MD5 Message-Digest Algorithm", RFC 1321,
+
+
+
+Zeilenga                                                        [Page 8]
+\f
+INTERNET-DRAFT              LDAP AuthPasswd                 11 July 2000
+
+
+            April 1992
+
+  [RFC2219] S. Bradner, "Key words for use in RFCs to Indicate
+            Requirement Levels", RFC 2119, March 1997.
+
+  [RFC2222] J. Myers, "Simple Authentication and Security Layer (SASL)",
+            RFC 2222, October 1997.
+
+  [RFC2234] D. Crocker (editor), P. Overell, "Augmented BNF for Syntax
+            Specifications: ABNF", RFC 2234, November 1997.
+
+  [RFC2251] M. Wahl, T. Howes, S. Kille, "Lightweight Directory Access
+            Protocol (v3)", RFC 2251, December 1997.
+
+  [RFC2252] M. Wahl, A. Coulbeck, T. Howes, S. Kille, "Lightweight
+            Directory Access Protocol (v3):  Attribute Syntax
+            Definitions", RFC 2252, December 1997.
+
+  [RFC2256] M. Wahl, "A Summary of the X.500(96) User Schema for use
+            with LDAPv3", RFC 2256, December 1997.
+
+  [RFC2307] L. Howard, "An Approach for Using LDAP as a Network
+            Information Service", RFC 2307, March 1998.
+
+  [RFC2829] M. Wahl, H. Alvestrand, J. Hodges, RL "Bob" Morgan,
+            "Authentication Methods for LDAP", RFC 2829, June 2000.
+
+  [RFC2831] P. Leach, C. Newman, "Using Digest Authentication as a SASL
+            Mechanism", RFC 2831, June 2000.
+
+  [PW-EXOP] K. Zeilenga, "LDAP Password Modify Extended Operation"
+            draft-zeilenga-ldap-passwd-exop-xx.txt, a work in progress.
+
+  [SHA1]    NIST, FIPS PUB 180-1: Secure Hash Standard, April 1995.
+
+
+11.  Author's Address
+
+  Kurt D. Zeilenga
+  OpenLDAP Foundation
+  <Kurt@OpenLDAP.org>
+
+
+
+
+
+
+
+
+
+
+Zeilenga                                                        [Page 9]
+\f
diff --git a/doc/drafts/draft-zeilenga-ldap-grouping-xx.txt b/doc/drafts/draft-zeilenga-ldap-grouping-xx.txt
new file mode 100644 (file)
index 0000000..8b06d90
--- /dev/null
@@ -0,0 +1,507 @@
+
+
+
+
+
+
+INTERNET-DRAFT                                      Kurt D. Zeilenga
+Intended Category: Standard Track                   OpenLDAP Foundation
+Expires: 4 January 2001                             4 July 2000
+
+
+                  LDAPv3: Grouping of Related Operations
+                  <draft-zeilenga-ldap-grouping-00.txt>
+
+
+Status of Memo
+
+  This document is an Internet-Draft and is in full conformance with all
+  provisions of Section 10 of RFC2026.
+
+  This document is intended to be, after appropriate review and
+  revision, submitted to the RFC Editor as a Standard Track document.
+  Distribution of this memo is unlimited.  Technical discussion of this
+  document will take place on the IETF LDAP Extension Working Group
+  mailing list <ietf-ldapext@netscape.com>.  Please send editorial
+  comments directly to the author <Kurt@OpenLDAP.org>.
+
+  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.
+
+  Copyright 2000, The Internet Society.  All Rights Reserved.
+
+  Please see the Copyright section near the end of this document for
+  more information.
+
+
+1. Abstract
+
+  This document provides a general mechanisms for grouping related LDAP
+  operations.  Grouping of operations may be used to support
+  replication, proxies, and higher level operations such as
+  transactions.  This document describes a set of LDAP [RFC2251]
+  extended operations and other protocol and schema elements to support
+  grouping of related operations.
+
+
+
+
+Zeilenga                                                        [Page 1]
+\f
+INTERNET-DRAFT       draft-zeilenga-ldap-grouping-00         4 July 2000
+
+
+2. Overview
+
+  This document provides a mechanism to allow clients to group
+  operations.
+
+  A group of operations is defined as a set of operations upon a common
+  session identified by a unique cookie.  All requests which are
+  initiated with the same cookie belong to same grouping.  The cookie is
+  obtained using the create group operation and is normally valid until
+  the end group operation is issued.  A group may be ended by a server
+  prematurely as noted described below.
+
+  Operations regardless of their grouping (or lack of grouping) may be
+  intermixed.  Groups may be nested.
+
+  Each group is of a particular type.  This type defines the semantics
+  of the group and is specified when the group is created.
+
+  The key words "SHALL", "SHALL NOT", "MUST", "MUST NOT", "SHOULD",
+  "SHOULD NOT", "MAY" and "MAY NOT" used in this document are to be
+  interpreted as described in [RFC2119].
+
+
+3. Protocol Elements
+
+  This document describes two extended operations, one unsolicited
+  notification, and one control.  Extended operations and controls are
+  described by LDAP [RFC2251] as follows:
+
+    ExtendedRequest ::= [APPLICATION 23] SEQUENCE {
+      requestName    [0] LDAPOID,
+      requestValue   [1] OCTET STRING OPTIONAL
+    }
+
+    ExtendedResponse ::= [APPLICATION 24] SEQUENCE {
+      COMPONENTS of LDAPResult,
+      responseName   [10] LDAPOID OPTIONAL,
+      response       [11] OCTET STRING OPTIONAL
+    }
+
+    Control ::= SEQUENCE {
+      controlType    LDAPOID,
+      criticality    BOOLEAN DEFAULT FALSE,
+      controlValue   OCTET STRING OPTIONAL
+    }
+
+
+  Editor's Note:
+
+
+
+Zeilenga                                                        [Page 2]
+\f
+INTERNET-DRAFT       draft-zeilenga-ldap-grouping-00         4 July 2000
+
+
+    OID which appear in this document are fictious.  Actual OIDs will be
+    assigned before this document is progressed.
+
+3.1 Common Protocol Elements
+
+    groupCookie :== OCTET STRING
+
+  A groupCookie is an arbitrary octet string uniquely identify a
+  grouping of related operations within the session.
+
+  A groupCookie is a notational convenience.
+
+
+
+3.2 createGrouping Operation
+
+  The createGrouping extended operation is used to create or start a
+  grouping of related operations.  The operation consists of the
+  createGroupingRequest and the createGroupingResponse.  The OID
+  createGroupingOID identifies this operation and SHOULD be listed as a
+  value of supportedExtensions in the root DSE of servers which support
+  this operation.
+
+    createGroupingOID ::= "1.1.1"
+
+
+3.2.1 createGroupingRequest
+
+  The client initiates this operation by sending a
+  createGroupingRequest.  This request is an ExtendedRequest where the
+  requestName is the value createGroupOID and requestValue is BER
+  encoded createGroupingRequestValue
+
+    createGroupingRequestValue ::= SEQUENCE {
+      createGroupType     [0] LDAPOID,
+      createGroupValue    [1] OCTET STRING OPTIONAL
+    }
+
+  where createGroupType is an OID that describes the specific type of
+  grouping and createGroupValue contains a type specific payload.
+
+
+3.2.1 createGroupingResponse
+
+  The createGroupingResponse is sent in response to a
+  createGroupingRequest.  This response is an ExtendedResponse where the
+  responseName MUST be the value of the requestName provided in request
+  and the response is a BER encoded createGroupingResponseValue.
+
+
+
+Zeilenga                                                        [Page 3]
+\f
+INTERNET-DRAFT       draft-zeilenga-ldap-grouping-00         4 July 2000
+
+
+    createGroupingResponseValue ::= SEQUENCE {
+      createGroupCookie [0] groupCookie,
+      createGroupValue  [1] OCTET STRING OPTIONAL
+    }
+
+  where createGroupCookie is a cookie uniquely identifying the grouping
+  and createGroupValue is a type specific payload.
+
+
+3.3 endGrouping Operation
+
+  The endGrouping extended operation is used to end or stop a grouping
+  of related operations.  The operation consists of the
+  endGroupingRequest and the endGroupingResponse.  The OID
+  endGroupingOID identifies this operation and SHOULD be listed as a
+  value of supportedExtensions in the root DSE of servers which support
+  this operation.
+
+    endGroupingOID ::= "1.1.2"
+
+
+3.3.1 endGroupingRequest
+
+  The client initiates this operation by sending an endGroupingRequest.
+  This request is an ExtendedRequest where the requestName is the value
+  endGroupOID and requestValue is BER encoded endGroupingRequestValue
+
+    endGroupingRequestValue ::= SEQUENCE {
+      endGroupCookie  [0] groupCookie,
+      groupValue [1] OCTET STRING OPTIONAL
+    }
+
+  where endGroupCookie is an cookie identifying the grouping and
+  groupValue contains a type specific payload.
+
+
+3.3.2 endGroupingResponse
+
+  The endGroupingResponse is sent in response to a endGroupingRequest.
+  This response is an ExtendedResponse where the responseName MUST be
+  the value of the requestName provided in request and the response is a
+  BER encoded endGroupingResponseValue
+
+    endGroupingResponseValue ::= SEQUENCE {
+      groupValue  [1] OCTET STRING OPTIONAL
+    }
+
+  where groupValue is a type specific payload.
+
+
+
+Zeilenga                                                        [Page 4]
+\f
+INTERNET-DRAFT       draft-zeilenga-ldap-grouping-00         4 July 2000
+
+
+3.4 endGroupingNotice
+
+  The endGroupingNotice is an LDAP unsolicited notification.  The
+  notification may be sent to the client to end a grouping which the
+  server is unable or unwilling to continue to process.  The notice is
+  an extendedResponse where the responseName is the OID
+  endGroupingNoticeOID and the response is a BER encoded
+  endGroupingNoticeValue
+
+    endGroupingNoticeOID ::= "1.1.3"
+
+    endGroupingNoticeValue ::= SEQUENCE {
+      endGroupingCookie [0] groupCookie,
+      groupValue        [1] OCTET STRING OPTIONAL
+    }
+
+  where endGroupingCookie is a cookie uniquely identifying the grouping
+  and groupingValue contains a type specific payload.
+
+
+3.5 groupingControl
+
+  The groupingControl is used to identify requests and responses as
+  belonging to grouping of operations.  The groupingControl is a Control
+  where the controlType is the OID groupingControlOID and the
+  criticalValue is a BER encoded groupingControlValue
+
+    groupingControlOID ::= "1.1.4"
+
+    groupingControlValue ::= SEQUENCE {
+      groupingCookie   [0] groupCookie,
+      groupValue       [1] OCTET STRING OPTIONAL
+    }
+
+  where groupingCookie is a cookie uniquely identifying the grouping,
+  the critical is TRUE, and groupingValue contains a type specific
+  payload.
+
+  The value groupingControlOID SHOULD be listed as a value of
+  supportedControls in the root DSE by servers which support this
+  control.
+
+  The control MAY be present on add, compare, delete, moddn, modify, and
+  search requests and responses.  The control SHALL NOT be present on a
+  abandon, bind, unbind.  The control SHALL NOT be present on any
+  extended operation which affects the behavior of the session such as
+  the Start TLS [RFC2830] operation.  The control SHALL NOT be present
+  if the operation includes any control which likewise causes the
+
+
+
+Zeilenga                                                        [Page 5]
+\f
+INTERNET-DRAFT       draft-zeilenga-ldap-grouping-00         4 July 2000
+
+
+  operation to affects the behavior of the session.
+
+  The control SHALL NOT appear multiple times in the same LDAP PDU and.
+  If multiple occurrences of the control are detected, the PDU MUST be
+  treated as a protocol error.
+
+4. Schema Elements
+
+4.1. supportedGroupingTypes
+
+  Servers SHOULD publish grouping types they support listing their OID
+  as values of the supportedGrouping attribute type in the root DSE.
+  The supportedGrouping attribute type is defined as:
+
+    ( 1.1.5 NAME 'supportedGroupingTypes'
+      DESC 'supported types of groupings of operations'
+      EQUALITY objectIdentifierMatch
+      SYNTAX ObjectIdentifierSyntax )
+
+
+5. Operational Semantics
+
+  This section needs work.
+
+
+5.1 Grouping Operations
+
+
+5.1.1 createGrouping
+
+  To group related operations, the client MUST request a groupCookie
+  from the server by sending a createGroupingRequest as described in
+  3.2.1.  The client SHALL provide type specific payload in
+  createGroupValue if so required by the grouping type.
+
+  The server SHALL respond with a createGroupingResponse as described in
+  3.2.2.  If the server is willing and able to create the grouping as
+  requested (and per type requirements), it SHALL respond with success,
+  provide a session-unique groupCookie and, if appropriate, a type
+  specific payload.  Otherwise the server SHALL respond with a non-
+  successful response and provide no groupCookie, but MAY, if
+  appropriate, provide a type specific payload.
+
+
+5.1.2 endGrouping
+
+  When the client wishes to end the grouping, the client SHALL send a
+  endGroupingRequest as described in 3.3.1.  The client SHALL provide
+
+
+
+Zeilenga                                                        [Page 6]
+\f
+INTERNET-DRAFT       draft-zeilenga-ldap-grouping-00         4 July 2000
+
+
+  the groupCookie of the grouping to be ended and MAY provided a type
+  specific payload.
+
+  The server SHALL respond with an endGroupingResponse as described in
+  3.3.2.
+
+
+5.1.3 endGroupNotice
+
+  The server MAY end a group without solicitation for any reason but
+  MUST send a endGrouping Notice, as described in 3.4, indicating this
+  action.  The server SHALL provide the groupCookie of the group it
+  terminated and MAY provide a type specific payload.  The notice SHALL
+  have a non-success resultCode.
+
+
+5.1.4 grouped operations
+
+  Operations with a group are carry a groupingControl as described in
+  3.5.
+
+  Group type specifications MAY restrict the types and/or number of
+  operations which may be related.  Servers MAY also place restrictions
+  upon groupings.  Clients SHOULD NOT assume arbitrary support for
+  grouping.
+
+
+5.1.5 nested groupings
+
+  Groups of the same or different types may be nested.  A nested group
+  is instantiated by providing a groupingControl containing the parent
+  group with the createGroupingRequest.
+
+  Group type specifications MAY restrict the types of groupings which
+  may be nested.  Servers MAY also place restrictions upon nesting.
+  Clients SHOULD NOT assume arbitrary support for nesting.
+
+
+5.3 Other Operations
+
+  Upon issuing of any grouping operation, semantics of non-grouping
+  operations listed is modified as described below.
+
+5.3.1 bind
+
+  The client SHOULD end all outstanding groupings before issuing a bind
+  request.
+
+
+
+
+Zeilenga                                                        [Page 7]
+\f
+INTERNET-DRAFT       draft-zeilenga-ldap-grouping-00         4 July 2000
+
+
+  The bind operation MUST, in addition to the behavior described in RFC
+  2251, must abandon all outstanding groups.
+
+
+5.3.2 unbind
+
+  The unbind operation MUST, in addition to the behavior described in
+  RFC 2251, must abandon all outstanding groups.
+
+
+5.3.3 Start TLS
+
+  The client SHALL end all outstanding groupings before issuing a Start
+  TLS request.
+
+  The Start TLS operation MUST, in addition to the behavior described in
+  RFC 2830, return operationsError if there are any outstanding
+  groupings.
+
+
+7. Security Considerations
+
+  This mechanism may be used to support complex groupings of related
+  operations for arbitrary purposes.  This document places no
+  restrictions on how the grouped operations relate to each other.
+
+  It is conceived that different groups of operations may have different
+  authorization and/or access controls associated with them (when used
+  to multiplex proxied directory sessions).  Authors of specifications
+  for such groupings take special care in addressing security issues.
+
+  It is conceived that different groups of operations may form complex
+  super-operations such as transactions.  Authors of specifications for
+  such groupings should take special care to address denial of service
+  issues.
+
+
+8. References
+
+  [RFC2119] S. Bradner, "Key Words for use in RFCs to Indicate
+            Requirement Levels", Harvard University, RFC 2119, March
+            1997.
+
+  [RFC2251] M. Wahl, S. Kille, T. Howes, "Lightweight Directory Access
+            Protocol (v3)", RFC 2251, December 1997.
+
+
+9. Acknowledgments
+
+
+
+Zeilenga                                                        [Page 8]
+\f
+INTERNET-DRAFT       draft-zeilenga-ldap-grouping-00         4 July 2000
+
+
+  The author gratefully acknowledge the contributions of the IETF LDUP
+  and LDAPext working group.
+
+
+10. Additional Information
+
+  Discussions regarding these suggestions may directed to the author:
+
+  Kurt D. Zeilenga
+  OpenLDAP Foundation
+  <Kurt@OpenLDAP.org>
+
+  or the LDAPext Working Group mailing list:
+
+  <ietf-ldapext@netscape.com>
+
+
+Copyright 2000, The Internet Society.  All Rights Reserved.
+
+  This document and translations of it may be copied and furnished
+  to others, and derivative works that comment on or otherwise explain
+  it or assist in its implementation may be prepared, copied, published
+  and distributed, in whole or in part, without restriction of any
+  kind, provided that the above copyright notice and this paragraph
+  are included on all such copies and derivative works.  However,
+  this document itself may not be modified in any way, such as by
+  removing the copyright notice or references to the Internet Society
+  or other Internet organizations, except as needed for the  purpose
+  of developing Internet standards in which case the procedures for
+  copyrights defined in the Internet Standards process must be
+  followed, or as required to translate it into languages other than
+  English.
+
+  The limited permissions granted above are perpetual and will not
+  be revoked by the Internet Society or its successors or assigns.
+
+  This document and the information contained herein is provided on
+  an "AS IS" basis and THE AUTHORS, THE INTERNET SOCIETY, AND THE
+  INTERNET ENGINEERING TASK FORCE DISCLAIMS 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                                                        [Page 9]
+\f
diff --git a/doc/drafts/draft-zeilenga-ldap-namedref-xx.txt b/doc/drafts/draft-zeilenga-ldap-namedref-xx.txt
new file mode 100644 (file)
index 0000000..c4fc770
--- /dev/null
@@ -0,0 +1,675 @@
+
+
+
+
+
+
+INTERNET-DRAFT                                      Kurt D. Zeilenga
+Intended Category: Standard Track                   OpenLDAP Foundation
+Expires: 4 January 2001                             4 July 2000
+
+
+                   Named References in LDAP Directories
+                  <draft-zeilenga-ldap-namedref-00.txt>
+
+1.      Status of this Memo
+
+  This document is an Internet-Draft and is in full conformance with all
+  provisions of Section 10 of RFC2026.
+
+  This document is intended to be, after appropriate review and
+  revision, submitted to the RFC Editor as a Standard Track document.
+  Distribution of this memo is unlimited.  Technical discussion of this
+  document will take place on the IETF LDAP Extension Working Group
+  mailing list <ietf-ldapext@netscape.com>.  Please send editorial
+  comments directly to the author <Kurt@OpenLDAP.org>.
+
+  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.
+
+  Copyright 2000, The Internet Society.  All Rights Reserved.
+
+  Please see the Copyright section near the end of this document for
+  more information.
+
+2.  Abstract
+
+  This document defines schema and protocol elements for representing
+  and manipulating generic knowledge information in LDAP [RFC2251]
+  directories.  An attribute type "ref" is used to store URIs [RFC1738]
+  which may refer to LDAP and non-LDAP services.  An object class
+  "referral" is used to construct entries in an LDAP directory which
+  references to other directories or services.  An control, ManageDsaIT,
+  is defined to allow clients to manipulate referral objects as normal
+  entries.  The document describes procedures directory servers should
+  follow when supporting these elements.
+
+
+
+Zeilenga                                                        [Page 1]
+\f
+INTERNET-DRAFT       draft-zeilenga-ldap-namedref-00         4 July 2000
+
+
+3.  Background and intended usage
+
+  The broadening of interest in LDAP directories beyond their use as
+  front ends to X.500 directories has created a need to represent
+  knowledge information in a more general way. Knowledge information is
+  information about one or more servers maintained in another server,
+  used to link servers and services together.
+
+  This document defines a general method of representing knowledge
+  information in LDAP directories, based on URIs.
+
+  This document does not detail client processing of referral and search
+  reference responses.  This is detailed in RFC 2251 or subsequent
+  documents.
+
+  The key words "SHALL", "SHALL NOT", "MUST", "MUST NOT", "SHOULD",
+  "SHOULD NOT", "MAY" and "MAY NOT" used in this document are to be
+  interpreted as described in [RFC2119].
+
+
+4.  Schema
+
+4.1  The ref attribute type
+
+  This section defines the ref attribute type for holding general
+  knowledge reference information.
+
+      ( 2.16.840.1.113730.3.1.34
+          NAME 'ref'
+          DESC 'URI reference'
+          EQUALITY caseExactIA5Match
+          SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
+          USAGE distributedOperation )
+
+  The ref attribute type has IA5 syntax and is case sensitive.  The ref
+  attribute is multi valued. Values placed in the attribute MUST conform
+  to the specification given for the labeledURI attribute defined in
+  [RFC2079].  The labeledURI specification defines a format that is a
+  URI, optionally followed by whitespace and a label. This document does
+  not make use of the label portion of the syntax.  Future documents MAY
+  enable new functionality by imposing additional structure on the label
+  portion of the syntax as it appears in the ref attribute.
+
+  If the URI contained in a ref attribute value refers to an LDAPv3
+  server, it MUST be in the LDAP URI scheme described in [RFC2255].
+  Other URI schemes MAY be used but MUST refer to services which are
+  capable of completing operations referred to the services.  The URI
+  values, regardless of scheme, contained in a ref attribute must point
+
+
+
+Zeilenga                                                        [Page 2]
+\f
+INTERNET-DRAFT       draft-zeilenga-ldap-namedref-00         4 July 2000
+
+
+  to services which are equally capable of handling operations refer to
+  said services.
+
+  The integrity of the URI SHALL NOT be validated by the server holding
+  or returning the reference.
+
+  When returning a referral result, the server MUST NOT return the label
+  portion of the labeledURI as part of the referral. Only the URI
+  portion of the ref attribute SHOULD be returned.
+
+  The ref attribute SHOULD NOT be used for naming.
+
+
+4.2.  The referral object class
+
+  The referral object class is defined as follows.
+
+      ( 2.16.840.1.113730.3.2.6
+          NAME 'referral'
+          DESC 'named reference object'
+          STRUCTURAL MUST ref )
+
+  The referral object class is a structural object class used to
+  represent a named reference in the directory.  The referral object
+  class SHOULD be used in conjunction with the extensibleObject object
+  class to support the naming attributes used in the entry's
+  distinguished name.
+
+  In the presence of a ManageDsaIT control, referral objects are treated
+  as normal entries.  Note that the ref attribute is operational and
+  will only returned in a search entry response when requested.
+
+  In the absence of a ManageDsaIT control, referral objects contents are
+  used to construct referrals and search references and, as such, the
+  referral entries themselves are general visible to clients.
+
+
+5.  Use of the ref attribute
+
+  Two uses the ref attribute is defined in this document.  The first
+  use, in conjunction with the referral object class, represents a named
+  reference.  The second use, in conjunction with the Root DSE,
+  represents superior reference.  The following sections detail these
+  usages of the ref attribute.
+
+  Other uses of the ref attribute MAY be defined in subsequent
+  documents, or by bilateral agreement between cooperating clients and
+  servers and SHOULD be defined in conjunction with an object class
+
+
+
+Zeilenga                                                        [Page 3]
+\f
+INTERNET-DRAFT       draft-zeilenga-ldap-namedref-00         4 July 2000
+
+
+  indicating the usage.
+
+
+5.1.  Named reference
+
+  A named reference is used to facilitate distributed name resolution or
+  search across multiple servers.  The ref attribute appears in an
+  referral object (an entry with object class of referral) named in the
+  referencing server.  The value of the ref attribute points to the
+  corresponding entry maintained in the referenced server.
+
+  While the distinguished name in a value of the ref attribute is
+  typically that of an entry in a naming context below the naming
+  context held by the referencing server, it is permitted to be the
+  distinguished name of any entry.  If the ref attribute is multi-valued
+  all the DNs in the values of the ref attribute SHOULD have the same
+  value.  Administrators SHOULD avoid configuring naming loops using
+  referrals.
+
+  The URI SHOULD NOT explicitly define a scope and the server SHOULD NOT
+  explicitly add a scope to the URI before returning it to the client as
+  a referral or search reference as the scope is implied by the
+  operation.
+
+  Named references MUST be treated as normal entries if the request
+  includes the ManageDsaIT control.  The remainder of this section
+  describes processing of requests which do not include the ManageDsaIT
+  control.
+
+
+5.1.1.  Scenarios
+
+  The following sections contain specifications of how referral objects
+  should be used in different scenarios followed by examples that
+  illustrate that usage. The scenarios described consist of referral
+  operation when finding target of a non-search operation, when finding
+  the base of a search operation, and when generating search references.
+
+  It is to be noted that, in this document, a search operation is
+  conceptually divided into two distinct, sequential phases: (1) finding
+  the base object where the search is to begin, and (2) performing the
+  search itself. The operation of the server with respect to referrals
+  in phase (1) is similar to the operation of the server while finding
+  the target object for a non-search operations.
+
+  It is to also be noted that the ref attribute may have multiple values
+  and, where these sections refer to a single ref attribute value,
+  multiple ref attribute values may be substituted and SHOULD be
+
+
+
+Zeilenga                                                        [Page 4]
+\f
+INTERNET-DRAFT       draft-zeilenga-ldap-namedref-00         4 July 2000
+
+
+  processed and returned as a group in a referral or search reference in
+  the same way as described for a single ref attribute value.
+
+  Search references returned for a given request may be returned in any
+  order.
+
+
+5.1.1.1.  Example configuration
+
+
+   |------------------------------------------------------------|
+   |                    Server A                                |
+   | dn: o=abc,c=us                dn: o=xyz,c=us               |
+   | o: abc                        o: xyz                       |
+   | ref: ldap://hostB/o=abc,c=us  ref: ldap://hostD/o=xyz,c=us |
+   | ref: ldap://hostC/o=abc,c=us  objectclass: referral        |
+   | objectclass: referral         objectclass: extensibleObject|
+   | objectclass: extensibleObject                              |
+   |____________________________________________________________|
+
+   |------------------| |------------------| |------------------|
+   |       Server B   | |       Server D   | |      Server C    |
+   | dn: o=abc,c=us   | | dn: o=xyz,c=us   | | dn: o=abc,c=us   |
+   | o: abc           | | o: xyz           | | o: abc           |
+   | other attributes | | other attributes | | other attributes |
+   |__________________| |__________________| |__________________|
+
+  In this example, Server A holds references for two entries:
+  "o=abc,c=us" and "o=xyz,c=us". For the "o=abc,c=us" entry, Server A
+  holds two references, one to Server B and one to Server C.  The
+  entries referenced are replicas of each other. For the "o=xyz,c=us"
+  entry, Server A holds a single reference to the entry contained in
+  Server D.
+
+  In the following protocol interaction examples, the client has
+  contacted Server A.  Server A holds the naming context "c=us".
+
+
+5.1.1.2.  Base or Target object considerations
+
+  As previously described, the process of generating referrals for a
+  search can be described in two phases. The first, which is described
+  in this section, is generating referrals based on the base object
+  specified in the search. This process is similar to the process of
+  generating referrals based on the target object while processing other
+  operations (modify, add, delete, modify DN, and compare) with the sole
+  exception that for these other operations, the DN in the referral must
+  be modified in some cases.
+
+
+
+Zeilenga                                                        [Page 5]
+\f
+INTERNET-DRAFT       draft-zeilenga-ldap-namedref-00         4 July 2000
+
+
+  If a client requests any of these operations, there are four cases
+  that the server must handle with respect to the base or target object
+  specified in the request.
+
+  Case 1: The base or target object is not held by the server and is not
+  within or subordinate to any naming context nor is subordinate to any
+  referral object held by the server.
+
+  The handling of this case is described in section 6.
+
+  Case 2: The base or target object is held by the server and is a
+  referral object.
+
+  In this case, if the type of operation requested is a search or the
+  URI contained in the ref attribute of the requested base object is NOT
+  an LDAP URI, the server SHOULD return the URI value contained in the
+  ref attribute of the base object whose DN is the DN requested by the
+  client as the base for the operation.
+
+  Example:
+
+  If the client issues a search in which the base object is
+  "o=xyz,c=us", server A will return
+
+      SearchResultDone "referral" {
+          ldap://hostD/o=xyz,c=us
+      }
+
+  If the type of operation requested is not a search and the URI
+  contained in the ref attribute of the requested target object is an
+  LDAP URI, the server SHOULD return a modified form of this URI.  The
+  returned URI MUST have only the protocol, host, port, and trailing "/"
+  portion of the URI contained in the ref attribute.  The server SHOULD
+  strip any DN, attributes, scope, and filter parts of the URI.
+
+  Example:
+
+  If the client issues a modify request for the target object of
+  "o=abc,c=us", server A will return
+
+      ModifyResponse "referral" {
+          ldap://hostB/
+          ldap://hostC/
+      }
+
+  Case 3: The base or target object is not held by the server, but is
+  object where the nearest naming context contains no referral object
+  which the base or target object is subordinate to.
+
+
+
+Zeilenga                                                        [Page 6]
+\f
+INTERNET-DRAFT       draft-zeilenga-ldap-namedref-00         4 July 2000
+
+
+  In the context of this document, the nearest naming context means the
+  deepest context which the object is within.  That is, if the object is
+  within multiple naming contexts, the nearest naming context the one
+  which is subordinate to all other naming contexts the object is
+  within.
+
+  If the nearest naming context contains no referral object which the
+  base or target object is subordinate to the request, request SHOULD be
+  process normally as appropriate for a nonexistent base or target
+  object (generally return noSuchObject).
+
+  Case 4: The base or target object is not held by the server, but is
+  object where the nearest naming context contains a referral object
+  which the base or target object is subordinate to.
+
+  As noted above, the nearest naming context means the deepest context
+  which the object is within.
+
+  If a client requests an operation for which the base or target object
+  is not held by the server but the nearest naming context contains a
+  referral object which the base or target object is subordinate to, the
+  server MUST return a referral response which contains referral values
+  constructed from the URI components of ref attribute values of the
+  referral object.
+
+  For each ref attribute value, if the URI component is not an LDAP
+  URIs, it SHOULD be returned as-is.  If URI component is an LDAP URI,
+  the URI MUST be modified, regardless of the type of operation, as case
+  2 describes for a non-search request. That is, the DN, attributes,
+  scope, and filter parts of the URI MUST be stripped from the returned
+  URI.
+
+  Example:
+
+  If the client issues an add request where the target object has a DN
+  of "cn=Chris Lukas,o=abc,c=us", server A will return
+
+      AddResponse "referral" {
+          ldap://hostB/
+          ldap://hostC/
+      }
+
+
+5.1.1.3.  Search with one level or subtree scope
+
+  For search operations, once the base object has been found and
+  determined not to be a referral object, the search may progress.  Any
+  entries matching the filter and scope of the search which is not a
+
+
+
+Zeilenga                                                        [Page 7]
+\f
+INTERNET-DRAFT       draft-zeilenga-ldap-namedref-00         4 July 2000
+
+
+  referral object are returned to the client normally as described in
+  [RFC2251].
+
+  For each referral object within the requested scope, regardless of the
+  filter, the server SHOULD return a SearchResultReference which is
+  constructed from the URI component of values of the ref attribute.  If
+  the URI component is not an LDAP URI, it should be returned as is.  If
+  the URI component is an LDAP URI, the URI must be modified to remove
+  any explicit scope specifier.
+
+  One Level Example:
+
+  If a client requests a one level search of "c=US" then, in addition to
+  any entries one level below the "c=US" naming context matching the
+  filter (shown below as "... SearchResultEntry responses ..."), the
+  server will also return search references for any referral object
+  within the scope of the search.
+
+  The order of the SearchResultEntry responses and the
+  SearchResultReference responses is undefined.  One possible sequence
+  is shown.
+
+      ... SearchResultEntry responses ...
+
+      SearchResultReference {
+          ldap://hostB/o=abc,c=us
+          ldap://hostC/o=abc,c=us
+      }
+
+      SearchResultReference {
+          ldap://hostD/o=xyz,c=us
+      }
+
+      SearchResultDone "success"
+
+
+  Subtree Example:
+
+  If a client requests a subtree search of "c=us", then in addition to
+  any entries in the "c=us" naming context which match the filter,
+  Server A will also return two continuation references. As described in
+  the preceding section, the order of the responses is not defined.
+
+  One possible response might be:
+
+      SearchResultReference {
+          ldap://hostB/o=abc,c=us
+          ldap://hostC/o=abc,c=us
+
+
+
+Zeilenga                                                        [Page 8]
+\f
+INTERNET-DRAFT       draft-zeilenga-ldap-namedref-00         4 July 2000
+
+
+      }
+
+      ... SearchResultEntry responses ...
+
+      SearchResultReference {
+          ldap://hostD/o=xyz,c=us
+      }
+
+      SearchResultDone "success"
+
+
+6.  Superior Reference
+
+  An LDAP server may be configured to return a superior reference in the
+  case where the requested base or target object is not contained within
+  or subordinate to a naming context held by the server or referral
+  object.
+
+  An LDAP server's root DSE MAY contain a ref attribute. The values of
+  the ref attribute in the root DSE that are LDAP URIs SHOULD NOT
+  contain any DN part nor other search parameters (scope, filter,
+  attribute list).  They MUST include the URI hostpart.
+
+  If the LDAP server's root DSE contains a ref attribute and a client
+  requests a target or base object not held by the server and not
+  contained within or subordinate to any naming context held by the
+  server or referral object, the server MUST return the URI component of
+  the values in the ref attribute of the root DSE as illustrated in the
+  example.
+
+  If the LDAP server's root DSE does not contain a ref attribute, the
+  server may return referral result with or more URIs determined via an
+  appropriate method, return noSuchObject, or other appropriate
+  resultCode.
+
+  The presence of the ref attribute within the root DSE SHALL NOT cause
+  operations upon the root DSE to generate a referral.
+
+  Example:
+
+  If a client requests a subtree search of "c=de" from server A in the
+  example configuration, and server A has the following ref attribute
+  defined in it's root DSE:
+
+      ref: ldap://hostG/
+
+  then server A will return
+
+
+
+
+Zeilenga                                                        [Page 9]
+\f
+INTERNET-DRAFT       draft-zeilenga-ldap-namedref-00         4 July 2000
+
+
+      SearchResultDone "referral" {
+          ldap://hostG/
+      }
+
+
+8.  The ManageDsaIT control
+
+  The ManageDsaIT control indicates that the operation has been
+  requested so that the DSA (server) Information Tree is managed.  The
+  controls causes DSEs, regardless of type, to be treated as normal
+  entries allowing clients to interrogate and update these entries using
+  LDAP operations.  This control is analogous to the ManageDsaIT option
+  described in X.511(93) [X.511].
+
+  A client MAY specify the following control when issuing an add,
+  compare, delete, modify, modifyDN, search request or an extended
+  operation for which the control is defined.
+
+  The control type is 2.16.840.1.113730.3.4.2.  The control criticality
+  may be TRUE or FALSE.  There is no value; the controlValue field is
+  absent.
+
+  When present in the request, the server SHALL NOT generate a referral
+  or continuation reference for any referral object and instead perform
+  treat the referral object as an normal entry.  When not present,
+  referral objects SHALL be handled as described above.
+
+  The control MAY cause other objects to be treated as normal entries as
+  defined by subsequent documents.
+
+
+9.  Relationship to X.500 Knowledge References
+
+  The X.500 standard defines several types of knowledge references, used
+  to bind together different parts of the X.500 namespace. In X.500,
+  knowledge references can be associated with a set of unnamed entries
+  (e.g., a reference, associated with an entry, to a server containing
+  the descendants of that entry).
+
+  This creates a potential problem for LDAP clients resolving an LDAPv3
+  URI referral referring to an LDAP directory back-ended by X.500.
+  Suppose the search is a subtree search, and that server A holds the
+  base object of the search, and server B holds the descendants of the
+  base object. The behavior of X.500(1993) subordinate references is
+  that the base object on server A is searched, and a single
+  continuation reference is returned pointing to all of the descendants
+  held on server B.
+
+
+
+
+Zeilenga                                                       [Page 10]
+\f
+INTERNET-DRAFT       draft-zeilenga-ldap-namedref-00         4 July 2000
+
+
+  An LDAP URI only allows the base object to be specified.  It is not
+  possible using standard LDAP URIs to indicate a search of several
+  entries whose names are not known to the server holding the superior
+  entry.
+
+  X.500 solves this problem by having two fields, one indicating the
+  progress of name resolution and the other indicating the target of the
+  search. In the above example, name resolution would be complete by the
+  time the query reached server B, indicating that it should not refer
+  the request.
+
+  This document does not address this problem.  This problem will be
+  addressed in separate documents which define the changes to the X.500
+  distribution model and LDAPv3 extensions to indicate the progress of
+  name resolution.
+
+
+10.  Security Considerations
+
+  This document defines mechanisms that can be used to "glue" LDAP (and
+  other) servers together. The information used to specify this glue
+  information should be protected from unauthorized modification.  If
+  the server topology information itself is not public information, the
+  information should be protected from unauthorized access as well.
+
+
+11.  References
+
+  [RFC1738] Berners-Lee, T., Masinter, L., and McCahill, M., "Uniform
+            Resource Locators (URL)", RFC 1738, CERN, Xerox Corporation,
+            University of Minnesota, December 1994.
+
+  [RFC2079] M. Smith, "Definition of an X.500 Attribute Type and an
+            Object Class to Hold Uniform Resource Identifiers (URIs)",
+            RFC 2079, January 1997.
+
+  [RFC2119] S. Bradner, "Key Words for use in RFCs to Indicate
+            Requirement Levels", RFC 2119 (Also BCP0014), March 1997.
+
+  [RFC2251] M. Wahl, T. Howes, S. Kille, "Lightweight Directory Access
+            Protocol (v3)", RFC 2251, December 1997.
+
+  [RFC2255] T. Howes, M. Smith, "The LDAP URL Format", RFC 2255,
+            December, 1997.
+
+  [X.500]   ITU-T Rec. X.501, "The Directory: Models", 1993.
+
+  [X.511]   ITU-T Rec. X.511, "The Directory: Abstract Service
+
+
+
+Zeilenga                                                       [Page 11]
+\f
+INTERNET-DRAFT       draft-zeilenga-ldap-namedref-00         4 July 2000
+
+
+            Definition", 1993.
+
+
+
+12.  Acknowledgments
+
+  This document is borrows heavily from previous work by IETF LDAPext
+  working group.  In particular, this document is based upon "Named
+  Referral in LDAP Directories" (a work in progress) by Christopher
+  Lukes, Tim Howes, Michael Roszkowski, Mark C. Smith, and Mark Wahl.
+
+
+13.  Author's Address
+
+  Kurt D. Zeilenga
+  OpenLDAP Foundation
+  <Kurt@OpenLDAP.org>
+
+
+  This draft expires 4 Jan. 2001.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Zeilenga                                                       [Page 12]
+\f
diff --git a/doc/drafts/draft-zeilenga-ldap-passwd-exop-xx.txt b/doc/drafts/draft-zeilenga-ldap-passwd-exop-xx.txt
new file mode 100644 (file)
index 0000000..ea160b6
--- /dev/null
@@ -0,0 +1,333 @@
+INTERNET-DRAFT                                      Kurt D. Zeilenga
+Intended Category: Standard Track                   OpenLDAP Foundation
+Expires: 13 December 2000                           13 June 2000
+
+
+                 LDAP Password Modify Extended Operation
+                 <draft-zeilenga-ldap-passwd-exop-03.txt>
+
+
+1.      Status of this Memo
+
+  This document is an Internet-Draft and is in full conformance with all
+  provisions of Section 10 of RFC2026.
+
+  This document is intended to be, after appropriate review and
+  revision, submitted to the RFC Editor as a Standard Track document.
+  Distribution of this memo is unlimited.  Technical discussion of this
+  document will take place on the IETF LDAP Extension Working Group
+  mailing list <ietf-ldapext@netscape.com>.  Please send editorial
+  comments directly to the author <Kurt@OpenLDAP.org>.
+
+  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.
+
+  Copyright 2000, The Internet Society.  All Rights Reserved.
+
+  Please see the Copyright section near the end of this document for
+  more information.
+
+
+2.      Abstract
+
+  The integration of LDAP [RFC2251] and external authentication services
+  has introduced non-DN authentication identities and allowed for
+  non-directory storage of passwords.   As such, mechanisms which update
+  the directory, such as Modify operation, cannot be used to change a
+  user's password.  This document describes an LDAP extended operation
+  to allow allow modification of user passwords which is not dependent
+  upon the form of the authentication identity nor the password storage
+
+
+
+Zeilenga                                                        [Page 1]
+\f
+INTERNET-DRAFT     draft-zeilenga-ldap-passwd-exop-03       13 June 2000
+
+
+  mechanism used.
+
+  The key words ``MUST'', ``MUST NOT'', ``REQUIRED'', ``SHALL'', ``SHALL
+  NOT'', ``SHOULD'', ``SHOULD NOT'', ``RECOMMENDED'',  and ``MAY'' in
+  this document are to be interpreted as described in RFC 2119
+  [RFC2119].
+
+
+3.      Background and Intent of Use
+
+  Lightweight Directory Access Protocol (LDAP) [RFC2251] is designed to
+  support an number of authentication mechanisms including simple user
+  name/password pairs.  Traditionally LDAP users where identified by the
+  Distinguished Name [RFC2253] of a directory entry and this entry
+  contained a userPassword [RFC2256] attribute containing one or more
+  passwords.
+
+  The protocol does not mandate that passwords associated with a user be
+  stored in the directory server.  The server may use any attribute
+  suitable for password storage, such as userPassword or authPassword
+  [AuthPasswd], or use non-directory storage.
+
+  The integration of application neutral SASL [RFC2222] services which
+  support simple username/password mechanisms (such as DIGEST-MD5) has
+  introduced non-LDAP DN authentication identity forms and made storage
+  of passwords the responsibility of the SASL service provider.
+
+  LDAP update operations are designed to act upon attributes of an entry
+  within the directory.  LDAP update operations cannot be used to modify
+  a user's password when the user is not represented by a DN, does not
+  have a entry, or when that password used by the server is not stored
+  as an attribute of an entry.  An alternative mechanism are needed.
+
+  This document describes an LDAP Extended Operation intended to be
+  allow directory clients to update user passwords.  The user may or may
+  not have be associated with a directory entry. The user may or may not
+  be represented as an LDAP DN.  The user's password may or may not be
+  stored in the directory.
+
+  The operation SHOULD NOT be used without adequate security protection
+  as the operation affords no privacy or integrity protect itself.  This
+  operation SHOULD NOT be used by "anonymous" clients.
+
+
+4.      Password Modify Request and Response
+
+  The Password Modify operation is an LDAPv3 Extended Operation
+  [RFC2251, Section 4.12] and is identified by the OBJECT IDENTIFIER
+
+
+
+Zeilenga                                                        [Page 2]
+\f
+INTERNET-DRAFT     draft-zeilenga-ldap-passwd-exop-03       13 June 2000
+
+
+  passwdModifyOID.  This section details the syntax of the protocol
+  request and response.
+
+    passwdModifyOID OBJECT IDENTIFIER ::= 1.3.6.1.4.1.4203.666.6.1
+
+    [Editor's Note: this OID is temporary.  A permanent OID
+      will be assigned to this object before this document is
+      progressed as an RFC.]
+
+    PasswdModifyRequestValue ::= SEQUENCE {
+      userIdentity    [0]  OCTET STRING OPTIONAL
+      oldPasswd       [1]  OCTET STRING OPTIONAL
+      newPasswd       [2]  OCTET STRING OPTIONAL }
+
+    PasswordModifyResponseValue ::= SEQUENCE {
+      genPasswd       [0]     OCTET STRING OPTIONAL }
+
+
+4.1.    Password Modify Request
+
+  A Password Modify request is an ExtendedRequest with the requestName
+  field containing passwdModifyOID OID and optionally provides a
+  requestValue field.  If the requestValue field is provided, it SHALL
+  contain a PasswdModifyRequestValue with one or more fields present.
+
+  The userIdentity field, if present, SHALL contain an octet string
+  representation of the user associated with the request.  This string
+  may or may not be an LDAPDN [RFC2253].  If no userIdentity field is
+  present, the request acts up upon the password of the user currently
+  associated with the LDAP session.
+
+  The oldPasswd field, if present, SHALL contain the user's current
+  password.
+
+  The newPasswd field, if present, SHALL contain the desired password
+  for this user.
+
+
+4.2.    Password Modify Response
+
+  A Password Modify response is an ExtendedResponse where the
+  responseName field is absent and the response field is optional.  The
+  response field, if present, SHALL contain a PasswdModifyResponseValue
+  with genPasswd field present.
+
+  The genPasswd field, if present, SHALL contain a generated password
+  for the user.
+
+
+
+
+Zeilenga                                                        [Page 3]
+\f
+INTERNET-DRAFT     draft-zeilenga-ldap-passwd-exop-03       13 June 2000
+
+
+  If an resultCode other than success (0) is indicated in the response,
+  the response field MUST be absent.
+
+
+5.      Operation Requirements
+
+  Clients SHOULD NOT submit a Password Modification request without
+  ensuring adequate security safeguards are in place.  Servers SHOULD
+  return a non-success resultCode if sufficient security protection are
+  not in place.
+
+  Servers SHOULD indicate their support for this extended operation by
+  providing PasswordModifyOID as a value of the supportedExtensions
+  attribute type in their root DSE.  Clients SHOULD verify the server
+  implements this extended operation prior to attempting the operation
+  by asserting the supportedExtensions attribute contains a value of
+  PasswordModifyOID.
+
+  The server SHALL only return success upon successfully changing the
+  user's password.  The server SHALL leave the password unmodified and
+  return a non-success resultCode otherwise.
+
+  If the server does not recognize provided fields or does not support
+  the combination of fields provided, it SHALL NOT change the user
+  password.
+
+  If the provided oldPasswd value cannot be verified or is incorrect,
+  the server SHALL NOT change the user password.
+
+  The server SHALL NOT generate a password on behalf of the client if
+  the client has provided a newPassword.  In absence of a client
+  provided newPassword, the server SHALL either generate a password on
+  behalf of the client or return a non-success result code.  The server
+  MUST provide the generated password upon success as the value of the
+  genPasswd field.
+
+  The server MAY return adminLimitExceeded, busy,
+  confidentialityRequired, operationsError, unavailable,
+  unwillingToPerform, or other non-success resultCode as appropriate to
+  indicate that it was unable to successfully complete the operation.
+
+  Servers MAY implement administrative policies which restrict this
+  operation.
+
+
+6.      Other requirements
+
+  A server which supports this operation SHOULD provide a
+
+
+
+Zeilenga                                                        [Page 4]
+\f
+INTERNET-DRAFT     draft-zeilenga-ldap-passwd-exop-03       13 June 2000
+
+
+  supportedExtension attribute in the Root DSE which contains as one of
+  its values the passwdModifyOID OID.  A server MAY advertise the
+  extension only when the client is authorized and/or has established
+  the necessary security protections to use this operation.  Clients
+  SHOULD verify the server has advertised the extension before
+  attempting the operation.
+
+
+7.      Security Considerations
+
+  This operation is used to modify user passwords.  The operation itself
+  does not provide any security protection to ensure integrity and/or
+  confidentiality of the information.  Use of this operation is strongly
+  discouraged when privacy protections are not in place to guarantee
+  confidentiality and may result in the disclosure of the password to
+  unauthorized parties.
+
+
+8.      Copyright
+
+  Copyright 2000, The Internet Society.  All Rights Reserved.
+
+  This document and translations of it may be copied and furnished to
+  others, and derivative works that comment on or otherwise explain it
+  or assist in its implementation may be prepared, copied, published and
+  distributed, in whole or in part, without restriction of any kind,
+  provided that the above copyright notice and this paragraph are
+  included on all such copies and derivative works.  However, this
+  document itself may not be modified in any way, such as by removing
+  the copyright notice or references to the Internet Society or other
+  Internet organizations, except as needed for the  purpose of
+  developing Internet standards in which case the procedures for
+  copyrights defined in the Internet Standards process must be followed,
+  or as required to translate it into languages other than English.
+
+  The limited permissions granted above are perpetual and will not be
+  revoked by the Internet Society or its successors or assigns.
+
+  This document and the information contained herein is provided on an
+  "AS IS" basis and THE AUTHORS, THE INTERNET SOCIETY, AND THE INTERNET
+  ENGINEERING TASK FORCE DISCLAIMS 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.
+
+
+9.      Bibliography
+
+
+
+
+Zeilenga                                                        [Page 5]
+\f
+INTERNET-DRAFT     draft-zeilenga-ldap-passwd-exop-03       13 June 2000
+
+
+  [RFC2219]       S. Bradner, "Key words for use in RFCs to Indicate
+                  Requirement Levels", RFC 2119, March 1997.
+
+  [RFC2222]       J. Myers, "Simple Authentication and Security
+                  Layer (SASL)", RFC 2222, October 1997.
+
+  [RFC2251]       M. Wahl, T. Howes, S. Kille, "Lightweight
+                  Directory Access Protocol (v3)", RFC 2251,
+                  December 1997.
+
+  [RFC2252]       M. Wahl, A. Coulbeck, T. Howes, S. Kille,
+                  "Lightweight Directory Access Protocol (v3):
+                  Attribute Syntax Definitions", RFC 2252,
+                  December 1997.
+
+  [RFC2253]       M. Wahl, S. Kille, T. Howes, "Lightweight
+                  Directory Access Protocol (v3): UTF-8 String
+                  Representation of Distinguished Names", RFC 2253,
+                  December 1997.
+
+  [RFC2256]       M. Wahl, "A Summary of the X.500(96) User Schema
+                  for use with LDAPv3", RFC 2256, December 1997.
+
+  [AuthPasswd]    K. Zeilenga, "LDAP Authentication Password
+                  Attribute", draft-zeilenga-ldap-authpasswd-xx.txt,
+                  a work in progress.
+
+10.     Acknowledgment
+
+  This document borrows from a number of IETF documents and is based
+  upon input from the IETF LDAPext working group.
+
+
+11.     Author's Address
+
+  Kurt D. Zeilenga
+  OpenLDAP Foundation
+  <Kurt@OpenLDAP.org>
+
+
+
+
+
+
+
+
+
+
+
+
+
+Zeilenga                                                        [Page 6]
+\f
diff --git a/doc/drafts/draft-zeilenga-ldapv3bis-opattrs-xx.txt b/doc/drafts/draft-zeilenga-ldapv3bis-opattrs-xx.txt
new file mode 100644 (file)
index 0000000..0daa771
--- /dev/null
@@ -0,0 +1,221 @@
+INTERNET-DRAFT                                      Kurt D. Zeilenga
+Intended Category: Standard Track                   OpenLDAP Foundation
+Expires: 29 December 2000                           29 June 2000
+
+
+                    LDAPv3: All Operational Attributes
+                <draft-zeilenga-ldapv3bis-opattrs-00.txt>
+
+
+1.      Status of this Memo
+
+  This document is an Internet-Draft and is in full conformance with all
+  provisions of Section 10 of RFC2026.
+
+  This document is intended to be, after appropriate review and
+  revision, submitted to the RFC Editor as a Standard Track document.
+  Distribution of this memo is unlimited.  Technical discussion of this
+  document will take place on the IETF LDAP Extension Working Group
+  mailing list <ietf-ldapext@netscape.com>.  Please send editorial
+  comments directly to the author <Kurt@OpenLDAP.org>.
+
+  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.
+
+  Copyright 2000, The Internet Society.  All Rights Reserved.
+
+  Please see the Copyright section near the end of this document for
+  more information.
+
+
+2.      Overview
+
+  X.500 provides a mechanism for clients to request all operational
+  attributes be returned with entries provided in response to a search
+  operation.   LDAP [RFC2251] does not provide a similar mechanism to
+  clients to request the return of operational attributes.  The lack of
+  such a mechanisms hinders discovery of operational attributes present
+  in an entry.
+
+
+
+
+Zeilenga                                                        [Page 1]
+\f
+INTERNET-DRAFT     draft-zeilenga-ldapv3bis-opattrs-00      13 June 2000
+
+
+  This document defines a simple mechanism which clients may use to
+  request all operation attributes.  This document updates RFC 2251 as
+  detailed below.
+
+  The key words ``MUST'', ``MUST NOT'', ``REQUIRED'', ``SHALL'', ``SHALL
+  NOT'', ``SHOULD'', ``SHOULD NOT'', ``RECOMMENDED'',  and ``MAY'' in
+  this document are to be interpreted as described in RFC 2119
+  [RFC2119].
+
+
+3.      Changes to RFC 2251
+
+  This document updates RFC 2251 as follows:
+
+  In Section 3.2.1, Attributes of Entries, the paragraph:
+      Some attributes, termed operational attributes, are used by
+      servers for administering the directory system itself.  They are
+      not returned in search results unless explicitly requested by
+      name.  Attributes which are not operational, such as "mail", will
+      have their schema and syntax constraints enforced by servers, but
+      servers will generally not make use of their values.
+
+  is replaced with:
+      Some attributes, termed operational attributes, are used by
+      servers for administering the directory system itself.  They are
+      not returned in search results unless explicitly requested.
+      Attributes which are not operational, such as "mail", will have
+      their schema and syntax constraints enforced by servers, but
+      servers will generally not make use of their values.
+
+  In Section 4.5.1, Search Request, the paragraph:
+      - attributes: A list of the attributes to be returned from each
+      entry which matches the search filter. There are two special
+      values which may be used: an empty list with no attributes, and
+      the attribute description string "*".  Both of these signify that
+      all user attributes are to be returned.  (The "*" allows the
+      client to request all user attributes in addition to specific
+      operational attributes).
+
+  is replaced with:
+      - attributes: A list of the attributes to be returned from each
+      entry which matches the search filter. There are three special
+      values which may be used.  An empty list with no attributes
+      signifies that all user attributes are to be returned.  An
+      attribute list containing the attribute description string "*"
+      signifies that all user attributes are to be returned.   An
+      attribute list containing the attribute description string "+"
+      signifies that all operational attributes are to be returned.
+
+
+
+Zeilenga                                                        [Page 2]
+\f
+INTERNET-DRAFT     draft-zeilenga-ldapv3bis-opattrs-00      13 June 2000
+
+
+      (The "*" allows the client to request all user attributes in
+      addition to any requested operational attributes.  The "+" allows
+      the client to request all operational attributes in addition to
+      requested user attributes.  A client may list both "*" and "+" to
+      request all attributes.)
+
+  and the paragraph:
+      Client implementors should note that even if all user attributes
+      are requested, some attributes of the entry may not be included in
+      search results due to access control or other restrictions.
+      Furthermore, servers will not return operational attributes, such
+      as objectClasses or attributeTypes, unless they are listed by
+      name, since there may be extremely large number of values for
+      certain operational attributes. (A list of operational attributes
+      for use in LDAP is given in [5].)
+
+  is replaced with:
+      Client implementors should note that results may not include all
+      requested attributes due to access controls or other restrictions.
+      In addition, client implementors should request types only be
+      returned when discovering operational attributes as certain
+      operational attributes may have extremely large number of values.
+      Furthermore, servers will not return operational attributes, such
+      as objectClasses or attributeTypes, unless they are requested,
+      since there may be extremely large number of values for certain
+      operational attributes. (A list of operational attributes for use
+      in LDAP is given in [5].)
+
+
+5.      Interoperability Considerations
+
+  The addition of this mechanism to LDAPv3 is not believed to cause
+  significant interoperability problems.  A server which does not
+  support the "+" should ignore the attribute description per RFC 2251,
+  section 4.5.1 and only return the attributes for the attribute
+  descriptions strings they do recognize.   From the client's
+  perspective, this is one possible "other restriction" noted above.
+
+
+5.      Security Considerations
+
+  This document provides a mechanism which clients may use to discover
+  operational attributes.  Access controls should be used to restrict
+  access to operational attributes per local policy.
+
+
+6.      Copyright
+
+
+
+
+Zeilenga                                                        [Page 3]
+\f
+INTERNET-DRAFT     draft-zeilenga-ldapv3bis-opattrs-00      13 June 2000
+
+
+  Copyright 2000, The Internet Society.  All Rights Reserved.
+
+  This document and translations of it may be copied and furnished to
+  others, and derivative works that comment on or otherwise explain it
+  or assist in its implementation may be prepared, copied, published and
+  distributed, in whole or in part, without restriction of any kind,
+  provided that the above copyright notice and this paragraph are
+  included on all such copies and derivative works.  However, this
+  document itself may not be modified in any way, such as by removing
+  the copyright notice or references to the Internet Society or other
+  Internet organizations, except as needed for the  purpose of
+  developing Internet standards in which case the procedures for
+  copyrights defined in the Internet Standards process must be followed,
+  or as required to translate it into languages other than English.
+
+  The limited permissions granted above are perpetual and will not be
+  revoked by the Internet Society or its successors or assigns.
+
+  This document and the information contained herein is provided on an
+  "AS IS" basis and THE AUTHORS, THE INTERNET SOCIETY, AND THE INTERNET
+  ENGINEERING TASK FORCE DISCLAIMS 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.
+
+7.      Bibliography
+
+  [RFC2219]       S. Bradner, "Key words for use in RFCs to Indicate
+                  Requirement Levels", RFC 2119, March 1997.
+
+  [RFC2251]       M. Wahl, T. Howes, S. Kille, "Lightweight
+                  Directory Access Protocol (v3)", RFC 2251,
+                  December 1997.
+
+  [X.500]         ITU-T Rec. X.500, "The Directory: Overview of
+                  Concepts, Models and Service",  1993.
+
+
+8.     Author's Address
+
+  Kurt D. Zeilenga
+  OpenLDAP Foundation
+  <Kurt@OpenLDAP.org>
+
+
+
+
+
+
+
+
+Zeilenga                                                        [Page 4]
+\f
index 480a66ad08975a88f16de9be3240af0806a8de17..ec231f8a1ba49595fadaecdbc89bfc39f16c3f77 100644 (file)
@@ -1,4 +1,4 @@
-.TH LDAPDELETE 1 "20 April 2000" "OpenLDAP LDVERSION"
+.TH LDAPDELETE 1 "12 July 2000" "OpenLDAP LDVERSION"
 .\" $OpenLDAP$
 .\" Copyright 1998-2000 The OpenLDAP Foundation All Rights Reserved.
 .\" Copying restrictions apply.  See COPYRIGHT/LICENSE.
@@ -37,12 +37,16 @@ ldapdelete \- LDAP delete entry tool
 [\c
 .BI \-p \ ldapport\fR]
 [\c
-.BR \-E[E] ]
-[\c
-.BR \-I[I] ]
+.BR \-O \ security-properties ]
 [\c
 .BI \-U \ username\fR]
 [\c
+.BR \-x ]
+[\c
+.BR \-I ]
+[\c
+.BR \-Q ]
+[\c
 .BI \-X \ authzid\fR]
 [\c
 .BI \-Y \ mech\fR]
@@ -109,6 +113,9 @@ each line.  In this case, the \fIfilter\fP given on the command line
 is treated as a pattern where the first occurrence of \fB%s\fP is
 replaced with a line from \fIfile\fP.
 .TP
+.B \-x 
+Use simple authentication instead of SASL.
+.TP
 .BI \-D \ binddn
 Use \fIbinddn\fP to bind to the LDAP directory. \fIbinddn\fP should be
 a string-represented DN as defined in RFC 1779.
@@ -129,30 +136,21 @@ Specify an alternate TCP port where the ldap server is listening.
 .BI \-P \ 2\fR\||\|\fI3
 Specify the LDAP protocol version to use.
 .TP
-.BI \-r
+.B \-r
 Do a recursive delete.  If the DN specified isn't a leaf, its
 children, and all their children are deleted down the tree.  No
 verification is done, so if you add this switch, ldapdelete will
 happily delete large portions of your tree.  Use with care.
 .TP
-.B \-E[E]
-Requset the use of SASL privacy (encryption). If the server allows it, data
-sent between the client and the server will be encrypted. If the server
-requires the use of encryption and this flag is not specified, the command
-will fail. If you use
-.B \-EE\c
-, the command will fail if the server does not support encryption.
-.B \-E[E]
-implies
-.B \-I[I]
-.TP
-.B \-I[I]
-Request the use of SASL integrity checking. It protects data sent between the
-client and the server from being modified along the way, but it does not
-prevent sniffing. If the server requires the use of integrity checking and
-this flag is not specified, the command will fail.If you use
-.B \-II\c
-, the command will fail if the server does not support this function. 
+.BI \-O \ security-properties
+Specify SASL security properties.
+.TP
+.B \-I
+Enable SASL Interactive mode.  Always prompt.  Default is to prompt
+only as needed.
+.TP
+.B \-Q
+Enable SASL Quiet mode.  Never prompt.
 .TP
 .BI \-U \ username
 Specify the username for SASL bind. The syntax of the username depends on the
@@ -206,6 +204,8 @@ Kille, S.,
 ISODE Consortium, March 1995.
 .SH BUGS
 There is no interactive mode, but there probably should be.
+.SH AUTHOR
+The OpenLDAP Project <http://www.openldap.org/>
 .SH ACKNOWLEDGEMENTS
 .B     OpenLDAP
 is developed and maintained by The OpenLDAP Project (http://www.openldap.org/).
index 4feb264fa785139485b9a132c5c45ffe7f83c26d..6c001b38c6a429c9fdbdcd98f22bc09a222c09e4 100644 (file)
@@ -1,4 +1,4 @@
-.TH LDAPMODIFY 1 "20 April 2000" "OpenLDAP LDVERSION"
+.TH LDAPMODIFY 1 "12 July 2000" "OpenLDAP LDVERSION"
 .\" $OpenLDAP$
 .\" Copyright 1998-2000 The OpenLDAP Foundation All Rights Reserved.
 .\" Copying restrictions apply.  See COPYRIGHT/LICENSE.
@@ -41,12 +41,16 @@ ldapmodify, ldapadd \- LDAP modify entry and LDAP add entry tools
 [\c
 .BI \-P \ 2\fR\||\|\fI3\fR]
 [\c
-.BR \-E[E] ]
+.BR \-O \ security-properties ]
 [\c
-.BR \-I[I] ]
+.BR \-I ]
+[\c
+.BR \-Q ]
 [\c
 .BI \-U \ username\fR]
 [\c
+.BR \-x ]
+[\c
 .BI \-X \ authzid\fR]
 [\c
 .BI \-Y \ mech\fR]
@@ -180,6 +184,9 @@ must be compiled with LDAP_DEBUG defined for this option to have any effect.
 Read the entry modification information from \fIfile\fP instead of from
 standard input.
 .TP
+.B \-x 
+Use simple authentication instead of SASL.
+.TP
 .BI \-D \ binddn
 Use \fIbinddn\fP to bind to the LDAP directory. \fIbinddn\fP should be
 a string-represented DN as defined in RFC 1779.
@@ -200,24 +207,15 @@ Specify an alternate TCP port where the ldap server is listening.
 .BI \-P \ 2\fR\||\|\fI3
 Specify the LDAP protocol version to use.
 .TP
-.B \-E[E]
-Requset the use of SASL privacy (encryption). If the server allows it, data
-sent between the client and the server will be encrypted. If the server
-requires the use of encryption and this flag is not specified, the command
-will fail. If you use
-.B \-EE\c
-, the command will fail if the server does not support encryption.
-.B \-E[E]
-implies
-.B \-I[I]
+.BI \-O \ security-properties
+Specify SASL security properties.
+.TP
+.B \-I
+Enable SASL Interactive mode.  Always prompt.  Default is to prompt
+only as needed.
 .TP
-.B \-I[I]
-Request the use of SASL integrity checking. It protects data sent between the
-client and the server from being modified along the way, but it does not
-prevent sniffing. If the server requires the use of integrity checking and
-this flag is not specified, the command will fail.If you use
-.B \-II\c
-, the command will fail if the server does not support this function. 
+.B \-Q
+Enable SASL Quiet mode.  Never prompt.
 .TP
 .BI \-U \ username
 Specify the username for SASL bind. The syntax of the username depends on the
@@ -426,6 +424,8 @@ Kille, S.,
 ISODE Consortium, March 1995.
 .SH BUGS
 There is no interactive mode, but there probably should be.
+.SH AUTHOR
+The OpenLDAP Project <http://www.openldap.org/>
 .SH ACKNOWLEDGEMENTS
 .B     OpenLDAP
 is developed and maintained by The OpenLDAP Project (http://www.openldap.org/).
index e85ddd69ab0140353ea1b16a3e6e15794f5e1819..56d4b9c00f18545caf4ac2a6c9bfbfd179a4eba2 100644 (file)
@@ -1,4 +1,4 @@
-.TH LDAPMODRDN 1 "20 April 2000" "OpenLDAP LDVERSION"
+.TH LDAPMODRDN 1 "12 July 2000" "OpenLDAP LDVERSION"
 .\" $OpenLDAP$
 .\" Copyright 1998-2000 The OpenLDAP Foundation All Rights Reserved.
 .\" Copying restrictions apply.  See COPYRIGHT/LICENSE.
@@ -37,12 +37,16 @@ ldapmodrdn \- LDAP rename entry tool
 [\c
 .BI \-P \ 2\fR\||\|\fI3\fR]
 [\c
-.BR \-E[E] ]
+.BR \-O \ security-properties ]
 [\c
-.BR \-I[I] ]
+.BR \-I ]
+[\c
+.BR \-Q ]
 [\c
 .BI \-U \ username\fR]
 [\c
+.BR \-x ]
+[\c
 .BI \-X \ authzid\fR]
 [\c
 .BI \-Y \ mech\fR]
@@ -111,6 +115,9 @@ compiled with LDAP_DEBUG defined for this option to have any effect.
 Read the entry modification information from \fIfile\fP instead of from
 standard input or the command-line.
 .TP
+.B \-x 
+Use simple authentication instead of SASL.
+.TP
 .B \-D binddn
 Use \fIbinddn\fP to bind to the LDAP directory. \fIbinddn\fP should be
 a string-represented DN as defined in RFC 1779.
@@ -131,24 +138,15 @@ Specify an alternate TCP port where the ldap server is listening.
 .BI \-P \ 2\fR\||\|\fI3
 Specify the LDAP protocol version to use.
 .TP
-.B \-E[E]
-Requset the use of SASL privacy (encryption). If the server allows it, data
-sent between the client and the server will be encrypted. If the server
-requires the use of encryption and this flag is not specified, the command
-will fail. If you use
-.B \-EE\c
-, the command will fail if the server does not support encryption.
-.B \-E[E]
-implies
-.B \-I[I]
-.TP
-.B \-I[I]
-Request the use of SASL integrity checking. It protects data sent between the
-client and the server from being modified along the way, but it does not
-prevent sniffing. If the server requires the use of integrity checking and
-this flag is not specified, the command will fail.If you use
-.B \-II\c
-, the command will fail if the server does not support this function. 
+.BI \-O \ security-properties
+Specify SASL security properties.
+.TP
+.B \-I
+Enable SASL Interactive mode.  Always prompt.  Default is to prompt
+only as needed.
+.TP
+.B \-Q
+Enable SASL Quiet mode.  Never prompt.
 .TP
 .BI \-U \ username
 Specify the username for SASL bind. The syntax of the username depends on the
@@ -225,6 +223,8 @@ Kille, S.,
 ISODE Consortium, March 1995.
 .SH BUGS
 There is no interactive mode, but there probably should be.
+.SH AUTHOR
+The OpenLDAP Project <http://www.openldap.org/>
 .SH ACKNOWLEDGEMENTS
 .B     OpenLDAP
 is developed and maintained by The OpenLDAP Project (http://www.openldap.org/).
index a985647f5a06eaf52247a2cece66521c935a6d37..8e0c3d4ca3273bb85b0467c82237da8ed48c3ddf 100644 (file)
@@ -1,4 +1,4 @@
-.TH LDAPPASSWD 1 "20 April 2000" "LDAPPasswd"
+.TH LDAPPASSWD 1 "12 July 2000" "LDAPPasswd"
 .\" $OpenLDAP$
 .\" Copyright 1998-2000 The OpenLDAP Foundation All Rights Reserved.
 .\" Copying restrictions apply.  See COPYRIGHT/LICENSE.
@@ -33,12 +33,16 @@ ldappasswd \- change the password of an LDAP entry
 [\c
 .BI \-w \ passwd\fR]
 [\c
-.BR \-E[E] ]
+.BR \-O \ security-properties ]
 [\c
-.BR \-I[I] ]
+.BR \-I ]
+[\c
+.BR \-Q ]
 [\c
 .BI \-U \ username\fR]
 [\c
+.BR \-x ]
+[\c
 .BI \-X \ authzid\fR]
 [\c
 .BI \-Y \ mech\fR]
@@ -47,15 +51,17 @@ ldappasswd \- change the password of an LDAP entry
 .SH DESCRIPTION
 .B ldappasswd
 is a tool to set the password of an LDAP user.
-It is neither designed nor intended to be a replacement for
-.BR passwd (1)
-and should not be installed as such.
 .LP
 .B ldappasswd
 sets the password of associated with the user.  If the new
 password is not specified on the command line or the user
 doesn't enable prompting, the server will be asked to generate
 a password for the user.
+.LP
+.B ldappasswd
+is neither designed nor intended to be a replacement for
+.BR passwd (1)
+and should not be installed as such.
 .SH OPTIONS
 .TP
 .BI \-A
@@ -68,6 +74,9 @@ Set the old password to \fIoldPasswd\fP.
 .B \-C
 Automatically chase referrals.
 .TP
+.B \-x 
+Use simple authentication instead of SASL.
+.TP
 .BI \-D \ binddn
 Use \fIbinddn\fP to bind to the LDAP directory. \fIbinddn\fP should
 be a string-represented DN as defined in RFC 2253.
@@ -107,24 +116,15 @@ This is used instead of specifying the password on the command line.
 .BI \-w \ passwd
 Use \fIpasswd\fP as the password to bind with.
 .TP
-.B \-E[E]
-Requset the use of SASL privacy (encryption). If the server allows it, data
-sent between the client and the server will be encrypted. If the server
-requires the use of encryption and this flag is not specified, the command
-will fail. If you use
-.B \-EE\c
-, the command will fail if the server does not support encryption.
-.B \-E[E]
-implies
-.B \-I[I]
-.TP
-.B \-I[I]
-Request the use of SASL integrity checking. It protects data sent between the
-client and the server from being modified along the way, but it does not
-prevent sniffing. If the server requires the use of integrity checking and
-this flag is not specified, the command will fail.If you use
-.B \-II\c
-, the command will fail if the server does not support this function. 
+.BI \-O \ security-properties
+Specify SASL security properties.
+.TP
+.B \-I
+Enable SASL Interactive mode.  Always prompt.  Default is to prompt
+only as needed.
+.TP
+.B \-Q
+Enable SASL Quiet mode.  Never prompt.
 .TP
 .BI \-U \ username
 Specify the username for SASL bind. The syntax of the username depends on the
@@ -134,11 +134,9 @@ actual SASL mechanism used.
 Specify the requested authorization ID for SASL bind.
 .I authzid
 must be one of the following formats:
-.B dn:\c
-.I <distinguished name>
+.BI dn: <distinguished name>
 or
-.B u:\c
-.I <username>
+.BI u: <username>\fP.
 .TP
 .BI \-Y \ mech
 Specify the SASL mechanism to be used for authentication. If it's not
@@ -146,10 +144,14 @@ specified, the program will choose the best mechanism the server knows.
 .TP
 .B \-Z[Z]
 Issue StartTLS (Transport Layer Security) extended operation. If you use
-.B \-ZZ\c
-, the command will require the operation to be successful.
+.BR \-ZZ ,
+the command will require the operation to be successful
 .SH SEE ALSO
-.BR ldap_bind (3)
+.BR ldap_sasl_bind (3)
+.BR ldap_extended_operation (3)
+.BR ldap_start_tls (3)
+.SH AUTHOR
+The OpenLDAP Project <http://www.openldap.org/>
 .SH ACKNOWLEDGEMENTS
 .B     OpenLDAP
 is developed and maintained by The OpenLDAP Project (http://www.openldap.org/).
index 0c59f5231edeec86deb9e67b949adecb7e1c5c61..6df7eac3a24a0cdd692efc290b1c7c1e2bc09c6e 100644 (file)
@@ -1,4 +1,4 @@
-.TH LDAPSEARCH 1 "20 April 2000" "OpenLDAP LDVERSION"
+.TH LDAPSEARCH 1 "12 July 2000" "OpenLDAP LDVERSION"
 .\" $OpenLDAP$
 .\" Copyright 1998-2000 The OpenLDAP Foundation All Rights Reserved.
 .\" Copying restrictions apply.  See COPYRIGHT/LICENSE.
@@ -53,12 +53,16 @@ ldapsearch \- LDAP search tool
 [\c
 .BI \-z \ sizelimit\fR]
 [\c
-.BR \-E[E] ]
+.BR \-O \ security-properties ]
 [\c
-.BR \-I[I] ]
+.BR \-I ]
+[\c
+.BR \-Q ]
 [\c
 .BI \-U \ username\fR]
 [\c
+.BR \-x ]
+[\c
 .BI \-X \ authzid\fR]
 [\c
 .BI \-Y \ mech\fR]
@@ -157,6 +161,9 @@ is treated as a pattern where the first occurrence of \fB%s\fP is
 replaced with a line from \fIfile\fP.  If \fIfile\fP is a single \fI-\fP
 character, then the lines are read from standard input.
 .TP
+.B \-x 
+Use simple authentication instead of SASL.
+.TP
 .BI \-D \ binddn
 Use \fIbinddn\fP to bind to the LDAP directory. \fIbinddn\fP should be
 a string-represented DN as defined in RFC 1779.
@@ -222,29 +229,21 @@ limit.
 A server may impose a maximal sizelimit which only
 the root user may override.
 .TP
-.B \-E[E]
-Requset the use of SASL privacy (encryption). If the server allows it, data
-sent between the client and the server will be encrypted. If the server
-requires the use of encryption and this flag is not specified, the command
-will fail. If you use
-.B \-EE\c
-, the command will fail if the server does not support encryption.
-.B \-E[E]
-implies
-.B \-I[I]
-.TP
-.B \-I[I]
-Request the use of SASL integrity checking. It protects data sent between the
-client and the server from being modified along the way, but it does not
-prevent sniffing. If the server requires the use of integrity checking and
-this flag is not specified, the command will fail.If you use
-.B \-II\c
-, the command will fail if the server does not support this function. 
+.BI \-O \ security-properties
+Specify SASL security properties.
+.TP
+.B \-I
+Enable SASL Interactive mode.  Always prompt.  Default is to prompt
+only as needed.
+.TP
+.B \-Q
+Enable SASL Quiet mode.  Never prompt.
 .TP
 .BI \-U \ username
 Specify the username for SASL bind. The syntax of the username depends on the
 actual SASL mechanism used.
 .TP
+.TP
 .BI \-X \ authzid
 Specify the requested authorization ID for SASL bind.
 .I authzid
@@ -390,6 +389,8 @@ Howes, T.,
 .SM RFC
 1558,
 University of Michigan, December 1993.
+.SH AUTHOR
+The OpenLDAP Project <http://www.openldap.org/>
 .SH ACKNOWLEDGEMENTS
 .B     OpenLDAP
 is developed and maintained by The OpenLDAP Project (http://www.openldap.org/).
index 70b260f2a33f3a0d8f082c1e598901c465abc25d..4a9378c4123445a56c7174285ee13b3b48c9aff9 100644 (file)
@@ -1,4 +1,4 @@
-.TH LBER_DECODE 3 "12 May 2000" "OpenLDAP LDVERSION"
+.TH LBER_DECODE 3 "12 July 2000" "OpenLDAP LDVERSION"
 .\" $OpenLDAP$
 .\" Copyright 1998-2000 The OpenLDAP Foundation All Rights Reserved.
 .\" Copying restrictions apply.  See COPYRIGHT/LICENSE.
@@ -349,20 +349,11 @@ Some routines may dynamically allocate memory
 which must be freed by the caller using supplied deallocation routines.
 .SH SEE ALSO
 .BR lber-encode (3)
+.BR lber-memory (3)
 .BR lber-types (3)
 .BR ldap-parse (3)
 .BR ldap-sync (3)
 .BR ldap-async (3)
-.LP
-Yeong, W., Howes, T., and Hardcastle-Kille, S.,
-"Lightweight Directory Access Protocol", OSI-DS-26, April 1992.
-.LP
-Information Processing - Open Systems Interconnection - Model and Notation -
-Service Definition - Specification of Basic Encoding Rules for Abstract
-Syntax Notation One, International Organization for Standardization,
-International Standard 8825.
-.SH AUTHOR
-Tim Howes, University of Michigan
 .SH ACKNOWLEDGEMENTS
 .B     OpenLDAP
 is developed and maintained by The OpenLDAP Project (http://www.openldap.org/).
index 9d5fbb980dc7b3179383570e369ab9c49faad3d7..f7a9e34ccddeae36f2bd68747c7b239ff909c902 100644 (file)
@@ -317,20 +317,11 @@ The return values for all of these functions are declared in the
 <lber.h> header file.
 .SH SEE ALSO
 .BR lber-decode (3)
+.BR lber-memory (3)
 .BR lber-types (3)
 .BR ldap-async (3)
 .BR ldap-sync (3)
 .BR ldap-parse (3)
-.LP
-Yeong, W., Howes, T., and Hardcastle-Kille, S.,
-"Lightweight Directory Access Protocol", OSI-DS-26, April 1992.
-.LP
-Information Processing - Open Systems Interconnection - Model and Notation -
-Service Definition - Specification of Basic Encoding Rules for Abstract
-Syntax Notation One, International Organization for Standardization,
-International Standard 8825.
-.SH AUTHOR
-Tim Howes, University of Michigan
 .SH ACKNOWLEDGEMENTS
 .B     OpenLDAP
 is developed and maintained by The OpenLDAP Project (http://www.openldap.org/).
diff --git a/doc/man/man3/lber-memory.3 b/doc/man/man3/lber-memory.3
new file mode 100644 (file)
index 0000000..beeadc6
--- /dev/null
@@ -0,0 +1,58 @@
+.TH LBER_MEMORY 3 "12 July 2000" "OpenLDAP LDVERSION"
+.\" $OpenLDAP$
+.\" Copyright 1998-2000 The OpenLDAP Foundation All Rights Reserved.
+.\" Copying restrictions apply.  See COPYRIGHT/LICENSE.
+.SH NAME
+ber_memalloc, ber_memcalloc, ber_memrealloc, ber_memfree \- LBER memory allocators
+.SH SYNOPSIS
+.nf
+.ft B
+#include <lber.h>
+.ft
+.fi
+.LP
+.nf
+.ft B
+void * ber_memalloc(
+       ber_len_t bytes )
+.ft
+.fi
+.LP
+.nf
+.ft B
+void * ber_memcalloc(
+       ber_len_t nelems, ber_len_t bytes )
+.ft
+.fi
+.LP
+.nf
+.ft B
+void * ber_memrealloc(
+       void \(**ptr,
+       ber_len_t bytes);
+.ft
+.fi
+.LP
+.nf
+.ft B
+void * ber_memfree(
+       void \(**ptr );
+.ft
+.fi
+.SH DESCRIPTION
+.LP
+These routines are used to allocate/deallocate memory used/returned
+by the Lightweight BER library as required by
+.BR lber-encode (3)
+and
+.BR lber-decode (3).
+.SH SEE ALSO
+.BR lber-decode (3)
+.BR lber-encode (3)
+.BR lber-types (3)
+.LP
+.SH ACKNOWLEDGEMENTS
+.B     OpenLDAP
+is developed and maintained by The OpenLDAP Project (http://www.openldap.org/).
+.B     OpenLDAP
+is derived from University of Michigan LDAP 3.3 Release.  
diff --git a/doc/man/man3/lber-types.3 b/doc/man/man3/lber-types.3
new file mode 100644 (file)
index 0000000..ab9bf04
--- /dev/null
@@ -0,0 +1,45 @@
+.TH LBER_TYPES 3 "12 July 2000" "OpenLDAP LDVERSION"
+.\" $OpenLDAP$
+.\" Copyright 1998-2000 The OpenLDAP Foundation All Rights Reserved.
+.\" Copying restrictions apply.  See COPYRIGHT/LICENSE.
+.SH NAME
+ber_int_t, ber_len_t, ber_tag_t \- LBER types
+.SH SYNOPSIS
+.nf
+.ft B
+#include <lber.h>
+.ft
+.fi
+.LP
+.nf
+.ft B
+typedef impl_int_t ber_int_t;
+typedef impl_len_t ber_len_t;
+typedef impl_tag_t ber_tag_t;
+.ft
+.fi
+.SH DESCRIPTION
+.LP
+The are basic types defined for use with the Lightweight BER library.
+.LP
+.B ber_int_t
+is a signed integer of at least 32 bits.
+.LP
+.B ber_len_t
+is a unsigned integer of at least 32 bits used to represent a length.  
+It is commonly equivalent to a
+.BR size_t .
+.LP
+.B ber_len_t
+is a unsigned integer of at least 32 bits used to represent a
+BER tag.  It is commonly equivalent to a
+.BR unsigned\ long .
+.SH SEE ALSO
+.BR lber-encode (3)
+.BR lber-decode (3)
+.LP
+.SH ACKNOWLEDGEMENTS
+.B     OpenLDAP
+is developed and maintained by The OpenLDAP Project (http://www.openldap.org/).
+.B     OpenLDAP
+is derived from University of Michigan LDAP 3.3 Release.  
index 79b9f2edb42bd0a371fe0b71bd3b365571ffe13f..097e781cbde708128280c96ea67cdbf81726d6f1 100644 (file)
@@ -1,4 +1,4 @@
-.TH LDAP 3 "13 May 2000" "OpenLDAP LDVERSION"
+.TH LDAP 3 "21 July 2000" "OpenLDAP LDVERSION"
 .\" $OpenLDAP$
 .\" Copyright 1998-2000 The OpenLDAP Foundation All Rights Reserved.
 .\" Copying restrictions apply.  See COPYRIGHT/LICENSE.
@@ -12,8 +12,12 @@ ldap - OpenLDAP Lightweight Directory Access Protocol API
 .fi
 .SH DESCRIPTION
 .LP
-The Lightweight Directory Access Protocol provides TCP/IP access to
-the X.500 Directory or to a stand-alone LDAP server.
+The Lightweight Directory Access Protocol provides access to
+X.500 directory services.  The services may be stand\-alone
+part of a distributed directory service.  This API supports
+LDAP over TCP, LDAP over SSL, and LDAP over IPC (UNIX domain
+sockets).
+.LP
 The OpenLDAP LDAP package includes a stand-alone server in
 .BR slapd (8),
 various LDAP clients, and an LDAP client library used to provide
@@ -24,28 +28,27 @@ Both synchronous and asynchronous APIs are provided.  Also included are
 various routines to parse the results returned from these routines.
 These routines are found in the \-lldap library.
 .LP
-The basic interaction is as follows.  A connection is made to an LDAP
-server by calling
-.BR ldap_open (3).
-An LDAP bind operation is performed by calling
-one of
-.BR ldap_bind (3)
+The basic interaction is as follows.  A session handle associated
+with created using
+.BR ldap_init (3).
+The underlying session is established upon first use which is
+commonly an LDAP bind operation.  The LDAP bind operation is
+performed by calling one of
+.BR ldap_sasl_bind (3)
 and friends.  Next, other operations are performed
 by calling one of the synchronous or asynchronous routines (e.g.,
-.BR ldap_search_s (3)
+.BR ldap_search_ext_s (3)
 or
-.BR ldap_search (3)
+.BR ldap_search_ext (3)
 followed by
 .BR ldap_result (3)).
 Results returned from these routines are interpreted by calling the
-LDAP parsing routines.  The LDAP association is terminated by calling
-.BR ldap_unbind (3).
+LDAP parsing routines such as
+.BR ldap_parse_result (3).
+The LDAP association and underlying connection is terminated by calling
+.BR ldap_unbind_ext (3).
 Errors can be interpreted by calling
-.BR ldap_perror (3).
-The
-.BR ldap_set_rebind_proc (3)
-routine can be used to set a routine to be called back when an LDAP bind
-operation needs to occur when handling a client referral.
+.BR ldap_err2string (3).
 .SH SEARCH FILTERS
 Search filters to be passed to the ldap search routines can be
 constructed by hand, or by calling the
@@ -67,9 +70,8 @@ and
 .BR ldap_next_attribute (3)
 to step through an entry's attributes, and
 .BR ldap_get_values (3)
-to retrieve a given attribute's value, and then calling
-.BR printf (3)
-or whatever to display the values.
+to retrieve a given attribute's value.  Attribute values
+may or may not be displayable.
 .LP
 Alternatively, the entry can be output automatically by calling
 the
@@ -94,7 +96,7 @@ The
 .BR ldap_ufn (3)
 routines implement a user friendly naming
 scheme via LDAP.  This scheme allows you to look up entries
-using fuzzy, untyped names like "mark smith, umich, us".
+using fuzzy, untyped names like "john smith, example corp, ca, us".
 .SH CACHING
 The
 .BR ldap_cache (3)
@@ -130,9 +132,10 @@ Also included in the distribution is a set of lightweight Basic
 Encoding Rules routines.  These routines are used by the LDAP library
 routines to encode and decode LDAP protocol elements using the
 (slightly simplified) Basic Encoding Rules defined by LDAP.  They are
-not normally used directly by an LDAP application program.  The
+not normally used directly by an LDAP application program excepting
+in the handling of controls and extended operations.  The
 routines provide a printf and scanf-like interface, as well as
-lower-level access.  These routines are found in the liblber.a
+lower-level access.  These routines are found in the -llber
 library.
 .SH INDEX
 .TP 20
@@ -323,12 +326,6 @@ convert a DN into its component parts
 .SM ldap_explode_rdn(3)
 convert a RDN into its component parts
 .TP
-.SM ldap_explode_dns(3)
-convert a DNS-style DN into its component parts (experimental)
-.TP
-.SM ldap_is_dns_dn(3)
-check to see if a DN is a DNS-style DN (experimental)
-.TP
 .SM ldap_dn2ufn(3)
 convert a DN into user friendly form
 .TP
@@ -467,24 +464,6 @@ sort a list of attribute values
 .SM ldap_sort_strcasecmp(3)
 case insensitive string comparison
 .TP
-.SM ldap_set_string_translators(3)
-set character set translation routines used by LDAP library
-.TP
-.SM ldap_t61_to_8859(3)
-translate from ISO-8859 characters to the T.61 characters
-.TP
-.SM ldap_8859_to_t61(3)
-translate from T.61 characters to the ISO-8859 characters
-.TP
-.SM ldap_translate_from_t61(3)
-translate from the T.61 character set to another character set
-.TP
-.SM ldap_translate_to_t61(3)
-translate to the T.61 character set from another character set
-.TP
-.SM ldap_enable_translation(3)
-enable or disable character translation for an LDAP entry result
-.TP
 .SM cldap_open(3)
 open a connectionless LDAP (CLDAP) session
 .TP
@@ -498,9 +477,6 @@ set retry and timeout information using connectionless LDAP
 terminate a connectionless LDAP session
 .SH SEE ALSO
 .BR slapd (8)
-.SH AUTHORS
-Tim Howes, Mark Smith, Gordon Good, Lance Sloan, and Steve Rothwell from
-the University of Michigan, along with help from lots of others.
 .SH ACKNOWLEDGEMENTS
 .B     OpenLDAP
 is developed and maintained by The OpenLDAP Project (http://www.openldap.org/).
diff --git a/doc/man/man3/ldap_abandon.3.links b/doc/man/man3/ldap_abandon.3.links
new file mode 100644 (file)
index 0000000..3b7bc3f
--- /dev/null
@@ -0,0 +1 @@
+ldap_abandon_ext.3
index 5a065552c1c5e3a58bfff2c2d688689bfe4edbee..8114ef193c930c2f3c54f076280899aba5572b35 100644 (file)
@@ -1 +1,3 @@
 ldap_add_s.3
+ldap_add_ext.3
+ldap_add_ext_s.3
index b03f5928a3f3da93211ac6bd56eaef1c41571d87..ae1b7b86c646c845f18fcfc61999f3830e79bf56 100644 (file)
@@ -1,11 +1,15 @@
 ldap_bind_s.3
 ldap_simple_bind.3
 ldap_simple_bind_s.3
+ldap_sasl_bind.3
+ldap_sasl_bind_s.3
 ldap_kerberos_bind_s.3
 ldap_kerberos_bind1.3
 ldap_kerberos_bind1_s.3
 ldap_kerberos_bind2.3
 ldap_kerberos_bind2_s.3
 ldap_unbind.3
+ldap_unbind_ext.3
 ldap_unbind_s.3
+ldap_unbind_ext_s.3
 ldap_set_rebind_proc.3
diff --git a/doc/man/man3/ldap_charset.3 b/doc/man/man3/ldap_charset.3
deleted file mode 100644 (file)
index 37c9eea..0000000
+++ /dev/null
@@ -1,134 +0,0 @@
-.TH LDAP_CHARSET 3 "22 September 1998" "OpenLDAP LDVERSION"
-.\" $OpenLDAP$
-.\" Copyright 1998-2000 The OpenLDAP Foundation All Rights Reserved.
-.\" Copying restrictions apply.  See COPYRIGHT/LICENSE.
-.SH NAME
-ldap_set_string_translators,
-ldap_t61_to_8859,
-ldap_8859_to_t61,
-ldap_translate_from_t61,
-ldap_translate_to_t61,
-ldap_enable_translation \- LDAP character set translation routines
-.SH SYNOPSIS
-.nf
-.ft B
-#include <ldap.h>
-.ft
-.LP
-.ft B
-void ldap_set_string_translators( ld, encode_proc, decode_proc )
-.ft
-LDAP                   *ld;
-BERTranslateProc       encode_proc;
-BERTranslateProc       decode_proc;
-.LP
-.ft B
-typedef int (*BERTranslateProc)( char **bufp, unsigned long *buflenp,
-       int free_input );
-.ft
-.LP
-.ft B
-int ldap_t61_to_8859( bufp, buflenp, free_input )
-.ft
-char           **bufp;
-unsigned long  *buflenp;
-int            free_input;
-.LP
-.ft B
-int ldap_8859_to_t61( bufp, buflenp, free_input )
-.ft
-char           **bufp;
-unsigned long  *buflenp;
-int            free_input;
-.LP
-.ft B
-int ldap_translate_from_t61( ld, bufp, lenp, free_input )
-.ft
-LDAP           *ld;
-char           **bufp;
-unsigned long  *lenp;
-int             free_input;
-.LP
-.ft B
-int ldap_translate_to_t61( ld, bufp, lenp, free_input )
-.ft
-LDAP           *ld;
-char           **bufp;
-unsigned long  *lenp;
-int             free_input;
-.LP
-.ft B
-void ldap_enable_translation( ld, entry, enable )
-.ft
-LDAP           *ld;
-LDAPMessage    *entry;
-int            enable;
-.fi
-.SH DESCRIPTION
-.LP
-These routines are used to used to enable translation of character strings
-used in the LDAP library to and from the T.61 character set used in the
-LDAP protocol.  These functions are only available if the LDAP and LBER
-libraries are compiled with STR_TRANSLATION defined.
-It is also possible to turn on character translation by default so that
-all LDAP library callers will experience translation; see the LDAP
-Make-common source file for details.
-.LP
-.B ldap_set_string_translators()
-sets the translation routines that will
-be used by the LDAP library.  They are not actually used until the
-\fIld_lberoptions\fP field of the LDAP structure is set to include the
-LBER_TRANSLATE_STRINGS option.
-.LP
-.B ldap_t61_to_8859()
-and
-.B ldap_8859_to_t61()
-are translation routines for
-converting between T.61 characters and ISO-8859 characters.  The specific
-8859 character set used is determined at compile time.
-.LP
-.B ldap_translate_from_t61()
-is used to translate a string of characters from the T.61 character set to a
-different character set.  The actual translation is done using the
-\fIdecode_proc\fP that was passed to a previous call to
-.B ldap_set_string_translators().
-On entry, \fI*bufp\fP should point to the start of the T.61 characters
-to be translated and \fI*lenp\fP should contain the number of bytes to
-translate.  If \fIfree_input\fP is non-zero, the input buffer will be
-freed if translation is a success.  If the translation is a success,
-LDAP_SUCCESS will be returned, \fI*bufp\fP will point to a newly
-dynamically allocated buffer that contains the translated characters, and
-\fI*lenp\fP will contain the length of the result.  If translation
-fails, an LDAP error code will be returned.
-
-.LP
-.B ldap_translate_to_t61()
-is used to translate a string of characters to the T.61 character set from a
-different character set.  The actual translation is done using the
-\fIencode_proc\fP that was passed to a previous call to
-.B ldap_set_string_translators().
-This function is called just like
-.B ldap_translate_from_t61().
-.LP
-.B ldap_enable_translation()
-is used to turn on or off string translation for the LDAP entry \fIentry\fP
-(typically obtained by calling
-.B ldap_first_entry()
-or
-.B ldap_next_entry()
-after a successful LDAP search operation).  If \fIenable\fP is zero,
-translation is disabled; if non-zero, translation is enabled.  This routine
-is useful if you need to ensure that a particular attribute is not
-translated when it is extracted using
-.B ldap_get_values()
-or
-.B ldap_get_values_len().
-For example, you would not want to translate a binary attributes such as
-jpegPhoto.
-.SH SEE ALSO
-.BR ldap (3)
-.SH ACKNOWLEDGEMENTS
-.B     OpenLDAP
-is developed and maintained by The OpenLDAP Project (http://www.openldap.org/).
-.B     OpenLDAP
-is derived from University of Michigan LDAP 3.3 Release.  
diff --git a/doc/man/man3/ldap_charset.3.links b/doc/man/man3/ldap_charset.3.links
deleted file mode 100644 (file)
index c7525af..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-ldap_set_string_translators.3
-ldap_enable_translation.3
-ldap_translate_from_t61.3
-ldap_translate_to_t61.3
-ldap_t61_to_8859.3
-ldap_8859_to_t61.3
index ed16b8ec5711cb82fecf9273d57725627d05c72b..66821ccc860f3c6d1cfacc2afce914bfbf118271 100644 (file)
@@ -1 +1,3 @@
 ldap_compare_s.3
+ldap_compare_ext.3
+ldap_compare_ext_s.3
index 7bf980f207418fc9244bada4521c98fdf8c23fd9..d4eac2fdc3275645c065e406a12d55f661f964cf 100644 (file)
@@ -1 +1,3 @@
 ldap_delete_s.3
+ldap_delete_ext.3
+ldap_delete_ext_s.3
index c76f28242c4f3ac4d1ab25ff848565b5d71cb6f4..53e995a9f365860d26937c7766718cafa62ceea8 100644 (file)
@@ -1,9 +1,9 @@
-.TH LDAP_GET_DN 3 "22 September 1998" "OpenLDAP LDVERSION"
+.TH LDAP_GET_DN 3 "21 July 2000" "OpenLDAP LDVERSION"
 .\" $OpenLDAP$
 .\" Copyright 1998-2000 The OpenLDAP Foundation All Rights Reserved.
 .\" Copying restrictions apply.  See COPYRIGHT/LICENSE.
 .SH NAME
-ldap_get_dn, ldap_explode_dn, ldap_explode_rdn, ldap_dn2ufn, ldap_is_dns_dn, ldap_explode_dns \- LDAP DN handling routines
+ldap_get_dn, ldap_explode_dn, ldap_explode_rdn, ldap_dn2ufn \- LDAP DN handling routines
 .SH SYNOPSIS
 .nf
 .ft B
@@ -31,16 +31,6 @@ int notypes;
 char *ldap_dn2ufn(dn)
 .ft
 char *dn;
-.LP
-.ft B
-int ldap_is_dns_dn(dn)
-.ft
-char *dn;
-.LP
-.ft B
-char **ldap_explode_dns(dn)
-.ft
-char *dn;
 .SH DESCRIPTION
 These routines allow LDAP entry names (Distinguished Names, or DNs)
 to be obtained, parsed, converted to a user-friendly form, and tested.
@@ -93,20 +83,6 @@ for more details on the UFN format.  The space for the UFN returned
 is obtained dynamically and the user is responsible for freeing it
 via a call to
 .BR ldap_memfree (3).
-.LP
-.B ldap_is_dns_dn()
-returns non-zero if the dn string is an experimental
-DNS-style DN (generally in the form of an RFC 822 e-mail address).  It
-returns zero if the dn appears to be an RFC 1779 format DN.
-.LP
-.B ldap_explode_dns()
-takes a DNS-style DN and breaks it up into its
-component parts.
-.B ldap_explode_dns()
-returns a NULL-terminated array.
-For example, the DN "mcs.umich.edu" will return { "mcs", "umich", "edu",
-NULL }.  The result can be freed by calling
-.BR ldap_value_free (3).
 .SH ERRORS
 If an error occurs in
 .BR ldap_get_dn() ,
@@ -117,7 +93,6 @@ field in the \fIld\fP parameter is set to indicate the error.  See
 for a description of possible error codes.
 .BR ldap_explode_dn() ,
 .BR ldap_explode_rdn() ,
-.B ldap_explode_dns()
 and
 .B ldap_dn2ufn()
 will return NULL with
index f713c4ba0e478a27639f7ab02fdffcae76540800..fe88d238cff267c3a92349a597fe25810c209767 100644 (file)
@@ -1,4 +1,3 @@
 ldap_explode_dn.3
-ldap_explode_dns.3
+ldap_explode_rdn.3
 ldap_dn2ufn.3
-ldap_is_dns_dn.3
index 8eebf4129a951e8a31592cb609fbf97ed1e37443..81c6f2a7d27d799a32b9b60f156b2278ae21481f 100644 (file)
@@ -1,2 +1,4 @@
 ldap_modify_s.3
+ldap_modify_ext.3
+ldap_modify_ext_s.3
 ldap_mods_free.3
index ff54c0d4557231f552fa6094fef976f87d5d80de..d85bf8197c9e092937e05273b9f91f82b305c1cb 100644 (file)
@@ -1,2 +1,4 @@
 ldap_search_s.3
 ldap_search_st.3
+ldap_search_ext.3
+ldap_search_ext_s.3
index 1e9e5266e9345e2c7ecda4094f4d1b262f8956f2..0ba36c568cdc57ea10218b8121b37725669d05b3 100644 (file)
@@ -63,6 +63,9 @@ listed of host may be provided.
 Used to specify the port used with connecting to LDAP servers(s).
 The port may be specified as a number.
 .TP 1i
+\fBSASL_SECPROPS <string>\fP
+Used to specify Cyrus SASL security properties.
+.TP 1i
 \fBSIZELIMIT <integer>\fP
 Used to specify a size limit to use when performing searches.  The
 number should be an non-negative integer.  \fISIZELIMIT\fP of zero (0)
index 14d95a89373f87e426d789839452ec46f84183f3..5b101652f282e2bf5360173b4fe74a63440d1bc3 100644 (file)
@@ -74,10 +74,10 @@ by <who>).
 See Developer's FAQ (http://www.openldap.org/faq/) for details.
 .TP
 .B
-attributetype ( <oid> [NAME <name>] [DESC <description>] [OBSOLETE] \
-[SUP <oid>] [EQUALITY <oid>] [ORDERING <oid>] [SUBSTR <oid>] \
-[SYNTAX <oidlen>] [SINGLE-VALUE] [COLLECTIVE] [NO-USER-MODIFICATION] \
-[USAGE <attributeUsage>] )
+attributetype ( <oid> [NAME <name>] [DESC <description>] \
+[OBSOLETE] [SUP <oid>] [EQUALITY <oid>] [ORDERING <oid>] \
+[SUBSTR <oid>] [SYNTAX <oidlen>] [SINGLE\-VALUE] [COLLECTIVE] \
+[NO\-USER\-MODIFICATION] [USAGE <attributeUsage>] )
 Specify an attribute type using the LDAPv3 syntax defined in RFC 2252.
 The slapd parser extends the RFC 2252 definition by allowing string
 forms as well as numeric OIDs to be used for the attribute OID and
index 96a24e74633f91a1658f71c18f01bcc1c9c04cb5..3b0faea380d476cbad95f0e282844884e89dd8ad 100644 (file)
@@ -23,7 +23,7 @@ is used to generate an LDAP Directory Interchange Format
 .BR slapd (8)
 database.
 It opens the given database determined by the database number or
-suffix and and writes the corresponding LDIF to standard output or
+suffix and writes the corresponding LDIF to standard output or
 the specified file.
 .LP
 The LDIF generated by this tool is suitable for use with
diff --git a/doc/man/man8/slapindex.8 b/doc/man/man8/slapindex.8
new file mode 100644 (file)
index 0000000..b94fc7d
--- /dev/null
@@ -0,0 +1,83 @@
+.TH SLAPINDEX 8C "17 July 1999" "OpenLDAP LDVERSION"
+.\" $OpenLDAP$
+.\" Copyright 1998-2000 The OpenLDAP Foundation All Rights Reserved.
+.\" Copying restrictions apply.  See COPYRIGHT/LICENSE.
+.SH NAME
+slapindex \- SLAPD index to LDIF utility
+.SH SYNOPSIS
+.B SBINDIR/slapcat
+.B [\-v]
+.B [\-c]
+.B [\-d level]
+.B [\-b suffix]
+.B [\-n dbnum]
+.B [\-f slapd.conf]
+.B 
+.LP
+.SH DESCRIPTION
+.LP
+.B Slapindex
+is used to regenerate
+.BR slapd (8)
+indices based upon the current contents of a database.
+It opens the given database determined by the database number or
+suffix and updates the indices for all values of all attributes
+of all entries.
+.SH OPTIONS
+.TP
+.B \-v
+enable verbose mode.
+.TP
+.B \-c
+enable continue (ignore errors) mode.
+.TP
+.BI \-d " level"
+enable debugging messages as defined by the specified
+.IR level .
+.TP
+.BI \-b " suffix" 
+Use the specified \fIsuffix\fR to determine which database to
+generate output for.  The \-b cannot be used in conjunction
+with the
+.B \-n
+option.
+.TP
+.BI \-n " dbnum"
+Generate output for the \fIdbnum\fR\-th database listed in the
+configuration file.  The
+.B \-n
+cannot be used in conjunction with the
+.B \-b
+option.
+.TP
+.BI \-f " slapd.conf"
+specify an alternative
+.BR slapd.conf (5)
+file.
+.SH LIMITATIONS
+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.
+.LP
+This command provides ample opportunity for the user to obtain
+and drink their favorite beverage.
+.SH EXAMPLES
+To reindex your SLAPD database, give the command:
+.LP
+.nf
+.ft tt
+       SBINDIR/slapindex
+.ft
+.fi
+.SH "SEE ALSO"
+.BR ldap (3),
+.BR ldif (5),
+.BR slapadd (8),
+.BR ldapadd (1),
+.BR slapd (8)
+.SH ACKNOWLEDGEMENTS
+.B     OpenLDAP
+is developed and maintained by The OpenLDAP Project (http://www.openldap.org/).
+.B     OpenLDAP
+is derived from University of Michigan LDAP 3.3 Release.  
index 84d787de27e79eebbd34f81fd9788a2608802db7..706125a18a877003d046df181f70cd627b04c62a 100644 (file)
@@ -3,9 +3,10 @@
 .\" Copyright 1998-2000 The OpenLDAP Foundation All Rights Reserved.
 .\" Copying restrictions apply.  See COPYRIGHT/LICENSE.
 .SH NAME
-slappassword \- OpenLDAP password utility
+slappasswd \- OpenLDAP password utility
 .SH SYNOPSIS
 .B SBINDIR/slappasswd
+.B [\-a]
 .B [\-v]
 .B [\-s secret]
 .B [\-h hash]
@@ -20,6 +21,9 @@ as a userPassword value
 .BR rootpw .
 .SH OPTIONS
 .TP
+.B \-a
+generate authPassword values instead of RFC2307 passwords
+.TP
 .B \-v
 enable verbose mode.
 .TP
@@ -27,8 +31,8 @@ enable verbose mode.
 The secret to hash.  If not provided, the user will be prompted
 for the secret to hash.
 .TP
-.BI \-h " hash"
-The hash algorithm to use.  Algorithms supported include
+.BI \-h " scheme"
+The hash scheme to use.  RFC2307 schemes supported include
 .IR {CRYPT} ,
 .IR {MD5} ,
 .IR {SMD5} ,
@@ -36,10 +40,18 @@ The hash algorithm to use.  Algorithms supported include
 .IR {SHA} .
 The default is 
 .IR {SSHA} .
+.LP
+If \-a is specified, the following authPassword schemes
+may be specified:
+.IR MD5 ,
+.IR SHA1 ", and"
+.IR X-CRYPT .
+The default is
+.IR SHA1 .
 .SH LIMITATIONS
 The practice storing hashed passwords in userPassword
 violates Standard Track schema and may hinder
-interoperability.
+interoperability.  authPassword is not yet widely supported.
 .SH "SECURITY CONSIDERATIONS"
 Use of hashed passwords does not protect passwords during
 protocol transfer.  TLS or other eavesdropping protections
@@ -47,7 +59,8 @@ should be inplace before using LDAP simple bind.  The
 hashed password values should be protected as if they
 were clear text passwords.
 .SH "SEE ALSO"
-.BR ldapmodify (3),
+.BR ldappasswd (1),
+.BR ldapmodify (1),
 .BR slapd (8)
 .SH ACKNOWLEDGEMENTS
 .B     OpenLDAP
index 297dcc719406f41ceede26fb89fb3b16b374f4af..b599d3b1e8f64ccd365f72c753cb7a829c3935a3 100644 (file)
@@ -1,12 +1,5 @@
 This is an index of RFC contained in this directory:
 
-STD    Standard
-DS     Draft Standard
-PS     Proposed Standard
-
-I      Information
-E      Experimental
-
 rfc1274.txt COSINE and Internet X.500 Schema (PS)
 rfc1275.txt X.500 Replication Requirements (I)
 rfc1279.txt X.500 and Domains (E)
@@ -49,9 +42,19 @@ rfc2696.txt LDAP Simple Paged Result Control (PS)
 rfc2713.txt LDAP Java schema (I)
 rfc2714.txt LDAP COBRA schema (I)
 rfc2798.txt LDAP inetOrgPerson schema (I)
-rfc2829.txt LDAPv3/Authentication Methods (PS)
-rfc2830.txt LDAPv3/StartTLS (PS)
+rfc2820.txt Access Control Requirements for LDAP (I)
+rfc2829.txt LDAPv3: Authentication Methods (PS)
+rfc2830.txt LDAPv3: StartTLS (PS)
 rfc2831.txt SASL/DIGEST-MD5 (PS)
 rfc2849.txt LDIFv1 (PS)
 
+Legend:
+STD    Standard
+DS     Draft Standard
+PS     Proposed Standard
+I      Information
+E      Experimental
+FYI    For Your Information 
+BCP    Best Common Practice
+
 $OpenLDAP$
diff --git a/doc/rfc/rfc2820.txt b/doc/rfc/rfc2820.txt
new file mode 100644 (file)
index 0000000..0a519f7
--- /dev/null
@@ -0,0 +1,507 @@
+
+
+
+
+
+
+Network Working Group                                      E. Stokes
+Request for Comments: 2820                                  D. Byrne
+Category: Informational                                          IBM
+                                                          B. Blakley
+                                                              Dascom
+                                                           P. Behera
+                                                            Netscape
+                                                            May 2000
+
+
+                  Access Control Requirements for LDAP
+
+Status of this Memo
+
+   This memo provides information for the Internet community.  It does
+   not specify an Internet standard of any kind.  Distribution of this
+   memo is unlimited.
+
+Copyright Notice
+
+   Copyright (C) The Internet Society (2000).  All Rights Reserved.
+
+Abstract
+
+   This document describes the fundamental requirements of an access
+   control list (ACL) model for the Lightweight Directory Application
+   Protocol (LDAP) directory service.  It is intended to be a gathering
+   place for access control requirements needed to provide authorized
+   access to and interoperability between directories.
+
+   The keywords "MUST", "SHOULD", and "MAY" used in this document are to
+   be interpreted as described in [bradner97].
+
+1.  Introduction
+
+   The ability to securely access (replicate and distribute) directory
+   information throughout the network is necessary for successful
+   deployment.  LDAP's acceptance as an access protocol for directory
+   information is driving the need to provide an access control model
+   definition for LDAP directory content among servers within an
+   enterprise and the Internet.  Currently LDAP does not define an
+   access control model, but is needed to ensure consistent secure
+   access across heterogeneous LDAP implementations.  The requirements
+   for access control are critical to the successful deployment and
+   acceptance of LDAP in the market place.
+
+   The RFC 2119 terminology is used in this document.
+
+
+
+
+Stokes, et al.               Informational                      [Page 1]
+\f
+RFC 2820          Access Control Requirements for LDAP          May 2000
+
+
+2.  Objectives
+
+   The major objective is to provide a simple, but secure, highly
+   efficient access control model for LDAP while also providing the
+   appropriate flexibility to meet the needs of both the Internet and
+   enterprise environments and policies.
+
+   This generally leads to several general requirements that are
+   discussed below.
+
+3.  Requirements
+
+   This section is divided into several areas of requirements: general,
+   semantics/policy, usability, and nested groups (an unresolved issue).
+   The requirements are not in any priority order.  Examples and
+   explanatory text is provided where deemed necessary.  Usability is
+   perhaps the one set of requirements that is generally overlooked, but
+   must be addressed to provide a secure system. Usability is a security
+   issue, not just a nice design goal and requirement. If it is
+   impossible to set and manage a policy for a secure situation that a
+   human can understand, then what was set up will probably be non-
+   secure. We all need to think of usability as a functional security
+   requirement.
+
+3.1  General
+
+   G1.  Model SHOULD be general enough to support extensibility to add
+   desirable features in the future.
+
+   G2.  When in doubt, safer is better, especially when establishing
+   defaults.
+
+   G3.  ACL administration SHOULD be part of the LDAP protocol.  Access
+   control information MUST be an LDAP attribute.
+
+   G4.  Object reuse protection SHOULD be provided and MUST NOT inhibit
+   implementation of object reuse. The directory SHOULD support policy
+   controlling the re-creation of deleted DNs, particularly in cases
+   where they are re-created for the purpose of assigning them to a
+   subject other than the owner of the deleted DN.
+
+3.2  Semantics / Policy
+
+   S1.  Omitted as redundant; see U8.
+
+   S2.  More specific policies must override less specific ones (e.g.
+   individual user entry in ACL SHOULD take precedence over group entry)
+   for the evaluation of an ACL.
+
+
+
+Stokes, et al.               Informational                      [Page 2]
+\f
+RFC 2820          Access Control Requirements for LDAP          May 2000
+
+
+   S3.  Multiple policies of equal specificity SHOULD be combined in
+   some easily-understood way (e.g. union or intersection).  This is
+   best understood by example.  Suppose user A belongs to 3 groups and
+   those 3 groups are listed on the ACL. Also suppose that the
+   permissions for each of those groups are not identical. Each group is
+   of equal specificity (e.g. each group is listed on the ACL) and the
+   policy for granting user A access (given the example) SHOULD be
+   combined in some easily understood way, such as by intersection or
+   union.  For example, an intersection policy here may yield a more
+   limited access for user A than a union policy.
+
+   S4.  Newly created directory entries SHOULD be subject to a secure
+   default policy.
+
+   S5.  Access policy SHOULD NOT be expressed in terms of attributes
+   which the directory administrator or his organization cannot
+   administer (e.g. groups whose membership is administered by another
+   organization).
+
+   S6.  Access policy SHOULD NOT be expressed in terms of attributes
+   which are easily forged (e.g. IP addresses).  There may be valid
+   reasons for enabling access based on attributes that are easily
+   forged and the behavior/implications of doing that should be
+   documented.
+
+   S7.  Humans (including administrators) SHOULD NOT be required to
+   manage access policy on the basis of attributes which are not
+   "human-readable" (e.g. IP addresses).
+
+   S8.  It MUST be possible to deny a subject the right to invoke a
+   directory operation.  The system SHOULD NOT require a specific
+   implementation of denial (e.g.  explicit denial, implicit denial).
+
+   S9.  The system MUST be able (semantically) to support either
+   default-grant or default-deny semantics (not simultaneously).
+
+   S10.  The system MUST be able to support either union semantics or
+   intersection semantics for aggregate subjects (not simultaneously).
+
+   S11.  Absence of policy SHOULD be interpretable as grant or deny.
+   Deny takes precedence over grant among entries of equal specificity.
+
+   S12.  ACL policy resolution MUST NOT depend on the order of entries
+   in the ACL.
+
+   S13.  Rights management MUST have no side effects.  Granting a
+   subject one right to an object MUST NOT implicitly grant the same or
+   any other subject a different right to the same object.  Granting a
+
+
+
+Stokes, et al.               Informational                      [Page 3]
+\f
+RFC 2820          Access Control Requirements for LDAP          May 2000
+
+
+   privilege attribute to one subject MUST NOT implicitly grant the same
+   privilege attribute to any other subject.  Granting a privilege
+   attribute to one subject MUST NOT implicitly grant a different
+   privilege attribute to the same or any other subject.  Definition: An
+   ACL's "scope" is defined as the set of directory objects governed by
+   the policy it defines; this set of objects is a sub-tree of the
+   directory.  Changing the policy asserted by an ACL (by changing one
+   or more of its entries) MUST NOT implicitly change the policy
+   governed by an ACL in a different scope.
+
+   S14.  It SHOULD be possible to apply a single policy to multiple
+   directory entries, even if those entries are in different subtrees.
+   Applying a single policy to multiple directory entries SHOULD NOT
+   require creation and storage of multiple copies of the policy data.
+   The system SHOULD NOT require a specific implementation (e.g. nested
+   groups, named ACLs) of support for policy sharing.
+
+3.3  Usability (Manageability)
+
+   U1.  When in doubt, simpler is better, both at the interface and in
+   the implementation.
+
+   U2.  Subjects MUST be drawn from the "natural" LDAP namespace; they
+   should be DNs.
+
+   U3.  It SHOULD NOT be possible via ACL administration to lock all
+   users, including all administrators, out of the directory.
+
+   U4.  Administrators SHOULD NOT be required to evaluate arbitrary
+   Boolean predicates in order to create or understand policy.
+
+   U5.  Administrators SHOULD be able to administer access to
+   directories and their attributes based on their sensitivity, without
+   having to understand the semantics of individual schema elements and
+   their attributes (see U9).
+
+   U6.  Management of access to resources in an entire subtree SHOULD
+   require only one ACL (at the subtree root).  Note that this makes
+   access control based explicitly on attribute types very hard, unless
+   you constrain the types of entries in subtrees.  For example, another
+   attribute is added to an entry. That attribute may fall outside the
+   grouping covered by the ACL and hence require additional
+   administration where the desired affect is indeed a different ACL.
+   Access control information specified in one administrative area MUST
+   NOT have jurisdiction in another area.  You SHOULD NOT be able to
+   control access to the aliased entry in the alias.  You SHOULD be able
+   to control access to the alias name.
+
+
+
+
+Stokes, et al.               Informational                      [Page 4]
+\f
+RFC 2820          Access Control Requirements for LDAP          May 2000
+
+
+   U7.  Override of subtree policy MUST be supported on a per-
+   directory-entry basis.
+
+   U8.  Control of access to individual directory entry attributes (not
+   just the whole directory entry) MUST be supported.
+
+   U9.  Administrator MUST be able to coarsen access policy granularity
+   by grouping attributes with similar access sensitivities.
+
+   U10.  Control of access on a per-user granularity MUST be supported.
+
+   U11.  Administrator MUST be able to aggregate users (for example, by
+   assigning them to groups or roles) to simplify administration.
+
+   U12.  It MUST be possible to review "effective access" of any user,
+   group, or role to any entry's attributes. This aids the administrator
+   in setting the correct policy.
+
+   U13.  A single administrator SHOULD be able to define policy for the
+   entire directory tree.  An administrator MUST be able to delegate
+   policy administration for specific subtrees to other users.  This
+   allows for the partitioning of the entire directory tree for policy
+   administration, but still allows a single policy to be defined for
+   the entire tree independent of partitioning.  (Partition in this
+   context means scope of administration). An administrator MUST be able
+   to create new partitions at any point in the directory tree, and MUST
+   be able to merge a superior and subordinate partition.  An
+   administrator MUST be able to configure whether delegated access
+   control information from superior partitions is to be accepted or
+   not.
+
+   U14.  It MUST be possible to authorize users to traverse directory
+   structure even if they are not authorized to examine or modify some
+   traversed entries; it MUST also be possible to prohibit this.  The
+   tree structure MUST be able to be protected from view if so desired
+   by the administrator.
+
+   U15.  It MUST be possible to create publicly readable entries, which
+   may be read even by unauthenticated clients.
+
+   U16.  The model for combining multiple access control list entries
+   referring to a single individual MUST be easy to understand.
+
+   U17.  Administrator MUST be able to determine where inherited policy
+   information comes from, that is, where ACLs are located and which
+   ACLs were applied. Where inheritance of ACLs is applied, it must be
+   able to be shown how/where that new ACL is derived from.
+
+
+
+
+Stokes, et al.               Informational                      [Page 5]
+\f
+RFC 2820          Access Control Requirements for LDAP          May 2000
+
+
+   U18.  It SHOULD be possible for the administrator to configure the
+   access control system to permit users to grant additional access
+   control rights for entries which they create.
+
+4.  Security Considerations
+
+   Access control is a security consideration.  This documents addresses
+   the requirements.
+
+5.  Glossary
+
+   This glossary is intended to aid the novice not versed in depth about
+   access control.  It contains a list of terms and their definitions
+   that are commonly used in discussing access control [emca].
+
+   Access control - The prevention of use of a resource by unidentified
+   and/or unauthorized entities in any other that an authorized manner.
+
+   Access control list - A set of control attributes.  It is a list,
+   associated with a security object or a group of security objects.
+   The list contains the names of security subjects and the type of
+   access that may be granted.
+
+   Access control policy - A set of rules, part of a security policy, by
+   which human users, or their representatives, are authenticated and by
+   which access by these users to applications and other services and
+   security objects is granted or denied.
+
+   Access context - The context, in terms of such variables as location,
+   time of day, level of security of the underlying associations, etc.,
+   in which an access to a security object is made.
+
+   Authorization - The granting of access to a security object.
+
+   Authorization policy - A set of rules, part of an access control
+   policy, by which access by security subjects to security objects is
+   granted or denied.  An authorization policy may be defined in terms
+   of access control lists, capabilities, or attributes assigned to
+   security subjects, security objects, or both.
+
+   Control attributes - Attributes, associated with a security object
+   that, when matched against the privilege attributes of a security
+   subject, are used to grant or deny access to the security object.  An
+   access control list or list of rights or time of day range are
+   examples of control attributes.
+
+   Credentials - Data that serve to establish the claimed identity of a
+   security subject relative to a given security domain.
+
+
+
+Stokes, et al.               Informational                      [Page 6]
+\f
+RFC 2820          Access Control Requirements for LDAP          May 2000
+
+
+   Privilege attributes - Attributes, associated with a security subject
+   that, when matched against control attributes of a security object,
+   are used to grant or deny access to that subject.  Group and role
+   memberships are examples of privilege attributes.
+
+   Security attributes - A general term covering both privilege
+   attributes and control attributes.  The use of security attributes is
+   defined by a security policy.
+
+   Security object - An entity in a passive role to which a security
+   policy applies.
+
+   Security policy - A general term covering both access control
+   policies and authorization policies.
+
+   Security subject - An entity in an active role to which a security
+   policy applies.
+
+6.  References
+
+   [ldap]      Kille, S., Howes, T. and M. Wahl, "Lightweight Directory
+               Access Protocol (v3)", RFC 2251, August 1997.
+
+   [ecma]      ECMA, "Security in Open Systems: A Security Framework"
+               ECMA TR/46, July 1988.
+
+   [bradner97] Bradner, S., "Key Words for use in RFCs to Indicate
+               Requirement Levels", BCP 14, RFC 2119, March 1997.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Stokes, et al.               Informational                      [Page 7]
+\f
+RFC 2820          Access Control Requirements for LDAP          May 2000
+
+
+7. Authors' Addresses
+
+   Bob Blakley
+   Dascom
+   5515 Balcones Drive
+   Austin, TX 78731
+   USA
+
+   Phone: +1 512 458 4037  ext 5012
+   Fax:   +1 512 458 2377
+   EMail: blakley@dascom.com
+
+
+   Ellen Stokes
+   IBM
+   11400 Burnet Rd
+   Austin, TX 78758
+   USA
+
+   Phone: +1 512 838 3725
+   Fax:   +1 512 838 0156
+   EMail: stokes@austin.ibm.com
+
+
+   Debbie Byrne
+   IBM
+   11400 Burnet Rd
+   Austin, TX 78758
+   USA
+
+   Phone: +1 512 838 1930
+   Fax:   +1 512 838 8597
+   EMail: djbyrne@us.ibm.com
+
+
+   Prasanta Behera
+   Netscape
+   501 Ellis Street
+   Mountain View, CA 94043
+   USA
+
+   Phone: +1 650 937 4948
+   Fax:   +1 650 528-4164
+   EMail: prasanta@netscape.com
+
+
+
+
+
+
+
+Stokes, et al.               Informational                      [Page 8]
+\f
+RFC 2820          Access Control Requirements for LDAP          May 2000
+
+
+8.  Full Copyright Statement
+
+   Copyright (C) The Internet Society (2000).  All Rights Reserved.
+
+   This document and translations of it may be copied and furnished to
+   others, and derivative works that comment on or otherwise explain it
+   or assist in its implementation may be prepared, copied, published
+   and distributed, in whole or in part, without restriction of any
+   kind, provided that the above copyright notice and this paragraph are
+   included on all such copies and derivative works.  However, this
+   document itself may not be modified in any way, such as by removing
+   the copyright notice or references to the Internet Society or other
+   Internet organizations, except as needed for the purpose of
+   developing Internet standards in which case the procedures for
+   copyrights defined in the Internet Standards process must be
+   followed, or as required to translate it into languages other than
+   English.
+
+   The limited permissions granted above are perpetual and will not be
+   revoked by the Internet Society or its successors or assigns.
+
+   This document and the information contained herein is provided on an
+   "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+   TASK FORCE DISCLAIMS 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.
+
+Acknowledgement
+
+   Funding for the RFC Editor function is currently provided by the
+   Internet Society.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Stokes, et al.               Informational                      [Page 9]
+\f
index 3f143363d74f4ad7c873aae63cd92dd1fdc1fc32..6975417419e91f253e087ba20a6f936d3513951f 100644 (file)
@@ -13,6 +13,9 @@
 #ifndef _AC_ALLOCA_H
 #define _AC_ALLOCA_H
 
+/*
+ * use of alloca is disallowed as it is machine dependent
+ */
 #error  "alloca() not supported, use malloc()"
 
 /* AIX requires this to be the first thing in the file.  */
index faca4c66ad285b732f7f35649bd58df88d9c153b..667aae039671dd16d07b963f0918321bd3b00cad 100644 (file)
 #include <signal.h>
 
 #undef SIGNAL
-#ifdef HAVE_SIGSET
+
+#if defined( HAVE_SIGACTION )
+#define SIGNAL lutil_sigaction
+typedef void (*lutil_sig_t)(int);
+LDAP_LUTIL_F(lutil_sig_t) lutil_sigaction( int sig, lutil_sig_t func );
+#define SIGNAL_REINSTALL(sig,act)      (void)0
+#elif defined( HAVE_SIGSET )
 #define SIGNAL sigset
+#define SIGNAL_REINSTALL sigset
 #else
 #define SIGNAL signal
+#define SIGNAL_REINSTALL signal
 #endif
 
 #if !defined( LDAP_SIGUSR1 ) || !defined( LDAP_SIGUSR2 )
index 81b4895e8cb5b7b2a67134a04bc95b5163e2f34a..027ed88765844d1b77938427e331dba9a40201b9 100644 (file)
@@ -167,5 +167,13 @@ LDAP_F (int) ldap_pvt_inet_aton LDAP_P(( const char *, struct in_addr * ));
 #define AC_HTONS( s ) htons( s )
 #define AC_NTOHS( s ) ntohs( s )
 
+#ifdef LDAP_PF_LOCAL
+#  if !defined( AF_LOCAL ) && defined( AF_UNIX )
+#    define AF_LOCAL   AF_UNIX
+#  endif
+#  if !defined( PF_LOCAL ) && defined( PF_UNIX )
+#    define PF_LOCAL   PF_UNIX
+#  endif
+#endif
 
 #endif /* _AC_SOCKET_H_ */
index bac0dc256e995eec8fe2a2f5af681bc3dd849094..c5471e158379479d4f3e16f9d7095438061fe53c 100644 (file)
@@ -75,4 +75,10 @@ int (strncasecmp)();
 #      endif
 #endif
 
+#define AC_MEMCPY( d, s, n ) (SAFEMEMCPY((d),(s),(n)))
+#define AC_FMEMCPY( d, s, n ) do { \
+               if((n) == 1) *((char*)(d)) = *((char*)(s)); \
+               else AC_MEMCPY( (d), (s), (n) ); \
+       } while(0)
+
 #endif /* _AC_STRING_H */
index 8a06fe60e8a40fc426b6d0d5511b3888e3e286e4..7751cd960d2a16f3c2669c64c9618ee946513a0b 100644 (file)
@@ -122,6 +122,7 @@ LDAP_BEGIN_DECL
 #define LDAP_OPT_X_TLS                 0x6007
 #define LDAP_OPT_X_TLS_PROTOCOL                0x6008
 #define LDAP_OPT_X_TLS_CIPHER_SUITE    0x6009
+#define LDAP_OPT_X_TLS_RANDOM_FILE     0x600a
 
 #define LDAP_OPT_X_TLS_NEVER           0
 #define LDAP_OPT_X_TLS_HARD            1
@@ -130,9 +131,17 @@ LDAP_BEGIN_DECL
 #define LDAP_OPT_X_TLS_TRY             4
 
 /* OpenLDAP SASL options */
-#define LDAP_OPT_X_SASL_MINSSF         0x6100
-#define LDAP_OPT_X_SASL_MAXSSF         0x6101
-#define LDAP_OPT_X_SASL_ACTSSF         0x6102
+#define LDAP_OPT_X_SASL_MECH                   0x6100
+#define LDAP_OPT_X_SASL_REALM                  0x6101
+#define LDAP_OPT_X_SASL_AUTHCID                        0x6102
+#define LDAP_OPT_X_SASL_AUTHZID                        0x6103
+#define LDAP_OPT_X_SASL_SSF                            0x6104 /* read-only */
+#define LDAP_OPT_X_SASL_SSF_EXTERNAL   0x6105 /* write-only */
+#define LDAP_OPT_X_SASL_SECPROPS               0x6106 /* write-only */
+#define LDAP_OPT_X_SASL_SSF_MIN                        0x6107
+#define LDAP_OPT_X_SASL_SSF_MAX                        0x6108
+#define        LDAP_OPT_X_SASL_MAXBUFSIZE              0x6109
+
 
 /* on/off values */
 #define LDAP_OPT_ON            ((void *) 1)
@@ -192,7 +201,7 @@ typedef struct ldapcontrol {
 /* LDAP Extended Operations */
 #define LDAP_EXOP_START_TLS "1.3.6.1.4.1.1466.20037"
 
-#define LDAP_EXOP_X_MODIFY_PASSWD "1.3.6.1.4.1.4203.666.6.1"
+#define LDAP_EXOP_X_MODIFY_PASSWD "1.3.6.1.4.1.4203.1.11.1"
 #define LDAP_TAG_EXOP_X_MODIFY_PASSWD_ID       ((ber_tag_t) 0x80U)
 #define LDAP_TAG_EXOP_X_MODIFY_PASSWD_OLD      ((ber_tag_t) 0x81U)
 #define LDAP_TAG_EXOP_X_MODIFY_PASSWD_NEW      ((ber_tag_t) 0x82U)
@@ -244,9 +253,9 @@ typedef struct ldapcontrol {
 #define LDAP_REQ_MODIFY                        ((ber_tag_t) 0x66U)     /* application + constructed */
 #define LDAP_REQ_ADD                   ((ber_tag_t) 0x68U)     /* application + constructed */
 #define LDAP_REQ_DELETE                        ((ber_tag_t) 0x4aU)     /* application + primitive   */
-#define LDAP_REQ_MODRDN                        ((ber_tag_t) 0x6cU)     /* application + constructed */
-#define LDAP_REQ_MODDN                 LDAP_REQ_MODRDN 
-#define LDAP_REQ_RENAME                        LDAP_REQ_MODRDN 
+#define LDAP_REQ_MODDN                 ((ber_tag_t) 0x6cU)     /* application + constructed */
+#define LDAP_REQ_MODRDN                        LDAP_REQ_MODDN  
+#define LDAP_REQ_RENAME                        LDAP_REQ_MODDN  
 #define LDAP_REQ_COMPARE               ((ber_tag_t) 0x6eU)     /* application + constructed */
 #define LDAP_REQ_ABANDON               ((ber_tag_t) 0x50U)     /* application + primitive   */
 #define LDAP_REQ_EXTENDED              ((ber_tag_t) 0x77U)     /* application + constructed */
@@ -259,9 +268,9 @@ typedef struct ldapcontrol {
 #define LDAP_RES_MODIFY                        ((ber_tag_t) 0x67U)     /* application + constructed */
 #define LDAP_RES_ADD                   ((ber_tag_t) 0x69U)     /* application + constructed */
 #define LDAP_RES_DELETE                        ((ber_tag_t) 0x6bU)     /* application + constructed */
-#define LDAP_RES_MODRDN                        ((ber_tag_t) 0x6dU)     /* application + constructed */
-#define LDAP_RES_MODDN                 LDAP_RES_MODRDN /* application + constructed */
-#define LDAP_RES_RENAME                        LDAP_RES_MODRDN /* application + constructed */
+#define LDAP_RES_MODDN                 ((ber_tag_t) 0x6dU)     /* application + constructed */
+#define LDAP_RES_MODRDN                        LDAP_RES_MODDN  /* application + constructed */
+#define LDAP_RES_RENAME                        LDAP_RES_MODDN  /* application + constructed */
 #define LDAP_RES_COMPARE               ((ber_tag_t) 0x6fU)     /* application + constructed */
 #define LDAP_RES_EXTENDED              ((ber_tag_t) 0x78U)     /* V3: application + constructed */
 #define LDAP_RES_EXTENDED_PARTIAL      ((ber_tag_t) 0x79U)     /* V3+: application + constructed */
@@ -271,7 +280,8 @@ typedef struct ldapcontrol {
 
 
 /* sasl methods */
-#define LDAP_SASL_SIMPLE                       NULL
+#define LDAP_SASL_SIMPLE               ((char*)0)
+
 
 /* authentication methods available */
 #define LDAP_AUTH_NONE         ((ber_tag_t) 0x00U)     /* no authentication              */
@@ -559,6 +569,13 @@ ldap_set_rebind_proc LDAP_P((
 /*
  * in controls.c:
  */
+LDAP_F( int ) 
+ldap_create_control LDAP_P(( 
+       const char *requestOID, 
+       BerElement *ber, 
+       int iscritical,
+       LDAPControl **ctrlp ));
+
 LDAP_F( void )
 ldap_control_free LDAP_P((
        LDAPControl *ctrl ));
@@ -686,16 +703,35 @@ ldap_sasl_bind LDAP_P((
        LDAPControl             **clientctrls,
        int                             *msgidp ));
 
+/* Interaction flags (should be passed about in a control)
+ *  Automatic (default): use defaults, prompt otherwise
+ *  Interactive: prompt always
+ *  Quiet: never prompt
+ */
+#define LDAP_SASL_AUTOMATIC            0U
+#define LDAP_SASL_INTERACTIVE  1U
+#define LDAP_SASL_QUIET                        2U
+
+/*
+ * V3 SASL Interaction Function Callback Prototype
+ *     when using Cyrus SASL, interact is pointer to sasl_interact_t
+ *  should likely passed in a control (and provided controls)
+ */
+typedef int (LDAP_SASL_INTERACT_PROC) LDAP_P((
+       LDAP *ld, unsigned flags, void* defaults, void *interact ));
+
 LDAP_F( int )
-ldap_negotiated_sasl_bind_s LDAP_P((
+ldap_sasl_interactive_bind_s LDAP_P((
        LDAP *ld,
        LDAP_CONST char *dn, /* usually NULL */
-       LDAP_CONST char *authenticationId, 
-       LDAP_CONST char *authorizationId, /* usually NULL */
        LDAP_CONST char *saslMechanism,
-       struct berval *passPhrase,
        LDAPControl **serverControls,
-       LDAPControl **clientControls ));
+       LDAPControl **clientControls,
+
+       /* should be client controls */
+       unsigned flags,
+       LDAP_SASL_INTERACT_PROC *proc,
+       void *defaults ));
 
 LDAP_F( int )
 ldap_sasl_bind_s LDAP_P((
index f6eeb6f3792103392a2f69f3692ececb7f2ee754..92e287cdfd5f1b5c8322b2dea1da45007116915e 100644 (file)
@@ -92,6 +92,10 @@ ldap_str2charray LDAP_P((
        const char *str,
        const char *brkstr ));
 
+LDAP_F( char * )
+ldap_charray2str LDAP_P((
+       char **array, const char* sep ));
+
 /* url.c */
 LDAP_F (void) ldap_pvt_hex_unescape LDAP_P(( char *s ));
 LDAP_F (int) ldap_pvt_unhex( int c );
@@ -118,23 +122,23 @@ LDAP_F (int) ldap_pvt_unhex( int c );
 #define LDAP_NEEDSESCAPE(c)    ((c) == '\\' || (c) == '"')
 
 #ifdef HAVE_CYRUS_SASL
-/* sasl.c */
-LDAP_END_DECL
-#include <sasl.h>
-#include <ldap.h> 
-LDAP_BEGIN_DECL
-
-LDAP_F (int) ldap_pvt_sasl_init LDAP_P(( void )); /* clientside init */
-LDAP_F (int) ldap_pvt_sasl_install LDAP_P(( Sockbuf *, void * ));
-LDAP_F (int) ldap_pvt_sasl_bind LDAP_P(( LDAP *, LDAP_CONST char *,
-       LDAP_CONST char *, LDAP_CONST sasl_callback_t *, LDAPControl **,
-       LDAPControl ** ));
-LDAP_F (int) ldap_pvt_sasl_get_option LDAP_P(( LDAP *ld, int option,
-       void *arg ));
-LDAP_F (int) ldap_pvt_sasl_set_option LDAP_P(( LDAP *ld, int option,
-       void *arg ));
+/* cyrus.c */
+struct sasl_security_properties; /* avoid pulling in <sasl.h> */
+LDAP_F (int) ldap_pvt_sasl_secprops LDAP_P((
+       const char *in,
+       struct sasl_security_properties *secprops ));
+
+LDAP_F (void *) ldap_pvt_sasl_mutex_new LDAP_P((void));
+LDAP_F (int) ldap_pvt_sasl_mutex_lock LDAP_P((void *mutex));
+LDAP_F (int) ldap_pvt_sasl_mutex_unlock LDAP_P((void *mutex));
+LDAP_F (void) ldap_pvt_sasl_mutex_dispose LDAP_P((void *mutex));
+
+struct sockbuf; /* avoid pulling in <lber.h> */
+LDAP_F (int) ldap_pvt_sasl_install LDAP_P(( struct sockbuf *, void * ));
 #endif /* HAVE_CYRUS_SASL */
 
+#define LDAP_PVT_SASL_LOCAL_SSF        52      /* SSF for Unix Domain Sockets */
+
 /* search.c */
 LDAP_F( char * )
 ldap_pvt_find_wildcard LDAP_P((        const char *s ));
@@ -154,16 +158,16 @@ struct ldapoptions;
 struct ldap;
 
 LDAP_F (int) ldap_pvt_tls_init LDAP_P(( void ));
-LDAP_F (int) ldap_pvt_tls_config LDAP_P(( struct ldapoptions *lo, int option, const char *arg ));
 LDAP_F (int) ldap_pvt_tls_connect LDAP_P(( struct ldap *ld, Sockbuf *sb, void *ctx_arg ));
 LDAP_F (int) ldap_pvt_tls_accept LDAP_P(( Sockbuf *sb, void *ctx_arg ));
-LDAP_F (int) ldap_pvt_tls_get_option LDAP_P(( struct ldapoptions *lo, int option, void *arg ));
-LDAP_F (int) ldap_pvt_tls_set_option LDAP_P(( struct ldapoptions *lo, int option, void *arg ));
 LDAP_F (void *) ldap_pvt_tls_sb_handle LDAP_P(( Sockbuf *sb ));
 LDAP_F (void *) ldap_pvt_tls_get_handle LDAP_P(( struct ldap *ld ));
 LDAP_F (int) ldap_pvt_tls_inplace LDAP_P(( Sockbuf *sb ));
 LDAP_F (int) ldap_pvt_tls_start LDAP_P(( struct ldap *ld, Sockbuf *sb, void *ctx_arg ));
 
+LDAP_F (int) ldap_pvt_tls_get_option LDAP_P(( struct ldapoptions *lo, int option, void *arg ));
+LDAP_F (int) ldap_pvt_tls_set_option LDAP_P(( struct ldapoptions *lo, int option, void *arg ));
+
 /*  
  * UTF-8 (in utf-8.c)
  */
index e6933d9d229d1837ed295618e0a6c261e2a96ca4..fe7ab543dde5b10186a45f64f3f86d4216420a11 100644 (file)
@@ -36,14 +36,14 @@ LDAP_BEGIN_DECL
 typedef struct ldap_schema_extension_item {
        char *lsei_name;
        char **lsei_values;
-} LDAP_SCHEMA_EXTENSION_ITEM;
+} LDAPSchemaExtensionItem;
 
 typedef struct ldap_syntax {
        char *syn_oid;          /* REQUIRED */
        char **syn_names;       /* OPTIONAL */
        char *syn_desc;         /* OPTIONAL */
-       LDAP_SCHEMA_EXTENSION_ITEM **syn_extensions; /* OPTIONAL */
-} LDAP_SYNTAX;
+       LDAPSchemaExtensionItem **syn_extensions; /* OPTIONAL */
+} LDAPSyntax;
 
 typedef struct ldap_matchingrule {
        char *mr_oid;           /* REQUIRED */
@@ -51,8 +51,8 @@ typedef struct ldap_matchingrule {
        char *mr_desc;          /* OPTIONAL */
        int  mr_obsolete;       /* OPTIONAL */
        char *mr_syntax_oid;    /* REQUIRED */
-       LDAP_SCHEMA_EXTENSION_ITEM **mr_extensions; /* OPTIONAL */
-} LDAP_MATCHING_RULE;
+       LDAPSchemaExtensionItem **mr_extensions; /* OPTIONAL */
+} LDAPMatchingRule;
 
 typedef struct ldap_attributetype {
        char *at_oid;           /* REQUIRED */
@@ -70,8 +70,8 @@ typedef struct ldap_attributetype {
        int  at_no_user_mod;    /* 0=no, 1=yes */
        int  at_usage;          /* 0=userApplications, 1=directoryOperation,
                                   2=distributedOperation, 3=dSAOperation */
-       LDAP_SCHEMA_EXTENSION_ITEM **at_extensions; /* OPTIONAL */
-} LDAP_ATTRIBUTE_TYPE;
+       LDAPSchemaExtensionItem **at_extensions; /* OPTIONAL */
+} LDAPAttributeType;
 
 typedef struct ldap_objectclass {
        char *oc_oid;           /* REQUIRED */
@@ -82,8 +82,8 @@ typedef struct ldap_objectclass {
        int  oc_kind;           /* 0=ABSTRACT, 1=STRUCTURAL, 2=AUXILIARY */
        char **oc_at_oids_must; /* OPTIONAL */
        char **oc_at_oids_may;  /* OPTIONAL */
-       LDAP_SCHEMA_EXTENSION_ITEM **oc_extensions; /* OPTIONAL */
-} LDAP_OBJECT_CLASS;
+       LDAPSchemaExtensionItem **oc_extensions; /* OPTIONAL */
+} LDAPObjectClass;
 
 #define LDAP_SCHEMA_NO                         0
 #define LDAP_SCHEMA_YES                                1
@@ -109,81 +109,81 @@ typedef struct ldap_objectclass {
 
 LDAP_F( LDAP_CONST char * )
 ldap_syntax2name LDAP_P((
-       LDAP_SYNTAX * syn ));
+       LDAPSyntax * syn ));
 
 LDAP_F( LDAP_CONST char * )
 ldap_matchingrule2name LDAP_P((
-       LDAP_MATCHING_RULE * mr ));
+       LDAPMatchingRule * mr ));
 
 LDAP_F( LDAP_CONST char * )
 ldap_attributetype2name LDAP_P((
-       LDAP_ATTRIBUTE_TYPE * at ));
+       LDAPAttributeType * at ));
 
 LDAP_F( LDAP_CONST char * )
 ldap_objectclass2name LDAP_P((
-       LDAP_OBJECT_CLASS * oc ));
+       LDAPObjectClass * oc ));
 
 LDAP_F( void )
 ldap_syntax_free LDAP_P((
-       LDAP_SYNTAX * syn ));
+       LDAPSyntax * syn ));
 
 LDAP_F( void )
 ldap_matchingrule_free LDAP_P((
-       LDAP_MATCHING_RULE * mr ));
+       LDAPMatchingRule * mr ));
 
 LDAP_F( void )
 ldap_attributetype_free LDAP_P((
-       LDAP_ATTRIBUTE_TYPE * at ));
+       LDAPAttributeType * at ));
 
 LDAP_F( void )
 ldap_objectclass_free LDAP_P((
-       LDAP_OBJECT_CLASS * oc ));
+       LDAPObjectClass * oc ));
 
-LDAP_F( LDAP_OBJECT_CLASS * )
+LDAP_F( LDAPObjectClass * )
 ldap_str2objectclass LDAP_P((
        LDAP_CONST char * s,
        int * code,
        LDAP_CONST char ** errp,
        LDAP_CONST int flags ));
 
-LDAP_F( LDAP_ATTRIBUTE_TYPE * )
+LDAP_F( LDAPAttributeType * )
 ldap_str2attributetype LDAP_P((
        LDAP_CONST char * s,
        int * code,
        LDAP_CONST char ** errp,
        LDAP_CONST int flags ));
 
-LDAP_F( LDAP_SYNTAX * )
+LDAP_F( LDAPSyntax * )
 ldap_str2syntax LDAP_P((
        LDAP_CONST char * s,
        int * code,
        LDAP_CONST char ** errp,
        LDAP_CONST int flags ));
 
-LDAP_F( LDAP_MATCHING_RULE * )
+LDAP_F( LDAPMatchingRule * )
 ldap_str2matchingrule LDAP_P((
        LDAP_CONST char * s,
        int * code,
        LDAP_CONST char ** errp,
        LDAP_CONST int flags ));
 
-LDAP_F( char *)
+LDAP_F( char * )
 ldap_objectclass2str LDAP_P((
-       LDAP_CONST LDAP_OBJECT_CLASS * oc ));
+       LDAP_CONST LDAPObjectClass * oc ));
 
-LDAP_F( char *)
+LDAP_F( char * )
 ldap_attributetype2str LDAP_P((
-       LDAP_CONST LDAP_ATTRIBUTE_TYPE * at ));
+       LDAP_CONST LDAPAttributeType * at ));
 
-LDAP_F( char *)
+LDAP_F( char * )
 ldap_syntax2str LDAP_P((
-       LDAP_CONST LDAP_SYNTAX * syn ));
+       LDAP_CONST LDAPSyntax * syn ));
 
-LDAP_F( char *)
+LDAP_F( char * )
 ldap_matchingrule2str LDAP_P((
-       LDAP_CONST LDAP_MATCHING_RULE * mr ));
+       LDAP_CONST LDAPMatchingRule * mr ));
 
-LDAP_F( char *)
+LDAP_F( char * )
 ldap_scherr2str LDAP_P((
        int code )) LDAP_GCCATTR((const));
 
diff --git a/include/lutil_ldap.h b/include/lutil_ldap.h
new file mode 100644 (file)
index 0000000..87e00c7
--- /dev/null
@@ -0,0 +1,39 @@
+/* $OpenLDAP$ */
+/*
+ * Copyright 2000 The OpenLDAP Foundation, Redwood City, California, USA
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted only
+ * as authorized by the OpenLDAP Public License.  A copy of this
+ * license is available at http://www.OpenLDAP.org/license.html or
+ * in file LICENSE in the top-level directory of the distribution.
+ */
+
+#ifndef _LUTIL_LDAP_H
+#define _LUTIL_LDAP_H 1
+
+#include <ldap_cdefs.h>
+#include <lber_types.h>
+
+/*
+ * Include file for lutil LDAP routines
+ */
+
+LDAP_BEGIN_DECL
+
+LDAP_LUTIL_F( void * )
+lutil_sasl_defaults LDAP_P((
+       LDAP *ld,
+       char *mech,
+       char *realm,
+       char *authcid,
+       char *passwd,
+       char *authzid ));
+
+LDAP_LUTIL_F( int )
+lutil_sasl_interact LDAP_P((
+       LDAP *ld, unsigned flags, void *defaults, void *p ));
+
+LDAP_END_DECL
+
+#endif /* _LUTIL_LDAP_H */
index 54b003fa6a96903b92819ffea94a66eca02267ad..7d01ec40fe227562a27f45f87eaf918626e42eae 100644 (file)
 /* define to support CLDAP */
 #undef LDAP_CONNECTIONLESS
 
-/* define to support PF_UNIX */
-#undef LDAP_PF_UNIX
+/* define to support PF_LOCAL */
+#undef LDAP_PF_LOCAL
 
 /* define to support PF_INET6 */
 #undef LDAP_PF_INET6
index 99ff60b90883ae10763d4d3fd6904e36b1a49228..ef12bf46d61b64dc42dc2cee01d3b84c36121dc0 100644 (file)
@@ -136,29 +136,22 @@ ber_skip_tag( BerElement *ber, ber_len_t *len )
 
 ber_tag_t
 ber_peek_tag(
-       BerElement *ber_in,
+       BerElement *ber,
        ber_len_t *len )
 {
-       ber_tag_t       tag;
-       BerElement *ber;
-
-       assert( ber_in != NULL );
-       assert( BER_VALID( ber_in ) );
-
-       *len = 0;
-
-       ber = ber_dup( ber_in );
-
-       if( ber == NULL ) {
-               return LBER_ERROR;
-       }
+       /*
+        * This implementation assumes ber_skip_tag() only
+        * modifies ber_ptr field of the BerElement.
+        */
 
-       assert( BER_VALID( ber ) );
+       char *save;
+       ber_tag_t       tag;
 
+       save = ber->ber_ptr;
        tag = ber_skip_tag( ber, len );
+       ber->ber_ptr = save;
 
-       ber_free( ber, 0 );
-       return( tag );
+       return tag;
 }
 
 static ber_len_t
index 00bcf197af9de4980d60376624191b067cfd7e4b..ff3bf64be3dc422c459157f916bcb8dabb8e84e4 100644 (file)
@@ -533,7 +533,7 @@ ber_put_seqorset( BerElement *ber )
                                 * the length field.  Move the data if
                                 * we don't actually need that much
                                 */
-                               SAFEMEMCPY( (*sos)->sos_first + taglen +
+                               AC_MEMCPY( (*sos)->sos_first + taglen +
                                    lenlen, (*sos)->sos_first + taglen +
                                    FOUR_BYTE_LEN, len );
                        }
@@ -583,7 +583,7 @@ ber_put_seqorset( BerElement *ber )
                        tmptag >>= 8;
                }
 
-               SAFEMEMCPY( (*sos)->sos_first,
+               AC_FMEMCPY( (*sos)->sos_first,
                        &nettag[sizeof(ber_tag_t) - taglen],
                        taglen );
 
@@ -594,12 +594,12 @@ ber_put_seqorset( BerElement *ber )
                }
 
                /* one byte of length length */
-               SAFEMEMCPY( (*sos)->sos_first + 1, &ltag, 1 );
+               (*sos)->sos_first[1] = ltag;
 
                if ( ber->ber_options & LBER_USE_DER ) {
                        if (lenlen > 1) {
                                /* Write the length itself */
-                               SAFEMEMCPY( (*sos)->sos_first + 2,
+                               AC_FMEMCPY( (*sos)->sos_first + 2,
                                    &netlen[sizeof(ber_len_t) - (lenlen - 1)],
                                        lenlen - 1 );
                        }
@@ -609,13 +609,13 @@ ber_put_seqorset( BerElement *ber )
                                 * the length field.  Move the data if
                                 * we don't actually need that much
                                 */
-                               SAFEMEMCPY( (*sos)->sos_first + taglen +
+                               AC_FMEMCPY( (*sos)->sos_first + taglen +
                                    lenlen, (*sos)->sos_first + taglen +
                                    FOUR_BYTE_LEN, len );
                        }
                } else {
                        /* the length itself */
-                       SAFEMEMCPY( (*sos)->sos_first + taglen + 1,
+                       AC_FMEMCPY( (*sos)->sos_first + taglen + 1,
                            &netlen[sizeof(ber_len_t) - (FOUR_BYTE_LEN - 1)],
                                FOUR_BYTE_LEN - 1 );
                }
index 27220e42675535c913ead6a0c7d23f4bee630745..6de4335ca2c99aa1978c7a29bdef7324acdd554e 100644 (file)
 
 #include "lber-int.h"
 
-static ber_slen_t BerRead LDAP_P((
-       Sockbuf *sb,
-       char *buf,
-       ber_len_t len ));
-
 #define EXBUFSIZ       1024
 
 /* probably far too large... */
@@ -52,7 +47,7 @@ static ber_slen_t BerRead LDAP_P((
 static ber_slen_t
 BerRead(
        Sockbuf *sb,
-       char *buf,
+       unsigned char *buf,
        ber_len_t len )
 {
        ber_slen_t      c;
@@ -69,7 +64,7 @@ BerRead(
                                break;
                        return( c );
                }
-               buf+= c;
+               buf+=c;
                nread+=c;
                len-=c;
        }
@@ -93,7 +88,7 @@ ber_read(
        nleft = ber->ber_end - ber->ber_ptr;
        actuallen = nleft < len ? nleft : len;
 
-       SAFEMEMCPY( buf, ber->ber_ptr, actuallen );
+       AC_MEMCPY( buf, ber->ber_ptr, actuallen );
 
        ber->ber_ptr += actuallen;
 
@@ -117,7 +112,7 @@ ber_write(
                        if ( ber_realloc( ber, len ) != 0 )
                                return( -1 );
                }
-               SAFEMEMCPY( ber->ber_ptr, buf, (size_t)len );
+               AC_MEMCPY( ber->ber_ptr, buf, (size_t)len );
                ber->ber_ptr += len;
                return( (ber_slen_t) len );
 
@@ -126,7 +121,7 @@ ber_write(
                        if ( ber_realloc( ber, len ) != 0 )
                                return( -1 );
                }
-               SAFEMEMCPY( ber->ber_sos->sos_ptr, buf, (size_t)len );
+               AC_MEMCPY( ber->ber_sos->sos_ptr, buf, (size_t)len );
                ber->ber_sos->sos_ptr += len;
                ber->ber_sos->sos_clen += len;
                return( (ber_slen_t) len );
@@ -397,7 +392,7 @@ int ber_flatten(
                        return( -1 );
                }
 
-               SAFEMEMCPY( bv->bv_val, ber->ber_buf, len );
+               AC_MEMCPY( bv->bv_val, ber->ber_buf, len );
                bv->bv_val[len] = '\0';
                bv->bv_len = len;
        }
index 6ee5e7389ef22b3c354c189cabf2878c26e9166d..7234e33db2ed8aa742dd5d266baf6fcd4975d5cc 100644 (file)
@@ -71,8 +71,8 @@ struct sockbuf {
 #define        sb_options              sb_opts.lbo_options
 #define        sb_debug                sb_opts.lbo_debug
        ber_socket_t            sb_fd;
-       int             sb_trans_needs_read:1;
-       int             sb_trans_needs_write:1;
+       unsigned int            sb_trans_needs_read:1;
+       unsigned int            sb_trans_needs_write:1;
 };
 
 #define SOCKBUF_VALID( sb )    ( (sb)->sb_valid == LBER_VALID_SOCKBUF )
index a500569cdc59feac0eb18055211849f4c7c5e937..861dd3a23a127990c2806fb6fdf63ebf1e8e49e3 100644 (file)
@@ -473,7 +473,7 @@ ber_bvdup(
                return NULL;
        }
 
-       SAFEMEMCPY( new->bv_val, bv->bv_val, bv->bv_len );
+       AC_MEMCPY( new->bv_val, bv->bv_val, bv->bv_len );
        new->bv_val[bv->bv_len] = '\0';
        new->bv_len = bv->bv_len;
 
@@ -564,6 +564,6 @@ ber_strdup( LDAP_CONST char *s )
                return( NULL );
        }
 
-       SAFEMEMCPY( p, s, len );
+       AC_MEMCPY( p, s, len );
        return( p );
 }
index 0b6ded358fdd881a6e8b5d36e4b77a574bd4b158..3689f0df582c61c87e1a298a8d04ea32aa65f686 100644 (file)
@@ -124,7 +124,7 @@ ber_set_option(
                        return LBER_OPT_ERROR;
                }
 
-               memcpy(ber_int_memory_fns, f, sizeof(BerMemoryFunctions));
+               AC_MEMCPY(ber_int_memory_fns, f, sizeof(BerMemoryFunctions));
 
                ber_int_options.lbo_valid = LBER_INITIALIZED;
                return LBER_OPT_SUCCESS;
index 5c133e65400f77714c6090ec5befed23dff301b9..06fd8bd937004879697da481ffa85759ad3bbe7e 100644 (file)
@@ -232,12 +232,14 @@ ber_pvt_sb_copy_out( Sockbuf_Buf *sbb, char *buf, ber_len_t len )
 
        assert( buf != NULL );
        assert( sbb != NULL );
+#if 0
        assert( sbb->buf_size > 0 );
+#endif
 
        max = sbb->buf_end - sbb->buf_ptr;
        max = ( max < len) ? max : len;
        if ( max ) {
-               memcpy( buf, sbb->buf_base + sbb->buf_ptr, max );
+               AC_MEMCPY( buf, sbb->buf_base + sbb->buf_ptr, max );
                sbb->buf_ptr += max;
                if ( sbb->buf_ptr >= sbb->buf_end )
                        sbb->buf_ptr = sbb->buf_end = 0;
@@ -656,7 +658,7 @@ sb_dgram_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg )
        p = (struct dgram_data *)sbiod->sbiod_pvt;
 
        if ( opt == LBER_SB_OPT_UDP_SET_DST ) {
-               memcpy( &p->dst, arg, sizeof( struct sockaddr ) );
+               AC_MEMCPY( &p->dst, arg, sizeof( struct sockaddr ) );
                return 1;
        }
        else if ( opt == LBER_SB_OPT_UDP_GET_SRC ) {
index fc02e1d780aa59bcbcd85d3905bc8fdd8bfa666e..b89e4dee2c387f8ae10670ef44429c294a73cc21 100644 (file)
@@ -10,7 +10,7 @@ XLIBRARY = ../libldap.a
 PROGRAMS = apitest ltest ttest
 
 SRCS   = bind.c open.c result.c error.c compare.c search.c \
-       controls.c messages.c references.c extended.c \
+       controls.c messages.c references.c extended.c cyrus.c \
        modify.c add.c modrdn.c delete.c abandon.c ufn.c cache.c \
        getfilter.c sasl.c sbind.c kbind.c unbind.c friendly.c cldap.c \
        free.c disptmpl.c srchpref.c dsparse.c tmplout.c sort.c \
@@ -20,7 +20,7 @@ SRCS  = bind.c open.c result.c error.c compare.c search.c \
        charray.c tls.c dn.c os-local.c dnssrv.c \
        utf-8.c
 OBJS   = bind.lo open.lo result.lo error.lo compare.lo search.lo \
-       controls.lo messages.lo references.lo extended.lo \
+       controls.lo messages.lo references.lo extended.lo cyrus.lo \
        modify.lo add.lo modrdn.lo delete.lo abandon.lo ufn.lo cache.lo \
        getfilter.lo sasl.lo sbind.lo kbind.lo unbind.lo friendly.lo cldap.lo \
        free.lo disptmpl.lo srchpref.lo dsparse.lo tmplout.lo sort.lo \
index 93e0e3108389ce400bafe7efcfb8c457ba4e12a1..82212582c1b02e6ebbc04aff244ca57f350ed93f 100644 (file)
@@ -240,7 +240,7 @@ ldap_add_request_to_cache( LDAP *ld, ber_tag_t msgtype, BerElement *request )
                        ld->ld_errno = LDAP_NO_MEMORY;
                        return;
                }
-               SAFEMEMCPY( new->lm_ber->ber_buf, request->ber_buf,
+               AC_MEMCPY( new->lm_ber->ber_buf, request->ber_buf,
                    (size_t)len );
                new->lm_ber->ber_ptr = new->lm_ber->ber_buf;
                new->lm_ber->ber_end = new->lm_ber->ber_buf + len;
@@ -498,7 +498,7 @@ msg_dup( LDAPMessage *msg )
                        LDAP_FREE( (char *)new );
                        return( NULL );
                }
-               SAFEMEMCPY( new->lm_ber->ber_buf, msg->lm_ber->ber_buf,
+               AC_MEMCPY( new->lm_ber->ber_buf, msg->lm_ber->ber_buf,
                    (size_t)len );
                new->lm_ber->ber_ptr = new->lm_ber->ber_buf +
                        ( msg->lm_ber->ber_ptr - msg->lm_ber->ber_buf );
index 744ab07b7397c8966f213297ee1781e0ae220173..82d2feeb1ba264e09413991ad54c337addb7d220 100644 (file)
@@ -217,3 +217,48 @@ ldap_str2charray( const char *str_in, const char *brkstr )
        LDAP_FREE( str );
        return( res );
 }
+
+char * ldap_charray2str( char **a, const char *sep )
+{
+       char *s, **v, *p;
+       int len = 0;
+       int slen;
+
+       if( sep == NULL ) sep = " ";
+
+       slen = strlen( sep );
+
+       for ( v = a; *v != NULL; v++ ) {
+               len += strlen( *v ) + slen; /* for a space */
+       }
+
+       if ( len == 0 ) {
+               return NULL;
+       }
+
+       len -= slen;
+       len += 1; /* EOS */
+
+       s = LDAP_MALLOC ( len );
+
+       if ( s == NULL ) {
+               return NULL;    
+       }
+
+       p = s;
+       for ( v = a; *v != NULL; v++ ) {
+               int len;
+
+               if ( v != a ) {
+                       strncpy( p, sep, slen );
+                       p += slen;
+               }
+
+               len = strlen( *v );
+               strncpy( p, *v, len );
+               p += len;
+       }
+
+       *p = '\0';
+       return s;
+}
index 50839df1fa848831157e0b505c201c0eefe4db57..1ec30c88e468866bdb01415d3da6583773b2436e 100644 (file)
@@ -139,7 +139,7 @@ cldap_open( LDAP_CONST char *host, int port )
                }
 
                for ( i = 0; hp->h_addr_list[ i ] != 0; ++i ) {
-                   SAFEMEMCPY( (char *)&sock.sin_addr,
+                   AC_MEMCPY( (char *)&sock.sin_addr,
                            (char *)hp->h_addr_list[ i ],
                            sizeof(sock.sin_addr));
                    if ( add_addr( ld, (struct sockaddr *)&sock ) < 0 ) {
@@ -287,7 +287,7 @@ add_addr( LDAP *ld, struct sockaddr *sap )
        return( -1 );
     }
 
-    SAFEMEMCPY( (char *)newsap, (char *)sap, sizeof( struct sockaddr ));
+    AC_MEMCPY( (char *)newsap, (char *)sap, sizeof( struct sockaddr ));
     addrs[ ld->ld_cldapnaddr++ ] = newsap;
     ld->ld_cldapaddrs = (void **)addrs;
     return( 0 );
index 72857fb3bbafb404fa1ed2e7318650abf25c7f9d..6a814b80fe053a3082e29928689ef832f8a55f79 100644 (file)
@@ -348,7 +348,7 @@ ldap_control_dup( const LDAPControl *c )
                        return NULL;
                }
                
-               SAFEMEMCPY( new->ldctl_value.bv_val, c->ldctl_value.bv_val, 
+               AC_MEMCPY( new->ldctl_value.bv_val, c->ldctl_value.bv_val, 
                        c->ldctl_value.bv_len );
 
                new->ldctl_value.bv_len = c->ldctl_value.bv_len;
@@ -386,7 +386,7 @@ ldap_control_dup( const LDAPControl *c )
  * June 2000 sfs  Added control utilities
  */
 /*---
-   ldap_int_create_control
+   ldap_create_control
    
    Internal function to create an LDAP control from the encoded BerElement.
 
@@ -402,8 +402,8 @@ ldap_control_dup( const LDAPControl *c )
 ---*/
 
 int
-ldap_int_create_control(
-       const char *requestOID,
+ldap_create_control(
+       LDAP_CONST char *requestOID,
        BerElement *ber,
        int iscritical,
        LDAPControl **ctrlp )
@@ -415,24 +415,24 @@ ldap_int_create_control(
                return LDAP_PARAM_ERROR;
        }
 
-       if ( ber_flatten( ber, &bvalp ) == LBER_ERROR ) {
+       ctrl = (LDAPControl *) LDAP_MALLOC( sizeof(LDAPControl) );
+       if ( ctrl == NULL ) {
                return LDAP_NO_MEMORY;
        }
 
-       ctrl = (LDAPControl *) LBER_MALLOC( sizeof(LDAPControl) );
-       if ( ctrl == NULL ) {
-               ber_bvfree( bvalp );
+       if ( ber_flatten( ber, &bvalp ) == LBER_ERROR ) {
+               LDAP_FREE( ctrl );
                return LDAP_NO_MEMORY;
        }
 
        ctrl->ldctl_value = *bvalp;
-       LDAP_FREE( bvalp );
+       ber_memfree( bvalp );
 
        ctrl->ldctl_oid = LDAP_STRDUP( requestOID );
        ctrl->ldctl_iscritical = iscritical;
 
-       if ( ctrl->ldctl_oid == NULL ) {
-               LBER_FREE( ctrl );
+       if ( requestOID != NULL && ctrl->ldctl_oid == NULL ) {
+               ldap_control_free( ctrl );
                return LDAP_NO_MEMORY;
        }
 
diff --git a/libraries/libldap/cyrus.c b/libraries/libldap/cyrus.c
new file mode 100644 (file)
index 0000000..0320f7b
--- /dev/null
@@ -0,0 +1,943 @@
+/* $OpenLDAP$ */
+/*
+ * Copyright 1999-2000 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+
+#include "portable.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <ac/socket.h>
+#include <ac/string.h>
+#include <ac/time.h>
+#include <ac/errno.h>
+
+#include "ldap-int.h"
+#ifdef LDAP_R_COMPILE
+#include "ldap_pvt_thread.h"
+#endif
+
+#ifdef HAVE_CYRUS_SASL
+#include <sasl.h>
+
+/*
+* Various Cyrus SASL related stuff.
+*/
+
+#define SASL_MAX_BUFF_SIZE     65536
+#define SASL_MIN_BUFF_SIZE     4096
+
+int ldap_int_sasl_init( void )
+{
+       /* XXX not threadsafe */
+       static int sasl_initialized = 0;
+
+       static sasl_callback_t client_callbacks[] = {
+#ifdef SASL_CB_GETREALM
+               { SASL_CB_GETREALM, NULL, NULL },
+#endif
+               { SASL_CB_USER, NULL, NULL },
+               { SASL_CB_AUTHNAME, NULL, NULL },
+               { SASL_CB_PASS, NULL, NULL },
+               { SASL_CB_ECHOPROMPT, NULL, NULL },
+               { SASL_CB_NOECHOPROMPT, NULL, NULL },
+               { SASL_CB_LIST_END, NULL, NULL }
+       };
+
+       if ( sasl_initialized ) {
+               return 0;
+       }
+
+#ifndef CSRIMALLOC
+       sasl_set_alloc(
+               ber_memalloc,
+               ber_memcalloc,
+               ber_memrealloc,
+               ber_memfree );
+#endif /* CSRIMALLOC */
+
+#ifdef LDAP_R_COMPILE
+       sasl_set_mutex(
+               ldap_pvt_sasl_mutex_new,
+               ldap_pvt_sasl_mutex_lock,
+               ldap_pvt_sasl_mutex_unlock,    
+               ldap_pvt_sasl_mutex_dispose );    
+#endif
+
+       if ( sasl_client_init( client_callbacks ) == SASL_OK ) {
+               sasl_initialized = 1;
+               return 0;
+       }
+
+       return -1;
+}
+
+/*
+ * SASL encryption support for LBER Sockbufs
+ */
+
+struct sb_sasl_data {
+       sasl_conn_t             *sasl_context;
+       Sockbuf_Buf             sec_buf_in;
+       Sockbuf_Buf             buf_in;
+       Sockbuf_Buf             buf_out;
+};
+
+static int
+sb_sasl_setup( Sockbuf_IO_Desc *sbiod, void *arg )
+{
+       struct sb_sasl_data     *p;
+
+       assert( sbiod != NULL );
+
+       p = LBER_MALLOC( sizeof( *p ) );
+       if ( p == NULL )
+               return -1;
+       p->sasl_context = (sasl_conn_t *)arg;
+       ber_pvt_sb_buf_init( &p->sec_buf_in );
+       ber_pvt_sb_buf_init( &p->buf_in );
+       ber_pvt_sb_buf_init( &p->buf_out );
+       if ( ber_pvt_sb_grow_buffer( &p->sec_buf_in, SASL_MIN_BUFF_SIZE ) < 0 ) {
+               errno = ENOMEM;
+               return -1;
+       }
+
+       sbiod->sbiod_pvt = p;
+
+       return 0;
+}
+
+static int
+sb_sasl_remove( Sockbuf_IO_Desc *sbiod )
+{
+       struct sb_sasl_data     *p;
+
+       assert( sbiod != NULL );
+       
+       p = (struct sb_sasl_data *)sbiod->sbiod_pvt;
+       ber_pvt_sb_buf_destroy( &p->sec_buf_in );
+       ber_pvt_sb_buf_destroy( &p->buf_in );
+       ber_pvt_sb_buf_destroy( &p->buf_out );
+       LBER_FREE( p );
+       sbiod->sbiod_pvt = NULL;
+       return 0;
+}
+
+static ber_len_t
+sb_sasl_pkt_length( const char *buf, int debuglevel )
+{
+       ber_len_t               size;
+       long                    tmp;
+
+       assert( buf != NULL );
+
+       tmp = *((long *)buf);
+       size = ntohl( tmp );
+   
+       if ( size > SASL_MAX_BUFF_SIZE ) {
+               /* somebody is trying to mess me up. */
+               ber_log_printf( LDAP_DEBUG_ANY, debuglevel,
+                       "sb_sasl_pkt_length: received illegal packet length "
+                       "of %lu bytes\n", (unsigned long)size );      
+               size = 16; /* this should lead to an error. */
+}
+
+       return size + 4; /* include the size !!! */
+}
+
+/* Drop a processed packet from the input buffer */
+static void
+sb_sasl_drop_packet ( Sockbuf_Buf *sec_buf_in, int debuglevel )
+{
+       ber_slen_t                      len;
+
+       len = sec_buf_in->buf_ptr - sec_buf_in->buf_end;
+       if ( len > 0 )
+               memmove( sec_buf_in->buf_base, sec_buf_in->buf_base +
+                       sec_buf_in->buf_end, len );
+   
+       if ( len >= 4 ) {
+               sec_buf_in->buf_end = sb_sasl_pkt_length( sec_buf_in->buf_base,
+                       debuglevel);
+       }
+       else {
+               sec_buf_in->buf_end = 0;
+       }
+       sec_buf_in->buf_ptr = len;
+}
+
+static ber_slen_t
+sb_sasl_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len)
+{
+       struct sb_sasl_data     *p;
+       ber_slen_t              ret, bufptr;
+   
+       assert( sbiod != NULL );
+       assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
+
+       p = (struct sb_sasl_data *)sbiod->sbiod_pvt;
+
+       /* Are there anything left in the buffer? */
+       ret = ber_pvt_sb_copy_out( &p->buf_in, buf, len );
+       bufptr = ret;
+       len -= ret;
+
+       if ( len == 0 )
+               return bufptr;
+
+       ber_pvt_sb_buf_destroy( &p->buf_in );
+
+       /* Read the length of the packet */
+       while ( p->sec_buf_in.buf_ptr < 4 ) {
+               ret = LBER_SBIOD_READ_NEXT( sbiod, p->sec_buf_in.buf_base,
+                       4 - p->sec_buf_in.buf_ptr );
+#ifdef EINTR
+               if ( ( ret < 0 ) && ( errno == EINTR ) )
+                       continue;
+#endif
+               if ( ret <= 0 )
+                       return ret;
+
+               p->sec_buf_in.buf_ptr += ret;
+       }
+
+       /* The new packet always starts at p->sec_buf_in.buf_base */
+       ret = sb_sasl_pkt_length( p->sec_buf_in.buf_base,
+               sbiod->sbiod_sb->sb_debug );
+
+       /* Grow the packet buffer if neccessary */
+       if ( ( p->sec_buf_in.buf_size < ret ) && 
+                       ber_pvt_sb_grow_buffer( &p->sec_buf_in, ret ) < 0 ) {
+               errno = ENOMEM;
+               return -1;
+       }
+       p->sec_buf_in.buf_end = ret;
+
+       /* Did we read the whole encrypted packet? */
+       while ( p->sec_buf_in.buf_ptr < p->sec_buf_in.buf_end ) {
+               /* No, we have got only a part of it */
+               ret = p->sec_buf_in.buf_end - p->sec_buf_in.buf_ptr;
+
+               ret = LBER_SBIOD_READ_NEXT( sbiod, p->sec_buf_in.buf_base +
+                       p->sec_buf_in.buf_ptr, ret );
+#ifdef EINTR
+               if ( ( ret < 0 ) && ( errno == EINTR ) )
+                       continue;
+#endif
+               if ( ret <= 0 )
+                       return ret;
+
+               p->sec_buf_in.buf_ptr += ret;
+       }
+
+       /* Decode the packet */
+       ret = sasl_decode( p->sasl_context, p->sec_buf_in.buf_base,
+               p->sec_buf_in.buf_end, &p->buf_in.buf_base,
+               (unsigned *)&p->buf_in.buf_end );
+       if ( ret != SASL_OK ) {
+               ber_log_printf( LDAP_DEBUG_ANY, sbiod->sbiod_sb->sb_debug,
+                       "sb_sasl_read: failed to decode packet: %s\n",
+                       sasl_errstring( ret, NULL, NULL ) );
+               sb_sasl_drop_packet( &p->sec_buf_in,
+                       sbiod->sbiod_sb->sb_debug );
+               errno = EIO;
+               return -1;
+       }
+       
+       /* Drop the packet from the input buffer */
+       sb_sasl_drop_packet( &p->sec_buf_in, sbiod->sbiod_sb->sb_debug );
+
+       p->buf_in.buf_size = p->buf_in.buf_end;
+
+       bufptr += ber_pvt_sb_copy_out( &p->buf_in, (char*) buf + bufptr, len );
+
+       return bufptr;
+}
+
+static ber_slen_t
+sb_sasl_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len)
+{
+       struct sb_sasl_data     *p;
+       int                     ret;
+
+       assert( sbiod != NULL );
+       assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
+
+       p = (struct sb_sasl_data *)sbiod->sbiod_pvt;
+
+       /* Are there anything left in the buffer? */
+       if ( p->buf_out.buf_ptr != p->buf_out.buf_end ) {
+               ret = ber_pvt_sb_do_write( sbiod, &p->buf_out );
+               if ( ret <= 0 )
+                       return ret;
+       }
+
+       /* now encode the next packet. */
+       ber_pvt_sb_buf_destroy( &p->buf_out );
+       ret = sasl_encode( p->sasl_context, buf, len, &p->buf_out.buf_base,
+               (unsigned *)&p->buf_out.buf_size );
+       if ( ret != SASL_OK ) {
+               ber_log_printf( LDAP_DEBUG_ANY, sbiod->sbiod_sb->sb_debug,
+                       "sb_sasl_write: failed to encode packet: %s\n",
+                       sasl_errstring( ret, NULL, NULL ) );
+               return -1;
+       }
+       p->buf_out.buf_end = p->buf_out.buf_size;
+
+       ret = ber_pvt_sb_do_write( sbiod, &p->buf_out );
+       if ( ret <= 0 )
+               return ret;
+       return len;
+}
+
+static int
+sb_sasl_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg )
+{
+       struct sb_sasl_data     *p;
+
+       p = (struct sb_sasl_data *)sbiod->sbiod_pvt;
+
+       if ( opt == LBER_SB_OPT_DATA_READY ) {
+               if ( p->buf_in.buf_ptr != p->buf_in.buf_end )
+                       return 1;
+       }
+       
+       return LBER_SBIOD_CTRL_NEXT( sbiod, opt, arg );
+}
+
+Sockbuf_IO ldap_pvt_sockbuf_io_sasl = {
+       sb_sasl_setup,          /* sbi_setup */
+       sb_sasl_remove,         /* sbi_remove */
+       sb_sasl_ctrl,           /* sbi_ctrl */
+       sb_sasl_read,           /* sbi_read */
+       sb_sasl_write,          /* sbi_write */
+       NULL                    /* sbi_close */
+};
+
+int ldap_pvt_sasl_install( Sockbuf *sb, void *ctx_arg )
+{
+       Debug( LDAP_DEBUG_TRACE, "ldap_pvt_sasl_install\n",
+               0, 0, 0 );
+
+       /* don't install the stuff unless security has been negotiated */
+
+       if ( !ber_sockbuf_ctrl( sb, LBER_SB_OPT_HAS_IO,
+                       &ldap_pvt_sockbuf_io_sasl ) )
+               ber_sockbuf_add_io( sb, &ldap_pvt_sockbuf_io_sasl,
+                       LBER_SBIOD_LEVEL_APPLICATION, ctx_arg );
+
+       return LDAP_SUCCESS;
+}
+
+static int
+sasl_err2ldap( int saslerr )
+{
+       int rc;
+
+       switch (saslerr) {
+               case SASL_CONTINUE:
+                       rc = LDAP_MORE_RESULTS_TO_RETURN;
+                       break;
+               case SASL_INTERACT:
+                       rc = LDAP_LOCAL_ERROR;
+                       break;
+               case SASL_OK:
+                       rc = LDAP_SUCCESS;
+                       break;
+               case SASL_FAIL:
+                       rc = LDAP_LOCAL_ERROR;
+                       break;
+               case SASL_NOMEM:
+                       rc = LDAP_NO_MEMORY;
+                       break;
+               case SASL_NOMECH:
+                       rc = LDAP_AUTH_UNKNOWN;
+                       break;
+               case SASL_BADAUTH:
+                       rc = LDAP_AUTH_UNKNOWN;
+                       break;
+               case SASL_NOAUTHZ:
+                       rc = LDAP_PARAM_ERROR;
+                       break;
+               case SASL_TOOWEAK:
+               case SASL_ENCRYPT:
+                       rc = LDAP_AUTH_UNKNOWN;
+                       break;
+               default:
+                       rc = LDAP_LOCAL_ERROR;
+                       break;
+       }
+
+       assert( rc == LDAP_SUCCESS || LDAP_API_ERROR( rc ) );
+       return rc;
+}
+
+int
+ldap_int_sasl_open(
+       LDAP *ld, 
+       LDAPConn *lc,
+       const char * host,
+       ber_len_t ssf )
+{
+       int rc;
+       sasl_conn_t *ctx;
+
+       sasl_callback_t *session_callbacks =
+               ber_memcalloc( 2, sizeof( sasl_callback_t ) );
+
+       if( session_callbacks == NULL ) return LDAP_NO_MEMORY;
+
+       session_callbacks[0].id = SASL_CB_USER;
+       session_callbacks[0].proc = NULL;
+       session_callbacks[0].context = ld;
+
+       session_callbacks[1].id = SASL_CB_LIST_END;
+       session_callbacks[1].proc = NULL;
+       session_callbacks[1].context = NULL;
+
+       assert( lc->lconn_sasl_ctx == NULL );
+
+       if ( host == NULL ) {
+               ld->ld_errno = LDAP_UNAVAILABLE;
+               return ld->ld_errno;
+       }
+
+       rc = sasl_client_new( "ldap", host, session_callbacks,
+               SASL_SECURITY_LAYER, &ctx );
+
+       if ( rc != SASL_OK ) {
+               ld->ld_errno = sasl_err2ldap( rc );
+               return ld->ld_errno;
+       }
+
+       Debug( LDAP_DEBUG_TRACE, "ldap_int_sasl_open: %s\n",
+               host, 0, 0 );
+
+       lc->lconn_sasl_ctx = ctx;
+
+       if( ssf ) {
+               sasl_external_properties_t extprops;
+               memset(&extprops, 0L, sizeof(extprops));
+               extprops.ssf = ssf;
+
+               (void) sasl_setprop( ctx, SASL_SSF_EXTERNAL,
+                       (void *) &extprops );
+
+               Debug( LDAP_DEBUG_TRACE, "ldap_int_sasl_open: ssf=%ld\n",
+                       (long) ssf, 0, 0 );
+       }
+
+       return LDAP_SUCCESS;
+}
+
+int ldap_int_sasl_close( LDAP *ld, LDAPConn *lc )
+{
+       sasl_conn_t *ctx = lc->lconn_sasl_ctx;
+       assert( ctx != NULL );
+
+       if( ctx ) {
+               sasl_dispose( &ctx );
+               lc->lconn_sasl_ctx = NULL;
+       }
+
+       return LDAP_SUCCESS;
+}
+
+int
+ldap_int_sasl_bind(
+       LDAP                    *ld,
+       const char              *dn,
+       const char              *mechs,
+       LDAPControl             **sctrls,
+       LDAPControl             **cctrls,
+       unsigned                flags,
+       LDAP_SASL_INTERACT_PROC *interact,
+       void * defaults )
+{
+       char *data;
+       const char *mech = NULL;
+       const char *pmech = NULL;
+       int                     saslrc, rc;
+       sasl_ssf_t              *ssf = NULL;
+       sasl_conn_t     *ctx;
+       sasl_interact_t *prompts = NULL;
+       unsigned credlen;
+       struct berval ccred;
+       ber_socket_t            sd;
+
+       Debug( LDAP_DEBUG_TRACE, "ldap_int_sasl_bind: %s\n",
+               mechs ? mechs : "<null>", 0, 0 );
+
+       /* do a quick !LDAPv3 check... ldap_sasl_bind will do the rest. */
+       if (ld->ld_version < LDAP_VERSION3) {
+               ld->ld_errno = LDAP_NOT_SUPPORTED;
+               return ld->ld_errno;
+       }
+
+       ber_sockbuf_ctrl( ld->ld_sb, LBER_SB_OPT_GET_FD, &sd );
+
+       if ( sd == AC_SOCKET_INVALID ) {
+               /* not connected yet */
+               int rc = ldap_open_defconn( ld );
+  
+               if( rc < 0 ) return ld->ld_errno;
+               ber_sockbuf_ctrl( ld->ld_sb, LBER_SB_OPT_GET_FD, &sd );
+
+               if( sd == AC_SOCKET_INVALID ) {
+                       ld->ld_errno = LDAP_UNAVAILABLE;
+                       return ld->ld_errno;
+               }
+       }   
+
+       ctx = ld->ld_defconn->lconn_sasl_ctx;
+
+       if( ctx == NULL ) {
+               ld->ld_errno = LDAP_UNAVAILABLE;
+               return ld->ld_errno;
+       }
+
+       /* (re)set security properties */
+       sasl_setprop( ctx, SASL_SEC_PROPS,
+               &ld->ld_options.ldo_sasl_secprops );
+
+       ccred.bv_val = NULL;
+       ccred.bv_len = 0;
+
+       do {
+               saslrc = sasl_client_start( ctx,
+                       mechs,
+                       NULL,
+                       &prompts,
+                       &ccred.bv_val,
+                       &credlen,
+                       &mech );
+
+               if( pmech == NULL && mech != NULL ) {
+                       pmech = mech;
+
+                       if( flags != LDAP_SASL_QUIET ) {
+                               fprintf(stderr,
+                                       "SASL/%s authentication started\n",
+                                       pmech );
+                       }
+               }
+
+               if( saslrc == SASL_INTERACT ) {
+                       int res;
+                       if( !interact ) break;
+                       res = (interact)( ld, flags, defaults, prompts );
+                       if( res != LDAP_SUCCESS ) {
+                               break;
+                       }
+               }
+       } while ( saslrc == SASL_INTERACT );
+
+       ccred.bv_len = credlen;
+
+       if ( (saslrc != SASL_OK) && (saslrc != SASL_CONTINUE) ) {
+               ld->ld_errno = sasl_err2ldap( saslrc );
+               return ld->ld_errno;
+       }
+
+       do {
+               struct berval *scred;
+               unsigned credlen;
+
+               scred = NULL;
+
+               rc = ldap_sasl_bind_s( ld, dn, mech, &ccred, sctrls, cctrls, &scred );
+
+               if ( ccred.bv_val != NULL ) {
+                       LDAP_FREE( ccred.bv_val );
+                       ccred.bv_val = NULL;
+               }
+
+               if ( rc != LDAP_SUCCESS && rc != LDAP_SASL_BIND_IN_PROGRESS ) {
+                       return ld->ld_errno;
+               }
+
+               if( rc == LDAP_SUCCESS && saslrc == SASL_OK ) {
+                       /* we're done, no need to step */
+                       if( scred ) {
+                               /* but server provided us with data! */
+                               Debug( LDAP_DEBUG_TRACE,
+                                       "ldap_int_sasl_bind: rc=%d sasl=%d len=%ld\n",
+                                       rc, saslrc, scred->bv_len );
+                               ber_bvfree( scred );
+                               return ld->ld_errno = LDAP_LOCAL_ERROR;
+                       }
+                       break;
+               }
+
+               do {
+                       saslrc = sasl_client_step( ctx,
+                               (scred == NULL) ? NULL : scred->bv_val,
+                               (scred == NULL) ? 0 : scred->bv_len,
+                               &prompts,
+                               &ccred.bv_val,
+                               &credlen );
+
+                       Debug( LDAP_DEBUG_TRACE, "sasl_client_start: %d\n",
+                               saslrc, 0, 0 );
+
+                       if( saslrc == SASL_INTERACT ) {
+                               int res;
+                               if( !interact ) break;
+                               res = (interact)( ld, flags, defaults, prompts );
+                               if( res != LDAP_SUCCESS ) {
+                                       break;
+                               }
+                       }
+               } while ( saslrc == SASL_INTERACT );
+
+               ccred.bv_len = credlen;
+               ber_bvfree( scred );
+
+               if ( (saslrc != SASL_OK) && (saslrc != SASL_CONTINUE) ) {
+                       ld->ld_errno = sasl_err2ldap( saslrc );
+                       return ld->ld_errno;
+               }
+       } while ( rc == LDAP_SASL_BIND_IN_PROGRESS );
+
+       if ( rc != LDAP_SUCCESS ) {
+               return rc;
+       }
+
+       if ( saslrc != SASL_OK ) {
+               return ld->ld_errno = sasl_err2ldap( saslrc );
+       }
+
+       /* likely should add a quiet option */
+
+       if( flags != LDAP_SASL_QUIET ) {
+               saslrc = sasl_getprop( ctx, SASL_USERNAME, (void **) &data );
+               if( saslrc == SASL_OK && data && *data ) {
+                       fprintf( stderr, "SASL username: %s\n", data );
+               }
+
+               saslrc = sasl_getprop( ctx, SASL_REALM, (void **) &data );
+               if( saslrc == SASL_OK && data && *data ) {
+                       fprintf( stderr, "SASL realm: %s\n", data );
+               }
+       }
+
+       saslrc = sasl_getprop( ctx, SASL_SSF, (void **) &ssf );
+       if( saslrc == SASL_OK ) {
+               if( flags != LDAP_SASL_QUIET ) {
+                       fprintf( stderr, "SASL SSF: %lu\n",
+                               (unsigned long) *ssf );
+               }
+
+               if( ssf && *ssf ) {
+                       if( flags != LDAP_SASL_QUIET ) {
+                               fprintf( stderr, "SASL installing layers\n" );
+                       }
+                       ldap_pvt_sasl_install( ld->ld_sb, ctx );
+               }
+       }
+
+       return rc;
+}
+
+int ldap_pvt_sasl_secprops(
+       const char *in,
+       sasl_security_properties_t *secprops )
+{
+       int i;
+       char **props = ldap_str2charray( in, "," );
+       unsigned sflags = 0;
+       int got_sflags = 0;
+       sasl_ssf_t max_ssf;
+       int got_max_ssf = 0;
+       sasl_ssf_t min_ssf;
+       int got_min_ssf = 0;
+       unsigned maxbufsize;
+       int got_maxbufsize = 0;
+
+       if( props == NULL || secprops == NULL ) {
+               return LDAP_PARAM_ERROR;
+       }
+
+       for( i=0; props[i]; i++ ) {
+               if( !strcasecmp(props[i], "none") ) {
+                       got_sflags++;
+
+               } else if( !strcasecmp(props[i], "noplain") ) {
+                       got_sflags++;
+                       sflags |= SASL_SEC_NOPLAINTEXT;
+
+               } else if( !strcasecmp(props[i], "noactive") ) {
+                       got_sflags++;
+                       sflags |= SASL_SEC_NOACTIVE;
+
+               } else if( !strcasecmp(props[i], "nodict") ) {
+                       got_sflags++;
+                       sflags |= SASL_SEC_NODICTIONARY;
+
+               } else if( !strcasecmp(props[i], "forwardsec") ) {
+                       got_sflags++;
+                       sflags |= SASL_SEC_FORWARD_SECRECY;
+
+               } else if( !strcasecmp(props[i], "noanonymous")) {
+                       got_sflags++;
+                       sflags |= SASL_SEC_NOANONYMOUS;
+
+               } else if( !strcasecmp(props[i], "passcred") ) {
+                       got_sflags++;
+                       sflags |= SASL_SEC_PASS_CREDENTIALS;
+
+               } else if( !strncasecmp(props[i],
+                       "minssf=", sizeof("minssf")) )
+               {
+                       if( isdigit( props[i][sizeof("minssf")] ) ) {
+                               got_max_ssf++;
+                               min_ssf = atoi( &props[i][sizeof("minssf")] );
+                       } else {
+                               return LDAP_NOT_SUPPORTED;
+                       }
+
+               } else if( !strncasecmp(props[i],
+                       "maxssf=", sizeof("maxssf")) )
+               {
+                       if( isdigit( props[i][sizeof("maxssf")] ) ) {
+                               got_max_ssf++;
+                               max_ssf = atoi( &props[i][sizeof("maxssf")] );
+                       } else {
+                               return LDAP_NOT_SUPPORTED;
+                       }
+
+               } else if( !strncasecmp(props[i],
+                       "maxbufsize=", sizeof("maxbufsize")) )
+               {
+                       if( isdigit( props[i][sizeof("maxbufsize")] ) ) {
+                               got_maxbufsize++;
+                               maxbufsize = atoi( &props[i][sizeof("maxbufsize")] );
+                       } else {
+                               return LDAP_NOT_SUPPORTED;
+                       }
+
+               } else {
+                       return LDAP_NOT_SUPPORTED;
+               }
+       }
+
+       if(got_sflags) {
+               secprops->security_flags = sflags;
+       }
+       if(got_min_ssf) {
+               secprops->min_ssf = min_ssf;
+       }
+       if(got_max_ssf) {
+               secprops->max_ssf = max_ssf;
+       }
+       if(got_maxbufsize) {
+               secprops->maxbufsize = maxbufsize;
+       }
+
+       ldap_charray_free( props );
+       return LDAP_SUCCESS;
+}
+
+int
+ldap_int_sasl_config( struct ldapoptions *lo, int option, const char *arg )
+{
+       int rc;
+
+       switch( option ) {
+       case LDAP_OPT_X_SASL_SECPROPS:
+               rc = ldap_pvt_sasl_secprops( arg, &lo->ldo_sasl_secprops );
+               if( rc == LDAP_SUCCESS ) return 0;
+       }
+
+       return -1;
+}
+
+int
+ldap_int_sasl_get_option( LDAP *ld, int option, void *arg )
+{
+       if ( ld == NULL )
+               return -1;
+
+       switch ( option ) {
+               case LDAP_OPT_X_SASL_MECH: {
+                       *(char **)arg = ld->ld_options.ldo_def_sasl_mech
+                               ? LDAP_STRDUP( ld->ld_options.ldo_def_sasl_mech ) : NULL;
+               } break;
+               case LDAP_OPT_X_SASL_REALM: {
+                       *(char **)arg = ld->ld_options.ldo_def_sasl_realm
+                               ? LDAP_STRDUP( ld->ld_options.ldo_def_sasl_realm ) : NULL;
+               } break;
+               case LDAP_OPT_X_SASL_AUTHCID: {
+                       *(char **)arg = ld->ld_options.ldo_def_sasl_authcid
+                               ? LDAP_STRDUP( ld->ld_options.ldo_def_sasl_authcid ) : NULL;
+               } break;
+               case LDAP_OPT_X_SASL_AUTHZID: {
+                       *(char **)arg = ld->ld_options.ldo_def_sasl_authzid
+                               ? LDAP_STRDUP( ld->ld_options.ldo_def_sasl_authzid ) : NULL;
+               } break;
+
+               case LDAP_OPT_X_SASL_SSF: {
+                       int sc;
+                       sasl_ssf_t      *ssf;
+                       sasl_conn_t *ctx;
+
+                       if( ld->ld_defconn == NULL ) {
+                               return -1;
+                       }
+
+                       ctx = ld->ld_defconn->lconn_sasl_ctx;
+
+                       if ( ctx == NULL ) {
+                               return -1;
+                       }
+
+                       sc = sasl_getprop( ctx, SASL_SSF,
+                               (void **) &ssf );
+
+                       if ( sc != SASL_OK ) {
+                               return -1;
+                       }
+
+                       *(ber_len_t *)arg = *ssf;
+               } break;
+
+               case LDAP_OPT_X_SASL_SSF_EXTERNAL:
+                       /* this option is write only */
+                       return -1;
+
+               case LDAP_OPT_X_SASL_SSF_MIN:
+                       *(ber_len_t *)arg = ld->ld_options.ldo_sasl_secprops.min_ssf;
+                       break;
+               case LDAP_OPT_X_SASL_SSF_MAX:
+                       *(ber_len_t *)arg = ld->ld_options.ldo_sasl_secprops.max_ssf;
+                       break;
+               case LDAP_OPT_X_SASL_MAXBUFSIZE:
+                       *(ber_len_t *)arg = ld->ld_options.ldo_sasl_secprops.maxbufsize;
+                       break;
+
+               case LDAP_OPT_X_SASL_SECPROPS:
+                       /* this option is write only */
+                       return -1;
+
+               default:
+                       return -1;
+       }
+       return 0;
+}
+
+int
+ldap_int_sasl_set_option( LDAP *ld, int option, void *arg )
+{
+       if ( ld == NULL )
+               return -1;
+
+       switch ( option ) {
+       case LDAP_OPT_X_SASL_SSF:
+               /* This option is read-only */
+               return -1;
+
+       case LDAP_OPT_X_SASL_SSF_EXTERNAL: {
+               int sc;
+               sasl_external_properties_t extprops;
+               sasl_conn_t *ctx;
+
+               if( ld->ld_defconn == NULL ) {
+                       return -1;
+               }
+
+               ctx = ld->ld_defconn->lconn_sasl_ctx;
+
+               if ( ctx == NULL ) {
+                       return -1;
+               }
+
+               memset(&extprops, 0L, sizeof(extprops));
+
+               extprops.ssf = * (ber_len_t *) arg;
+
+               sc = sasl_setprop( ctx, SASL_SSF_EXTERNAL,
+                       (void *) &extprops );
+
+               if ( sc != SASL_OK ) {
+                       return -1;
+               }
+               } break;
+
+       case LDAP_OPT_X_SASL_SSF_MIN:
+               ld->ld_options.ldo_sasl_secprops.min_ssf = *(ber_len_t *)arg;
+               break;
+       case LDAP_OPT_X_SASL_SSF_MAX:
+               ld->ld_options.ldo_sasl_secprops.max_ssf = *(ber_len_t *)arg;
+               break;
+       case LDAP_OPT_X_SASL_MAXBUFSIZE:
+               ld->ld_options.ldo_sasl_secprops.maxbufsize = *(ber_len_t *)arg;
+               break;
+
+       case LDAP_OPT_X_SASL_SECPROPS: {
+               int sc;
+               sc = ldap_pvt_sasl_secprops( (char *) arg,
+                       &ld->ld_options.ldo_sasl_secprops );
+
+               return sc == LDAP_SUCCESS ? 0 : -1;
+               }
+
+       default:
+               return -1;
+       }
+       return 0;
+}
+
+#ifdef LDAP_R_COMPILE
+void *ldap_pvt_sasl_mutex_new(void)
+{
+       ldap_pvt_thread_mutex_t *mutex;
+
+       mutex = (ldap_pvt_thread_mutex_t *) LDAP_MALLOC(
+               sizeof(ldap_pvt_thread_mutex_t) );
+
+       if ( ldap_pvt_thread_mutex_init( mutex ) == 0 ) {
+               return mutex;
+       }
+       return NULL;
+}
+
+int ldap_pvt_sasl_mutex_lock(void *mutex)
+{
+       return ldap_pvt_thread_mutex_lock( (ldap_pvt_thread_mutex_t *)mutex )
+               ? SASL_FAIL : SASL_OK;
+}
+
+int ldap_pvt_sasl_mutex_unlock(void *mutex)
+{
+       return ldap_pvt_thread_mutex_unlock( (ldap_pvt_thread_mutex_t *)mutex )
+               ? SASL_FAIL : SASL_OK;
+}
+
+void ldap_pvt_sasl_mutex_dispose(void *mutex)
+{
+       (void) ldap_pvt_thread_mutex_destroy( (ldap_pvt_thread_mutex_t *)mutex );
+       LDAP_FREE( mutex );
+}
+#endif
+
+#else
+int ldap_int_sasl_init( void )
+{ return LDAP_SUCCESS; }
+
+int ldap_int_sasl_close( LDAP *ld, LDAPConn *lc )
+{ return LDAP_SUCCESS; }
+
+int
+ldap_int_sasl_bind(
+       LDAP                    *ld,
+       const char              *dn,
+       const char              *mechs,
+       LDAPControl             **sctrls,
+       LDAPControl             **cctrls,
+       unsigned                flags,
+       LDAP_SASL_INTERACT_PROC *interact,
+       void * defaults )
+{ return LDAP_NOT_SUPPORTED; }
+#endif /* HAVE_CYRUS_SASL */
index 57d80a541cf11410dfb73cedacb91f6b66a8a2e4..2b7771c5bdf1b74dbcbf3d1d4fcbb2ff5c91cdbd 100644 (file)
@@ -135,7 +135,7 @@ next_line( char **bufp, ber_len_t *blenp, char **linep )
        return( -1 );   /* fatal error */
     }
 
-    (void) memcpy( line, linestart, p - linestart );
+    AC_MEMCPY( line, linestart, p - linestart );
     line[ p - linestart - 1 ] = '\0';
     *linep = line;
     return( strlen( line ));
index 90fcac082fdf876cb01a3c70b07fe833bede303c..61ae88f4b6797db61a6d1d82c7aa78ceee796777 100644 (file)
@@ -231,7 +231,7 @@ ldap_parse_result(
        if(serverctrls != NULL) *serverctrls = NULL;
 
        /* Find the next result... */
-       for ( lm = r; lm->lm_chain != NULL; lm = lm->lm_chain ) {
+       for ( lm = r; lm != NULL; lm = lm->lm_chain ) {
                /* skip over entries and references */
                if( lm->lm_msgtype != LDAP_RES_SEARCH_ENTRY &&
                        lm->lm_msgtype != LDAP_RES_SEARCH_REFERENCE &&
index 0d8b488e19ac18c35e24fba7a0161fb22cd04322..3ed841ab5eb22261622e7bc92fb2a908ab531923 100644 (file)
@@ -334,7 +334,7 @@ explode_name( const char *name, int notypes, int is_type )
                                if (( parts[ count-1 ] = (char *)LDAP_CALLOC( 1,
                                    len + 1 )) != NULL )
                                {
-                                       SAFEMEMCPY( parts[ count-1 ], rdn, len );
+                                       AC_MEMCPY( parts[ count-1 ], rdn, len );
 
                                        if( !endquote ) {
                                                /* skip trailing spaces */
index ccdca5ea402e074b3feec2515a125a9ae4beb243..66d40656ade8d090db1c522abe2dd4f92e546267 100644 (file)
@@ -104,7 +104,7 @@ ldap_get_entry_controls(
        }
 
        /* make a local copy of the BerElement */
-       SAFEMEMCPY(&be, entry->lm_ber, sizeof(be));
+       AC_MEMCPY(&be, entry->lm_ber, sizeof(be));
 
        if ( ber_scanf( &be, "{xx" /*}*/ ) == LBER_ERROR ) {
                rc = LDAP_DECODING_ERROR;
index c837631e6d65f3acd36ea3b4dfca7f73a62cc223..9939ae88acd1dad6017747ad281a1200d344b2ed 100644 (file)
@@ -370,7 +370,7 @@ ldap_build_filter(
                                    *f++ = ' ';
                                }
                                slen = strlen( valwords[ i ] );
-                               SAFEMEMCPY( f, valwords[ i ], slen );
+                               AC_MEMCPY( f, valwords[ i ], slen );
                                f += slen;
                            }
                        }
@@ -379,17 +379,17 @@ ldap_build_filter(
                        if ( wordcount > 0 ) {
                            wordnum = wordcount - 1;
                            slen = strlen( valwords[ wordnum ] );
-                           SAFEMEMCPY( f, valwords[ wordnum ], slen );
+                           AC_MEMCPY( f, valwords[ wordnum ], slen );
                            f += slen;
                        }
                    } else if ( value != NULL ) {
                        slen = strlen( value );
-                       SAFEMEMCPY( f, value, slen );
+                       AC_MEMCPY( f, value, slen );
                        f += slen;
                    }
                } else if ( *p == 'a' && attr != NULL ) {
                    slen = strlen( attr );
-                   SAFEMEMCPY( f, attr, slen );
+                   AC_MEMCPY( f, attr, slen );
                    f += slen;
                } else {
                    *f++ = *p;
index 03fee191de20c21244f775bea2e579ae8ebfb1e8..164761b6edfa4254a540a7cc4ecc5bb863b8da05 100644 (file)
@@ -26,8 +26,10 @@ struct ldapoptions ldap_int_global_options =
 #define ATTR_INT       2
 #define ATTR_KV                3
 #define ATTR_STRING    4
-#define ATTR_TLS       5
-#define ATTR_URIS      6
+#define ATTR_URIS      5
+
+#define ATTR_SASL      6
+#define ATTR_TLS       7
 
 struct ol_keyvalue {
        const char *            key;
@@ -59,26 +61,35 @@ static const struct ol_attribute {
                offsetof(struct ldapoptions, ldo_defbinddn)},
        {0, ATTR_STRING,        "BASE",                 NULL,
                offsetof(struct ldapoptions, ldo_defbase)},
-       {0, ATTR_INT,           "PORT",                 NULL,
+       {0, ATTR_INT,           "PORT",                 NULL,           /* deprecated */
                offsetof(struct ldapoptions, ldo_defport)},
-       /* **** keep this around for backward compatibility */
-       {0, ATTR_URIS,          "HOST",                 NULL,   1},
-       /* **** */
-       {0, ATTR_URIS,          "URI",                  NULL,   0},
+       {0, ATTR_URIS,          "HOST",                 NULL,   1},     /* deprecated */
+       {0, ATTR_URIS,          "URI",                  NULL,   0}, /* replaces HOST/URI */
        {0, ATTR_BOOL,          "REFERRALS",    NULL,   LDAP_BOOL_REFERRALS},
        {0, ATTR_BOOL,          "RESTART",              NULL,   LDAP_BOOL_RESTART},
+
+#ifdef HAVE_CYRUS_SASL
+       {1, ATTR_STRING,        "SASL_MECH",            NULL,
+               offsetof(struct ldapoptions, ldo_def_sasl_mech)},
+       {1, ATTR_STRING,        "SASL_REALM",           NULL,
+               offsetof(struct ldapoptions, ldo_def_sasl_realm)},
+       {1, ATTR_STRING,        "SASL_AUTHCID",         NULL,
+               offsetof(struct ldapoptions, ldo_def_sasl_authcid)},
+       {1, ATTR_STRING,        "SASL_AUTHZID",         NULL,
+               offsetof(struct ldapoptions, ldo_def_sasl_authzid)},
+       {0, ATTR_SASL,          "SASL_SECPROPS",        NULL,   LDAP_OPT_X_SASL_SECPROPS},
+#endif
+
+#ifdef HAVE_TLS
        {0, ATTR_TLS,           "TLS",                  NULL,   LDAP_OPT_X_TLS},
-       {0, ATTR_TLS,           "TLS_CERT",             NULL,   LDAP_OPT_X_TLS_CERTFILE},
-       {0, ATTR_TLS,           "TLS_KEY",              NULL,   LDAP_OPT_X_TLS_KEYFILE},
+       {1, ATTR_TLS,           "TLS_CERT",             NULL,   LDAP_OPT_X_TLS_CERTFILE},
+       {1, ATTR_TLS,           "TLS_KEY",              NULL,   LDAP_OPT_X_TLS_KEYFILE},
        {0, ATTR_TLS,           "TLS_CACERT",   NULL,   LDAP_OPT_X_TLS_CACERTFILE},
        {0, ATTR_TLS,           "TLS_CACERTDIR",NULL,   LDAP_OPT_X_TLS_CACERTDIR},
-       {0, ATTR_TLS,           "TLS_REQCERT",  NULL,   LDAP_OPT_X_TLS_REQUIRE_CERT},
-#ifdef HAVE_CYRUS_SASL
-       {0, ATTR_INT,           "SASL_MINSSF",  NULL,
-               offsetof(struct ldapoptions, ldo_sasl_minssf)},
-       {0, ATTR_INT,           "SASL_MAXSSF",  NULL,
-               offsetof(struct ldapoptions, ldo_sasl_maxssf)},
+       {1, ATTR_TLS,           "TLS_REQCERT",  NULL,   LDAP_OPT_X_TLS_REQUIRE_CERT},
+       {1, ATTR_TLS,           "TLS_RANDFILE", NULL,   LDAP_OPT_X_TLS_RANDOM_FILE},
 #endif
+
        {0, ATTR_NONE,          NULL,           NULL,   0}
 };
 
@@ -200,11 +211,6 @@ static void openldap_ldap_init_w_conf(
                                if (* (char**) p != NULL) LDAP_FREE(* (char**) p);
                                * (char**) p = LDAP_STRDUP(opt);
                                break;
-                       case ATTR_TLS:
-#ifdef HAVE_TLS
-                               ldap_pvt_tls_config( gopts, attrs[i].offset, opt );
-#endif
-                               break;
                        case ATTR_URIS:
                                if (attrs[i].offset == 0) {
                                        ldap_set_option( NULL, LDAP_OPT_URI, opt );
@@ -212,7 +218,18 @@ static void openldap_ldap_init_w_conf(
                                        ldap_set_option( NULL, LDAP_OPT_HOST_NAME, opt );
                                }
                                break;
+                       case ATTR_SASL:
+#ifdef HAVE_CYRUS_SASL
+                               ldap_int_sasl_config( gopts, attrs[i].offset, opt );
+#endif
+                               break;
+                       case ATTR_TLS:
+#ifdef HAVE_TLS
+                               ldap_int_tls_config( gopts, attrs[i].offset, opt );
+#endif
+                               break;
                        }
+
                        break;
                }
        }
@@ -334,11 +351,6 @@ static void openldap_ldap_init_w_env(
                                * (char**) p = LDAP_STRDUP(value);
                        }
                        break;
-               case ATTR_TLS:
-#ifdef HAVE_TLS
-                       ldap_pvt_tls_config( gopts, attrs[i].offset, value );
-#endif                         
-                       break;
                case ATTR_URIS:
                        if (attrs[i].offset == 0) {
                                ldap_set_option( NULL, LDAP_OPT_URI, value );
@@ -346,6 +358,16 @@ static void openldap_ldap_init_w_env(
                                ldap_set_option( NULL, LDAP_OPT_HOST_NAME, value );
                        }
                        break;
+               case ATTR_SASL:
+#ifdef HAVE_CYRUS_SASL
+                       ldap_int_sasl_config( gopts, attrs[i].offset, value );
+#endif                         
+                       break;
+               case ATTR_TLS:
+#ifdef HAVE_TLS
+                       ldap_int_tls_config( gopts, attrs[i].offset, value );
+#endif                         
+                       break;
                }
        }
 }
@@ -381,34 +403,57 @@ void ldap_int_initialize_global_options( struct ldapoptions *gopts, int *dbglvl
 
        LDAP_BOOL_SET(gopts, LDAP_BOOL_REFERRALS);
 
+#ifdef HAVE_CYRUS_SASL
+       gopts->ldo_def_sasl_mech = NULL;
+       gopts->ldo_def_sasl_realm = NULL;
+       gopts->ldo_def_sasl_authcid = NULL;
+       gopts->ldo_def_sasl_authzid = NULL;
+
+       memset( &gopts->ldo_sasl_secprops, '\0', sizeof(gopts->ldo_sasl_secprops) );
+
+       gopts->ldo_sasl_secprops.max_ssf = INT_MAX;
+       gopts->ldo_sasl_secprops.maxbufsize = 65536;
+       gopts->ldo_sasl_secprops.security_flags = SASL_SEC_NOPLAINTEXT|SASL_SEC_NOANONYMOUS;
+#endif
+
 #ifdef HAVE_TLS
        gopts->ldo_tls_ctx = NULL;
 #endif
-#ifdef HAVE_CYRUS_SASL
-       gopts->ldo_sasl_minssf = 0;
-       gopts->ldo_sasl_maxssf = INT_MAX;
-#endif
 
        gopts->ldo_valid = LDAP_INITIALIZED;
 
        return;
 }
 
+#if defined(LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND) \
+       || defined(HAVE_TLS) || defined(HAVE_CYRUS_SASL)
+char * ldap_int_hostname = "localhost";
+#endif
+
 void ldap_int_initialize( struct ldapoptions *gopts, int *dbglvl )
 {
        if ( gopts->ldo_valid == LDAP_INITIALIZED ) {
                return;
        }
 
+#if defined(LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND) \
+       || defined(HAVE_TLS) || defined(HAVE_CYRUS_SASL)
+       {
+               char hostbuf[MAXHOSTNAMELEN+1];
+               if( gethostname( hostbuf, MAXHOSTNAMELEN ) == 0 ) {
+                       hostbuf[MAXHOSTNAMELEN] = '\0';
+                       ldap_int_hostname = hostbuf;
+               }
+       }
+#endif
+
        ldap_int_utils_init();
 
 #ifdef HAVE_TLS
        ldap_pvt_tls_init();
 #endif
 
-#ifdef HAVE_CYRUS_SASL
-       ldap_pvt_sasl_init();
-#endif
+       ldap_int_sasl_init();
 
        if ( ldap_int_tblsize == 0 )
                ldap_int_ip_init();
@@ -419,6 +464,21 @@ void ldap_int_initialize( struct ldapoptions *gopts, int *dbglvl )
                return;
        }
 
+#ifdef HAVE_CYRUS_SASL
+       {
+               /* set authentication identity to current user name */
+               char *user = getenv("USER");
+
+               if( user == NULL ) user = getenv("USERNAME");
+               if( user == NULL ) user = getenv("LOGNAME");
+
+               if( user != NULL ) {
+                       /* this value is leaked, need at_exit() handler */
+                       gopts->ldo_def_sasl_authcid = LDAP_STRDUP( user );
+               }
+    }
+#endif
+
        openldap_ldap_init_w_sysconf(LDAP_CONF_FILE);
        openldap_ldap_init_w_userconf(LDAP_USERRC_FILE);
 
index 65fb0d2e036be7792863bb0d667495df5ad69968..240c3f7b242a84fa44fec3205f28900e829ed611 100644 (file)
@@ -275,7 +275,7 @@ ldap_get_kerberosv4_credentials(
        }
 
        *len = ktxt.length;
-       memcpy( cred, ktxt.dat, ktxt.length );
+       AC_MEMCPY( cred, ktxt.dat, ktxt.length );
 
        return( cred );
 }
index fd6352d93a3963a082cba34ed461d6139d5b9530..3bd030494efd9c0495c413a498a4271875b27fba 100644 (file)
 
 #include "../liblber/lber-int.h"
 
+#ifdef HAVE_CYRUS_SASL
+       /* the need for this should be removed */
+#include <sasl.h>
+#endif
+
 /* 
  * Support needed if the library is running in the kernel
  */
@@ -120,7 +125,17 @@ struct ldapoptions {
        LDAPURLDesc *ldo_defludp;
        int             ldo_defport;
        char*   ldo_defbase;
-       char*   ldo_defbinddn;  /* simple bind dn */
+       char*   ldo_defbinddn;  /* bind dn */
+
+#ifdef HAVE_CYRUS_SASL
+       char*   ldo_def_sasl_mech;              /* SASL Mechanism(s) */
+       char*   ldo_def_sasl_realm;             /* SASL realm */
+       char*   ldo_def_sasl_authcid;   /* SASL authentication identity */
+       char*   ldo_def_sasl_authzid;   /* SASL authorization identity */
+
+       /* SASL Security Properties */
+       struct sasl_security_properties ldo_sasl_secprops;
+#endif
 
 #ifdef LDAP_CONNECTIONLESS
        int             ldo_cldaptries; /* connectionless search retry count */
@@ -140,10 +155,6 @@ struct ldapoptions {
        /* tls context */
        void            *ldo_tls_ctx;
        int             ldo_tls_mode;
-#endif
-#ifdef HAVE_CYRUS_SASL
-       sasl_ssf_t      ldo_sasl_minssf;
-       sasl_ssf_t      ldo_sasl_maxssf;
 #endif
        LDAP_BOOLEANS ldo_booleans;     /* boolean options */
 };
@@ -164,7 +175,8 @@ typedef struct ldap_server {
  * structure for representing an LDAP server connection
  */
 typedef struct ldap_conn {
-       Sockbuf                 *lconn_sb;
+       Sockbuf         *lconn_sb;
+       void            *lconn_sasl_ctx;
        int                     lconn_refcnt;
        time_t          lconn_lastused; /* time */
        int                     lconn_rebind_inprogress;        /* set if rebind in progress */
@@ -266,7 +278,8 @@ struct ldap {
 #define ld_cctrls              ld_options.ldo_cctrls
 #define ld_rebindproc  ld_options.ldo_rebindproc
 
-#define ld_version             ld_options.ldo_version  
+#define ld_version             ld_options.ldo_version
+
        char    *ld_host;
        int             ld_port;
 
@@ -298,22 +311,20 @@ struct ldap {
        LDAPConn        *ld_defconn;    /* default connection */
        LDAPConn        *ld_conns;      /* list of server connections */
        void            *ld_selectinfo; /* platform specifics for select */
-#ifdef HAVE_CYRUS_SASL
-       sasl_conn_t             *ld_sasl_context;
-#endif /* HAVE_CYRUS_SASL */
 };
 #define LDAP_VALID(ld) ( (ld)->ld_valid == LDAP_VALID_SESSION )
 
 #if defined(HAVE_RES_QUERY) && defined(LDAP_R_COMPILE)
 #include <ldap_pvt_thread.h>
-extern ldap_pvt_thread_mutex_t ldap_int_resolv_mutex;
+LDAP_V ( ldap_pvt_thread_mutex_t ) ldap_int_resolv_mutex;
 #endif /* HAVE_RES_QUERY && LDAP_R_COMPILE */
 
 /*
  * in init.c
  */
 
-LDAP_F ( struct ldapoptions ) ldap_int_global_options;
+LDAP_V ( struct ldapoptions ) ldap_int_global_options;
+
 LDAP_F ( void ) ldap_int_initialize LDAP_P((struct ldapoptions *, int *));
 LDAP_F ( void ) ldap_int_initialize_global_options LDAP_P((
        struct ldapoptions *, int *));
@@ -371,12 +382,6 @@ LDAP_F (int) ldap_int_put_controls LDAP_P((
        LDAPControl *const *ctrls,
        BerElement *ber ));
 
-LDAP_F( int ) 
-ldap_int_create_control LDAP_P(( 
-       const char *requestOID, 
-       BerElement *ber, 
-       int iscritical,
-       LDAPControl **ctrlp ));
 
 /*
  * in dsparse.c
@@ -400,16 +405,20 @@ LDAP_F (char *) ldap_get_kerberosv4_credentials LDAP_P((
  * in open.c
  */
 LDAP_F (int) ldap_open_defconn( LDAP *ld );
-LDAP_F (int) open_ldap_connection( LDAP *ld, Sockbuf *sb, LDAPURLDesc *srvlist, char **krbinstancep, int async );
+LDAP_F (int) ldap_int_open_connection( LDAP *ld,
+       LDAPConn *conn, LDAPURLDesc *srvlist, int async );
 
 /*
  * in os-ip.c
  */
 LDAP_F (int) ldap_int_tblsize;
 LDAP_F (int) ldap_int_timeval_dup( struct timeval **dest, const struct timeval *tm );
-LDAP_F (int) ldap_connect_to_host( LDAP *ld, Sockbuf *sb, const char *host, unsigned long address, int port, int async );
+LDAP_F (int) ldap_connect_to_host( LDAP *ld, Sockbuf *sb,
+       int proto, const char *host, unsigned long address, int port,
+       int async );
 
 #if defined(LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND) || defined(HAVE_TLS) || defined(HAVE_CYRUS_SASL)
+LDAP_V (char *) ldap_int_hostname;
 LDAP_F (char *) ldap_host_connected_to( Sockbuf *sb );
 #endif /* LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND */
 
@@ -427,7 +436,8 @@ LDAP_F (int) ldap_is_write_ready( LDAP *ld, Sockbuf *sb );
  * in os-local.c
  */
 #ifdef LDAP_PF_UNIX 
-LDAP_F (int) ldap_connect_to_path( LDAP *ld, Sockbuf *sb, const char *path, int async );
+LDAP_F (int) ldap_connect_to_path( LDAP *ld, Sockbuf *sb, int proto,
+       const char *path, int async );
 #endif /* LDAP_PF_UNIX */
 
 /*
@@ -518,6 +528,38 @@ LDAP_F (char *) ldap_url_list2urls LDAP_P((
 LDAP_F (void) ldap_free_urllist LDAP_P((
        LDAPURLDesc *ludlist ));
 
+/*
+ * in cyrus.c
+ */
+LDAP_F (int) ldap_int_sasl_init LDAP_P(( void ));
+
+LDAP_F (int) ldap_int_sasl_open LDAP_P((
+       LDAP *ld, LDAPConn *conn,
+       const char* host, ber_len_t ssf ));
+LDAP_F (int) ldap_int_sasl_close LDAP_P(( LDAP *ld, LDAPConn *conn ));
+
+LDAP_F (int) ldap_int_sasl_get_option LDAP_P(( LDAP *ld,
+       int option, void *arg ));
+LDAP_F (int) ldap_int_sasl_set_option LDAP_P(( LDAP *ld,
+       int option, void *arg ));
+LDAP_F (int) ldap_int_sasl_config LDAP_P(( struct ldapoptions *lo,
+       int option, const char *arg ));
+
+LDAP_F (int) ldap_int_sasl_bind LDAP_P((
+       struct ldap *ld,
+       const char *,
+       const char *,
+       LDAPControl **, LDAPControl **,
+
+       /* should be passed in client controls */
+       unsigned flags,
+       LDAP_SASL_INTERACT_PROC *interact,
+       void *defaults ));
+
+/*
+ * in tls.c
+ */
+LDAP_F (int) ldap_int_tls_config LDAP_P(( struct ldapoptions *lo, int option, const char *arg ));
 
 LDAP_END_DECL
 
index 32fd51d2ed7455e51fae9acad1381edb6748087d..03d508c94fa90a745a15be11bbfd1fe38d16475f 100644 (file)
@@ -7,9 +7,6 @@
 # This file should be world readable.
 
 #BASE  dc=OpenLDAP, dc=Org
-#HOST  ldap.openldap.org
-#PORT  389
-
 #URI   ldap://ldap.openldap.org ldap://ldap-master.openldap.org:666
 
 #SIZELIMIT     12
index 0ba5b193b54ea00f63727ea0442486bedc1f1dc8..899d698fd7a13b67becadae5141059ec7288df17 100644 (file)
@@ -163,6 +163,10 @@ SOURCE=.\controls.c
 # End Source File
 # Begin Source File
 
+SOURCE=.\cyrus.c
+# End Source File
+# Begin Source File
+
 SOURCE=.\delete.c
 # End Source File
 # Begin Source File
index f0a5a593df419905dd890d0f6e3f814e22145b91..4b2176a2a4e34d16307eb727bc945d136c3debd1 100644 (file)
 
 int ldap_open_defconn( LDAP *ld )
 {
-       if (( ld->ld_defconn = ldap_new_connection( ld, ld->ld_options.ldo_defludp, 1,1,NULL )) == NULL )
-       {
+       ld->ld_defconn = ldap_new_connection( ld,
+               ld->ld_options.ldo_defludp, 1, 1, NULL );
+
+       if( ld->ld_defconn == NULL ) {
                ld->ld_errno = LDAP_SERVER_DOWN;
                return -1;
        }
 
        ++ld->ld_defconn->lconn_refcnt; /* so it never gets closed/freed */
-
        return 0;
 }
 
@@ -91,7 +92,7 @@ ldap_create( LDAP **ldp )
                ldap_int_initialize(gopts, NULL);
        }
 
-       Debug( LDAP_DEBUG_TRACE, "ldap_init\n", 0, 0, 0 );
+       Debug( LDAP_DEBUG_TRACE, "ldap_create\n", 0, 0, 0 );
 
 #ifdef HAVE_WINSOCK2
 {      WORD wVersionRequested;
@@ -134,15 +135,25 @@ ldap_create( LDAP **ldp )
        }
    
        /* copy the global options */
-       memcpy(&ld->ld_options, gopts, sizeof(ld->ld_options));
+       AC_MEMCPY(&ld->ld_options, gopts, sizeof(ld->ld_options));
 
        ld->ld_valid = LDAP_VALID_SESSION;
 
        /* but not pointers to malloc'ed items */
-       ld->ld_options.ldo_defludp = NULL;
        ld->ld_options.ldo_sctrls = NULL;
        ld->ld_options.ldo_cctrls = NULL;
 
+#ifdef HAVE_CYRUS_SASL
+       ld->ld_options.ldo_def_sasl_mech = gopts->ldo_def_sasl_mech
+               ? LDAP_STRDUP( gopts->ldo_def_sasl_mech ) : NULL;
+       ld->ld_options.ldo_def_sasl_realm = gopts->ldo_def_sasl_realm
+               ? LDAP_STRDUP( gopts->ldo_def_sasl_realm ) : NULL;
+       ld->ld_options.ldo_def_sasl_authcid = gopts->ldo_def_sasl_authcid
+               ? LDAP_STRDUP( gopts->ldo_def_sasl_authcid ) : NULL;
+       ld->ld_options.ldo_def_sasl_authzid = gopts->ldo_def_sasl_authzid
+               ? LDAP_STRDUP( gopts->ldo_def_sasl_authzid ) : NULL;
+#endif
+
        ld->ld_options.ldo_defludp = ldap_url_duplist(gopts->ldo_defludp);
 
        if ( ld->ld_options.ldo_defludp == NULL ) {
@@ -179,7 +190,7 @@ ldap_create( LDAP **ldp )
  *
  * Example:
  *     LDAP    *ld;
- *     ld = ldap_open( host, port );
+ *     ld = ldap_init( host, port );
  */
 LDAP *
 ldap_init( LDAP_CONST char *defhost, int defport )
@@ -250,8 +261,9 @@ ldap_start_tls_s ( LDAP *ld,
                if (ldap_pvt_tls_inplace(lc->lconn_sb) != 0)
                        return LDAP_OPERATIONS_ERROR;
 
+               /* XXYYZ: this initiates operaton only on default connection! */
                rc = ldap_extended_operation_s(ld, LDAP_EXOP_START_TLS,
-                                                       NULL, serverctrls, clientctrls, &rspoid, &rspdata);
+                       NULL, serverctrls, clientctrls, &rspoid, &rspdata);
 
                if (rc != LDAP_SUCCESS)
                        return rc;
@@ -270,14 +282,21 @@ ldap_start_tls_s ( LDAP *ld,
 }
 
 int
-open_ldap_connection( LDAP *ld, Sockbuf *sb, LDAPURLDesc *srv,
-       char **krbinstancep, int async )
+ldap_int_open_connection(
+       LDAP *ld,
+       LDAPConn *conn,
+       LDAPURLDesc *srv,
+       int async )
 {
        int rc = -1;
+#ifdef HAVE_CYRUS_SASL
+       char *sasl_host = NULL;
+       int sasl_ssf = 0;
+#endif
        int port;
        long addr;
 
-       Debug( LDAP_DEBUG_TRACE, "open_ldap_connection\n", 0, 0, 0 );
+       Debug( LDAP_DEBUG_TRACE, "ldap_int_open_connection\n", 0, 0, 0 );
 
        port = srv->lud_port;
        if (port == 0)
@@ -290,62 +309,78 @@ open_ldap_connection( LDAP *ld, Sockbuf *sb, LDAPURLDesc *srv,
 
        switch ( ldap_pvt_url_scheme2proto( srv->lud_scheme ) ) {
                case LDAP_PROTO_TCP:
-                       rc = ldap_connect_to_host( ld, sb, srv->lud_host,
-                               addr, port, async );
-                       if ( rc == -1 )
-                               return rc;
-                       ber_sockbuf_add_io( sb, &ber_sockbuf_io_tcp,
+                       rc = ldap_connect_to_host( ld, conn->lconn_sb, 0,
+                               srv->lud_host, addr, port, async );
+                       if ( rc == -1 ) return rc;
+                       ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_tcp,
                                LBER_SBIOD_LEVEL_PROVIDER, NULL );
+
+#ifdef HAVE_CYRUS_SASL
+                       sasl_host = ldap_host_connected_to( conn->lconn_sb );
+#endif
                        break;
                case LDAP_PROTO_UDP:
-                       rc = ldap_connect_to_host( ld, sb, srv->lud_host,
-                               addr, port, async );
-                       if ( rc == -1 )
-                               return rc;
-                       ber_sockbuf_add_io( sb, &ber_sockbuf_io_udp,
+                       rc = ldap_connect_to_host( ld, conn->lconn_sb, 1,
+                               srv->lud_host, addr, port, async );
+                       if ( rc == -1 ) return rc;
+                       ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_udp,
                                LBER_SBIOD_LEVEL_PROVIDER, NULL );
                        break;
                case LDAP_PROTO_IPC:
-#ifdef LDAP_PF_UNIX
-                       /* only IPC mechanism supported is PF_UNIX */
-                       rc = ldap_connect_to_path( ld, sb, srv->lud_host,
-                               async );
-                       if ( rc == -1 )
-                               return rc;
-                       ber_sockbuf_add_io( sb, &ber_sockbuf_io_fd,
+#ifdef LDAP_PF_LOCAL
+                       /* only IPC mechanism supported is PF_LOCAL (PF_UNIX) */
+                       rc = ldap_connect_to_path( ld, conn->lconn_sb, 0,
+                               srv->lud_host, async );
+                       if ( rc == -1 ) return rc;
+                       ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_fd,
                                LBER_SBIOD_LEVEL_PROVIDER, NULL );
+
+#ifdef HAVE_CYRUS_SASL
+                       sasl_host = ldap_host_connected_to( conn->lconn_sb );
+                       sasl_ssf = LDAP_PVT_SASL_LOCAL_SSF;
+#endif
                        break;
-#endif /* LDAP_PF_UNIX */
+#endif /* LDAP_PF_LOCAL */
                default:
                        return -1;
                        break;
        }
 
-       ber_sockbuf_add_io( sb, &ber_sockbuf_io_readahead,
+#ifdef HAVE_CYRUS_SASL
+       if( sasl_host != NULL ) {
+               ldap_int_sasl_open( ld, conn, sasl_host, sasl_ssf );
+       }
+#endif
+
+       ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_readahead,
                LBER_SBIOD_LEVEL_PROVIDER, NULL );
 #ifdef LDAP_DEBUG
-       ber_sockbuf_add_io( sb, &ber_sockbuf_io_debug, INT_MAX, NULL );
+       ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_debug,
+               INT_MAX, NULL );
 #endif
 
 #ifdef HAVE_TLS
        if (ld->ld_options.ldo_tls_mode == LDAP_OPT_X_TLS_HARD ||
                strcmp( srv->lud_scheme, "ldaps" ) == 0 )
        {
-               rc = ldap_pvt_tls_start( ld, sb, ld->ld_options.ldo_tls_ctx );
+               rc = ldap_pvt_tls_start( ld, conn->lconn_sb,
+                       ld->ld_options.ldo_tls_ctx );
                if (rc != LDAP_SUCCESS)
                        return rc;
        }
 #endif
 
-       if ( krbinstancep != NULL ) {
+       if ( conn->lconn_krbinstance != NULL ) {
 #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND
                char *c;
-               if (( *krbinstancep = ldap_host_connected_to( sb )) != NULL &&
-                   ( c = strchr( *krbinstancep, '.' )) != NULL ) {
+               conn->lconn_krbinstance = ldap_host_connected_to( conn->sb );
+
+               if( conn->lconn_krbinstance != NULL && 
+                   ( c = strchr( conn->lconn_krbinstance, '.' )) != NULL ) {
                        *c = '\0';
                }
 #else /* LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND */
-               *krbinstancep = NULL;
+               conn->lconn_krbinstance = NULL;
 #endif /* LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND */
        }
 
index a45cccecf77d5c6c7e9c1dca2e9fe608d717ab4b..515f906b9845b2efa7bbef4cfd041c937347a8d5 100644 (file)
@@ -285,7 +285,7 @@ ldap_get_option(
                        return LDAP_OPT_SUCCESS;
 #endif
 #ifdef HAVE_CYRUS_SASL
-               if ( ldap_pvt_sasl_get_option(ld, option, outvalue ) == 0 )
+               if ( ldap_int_sasl_get_option(ld, option, outvalue ) == 0 )
                        return LDAP_OPT_SUCCESS;
 #endif
                /* bad param */
@@ -582,7 +582,7 @@ ldap_set_option(
                return LDAP_OPT_SUCCESS;
 #endif
 #ifdef HAVE_CYRUS_SASL
-               if ( ldap_pvt_sasl_set_option( ld, option, (void *)invalue ) == 0 )
+               if ( ldap_int_sasl_set_option( ld, option, (void *)invalue ) == 0 )
                        return LDAP_OPT_SUCCESS;
 #endif
                /* bad param */
index 7ffc16bd8ce3eee3f829002583982bb38c49df6f..c2143561a10a7e2841b931901ecd5dddccb9a50e 100644 (file)
@@ -74,7 +74,7 @@ ldap_int_timeval_dup( struct timeval **dest, const struct timeval *src )
                return 1;
        }
 
-       SAFEMEMCPY( (char *) new, (const char *) src, sizeof(struct timeval));
+       AC_MEMCPY( (char *) new, (const char *) src, sizeof(struct timeval));
 
        *dest = new;
        return 0;
@@ -95,9 +95,9 @@ ldap_pvt_ndelay_off(LDAP *ld, int fd)
 }
 
 static ber_socket_t
-ldap_pvt_socket(LDAP *ld, int family)
+ldap_int_socket(LDAP *ld, int family, int type )
 {
-       ber_socket_t s = socket(family, SOCK_STREAM, 0);
+       ber_socket_t s = socket(family, type, 0);
        osip_debug(ld, "ldap_new_socket: %d\n",s,0,0);
        return ( s );
 }
@@ -110,22 +110,23 @@ ldap_pvt_close_socket(LDAP *ld, int s)
 }
 
 static int
-ldap_pvt_prepare_socket(LDAP *ld, int fd)
+ldap_int_prepare_socket(LDAP *ld, int s, int proto )
 {
-       osip_debug(ld, "ldap_prepare_socket: %d\n",fd,0,0);
+       osip_debug(ld, "ldap_prepare_socket: %d\n", s,0,0);
 
 #ifdef TCP_NODELAY
-{
-       int dummy = 1;
-       if ( setsockopt( fd, IPPROTO_TCP, TCP_NODELAY,
-               (char*) &dummy, sizeof(dummy) ) == AC_SOCKET_ERROR )
-       {
-               osip_debug(ld, "ldap_prepare_socket: "
-                       "setsockopt(%d, TCP_NODELAY) failed (ignored).\n",
-                       fd, 0, 0);
+       if( proto = LDAP_PROTO_TCP ) {
+               int dummy = 1;
+               if ( setsockopt( s, IPPROTO_TCP, TCP_NODELAY,
+                       (char*) &dummy, sizeof(dummy) ) == AC_SOCKET_ERROR )
+               {
+                       osip_debug(ld, "ldap_prepare_socket: "
+                               "setsockopt(%d, TCP_NODELAY) failed (ignored).\n",
+                               s, 0, 0);
+               }
        }
-}
 #endif
+
        return 0;
 }
 
@@ -183,7 +184,9 @@ ldap_pvt_is_socket_ready(LDAP *ld, int s)
 #undef TRACE
 
 static int
-ldap_pvt_connect(LDAP *ld, ber_socket_t s, struct sockaddr *sin, socklen_t addrlen, int async)
+ldap_pvt_connect(LDAP *ld, ber_socket_t s,
+       struct sockaddr *sin, socklen_t addrlen,
+       int async)
 {
        struct timeval  tv, *opt_tv=NULL;
        fd_set          wfds, *z=NULL;
@@ -275,8 +278,10 @@ ldap_pvt_inet_aton( const char *host, struct in_addr *in)
 
 
 int
-ldap_connect_to_host(LDAP *ld, Sockbuf *sb, const char *host,
-               unsigned long address, int port, int async)
+ldap_connect_to_host(LDAP *ld, Sockbuf *sb,
+       int proto,
+       const char *host,
+       unsigned long address, int port, int async)
 {
        struct sockaddr_in      sin;
        struct in_addr          in;
@@ -290,12 +295,13 @@ ldap_connect_to_host(LDAP *ld, Sockbuf *sb, const char *host,
        
        if (host != NULL) {
 #ifdef HAVE_GETADDRINFO
-               char serv[7];
+               char serv[7];
                struct addrinfo hints, *res, *sai;
 
                memset( &hints, '\0', sizeof(hints) );
                hints.ai_family = AF_UNSPEC;
-               hints.ai_socktype = SOCK_STREAM;
+               hints.ai_socktype = proto == LDAP_PROTO_UDP
+                       ? SOCK_DGRAM : SOCK_STREAM;
 
                snprintf(serv, sizeof serv, "%d", ntohs(port));
                if ( getaddrinfo(host, serv, &hints, &res) ) {
@@ -305,11 +311,18 @@ ldap_connect_to_host(LDAP *ld, Sockbuf *sb, const char *host,
                sai = res;
                rc = -1;
                do {
-                       s = ldap_pvt_socket( ld, sai->ai_family );
+                       /* we assume AF_x and PF_x are equal for all x */
+                       s = ldap_int_socket( ld, sai->ai_family,
+                               proto == LDAP_PROTO_UDP ? SOCK_DGRAM : SOCK_STREAM );
                        if ( s == -1 ) {
                                continue;
                        }
 
+                       if ( ldap_int_prepare_socket(ld, s, proto ) == -1 ) {
+                               ldap_pvt_close_socket(ld, s);
+                               break;
+                       }
+
                        switch (sai->ai_family) {
 #ifdef LDAP_PF_INET6
                        case AF_INET6: {
@@ -330,6 +343,7 @@ ldap_connect_to_host(LDAP *ld, Sockbuf *sb, const char *host,
                                        addr, serv, 0);
                        } break;
                        }
+
                        rc = ldap_pvt_connect(ld, s, sai->ai_addr, sai->ai_addrlen, async);
                        if ( (rc == 0) || (rc == -2) ) {
                                ber_sockbuf_ctrl( sb, LBER_SB_OPT_SET_FD, &s );
@@ -363,15 +377,15 @@ ldap_connect_to_host(LDAP *ld, Sockbuf *sb, const char *host,
        rc = s = -1;
        for ( i = 0; !use_hp || (hp->h_addr_list[i] != 0); ++i, rc = -1 ) {
 
-               s = ldap_pvt_socket( ld, AF_INET );
+               s = ldap_int_socket( ld, PF_INET,
+                       proto == LDAP_PROTO_UDP ? SOCK_DGRAM : SOCK_STREAM );
                if ( s == -1 ) {
                        /* use_hp ? continue : break; */
                        break;
                }
           
-               if ( ldap_pvt_prepare_socket(ld, s) == -1 ) {
+               if ( ldap_int_prepare_socket( ld, s, proto ) == -1 ) {
                        ldap_pvt_close_socket(ld, s);
-                       /* use_hp ? continue : break; */
                        break;
                }
 
@@ -380,12 +394,14 @@ ldap_connect_to_host(LDAP *ld, Sockbuf *sb, const char *host,
                sin.sin_port = port;
                p = (char *)&sin.sin_addr;
                q = use_hp ? (char *)hp->h_addr_list[i] : (char *)&address;
-               SAFEMEMCPY(p, q, sizeof(sin.sin_addr) );
+               AC_MEMCPY(p, q, sizeof(sin.sin_addr) );
 
                osip_debug(ld, "ldap_connect_to_host: Trying %s:%d\n", 
                                inet_ntoa(sin.sin_addr),ntohs(sin.sin_port),0);
 
-               rc = ldap_pvt_connect(ld, s, (struct sockaddr *)&sin, sizeof(struct sockaddr_in), async);
+               rc = ldap_pvt_connect(ld, s,
+                       (struct sockaddr *)&sin, sizeof(struct sockaddr_in),
+                       async);
    
                if ( (rc == 0) || (rc == -2) ) {
                        ber_sockbuf_ctrl( sb, LBER_SB_OPT_SET_FD, &s );
@@ -401,27 +417,28 @@ ldap_connect_to_host(LDAP *ld, Sockbuf *sb, const char *host,
        return rc;
 }
 
-#if defined( LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND ) || defined( HAVE_TLS ) || defined( HAVE_CYRUS_SASL )
+#if defined( LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND ) \
+       || defined( HAVE_TLS ) || defined( HAVE_CYRUS_SASL )
 char *
 ldap_host_connected_to( Sockbuf *sb )
 {
-       struct hostent          *hp;
-       socklen_t               len;
-       struct sockaddr         sa;
-       char                    *addr;
+       struct hostent  *hp;
+       socklen_t               len;
+       struct sockaddr sa;
+       char                    *addr;
+       char                    *host;
 
        /* buffers for gethostbyaddr_r */
-       struct hostent          he_buf;
-        int                    local_h_errno;
+       struct hostent  he_buf;
+       int                             local_h_errno;
        char                    *ha_buf=NULL;
-       ber_socket_t            sd;
-#define DO_RETURN(x) if (ha_buf) LDAP_FREE(ha_buf); return (x);
-   
+       ber_socket_t    sd;
+
        (void)memset( (char *)&sa, '\0', sizeof( struct sockaddr ));
        len = sizeof( sa );
 
        ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, &sd );
-       if ( getpeername( sd, (struct sockaddr *)&sa, &len ) == -1 ) {
+       if ( getpeername( sd, &sa, &len ) == -1 ) {
                return( NULL );
        }
 
@@ -432,6 +449,10 @@ ldap_host_connected_to( Sockbuf *sb )
         */
 
        switch (sa.sa_family) {
+#ifdef LDAP_PF_LOCAL
+       case AF_LOCAL:
+               return LDAP_STRDUP( ldap_int_hostname );
+#endif
 #ifdef LDAP_PF_INET6
        case AF_INET6:
                addr = (char *) &((struct sockaddr_in6 *)&sa)->sin6_addr;
@@ -441,25 +462,37 @@ ldap_host_connected_to( Sockbuf *sb )
        case AF_INET:
                addr = (char *) &((struct sockaddr_in *)&sa)->sin_addr;
                len = sizeof( struct in_addr );
+
+               {
+                       struct sockaddr_in localhost;
+                       localhost.sin_addr.s_addr = htonl( INADDR_ANY );
+
+                       if( memcmp ( &localhost.sin_addr,
+                               &((struct sockaddr_in *)&sa)->sin_addr,
+                               sizeof(localhost.sin_addr) ) == 0 )
+                       {
+                               return LDAP_STRDUP( ldap_int_hostname );
+                       }
+               }
                break;
+
        default:
                return( NULL );
                break;
        }
+
+       host = NULL;
        if ((ldap_pvt_gethostbyaddr_a( addr, len,
                sa.sa_family, &he_buf, &ha_buf,
-               &hp,&local_h_errno ) ==0 ) && (hp != NULL) )
+               &hp,&local_h_errno ) == 0 ) &&
+               (hp != NULL) && ( hp->h_name != NULL ) )
        {
-               if ( hp->h_name != NULL ) {
-                       char *host = LDAP_STRDUP( hp->h_name );   
-                       DO_RETURN( host );
-               }
+               host = LDAP_STRDUP( hp->h_name );   
        }
 
-       DO_RETURN( NULL );
+       LDAP_FREE( ha_buf );
+       return host;
 }
-#undef DO_RETURN   
-   
 #endif /* LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND || HAVE_TLS */
 
 
index 89d4278e185693a4ff8a97bf883f139f569d9e69..6ccb1f4bd7b7c75474dd4046e5014fec77d8df25 100644 (file)
@@ -13,7 +13,7 @@
 
 #include "portable.h"
 
-#ifdef LDAP_PF_UNIX
+#ifdef LDAP_PF_LOCAL
 
 #include <stdio.h>
 
@@ -65,7 +65,7 @@ ldap_pvt_ndelay_off(LDAP *ld, int fd)
 static ber_socket_t
 ldap_pvt_socket(LDAP *ld)
 {
-       ber_socket_t s = socket(AF_UNIX, SOCK_STREAM, 0);
+       ber_socket_t s = socket(PF_LOCAL, SOCK_STREAM, 0);
        oslocal_debug(ld, "ldap_new_socket: %d\n",s,0,0);
        return ( s );
 }
@@ -203,7 +203,7 @@ ldap_connect_to_path(LDAP *ld, Sockbuf *sb, const char *path, int async)
        oslocal_debug(ld, "ldap_connect_to_path: Trying %s\n", path, 0, 0);
 
        memset( &server, '\0', sizeof(server) );
-       server.sun_family = AF_UNIX;
+       server.sun_family = AF_LOCAL;
        strcpy( server.sun_path, path );
 
        rc = ldap_pvt_connect(ld, s, &server, async);
@@ -217,4 +217,4 @@ ldap_connect_to_path(LDAP *ld, Sockbuf *sb, const char *path, int async)
 }
 #else
 static int dummy;
-#endif /* LDAP_PF_UNIX */
+#endif /* LDAP_PF_LOCAL */
index 9336aa94174d7620fade24ab14e60fb0f07dbcfc..6a6d723356bdd161edc524303f995e1af03e9e7f 100644 (file)
@@ -105,7 +105,7 @@ ldap_parse_reference(
        }
 
        /* make a private copy of BerElement */
-       SAFEMEMCPY(&be, ref->lm_ber, sizeof(be));
+       AC_MEMCPY(&be, ref->lm_ber, sizeof(be));
        
        if ( ber_scanf( &be, "{v" /*}*/, &refs ) == LBER_ERROR ) {
                rc = LDAP_DECODING_ERROR;
index 8c348a1552fc8eaf944ce93735e6fa4afb6e9883..7ca2c675c9d7e787c2e68c2ea2c85b28d103dd5f 100644 (file)
@@ -256,9 +256,7 @@ ldap_new_connection( LDAP *ld, LDAPURLDesc *srvlist, int use_ldsb,
 
        if ( connect ) {
                for ( srv = srvlist; srv != NULL; srv = srv->lud_next ) {
-                       if ( open_ldap_connection( ld, lc->lconn_sb,
-                                       srv, &lc->lconn_krbinstance, 0 ) != -1 )
-                       {
+                       if ( ldap_int_open_connection( ld, lc, srv, 0 ) != -1 ) {
                                break;
                        }
                }
@@ -396,6 +394,8 @@ ldap_free_connection( LDAP *ld, LDAPConn *lc, int force, int unbind )
                        ber_free( lc->lconn_ber, 1 );
                }
 
+               ldap_int_sasl_close( ld, lc );
+
                prevlc = NULL;
                for ( tmplc = ld->ld_conns; tmplc != NULL;
                    tmplc = tmplc->lconn_next ) {
index a7dab4373aa21e5abf6331765451a0c68ffc89e6..a98f41e205d23f2dc5ca8d137760947c061c18ef 100644 (file)
@@ -27,6 +27,7 @@
 
 #include "portable.h"
 
+#include <stdlib.h>
 #include <stdio.h>
 
 #include <ac/socket.h>
@@ -345,367 +346,6 @@ ldap_parse_sasl_bind_result(
        return( ld->ld_errno );
 }
 
-#ifdef HAVE_CYRUS_SASL
-/*
-* Various Cyrus SASL related stuff.
-*/
-
-#define MAX_BUFF_SIZE  65536
-#define MIN_BUFF_SIZE  4096
-
-static char *
-array2str( char **a )
-{
-       char *s, **v, *p;
-       int len = 0;
-
-       for ( v = a; *v != NULL; v++ ) {
-               len += strlen( *v ) + 1; /* for a space */
-       }
-
-       if ( len == 0 ) {
-               return NULL;
-       }
-
-       s = LDAP_MALLOC ( len ); /* last space holds \0 */
-
-       if ( s == NULL ) {
-               return NULL;    
-       }
-
-       p = s;
-       for ( v = a; *v != NULL; v++ ) {
-               int len;
-
-               if ( v != a ) {
-                       strncpy( p, " ", 1 );
-                       ++p;
-               }
-               len = strlen( *v );
-               strncpy( p, *v, len );
-               p += len;
-       }
-
-       *p = '\0';
-
-       return s;
-}
-
-int ldap_pvt_sasl_init( void )
-{
-       /* XXX not threadsafe */
-       static int sasl_initialized = 0;
-
-       if ( sasl_initialized ) {
-               return 0;
-       }
-#ifndef CSRIMALLOC
-       sasl_set_alloc( ber_memalloc, ber_memcalloc, ber_memrealloc, ber_memfree );
-#endif /* CSRIMALLOC */
-
-       if ( sasl_client_init( NULL ) == SASL_OK ) {
-               sasl_initialized = 1;
-               return 0;
-       }
-
-       return -1;
-}
-
-/*
- * SASL encryption support for LBER Sockbufs
- */
-
-struct sb_sasl_data {
-       sasl_conn_t             *sasl_context;
-       Sockbuf_Buf             sec_buf_in;
-       Sockbuf_Buf             buf_in;
-       Sockbuf_Buf             buf_out;
-};
-
-static int
-sb_sasl_setup( Sockbuf_IO_Desc *sbiod, void *arg )
-{
-       struct sb_sasl_data     *p;
-
-       assert( sbiod != NULL );
-
-       p = LBER_MALLOC( sizeof( *p ) );
-       if ( p == NULL )
-               return -1;
-       p->sasl_context = (sasl_conn_t *)arg;
-       ber_pvt_sb_buf_init( &p->sec_buf_in );
-       ber_pvt_sb_buf_init( &p->buf_in );
-       ber_pvt_sb_buf_init( &p->buf_out );
-       if ( ber_pvt_sb_grow_buffer( &p->sec_buf_in, MIN_BUFF_SIZE ) < 0 ) {
-               errno = ENOMEM;
-               return -1;
-       }
-
-       sbiod->sbiod_pvt = p;
-
-       return 0;
-}
-
-static int
-sb_sasl_remove( Sockbuf_IO_Desc *sbiod )
-{
-       struct sb_sasl_data     *p;
-
-       assert( sbiod != NULL );
-       
-       p = (struct sb_sasl_data *)sbiod->sbiod_pvt;
-       ber_pvt_sb_buf_destroy( &p->sec_buf_in );
-       ber_pvt_sb_buf_destroy( &p->buf_in );
-       ber_pvt_sb_buf_destroy( &p->buf_out );
-       LBER_FREE( p );
-       sbiod->sbiod_pvt = NULL;
-       return 0;
-}
-
-static ber_len_t
-sb_sasl_pkt_length( const char *buf, int debuglevel )
-{
-       ber_len_t               size;
-       long                    tmp;
-
-       assert( buf != NULL );
-
-       tmp = *((long *)buf);
-       size = ntohl( tmp );
-   
-       if ( size > MAX_BUFF_SIZE ) {
-               /* somebody is trying to mess me up. */
-               ber_log_printf( LDAP_DEBUG_ANY, debuglevel,
-                       "sb_sasl_pkt_length: received illegal packet length "
-                       "of %lu bytes\n", (unsigned long)size );      
-               size = 16; /* this should lead to an error. */
-}
-
-       return size + 4; /* include the size !!! */
-}
-
-/* Drop a processed packet from the input buffer */
-static void
-sb_sasl_drop_packet ( Sockbuf_Buf *sec_buf_in, int debuglevel )
-{
-       ber_slen_t                      len;
-
-       len = sec_buf_in->buf_ptr - sec_buf_in->buf_end;
-       if ( len > 0 )
-               memmove( sec_buf_in->buf_base, sec_buf_in->buf_base +
-                       sec_buf_in->buf_end, len );
-   
-       if ( len >= 4 ) {
-               sec_buf_in->buf_end = sb_sasl_pkt_length( sec_buf_in->buf_base,
-                       debuglevel);
-       }
-       else {
-               sec_buf_in->buf_end = 0;
-       }
-       sec_buf_in->buf_ptr = len;
-}
-
-static ber_slen_t
-sb_sasl_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len)
-{
-       struct sb_sasl_data     *p;
-       ber_slen_t              ret, bufptr;
-   
-       assert( sbiod != NULL );
-       assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
-
-       p = (struct sb_sasl_data *)sbiod->sbiod_pvt;
-
-       /* Are there anything left in the buffer? */
-       ret = ber_pvt_sb_copy_out( &p->buf_in, buf, len );
-       bufptr = ret;
-       len -= ret;
-
-       if ( len == 0 )
-               return bufptr;
-
-       ber_pvt_sb_buf_destroy( &p->buf_in );
-
-       /* Read the length of the packet */
-       while ( p->sec_buf_in.buf_ptr < 4 ) {
-               ret = LBER_SBIOD_READ_NEXT( sbiod, p->sec_buf_in.buf_base,
-                       4 - p->sec_buf_in.buf_ptr );
-#ifdef EINTR
-               if ( ( ret < 0 ) && ( errno == EINTR ) )
-                       continue;
-#endif
-               if ( ret <= 0 )
-                       return ret;
-
-               p->sec_buf_in.buf_ptr += ret;
-       }
-
-       /* The new packet always starts at p->sec_buf_in.buf_base */
-       ret = sb_sasl_pkt_length( p->sec_buf_in.buf_base,
-               sbiod->sbiod_sb->sb_debug );
-
-       /* Grow the packet buffer if neccessary */
-       if ( ( p->sec_buf_in.buf_size < ret ) && 
-                       ber_pvt_sb_grow_buffer( &p->sec_buf_in, ret ) < 0 ) {
-               errno = ENOMEM;
-               return -1;
-       }
-       p->sec_buf_in.buf_end = ret;
-
-       /* Did we read the whole encrypted packet? */
-       while ( p->sec_buf_in.buf_ptr < p->sec_buf_in.buf_end ) {
-               /* No, we have got only a part of it */
-               ret = p->sec_buf_in.buf_end - p->sec_buf_in.buf_ptr;
-
-               ret = LBER_SBIOD_READ_NEXT( sbiod, p->sec_buf_in.buf_base +
-                       p->sec_buf_in.buf_ptr, ret );
-#ifdef EINTR
-               if ( ( ret < 0 ) && ( errno == EINTR ) )
-                       continue;
-#endif
-               if ( ret <= 0 )
-                       return ret;
-
-               p->sec_buf_in.buf_ptr += ret;
-       }
-
-       /* Decode the packet */
-       ret = sasl_decode( p->sasl_context, p->sec_buf_in.buf_base,
-               p->sec_buf_in.buf_end, &p->buf_in.buf_base,
-               (unsigned *)&p->buf_in.buf_end );
-       if ( ret != SASL_OK ) {
-               ber_log_printf( LDAP_DEBUG_ANY, sbiod->sbiod_sb->sb_debug,
-                       "sb_sasl_read: failed to decode packet: %s\n",
-                       sasl_errstring( ret, NULL, NULL ) );
-               sb_sasl_drop_packet( &p->sec_buf_in,
-                       sbiod->sbiod_sb->sb_debug );
-               errno = EIO;
-               return -1;
-       }
-       
-       /* Drop the packet from the input buffer */
-       sb_sasl_drop_packet( &p->sec_buf_in, sbiod->sbiod_sb->sb_debug );
-
-       p->buf_in.buf_size = p->buf_in.buf_end;
-
-       bufptr += ber_pvt_sb_copy_out( &p->buf_in, (char*) buf + bufptr, len );
-
-       return bufptr;
-}
-
-static ber_slen_t
-sb_sasl_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len)
-{
-       struct sb_sasl_data     *p;
-       int                     ret;
-
-       assert( sbiod != NULL );
-       assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
-
-       p = (struct sb_sasl_data *)sbiod->sbiod_pvt;
-
-       /* Are there anything left in the buffer? */
-       if ( p->buf_out.buf_ptr != p->buf_out.buf_end ) {
-               ret = ber_pvt_sb_do_write( sbiod, &p->buf_out );
-               if ( ret <= 0 )
-                       return ret;
-       }
-
-       /* now encode the next packet. */
-       ber_pvt_sb_buf_destroy( &p->buf_out );
-       ret = sasl_encode( p->sasl_context, buf, len, &p->buf_out.buf_base,
-               (unsigned *)&p->buf_out.buf_size );
-       if ( ret != SASL_OK ) {
-               ber_log_printf( LDAP_DEBUG_ANY, sbiod->sbiod_sb->sb_debug,
-                       "sb_sasl_write: failed to encode packet: %s\n",
-                       sasl_errstring( ret, NULL, NULL ) );
-               return -1;
-       }
-       p->buf_out.buf_end = p->buf_out.buf_size;
-
-       ret = ber_pvt_sb_do_write( sbiod, &p->buf_out );
-       if ( ret <= 0 )
-               return ret;
-       return len;
-}
-
-static int
-sb_sasl_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg )
-{
-       struct sb_sasl_data     *p;
-
-       p = (struct sb_sasl_data *)sbiod->sbiod_pvt;
-
-       if ( opt == LBER_SB_OPT_DATA_READY ) {
-               if ( p->buf_in.buf_ptr != p->buf_in.buf_end )
-                       return 1;
-       }
-       
-       return LBER_SBIOD_CTRL_NEXT( sbiod, opt, arg );
-}
-
-Sockbuf_IO ldap_pvt_sockbuf_io_sasl =
-{
-       sb_sasl_setup,          /* sbi_setup */
-       sb_sasl_remove,         /* sbi_remove */
-       sb_sasl_ctrl,           /* sbi_ctrl */
-       sb_sasl_read,           /* sbi_read */
-       sb_sasl_write,          /* sbi_write */
-       NULL                    /* sbi_close */
-};
-
-int ldap_pvt_sasl_install( Sockbuf *sb, void *ctx_arg )
-{
-       /* don't install the stuff unless security has been negotiated */
-
-       if ( !ber_sockbuf_ctrl( sb, LBER_SB_OPT_HAS_IO,
-                       &ldap_pvt_sockbuf_io_sasl ) )
-               ber_sockbuf_add_io( sb, &ldap_pvt_sockbuf_io_sasl,
-                       LBER_SBIOD_LEVEL_APPLICATION, ctx_arg );
-
-       return LDAP_SUCCESS;
-}
-
-static int
-sasl_err2ldap( int saslerr )
-{
-       int rc;
-
-       switch (saslerr) {
-               case SASL_CONTINUE:
-                       rc = LDAP_MORE_RESULTS_TO_RETURN;
-                       break;
-               case SASL_OK:
-                       rc = LDAP_SUCCESS;
-                       break;
-               case SASL_FAIL:
-                       rc = LDAP_LOCAL_ERROR;
-                       break;
-               case SASL_NOMEM:
-                       rc = LDAP_NO_MEMORY;
-                       break;
-               case SASL_NOMECH:
-                       rc = LDAP_AUTH_UNKNOWN;
-                       break;
-               case SASL_BADAUTH:
-                       rc = LDAP_AUTH_UNKNOWN;
-                       break;
-               case SASL_NOAUTHZ:
-                       rc = LDAP_PARAM_ERROR;
-                       break;
-               case SASL_TOOWEAK:
-               case SASL_ENCRYPT:
-                       rc = LDAP_AUTH_UNKNOWN;
-                       break;
-               default:
-                       rc = LDAP_LOCAL_ERROR;
-                       break;
-       }
-
-       assert( rc == LDAP_SUCCESS || LDAP_API_ERROR( rc ) );
-       return rc;
-}
-
 int
 ldap_pvt_sasl_getmechs ( LDAP *ld, char **pmechlist )
 {
@@ -739,7 +379,7 @@ ldap_pvt_sasl_getmechs ( LDAP *ld, char **pmechlist )
                return ld->ld_errno;
        }
 
-       mechlist = array2str( values );
+       mechlist = ldap_charray2str( values, " " );
        if ( mechlist == NULL ) {
                ld->ld_errno = LDAP_NO_MEMORY;
                LDAP_VFREE( values );
@@ -755,361 +395,51 @@ ldap_pvt_sasl_getmechs ( LDAP *ld, char **pmechlist )
        return LDAP_SUCCESS;
 }
 
-int
-ldap_pvt_sasl_bind(
-       LDAP                    *ld,
-       LDAP_CONST char         *dn,
-       LDAP_CONST char         *mechs,
-       LDAP_CONST sasl_callback_t      *callbacks,
-       LDAPControl             **sctrls,
-       LDAPControl             **cctrls )
-{
-       const char *mech;
-       int                     saslrc, rc;
-       sasl_ssf_t              *ssf = NULL;
-       unsigned credlen;
-       struct berval ccred, *scred;
-       char *host;
-       sasl_interact_t *client_interact = NULL;
-       struct sockaddr_in      sin;
-       socklen_t               len;
-       sasl_security_properties_t      secprops;
-       ber_socket_t            sd;
-
-       Debug( LDAP_DEBUG_TRACE, "ldap_pvt_sasl_bind\n", 0, 0, 0 );
-
-       /* do a quick !LDAPv3 check... ldap_sasl_bind will do the rest. */
-       if (ld->ld_version < LDAP_VERSION3) {
-               ld->ld_errno = LDAP_NOT_SUPPORTED;
-               return ld->ld_errno;
-       }
-
-       ber_sockbuf_ctrl( ld->ld_sb, LBER_SB_OPT_GET_FD, &sd );
-
-       if ( sd == AC_SOCKET_INVALID ) {
-               /* not connected yet */
-               int rc = ldap_open_defconn( ld );
-  
-               if( rc < 0 ) return ld->ld_errno;
-               ber_sockbuf_ctrl( ld->ld_sb, LBER_SB_OPT_GET_FD, &sd );
-       }   
-
-       /* XXX this doesn't work with PF_LOCAL hosts */
-       host = ldap_host_connected_to( ld->ld_sb );
-
-       if ( host == NULL ) {
-               ld->ld_errno = LDAP_UNAVAILABLE;
-               return ld->ld_errno;
-       }
-
-       if ( ld->ld_sasl_context != NULL ) {
-               sasl_dispose( &ld->ld_sasl_context );
-       }
-
-       saslrc = sasl_client_new( "ldap", host, callbacks, SASL_SECURITY_LAYER,
-               &ld->ld_sasl_context );
-
-       LDAP_FREE( host );
-
-       if ( (saslrc != SASL_OK) && (saslrc != SASL_CONTINUE) ) {
-               ld->ld_errno = sasl_err2ldap( saslrc );
-               sasl_dispose( &ld->ld_sasl_context );
-               return ld->ld_errno;
-       }
-
-       len = sizeof( sin );
-       if ( getpeername( sd, (struct sockaddr *)&sin, &len ) == -1 ) {
-               Debug( LDAP_DEBUG_ANY, "SASL: can't query remote IP.\n",
-                       0, 0, 0 );
-               ld->ld_errno = LDAP_OPERATIONS_ERROR;
-               return ld->ld_errno;
-       }
-       sasl_setprop( ld->ld_sasl_context, SASL_IP_REMOTE, &sin );
-
-       len = sizeof( sin );
-       if ( getsockname( sd, (struct sockaddr *)&sin, &len ) == -1 ) {
-               Debug( LDAP_DEBUG_ANY, "SASL: can't query local IP.\n",
-                       0, 0, 0 );
-               ld->ld_errno = LDAP_OPERATIONS_ERROR;
-               return ld->ld_errno;
-       }
-       sasl_setprop( ld->ld_sasl_context, SASL_IP_LOCAL, &sin );
-
-       memset( &secprops, '\0', sizeof( secprops ) );
-       secprops.min_ssf = ld->ld_options.ldo_sasl_minssf;
-       secprops.max_ssf = ld->ld_options.ldo_sasl_maxssf;
-       secprops.security_flags = SASL_SECURITY_LAYER;
-       secprops.maxbufsize = 65536;
-       sasl_setprop( ld->ld_sasl_context, SASL_SEC_PROPS, &secprops );
-
-       ccred.bv_val = NULL;
-       ccred.bv_len = 0;
-
-       saslrc = sasl_client_start( ld->ld_sasl_context,
-               mechs,
-               NULL,
-               &client_interact,
-               &ccred.bv_val,
-               &credlen,
-               &mech );
-
-       ccred.bv_len = credlen;
-
-       if ( (saslrc != SASL_OK) && (saslrc != SASL_CONTINUE) ) {
-               ld->ld_errno = sasl_err2ldap( saslrc );
-               sasl_dispose( &ld->ld_sasl_context );
-               return ld->ld_errno;
-       }
-
-       scred = NULL;
-
-       do {
-               unsigned credlen;
-               sasl_interact_t *client_interact = NULL;
-
-               rc = ldap_sasl_bind_s( ld, dn, mech, &ccred, sctrls, cctrls, &scred );
-               if ( rc == LDAP_SUCCESS ) {
-                       break;
-               } else if ( rc != LDAP_SASL_BIND_IN_PROGRESS ) {
-                       if ( ccred.bv_val != NULL ) {
-                               LDAP_FREE( ccred.bv_val );
-                       }
-                       sasl_dispose( &ld->ld_sasl_context );
-                       return ld->ld_errno;
-               }
-
-               if ( ccred.bv_val != NULL ) {
-                       LDAP_FREE( ccred.bv_val );
-                       ccred.bv_val = NULL;
-               }
-
-               saslrc = sasl_client_step( ld->ld_sasl_context,
-                       (scred == NULL) ? NULL : scred->bv_val,
-                       (scred == NULL) ? 0 : scred->bv_len,
-                       &client_interact,
-                       &ccred.bv_val,
-                       &credlen );
-
-               ccred.bv_len = credlen;
-               ber_bvfree( scred );
-
-               if ( (saslrc != SASL_OK) && (saslrc != SASL_CONTINUE) ) {
-                       ld->ld_errno = sasl_err2ldap( saslrc );
-                       sasl_dispose( &ld->ld_sasl_context );
-                       return ld->ld_errno;
-               }
-       } while ( rc == LDAP_SASL_BIND_IN_PROGRESS );
-
-       assert ( rc == LDAP_SUCCESS );
-
-       if ( sasl_getprop( ld->ld_sasl_context, SASL_SSF, (void **)&ssf )
-               == SASL_OK && ssf && *ssf ) {
-               ldap_pvt_sasl_install( ld->ld_sb, ld->ld_sasl_context );
-       }
-
-       return rc;
-}
-
-/* based on sample/sample-client.c */
-static int
-ldap_pvt_sasl_getsecret(sasl_conn_t *conn,
-       void *context, int id, sasl_secret_t **psecret)
-{
-       struct berval *passphrase = (struct berval *)context;
-       size_t len;           
-
-       if ( conn == NULL || psecret == NULL || id != SASL_CB_PASS ) {
-               return SASL_BADPARAM;
-       }
-
-       len = (passphrase != NULL) ? (size_t)passphrase->bv_len: 0;
-
-       *psecret = (sasl_secret_t *) LDAP_MALLOC( sizeof( sasl_secret_t ) + len );
-       if ( *psecret == NULL ) {
-               return SASL_NOMEM;
-       }
-
-       (*psecret)->len = passphrase->bv_len;
-
-       if ( passphrase != NULL ) {
-               memcpy((*psecret)->data, passphrase->bv_val, len);
-       }
-
-       return SASL_OK;
-}
-
-static int
-ldap_pvt_sasl_getsimple(void *context, int id, const char **result, int *len)
-{
-       const char *value = (const char *)context;
-
-       if ( result == NULL ) {
-               return SASL_BADPARAM;
-       }
-
-       switch ( id ) {
-               case SASL_CB_USER:
-               case SASL_CB_AUTHNAME:
-                       *result = value;
-                       if ( len )
-                               *len = value ? strlen( value ) : 0;
-                       break;
-               case SASL_CB_LANGUAGE:
-                       *result = NULL;
-                       if ( len )
-                               *len = 0;
-                       break;
-               default:
-                       return SASL_BADPARAM;
-       }
-
-       return SASL_OK;
-}
-
-int
-ldap_pvt_sasl_get_option( LDAP *ld, int option, void *arg )
-{
-       sasl_ssf_t      *ssf;
-       
-       if ( ld == NULL )
-               return -1;
-
-       switch ( option ) {
-               case LDAP_OPT_X_SASL_MINSSF:
-                       *(int *)arg = ld->ld_options.ldo_sasl_minssf;
-                       break;
-               case LDAP_OPT_X_SASL_MAXSSF:
-                       *(int *)arg = ld->ld_options.ldo_sasl_maxssf;
-                       break;
-               case LDAP_OPT_X_SASL_ACTSSF:
-                       if ( ld->ld_sasl_context == NULL ) {
-                               *(int *)arg = -1;
-                               break;
-                       }
-                       if ( sasl_getprop( ld->ld_sasl_context, SASL_SSF,
-                               (void **) &ssf ) != SASL_OK )
-                       {
-                               return -1;
-                       }
-                       *(int *)arg = *ssf;
-                       break;
-               default:
-                       return -1;
-       }
-       return 0;
-}
-
-int
-ldap_pvt_sasl_set_option( LDAP *ld, int option, void *arg )
-{
-       if ( ld == NULL )
-               return -1;
-
-       switch ( option ) {
-               case LDAP_OPT_X_SASL_MINSSF:
-                       ld->ld_options.ldo_sasl_minssf = *(int *)arg;
-                       break;
-               case LDAP_OPT_X_SASL_MAXSSF:
-                       ld->ld_options.ldo_sasl_maxssf = *(int *)arg;
-                       break;
-               case LDAP_OPT_X_SASL_ACTSSF:
-                       /* This option is read-only */
-               default:
-                       return -1;
-       }
-       return 0;
-}
-
 /*
- * ldap_negotiated_sasl_bind_s - bind to the ldap server (and X.500)
- * using SASL authentication.
+ * ldap_sasl_interactive_bind_s - interactive SASL authentication
  *
- * This routine attempts to authenticate the user referred by the
- * authentication id using the provided password.  An optional
- * authorization identity may be provided.  An DN is generally not
- * provided [see AuthMethod].
+ * This routine uses interactive callbacks.
  *
- * If the mechanism negotiated does not require a password, the
- * passwd field is ignored.  [A callback mechanism should really
- * be used].
- * 
  * LDAP_SUCCESS is returned upon success, the ldap error code
  * otherwise.
- *
- * Examples:
- *     ldap_negotiated_sasl_bind_s( ld, NULL,
- *         NULL, NULL, NULL,
- *             NULL, NULL, NULL, NULL );
- *
- *     ldap_negotiated_sasl_bind_s( ld, NULL,
- *         "user@OPENLDAP.ORG", NULL, NULL,
- *             "GSSAPI", NULL, NULL, NULL );
- *
- *     ldap_negotiated_sasl_bind_s( ld, NULL,
- *         "manager", "dn:cn=user,dc=openldap,dc=org", NULL,
- *             "DIGEST-MD5", NULL, NULL, NULL );
- *
- *     ldap_negotiated_sasl_bind_s( ld, NULL,
- *         "root@OPENLDAP.ORG", "u:user@OPENLDAP.ORG", NULL,
- *             "GSSAPI", NULL, NULL, NULL );
- *
- *     ldap_negotiated_sasl_bind_s( ld, NULL,
- *         "manager", "dn:cn=user,dc=openldap,dc=org", NULL,
- *             "DIGEST-MD5", NULL, NULL, NULL );
  */
 int
-ldap_negotiated_sasl_bind_s(
+ldap_sasl_interactive_bind_s(
        LDAP *ld,
        LDAP_CONST char *dn, /* usually NULL */
-       LDAP_CONST char *authenticationId,
-       LDAP_CONST char *authorizationId, /* commonly NULL */
-       LDAP_CONST char *saslMechanism,
-       struct berval *passPhrase,
+       LDAP_CONST char *mechs,
        LDAPControl **serverControls,
-       LDAPControl **clientControls)
+       LDAPControl **clientControls,
+       unsigned flags,
+       LDAP_SASL_INTERACT_PROC *interact,
+       void *defaults )
 {
-       int n;
-       sasl_callback_t callbacks[4];
        int rc;
 
-       Debug( LDAP_DEBUG_TRACE, "ldap_negotiated_sasl_bind_s\n", 0, 0, 0 );
+       if( mechs == NULL || *mechs == '\0' ) {
+               char *smechs;
 
-       if( saslMechanism == NULL || *saslMechanism == '\0' ) {
-               char *mechs;
-               rc = ldap_pvt_sasl_getmechs( ld, &mechs );
+               rc = ldap_pvt_sasl_getmechs( ld, &smechs );
 
                if( rc != LDAP_SUCCESS ) {
                        return rc;
                }
 
-               saslMechanism = mechs;
-       }
+               Debug( LDAP_DEBUG_TRACE,
+                       "ldap_interactive_sasl_bind_s: server supports: %s\n",
+                       smechs, 0, 0 );
 
-       /* SASL Authentication Identity */
-       callbacks[n=0].id = SASL_CB_AUTHNAME;
-       callbacks[n].proc = ldap_pvt_sasl_getsimple;
-       callbacks[n].context = (void *)authenticationId;
+               mechs = smechs;
 
-       /* SASL Authorization Identity (userid) */
-       if( authorizationId != NULL ) {
-               callbacks[++n].id = SASL_CB_USER;
-               callbacks[n].proc = ldap_pvt_sasl_getsimple;
-               callbacks[n].context = (void *)authorizationId;
+       } else {
+               Debug( LDAP_DEBUG_TRACE,
+                       "ldap_interactive_sasl_bind_s: user selected: %s\n",
+                       mechs, 0, 0 );
        }
 
-       callbacks[++n].id = SASL_CB_PASS;
-       callbacks[n].proc = ldap_pvt_sasl_getsecret;
-       callbacks[n].context = (void *)passPhrase;
-
-       callbacks[++n].id = SASL_CB_LIST_END;
-       callbacks[n].proc = NULL;
-       callbacks[n].context = NULL;
-
-       assert( n * sizeof(sasl_callback_t) < sizeof(callbacks) );
-
-       rc = ldap_pvt_sasl_bind(ld, dn, saslMechanism, callbacks,
-               serverControls, clientControls);
+       rc = ldap_int_sasl_bind( ld, dn, mechs,
+               serverControls, clientControls,
+               flags, interact, defaults );
 
        return rc;
 }
-#endif /* HAVE_CYRUS_SASL */
index a8f85951baf67c7647756cd37bfdc2625cc829ac..47f873db8ac70f337081571c05edf95e79e9d0b3 100644 (file)
@@ -27,25 +27,25 @@ choose_name( char *names[], LDAP_CONST char *fallback )
 }
 
 LDAP_CONST char *
-ldap_syntax2name( LDAP_SYNTAX * syn )
+ldap_syntax2name( LDAPSyntax * syn )
 {
        return( syn->syn_oid );
 }
 
 LDAP_CONST char *
-ldap_matchingrule2name( LDAP_MATCHING_RULE * mr )
+ldap_matchingrule2name( LDAPMatchingRule * mr )
 {
        return( choose_name( mr->mr_names, mr->mr_oid ) );
 }
 
 LDAP_CONST char *
-ldap_attributetype2name( LDAP_ATTRIBUTE_TYPE * at )
+ldap_attributetype2name( LDAPAttributeType * at )
 {
        return( choose_name( at->at_names, at->at_oid ) );
 }
 
 LDAP_CONST char *
-ldap_objectclass2name( LDAP_OBJECT_CLASS * oc )
+ldap_objectclass2name( LDAPObjectClass * oc )
 {
        return( choose_name( oc->oc_names, oc->oc_oid ) );
 }
@@ -267,9 +267,9 @@ print_noidlen(safe_string *ss, char *s, int l)
 }
 
 static int
-print_extensions(safe_string *ss, LDAP_SCHEMA_EXTENSION_ITEM **extensions)
+print_extensions(safe_string *ss, LDAPSchemaExtensionItem **extensions)
 {
-       LDAP_SCHEMA_EXTENSION_ITEM **ext;
+       LDAPSchemaExtensionItem **ext;
 
        if ( extensions ) {
                print_whsp(ss);
@@ -286,7 +286,7 @@ print_extensions(safe_string *ss, LDAP_SCHEMA_EXTENSION_ITEM **extensions)
 }
 
 char *
-ldap_syntax2str( const LDAP_SYNTAX * syn )
+ldap_syntax2str( const LDAPSyntax * syn )
 {
        safe_string * ss;
        char * retstring;
@@ -318,7 +318,7 @@ ldap_syntax2str( const LDAP_SYNTAX * syn )
 }
 
 char *
-ldap_matchingrule2str( const LDAP_MATCHING_RULE * mr )
+ldap_matchingrule2str( const LDAPMatchingRule * mr )
 {
        safe_string * ss;
        char * retstring;
@@ -367,7 +367,7 @@ ldap_matchingrule2str( const LDAP_MATCHING_RULE * mr )
 }
 
 char *
-ldap_objectclass2str( const LDAP_OBJECT_CLASS * oc )
+ldap_objectclass2str( const LDAPObjectClass * oc )
 {
        safe_string * ss;
        char * retstring;
@@ -446,7 +446,7 @@ ldap_objectclass2str( const LDAP_OBJECT_CLASS * oc )
 }
 
 char *
-ldap_attributetype2str( const LDAP_ATTRIBUTE_TYPE * at )
+ldap_attributetype2str( const LDAPAttributeType * at )
 {
        safe_string * ss;
        char * retstring;
@@ -966,13 +966,13 @@ parse_oids(const char **sp, int *code, const int allow_quoted)
 }
 
 static int
-add_extension(LDAP_SCHEMA_EXTENSION_ITEM ***extensions,
+add_extension(LDAPSchemaExtensionItem ***extensions,
              char * name, char ** values)
 {
        int n;
-       LDAP_SCHEMA_EXTENSION_ITEM **tmp, *ext;
+       LDAPSchemaExtensionItem **tmp, *ext;
 
-       ext = LDAP_CALLOC(1, sizeof(LDAP_SCHEMA_EXTENSION_ITEM));
+       ext = LDAP_CALLOC(1, sizeof(LDAPSchemaExtensionItem));
        if ( !ext )
                return 1;
        ext->lsei_name = name;
@@ -980,7 +980,7 @@ add_extension(LDAP_SCHEMA_EXTENSION_ITEM ***extensions,
 
        if ( !*extensions ) {
                *extensions =
-                 LDAP_CALLOC(2, sizeof(LDAP_SCHEMA_EXTENSION_ITEM *));
+                 LDAP_CALLOC(2, sizeof(LDAPSchemaExtensionItem *));
                if ( !*extensions )
                  return 1;
                n = 0;
@@ -988,7 +988,7 @@ add_extension(LDAP_SCHEMA_EXTENSION_ITEM ***extensions,
                for ( n=0; (*extensions)[n] != NULL; n++ )
                        ;
                tmp = LDAP_REALLOC(*extensions,
-                                  (n+2)*sizeof(LDAP_SCHEMA_EXTENSION_ITEM *));
+                                  (n+2)*sizeof(LDAPSchemaExtensionItem *));
                if ( !tmp )
                        return 1;
                *extensions = tmp;
@@ -999,9 +999,9 @@ add_extension(LDAP_SCHEMA_EXTENSION_ITEM ***extensions,
 }
 
 static void
-free_extensions(LDAP_SCHEMA_EXTENSION_ITEM **extensions)
+free_extensions(LDAPSchemaExtensionItem **extensions)
 {
-       LDAP_SCHEMA_EXTENSION_ITEM **ext;
+       LDAPSchemaExtensionItem **ext;
 
        if ( extensions ) {
                for ( ext = extensions; *ext != NULL; ext++ ) {
@@ -1014,15 +1014,16 @@ free_extensions(LDAP_SCHEMA_EXTENSION_ITEM **extensions)
 }
 
 void
-ldap_syntax_free( LDAP_SYNTAX * syn )
+ldap_syntax_free( LDAPSyntax * syn )
 {
        LDAP_FREE(syn->syn_oid);
+       LDAP_VFREE(syn->syn_names);
        LDAP_FREE(syn->syn_desc);
        free_extensions(syn->syn_extensions);
        LDAP_FREE(syn);
 }
 
-LDAP_SYNTAX *
+LDAPSyntax *
 ldap_str2syntax( const char * s, int * code, const char ** errp, const int flags )
 {
        int kind;
@@ -1030,7 +1031,7 @@ ldap_str2syntax( const char * s, int * code, const char ** errp, const int flags
        char * sval;
        int seen_name = 0;
        int seen_desc = 0;
-       LDAP_SYNTAX * syn;
+       LDAPSyntax * syn;
        char ** ext_vals;
 
        if ( !s ) {
@@ -1040,7 +1041,7 @@ ldap_str2syntax( const char * s, int * code, const char ** errp, const int flags
        }
 
        *errp = s;
-       syn = LDAP_CALLOC(1,sizeof(LDAP_SYNTAX));
+       syn = LDAP_CALLOC(1,sizeof(LDAPSyntax));
 
        if ( !syn ) {
                *code = LDAP_SCHERR_OUTOFMEM;
@@ -1151,7 +1152,7 @@ ldap_str2syntax( const char * s, int * code, const char ** errp, const int flags
 }
 
 void
-ldap_matchingrule_free( LDAP_MATCHING_RULE * mr )
+ldap_matchingrule_free( LDAPMatchingRule * mr )
 {
        LDAP_FREE(mr->mr_oid);
        LDAP_VFREE(mr->mr_names);
@@ -1161,7 +1162,7 @@ ldap_matchingrule_free( LDAP_MATCHING_RULE * mr )
        LDAP_FREE(mr);
 }
 
-LDAP_MATCHING_RULE *
+LDAPMatchingRule *
 ldap_str2matchingrule( const char * s, int * code, const char ** errp, const int flags )
 {
        int kind;
@@ -1171,7 +1172,7 @@ ldap_str2matchingrule( const char * s, int * code, const char ** errp, const int
        int seen_desc = 0;
        int seen_obsolete = 0;
        int seen_syntax = 0;
-       LDAP_MATCHING_RULE * mr;
+       LDAPMatchingRule * mr;
        char ** ext_vals;
        const char * savepos;
 
@@ -1182,7 +1183,7 @@ ldap_str2matchingrule( const char * s, int * code, const char ** errp, const int
        }
 
        *errp = s;
-       mr = LDAP_CALLOC(1,sizeof(LDAP_MATCHING_RULE));
+       mr = LDAP_CALLOC(1,sizeof(LDAPMatchingRule));
 
        if ( !mr ) {
                *code = LDAP_SCHERR_OUTOFMEM;
@@ -1342,7 +1343,7 @@ ldap_str2matchingrule( const char * s, int * code, const char ** errp, const int
 }
 
 void
-ldap_attributetype_free(LDAP_ATTRIBUTE_TYPE * at)
+ldap_attributetype_free(LDAPAttributeType * at)
 {
        LDAP_FREE(at->at_oid);
        LDAP_VFREE(at->at_names);
@@ -1356,7 +1357,7 @@ ldap_attributetype_free(LDAP_ATTRIBUTE_TYPE * at)
        LDAP_FREE(at);
 }
 
-LDAP_ATTRIBUTE_TYPE *
+LDAPAttributeType *
 ldap_str2attributetype( const char * s, int * code, const char ** errp, const int flags )
 {
        int kind;
@@ -1371,7 +1372,7 @@ ldap_str2attributetype( const char * s, int * code, const char ** errp, const in
        int seen_substr = 0;
        int seen_syntax = 0;
        int seen_usage = 0;
-       LDAP_ATTRIBUTE_TYPE * at;
+       LDAPAttributeType * at;
        char ** ext_vals;
        const char * savepos;
 
@@ -1382,7 +1383,7 @@ ldap_str2attributetype( const char * s, int * code, const char ** errp, const in
        }
 
        *errp = s;
-       at = LDAP_CALLOC(1,sizeof(LDAP_ATTRIBUTE_TYPE));
+       at = LDAP_CALLOC(1,sizeof(LDAPAttributeType));
 
        if ( !at ) {
                *code = LDAP_SCHERR_OUTOFMEM;
@@ -1689,7 +1690,7 @@ ldap_str2attributetype( const char * s, int * code, const char ** errp, const in
 }
 
 void
-ldap_objectclass_free(LDAP_OBJECT_CLASS * oc)
+ldap_objectclass_free(LDAPObjectClass * oc)
 {
        LDAP_FREE(oc->oc_oid);
        LDAP_VFREE(oc->oc_names);
@@ -1701,7 +1702,7 @@ ldap_objectclass_free(LDAP_OBJECT_CLASS * oc)
        LDAP_FREE(oc);
 }
 
-LDAP_OBJECT_CLASS *
+LDAPObjectClass *
 ldap_str2objectclass( const char * s, int * code, const char ** errp, const int flags )
 {
        int kind;
@@ -1714,7 +1715,7 @@ ldap_str2objectclass( const char * s, int * code, const char ** errp, const int
        int seen_kind = 0;
        int seen_must = 0;
        int seen_may = 0;
-       LDAP_OBJECT_CLASS * oc;
+       LDAPObjectClass * oc;
        char ** ext_vals;
        const char * savepos;
 
@@ -1725,7 +1726,7 @@ ldap_str2objectclass( const char * s, int * code, const char ** errp, const int
        }
 
        *errp = s;
-       oc = LDAP_CALLOC(1,sizeof(LDAP_OBJECT_CLASS));
+       oc = LDAP_CALLOC(1,sizeof(LDAPObjectClass));
 
        if ( !oc ) {
                *code = LDAP_SCHERR_OUTOFMEM;
index c1374a2c4c7256e0ea9cf3c7272e0f29493efb5c..69aafa1048442ef723d429d5560d8460faefca34 100644 (file)
@@ -327,7 +327,7 @@ ldap_create_sort_control (
        tag = ber_printf(ber, /*{*/ "N}");
        if( tag == LBER_ERROR ) goto exit;
 
-       ld->ld_errno = ldap_int_create_control( LDAP_CONTROL_SORTREQUEST,
+       ld->ld_errno = ldap_create_control( LDAP_CONTROL_SORTREQUEST,
                ber, isCritical, ctrlp);
 
        ber_free(ber, 1);
index 9e49d641976e17d49c5d9af47633c66115b3547c..f31c95239bdbfa64d7db84207916652fb5e09573 100644 (file)
@@ -29,6 +29,7 @@
 #include <openssl/ssl.h>
 #include <openssl/x509v3.h>
 #include <openssl/err.h>
+#include <openssl/rand.h>
 #elif defined( HAVE_SSL_H )
 #include <ssl.h>
 #endif
@@ -40,6 +41,7 @@ static char *tls_opt_cacertfile = NULL;
 static char *tls_opt_cacertdir = NULL;
 static int  tls_opt_require_cert = 0;
 static char *tls_opt_ciphersuite = NULL;
+static char *tls_opt_randfile = NULL;
 
 #define HAS_TLS( sb )  ber_sockbuf_ctrl( sb, LBER_SB_OPT_HAS_IO, \
                                (void *)&ldap_pvt_sockbuf_io_tls )
@@ -57,6 +59,8 @@ static DH * tls_tmp_dh_cb( SSL *ssl, int is_export, int key_length );
 
 static SSL_CTX *tls_def_ctx = NULL;
 
+static int tls_seed_PRNG( const char *randfile );
+
 #ifdef LDAP_R_COMPILE
 /*
  * provide mutexes for the SSLeay library.
@@ -100,8 +104,10 @@ ldap_pvt_tls_init( void )
 {
        static int tls_initialized = 0;
 
-       if ( tls_initialized )
-               return 0;
+       if ( tls_initialized ) return 0;
+
+       (void) tls_seed_PRNG( tls_opt_randfile );
+
        tls_initialized = 1;
 #ifdef LDAP_R_COMPILE
        tls_init_threads();
@@ -622,6 +628,7 @@ ldap_pvt_tls_accept( Sockbuf *sb, void *ctx_arg )
 #endif
                return -1;
        }
+
        return 0;
 }
 
@@ -664,7 +671,7 @@ ldap_pvt_tls_get_peer_issuer( LDAP *ld )
 }
 
 int
-ldap_pvt_tls_config( struct ldapoptions *lo, int option, const char *arg )
+ldap_int_tls_config( struct ldapoptions *lo, int option, const char *arg )
 {
        int i;
 
@@ -673,6 +680,7 @@ ldap_pvt_tls_config( struct ldapoptions *lo, int option, const char *arg )
        case LDAP_OPT_X_TLS_CACERTDIR:
        case LDAP_OPT_X_TLS_CERTFILE:
        case LDAP_OPT_X_TLS_KEYFILE:
+       case LDAP_OPT_X_TLS_RANDOM_FILE:
                return ldap_pvt_tls_set_option( NULL, option, (void *) arg );
        case LDAP_OPT_X_TLS_REQUIRE_CERT:
                i = ( ( strcasecmp( arg, "on" ) == 0 ) ||
@@ -694,9 +702,9 @@ ldap_pvt_tls_config( struct ldapoptions *lo, int option, const char *arg )
                if (i >= 0)
                        return ldap_pvt_tls_set_option( lo, option, &i );
                return -1;
-       default:
-               return -1;
        }
+
+       return -1;
 }
 
 int
@@ -731,6 +739,9 @@ ldap_pvt_tls_get_option( struct ldapoptions *lo, int option, void *arg )
        case LDAP_OPT_X_TLS_REQUIRE_CERT:
                *(int *)arg = tls_opt_require_cert;
                break;
+       case LDAP_OPT_X_TLS_RANDOM_FILE:
+               *(char **)arg = tls_opt_randfile;
+               break;
        default:
                return -1;
        }
@@ -794,6 +805,10 @@ ldap_pvt_tls_set_option( struct ldapoptions *lo, int option, void *arg )
                if ( tls_opt_ciphersuite ) free( tls_opt_ciphersuite );
                tls_opt_ciphersuite = arg ? LDAP_STRDUP( (char *) arg ) : NULL;
                break;
+       case LDAP_OPT_X_TLS_RANDOM_FILE:
+               if (tls_opt_randfile ) free (tls_opt_randfile );
+               tls_opt_randfile = arg ? LDAP_STRDUP( (char *) arg ) : NULL;
+               break;
        default:
                return -1;
        }
@@ -803,6 +818,9 @@ ldap_pvt_tls_set_option( struct ldapoptions *lo, int option, void *arg )
 int
 ldap_pvt_tls_start ( LDAP *ld, Sockbuf *sb, void *ctx_arg )
 {
+       /* Make sure tls is initialized, including PRNG properly seeded. */
+       ldap_pvt_tls_init();
+
        /*
         * Fortunately, the lib uses blocking io...
         */
@@ -919,13 +937,57 @@ tls_tmp_rsa_cb( SSL *ssl, int is_export, int key_length )
        tmp_rsa = RSA_generate_key( key_length, RSA_F4, NULL, NULL );
 
        if ( !tmp_rsa ) {
-               Debug( LDAP_DEBUG_ANY, "TLS: Failed to generate temporary %d-bit %s RSA key\n",
-                      key_length, is_export ? "export" : "domestic", 0 );
+               Debug( LDAP_DEBUG_ANY,
+                       "TLS: Failed to generate temporary %d-bit %s RSA key\n",
+                       key_length, is_export ? "export" : "domestic", 0 );
                return NULL;
        }
        return tmp_rsa;
 }
 
+static int
+tls_seed_PRNG( const char *randfile )
+{
+#ifndef URANDOM_DEVICE
+       /* no /dev/urandom (or equiv) */
+
+       char buffer[1024];
+       static int egdsocket = 0;
+
+       if (randfile == NULL) {
+               /* The seed file is $RANDFILE if defined, otherwise $HOME/.rnd.
+                * If $HOME is not set or buffer too small to hold the pathname,
+                * an error occurs.    - From RAND_file_name() man page.
+                * The fact is that when $HOME is NULL, .rnd is used.
+                */
+               randfile = RAND_file_name(buffer, sizeof( buffer ));
+
+       } else if (RAND_egd(randfile) > 0) {
+               /* EGD socket */
+               egdsocket = 1;
+               return 0;
+       }
+
+       if (randfile == NULL) {
+               Debug( LDAP_DEBUG_ANY,
+                       "TLS: Use configuration file or $RANDFILE to define seed file",
+                       0, 0, 0);
+               return -1;
+       }
+
+       RAND_load_file(randfile, -1);
+
+       if (RAND_status() == 0) {
+               Debug( LDAP_DEBUG_ANY,
+                       "TLS: PRNG has not been seeded with enough data",
+                       0, 0, 0);
+               return -1;
+       }
+#endif
+
+       return 0;
+}
+
 #if 0
 static DH *
 tls_tmp_dh_cb( SSL *ssl, int is_export, int key_length )
index 385312256f94e7663d9f9e235b8e9702573ea383..10a45aac58b179dbff22b1aafb35025c7f4f1422 100644 (file)
@@ -938,7 +938,7 @@ time2text( char *ldtimestr, int dateonly )
    
     timestr[ strlen( timestr ) - 1 ] = zone;   /* replace trailing newline */
     if ( dateonly ) {
-       SAFEMEMCPY( timestr + 11, timestr + 20, strlen( timestr + 20 ) + 1 );
+               AC_MEMCPY( timestr + 11, timestr + 20, strlen( timestr + 20 ) + 1 );
     }
 
     return( timestr );
index db21748c8db8d0fe6d3441902b648d8f1a32d52f..ec79348fec07bafe4a57ec13f923f5deb2e0862d 100644 (file)
@@ -98,7 +98,7 @@ ldap_ufn_search_ctx( LDAP *ld, char **ufncomp, int ncomp, char *prefix,
 
                        if ( (quote = strrchr( ufncomp[ncomp], '"' )) != NULL )
                                *quote = '\0';
-                       SAFEMEMCPY( ufncomp[ncomp], ufncomp[ncomp] + 1,
+                       AC_MEMCPY( ufncomp[ncomp], ufncomp[ncomp] + 1,
                                    strlen( ufncomp[ncomp] + 1 ) + 1 );
                }
                if ( ncomp == 0 )
index 98a559669f087e3ef0084ec217e036b3839856d9..a0b51a87c720bcd5574340e9cc696c265e5a4eea 100644 (file)
@@ -148,12 +148,6 @@ ldap_ld_free(
                ld->ld_options.ldo_tm_net = NULL;
        }
 
-#ifdef HAVE_CYRUS_SASL
-       if ( ld->ld_sasl_context != NULL ) {
-               sasl_dispose( &ld->ld_sasl_context );
-       }
-#endif 
-
        ber_sockbuf_free( ld->ld_sb );   
    
        LDAP_FREE( (char *) ld );
index b0484034a5f6bfc26d6c351e08facf0ea03ad97b..126b573cb20f322d764a5be4c3d10b76c99afaa5 100644 (file)
@@ -83,7 +83,7 @@ char *ldap_pvt_ctime( const time_t *tp, char *buf )
 # ifdef LDAP_R_COMPILE
        ldap_pvt_thread_mutex_lock( &ldap_int_ctime_mutex );
 # endif
-       memcpy( buf, ctime(tp), 26 );
+       AC_MEMCPY( buf, ctime(tp), 26 );
 # ifdef LDAP_R_COMPILE
        ldap_pvt_thread_mutex_unlock( &ldap_int_ctime_mutex );
 # endif
@@ -288,7 +288,7 @@ static char *cpy_aliases( char ***tgtio, char *buf, char **src )
        char **tgt=*tgtio;
        for( ; (*src) ; src++ ) {
                len = strlen( *src ) + 1;
-               memcpy( buf, *src, len );
+               AC_MEMCPY( buf, *src, len );
                *tgt++=buf;
                buf+=len;
        }
@@ -300,7 +300,7 @@ static char *cpy_addresses( char ***tgtio, char *buf, char **src, int len )
 {
        char **tgt=*tgtio;
        for( ; (*src) ; src++ ) {
-               memcpy( buf, *src, len );
+               AC_MEMCPY( buf, *src, len );
                *tgt++=buf;
                buf+=len;
        }
@@ -343,9 +343,9 @@ static int copy_hostent( struct hostent *res, char **buf, struct hostent * src )
        if (safe_realloc( buf, total_len )) {                    
                tp = (char **) *buf;
                tbuf = *buf + (n_alias + n_addr + 2) * sizeof( char * );
-               memcpy( res, src, sizeof( struct hostent ) );
+               AC_MEMCPY( res, src, sizeof( struct hostent ) );
                /* first the name... */
-               memcpy( tbuf, src->h_name, name_len );
+               AC_MEMCPY( tbuf, src->h_name, name_len );
                res->h_name = tbuf; tbuf+=name_len;
                /* now the aliases */
                res->h_aliases = tp;
index 889de2f4110d856508bdedfed8b54124ec42b242..8cfd03a5b55f8d409f07d987762cff8171f74a4a 100644 (file)
@@ -118,8 +118,8 @@ ldap_create_vlv_control( LDAP *ld,
        tag = ber_printf(ber, /*{*/ "N}"); 
        if( tag == LBER_ERROR ) goto exit;
 
-       ld->ld_errno = ldap_int_create_control(
-               LDAP_CONTROL_VLVREQUEST, ber, 1, ctrlp);
+       ld->ld_errno = ldap_create_control(     LDAP_CONTROL_VLVREQUEST,
+               ber, 1, ctrlp);
 
        ber_free(ber, 1);
        return(ld->ld_errno);
index 9ade237ee5720b16d3553f594b3f9ab215686db8..cc66467695c95661c7149d3dc87e04563671024b 100644 (file)
@@ -12,7 +12,7 @@ PROGRAMS = apitest ltest ttest
 XXDIR = $(srcdir)/../libldap
 XXSRCS = apitest.c test.c tmpltest.c extended.c \
        bind.c controls.c open.c result.c error.c compare.c search.c \
-       modify.c add.c modrdn.c delete.c abandon.c ufn.c cache.c \
+       modify.c add.c modrdn.c delete.c abandon.c ufn.c cache.c cyrus.c \
        getfilter.c sasl.c sbind.c kbind.c unbind.c friendly.c cldap.c \
        free.c disptmpl.c srchpref.c dsparse.c tmplout.c sort.c \
        getdn.c getentry.c getattr.c getvalues.c addentry.c \
@@ -28,7 +28,7 @@ OBJS  = threads.lo rdwr.lo tpool.lo  \
        thr_pth.lo thr_stub.lo \
        extended.lo \
        bind.lo controls.lo open.lo result.lo error.lo compare.lo search.lo \
-       modify.lo add.lo modrdn.lo delete.lo abandon.lo ufn.lo cache.lo \
+       modify.lo add.lo modrdn.lo delete.lo abandon.lo ufn.lo cache.lo cyrus.lo \
        getfilter.lo sasl.lo sbind.lo kbind.lo unbind.lo friendly.lo cldap.lo \
        free.lo disptmpl.lo srchpref.lo dsparse.lo tmplout.lo sort.lo \
        getdn.lo getentry.lo getattr.lo getvalues.lo addentry.lo \
index 1cf359ae8bb0c2a7f8896272c59e7944cb64ea88..fa07742f265ec2e23692016d5e44982de313fbe8 100644 (file)
@@ -164,6 +164,10 @@ SOURCE=..\libldap\controls.c
 # End Source File
 # Begin Source File
 
+SOURCE=..\libldap\cyrus.c
+# End Source File
+# Begin Source File
+
 SOURCE=..\libldap\delete.c
 # End Source File
 # Begin Source File
index 3e6825ac0a065263ce4ddf20a145c0a64f3420d9..8b857f630db3297a8768d083504f72661c983bf6 100644 (file)
@@ -51,7 +51,7 @@ ldbm_datum_dup( LDBM ldbm, Datum data )
        }
        dup.dsize = data.dsize;
        if ( (dup.dptr = (char *) malloc( data.dsize )) != NULL )
-               memcpy( dup.dptr, data.dptr, data.dsize );
+               AC_MEMCPY( dup.dptr, data.dptr, data.dsize );
 
        return( dup );
 }
@@ -811,7 +811,7 @@ ldbm_fetch( LDBM ldbm, Datum key )
        k.key.dsize = key.dsize + 1;                    
        k.key.dptr = malloc(k.key.dsize);
        *(k.key.dptr) = 'l';
-       memcpy( (void *)(k.key.dptr + 1), key.dptr, key.dsize );        
+       AC_MEMCPY( (void *)(k.key.dptr + 1), key.dptr, key.dsize );     
 #else
        k.key = key;
 #endif 
@@ -879,7 +879,7 @@ ldbm_store( LDBM ldbm, Datum key, Datum data, int flags )
        int_key.dsize = key.dsize + 1;
        int_key.dptr = malloc( int_key.dsize );
        *(int_key.dptr) = 'l';  /* Must not be NULL !*/
-       memcpy( (void *)(int_key.dptr + 1), key.dptr, key.dsize );
+       AC_MEMCPY( (void *)(int_key.dptr + 1), key.dptr, key.dsize );
 #else
        int_key = key;
 #endif
@@ -918,7 +918,7 @@ ldbm_delete( LDBM ldbm, Datum key )
        int_key.dsize = key.dsize + 1;
        int_key.dptr = malloc(int_key.dsize);
        *(int_key.dptr) = 'l';
-       memcpy( (void *)(int_key.dptr + 1), key.dptr, key.dsize );      
+       AC_MEMCPY( (void *)(int_key.dptr + 1), key.dptr, key.dsize );   
 #else
        int_key = key;
 #endif
@@ -974,7 +974,7 @@ ldbm_get_next( LDBM ldbm, kvpair (*fptr)(MDBM *, kvpair) )
 
            } else {
 
-               memcpy(ret.dptr, (void *)(out.key.dptr + delta),
+               AC_MEMCPY(ret.dptr, (void *)(out.key.dptr + delta),
                       ret.dsize );
 
            }
index daf90345987018786b4a82b52ecdddd44bf7c5fd..1f62be80e0a971a8591a9a13d714e7fcae492304 100644 (file)
@@ -80,7 +80,7 @@ ldif_fetch_url(
                        return -1;
                }
                p = newp;
-               SAFEMEMCPY( &p[total], buffer, bytes );
+               AC_MEMCPY( &p[total], buffer, bytes );
                total += bytes;
        }
 
index e4a85a226d0f7d67e075c3dd3f46d24bcecd5d81..e101cd9e3ecfa4ae01911c30e355c7fc7137b8d0 100644 (file)
@@ -231,7 +231,7 @@ done:
                        ber_memfree( freeme );
                        return( -1 );
                }
-               memcpy( p, value, vlen );
+               AC_MEMCPY( p, value, vlen );
                p[vlen] = '\0';
                value = p;
        }
index be9f2a08d523bd361bbba662627d0de3f8a86c23..bb85c616c9f77de6076f56e81d899563c72d3560 100644 (file)
@@ -13,11 +13,11 @@ NT_OBJS = ntservice.o slapdmsg.res
 UNIX_SRCS = detach.c
 UNIX_OBJS = detach.o
 
-SRCS   = base64.c debug.c entropy.c \
+SRCS   = base64.c debug.c entropy.c sasl.c signal.c \
        md5.c passwd.c sha1.c getpass.c lockf.c utils.c sockpair.c \
        @LIBSRCS@ $(@PLAT@_SRCS)
 
-OBJS   = base64.o debug.o entropy.o \
+OBJS   = base64.o debug.o entropy.o sasl.o signal.o \
        md5.o passwd.o sha1.o getpass.o lockf.o utils.o sockpair.o \
        @LIBOBJS@ $(@PLAT@_OBJS)
 
index 1fc4d74c71b2488207daa65497f0c67fd1fbb149..e179f32dbcd661ac233ad78ce62c7043123abae2 100644 (file)
@@ -609,7 +609,7 @@ static int chk_kerberos(
                }
 
                {
-                       char host[MAXHOSTNAMELEN];
+                       char host[MAXHOSTNAMELEN+1];
 
                        if( gethostname( host, MAXHOSTNAMELEN ) != 0 ) {
                                krb5_free_principal( context, client );
@@ -617,6 +617,8 @@ static int chk_kerberos(
                                return 1;
                        }
 
+                       host[MAXHOSTNAMELEN] = '\0';
+
                        ret = krb5_sname_to_principal( context,
                                host, "ldap", KRB5_NT_SRV_HST, &server );
                }
@@ -926,4 +928,4 @@ static struct berval *hash_crypt(
        return pw_string( scheme, &hash );
 }
 #endif
-#endif
\ No newline at end of file
+#endif
index 1759f7dee14210d7aa2fe36f71802569b9b0ffd5..13e9d9dd25c64f0ab9f829fae3a5458c2d56be84 100644 (file)
@@ -140,7 +140,7 @@ int lutil_entropy( char *buf, ber_len_t nbytes )
 
                        lutil_MD5Final( digest, &ctx );
 
-                       memcpy( &buf[n], digest,
+                       AC_MEMCPY( &buf[n], digest,
                                nbytes - n >= 16 ? 16 : nbytes - n );
                }
 
index 121921e98593c07cd499d732aa478c2e6883277c..31c305abd2ef80f9308ada647de271045ee375da 100644 (file)
@@ -172,6 +172,10 @@ SOURCE=..\..\include\lutil.h
 # End Source File
 # Begin Source File
 
+SOURCE=..\..\include\lutil_ldap.h
+# End Source File
+# Begin Source File
+
 SOURCE=..\..\include\lutil_lockf.h
 # End Source File
 # Begin Source File
@@ -200,6 +204,10 @@ SOURCE=..\..\include\portable.h
 # End Source File
 # Begin Source File
 
+SOURCE=.\sasl.c
+# End Source File
+# Begin Source File
+
 SOURCE=.\sha1.c
 # End Source File
 # Begin Source File
index 9ce509f8ffe13ab86436b802423dbd58d2bb4500..9e14cc2a4ae807d06b668fad3ee62105bd09a497 100644 (file)
@@ -110,10 +110,10 @@ lutil_MD5Update(
 
                t = 64-t;
                if (len < t) {
-                       memcpy(p, buf, len);
+                       AC_MEMCPY(p, buf, len);
                        return;
                }
-               memcpy(p, buf, t);
+               AC_MEMCPY(p, buf, t);
                lutil_MD5Transform(ctx->buf, ctx->in);
                buf += t;
                len -= t;
@@ -122,7 +122,7 @@ lutil_MD5Update(
        /* Process data in 64-byte chunks */
 
        while (len >= 64) {
-               memcpy(ctx->in, buf, 64);
+               AC_MEMCPY(ctx->in, buf, 64);
                lutil_MD5Transform(ctx->buf, ctx->in);
                buf += 64;
                len -= 64;
@@ -130,7 +130,7 @@ lutil_MD5Update(
 
        /* Handle any remaining bytes of data. */
 
-       memcpy(ctx->in, buf, len);
+       AC_MEMCPY(ctx->in, buf, len);
 }
 
 /*
index becde0e6c540b5f66898a054280959c3243e3297..68c2709ab6053a4d96843e1bb5005a70982e6938 100644 (file)
@@ -351,8 +351,8 @@ static struct berval * pw_string(
                return NULL;
        }
 
-       memcpy( pw->bv_val, sc->name.bv_val, sc->name.bv_len );
-       memcpy( &pw->bv_val[sc->name.bv_len], passwd->bv_val, passwd->bv_len );
+       AC_MEMCPY( pw->bv_val, sc->name.bv_val, sc->name.bv_len );
+       AC_MEMCPY( &pw->bv_val[sc->name.bv_len], passwd->bv_val, passwd->bv_len );
 
        pw->bv_val[pw->bv_len] = '\0';
        return pw;
@@ -380,9 +380,9 @@ static struct berval * pw_string64(
                        return NULL;
                }
 
-               memcpy( string.bv_val, hash->bv_val,
+               AC_MEMCPY( string.bv_val, hash->bv_val,
                        hash->bv_len );
-               memcpy( &string.bv_val[hash->bv_len], salt->bv_val,
+               AC_MEMCPY( &string.bv_val[hash->bv_len], salt->bv_val,
                        salt->bv_len );
                string.bv_val[string.bv_len] = '\0';
 
@@ -400,7 +400,7 @@ static struct berval * pw_string64(
                return NULL;
        }
 
-       memcpy(b64->bv_val, sc->name.bv_val, sc->name.bv_len);
+       AC_MEMCPY(b64->bv_val, sc->name.bv_val, sc->name.bv_len);
 
        rc = lutil_b64_ntop(
                string.bv_val, string.bv_len,
@@ -726,7 +726,7 @@ static int chk_kerberos(
                }
 
                {
-                       char host[MAXHOSTNAMELEN];
+                       char host[MAXHOSTNAMELEN+1];
 
                        if( gethostname( host, MAXHOSTNAMELEN ) != 0 ) {
                                krb5_free_principal( context, client );
@@ -734,6 +734,8 @@ static int chk_kerberos(
                                return 1;
                        }
 
+                       host[MAXHOSTNAMELEN] = '\0';
+
                        ret = krb5_sname_to_principal( context,
                                host, "ldap", KRB5_NT_SRV_HST, &server );
                }
diff --git a/libraries/liblutil/sasl.c b/libraries/liblutil/sasl.c
new file mode 100644 (file)
index 0000000..35f94fe
--- /dev/null
@@ -0,0 +1,202 @@
+/* $OpenLDAP$ */
+/*
+ * Copyright 2000 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+
+#include "portable.h"
+
+#ifdef HAVE_CYRUS_SASL
+
+#include <stdio.h>
+#include <ac/stdlib.h>
+#include <ac/string.h>
+#include <ac/unistd.h>
+
+#include <sasl.h>
+
+#include <ldap.h>
+#include "lutil_ldap.h"
+
+
+typedef struct lutil_sasl_defaults_s {
+       char *mech;
+       char *realm;
+       char *authcid;
+       char *passwd;
+       char *authzid;
+} lutilSASLdefaults;
+
+
+void *
+lutil_sasl_defaults(
+       LDAP *ld,
+       char *mech,
+       char *realm,
+       char *authcid,
+       char *passwd,
+       char *authzid )
+{
+       lutilSASLdefaults *defaults;
+       
+       defaults = ber_memalloc( sizeof( lutilSASLdefaults ) );
+
+       if( defaults == NULL ) return NULL;
+
+       defaults->mech = mech;
+       defaults->realm = realm;
+       defaults->authcid = authcid;
+       defaults->passwd = passwd;
+       defaults->authzid = authzid;
+
+       if( defaults->mech == NULL ) {
+               ldap_get_option( ld, LDAP_OPT_X_SASL_MECH, &defaults->mech );
+       }
+       if( defaults->realm == NULL ) {
+               ldap_get_option( ld, LDAP_OPT_X_SASL_REALM, &defaults->realm );
+       }
+       if( defaults->authcid == NULL ) {
+               ldap_get_option( ld, LDAP_OPT_X_SASL_AUTHCID, &defaults->authcid );
+       }
+       if( defaults->authzid == NULL ) {
+               ldap_get_option( ld, LDAP_OPT_X_SASL_AUTHZID, &defaults->authzid );
+       }
+
+       return defaults;
+}
+
+static int interaction(
+       unsigned flags,
+       sasl_interact_t *interact,
+       lutilSASLdefaults *defaults )
+{
+       const char *dflt = interact->defresult;
+       char input[1024];
+
+       int noecho=0;
+       int challenge=0;
+
+       switch( interact->id ) {
+       case SASL_CB_GETREALM:
+               if( defaults ) dflt = defaults->realm;
+               break;
+       case SASL_CB_AUTHNAME:
+               if( defaults ) dflt = defaults->authcid;
+               break;
+       case SASL_CB_PASS:
+               if( defaults ) dflt = defaults->passwd;
+               noecho = 1;
+               break;
+       case SASL_CB_USER:
+               if( defaults ) dflt = defaults->authzid;
+               break;
+       case SASL_CB_NOECHOPROMPT:
+               noecho = 1;
+               challenge = 1;
+               break;
+       case SASL_CB_ECHOPROMPT:
+               challenge = 1;
+               break;
+       }
+
+       if( dflt && !*dflt ) dflt = NULL;
+
+       if( flags != LDAP_SASL_INTERACTIVE &&
+               ( dflt || interact->id == SASL_CB_USER ) )
+       {
+               goto use_default;
+       }
+
+       if( flags == LDAP_SASL_QUIET ) {
+               /* don't prompt */
+               return LDAP_OTHER;
+       }
+
+       if( challenge ) {
+               if( interact->challenge ) {
+                       fprintf( stderr, "Challenge: %s\n", interact->challenge );
+               }
+       }
+
+       if( dflt ) {
+               fprintf( stderr, "Default: %s\n", dflt );
+       }
+
+       sprintf( input, "%s: ",
+               interact->prompt ? interact->prompt : "Interact" );
+
+       if( noecho ) {
+               interact->result = (char *) getpassphrase( input );
+               interact->len = interact->result
+                       ? strlen( interact->result ) : 0;
+
+       } else {
+               /* prompt user */
+               fputs( input, stderr );
+
+               /* get input */
+               interact->result = fgets( input, sizeof(input), stdin );
+
+               if( interact->result == NULL ) {
+                       interact->len = 0;
+                       return LDAP_UNAVAILABLE;
+               }
+
+               /* len of input */
+               interact->len = strlen(input); 
+
+               if( interact->len > 0 && input[interact->len - 1] == '\n' ) {
+                       /* input includes '\n', trim it */
+                       interact->len--;
+                       input[interact->len] = '\0';
+               }
+       }
+
+
+       if( interact->len > 0 ) {
+               /* duplicate */
+               char *p = interact->result;
+               interact->result = strdup( p );
+
+               /* zap */
+               memset( p, '\0', interact->len );
+
+       } else {
+use_default:
+               /* input must be empty */
+               interact->result = strdup( (dflt && *dflt) ? dflt : "" );
+               interact->len = interact->result
+                       ? strlen( interact->result ) : 0;
+       }
+
+       if( defaults && defaults->passwd && interact->id == SASL_CB_PASS ) {
+               /* zap password after first use */
+               memset( defaults->passwd, '\0', strlen(defaults->passwd) );
+               defaults->passwd = NULL;
+       }
+
+       return LDAP_SUCCESS;
+}
+
+int lutil_sasl_interact(
+       LDAP *ld,
+       unsigned flags,
+       void *defaults,
+       void *in )
+{
+       sasl_interact_t *interact = in;
+
+       if( flags == LDAP_SASL_INTERACTIVE ) {
+               fputs( "SASL Interaction\n", stderr );
+       }
+
+       while( interact->id != SASL_CB_LIST_END ) {
+               int rc = interaction( flags, interact, defaults );
+
+               if( rc )  return rc;
+               interact++;
+       }
+       
+       return LDAP_SUCCESS;
+}
+#endif
index b3e608b606f3b5b8d1db91c3c1b03c864b6fd7db..9d97ceb169c165118afe8b363458c9095079cb1f 100644 (file)
@@ -71,7 +71,7 @@ lutil_SHA1Transform( uint32 *state, const unsigned char *buffer )
 
 #ifdef SHA1HANDSOFF
     uint32 block[16];
-    (void)memcpy(block, buffer, 64);
+    (void)AC_MEMCPY(block, buffer, 64);
 #else
     uint32 *block = (u_int32 *) buffer;
 #endif
@@ -151,7 +151,7 @@ lutil_SHA1Update(
        context->count[1] += (len>>29)+1;
     j = (j >> 3) & 63;
     if ((j + len) > 63) {
-       (void)memcpy(&context->buffer[j], data, (i = 64-j));
+       (void)AC_MEMCPY(&context->buffer[j], data, (i = 64-j));
        lutil_SHA1Transform(context->state, context->buffer);
        for ( ; i + 63 < len; i += 64)
            lutil_SHA1Transform(context->state, &data[i]);
@@ -159,7 +159,7 @@ lutil_SHA1Update(
     } else {
        i = 0;
     }
-    (void)memcpy(&context->buffer[j], &data[i], len - i);
+    (void)AC_MEMCPY(&context->buffer[j], &data[i], len - i);
 }
 
 
diff --git a/libraries/liblutil/signal.c b/libraries/liblutil/signal.c
new file mode 100644 (file)
index 0000000..230a265
--- /dev/null
@@ -0,0 +1,33 @@
+/* $OpenLDAP$ */
+/*
+ * Copyright 2000 The OpenLDAP Foundation
+ * COPYING RESTRICTIONS APPLY.  See COPYRIGHT File in top level directory
+ * of this package for details.
+ */
+
+#include "portable.h"
+
+#ifdef HAVE_SIGACTION
+#include <ac/signal.h>
+
+lutil_sig_t
+lutil_sigaction(int sig, lutil_sig_t func)
+{
+       int rc;
+       struct sigaction action, oaction;
+
+       memset( &action, '\0', sizeof(action) );
+
+       action.sa_handler = func;
+       sigemptyset( &action.sa_mask );
+#ifdef SA_RESTART
+       action.sa_flags != SA_RESTART;
+#endif
+       
+       if( sigaction( sig, &action, &oaction ) != 0 ) {
+               return NULL;
+       }
+
+       return oaction.sa_handler;
+}
+#endif
index d7787e7127ea95ba1d869c93a369252f4f4e8257..1c3b14747d0b22177718d1959fa89301ade96b9a 100644 (file)
@@ -268,8 +268,8 @@ install-conf: FORCE
        @-$(MKDIR) $(DESTDIR)$(sysconfdir)
        @-$(INSTALL) -m 700 -d $(DESTDIR)$(localstatedir)/openldap-ldbm
        $(INSTALL) $(INSTALLFLAGS) -m 600 slapd.conf.tmp $(DESTDIR)$(sysconfdir)/slapd.conf.default
-       if test ! -f $(DESTDIR)$(sysconfdir)/$$cf; then \
-               echo "installing $$cf in $(sysconfdir)"; \
+       if test ! -f $(DESTDIR)$(sysconfdir)/slapd.conf; then \
+               echo "installing slapd.conf in $(sysconfdir)"; \
                echo "$(INSTALL) $(INSTALLFLAGS) -m 600 slapd.conf.tmp $(DESTDIR)$(sysconfdir)/slapd.conf"; \
                $(INSTALL) $(INSTALLFLAGS) -m 600 slapd.conf.tmp $(DESTDIR)$(sysconfdir)/slapd.conf; \
        else \
index cbed19b93150653000d6fe2afce86e2e5257d7f3..2e74071b3160c7360a5be014bcaa2ef1e46c693f 100644 (file)
@@ -366,8 +366,8 @@ acl_mask(
                e->e_dn, attr, 0 );
 
        Debug( LDAP_DEBUG_ACL,
-               "=> acl_mask: to value \"%s\" by \"%s\", (%s) \n",
-               val ? val->bv_val : "*",
+               "=> acl_mask: to %s by \"%s\", (%s) \n",
+               val ? "value" : "all values",
                op->o_ndn ?  op->o_ndn : "",
                accessmask2str( *mask, accessmaskbuf ) );
 
@@ -879,7 +879,7 @@ aci_bvstrdup( struct berval *bv )
 
        s = (char *)ch_malloc(bv->bv_len + 1);
        if (s != NULL) {
-               memcpy(s, bv->bv_val, bv->bv_len);
+               AC_MEMCPY(s, bv->bv_val, bv->bv_len);
                s[bv->bv_len] = 0;
        }
        return(s);
index f41c702ca6f9e3efe76ce6fc861fada46f6a4b3f..ce8641d93c1dd9fdabaf04f6ab742c3f2016d6ce 100644 (file)
@@ -487,7 +487,7 @@ parse_acl(
                                        }
 
                                        if (name && *name) {
-                                               rc = slap_str2ad( right, &b->a_group_at, &text );
+                                               rc = slap_str2ad( name, &b->a_group_at, &text );
 
                                                if( rc != LDAP_SUCCESS ) {
                                                        fprintf( stderr,
index e45ded2ae6a9dd06483bc095b39a54bf3c952399..d159ea8631279996900a567441c3727be96f8b21 100644 (file)
@@ -301,7 +301,7 @@ static int slap_mods2entry(
                                sizeof( struct berval * ) * (i+j) );
 
                        /* should check for duplicates */
-                       memcpy( &attr->a_vals[i], mods->sml_bvalues,
+                       AC_MEMCPY( &attr->a_vals[i], mods->sml_bvalues,
                                sizeof( struct berval * ) * j );
 
                        /* trim the mods array */
index 4ad381d9ffaef74806cf4de54a145fc21b2eea28..25c1d7589bfa895a3d5709bd0d10c8ecb71c7eed 100644 (file)
@@ -74,23 +74,12 @@ at_find(
     const char         *name
 )
 {
-       struct aindexrec        *air;
-       char                    *tmpname;
-
-       {
-               tmpname = (char *)name;
-       }
+       struct aindexrec *air;
 
-       if ( (air = (struct aindexrec *) avl_find( attr_index, tmpname,
-            (AVL_CMP) attr_index_name_cmp )) != NULL ) {
-               if ( tmpname != name )
-                       ldap_memfree( tmpname );
-               return( air->air_at );
-       }
+       air = (struct aindexrec *) avl_find( attr_index, name,
+            (AVL_CMP) attr_index_name_cmp );
 
-       if ( tmpname != name )
-               ldap_memfree( tmpname );
-       return( NULL );
+       return air != NULL ? air->air_at : NULL;
 }
 
 int
@@ -239,7 +228,7 @@ at_insert(
 
 int
 at_add(
-    LDAP_ATTRIBUTE_TYPE        *at,
+    LDAPAttributeType  *at,
     const char         **err
 )
 {
@@ -258,7 +247,7 @@ at_add(
                return SLAP_SCHERR_ATTR_INCOMPLETE;
        }
        sat = (AttributeType *) ch_calloc( 1, sizeof(AttributeType) );
-       memcpy( &sat->sat_atype, at, sizeof(LDAP_ATTRIBUTE_TYPE));
+       AC_MEMCPY( &sat->sat_atype, at, sizeof(LDAPAttributeType));
 
        sat->sat_cname = cname;
 
@@ -306,6 +295,7 @@ at_add(
        if ( sat->sat_equality_oid ) {
                if ( (mr = mr_find(sat->sat_equality_oid)) ) {
                        sat->sat_equality = mr;
+                       sat->sat_approx = mr->smr_associated;
                } else {
                        *err = sat->sat_equality_oid;
                        return SLAP_SCHERR_MR_NOT_FOUND;
index d1e0091d86108c267980d53a151224bcb38eeade..5e25c0055c61d67186889a11d771339c22f5a35f 100644 (file)
@@ -68,12 +68,6 @@ dnssrv_back_initialize(
        bi->bi_acl_group = 0;
        bi->bi_acl_attribute = 0;
 
-#ifdef HAVE_CYRUS_SASL
-       bi->bi_sasl_authorize = 0;
-       bi->bi_sasl_getsecret = 0;
-       bi->bi_sasl_putsecret = 0;
-#endif /* HAVE_CYRUS_SASL */
-
        bi->bi_connection_init = 0;
        bi->bi_connection_destroy = 0;
 
index eb62b343b0e4d8db0c894d112a60a6766eafc5ac..b98945a7d0bd2a562b69816e90b43ea99a1693a0 100644 (file)
@@ -78,12 +78,6 @@ ldap_back_initialize(
        bi->bi_acl_attribute = ldap_back_attribute;
        bi->bi_chk_referrals = 0;
 
-#ifdef HAVE_CYRUS_SASL
-       bi->bi_sasl_authorize = 0;
-       bi->bi_sasl_getsecret = 0;
-       bi->bi_sasl_putsecret = 0;
-#endif /* HAVE_CYRUS_SASL */
-
        bi->bi_connection_init = 0;
        bi->bi_connection_destroy = ldap_back_conn_destroy;
 
index 5f44fb48416129d67f43e60c4dfb64d3b135bd5c..d37dfeb3abe1adbf33013459b7d69edc02632a01 100644 (file)
@@ -279,8 +279,8 @@ char* new_superior(
 
        newDN = ch_malloc( dnlen - olen + nlen + 1 );
 
-       memcpy( newDN, dn, dnlen - olen );
-       memcpy( &newDN[dnlen - olen], newSup, nlen );
+       AC_MEMCPY( newDN, dn, dnlen - olen );
+       AC_MEMCPY( &newDN[dnlen - olen], newSup, nlen );
        newDN[dnlen - olen + nlen] = '\0';
 
        return newDN;
index ca614d978acdc0cbfab0aca68f2f992f5b7a8a55..81f1154a855a2f0e4d29843313e8663c5e23ea0f 100644 (file)
@@ -139,7 +139,7 @@ dn2id(
                return( NOID );
        }
 
-       (void) memcpy( (char *) &id, data.dptr, sizeof(ID) );
+       AC_MEMCPY( (char *) &id, data.dptr, sizeof(ID) );
 
        assert( id != NOID );
 
index 1ea9d565614a89deb58ce8549f8a74d1153e1ba0..2bdac2f06930879149431f0f117a88aa9b576d11 100644 (file)
@@ -96,11 +96,7 @@ extern ID ldbm_tool_entry_next LDAP_P(( BackendDB *be ));
 extern Entry* ldbm_tool_entry_get LDAP_P(( BackendDB *be, ID id ));
 extern ID ldbm_tool_entry_put LDAP_P(( BackendDB *be, Entry *e ));
 
-extern int ldbm_tool_index_attr LDAP_P(( BackendDB *be,
-       AttributeDescription* desc ));
-extern int ldbm_tool_index_change LDAP_P(( BackendDB *be,
-       AttributeDescription* desc,
-       struct berval **bv, ID id, int op ));
+extern int ldbm_tool_entry_reindex LDAP_P(( BackendDB *be, ID id ));
 extern int ldbm_tool_sync LDAP_P(( BackendDB *be ));
 
 extern int ldbm_back_referrals LDAP_P(( BackendDB *bd,
index 1cdaa750d4df901458695bcdd7413f361c785292..13ac4235b05752fa8a49c4bdfcf4dd0a33cd4305 100644 (file)
@@ -25,7 +25,7 @@ static void cont_alloc( Datum *cont, Datum *key )
 
        * (unsigned char *) cont->dptr = SLAP_INDEX_CONT_PREFIX;
 
-       memcpy( &((unsigned char *)cont->dptr)[1 + sizeof(ID)],
+       AC_MEMCPY( &((unsigned char *)cont->dptr)[1 + sizeof(ID)],
                key->dptr, key->dsize );
 }
 
@@ -196,7 +196,7 @@ idl_fetch(
                        continue;
                }
 
-               SAFEMEMCPY(
+               AC_MEMCPY(
                        (char *) &ID_BLOCK_ID(idl, nids),
                        (char *) &ID_BLOCK_ID(tmp[i], 0),
                        ID_BLOCK_NIDS(tmp[i]) * sizeof(ID) );
@@ -275,7 +275,7 @@ idl_split_block(
                ID_BLOCK_NIDS(*right) = 1;
                ID_BLOCK_ID(*right, 0) = id;
        } else {
-               SAFEMEMCPY(
+               AC_MEMCPY(
                        (char *) &ID_BLOCK_ID(*right, 0),
                        (char *) &ID_BLOCK_ID(b, 0),
                        nr * sizeof(ID) );
@@ -284,7 +284,7 @@ idl_split_block(
        }
 
        /* the id being inserted & everything after in the second block */
-       SAFEMEMCPY(
+       AC_MEMCPY(
                (char *) &ID_BLOCK_ID(*left, (nr == 0 ? 0 : 1)),
            (char *) &ID_BLOCK_ID(b, nr),
                nl * sizeof(ID) );
@@ -517,7 +517,7 @@ idl_insert_key(
 
                                k3.dptr = ch_malloc(k2.dsize);
                                k3.dsize = k2.dsize;
-                               memcpy(k3.dptr, k2.dptr, k3.dsize);
+                               AC_MEMCPY(k3.dptr, k2.dptr, k3.dsize);
                            if ( (rc = idl_store( be, db, k3, tmp )) != 0 ) {
                                Debug( LDAP_DEBUG_ANY,
                            "idl_insert_key: idl_store returned %d\n", rc, 0, 0 );
@@ -612,7 +612,7 @@ split:
                tmp = idl_alloc( ID_BLOCK_NMAX(idl) + 1 );
                ID_BLOCK_NIDS(tmp) = ID_BLOCK_INDIRECT_VALUE;
                /* everything up to the split block */
-               SAFEMEMCPY(
+               AC_MEMCPY(
                        (char *) &ID_BLOCK_ID(tmp, 0),
                        (char *) &ID_BLOCK_ID(idl, 0),
                    i * sizeof(ID) );
@@ -620,7 +620,7 @@ split:
                ID_BLOCK_ID(tmp, i) = ID_BLOCK_ID(tmp2, 0);
                ID_BLOCK_ID(tmp, i + 1) = ID_BLOCK_ID(tmp3, 0);
                /* everything after the split block */
-               SAFEMEMCPY(
+               AC_MEMCPY(
                        (char *) &ID_BLOCK_ID(tmp, i + 2),
                        (char *) &ID_BLOCK_ID(idl, i + 1),
                        (ID_BLOCK_NMAX(idl) - i - 1) * sizeof(ID) );
@@ -690,7 +690,7 @@ idl_insert( ID_BLOCK **idl, ID id, unsigned int maxids )
        }
 
        /* make a slot for the new id */
-       SAFEMEMCPY( &ID_BLOCK_ID(*idl, i+1), &ID_BLOCK_ID(*idl, i),
+       AC_MEMCPY( &ID_BLOCK_ID(*idl, i+1), &ID_BLOCK_ID(*idl, i),
                    (ID_BLOCK_NIDS(*idl) - i) * sizeof(ID) );
 
        ID_BLOCK_ID(*idl, i) = id;
@@ -735,7 +735,7 @@ idl_delete_key (
                                        ldbm_cache_delete( db, key );
 
                                } else {
-                                       SAFEMEMCPY (
+                                       AC_MEMCPY(
                                                &ID_BLOCK_ID(idl, i),
                                                &ID_BLOCK_ID(idl, i+1),
                                                (ID_BLOCK_NIDS(idl)-i) * sizeof(ID) );
@@ -779,7 +779,7 @@ idl_delete_key (
                {
                        if ( ID_BLOCK_ID(tmp, i) == id )
                        {
-                               SAFEMEMCPY(
+                               AC_MEMCPY(
                                        &ID_BLOCK_ID(tmp, i),
                                        &ID_BLOCK_ID(tmp, i+1),
                                        (ID_BLOCK_NIDS(tmp)-(i+1)) * sizeof(ID));
@@ -791,7 +791,7 @@ idl_delete_key (
 
                                } else {
                                        ldbm_cache_delete( db, data );
-                                       SAFEMEMCPY(
+                                       AC_MEMCPY(
                                                &ID_BLOCK_ID(idl, j),
                                                &ID_BLOCK_ID(idl, j+1),
                                                (nids-(j+1)) * sizeof(ID));
@@ -829,7 +829,7 @@ idl_dup( ID_BLOCK *idl )
 
        new = idl_alloc( ID_BLOCK_NMAX(idl) );
 
-       SAFEMEMCPY(
+       AC_MEMCPY(
                (char *) new,
                (char *) idl,
                (ID_BLOCK_NMAX(idl) + ID_BLOCK_IDS_OFFSET) * sizeof(ID) );
index 0d93e525ea58314e09bd1f8d9865d2f47df6f38d..db9f264fc25fde21a8750e7646519c496ac8255b 100644 (file)
@@ -174,10 +174,11 @@ static int indexer(
                        ad->ad_type->sat_equality,
                        &prefix, vals, &keys );
 
-               if( rc == LDAP_SUCCESS ) {
-                       for( i= 0; keys[i] != NULL; i++ ) {
+               if( rc == LDAP_SUCCESS && keys != NULL ) {
+                       for( i=0; keys[i] != NULL; i++ ) {
                                key_change( be, db, keys[i], id, op );
                        }
+                       ber_bvecfree( keys );
                }
        }
 
@@ -188,10 +189,11 @@ static int indexer(
                        ad->ad_type->sat_approx,
                        &prefix, vals, &keys );
 
-               if( rc == LDAP_SUCCESS ) {
-                       for( i= 0; keys[i] != NULL; i++ ) {
+               if( rc == LDAP_SUCCESS && keys != NULL ) {
+                       for( i=0; keys[i] != NULL; i++ ) {
                                key_change( be, db, keys[i], id, op );
                        }
+                       ber_bvecfree( keys );
                }
        }
 
@@ -202,10 +204,11 @@ static int indexer(
                        ad->ad_type->sat_substr,
                        &prefix, vals, &keys );
 
-               if( rc == LDAP_SUCCESS ) {
-                       for( i= 0; keys[i] != NULL; i++ ) {
+               if( rc == LDAP_SUCCESS && keys != NULL ) {
+                       for( i=0; keys[i] != NULL; i++ ) {
                                key_change( be, db, keys[i], id, op );
                        }
+                       ber_bvecfree( keys );
                }
        }
 
index aff7a076b154c1af21453bafaff5bdd540c41b62..dc4b5b81deb5e5b531b11cea840e94d23e8c1b9a 100644 (file)
@@ -79,15 +79,9 @@ ldbm_back_initialize(
        bi->bi_tool_entry_next = ldbm_tool_entry_next;
        bi->bi_tool_entry_get = ldbm_tool_entry_get;
        bi->bi_tool_entry_put = ldbm_tool_entry_put;
-       bi->bi_tool_index_attr = ldbm_tool_index_attr;
+       bi->bi_tool_entry_reindex = ldbm_tool_entry_reindex;
        bi->bi_tool_sync = ldbm_tool_sync;
 
-#ifdef HAVE_CYRUS_SASL
-       bi->bi_sasl_authorize = 0;
-       bi->bi_sasl_getsecret = 0;
-       bi->bi_sasl_putsecret = 0;
-#endif /* HAVE_CYRUS_SASL */
-
        bi->bi_connection_init = 0;
        bi->bi_connection_destroy = 0;
 
index 37cbfc5f05f074324f039ed6e7a56dfae94e6b2f..c92cbaab780948148f1e5826a435af8067c995b0 100644 (file)
@@ -40,7 +40,7 @@ next_id_read( Backend *be )
        data = ldbm_cache_fetch( db, key );
 
        if( data.dptr != NULL ) {
-               memcpy( &id, data.dptr, sizeof( ID ) );
+               AC_MEMCPY( &id, data.dptr, sizeof( ID ) );
                ldbm_datum_free( db->dbc_db, data );
 
        } else {
index a50cc731964889c38e0d275a335af857a7073fdb..6cc7d08c2d6065e0fdd7e675473bc04a3623328b 100644 (file)
@@ -204,30 +204,6 @@ int ldbm_modify_internal LDAP_P((Backend *be,
        const char *dn, Modifications *mods, Entry *e,
        const char ** ));
 
-#ifdef HAVE_CYRUS_SASL
-/*
- * sasl.c
- */
-int ldbm_sasl_authorize LDAP_P((
-        BackendDB *be,
-        const char *auth_identity,
-        const char *requested_user,
-        const char **user,
-        const char **errstring ));
-int ldbm_sasl_getsecret LDAP_P((
-        Backend *be,
-        const char *mechanism,
-        const char *auth_identity,
-        const char *realm,
-        sasl_secret_t **secret ));
-int ldbm_sasl_putsecret LDAP_P((
-        Backend *be,
-        const char *mechanism,
-        const char *auth_identity,
-        const char *realm,
-        const sasl_secret_t *secret ));
-#endif /* HAVE_CYRUS_SASL */
-
 /*
  * nextid.c
  */
index 37e6c7afefcb4796964884bb5413b81f193a08a4..b7812a00e35473711a5828ed62e9689e24e1de57 100644 (file)
@@ -5,10 +5,11 @@
  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
  */
 
-#ifdef HAVE_CYRUS_SASL
 
 #include "portable.h"
 
+#if 0
+
 #include <stdio.h>
 
 #include <ac/krb.h>
index 1715465e69b4bbb1c3e77c942259c0ee68f2e50b..68d2a289698eb4987336029b36794ee41185dfe4 100644 (file)
@@ -84,7 +84,7 @@ ID ldbm_tool_entry_first(
                return NOID;
        }
 
-       memcpy( &id, key.dptr, key.dsize );
+       AC_MEMCPY( &id, key.dptr, key.dsize );
 
        ldbm_datum_free( id2entry->dbc_db, key );
 
@@ -109,7 +109,7 @@ ID ldbm_tool_entry_next(
                return NOID;
        }
 
-       memcpy( &id, key.dptr, key.dsize );
+       AC_MEMCPY( &id, key.dptr, key.dsize );
 
        ldbm_datum_free( id2entry->dbc_db, key );
 
@@ -137,6 +137,10 @@ Entry* ldbm_tool_entry_get( BackendDB *be, ID id )
        e = str2entry( data.dptr );
        ldbm_datum_free( id2entry->dbc_db, data );
 
+       if( e != NULL ) {
+               e->e_id = id;
+       }
+
        return e;
 }
 
@@ -192,48 +196,40 @@ ID ldbm_tool_entry_put(
        return e->e_id;
 }
 
-int ldbm_tool_index_attr(
+int ldbm_tool_entry_reindex(
        BackendDB *be,
-       AttributeDescription *desc
-)
+       ID id )
 {
-       static DBCache *db = NULL;
-       slap_index indexmask;
-       char *at_cname;
-
-       assert( slapMode & SLAP_TOOL_MODE );
+       int rc;
+       Entry *e;
 
-       at_cname = desc->ad_cname->bv_val;
+       Debug( LDAP_DEBUG_ARGS, "=> ldbm_tool_entry_reindex( %ld )\n",
+               (long) id, 0, 0 );
 
-       assert( desc != NULL );
-       attr_mask( be->be_private, at_cname, &indexmask );
+       e = ldbm_tool_entry_get( be, id );
 
-       if ( (db = ldbm_cache_open( be, at_cname, LDBM_SUFFIX, LDBM_NEWDB ))
-           == NULL )
-       {
+       if( e == NULL ) {
                Debug( LDAP_DEBUG_ANY,
-                   "<= index_attr NULL (could not open %s%s)\n", at_cname,
-                   LDBM_SUFFIX, 0 );
-               return 0;
+                       "ldbm_tool_entry_reindex:: could not locate id=%ld\n",
+                       (long) id, 0, 0 );
+               return -1;
        }
 
-       ldbm_cache_close( be, db );
+       /*
+        * just (re)add them for now
+        * assume that some other routine (not yet implemented)
+        * will zap index databases
+        *
+        */
 
-       return indexmask != 0;
-}
+       Debug( LDAP_DEBUG_TRACE, "=> ldbm_tool_entry_reindex( %ld, \"%s\" )\n",
+               id, e->e_dn, 0 );
 
-int ldbm_tool_index_change(
-       BackendDB *be,
-       AttributeDescription *desc,
-       struct berval **bv,
-       ID id,
-       int op )
-{
-       assert( slapMode & SLAP_TOOL_MODE );
+       rc = index_entry_add( be, e, e->e_attrs );
 
-       index_values( be, desc, bv, id, op );
+       entry_free( e );
 
-       return 0;
+       return rc;
 }
 
 int ldbm_tool_sync( BackendDB *be )
index accff0551adb9e09cc4c04309f92fe3878256985..5190bff4c1d414553e58a1a9734290a4d3f3a723 100644 (file)
@@ -57,12 +57,6 @@ passwd_back_initialize(
        bi->bi_acl_attribute = 0;
        bi->bi_chk_referrals = 0;
 
-#ifdef HAVE_CYRUS_SASL
-       bi->bi_sasl_authorize = 0;
-       bi->bi_sasl_getsecret = 0;
-       bi->bi_sasl_putsecret = 0;
-#endif /* HAVE_CYRUS_SASL */
-
        bi->bi_connection_init = 0;
        bi->bi_connection_destroy = 0;
 
index b05b029132254129333f1d81462cbf2e57c47f6f..ddebb961ef76f997b2fbdf98593cf22fa5926f49 100644 (file)
@@ -61,12 +61,6 @@ shell_back_initialize(
        bi->bi_acl_attribute = 0;
        bi->bi_chk_referrals = 0;
 
-#ifdef HAVE_CYRUS_SASL
-       bi->bi_sasl_authorize = 0;
-       bi->bi_sasl_getsecret = 0;
-       bi->bi_sasl_putsecret = 0;
-#endif /* HAVE_CYRUS_SASL */
-
        bi->bi_connection_init = 0;
        bi->bi_connection_destroy = 0;
 
index 780e3b9cc3ac04517d5d815952a132593c84ed11..a5963c654447fbed4fcec8e2dcfcf5899d639f7c 100644 (file)
@@ -159,13 +159,13 @@ int backend_add(BackendInfo *aBackendInfo)
       /* if backendInfo == binfo no deallocation of old backendInfo */
       if (backendInfo == binfo) {
         newBackendInfo = ch_calloc(nBackendInfo + 1, sizeof(BackendInfo));
-        memcpy(newBackendInfo, backendInfo, sizeof(BackendInfo) * 
+        AC_MEMCPY(newBackendInfo, backendInfo, sizeof(BackendInfo) * 
                nBackendInfo);
       } else {
         newBackendInfo = ch_realloc(backendInfo, sizeof(BackendInfo) * 
                                     (nBackendInfo + 1));
       }
-      memcpy(&newBackendInfo[nBackendInfo], aBackendInfo, 
+      AC_MEMCPY(&newBackendInfo[nBackendInfo], aBackendInfo, 
             sizeof(BackendInfo));
       backendInfo = newBackendInfo;
       nBackendInfo++;
index 8239c9c3ef726f7e165de84d4f8cb24802065698..b78d96504d96ec1a5439ed8bc03d66e4f51d2614 100644 (file)
@@ -37,6 +37,7 @@ do_bind(
        ber_int_t               version;
        ber_tag_t method;
        char            *mech;
+       char            *saslmech;
        char            *dn;
        char *ndn;
        ber_tag_t       tag;
@@ -185,6 +186,7 @@ do_bind(
 
        if ( method == LDAP_AUTH_SASL ) {
                char *edn;
+               unsigned long ssf = 0;
 
                if ( version < LDAP_VERSION3 ) {
                        Debug( LDAP_DEBUG_ANY, "do_bind: sasl with LDAPv%ld\n",
@@ -204,30 +206,15 @@ do_bind(
                        goto cleanup;
                }
 
-               if( !charray_inlist( supportedSASLMechanisms, mech ) ) {
-                       Debug( LDAP_DEBUG_ANY,
-                               "do_bind: sasl mechanism=\"%s\" not supported.\n",
-                               mech, 0, 0 );
-                       send_ldap_result( conn, op, rc = LDAP_AUTH_METHOD_NOT_SUPPORTED,
-                               NULL, "SASL mechanism not supported", NULL, NULL );
-                       goto cleanup;
-               }
-
                ldap_pvt_thread_mutex_lock( &conn->c_mutex );
 
                if ( conn->c_sasl_bind_mech != NULL ) {
                        /* SASL bind is in progress */
-#ifdef HAVE_CYRUS_SASL
-                       assert( conn->c_sasl_bind_context != NULL );
-#endif
+                       saslmech = NULL;
 
                        if((strcmp(conn->c_sasl_bind_mech, mech) != 0)) {
                                /* mechanism changed */
-#ifdef HAVE_CYRUS_SASL
-                               /* dispose of context */
-                               sasl_dispose(&conn->c_sasl_bind_context);
-                               conn->c_sasl_bind_context = NULL;
-#endif
+                               slap_sasl_reset(conn);
                        }
 
                        free( conn->c_sasl_bind_mech );
@@ -236,39 +223,30 @@ do_bind(
 #ifdef LDAP_DEBUG
                } else {
                        /* SASL bind is NOT in progress */
+                       saslmech = mech;
                        assert( conn->c_sasl_bind_mech == NULL );
-#ifdef HAVE_CYRUS_SASL
-                       assert( conn->c_sasl_bind_context == NULL );
-#endif
 #endif
                }
 
                ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
 
                edn = NULL;
-               rc = sasl_bind( conn, op, dn, ndn, mech, &cred, &edn );
+               rc = slap_sasl_bind( conn, op, dn, ndn, saslmech, &cred,
+                       &edn, &ssf );
 
                if( rc == LDAP_SUCCESS ) {
                        ldap_pvt_thread_mutex_lock( &conn->c_mutex );
-#ifdef HAVE_CYRUS_SASL
-                       assert( conn->c_sasl_bind_context == NULL );
-#endif
                        conn->c_dn = edn;
+                       conn->c_authmech = mech;
+                       if( ssf ) conn->c_sasl_layers++;
                        ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
 
                } else if ( rc == LDAP_SASL_BIND_IN_PROGRESS ) {
-#ifdef HAVE_CYRUS_SASL
-                       assert( conn->c_sasl_bind_context != NULL );
-#endif
                        conn->c_sasl_bind_mech = mech;
-                       mech = NULL;
-
-#ifdef HAVE_CYRUS_SASL
-               } else {
-                       assert( conn->c_sasl_bind_context == NULL );
-#endif
                }
 
+               mech = NULL;
+
                goto cleanup;
 
        } else {
@@ -281,18 +259,11 @@ do_bind(
                        free(conn->c_sasl_bind_mech);
                        conn->c_sasl_bind_mech = NULL;
 
-#ifdef HAVE_CYRUS_SASL
-                       assert( conn->c_sasl_bind_context != NULL );
-                       sasl_dispose(&conn->c_sasl_bind_context);
-                       conn->c_sasl_bind_context = NULL;
-#endif
                } else {
                        assert( !conn->c_sasl_bind_in_progress );
-#ifdef HAVE_CYRUS_SASL
-                       assert( conn->c_sasl_bind_context == NULL );
-#endif
                }
 
+               slap_sasl_reset( conn );
                ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
        }
 
@@ -390,14 +361,6 @@ cleanup:
                free( conn->c_sasl_bind_mech );
                conn->c_sasl_bind_mech = NULL;
 
-#ifdef HAVE_CYRUS_SASL
-               if( conn->c_sasl_bind_context != NULL ) {
-                       /* dispose of context */
-                       sasl_dispose(&conn->c_sasl_bind_context);
-                       conn->c_sasl_bind_context = NULL;
-               }
-#endif
-
                ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
        }
 
index e031402ec8469d8b22abdc85a7dcd090180130f0..01ee0a1cd7286ba978d251af70a07c528ce20648 100644 (file)
@@ -48,7 +48,7 @@ read_config( const char *fname )
        FILE    *fp;
        char    *line, *savefname, *saveline;
        int     cargc, savelineno;
-       char    *cargv[MAXARGS];
+       char    *cargv[MAXARGS+1];
        int     lineno, i;
 #ifdef HAVE_TLS
        int rc;
@@ -116,7 +116,7 @@ read_config( const char *fname )
 
                        if( bi == NULL ) {
                                Debug( LDAP_DEBUG_ANY,
-                                       "backend %s initialization failed.n",
+                                       "backend %s initialization failed.\n",
                                    cargv[1], 0, 0 );
                                return( 1 );
                        }
@@ -135,7 +135,7 @@ read_config( const char *fname )
 
                        if( be == NULL ) {
                                Debug( LDAP_DEBUG_ANY,
-                                       "database %s initialization failed.n",
+                                       "database %s initialization failed.\n",
                                    cargv[1], 0, 0 );
                                return( 1 );
                        }
@@ -208,7 +208,7 @@ read_config( const char *fname )
                } else if ( strcasecmp( cargv[0], "password-hash" ) == 0 ) {
                        if ( cargc < 2 ) {
                                Debug( LDAP_DEBUG_ANY,
-           "%s: line %d: missing realm in \"password-hash <hash>\" line\n",
+           "%s: line %d: missing hash in \"password-hash <hash>\" line\n",
                                    fname, lineno, 0 );
                                return( 1 );
                        }
@@ -222,11 +222,11 @@ read_config( const char *fname )
                                default_passwd_hash = ch_strdup( cargv[1] );
                        }
 
-               /* set DIGEST realm */
-               } else if ( strcasecmp( cargv[0], "digest-realm" ) == 0 ) {
+               /* set SASL realm */
+               } else if ( strcasecmp( cargv[0], "sasl-realm" ) == 0 ) {
                        if ( cargc < 2 ) {
                                Debug( LDAP_DEBUG_ANY,
-           "%s: line %d: missing realm in \"digest-realm <realm>\" line\n",
+           "%s: line %d: missing realm in \"sasl-realm <realm>\" line\n",
                                    fname, lineno, 0 );
                                return( 1 );
                        }
@@ -243,6 +243,25 @@ read_config( const char *fname )
                                global_realm = ch_strdup( cargv[1] );
                        }
 
+               /* SASL security properties */
+               } else if ( strcasecmp( cargv[0], "sasl-secprops" ) == 0 ) {
+                       char *txt;
+
+                       if ( cargc < 2 ) {
+                               Debug( LDAP_DEBUG_ANY,
+           "%s: line %d: missing flags in \"sasl-secprops <properties>\" line\n",
+                                   fname, lineno, 0 );
+                               return 1;
+                       }
+
+                       txt = slap_sasl_secprops( cargv[1] );
+                       if ( txt != NULL ) {
+                               Debug( LDAP_DEBUG_ANY,
+           "%s: line %d: sasl-secprops: %s\n",
+                                   fname, lineno, txt );
+                               return 1;
+                       }
+
                /* set time limit */
                } else if ( strcasecmp( cargv[0], "sizelimit" ) == 0 ) {
                        if ( cargc < 2 ) {
@@ -863,12 +882,12 @@ strtok_quote( char *line, char *sep )
                        } else {
                                inquote = 1;
                        }
-                       SAFEMEMCPY( next, next + 1, strlen( next + 1 ) + 1 );
+                       AC_MEMCPY( next, next + 1, strlen( next + 1 ) + 1 );
                        break;
 
                case '\\':
                        if ( next[1] )
-                               SAFEMEMCPY( next,
+                               AC_MEMCPY( next,
                                            next + 1, strlen( next + 1 ) + 1 );
                        next++;         /* dont parse the escaped character */
                        break;
index a86d9b0f377aa0b08c8096e430144372508c76fe..a966c0f1747105f4226a7ad5e8a794f5c8c41536 100644 (file)
@@ -288,7 +288,9 @@ long connection_init(
        const char* dnsname,
        const char* peername,
        const char* sockname,
-       int use_tls )
+       int use_tls,
+       unsigned ssf,
+       char *authid )
 {
        unsigned long id;
        Connection *c;
@@ -376,9 +378,8 @@ long connection_init(
         c->c_pending_ops = NULL;
 
                c->c_sasl_bind_mech = NULL;
-#ifdef HAVE_CYRUS_SASL
-               c->c_sasl_bind_context = NULL;
-#endif
+               c->c_sasl_context = NULL;
+               c->c_sasl_extra = NULL;
 
         c->c_sb = ber_sockbuf_alloc( );
                c->c_currentber = NULL;
@@ -404,9 +405,8 @@ long connection_init(
     assert( c->c_ops == NULL );
     assert( c->c_pending_ops == NULL );
        assert( c->c_sasl_bind_mech == NULL );
-#ifdef HAVE_CYRUS_SASL
-       assert( c->c_sasl_bind_context == NULL );
-#endif
+       assert( c->c_sasl_context == NULL );
+       assert( c->c_sasl_extra == NULL );
        assert( c->c_currentber == NULL );
 
        c->c_listener_url = ch_strdup( url  );
@@ -441,6 +441,7 @@ long connection_init(
             s, c->c_peer_name, 0 );
     }
 
+
     id = c->c_connid = conn_nextid++;
 
     c->c_conn_state = SLAP_C_INACTIVE;
@@ -455,6 +456,8 @@ long connection_init(
            c->c_needs_tls_accept = 0;
     }
 #endif
+       slap_sasl_open( c );
+       slap_sasl_external( c, ssf, authid );
 
     ldap_pvt_thread_mutex_unlock( &c->c_mutex );
     ldap_pvt_thread_mutex_unlock( &connections_mutex );
@@ -504,7 +507,7 @@ connection_destroy( Connection *c )
                c->c_peer_domain = NULL;
        }
        if(c->c_peer_name != NULL) {
-#ifdef LDAP_PF_UNIX
+#ifdef LDAP_PF_lOCAL
                /*
                 * If peer was a domain socket, unlink. Mind you,
                 * they may be un-named. Should we leave this to
@@ -516,7 +519,7 @@ connection_destroy( Connection *c )
                                (void)unlink(path);
                        }
                }
-#endif /* LDAP_PF_UNIX */
+#endif /* LDAP_PF_LOCAL */
 
                free(c->c_peer_name);
                c->c_peer_name = NULL;
@@ -531,12 +534,8 @@ connection_destroy( Connection *c )
                free(c->c_sasl_bind_mech);
                c->c_sasl_bind_mech = NULL;
        }
-#ifdef HAVE_CYRUS_SASL
-       if(c->c_sasl_bind_context != NULL ) {
-               sasl_dispose( &c->c_sasl_bind_context );
-               c->c_sasl_bind_context = NULL;
-       }
-#endif
+
+       slap_sasl_close( c );
 
        if ( c->c_currentber != NULL ) {
                ber_free( c->c_currentber, 1 );
@@ -896,8 +895,9 @@ int connection_read(ber_socket_t s)
                        fd_set rfd;
 
                        Debug( LDAP_DEBUG_TRACE,
-                              "connection_read(%d): TLS accept error error=%d id=%ld, closing\n",
-                              s, rc, c->c_connid );
+                               "connection_read(%d): TLS accept error "
+                               "error=%d id=%ld, closing\n",
+                               s, rc, c->c_connid );
 
                        c->c_needs_tls_accept = 0;
                        /* connections_mutex and c_mutex are locked */
@@ -917,8 +917,14 @@ int connection_read(ber_socket_t s)
                                    NULL);
                        }
                        connection_close( c );
+
                } else if ( rc == 0 ) {
                        c->c_needs_tls_accept = 0;
+
+#if 0
+                       /* we need to let SASL know */
+                       slap_sasl_external( c, ssf, authid );
+#endif
                }
                connection_return( c );
                ldap_pvt_thread_mutex_unlock( &connections_mutex );
@@ -926,6 +932,28 @@ int connection_read(ber_socket_t s)
        }
 #endif
 
+#ifdef HAVE_CYRUS_SASL
+       if ( c->c_sasl_layers ) {
+               c->c_sasl_layers = 0;
+
+               rc = ldap_pvt_sasl_install( c->c_sb,  c->c_sasl_context );
+
+               if( rc != LDAP_SUCCESS ) {
+                       Debug( LDAP_DEBUG_TRACE,
+                               "connection_read(%d): SASL install error "
+                               "error=%d id=%ld, closing\n",
+                               s, rc, c->c_connid );
+
+                       /* connections_mutex and c_mutex are locked */
+                       connection_closing( c );
+                       connection_close( c );
+                       connection_return( c );
+                       ldap_pvt_thread_mutex_unlock( &connections_mutex );
+                       return 0;
+               }
+       }
+#endif
+
 #define CONNECTION_INPUT_LOOP 1
 
 #ifdef DATA_READY_LOOP
@@ -1093,7 +1121,6 @@ connection_resched( Connection *conn )
 static int connection_op_activate( Connection *conn, Operation *op )
 {
        struct co_arg *arg;
-       char *tmpdn;
        int status;
        ber_tag_t tag = op->o_tag;
 
@@ -1101,17 +1128,11 @@ static int connection_op_activate( Connection *conn, Operation *op )
                conn->c_conn_state = SLAP_C_BINDING;
        }
 
-       if ( conn->c_dn != NULL ) {
-               tmpdn = ch_strdup( conn->c_dn );
-       } else {
-               tmpdn = NULL;
-       }
-
        arg = (struct co_arg *) ch_malloc( sizeof(struct co_arg) );
        arg->co_conn = conn;
        arg->co_op = op;
 
-       arg->co_op->o_dn = ch_strdup( tmpdn != NULL ? tmpdn : "" );
+       arg->co_op->o_dn = ch_strdup( conn->c_dn != NULL ? conn->c_dn : "" );
        arg->co_op->o_ndn = ch_strdup( arg->co_op->o_dn );
        (void) dn_normalize( arg->co_op->o_ndn );
 
@@ -1124,17 +1145,12 @@ static int connection_op_activate( Connection *conn, Operation *op )
        
        slap_op_add( &conn->c_ops, arg->co_op );
 
-       if( tmpdn != NULL ) {
-               free( tmpdn );
-       }
-
        status = ldap_pvt_thread_pool_submit( &connection_pool,
                connection_operation, (void *) arg );
 
        if ( status != 0 ) {
                Debug( LDAP_DEBUG_ANY,
-               "ldap_pvt_thread_create failed (%d)\n", status, 0, 0 );
-
+               "ldap_pvt_thread_pool_submit failed (%d)\n", status, 0, 0 );
                /* should move op to pending list */
        }
 
index 88dcd60d4694c547108b7cc8cb88be7c4a156934..59c4143b77bbabb7bfccff5bc8ac2909d6c8bb75 100644 (file)
@@ -27,9 +27,9 @@ int allow_severity = LOG_INFO;
 int deny_severity = LOG_NOTICE;
 #endif /* TCP Wrappers */
 
-#ifdef LDAP_PF_UNIX
+#ifdef LDAP_PF_LOCAL
 #include <sys/stat.h>
-#endif /* LDAP_PF_UNIX */
+#endif /* LDAP_PF_LOCAL */
 
 /* globals */
 time_t starttime;
@@ -41,7 +41,7 @@ typedef union slap_sockaddr {
 #ifdef LDAP_PF_INET6
        struct sockaddr_in6 sa_in6_addr;
 #endif
-#ifdef LDAP_PF_UNIX
+#ifdef LDAP_PF_LOCAL
        struct sockaddr_un sa_un_addr;
 #endif
 } Sockaddr;
@@ -244,7 +244,7 @@ static Listener * open_listener( const char* url )
        hints.ai_family = AF_UNSPEC;
        hints.ai_socktype = SOCK_STREAM;
 
-#  ifdef LDAP_PF_UNIX
+#  ifdef LDAP_PF_LOCAL
        if ( ldap_pvt_url_scheme2proto(lud->lud_scheme) == LDAP_PROTO_IPC ) {
                if ( lud->lud_host == NULL || lud->lud_host[0] == '\0' ) {
                        err = getaddrinfo(NULL, LDAPI_SOCK, &hints, &res);
@@ -256,7 +256,7 @@ static Listener * open_listener( const char* url )
                                unlink( lud->lud_host );
                }
        } else
-#  endif /* LDAP_PF_UNIX */
+#  endif /* LDAP_PF_LOCAL */
        {
                snprintf(serv, sizeof serv, "%d", lud->lud_port);
                if( lud->lud_host == NULL || lud->lud_host[0] == '\0'
@@ -286,15 +286,15 @@ static Listener * open_listener( const char* url )
                        continue;
                }
 
-               if ( sai->ai_family != AF_UNIX ) {
+               if ( sai->ai_family != AF_LOCAL ) {
 #else
 
        if ( ldap_pvt_url_scheme2proto(lud->lud_scheme) == LDAP_PROTO_IPC ) {
-#ifdef LDAP_PF_UNIX
+#ifdef LDAP_PF_LOCAL
                port = 0;
                (void) memset( (void *)&l.sl_sa.sa_un_addr, '\0', sizeof(l.sl_sa.sa_un_addr) );
 
-               l.sl_sa.sa_un_addr.sun_family = AF_UNIX;
+               l.sl_sa.sa_un_addr.sun_family = AF_LOCAL;
 
                /* hack: overload the host to be the path */
                if ( lud->lud_host == NULL || lud->lud_host[0] == '\0' ) {
@@ -321,7 +321,7 @@ static Listener * open_listener( const char* url )
                        url, 0, 0);
                ldap_free_urldesc( lud );
                return NULL;
-#endif /* LDAP_PF_UNIX */
+#endif /* LDAP_PF_LOCAL */
        } else {
 
        port = lud->lud_port;
@@ -348,7 +348,7 @@ static Listener * open_listener( const char* url )
                                return NULL;
                        }
 
-                       memcpy( &l.sl_addr.sin_addr, he->h_addr,
+                       AC_MEMCPY( &l.sl_addr.sin_addr, he->h_addr,
                               sizeof( l.sl_addr.sin_addr ) );
                }
        }
@@ -375,10 +375,10 @@ static Listener * open_listener( const char* url )
        }
 #endif
 
-#ifdef LDAP_PF_UNIX
+#ifdef LDAP_PF_LOCAL
        /* for IP sockets only */
        if ( l.sl_sa.sa_addr.sa_family == AF_INET ) {
-#endif /* LDAP_PF_UNIX */
+#endif /* LDAP_PF_LOCAL */
 #endif /* HAVE_GETADDRINFO */
 
 #ifdef SO_REUSEADDR
@@ -419,7 +419,7 @@ static Listener * open_listener( const char* url )
 #endif
 
 #ifdef HAVE_GETADDRINFO
-               } /* sai->ai_family != AF_UNIX */
+               } /* sai->ai_family != AF_LOCAL */
                if (!bind(l.sl_sd, sai->ai_addr, sai->ai_addrlen))
                        break;
                err = sock_errno();
@@ -435,8 +435,8 @@ static Listener * open_listener( const char* url )
        }
 
        switch ( sai->ai_family ) {
-#  ifdef LDAP_PF_UNIX
-       case AF_UNIX:
+#  ifdef LDAP_PF_LOCAL
+       case AF_LOCAL:
                if ( chmod( (char *)sai->ai_addr, S_IRWXU ) < 0 ) {
                        int err = sock_errno();
                        Debug( LDAP_DEBUG_ANY, "daemon: fchmod(%ld) failed errno=%d (%s)",
@@ -447,7 +447,7 @@ static Listener * open_listener( const char* url )
                l.sl_name = ch_malloc( strlen((char *)sai->ai_addr) + sizeof("PATH=") );
                sprintf( l.sl_name, "PATH=%s", sai->ai_addr );
                break;
-#  endif /* LDAP_PF_UNIX */
+#  endif /* LDAP_PF_LOCAL */
 
        case AF_INET: {
                char addr[INET_ADDRSTRLEN];
@@ -475,14 +475,14 @@ static Listener * open_listener( const char* url )
                break;
        }
 #else
-#ifdef LDAP_PF_UNIX
+#ifdef LDAP_PF_LOCAL
        /* close conditional */
        }
-#endif /* LDAP_PF_UNIX */
+#endif /* LDAP_PF_LOCAL */
 
        switch ( l.sl_sa.sa_addr.sa_family ) {
-#ifdef LDAP_PF_UNIX
-               case AF_UNIX:
+#ifdef LDAP_PF_LOCAL
+               case AF_LOCAL:
                        rc = bind( l.sl_sd, (struct sockaddr *)&l.sl_sa,
                                sizeof(l.sl_sa.sa_un_addr) );
                        break;
@@ -508,8 +508,8 @@ static Listener * open_listener( const char* url )
        }
 
        switch ( l.sl_sa.sa_addr.sa_family ) {
-#ifdef LDAP_PF_UNIX
-               case AF_UNIX:
+#ifdef LDAP_PF_LOCAL
+               case AF_LOCAL:
                        if ( chmod( l.sl_sa.sa_un_addr.sun_path, S_IRWXU ) < 0 ) {
                                int err = sock_errno();
                                Debug( LDAP_DEBUG_ANY,
@@ -523,7 +523,7 @@ static Listener * open_listener( const char* url )
                                + sizeof("PATH=") );
                        sprintf( l.sl_name, "PATH=%s", l.sl_sa.sa_un_addr.sun_path );
                        break;
-#endif /* LDAP_PF_UNIX */
+#endif /* LDAP_PF_LOCAL */
 
                case AF_INET:
                        l.sl_name = ch_malloc( sizeof("IP=255.255.255.255:65336") );
@@ -689,7 +689,7 @@ slapd_daemon_task(
                int ns;
                int at;
                ber_socket_t nfds;
-#define SLAPD_EBADF_LIMIT 10
+#define SLAPD_EBADF_LIMIT 16
                int ebadf = 0;
 
 #define SLAPD_IDLE_CHECK_LIMIT 4
@@ -731,8 +731,8 @@ slapd_daemon_task(
                        }
                }
 #else
-               memcpy( &readfds, &slap_daemon.sd_readers, sizeof(fd_set) );
-               memcpy( &writefds, &slap_daemon.sd_writers, sizeof(fd_set) );
+               AC_MEMCPY( &readfds, &slap_daemon.sd_readers, sizeof(fd_set) );
+               AC_MEMCPY( &writefds, &slap_daemon.sd_writers, sizeof(fd_set) );
 #endif
                assert(!FD_ISSET(wake_sds[0], &readfds));
                FD_SET( wake_sds[0], &readfds );
@@ -783,8 +783,9 @@ slapd_daemon_task(
                                int err = sock_errno();
 
                                if( err == EBADF 
-#ifdef HAVE_WINSOCK
-                                       || err == WSAENOTSOCK   /* you'd think this would be EBADF */
+#ifdef WSAENOTSOCK
+                                       /* you'd think this would be EBADF */
+                                       || err == WSAENOTSOCK
 #endif
                                ) {
                                        if (++ebadf < SLAPD_EBADF_LIMIT)
@@ -828,16 +829,18 @@ slapd_daemon_task(
                        ber_int_t s;
                        socklen_t len = sizeof(from);
                        long id;
+                       unsigned ssf = 0;
+                       char *authid = NULL;
 
                        char    *dnsname;
                        char    *peeraddr;
-#ifdef LDAP_PF_UNIX
+#ifdef LDAP_PF_LOCAL
                        char    peername[MAXPATHLEN + sizeof("PATH=")];
 #elif defined(LDAP_PF_INET6)
                        char    peername[sizeof("IP=ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff 65535")];
 #else
                        char    peername[sizeof("IP=255.255.255.255:65336")];
-#endif /* LDAP_PF_UNIX */
+#endif /* LDAP_PF_LOCAL */
 
                        peername[0] = '\0';
 
@@ -896,11 +899,12 @@ slapd_daemon_task(
                        }
 
                        switch ( from.sa_addr.sa_family ) {
-#  ifdef LDAP_PF_UNIX
-                       case AF_UNIX:
+#  ifdef LDAP_PF_LOCAL
+                       case AF_LOCAL:
                                sprintf( peername, "PATH=%s", from.sa_un_addr.sun_path );
+                               ssf = LDAP_PVT_SASL_LOCAL_SSF;
                                break;
-#endif /* LDAP_PF_UNIX */
+#endif /* LDAP_PF_LOCAL */
 
 #  ifdef LDAP_PF_INET6
                        case AF_INET6: {
@@ -955,7 +959,7 @@ slapd_daemon_task(
                                {
                                        /* DENY ACCESS */
                                        Statslog( LDAP_DEBUG_ANY,
-                                               "fd=%ld connection from %s (%s) denied.\n",
+                                               "fd=%ld host access from %s (%s) denied.\n",
                                                (long) s,
                                                dnsname != NULL ? dnsname : "unknown",
                                                peeraddr != NULL ? peeraddr : "unknown",
@@ -966,18 +970,22 @@ slapd_daemon_task(
 #endif /* HAVE_TCPD */
                        }
 
-                       if( (id = connection_init(s,
+                       id = connection_init(s,
                                slap_listeners[l]->sl_url,
                                dnsname != NULL ? dnsname : "unknown",
                                peername,
                                slap_listeners[l]->sl_name,
 #ifdef HAVE_TLS
-                               slap_listeners[l]->sl_is_tls
+                               slap_listeners[l]->sl_is_tls,
 #else
-                               0
+                               0,
 #endif
-                               )) < 0 )
-                       {
+                               ssf,
+                               authid );
+
+                       if( authid ) ch_free(authid);
+
+                       if( id < 0 ) {
                                Debug( LDAP_DEBUG_ANY,
                                        "daemon: connection_init(%ld, %s, %s) failed.\n",
                                        (long) s,
@@ -1147,11 +1155,11 @@ slapd_daemon_task(
 
        for ( l = 0; slap_listeners[l] != NULL; l++ ) {
                if ( slap_listeners[l]->sl_sd != AC_SOCKET_INVALID ) {
-#ifdef LDAP_PF_UNIX
-                       if ( slap_listeners[l]->sl_sa.sa_addr.sa_family == AF_UNIX ) {
+#ifdef LDAP_PF_LOCAL
+                       if ( slap_listeners[l]->sl_sa.sa_addr.sa_family == AF_LOCAL ) {
                                unlink( slap_listeners[l]->sl_sa.sa_un_addr.sun_path );
                        }
-#endif /* LDAP_PF_UNIX */
+#endif /* LDAP_PF_LOCAL */
                        slapd_close( slap_listeners[l]->sl_sd );
                        break;
                }
@@ -1198,9 +1206,9 @@ int slapd_daemon( void )
 
 }
 
-#ifdef HAVE_WINSOCK2
 int sockinit(void)
 {
+#if defined( HAVE_WINSOCK2 )
     WORD wVersionRequested;
        WSADATA wsaData;
        int err;
@@ -1230,40 +1238,22 @@ int sockinit(void)
        }
 
        /* The WinSock DLL is acceptable. Proceed. */
-       return 0;
-}
-
-int sockdestroy(void)
-{
-       WSACleanup();
-       return 0;
-}
-
-#elif HAVE_WINSOCK
-static int sockinit(void)
-{
+#elif defined( HAVE_WINSOCK )
        WSADATA wsaData;
        if ( WSAStartup( 0x0101, &wsaData ) != 0 ) {
            return -1;
        }
-       return 0;
-}
-static int sockdestroy(void)
-{
-       WSACleanup();
+#endif
        return 0;
 }
 
-#else
-static int sockinit(void)
-{
-       return 0;
-}
-static int sockdestroy(void)
+int sockdestroy(void)
 {
+#if defined( HAVE_WINSOCK2 ) || defined( HAVE_WINSOCK )
+       WSACleanup();
+#endif
        return 0;
 }
-#endif
 
 RETSIGTYPE
 slap_sig_shutdown( int sig )
@@ -1287,7 +1277,7 @@ slap_sig_shutdown( int sig )
        WAKE_LISTENER(1);
 
        /* reinstall self */
-       (void) SIGNAL( sig, slap_sig_shutdown );
+       (void) SIGNAL_REINSTALL( sig, slap_sig_shutdown );
 }
 
 RETSIGTYPE
@@ -1296,5 +1286,5 @@ slap_sig_wake( int sig )
        WAKE_LISTENER(1);
 
        /* reinstall self */
-       (void) SIGNAL( sig, slap_sig_wake );
+       (void) SIGNAL_REINSTALL( sig, slap_sig_wake );
 }
index e4bcf3c23e7814e4754fdf36bf15b904623c58e7..551f21c3d7a3fafea34db36d15811f0d305114ca 100644 (file)
@@ -171,6 +171,8 @@ test_ava_filter(
                        mr = a->a_desc->ad_type->sat_approx;
                        if( mr != NULL ) break;
 
+                       /* use EQUALITY matching rule if no APPROX rule */
+
                case LDAP_FILTER_EQUALITY:
                        mr = a->a_desc->ad_type->sat_equality;
                        break;
index 2e25add973103433bed16616821137b00541a14e..5c41461dff564551cc0b36ba44e0c3e1dafe3591 100644 (file)
@@ -107,7 +107,11 @@ slap_init( int mode, const char *name )
                        ldap_pvt_thread_mutex_init( &crypt_mutex );
 #endif
 
-                       rc = backend_init( );
+                       rc = slap_sasl_init();
+
+                       if( rc == 0 ) {
+                               rc = backend_init( );
+                       }
                        break;
 
                default:
@@ -130,10 +134,6 @@ int slap_startup( Backend *be )
 
        rc = backend_startup( be );
 
-       if( rc == 0 ) {
-               rc = sasl_init();
-       }
-
        return rc;
 }
 
@@ -145,7 +145,7 @@ int slap_shutdown( Backend *be )
                "%s shutdown: initiated\n",
                slap_name, 0, 0 );
 
-       sasl_destroy();
+       slap_sasl_destroy();
 
        /* let backends do whatever cleanup they need to do */
        rc = backend_shutdown( be ); 
index 66825e5a64cc0df076d56b282bd6582ed41c107e..344247cf562d893c97c836f9b7b4546eef300343 100644 (file)
@@ -32,7 +32,7 @@ krbv4_ldap_auth(
 
        Debug( LDAP_DEBUG_TRACE, "=> kerberosv4_ldap_auth\n", 0, 0, 0 );
 
-       SAFEMEMCPY( ktxt->dat, cred->bv_val, cred->bv_len );
+       AC_MEMCPY( ktxt->dat, cred->bv_val, cred->bv_len );
        ktxt->length = cred->bv_len;
 
        strcpy( instance, "*" );
index c4f610bbb248e9540b291aa734a677f9f224eb5d..c9d765b0c838e5c84a31fa7712080141c26f09b0 100644 (file)
@@ -13,7 +13,6 @@
 #include <ac/time.h>
 #include <ac/unistd.h>
 #include <ac/wait.h>
-#include <ac/signal.h>
 #include <ac/errno.h>
 
 #include "slap.h"
@@ -516,7 +515,7 @@ wait4child( int sig )
 #else
     (void) wait( NULL );
 #endif
-    (void) SIGNAL( sig, wait4child );
+    (void) SIGNAL_REINSTALL( sig, wait4child );
     errno = save_errno;
 }
 
index ce1cd803da0c06ccfff5b6f528757009d6022f9c..1c337c53b98cf290fe68fb95afd570605949b484 100644 (file)
@@ -49,7 +49,6 @@ monitor_info(
        vals[1] = NULL;
 
        e = (Entry *) ch_calloc( 1, sizeof(Entry) );
-       /* initialize reader/writer lock */
        e->e_attrs = NULL;
        e->e_dn = ch_strdup( SLAPD_MONITOR_DN );
        e->e_ndn = ch_strdup(SLAPD_MONITOR_DN);
index d84694450cdb9e9ed463a0f986ccc524f47026d5..1f1257da97b3fc18cd6b001f8e90ac3e4036da90 100644 (file)
@@ -109,13 +109,14 @@ mr_insert(
 
 int
 mr_add(
-    LDAP_MATCHING_RULE         *mr,
+    LDAPMatchingRule           *mr,
        unsigned usage,
        slap_mr_convert_func *convert,
        slap_mr_normalize_func *normalize,
     slap_mr_match_func *match,
        slap_mr_indexer_func *indexer,
     slap_mr_filter_func        *filter,
+       MatchingRule    *amr,
     const char         **err
 )
 {
@@ -124,7 +125,7 @@ mr_add(
        int             code;
 
        smr = (MatchingRule *) ch_calloc( 1, sizeof(MatchingRule) );
-       memcpy( &smr->smr_mrule, mr, sizeof(LDAP_MATCHING_RULE));
+       AC_MEMCPY( &smr->smr_mrule, mr, sizeof(LDAPMatchingRule));
 
        smr->smr_usage = usage;
        smr->smr_convert = convert;
@@ -132,6 +133,7 @@ mr_add(
        smr->smr_match = match;
        smr->smr_indexer = indexer;
        smr->smr_filter = filter;
+       smr->smr_associated = amr;
 
        if ( smr->smr_syntax_oid ) {
                if ( (syn = syn_find(smr->smr_syntax_oid)) ) {
@@ -157,9 +159,11 @@ register_matching_rule(
        slap_mr_normalize_func *normalize,
        slap_mr_match_func *match,
        slap_mr_indexer_func *indexer,
-       slap_mr_filter_func *filter )
+       slap_mr_filter_func *filter,
+       const char* associated )
 {
-       LDAP_MATCHING_RULE *mr;
+       LDAPMatchingRule *mr;
+       MatchingRule *amr = NULL;
        int             code;
        const char      *err;
 
@@ -169,6 +173,22 @@ register_matching_rule(
                return -1;
        }
 
+       if( associated != NULL ) {
+               amr = mr_find( associated );
+
+#if 0
+               /* ignore for now */
+
+               if( amr == NULL ) {
+                       Debug( LDAP_DEBUG_ANY, "register_matching_rule: could not locate "
+                               "associated matching rule %s for %s\n",
+                               associated, desc, 0 );
+                       return -1;
+               }
+#endif
+
+       }
+
        mr = ldap_str2matchingrule( desc, &code, &err, LDAP_SCHEMA_ALLOW_ALL);
        if ( !mr ) {
                Debug( LDAP_DEBUG_ANY, "Error in register_matching_rule: %s before %s in %s\n",
@@ -177,9 +197,11 @@ register_matching_rule(
        }
 
        code = mr_add( mr, usage,
-               convert, normalize, match, indexer, filter,
+               convert, normalize, match, indexer, filter, amr,
                &err );
 
+       ldap_memfree( mr );
+
        if ( code ) {
                Debug( LDAP_DEBUG_ANY, "Error in register_syntax: %s for %s in %s\n",
                    scherr2str(code), err, desc );
index 1817fe114335178e3cd8166195e9acdf94744948..8ffd3d43c0b00e68eada4e46fafc9e967c44420b 100644 (file)
@@ -330,7 +330,7 @@ oc_insert(
 
 int
 oc_add(
-    LDAP_OBJECT_CLASS  *oc,
+    LDAPObjectClass    *oc,
     const char         **err
 )
 {
@@ -338,7 +338,7 @@ oc_add(
        int             code;
 
        soc = (ObjectClass *) ch_calloc( 1, sizeof(ObjectClass) );
-       memcpy( &soc->soc_oclass, oc, sizeof(LDAP_OBJECT_CLASS) );
+       AC_MEMCPY( &soc->soc_oclass, oc, sizeof(LDAPObjectClass) );
 
        if( soc->soc_sup_oids == NULL &&
                soc->soc_kind == LDAP_SCHEMA_STRUCTURAL )
index 80adc78a34772deee634a80341bca2a44f9d5a0a..4a925383e748c7d8b5b53d67597f7280b9cf7252 100644 (file)
@@ -16,8 +16,8 @@
 
 #include "slap.h"
 
-#if !defined(METAPHONE) && !defined(SLAPD_PHONETIC)
-#define METAPHONE
+#if !defined(SLAPD_METAPHONE) && !defined(SLAPD_PHONETIC)
+#define SLAPD_METAPHONE
 #endif
 
 #define iswordbreak(x)  (!isascii(x) || isspace((unsigned char) (x)) || \
@@ -162,7 +162,7 @@ phonetic( char *s )
 }
 
 #else
-#if defined(METAPHONE)
+#if defined(SLAPD_METAPHONE)
 
 /*
  * Metaphone copied from C Gazette, June/July 1991, pp 56-57,
index 27cf5cedffe305665cf49d7f8ba41a8fb8e96cdc..2c69c2a27eed4e2ac1c91eff6a5cc35cf283adf7 100644 (file)
@@ -90,7 +90,7 @@ LDAP_SLAPD_F (int) at_find_in_list LDAP_P(( AttributeType *sat, AttributeType **
 LDAP_SLAPD_F (int) at_append_to_list LDAP_P(( AttributeType *sat, AttributeType ***listp ));
 LDAP_SLAPD_F (int) at_delete_from_list LDAP_P(( int pos, AttributeType ***listp ));
 LDAP_SLAPD_F (int) at_schema_info LDAP_P(( Entry *e ));
-LDAP_SLAPD_F (int) at_add LDAP_P(( LDAP_ATTRIBUTE_TYPE *at, const char **err ));
+LDAP_SLAPD_F (int) at_add LDAP_P(( LDAPAttributeType *at, const char **err ));
 
 LDAP_SLAPD_F (int) is_at_subtype LDAP_P((
        AttributeType *sub,
@@ -268,7 +268,9 @@ LDAP_SLAPD_F (long) connection_init LDAP_P((
        const char* dnsname,
        const char* peername,
        const char* sockname,
-       int use_tls ));
+       int use_tls,
+       unsigned ssf,
+       char *id ));
 
 LDAP_SLAPD_F (void) connection_closing LDAP_P(( Connection *c ));
 LDAP_SLAPD_F (int) connection_state_closing LDAP_P(( Connection *c ));
@@ -526,16 +528,26 @@ LDAP_SLAPD_F (int) str2result LDAP_P(( char *s,
 /*
  * sasl.c
  */
-LDAP_SLAPD_F (char **) supportedSASLMechanisms;
 
-LDAP_SLAPD_F (int) sasl_init(void);
-LDAP_SLAPD_F (int) sasl_destroy(void);
-LDAP_SLAPD_F (int) sasl_errldap LDAP_P(( int ));
-LDAP_SLAPD_F (int) sasl_bind LDAP_P((
+LDAP_SLAPD_F (int) slap_sasl_init(void);
+LDAP_SLAPD_F (char *) slap_sasl_secprops( const char * );
+LDAP_SLAPD_F (int) slap_sasl_destroy(void);
+
+LDAP_SLAPD_F (int) slap_sasl_open( Connection *c );
+LDAP_SLAPD_F (char **) slap_sasl_mechs( Connection *c );
+
+LDAP_SLAPD_F (int) slap_sasl_external( Connection *c,
+       unsigned ssf,   /* relative strength of external security */
+       char *authid ); /* asserted authenication id */
+
+LDAP_SLAPD_F (int) slap_sasl_reset( Connection *c );
+LDAP_SLAPD_F (int) slap_sasl_close( Connection *c );
+
+LDAP_SLAPD_F (int) slap_sasl_bind LDAP_P((
        Connection *conn, Operation *op, 
        const char *dn, const char *ndn,
        const char *mech, struct berval *cred,
-       char **edn ));
+       char **edn, unsigned long *ssf ));
 
 /* oc.c */
 LDAP_SLAPD_F (int) oc_schema_info( Entry *e );
@@ -554,7 +566,7 @@ LDAP_SLAPD_F (ObjectClass *) oc_find LDAP_P((
        const char *ocname));
 
 LDAP_SLAPD_F (int) oc_add LDAP_P((
-       LDAP_OBJECT_CLASS *oc,
+       LDAPObjectClass *oc,
        const char **err));
 
 LDAP_SLAPD_F (int) is_object_subclass LDAP_P((
@@ -566,7 +578,7 @@ LDAP_SLAPD_F (Syntax *) syn_find LDAP_P((const char *synname));
 LDAP_SLAPD_F (Syntax *) syn_find_desc LDAP_P((const char *syndesc, int *slen));
 #ifdef SLAPD_BINARY_CONVERSION
 LDAP_SLAPD_F (int) syn_add LDAP_P((
-       LDAP_SYNTAX *syn,
+       LDAPSyntax *syn,
        unsigned flags,
        slap_syntax_validate_func *validate,
        slap_syntax_transform_func *normalize,
@@ -576,7 +588,7 @@ LDAP_SLAPD_F (int) syn_add LDAP_P((
        const char **err));
 #else
 LDAP_SLAPD_F (int) syn_add LDAP_P((
-       LDAP_SYNTAX *syn,
+       LDAPSyntax *syn,
        unsigned flags,
        slap_syntax_validate_func *validate,
        slap_syntax_transform_func *normalize,
@@ -585,13 +597,14 @@ LDAP_SLAPD_F (int) syn_add LDAP_P((
 #endif
 
 LDAP_SLAPD_F (MatchingRule *) mr_find LDAP_P((const char *mrname));
-LDAP_SLAPD_F (int) mr_add LDAP_P((LDAP_MATCHING_RULE *mr,
+LDAP_SLAPD_F (int) mr_add LDAP_P((LDAPMatchingRule *mr,
        unsigned usage,
        slap_mr_convert_func *convert,
        slap_mr_normalize_func *normalize,
        slap_mr_match_func *match,
        slap_mr_indexer_func *indexer,
        slap_mr_filter_func *filter,
+       MatchingRule * associated,
        const char **err));
 
 LDAP_SLAPD_F (int) register_syntax LDAP_P((
@@ -608,7 +621,8 @@ LDAP_SLAPD_F (int) register_matching_rule LDAP_P((
        slap_mr_normalize_func *normalize,
        slap_mr_match_func *match,
        slap_mr_indexer_func *indexer,
-       slap_mr_filter_func *filter     ));
+       slap_mr_filter_func *filter,
+       const char *associated ));
 
 LDAP_SLAPD_F (int) schema_info LDAP_P(( Entry **entry, const char **text ));
 
@@ -820,7 +834,9 @@ LDAP_SLAPD_F (int) config_info LDAP_P((
        Entry **e, const char **text ));
 
 LDAP_SLAPD_F (int) root_dse_info LDAP_P((
-       Entry **e, const char **text ));
+       Connection *conn,
+       Entry **e,
+       const char **text ));
 
 LDAP_SLAPD_F (int) do_abandon LDAP_P((Connection *conn, Operation *op));
 LDAP_SLAPD_F (int) do_add LDAP_P((Connection *conn, Operation *op));
index 7a7000d625850a74cfb04581ace1939d5107725e..d6c3bd4b52cee69619b284e5d7f52f0d0e34add9 100644 (file)
@@ -49,7 +49,7 @@ static char *v2ref( struct berval **ref, const char *text )
        for( i=0; ref[i] != NULL; i++ ) {
                v2 = ch_realloc( v2, len + ref[i]->bv_len + 1 );
                v2[len-1] = '\n';
-               memcpy(&v2[len], ref[i]->bv_val, ref[i]->bv_len );
+               AC_MEMCPY(&v2[len], ref[i]->bv_val, ref[i]->bv_len );
                len += ref[i]->bv_len;
                if (ref[i]->bv_val[ref[i]->bv_len-1] != '/')
                        ++len;
@@ -488,8 +488,8 @@ send_ldap_sasl(
        ber_tag_t tag;
        ber_int_t msgid;
 
-       Debug( LDAP_DEBUG_TRACE, "send_ldap_sasl %ld\n",
-               (long) err, NULL, NULL );
+       Debug( LDAP_DEBUG_TRACE, "send_ldap_sasl: err=%ld len=%ld\n",
+               (long) err, cred ? cred->bv_len : -1, NULL );
 
        tag = req2res( op->o_tag );
        msgid = (tag != LBER_SEQUENCE) ? op->o_msgid : 0;
index f987948c1e5506a9b94c84dd43ec00ba9f7bd461..8a9cfc653cb22a1792163ada04d538962981797a 100644 (file)
 #include "slap.h"
 
 int
-root_dse_info( Entry **entry, const char **text )
+root_dse_info(
+       Connection *conn,
+       Entry **entry,
+       const char **text )
 {
        char buf[BUFSIZ];
        Entry           *e;
        struct berval   val;
        struct berval   *vals[2];
        int             i, j;
+       char ** supportedSASLMechanisms;
 
        AttributeDescription *ad_objectClass = slap_schema.si_ad_objectClass;
        AttributeDescription *ad_namingContexts = slap_schema.si_ad_namingContexts;
@@ -85,6 +89,8 @@ root_dse_info( Entry **entry, const char **text )
        }
 
        /* supportedSASLMechanism */
+       supportedSASLMechanisms = slap_sasl_mechs( conn );
+
        if( supportedSASLMechanisms != NULL ) {
                for ( i=0; supportedSASLMechanisms[i] != NULL; i++ ) {
                        val.bv_val = supportedSASLMechanisms[i];
index 23dfaae8fa60ba99a4225198d5983c19323042a2..6e46d65fe3572308064423f935ce550b87409485 100644 (file)
 #include <lber.h>
 #include <ldap_log.h>
 
-char **supportedSASLMechanisms = NULL;
-char *sasl_host = NULL;
-
 #ifdef HAVE_CYRUS_SASL
+#include <limits.h>
+#include <sasl.h>
+
+#include <ldap_pvt.h>
 
 #ifdef SLAPD_SPASSWD
 #include <lutil.h>
 #endif
 
-static void *slap_sasl_mutex_new(void)
+static char *sasl_host = NULL;
+static sasl_security_properties_t sasl_secprops;
+
+
+static int
+slap_sasl_log(
+       void *context,
+       int priority,
+       const char *message) 
 {
-       ldap_pvt_thread_mutex_t *mutex;
+       Connection *conn = context;
+       int level;
+       const char * label;
 
-       mutex = (ldap_pvt_thread_mutex_t *) ch_malloc( sizeof(ldap_pvt_thread_mutex_t) );
-       if ( ldap_pvt_thread_mutex_init( mutex ) == 0 ) {
-               return mutex;
+       if ( message == NULL ) {
+               return SASL_BADPARAM;
        }
-       return NULL;
-}
 
-static int slap_sasl_mutex_lock(void *mutex)
-{
-       return ldap_pvt_thread_mutex_lock( (ldap_pvt_thread_mutex_t *)mutex );
-}
+       switch (priority) {
+       case SASL_LOG_ERR:
+               level = LDAP_DEBUG_ANY;
+               label = "Error";
+               break;
+       case SASL_LOG_WARNING:
+               level = LDAP_DEBUG_TRACE;
+               label = "Warning";
+               break;
+       case SASL_LOG_INFO:
+               level = LDAP_DEBUG_TRACE;
+               label = "Info";
+               break;
+       default:
+               return SASL_BADPARAM;
+       }
 
-static int slap_sasl_mutex_unlock(void *mutex)
-{
-       return ldap_pvt_thread_mutex_unlock( (ldap_pvt_thread_mutex_t *)mutex );
+       Debug( level, "SASL [conn=%d] %s: %s\n",
+               conn ? conn->c_connid: -1,
+               label, message );
+
+       return SASL_OK;
 }
 
-static void slap_sasl_mutex_dispose(void *mutex)
+static int
+slap_sasl_authorize(
+       void *context,
+       const char *authcid,
+       const char *authzid,
+       const char **user,
+       const char **errstr)
 {
-       (void) ldap_pvt_thread_mutex_destroy( (ldap_pvt_thread_mutex_t *)mutex );
-       free( mutex );
+       Connection *conn = context;
+
+       *user = NULL;
+
+       if ( authcid == NULL || *authcid == '\0' ) {
+               *errstr = "empty authentication identity";
+
+               Debug( LDAP_DEBUG_TRACE, "SASL Authorize [conn=%ld]: "
+                       "empty authentication identity\n",
+                       (long) (conn ? conn->c_connid : -1),
+                       0, 0 );
+               return SASL_BADAUTH;
+       }
+
+       Debug( LDAP_DEBUG_ARGS, "SASL Authorize [conn=%ld]: "
+               "authcid=\"%s\" authzid=\"%s\"\n",
+               (long) (conn ? conn->c_connid : -1),
+               authcid ? authcid : "<empty>",
+               authcid ? authcid : "<empty>" );
+
+       if ( authzid == NULL || *authzid == '\0' ||
+               strcmp( authcid, authzid ) == 0 )
+       {
+               char* cuser;
+               size_t len = sizeof("u:") + strlen( authcid );
+
+               cuser = ch_malloc( len );
+               strcpy( cuser, "u:" );
+               strcpy( &cuser[sizeof("u:")-1], authcid );
+
+               *user = cuser;
+
+               Debug( LDAP_DEBUG_TRACE, "SASL Authorize [conn=%ld]: "
+                       "\"%s\" as \"%s\"\n", 
+                       (long) (conn ? conn->c_connid : -1),
+                       authcid, cuser );
+
+               return SASL_OK;
+       }
+
+       Debug( LDAP_DEBUG_TRACE, "SASL Authorize [conn=%ld]: "
+               "\"%s\" as \"%s\" disallowed. No policy.\n", 
+               (long) (conn ? conn->c_connid : -1),
+               authcid, authzid );
+
+       *errstr = "no proxy policy";
+    return SASL_NOAUTHZ;
 }
 
+
 static int
 slap_sasl_err2ldap( int saslerr )
 {
@@ -60,9 +134,6 @@ slap_sasl_err2ldap( int saslerr )
                case SASL_CONTINUE:
                        rc = LDAP_SASL_BIND_IN_PROGRESS;
                        break;
-               case SASL_OK:
-                       rc = LDAP_SUCCESS;
-                       break;
                case SASL_FAIL:
                        rc = LDAP_OTHER;
                        break;
@@ -89,24 +160,34 @@ slap_sasl_err2ldap( int saslerr )
 
        return rc;
 }
+#endif
 
 
-int sasl_init( void )
+int slap_sasl_init( void )
 {
+#ifdef HAVE_CYRUS_SASL
        int rc;
-       char *mechs;
        sasl_conn_t *server = NULL;
+       static sasl_callback_t server_callbacks[] = {
+               { SASL_CB_LOG, &slap_sasl_log, NULL },
+               { SASL_CB_LIST_END, NULL, NULL }
+       };
 
-       sasl_set_alloc( ch_malloc, ch_calloc, ch_realloc, ch_free ); 
+       sasl_set_alloc(
+               ch_malloc,
+               ch_calloc,
+               ch_realloc,
+               ch_free ); 
 
        sasl_set_mutex(
-               slap_sasl_mutex_new,
-               slap_sasl_mutex_lock,
-               slap_sasl_mutex_unlock,
-               slap_sasl_mutex_dispose );
+               ldap_pvt_sasl_mutex_new,
+               ldap_pvt_sasl_mutex_lock,
+               ldap_pvt_sasl_mutex_unlock,
+               ldap_pvt_sasl_mutex_dispose );
 
+       /* should provide callbacks for logging */
        /* server name should be configurable */
-       rc = sasl_server_init( NULL, "slapd" );
+       rc = sasl_server_init( server_callbacks, "slapd" );
 
        if( rc != SASL_OK ) {
                Debug( LDAP_DEBUG_ANY, "sasl_server_init failed\n",
@@ -123,225 +204,340 @@ int sasl_init( void )
                }
        }
 
-       rc = sasl_server_new( "ldap", sasl_host, NULL, NULL,
-               SASL_SECURITY_LAYER, 
-               &server );
+       Debug( LDAP_DEBUG_TRACE,
+               "slap_sasl_init: %s initialized!\n",
+               sasl_host, 0, 0 );
 
-       if( rc != SASL_OK ) {
-               Debug( LDAP_DEBUG_ANY, "sasl_server_new failed\n",
-                       0, 0, 0 );
+       /* default security properties */
+       memset( &sasl_secprops, '\0', sizeof(sasl_secprops) );
+    sasl_secprops.max_ssf = UINT_MAX;
+    sasl_secprops.maxbufsize = 65536;
+    sasl_secprops.security_flags = SASL_SEC_NOPLAINTEXT|SASL_SEC_NOANONYMOUS;
+
+#ifdef SLAPD_SPASSWD
+       lutil_passwd_sasl_conn = server;
+#else
+       sasl_dispose( &server );
+#endif
+
+#endif
+       return 0;
+}
+
+int slap_sasl_destroy( void )
+{
+#ifdef HAVE_CYRUS_SASL
+#ifdef SLAPD_SPASSWD
+       sasl_dispose( &lutil_passwd_sasl_conn );
+#endif
+       sasl_done();
+#endif
+       return 0;
+}
+
+int slap_sasl_open( Connection *conn )
+{
+       int sc = LDAP_SUCCESS;
+
+#ifdef HAVE_CYRUS_SASL
+       sasl_conn_t *ctx = NULL;
+       sasl_callback_t *session_callbacks;
+
+       assert( conn->c_sasl_context == NULL );
+       assert( conn->c_sasl_extra == NULL );
+
+       conn->c_sasl_layers = 0;
+
+       session_callbacks =
+               ch_calloc( 3, sizeof(sasl_callback_t));
+       conn->c_sasl_extra = session_callbacks;
+
+       session_callbacks[0].id = SASL_CB_LOG;
+       session_callbacks[0].proc = &slap_sasl_log;
+       session_callbacks[0].context = conn;
+
+       session_callbacks[1].id = SASL_CB_PROXY_POLICY;
+       session_callbacks[1].proc = &slap_sasl_authorize;
+       session_callbacks[1].context = conn;
+
+       session_callbacks[2].id = SASL_CB_LIST_END;
+       session_callbacks[2].proc = NULL;
+       session_callbacks[2].context = NULL;
+
+       /* create new SASL context */
+       sc = sasl_server_new( "ldap", sasl_host, global_realm,
+               session_callbacks, SASL_SECURITY_LAYER, &ctx );
+
+       if( sc != SASL_OK ) {
+               Debug( LDAP_DEBUG_ANY, "sasl_server_new failed: %d\n",
+                       sc, 0, 0 );
                return -1;
        }
 
-#ifndef SLAPD_IGNORE_RFC2829
-       {
-               /* security flags should be configurable */
-               sasl_security_properties_t secprops;
-               memset(&secprops, '\0', sizeof(secprops));
-               secprops.security_flags = SASL_SEC_NOPLAINTEXT | SASL_SEC_NOANONYMOUS;
-               secprops.property_names = NULL;
-               secprops.property_values = NULL;
-       
-               rc = sasl_setprop( server, SASL_SEC_PROPS, &secprops );
-
-               if( rc != SASL_OK ) {
-                       Debug( LDAP_DEBUG_ANY, "sasl_setprop failed\n",
-                               0, 0, 0 );
+       conn->c_sasl_context = ctx;
+
+       if( sc == SASL_OK ) {
+               sc = sasl_setprop( ctx,
+                       SASL_SEC_PROPS, &sasl_secprops );
+
+               if( sc != SASL_OK ) {
+                       Debug( LDAP_DEBUG_ANY, "sasl_setprop failed: %d\n",
+                               sc, 0, 0 );
+                       slap_sasl_close( conn );
                        return -1;
                }
        }
+
+       sc = slap_sasl_err2ldap( sc );
 #endif
+       return sc;
+}
 
-       rc = sasl_listmech( server, NULL, NULL, ",", NULL,
-               &mechs, NULL, NULL);
+int slap_sasl_external(
+       Connection *conn,
+       unsigned ssf,
+       char *auth_id )
+{
+#ifdef HAVE_CYRUS_SASL
+       int sc;
+       sasl_conn_t *ctx = conn->c_sasl_context;
+       sasl_external_properties_t extprops;
 
-       if( rc != SASL_OK ) {
-               Debug( LDAP_DEBUG_ANY, "sasl_listmech failed: %d\n",
-                       rc, 0, 0 );
-               return -1;
+       if ( ctx == NULL ) {
+               return LDAP_UNAVAILABLE;
        }
 
-       Debug( LDAP_DEBUG_TRACE, "SASL mechanisms: %s\n",
-               mechs, 0, 0 );
+       memset( &extprops, 0L, sizeof(extprops) );
+       extprops.ssf = ssf;
+       extprops.auth_id = auth_id;
 
-       supportedSASLMechanisms = str2charray( mechs, "," );
+       sc = sasl_setprop( ctx, SASL_SSF_EXTERNAL,
+               (void *) &extprops );
 
-#ifdef SLAPD_SPASSWD
-       lutil_passwd_sasl_conn = server;
-#else
-       sasl_dispose( &server );
+       if ( sc != SASL_OK ) {
+               return LDAP_OTHER;
+       }
 #endif
 
-       return 0;
+       return LDAP_SUCCESS;
 }
 
-int sasl_destroy( void )
+int slap_sasl_reset( Connection *conn )
 {
-#ifdef SLAPD_SPASSWD
-       sasl_dispose( &lutil_passwd_sasl_conn );
+#ifdef HAVE_CYRUS_SASL
+       sasl_conn_t *ctx = conn->c_sasl_context;
+
+       if( ctx != NULL ) {
+       }
 #endif
-       charray_free( supportedSASLMechanisms );
-       return 0;
+       /* must return "anonymous" */
+       return LDAP_SUCCESS;
 }
 
+char ** slap_sasl_mechs( Connection *conn )
+{
+       char **mechs = NULL;
+
+#ifdef HAVE_CYRUS_SASL
+       sasl_conn_t *ctx = conn->c_sasl_context;
+
+       if( ctx != NULL ) {
+               int sc;
+               char *mechstr;
+
+               sc = sasl_listmech( ctx,
+                       NULL, NULL, ",", NULL,
+                       &mechstr, NULL, NULL );
+
+               if( sc != SASL_OK ) {
+                       Debug( LDAP_DEBUG_ANY, "slap_sasl_listmech failed: %d\n",
+                               sc, 0, 0 );
+                       return NULL;
+               }
+
+               mechs = str2charray( mechstr, "," );
+
+               ch_free( mechstr );
+       }
+#endif
+
+       return mechs;
+}
+
+int slap_sasl_close( Connection *conn )
+{
 #ifdef HAVE_CYRUS_SASL
-int sasl_bind(
+       sasl_conn_t *ctx = conn->c_sasl_context;
+
+       if( ctx != NULL ) {
+               sasl_dispose( &ctx );
+       }
+
+       conn->c_sasl_context = NULL;
+
+       free( conn->c_sasl_extra );
+       conn->c_sasl_extra = NULL;
+#endif
+
+       return LDAP_SUCCESS;
+}
+
+int slap_sasl_bind(
     Connection          *conn,
     Operation           *op,  
     const char          *dn,  
     const char          *ndn,
     const char          *mech,
     struct berval       *cred,
-       char                            **edn )
+       char                            **edn,
+       unsigned long           *ssfp )
 {
+       int rc = 1;
+
+#ifdef HAVE_CYRUS_SASL
+       sasl_conn_t *ctx = conn->c_sasl_context;
        struct berval response;
+       unsigned reslen;
        const char *errstr;
        int sc;
-       int rc = 1;
 
        Debug(LDAP_DEBUG_ARGS,
-               "==> sasl_bind: dn=\"%s\" mech=%s cred->bv_len=%d\n",
-               dn, mech, cred ? cred->bv_len : 0 );
-
-       if ( conn->c_sasl_bind_context == NULL ) {
-               sasl_callback_t callbacks[4];
-               int cbnum = 0;
-
-#if 0
-               if (be->be_sasl_authorize) {
-                       callbacks[cbnum].id = SASL_CB_PROXY_POLICY;
-                       callbacks[cbnum].proc = be->be_sasl_authorize;
-                       callbacks[cbnum].context = be;
-                       ++cbnum;
-               }
-
-               if (be->be_sasl_getsecret) {
-                       callbacks[cbnum].id = SASL_CB_SERVER_GETSECRET;
-                       callbacks[cbnum].proc = be->be_sasl_getsecret;
-                       callbacks[cbnum].context = be;
-                       ++cbnum;
-               }
-
-               if (be->be_sasl_putsecret) {
-                       callbacks[cbnum].id = SASL_CB_SERVER_PUTSECRET;
-                       callbacks[cbnum].proc = be->be_sasl_putsecret;
-                       callbacks[cbnum].context = be;
-                       ++cbnum;
-               }
-#endif
+               "==> sasl_bind: dn=\"%s\" mech=%s datalen=%d\n",
+               dn, mech ? mech : "<continuing>", cred ? cred->bv_len : 0 );
 
-               callbacks[cbnum].id = SASL_CB_LIST_END;
-               callbacks[cbnum].proc = NULL;
-               callbacks[cbnum].context = NULL;
-
-               /* create new SASL context */
-               sc = sasl_server_new( "ldap", sasl_host, global_realm,
-                       callbacks, SASL_SECURITY_LAYER, &conn->c_sasl_bind_context );
-
-               if( sc != SASL_OK ) {
-                       send_ldap_result( conn, op, rc = slap_sasl_err2ldap( sc ),
-                               NULL, "could not create new SASL context", NULL, NULL );
+       if( ctx == NULL ) {
+               send_ldap_result( conn, op, LDAP_UNAVAILABLE,
+                       NULL, "SASL unavailable on this session", NULL, NULL );
+               return rc;
+       }
 
-               } else {
-                       unsigned reslen;
-                       conn->c_authmech = ch_strdup( mech );
-
-                       sc = sasl_server_start( conn->c_sasl_bind_context,
-                               conn->c_authmech,
-                               cred->bv_val, cred->bv_len,
-                               (char **)&response.bv_val, &reslen, &errstr );
-
-                       response.bv_len = reslen;
-                       
-                       if ( (sc != SASL_OK) && (sc != SASL_CONTINUE) ) {
-                               send_ldap_result( conn, op, rc = slap_sasl_err2ldap( sc ),
-                                       NULL, errstr, NULL, NULL );
-                       }
-               }
+       if ( mech != NULL ) {
+               sc = sasl_server_start( ctx,
+                       mech,
+                       cred->bv_val, cred->bv_len,
+                       (char **)&response.bv_val, &reslen, &errstr );
 
        } else {
-               unsigned reslen;
-               sc = sasl_server_step( conn->c_sasl_bind_context,
+               sc = sasl_server_step( ctx,
                        cred->bv_val, cred->bv_len,
                        (char **)&response.bv_val, &reslen, &errstr );
-
-               response.bv_len = reslen;
-       
-               if ( (sc != SASL_OK) && (sc != SASL_CONTINUE) ) {
-                       send_ldap_result( conn, op, rc = slap_sasl_err2ldap( sc ),
-                               NULL, errstr, NULL, NULL );
-               }
        }
 
+       response.bv_len = reslen;
+
        if ( sc == SASL_OK ) {
-               char *authzid;
+               char *username = NULL;
 
-               sc = sasl_getprop( conn->c_sasl_bind_context, SASL_USERNAME,
-                       (void **)&authzid );
+               sc = sasl_getprop( ctx,
+                       SASL_USERNAME, (void **)&username );
 
                if ( sc != SASL_OK ) {
+                       Debug(LDAP_DEBUG_TRACE,
+                               "slap_sasl_bind: getprop(USERNAME) failed!\n",
+                               0, 0, 0);
+
                        send_ldap_result( conn, op, rc = slap_sasl_err2ldap( sc ),
                                NULL, "no SASL username", NULL, NULL );
 
+               } else if ( username == NULL || *username == '\0' ) {
+                       Debug(LDAP_DEBUG_TRACE,
+                               "slap_sasl_bind: getprop(USERNAME) returned NULL!\n",
+                               0, 0, 0);
+
+                       send_ldap_result( conn, op, rc = LDAP_INSUFFICIENT_ACCESS,
+                               NULL, "no SASL username", NULL, NULL );
+
                } else {
-                       Debug(LDAP_DEBUG_TRACE, "sasl_bind: username=%s\n",
-                               authzid, 0, 0);
+                       char *realm = NULL;
+                       sasl_ssf_t *ssf = NULL;
+
+                       (void) sasl_getprop( ctx,
+                               SASL_REALM, (void **)&realm );
+
+                       (void) sasl_getprop( ctx,
+                               SASL_SSF, (void *)&ssf );
+
+                       Debug(LDAP_DEBUG_TRACE,
+                               "slap_sasl_bind: username=\"%s\" realm=\"%s\" ssf=%lu\n",
+                               username ? username : "",
+                               realm ? realm : "",
+                               (unsigned long) ( ssf ? *ssf : 0 ) );
 
-                       if( !strncasecmp( authzid, "anonymous", sizeof("anonyous")-1 ) &&
-                               ( ( authzid[sizeof("anonymous")] == '\0' ) ||
-                                 ( authzid[sizeof("anonymous")] == '@' ) ) )
+                       *ssfp = ssf ? *ssf : 0;
+
+                       rc = LDAP_SUCCESS;
+
+                       if( username == NULL || (
+                               !strncasecmp( username, "anonymous", sizeof("anonyous")-1 ) &&
+                               ( ( username[sizeof("anonymous")] == '\0' ) ||
+                                 ( username[sizeof("anonymous")] == '@' ) ) ) )
                        {
-                               Debug(LDAP_DEBUG_TRACE, "<== sasl_bind: anonymous\n",
+                               Debug(LDAP_DEBUG_TRACE, "<== slap_sasl_bind: anonymous\n",
                                        0, 0, 0);
 
-                       } else {
-                               *edn = ch_malloc( sizeof( "authzid=" ) + strlen( authzid ) );
-                               strcpy( *edn, "authzid=" );
-                               strcat( *edn, authzid );
+                       } else if ( username[0] == 'u' && username[1] == ':'
+                               && username[2] != '\0'
+                               && strpbrk( &username[2], "=,;\"\\") == NULL )
+                       {
+                               *edn = ch_malloc( sizeof( "uid= + realm=" )
+                                       + strlen( &username[2] )
+                                       + ( realm ? strlen( realm ) : 0 ) );
+
+                               strcpy( *edn, "uid=" );
+                               strcat( *edn, &username[2] );
 
-                               Debug(LDAP_DEBUG_TRACE, "<== sasl_bind: authzdn: \"%s\"\n",
+                               if( realm && *realm ) {
+                                       strcat( *edn, " + realm=" );
+                                       strcat( *edn, realm );
+                               }
+
+                               Debug(LDAP_DEBUG_TRACE, "<== slap_sasl_bind: authzdn: \"%s\"\n",
                                        *edn, 0, 0);
+
+                       } else {
+                               rc = LDAP_INAPPROPRIATE_AUTH;
+                               errstr = "authorization disallowed";
+                               Debug(LDAP_DEBUG_TRACE, "<== slap_sasl_bind: %s\n",
+                                       errstr, 0, 0);
                        }
 
-                       send_ldap_sasl( conn, op, rc = LDAP_SUCCESS,
-                               NULL, NULL, NULL, NULL, &response );
+                       if( rc == LDAP_SUCCESS ) {
+                               send_ldap_sasl( conn, op, rc,
+                                       NULL, NULL, NULL, NULL,
+                                       response.bv_len ? &response : NULL );
+
+                       } else {
+                               send_ldap_result( conn, op, rc,
+                                       NULL, errstr, NULL, NULL );
+                       }
                }
 
        } else if ( sc == SASL_CONTINUE ) {
                send_ldap_sasl( conn, op, rc = LDAP_SASL_BIND_IN_PROGRESS,
-                       NULL, NULL, NULL, NULL,  &response );
-       } 
+                       NULL, NULL, NULL, NULL, &response );
 
-       if ( sc != SASL_CONTINUE && conn->c_sasl_bind_context != NULL ) {
-               sasl_dispose( &conn->c_sasl_bind_context );
-               conn->c_sasl_bind_context = NULL;
+       } else {
+               send_ldap_result( conn, op, rc = slap_sasl_err2ldap( sc ),
+                       NULL, errstr, NULL, NULL );
        }
 
-       Debug(LDAP_DEBUG_TRACE, "<== sasl_bind: rc=%d\n", rc, 0, 0);
-
-       return rc;
-}
-#endif /* HAVE_CYRUS_SASL */
+       Debug(LDAP_DEBUG_TRACE, "<== slap_sasl_bind: rc=%d\n", rc, 0, 0);
 
 #else
-/* no SASL support */
-int sasl_bind(
-    Connection          *conn,
-    Operation           *op,  
-    const char          *dn,  
-    const char          *ndn,
-    const char          *mech,
-    struct berval       *cred,
-       char                            **edn )
-{
-       int rc;
-
-       send_ldap_result( conn, op, rc = LDAP_UNWILLING_TO_PERFORM,
-               NULL, "SASL unavailable", NULL, NULL );
+       send_ldap_result( conn, op, rc = LDAP_UNAVAILABLE,
+               NULL, "SASL not supported", NULL, NULL );
+#endif
 
        return rc;
 }
 
-int sasl_init( void ) { return 0; }
-int sasl_destroy( void ) { return 0; }
+char* slap_sasl_secprops( const char *in )
+{
+#ifdef HAVE_CYRUS_SASL
+       int rc = ldap_pvt_sasl_secprops( in, &sasl_secprops );
+
+       return rc == LDAP_SUCCESS ? NULL : "Invalid security properties";
+#else
+       return "SASL not supported";
 #endif
+}
index 7f5aeafbf1d204f07be0bc9a445acdf675dc1c99..91237cc690a69c4237885a042352bbdee425fd2a 100644 (file)
 # select informational schema items:
 #      RFC2377 (uidObject)
 #
-# select experimental IETF LDAPext/LDUP items
-#   ldapSubentry draft
+# select IETF ''work in progress'' LDAPext/LDUP items
+#   ldapSubentry
 #      ldapRootDSE
-#      named referrals draft
+#      named referrals
 #      alias draft
 
 # Standard X.501(93) Operational Attribute Types from RFC2252
@@ -179,7 +179,7 @@ attributetype ( 2.5.4.15 NAME 'businessCategory'
        SUBSTR caseIgnoreSubstringsMatch
        SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{128} )
 
-attribute ( 2.5.4.16 NAME 'postalAddress'
+attributetype ( 2.5.4.16 NAME 'postalAddress'
        EQUALITY caseIgnoreListMatch
        SUBSTR caseIgnoreListSubstringsMatch
        SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )
@@ -523,7 +523,7 @@ objectclass ( 1.3.6.1.1.3.1 NAME 'uidObject'
        SUP top AUXILIARY MUST uid )
 
 #
-# From draft-ietf-ldapext-nameref-00.txt
+# From draft-zeilenga-ldap-nameref-00.txt
 #      used to represent referrals in the directory
 #
 attributetype ( 2.16.840.1.113730.3.1.34 NAME 'ref'
@@ -534,7 +534,7 @@ attributetype ( 2.16.840.1.113730.3.1.34 NAME 'ref'
 
 objectclass ( 2.16.840.1.113730.3.2.6 NAME 'referral'
        DESC 'Named referral object'
-       SUP top STRUCTURAL MAY ref )
+       SUP top STRUCTURAL MUST ref )
 
 #
 # LDAPsubEntry
@@ -575,7 +575,6 @@ attributetype ( 1.3.6.1.4.1.250.1.32
 attributetype ( 1.3.6.1.4.1.4203.666.1.1
        NAME 'authPassword'
        DESC 'OpenLDAP authentication password attribute'
-       EQUALITY authPasswordMatch
        SYNTAX 1.3.6.1.4.1.4203.666.2.2
        USAGE dSAOperation )
 
index 798606ab17844e3d13fca3331a35750f3c1f9b76..a8ace0c76e816ddcd362795135742feef4d5223d 100644 (file)
@@ -1,21 +1,23 @@
 # $OpenLDAP$
-# Assorted definitions from several sources
+# Assorted definitions from several sources, including
+# ''works in progress''.  Use with extreme care.
 
 #
 # draft-lachman-laser-ldap-mail-routing-01.txt
+#      This I-D has expired.
 #
 attributetype ( 2.16.840.1.113730.3.1.13
        NAME 'mailLocalAddress'
        DESC 'RFC822 email address of this recipient'
        EQUALITY caseIgnoreIA5Match
-       SYNTAX '1.3.6.1.4.1.1466.115.121.1.26{256}' )
+       SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} )
 
 attributetype ( 2.16.840.1.113730.3.1.18
        NAME 'mailHost'
        DESC 'fully-qualified hostname of the MTA that is the final 
                SMTP destination of messages to this recipient'
        EQUALITY caseIgnoreIA5Match
-       SYNTAX '1.3.6.1.4.1.1466.115.121.1.26{256}'
+       SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256}
        SINGLE-VALUE )
 
 attributetype ( 2.16.840.1.113730.3.1.47
@@ -23,12 +25,12 @@ attributetype ( 2.16.840.1.113730.3.1.47
        DESC 'RFC822 address to use when routing messages to 
                the SMTP MTA of this recipient'
        EQUALITY caseIgnoreIA5Match
-       SYNTAX '1.3.6.1.4.1.1466.115.121.1.26{256}'
+       SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256}
        SINGLE-VALUE )
 
 objectclass ( 2.16.840.1.113730.3.2.TBD
        NAME 'inetLocalMailRecipient'
        DESC 'Internet local mail recipient'
        SUP top AUXILIARY
-       MAY     ( mailLocalAddress $ mailHost $ mailRoutingAddress )
+       MAY     ( mailLocalAddress $ mailHost $ mailRoutingAddress ) )
 
index 747c3f94c50ea54ddcf4da994f59266aa6981455..51db9b7247db6d8b3296195b32e3f8ddbbb802b1 100644 (file)
 #define generalizedTimeMatch                   numericStringMatch
 #define generalizedTimeOrderingMatch   numericStringMatch
 
+/* approx matching rules */
+#define directoryStringApproxMatchOID  "1.3.6.1.4.1.4203.666.4.4"
+#define directoryStringApproxMatch             NULL
+#define IA5StringApproxMatchOID                        "1.3.6.1.4.1.4203.666.4.5"
+#define IA5StringApproxMatch                   NULL
+
 /* unimplemented matching routines */
 #define caseIgnoreListMatch                            NULL
 #define caseIgnoreListSubstringsMatch  NULL
 #define OpenLDAPaciMatch                               NULL
 #define authPasswordMatch                              NULL
 
-/* unimplied indexer/filter routines */
-#define caseIgnoreIA5SubstringsIndexer NULL
-#define caseIgnoreIA5SubstringsFilter  NULL
-
 /* recycled indexing/filtering routines */
 #define caseIgnoreIndexer                              caseIgnoreIA5Indexer
 #define caseIgnoreFilter                               caseIgnoreIA5Filter
@@ -81,8 +83,6 @@
 #define caseIgnoreSubstringsFilter             caseIgnoreIA5SubstringsFilter
 #define caseExactSubstringsIndexer             caseExactIA5SubstringsIndexer
 #define caseExactSubstringsFilter              caseExactIA5SubstringsFilter
-#define caseExactIA5SubstringsFilter   caseIgnoreIA5SubstringsFilter
-#define caseExactIA5SubstringsIndexer  caseIgnoreIA5SubstringsIndexer
 
 
 static int
@@ -867,7 +867,224 @@ int caseExactIA5Filter(
        *keysp = keys;
        return LDAP_SUCCESS;
 }
+/* Substrings Index generation function */
+int caseExactIA5SubstringsIndexer(
+       unsigned flags,
+       Syntax *syntax,
+       MatchingRule *mr,
+       struct berval *prefix,
+       struct berval **values,
+       struct berval ***keysp )
+{
+       int i, nkeys, types;
+       size_t slen, mlen;
+       struct berval **keys;
+       lutil_MD5_CTX   MD5context;
+       unsigned char   MD5digest[16];
+       struct berval digest;
+       digest.bv_val = MD5digest;
+       digest.bv_len = sizeof(MD5digest);
 
+       types = 0;
+       if( flags & SLAP_MR_SUBSTR_INITIAL ) types++;
+       if( flags & SLAP_MR_SUBSTR_FINAL ) types++;
+       /* no SUBSTR_ANY indexing */
+
+       nkeys=0;
+       for( i=0; values[i] != NULL; i++ ) {
+               /* count number of indices to generate */
+               if( values[i]->bv_len < SLAP_INDEX_SUBSTR_MINLEN ) {
+                       continue;
+               }
+
+               if( values[i]->bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
+                       nkeys += SLAP_INDEX_SUBSTR_MAXLEN - ( SLAP_INDEX_SUBSTR_MINLEN - 1);
+               } else {
+                       nkeys += values[i]->bv_len - ( SLAP_INDEX_SUBSTR_MINLEN - 1 );
+               }
+       }
+       assert( i > 0 );
+
+       if( nkeys == 0 ) {
+               /* no keys to generate */
+               *keysp = NULL;
+               return LDAP_SUCCESS;
+       }
+
+       nkeys *= types; /* We need to generate keys for each type */
+       keys = ch_malloc( sizeof( struct berval * ) * (nkeys+1) );
+
+       slen = strlen( syntax->ssyn_oid );
+       mlen = strlen( mr->smr_oid );
+
+       nkeys=0;
+       for( i=0; values[i] != NULL; i++ ) {
+               int j,max;
+               struct berval *value;
+
+               if( value->bv_len < SLAP_INDEX_SUBSTR_MINLEN ) continue;
+
+               max = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
+                       ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
+
+               value = values[i];
+
+               for( j=SLAP_INDEX_SUBSTR_MINLEN; j<=max; j++ ) {
+                       char pre;
+
+                       if( flags & SLAP_MR_SUBSTR_INITIAL ) {
+                               pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
+                               lutil_MD5Init( &MD5context );
+                               if( prefix != NULL && prefix->bv_len > 0 ) {
+                                       lutil_MD5Update( &MD5context,
+                                               prefix->bv_val, prefix->bv_len );
+                               }
+                               lutil_MD5Update( &MD5context,
+                                       &pre, sizeof( pre ) );
+                               lutil_MD5Update( &MD5context,
+                                       syntax->ssyn_oid, slen );
+                               lutil_MD5Update( &MD5context,
+                                       mr->smr_oid, mlen );
+                               lutil_MD5Update( &MD5context,
+                                       value->bv_val, j );
+                               lutil_MD5Final( MD5digest, &MD5context );
+
+                               keys[nkeys++] = ber_bvdup( &digest );
+                       }
+
+                       if( flags & SLAP_MR_SUBSTR_FINAL ) {
+                               pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
+                               lutil_MD5Init( &MD5context );
+                               if( prefix != NULL && prefix->bv_len > 0 ) {
+                                       lutil_MD5Update( &MD5context,
+                                               prefix->bv_val, prefix->bv_len );
+                               }
+                               lutil_MD5Update( &MD5context,
+                                       &pre, sizeof( pre ) );
+                               lutil_MD5Update( &MD5context,
+                                       syntax->ssyn_oid, slen );
+                               lutil_MD5Update( &MD5context,
+                                       mr->smr_oid, mlen );
+                               lutil_MD5Update( &MD5context,
+                                       &value->bv_val[value->bv_len-j], j );
+                               lutil_MD5Final( MD5digest, &MD5context );
+
+                               keys[nkeys++] = ber_bvdup( &digest );
+                       }
+
+               }
+       }
+
+       keys[nkeys] = NULL;
+       *keysp = keys;
+       return LDAP_SUCCESS;
+}
+
+int caseExactIA5SubstringsFilter(
+       unsigned flags,
+       Syntax *syntax,
+       MatchingRule *mr,
+       struct berval *prefix,
+       void * assertValue,
+       struct berval ***keysp )
+{
+       SubstringsAssertion *sa = assertValue;
+       char pre;
+       int nkeys = 0;
+       size_t slen, mlen, klen;
+       struct berval **keys;
+       lutil_MD5_CTX   MD5context;
+       unsigned char   MD5digest[LUTIL_MD5_BYTES];
+       struct berval *value;
+       struct berval digest;
+
+       if( sa->sa_initial != NULL &&
+               sa->sa_initial->bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
+       {
+               nkeys++;
+       }
+       if( sa->sa_final != NULL &&
+               sa->sa_final->bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
+       {
+               nkeys++;
+       }
+
+       if( nkeys == 0 ) {
+               *keysp = NULL;
+               return LDAP_SUCCESS;
+       }
+
+       digest.bv_val = MD5digest;
+       digest.bv_len = sizeof(MD5digest);
+
+       slen = strlen( syntax->ssyn_oid );
+       mlen = strlen( mr->smr_oid );
+
+       keys = ch_malloc( sizeof( struct berval * ) * (nkeys+1) );
+       nkeys = 0;
+
+       if( sa->sa_initial != NULL &&
+               sa->sa_initial->bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
+       {
+               pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
+               value = sa->sa_initial;
+
+               klen = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
+                       ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
+
+               lutil_MD5Init( &MD5context );
+               if( prefix != NULL && prefix->bv_len > 0 ) {
+                       lutil_MD5Update( &MD5context,
+                               prefix->bv_val, prefix->bv_len );
+               }
+               lutil_MD5Update( &MD5context,
+                       &pre, sizeof( pre ) );
+               lutil_MD5Update( &MD5context,
+                       syntax->ssyn_oid, slen );
+               lutil_MD5Update( &MD5context,
+                       mr->smr_oid, mlen );
+               lutil_MD5Update( &MD5context,
+                       value->bv_val, klen );
+               lutil_MD5Final( MD5digest, &MD5context );
+
+               ber_bvfree( value );
+               keys[nkeys++] = ber_bvdup( &digest );
+       }
+
+       if( sa->sa_final != NULL &&
+               sa->sa_final->bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
+       {
+               pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
+               value = sa->sa_final;
+
+               klen = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
+                       ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
+
+               lutil_MD5Init( &MD5context );
+               if( prefix != NULL && prefix->bv_len > 0 ) {
+                       lutil_MD5Update( &MD5context,
+                               prefix->bv_val, prefix->bv_len );
+               }
+               lutil_MD5Update( &MD5context,
+                       &pre, sizeof( pre ) );
+               lutil_MD5Update( &MD5context,
+                       syntax->ssyn_oid, slen );
+               lutil_MD5Update( &MD5context,
+                       mr->smr_oid, mlen );
+               lutil_MD5Update( &MD5context,
+                       &value->bv_val[value->bv_len-klen], klen );
+               lutil_MD5Final( MD5digest, &MD5context );
+
+               ber_bvfree( value );
+               keys[nkeys++] = ber_bvdup( &digest );
+       }
+
+       keys[nkeys] = NULL;
+
+       *keysp = keys;
+       return LDAP_SUCCESS;
+}
+       
 static int
 caseIgnoreIA5Match(
        int *matchp,
@@ -1133,6 +1350,229 @@ int caseIgnoreIA5Filter(
        return LDAP_SUCCESS;
 }
 
+/* Substrings Index generation function */
+int caseIgnoreIA5SubstringsIndexer(
+       unsigned flags,
+       Syntax *syntax,
+       MatchingRule *mr,
+       struct berval *prefix,
+       struct berval **values,
+       struct berval ***keysp )
+{
+       int i, nkeys, types;
+       size_t slen, mlen;
+       struct berval **keys;
+       lutil_MD5_CTX   MD5context;
+       unsigned char   MD5digest[16];
+       struct berval digest;
+       digest.bv_val = MD5digest;
+       digest.bv_len = sizeof(MD5digest);
+
+       types = 0;
+       if( flags & SLAP_MR_SUBSTR_INITIAL ) types++;
+       if( flags & SLAP_MR_SUBSTR_FINAL ) types++;
+       /* no SUBSTR_ANY indexing */
+
+       nkeys=0;
+       for( i=0; values[i] != NULL; i++ ) {
+               /* count number of indices to generate */
+               if( values[i]->bv_len < SLAP_INDEX_SUBSTR_MINLEN ) {
+                       continue;
+               }
+
+               if( values[i]->bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
+                       nkeys += SLAP_INDEX_SUBSTR_MAXLEN - ( SLAP_INDEX_SUBSTR_MINLEN - 1);
+               } else {
+                       nkeys += values[i]->bv_len - ( SLAP_INDEX_SUBSTR_MINLEN - 1 );
+               }
+       }
+       assert( i > 0 );
+
+       if( nkeys == 0 ) {
+               /* no keys to generate */
+               *keysp = NULL;
+               return LDAP_SUCCESS;
+       }
+
+       nkeys *= types; /* We need to generate keys for each type */
+       keys = ch_malloc( sizeof( struct berval * ) * (nkeys+1) );
+
+       slen = strlen( syntax->ssyn_oid );
+       mlen = strlen( mr->smr_oid );
+
+       nkeys=0;
+       for( i=0; values[i] != NULL; i++ ) {
+               int j,max;
+               struct berval *value;
+
+               if( values[i]->bv_len < SLAP_INDEX_SUBSTR_MINLEN ) continue;
+
+               max = SLAP_INDEX_SUBSTR_MAXLEN < values[i]->bv_len
+                       ? SLAP_INDEX_SUBSTR_MAXLEN : values[i]->bv_len;
+
+               value = ber_bvdup( values[i] );
+               ldap_pvt_str2upper( value->bv_val );
+
+               for( j=SLAP_INDEX_SUBSTR_MINLEN; j<=max; j++ ) {
+                       char pre;
+
+                       if( flags & SLAP_MR_SUBSTR_INITIAL ) {
+                               pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
+                               lutil_MD5Init( &MD5context );
+                               if( prefix != NULL && prefix->bv_len > 0 ) {
+                                       lutil_MD5Update( &MD5context,
+                                               prefix->bv_val, prefix->bv_len );
+                               }
+                               lutil_MD5Update( &MD5context,
+                                       &pre, sizeof( pre ) );
+                               lutil_MD5Update( &MD5context,
+                                       syntax->ssyn_oid, slen );
+                               lutil_MD5Update( &MD5context,
+                                       mr->smr_oid, mlen );
+                               lutil_MD5Update( &MD5context,
+                                       value->bv_val, j );
+                               lutil_MD5Final( MD5digest, &MD5context );
+
+                               keys[nkeys++] = ber_bvdup( &digest );
+                       }
+
+                       if( flags & SLAP_MR_SUBSTR_FINAL ) {
+                               pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
+                               lutil_MD5Init( &MD5context );
+                               if( prefix != NULL && prefix->bv_len > 0 ) {
+                                       lutil_MD5Update( &MD5context,
+                                               prefix->bv_val, prefix->bv_len );
+                               }
+                               lutil_MD5Update( &MD5context,
+                                       &pre, sizeof( pre ) );
+                               lutil_MD5Update( &MD5context,
+                                       syntax->ssyn_oid, slen );
+                               lutil_MD5Update( &MD5context,
+                                       mr->smr_oid, mlen );
+                               lutil_MD5Update( &MD5context,
+                                       &value->bv_val[value->bv_len-j], j );
+                               lutil_MD5Final( MD5digest, &MD5context );
+
+                               keys[nkeys++] = ber_bvdup( &digest );
+                       }
+
+               }
+
+               ber_bvfree( value );
+       }
+
+       keys[nkeys] = NULL;
+       *keysp = keys;
+       return LDAP_SUCCESS;
+}
+
+int caseIgnoreIA5SubstringsFilter(
+       unsigned flags,
+       Syntax *syntax,
+       MatchingRule *mr,
+       struct berval *prefix,
+       void * assertValue,
+       struct berval ***keysp )
+{
+       SubstringsAssertion *sa = assertValue;
+       char pre;
+       int nkeys = 0;
+       size_t slen, mlen, klen;
+       struct berval **keys;
+       lutil_MD5_CTX   MD5context;
+       unsigned char   MD5digest[LUTIL_MD5_BYTES];
+       struct berval *value;
+       struct berval digest;
+
+       if( sa->sa_initial != NULL &&
+               sa->sa_initial->bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
+       {
+               nkeys++;
+       }
+       if( sa->sa_final != NULL &&
+               sa->sa_final->bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
+       {
+               nkeys++;
+       }
+
+       if( nkeys == 0 ) {
+               *keysp = NULL;
+               return LDAP_SUCCESS;
+       }
+
+       digest.bv_val = MD5digest;
+       digest.bv_len = sizeof(MD5digest);
+
+       slen = strlen( syntax->ssyn_oid );
+       mlen = strlen( mr->smr_oid );
+
+       keys = ch_malloc( sizeof( struct berval * ) * (nkeys+1) );
+       nkeys = 0;
+
+       if( sa->sa_initial != NULL &&
+               sa->sa_initial->bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
+       {
+               pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
+               value = ber_bvdup( sa->sa_initial );
+               ldap_pvt_str2upper( value->bv_val );
+
+               klen = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
+                       ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
+
+               lutil_MD5Init( &MD5context );
+               if( prefix != NULL && prefix->bv_len > 0 ) {
+                       lutil_MD5Update( &MD5context,
+                               prefix->bv_val, prefix->bv_len );
+               }
+               lutil_MD5Update( &MD5context,
+                       &pre, sizeof( pre ) );
+               lutil_MD5Update( &MD5context,
+                       syntax->ssyn_oid, slen );
+               lutil_MD5Update( &MD5context,
+                       mr->smr_oid, mlen );
+               lutil_MD5Update( &MD5context,
+                       value->bv_val, klen );
+               lutil_MD5Final( MD5digest, &MD5context );
+
+               ber_bvfree( value );
+               keys[nkeys++] = ber_bvdup( &digest );
+       }
+
+       if( sa->sa_final != NULL &&
+               sa->sa_final->bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
+       {
+               pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
+               value = ber_bvdup( sa->sa_final );
+               ldap_pvt_str2upper( value->bv_val );
+
+               klen = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
+                       ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
+
+               lutil_MD5Init( &MD5context );
+               if( prefix != NULL && prefix->bv_len > 0 ) {
+                       lutil_MD5Update( &MD5context,
+                               prefix->bv_val, prefix->bv_len );
+               }
+               lutil_MD5Update( &MD5context,
+                       &pre, sizeof( pre ) );
+               lutil_MD5Update( &MD5context,
+                       syntax->ssyn_oid, slen );
+               lutil_MD5Update( &MD5context,
+                       mr->smr_oid, mlen );
+               lutil_MD5Update( &MD5context,
+                       &value->bv_val[value->bv_len-klen], klen );
+               lutil_MD5Final( MD5digest, &MD5context );
+
+               ber_bvfree( value );
+               keys[nkeys++] = ber_bvdup( &digest );
+       }
+
+       keys[nkeys] = NULL;
+
+       *keysp = keys;
+       return LDAP_SUCCESS;
+}
+       
 static int
 numericStringNormalize(
        Syntax *syntax,
@@ -1226,7 +1666,7 @@ objectIdentifierFirstComponentMatch(
 
        } else {
                char *stored = ch_malloc( oid.bv_len + 1 );
-               memcpy( stored, oid.bv_val, oid.bv_len );
+               AC_MEMCPY( stored, oid.bv_val, oid.bv_len );
                stored[oid.bv_len] = '\0';
 
                if ( !strcmp( syntax->ssyn_oid, SLAP_SYNTAX_MATCHINGRULES_OID ) ) {
@@ -1664,6 +2104,8 @@ struct mrule_defs_rec {
        slap_mr_match_func *            mrd_match;
        slap_mr_indexer_func *          mrd_indexer;
        slap_mr_filter_func *           mrd_filter;
+
+       char *                                          mrd_associated;
 };
 
 /*
@@ -1693,170 +2135,256 @@ struct mrule_defs_rec {
  */
 
 struct mrule_defs_rec mrule_defs[] = {
+       /*
+        * EQUALITY matching rules must be listed after associated APPROX
+        * matching rules.  So, we list all APPROX matching rules first.
+        */
+       {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' "
+               "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
+               SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT,
+               NULL, NULL,
+               directoryStringApproxMatch, NULL, NULL,
+               NULL},
+
+       {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' "
+               "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
+               SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT,
+               NULL, NULL,
+               IA5StringApproxMatch, NULL, NULL,
+               NULL},
+
+       /*
+        * Other matching rules
+        */
+       
        {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
                "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
                SLAP_MR_EQUALITY | SLAP_MR_EXT,
-               NULL, NULL, objectIdentifierMatch,
-               caseIgnoreIA5Indexer, caseIgnoreIA5Filter},
+               NULL, NULL,
+               objectIdentifierMatch, caseIgnoreIA5Indexer, caseIgnoreIA5Filter,
+               NULL},
 
        {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
                "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
                SLAP_MR_EQUALITY | SLAP_MR_EXT,
-               NULL, NULL, dnMatch, dnIndexer, dnFilter},
+               NULL, NULL,
+               dnMatch, dnIndexer, dnFilter,
+               NULL},
 
        {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
                "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
                SLAP_MR_EQUALITY | SLAP_MR_EXT,
-               NULL, NULL, caseIgnoreMatch, caseIgnoreIndexer, caseIgnoreFilter},
+               NULL, NULL,
+               caseIgnoreMatch, caseIgnoreIndexer, caseIgnoreFilter,
+               directoryStringApproxMatchOID },
 
        {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
                "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
                SLAP_MR_ORDERING,
-               NULL, NULL, caseIgnoreOrderingMatch, NULL, NULL},
+               NULL, NULL,
+               caseIgnoreOrderingMatch, NULL, NULL,
+               NULL},
 
        {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
                "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
                SLAP_MR_SUBSTR | SLAP_MR_EXT,
-               NULL, NULL, caseIgnoreSubstringsMatch,
-               caseIgnoreSubstringsIndexer, caseIgnoreSubstringsFilter},
+               NULL, NULL,
+               caseIgnoreSubstringsMatch,
+               caseIgnoreSubstringsIndexer,
+               caseIgnoreSubstringsFilter,
+               NULL},
 
        {"( 2.5.13.5 NAME 'caseExactMatch' "
                "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
                SLAP_MR_EQUALITY | SLAP_MR_EXT,
-               NULL, NULL, caseExactMatch, caseExactIndexer, caseExactFilter},
+               NULL, NULL,
+               caseExactMatch, caseExactIndexer, caseExactFilter,
+               directoryStringApproxMatchOID },
 
        {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
                "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
                SLAP_MR_ORDERING,
-               NULL, NULL, caseExactOrderingMatch, NULL, NULL},
+               NULL, NULL,
+               caseExactOrderingMatch, NULL, NULL,
+               NULL},
 
        {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
                "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
                SLAP_MR_SUBSTR | SLAP_MR_EXT,
-               NULL, NULL, caseExactSubstringsMatch,
-               caseExactSubstringsIndexer, caseExactSubstringsFilter},
+               NULL, NULL,
+               caseExactSubstringsMatch,
+               caseExactSubstringsIndexer,
+               caseExactSubstringsFilter,
+               NULL},
 
        {"( 2.5.13.8 NAME 'numericStringMatch' "
                "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
                SLAP_MR_EQUALITY | SLAP_MR_EXT,
-               NULL, NULL, caseIgnoreIA5Match, NULL, NULL},
+               NULL, NULL,
+               caseIgnoreIA5Match, NULL, NULL,
+               NULL},
 
        {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
                "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
                SLAP_MR_SUBSTR | SLAP_MR_EXT,
-               NULL, NULL, caseIgnoreIA5SubstringsMatch,
-               caseIgnoreIA5SubstringsIndexer, caseIgnoreIA5SubstringsFilter},
+               NULL, NULL,
+               caseIgnoreIA5SubstringsMatch,
+               caseIgnoreIA5SubstringsIndexer,
+               caseIgnoreIA5SubstringsFilter,
+               NULL},
 
        {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
                "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
                SLAP_MR_EQUALITY | SLAP_MR_EXT,
-               NULL, NULL, caseIgnoreListMatch, NULL, NULL},
+               NULL, NULL,
+               caseIgnoreListMatch, NULL, NULL,
+               NULL},
 
        {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
                "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
                SLAP_MR_SUBSTR | SLAP_MR_EXT,
-               NULL, NULL, caseIgnoreListSubstringsMatch, NULL, NULL},
+               NULL, NULL,
+               caseIgnoreListSubstringsMatch, NULL, NULL,
+               NULL},
 
        {"( 2.5.13.13 NAME 'booleanMatch' "
                "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
                SLAP_MR_EQUALITY | SLAP_MR_EXT,
-               NULL, NULL, booleanMatch, NULL, NULL},
+               NULL, NULL,
+               booleanMatch, NULL, NULL,
+               NULL},
 
        {"( 2.5.13.14 NAME 'integerMatch' "
                "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
                SLAP_MR_EQUALITY | SLAP_MR_EXT,
-               NULL, NULL, integerMatch, NULL, NULL},
+               NULL, NULL,
+               integerMatch, NULL, NULL,
+               NULL},
 
        {"( 2.5.13.16 NAME 'bitStringMatch' "
                "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
                SLAP_MR_EQUALITY | SLAP_MR_EXT,
-               NULL, NULL, bitStringMatch, NULL, NULL},
+               NULL, NULL,
+               bitStringMatch, NULL, NULL,
+               NULL},
 
        {"( 2.5.13.17 NAME 'octetStringMatch' "
                "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
                SLAP_MR_EQUALITY | SLAP_MR_EXT,
-               NULL, NULL, octetStringMatch, octetStringIndexer, octetStringFilter},
+               NULL, NULL,
+               octetStringMatch, octetStringIndexer, octetStringFilter,
+               NULL},
 
        {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
                "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
                SLAP_MR_EQUALITY | SLAP_MR_EXT,
-               NULL, NULL, telephoneNumberMatch, NULL, NULL},
+               NULL, NULL,
+               telephoneNumberMatch, NULL, NULL,
+               NULL},
 
        {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
                "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
                SLAP_MR_SUBSTR | SLAP_MR_EXT,
-               NULL, NULL, telephoneNumberSubstringsMatch, NULL, NULL},
+               NULL, NULL,
+               telephoneNumberSubstringsMatch, NULL, NULL,
+               NULL},
 
        {"( 2.5.13.22 NAME 'presentationAddressMatch' "
                "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
                SLAP_MR_EQUALITY | SLAP_MR_EXT,
-               NULL, NULL, presentationAddressMatch, NULL, NULL},
+               NULL, NULL,
+               presentationAddressMatch, NULL, NULL,
+               NULL},
 
        {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
                "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
                SLAP_MR_EQUALITY | SLAP_MR_EXT,
-               NULL, NULL, uniqueMemberMatch, NULL, NULL},
+               NULL, NULL,
+               uniqueMemberMatch, NULL, NULL,
+               NULL},
 
        {"( 2.5.13.24 NAME 'protocolInformationMatch' "
                "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
                SLAP_MR_EQUALITY | SLAP_MR_EXT,
-               NULL, NULL, protocolInformationMatch, NULL, NULL},
+               NULL, NULL,
+               protocolInformationMatch, NULL, NULL,
+               NULL},
 
        {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
                "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
                SLAP_MR_EQUALITY | SLAP_MR_EXT,
-               NULL, NULL, generalizedTimeMatch, NULL, NULL},
+               NULL, NULL,
+               generalizedTimeMatch, NULL, NULL,
+               NULL},
 
        {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
                "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
                SLAP_MR_ORDERING,
-               NULL, NULL, generalizedTimeOrderingMatch, NULL, NULL},
+               NULL, NULL,
+               generalizedTimeOrderingMatch, NULL, NULL,
+               NULL},
 
        {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
                "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
                SLAP_MR_EQUALITY | SLAP_MR_EXT,
-               NULL, NULL, integerFirstComponentMatch, NULL, NULL},
+               NULL, NULL,
+               integerFirstComponentMatch, NULL, NULL,
+               NULL},
 
        {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
                "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
                SLAP_MR_EQUALITY | SLAP_MR_EXT,
-               NULL, NULL, objectIdentifierFirstComponentMatch, NULL, NULL},
+               NULL, NULL,
+               objectIdentifierFirstComponentMatch, NULL, NULL,
+               NULL},
 
        {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
                "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
                SLAP_MR_EQUALITY | SLAP_MR_EXT,
                NULL, NULL,
-               caseExactIA5Match, caseExactIA5Indexer, caseExactIA5Filter},
+               caseExactIA5Match, caseExactIA5Indexer, caseExactIA5Filter,
+               IA5StringApproxMatchOID },
 
        {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
                "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
                SLAP_MR_EQUALITY | SLAP_MR_EXT,
                NULL, NULL,
-               caseIgnoreIA5Match, caseExactIA5Indexer, caseExactIA5Filter},
+               caseIgnoreIA5Match, caseExactIA5Indexer, caseExactIA5Filter,
+               IA5StringApproxMatchOID },
 
        {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
                "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
                SLAP_MR_SUBSTR,
-               NULL, NULL, caseIgnoreIA5SubstringsMatch,
-               caseIgnoreIA5SubstringsIndexer, caseIgnoreIA5SubstringsFilter},
+               NULL, NULL,
+               caseIgnoreIA5SubstringsMatch,
+               caseIgnoreIA5SubstringsIndexer,
+               caseIgnoreIA5SubstringsFilter,
+               NULL},
 
        {"( 1.3.6.1.4.1.4203.666.4.3 NAME 'caseExactIA5SubstringsMatch' "
                "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
                SLAP_MR_SUBSTR,
-               NULL, NULL, caseExactIA5SubstringsMatch,
-               caseExactIA5SubstringsIndexer, caseExactIA5SubstringsFilter},
+               NULL, NULL,
+               caseExactIA5SubstringsMatch,
+               caseExactIA5SubstringsIndexer,
+               caseExactIA5SubstringsFilter,
+               NULL},
 
        {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
                "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
                SLAP_MR_EQUALITY,
-               NULL, NULL, authPasswordMatch, NULL, NULL},
+               NULL, NULL,
+               authPasswordMatch, NULL, NULL,
+               NULL},
 
        {"( 1.3.6.1.4.1.4203.666.4.2 NAME 'OpenLDAPaciMatch' "
                "SYNTAX 1.3.6.1.4.1.4203.666.2.1 )",
                SLAP_MR_EQUALITY,
-               NULL, NULL, OpenLDAPaciMatch, NULL, NULL},
+               NULL, NULL,
+               OpenLDAPaciMatch, NULL, NULL,
+               NULL},
 
-       {NULL, SLAP_MR_NONE, NULL, NULL, NULL}
+       {NULL, SLAP_MR_NONE, NULL, NULL, NULL, NULL}
 };
 
 int
@@ -1903,7 +2431,8 @@ schema_init( void )
                        mrule_defs[i].mrd_normalize,
                    mrule_defs[i].mrd_match,
                        mrule_defs[i].mrd_indexer,
-                       mrule_defs[i].mrd_filter );
+                       mrule_defs[i].mrd_filter,
+                       mrule_defs[i].mrd_associated );
 
                if ( res ) {
                        fprintf( stderr,
index 6f00e93eef2fa297d1cbfed1887fd8d11004caca..7009c265a91a443629ec3999170262ba9eff4940 100644 (file)
@@ -166,7 +166,7 @@ parse_oc(
     char       **argv
 )
 {
-       LDAP_OBJECT_CLASS *oc;
+       LDAPObjectClass *oc;
        int             code;
        const char      *err;
        char            *oid = NULL;
@@ -257,7 +257,7 @@ parse_at(
     char       **argv
 )
 {
-       LDAP_ATTRIBUTE_TYPE *at;
+       LDAPAttributeType *at;
        int             code;
        const char      *err;
        char            *oid = NULL;
index 3959645337627db74e5e443b1d6bf212e6379bbc..653fb886fa8e8fb10add232c18f61687de28dc0e 100644 (file)
@@ -159,7 +159,7 @@ do_search(
                Entry *entry = NULL;
 
                if ( strcasecmp( nbase, LDAP_ROOT_DSE ) == 0 ) {
-                       rc = root_dse_info( &entry, &text );
+                       rc = root_dse_info( conn, &entry, &text );
                }
 
 #if defined( SLAPD_MONITOR_DN )
index 0fdec47ee2b783b10ce554f3c5c74007d8472f67..d5c021f4dc25678c1d7df5c451729d67ba4c53d1 100644 (file)
@@ -135,7 +135,7 @@ set_chase (SET_GATHER gatherer, void *cookie, char **set, char *attr, int attrle
                set_dispose(set);
                return(NULL);
        }
-       memcpy(attrstr, attr, attrlen);
+       AC_MEMCPY(attrstr, attr, attrlen);
        attrstr[attrlen] = 0;
 
        nset = ch_calloc(1, sizeof(char *));
@@ -197,12 +197,12 @@ set_samedn (char *dn1, char *dn2)
 int
 set_filter (SET_GATHER gatherer, void *cookie, char *filter, char *user, char *this, char ***results)
 {
-       #define IS_SET(x)       ( (long)(x) >= 256 )
-       #define IS_OP(x)        ( (long)(x) < 256 )
-       #define SF_ERROR(x)     { rc = -1; goto _error; }
-       #define SF_TOP()        (char **)( (stp < 0) ? 0 : stack[stp] )
-       #define SF_POP()        (char **)( (stp < 0) ? 0 : stack[stp--] )
-       #define SF_PUSH(x)      { if (stp >= 63) SF_ERROR(overflow); stack[++stp] = (char **)(long)(x); }
+#      define IS_SET(x)        ( (long)(x) >= 256 )
+#      define IS_OP(x) ( (long)(x) < 256 )
+#      define SF_ERROR(x)      { rc = -1; goto _error; }
+#      define SF_TOP() (char **)( (stp < 0) ? 0 : stack[stp] )
+#      define SF_POP() (char **)( (stp < 0) ? 0 : stack[stp--] )
+#      define SF_PUSH(x)       { if (stp >= 63) SF_ERROR(overflow); stack[++stp] = (char **)(long)(x); }
        char c;
        char **set, **lset;
        int len, op, rc, stp;
@@ -287,7 +287,7 @@ set_filter (SET_GATHER gatherer, void *cookie, char *filter, char *user, char *t
                        *set = ch_calloc(len + 1, sizeof(char));
                        if (*set == NULL)
                                SF_ERROR(memory);
-                       memcpy(*set, &filter[-len - 1], len);
+                       AC_MEMCPY(*set, &filter[-len - 1], len);
                        SF_PUSH(set);
                        set = NULL;
                        break;
index c55f23196610357bf009cba458bea677b1507409..d85493a321b911b448eac6d64c9caaebe18a266a 100644 (file)
 #include <ac/time.h>
 #include <ac/param.h>
 
-#ifdef HAVE_CYRUS_SASL
-#include <sasl.h>
-#endif
-
 #include "avl.h"
 
 #ifndef ldap_debug
@@ -141,10 +137,8 @@ LDAP_SLAPD_F (int) slap_debug;
 #define SLAP_INDEX_SUBSTR_DEFAULT ( SLAP_INDEX_SUBSTR \
        | SLAP_INDEX_SUBSTR_INITIAL | SLAP_INDEX_SUBSTR_FINAL )
 
-#define SLAP_INDEX_SUBSTR_INITIAL_MIN_LEN      2
-#define SLAP_INDEX_SUBSTR_INITIAL_MAX_LEN      4
-#define SLAP_INDEX_SUBSTR_FINAL_MIN_LEN                2
-#define SLAP_INDEX_SUBSTR_FINAL_MAX_LEN                4
+#define SLAP_INDEX_SUBSTR_MINLEN       2
+#define SLAP_INDEX_SUBSTR_MAXLEN       4
 
 #define SLAP_INDEX_FLAGS          0xF000UL
 #define SLAP_INDEX_SUBTYPES       0x1000UL /* use index with subtypes */
@@ -161,6 +155,8 @@ typedef long slap_index;
 #define SLAP_INDEX_EQUALITY_PREFIX     '='     /* prefix for equality keys     */
 #define SLAP_INDEX_APPROX_PREFIX       '~'             /* prefix for approx keys       */
 #define SLAP_INDEX_SUBSTR_PREFIX       '*'             /* prefix for substring keys    */
+#define SLAP_INDEX_SUBSTR_INITIAL_PREFIX '^'
+#define SLAP_INDEX_SUBSTR_FINAL_PREFIX '$'
 #define SLAP_INDEX_CONT_PREFIX         '.'             /* prefix for continuation keys */
 #define SLAP_INDEX_UNKNOWN_PREFIX      '?'             /* prefix for unknown keys */
 
@@ -204,7 +200,7 @@ typedef int slap_syntax_transform_func LDAP_P((
        struct berval ** out));
 
 typedef struct slap_syntax {
-       LDAP_SYNTAX                     ssyn_syn;
+       LDAPSyntax                      ssyn_syn;
 #define ssyn_oid               ssyn_syn.syn_oid
 #define ssyn_desc              ssyn_syn.syn_desc
 #define ssyn_extensions                ssyn_syn.syn_extensions
@@ -277,7 +273,7 @@ typedef int slap_mr_filter_func LDAP_P((
        struct berval ***keys ));
 
 typedef struct slap_matching_rule {
-       LDAP_MATCHING_RULE              smr_mrule;
+       LDAPMatchingRule                smr_mrule;
        unsigned                                smr_usage;
 
 #define SLAP_MR_TYPE_MASK              0xFF00U
@@ -305,7 +301,10 @@ typedef struct slap_matching_rule {
        slap_mr_match_func              *smr_match;
        slap_mr_indexer_func    *smr_indexer;
        slap_mr_filter_func             *smr_filter;
+
+       struct slap_matching_rule       *smr_associated;
        struct slap_matching_rule       *smr_next;
+
 #define smr_oid                                smr_mrule.mr_oid
 #define smr_names                      smr_mrule.mr_names
 #define smr_desc                       smr_mrule.mr_desc
@@ -316,7 +315,7 @@ typedef struct slap_matching_rule {
 
 typedef struct slap_attribute_type {
        char                                    *sat_cname;
-       LDAP_ATTRIBUTE_TYPE             sat_atype;
+       LDAPAttributeType               sat_atype;
        struct slap_attribute_type      *sat_sup;
        struct slap_attribute_type      **sat_subtypes;
        MatchingRule                    *sat_equality;
@@ -347,7 +346,7 @@ typedef struct slap_attribute_type {
 #define is_at_no_user_mod(at)  ((at)->sat_no_user_mod)
 
 typedef struct slap_object_class {
-       LDAP_OBJECT_CLASS               soc_oclass;
+       LDAPObjectClass         soc_oclass;
        struct slap_object_class        **soc_sups;
        AttributeType                   **soc_required;
        AttributeType                   **soc_allowed;
@@ -791,17 +790,10 @@ struct slap_backend_db {
 #define                be_entry_close bd_info->bi_tool_entry_close
 #define                be_entry_first bd_info->bi_tool_entry_first
 #define                be_entry_next bd_info->bi_tool_entry_next
+#define                be_entry_reindex bd_info->bi_tool_entry_reindex
 #define                be_entry_get bd_info->bi_tool_entry_get
 #define                be_entry_put bd_info->bi_tool_entry_put
-#define                be_index_attr bd_info->bi_tool_index_attr
-#define                be_index_change bd_info->bi_tool_index_change
 #define                be_sync bd_info->bi_tool_sync
-#endif
-
-#ifdef HAVE_CYRUS_SASL
-#define                be_sasl_authorize bd_info->bi_sasl_authorize
-#define                be_sasl_getsecret bd_info->bi_sasl_getsecret
-#define                be_sasl_putsecret bd_info->bi_sasl_putsecret
 #endif
 
        /* these should be renamed from be_ to bd_ */
@@ -970,25 +962,9 @@ struct slap_backend_info {
        ID (*bi_tool_entry_next) LDAP_P(( BackendDB *be ));
        Entry* (*bi_tool_entry_get) LDAP_P(( BackendDB *be, ID id ));
        ID (*bi_tool_entry_put) LDAP_P(( BackendDB *be, Entry *e ));
-       int (*bi_tool_index_attr) LDAP_P(( BackendDB *be,
-               AttributeDescription *desc ));
-       int (*bi_tool_index_change) LDAP_P(( BackendDB *be,
-               AttributeDescription *desc,
-               struct berval **bv, ID id, int op ));
+       int (*bi_tool_entry_reindex) LDAP_P(( BackendDB *be, ID id ));
        int (*bi_tool_sync) LDAP_P(( BackendDB *be ));
 
-#ifdef HAVE_CYRUS_SASL
-       int (*bi_sasl_authorize) LDAP_P(( BackendDB *be,
-               const char *authnid, const char *authzid,
-               const char **canon_authzid, const char **errstr ));
-       int (*bi_sasl_getsecret) LDAP_P(( BackendDB *be,
-               const char *mechanism, const char *authzid,
-               const char *realm, sasl_secret_t **secret ));
-       int (*bi_sasl_putsecret) LDAP_P(( BackendDB *be,
-               const char *mechanism, const char *auth_identity,
-               const char *realm, const sasl_secret_t *secret ));
-#endif /* HAVE_CYRUS_SASL */
-
 #define SLAP_INDEX_ADD_OP              0x0001
 #define SLAP_INDEX_DELETE_OP   0x0002
 
@@ -998,6 +974,23 @@ struct slap_backend_info {
        void    *bi_private;    /* anything the backend type needs */
 };
 
+typedef struct slap_authz_info {
+       unsigned        sai_ssf;                /* Security Strength Factor */
+       ber_tag_t       sai_method;             /* LDAP_AUTH_* from <ldap.h> */
+       char *          sai_mech;               /* SASL Mechanism */
+       char *          sai_dn;                 /* DN for reporting purposes */
+       char *          sai_ndn;                /* Normalized DN */
+} AuthorizationInformation;
+
+#define c_authtype     c_authz.sai_method
+#define c_authmech     c_authz.sai_mech
+#define c_dn           c_authz.sai_dn
+
+#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
+
 /*
  * represents an operation pending from an ldap client
  */
@@ -1005,31 +998,16 @@ typedef struct slap_op {
        ber_int_t       o_opid;         /* id of this operation           */
        ber_int_t       o_msgid;        /* msgid of the request           */
 
-       ldap_pvt_thread_t       o_tid;          /* thread handling this op        */
+       ldap_pvt_thread_t       o_tid;  /* thread handling this op        */
 
        BerElement      *o_ber;         /* ber of the request             */
 
        ber_tag_t       o_tag;          /* tag of the request             */
        time_t          o_time;         /* time op was initiated          */
 
-#ifdef SLAP_AUTHZID
-       /* should only be used for reporting purposes */
-       char    *o_authc_dn;    /* authentication DN */
-
-       /* should be used as the DN of the User */
-       char    *o_authz_dn;    /* authorization DN */
-       char    *o_authz_ndn;   /* authorizaiton NDN */
-
-#else
-       char            *o_dn;          /* dn bound when op was initiated */
-       char            *o_ndn;         /* normalized dn bound when op was initiated */
-#endif
+       AuthorizationInformation o_authz;
 
        ber_int_t       o_protocol;     /* version of the LDAP protocol used by client */
-       ber_tag_t       o_authtype;     /* auth method used to bind dn    */
-                                       /* values taken from ldap.h       */
-                                       /* LDAP_AUTH_*                    */
-       char            *o_authmech; /* SASL mechanism used to bind dn */
 
        LDAPControl     **o_ctrls;       /* controls */
 
@@ -1071,9 +1049,7 @@ typedef struct slap_conn {
        /* only can be changed by binding thread */
        int             c_sasl_bind_in_progress;        /* multi-op bind in progress */
        char    *c_sasl_bind_mech;                      /* mech in progress */
-#ifdef HAVE_CYRUS_SASL
-       sasl_conn_t     *c_sasl_bind_context;   /* Cyrus SASL state data */
-#endif
+       char    *c_cdn;
 
        /* authentication backend */
        Backend *c_authc_backend;
@@ -1081,23 +1057,9 @@ typedef struct slap_conn {
        /* authorization backend - normally same as c_authc_backend */
        Backend *c_authz_backend;
 
-#ifdef SLAP_AUTHZID
-       /* authentication backend */
-       /* should only be used for reporting purposes */
-       char    *c_authc_dn;    /* authentication DN */
-
-       /* should be used as the DN of the User */
-       char    *c_authz_dn;    /* authorization DN */
-       char    *c_authz_ndn;   /* authorization NDN */
-
-#else
-       char    *c_cdn;         /* DN provided by the client */
-       char    *c_dn;          /* DN bound to this conn  */
-#endif
+       AuthorizationInformation c_authz;
 
        ber_int_t       c_protocol;     /* version of the LDAP protocol used by client */
-       ber_tag_t       c_authtype;/* auth method used to bind c_dn  */
-       char    *c_authmech;    /* SASL mechanism used to bind c_dn */
 
        Operation       *c_ops;                 /* list of operations being processed */
        Operation       *c_pending_ops; /* list of pending operations */
@@ -1112,6 +1074,9 @@ typedef struct slap_conn {
        int     c_is_tls;               /* true if this LDAP over raw TLS */
        int     c_needs_tls_accept;     /* true if SSL_accept should be called */
 #endif
+       int             c_sasl_layers;   /* true if we need to install SASL i/o handlers */
+       void    *c_sasl_context;        /* SASL session context */
+       void    *c_sasl_extra;          /* SASL session extra stuff */
 
        long    c_n_ops_received;               /* num of ops received (next op_id) */
        long    c_n_ops_executing;      /* num of ops currently executing */
index 52521da78f176e3bbad81f75a6db4bf4acced98a..9b9e01c809e3ccde6a8e7f2f2e924fde75e78de0 100644 (file)
@@ -101,7 +101,7 @@ syn_insert(
 
 int
 syn_add(
-    LDAP_SYNTAX                *syn,
+    LDAPSyntax         *syn,
        unsigned flags,
     slap_syntax_validate_func  *validate,
     slap_syntax_transform_func *normalize,
@@ -118,7 +118,7 @@ syn_add(
 
        ssyn = (Syntax *) ch_calloc( 1, sizeof(Syntax) );
 
-       memcpy( &ssyn->ssyn_syn, syn, sizeof(LDAP_SYNTAX) );
+       AC_MEMCPY( &ssyn->ssyn_syn, syn, sizeof(LDAPSyntax) );
 
        ssyn->ssyn_next = NULL;
 
@@ -144,7 +144,7 @@ register_syntax(
        slap_syntax_transform_func *ber2str,
        slap_syntax_transform_func *str2ber )
 {
-       LDAP_SYNTAX     *syn;
+       LDAPSyntax      *syn;
        int             code;
        const char      *err;
 
@@ -156,6 +156,9 @@ register_syntax(
        }
 
        code = syn_add( syn, flags, validate, ber2str, str2ber, &err );
+
+       ldap_memfree( syn );
+
        if ( code ) {
                Debug( LDAP_DEBUG_ANY, "Error in register_syntax: %s %s in %s\n",
                    scherr2str(code), err, desc );
index fad33e3883ba94c7d79d9f04a3715ed764895245..227ffd0bea0633ea64a9d78c3766d131f6714de0 100644 (file)
@@ -75,3 +75,15 @@ clean-local: FORCE
 
 depend-local: FORCE
        $(MKDEP) $(DEFS) $(DEFINES) $(SRCS)
+
+install-local: install-ldbm-$(BUILD_LDBM)
+
+install-ldbm-no:
+
+install-ldbm-yes install-ldbm-mod: FORCE
+       -$(MKDIR) $(DESTDIR)$(sbindir)
+       @for bin in $(PROGRAMS); do \
+               $(LTINSTALL) $(INSTALLFLAGS) -s -m 755 \
+                       $$bin$(EXEEXT) $(DESTDIR)$(sbindir); \
+       done
+
index a2d8f742a56215ae6963ceda385042d5bf03e554..2398308aca710d7a0c0263ebe6baeda3207c92c3 100644 (file)
@@ -136,24 +136,19 @@ struct berval **get_entry_referrals(
        return NULL;
 }
 
-int sasl_init(void) {
-       return 0;
+int slap_sasl_init(void)
+{
+       return LDAP_SUCCESS;
 }
 
-int sasl_destroy(void) {
-       return 0;
+int slap_sasl_destroy(void)
+{
+       return LDAP_SUCCESS;
 }
 
-#ifdef HAVE_CYRUS_SASL
-int sasl_bind(
-    Connection          *conn,
-    Operation           *op,
-    const char          *dn,
-    const char          *ndn,
-    const char          *mech,
-    struct berval       *cred,
-    char                **edn)
+char * slap_sasl_secprops( const char *in )
 {
-       return -1;
+       assert(0);
+       return NULL;
 }
-#endif
+
index 45ba63a2d88e346a4886e5f611199e89fd3d9b6a..954635a801d62f93b522fae194cd46f82dbe0686 100644 (file)
@@ -54,7 +54,7 @@ usage( int tool )
                break;
 
        case SLAPINDEX:
-               options = "\tattributetype\n";
+               options = "\n";
                break;
        }
 
@@ -161,9 +161,7 @@ slap_tool_init(
                }
        }
 
-       if ( ( argc != optind + (tool == SLAPINDEX ? 1 : 0) )
-               || (dbnum >= 0 && base != NULL ) )
-       {
+       if ( ( argc != optind ) || (dbnum >= 0 && base != NULL ) ) {
                usage( tool );
        }
 
index efee55d7e873e23d39762d655dc7f338d29a3966..867e244cbd4d2b9bc12e3b8a4d28caa895c7c634 100644 (file)
@@ -19,9 +19,6 @@
 int
 main( int argc, char **argv )
 {
-       char            *type;
-       AttributeDescription *desc;
-       const char *text;
        ID id;
        int rc = EXIT_SUCCESS;
 
@@ -31,31 +28,13 @@ main( int argc, char **argv )
                !be->be_entry_close &&
                !be->be_entry_first &&
                !be->be_entry_next &&
-               !be->be_entry_get &&
-               !be->be_index_attr &&
-               !be->be_index_change )
+               !be->be_entry_reindex )
        {
                fprintf( stderr, "%s: database doesn't support necessary operations.\n",
                        progname );
                exit( EXIT_FAILURE );
        }
 
-       type = argv[argc - 1];
-
-       rc = slap_str2ad( type, &desc, &text );
-
-       if( rc != LDAP_SUCCESS ) {
-               fprintf( stderr, "%s: unrecognized attribute type: %s\n",
-                       progname, text );
-               exit( EXIT_FAILURE );
-       }
-
-       if ( !be->be_index_attr( be, desc ) ) {
-               fprintf( stderr, "attribute type \"%s\": no indices to generate\n",
-                       type );
-               exit( EXIT_FAILURE );
-       }
-
        if( be->be_entry_open( be, 0 ) != 0 ) {
                fprintf( stderr, "%s: could not open database.\n",
                        progname );
@@ -66,49 +45,23 @@ main( int argc, char **argv )
                id != NOID;
                id = be->be_entry_next( be ) )
        {
-               Entry* e = be->be_entry_get( be, id );
-
-               if ( e == NULL ) {
-                       fprintf( stderr,
-                               "entry id=%08lx: no data\n", (long) id );
-                       rc = EXIT_FAILURE;
-                       if( continuemode ) continue;
-                       break;
-               }
+               int rtn;
 
                if( verbose ) {
-                       printf("indexing id=%08lx dn=\"%s\"\n",
-                               id, e->e_dn );
+                       printf("indexing id=%08lx\n", (long) id );
                }
 
-               {
-                       Attribute *attr;
-                       
-                       for( attr = attrs_find( e->e_attrs, desc );
-                               attr != NULL;
-                               attr = attrs_find( attr->a_next, desc ) )
-                       {
+               rtn =  be->be_entry_reindex( be, id );
 
-                               if ( be->be_index_change( be,
-                                       desc, attr->a_vals, id, SLAP_INDEX_ADD_OP ) )
-                               {
-                                       rc = EXIT_FAILURE;
-
-                                       if( !continuemode ) {
-                                               entry_free( e );
-                                               goto done;
-                                       }
-                               }
-                       }
+               if( rtn != LDAP_SUCCESS ) {
+                       rc = EXIT_FAILURE;
+                       if( continuemode ) continue;
+                       break;
                }
-
-               entry_free( e );
        }
 
-done:
        (void) be->be_entry_close( be );
 
        slap_tool_destroy();
-
        return( rc );
 }
index 37c32c4e94a1e41c58e30341831a929c6f7f1269..c433ab63573a9498c6e8e6c97bb92efeb1969128 100644 (file)
@@ -63,7 +63,7 @@ main( int argc, char *argv[] )
                                char* p;
 
                                for( p = optarg; *p == '\0'; p++ ) {
-                                       *p = '*';
+                                       *p = '\0';
                                }
                        }
                        break;
index 2440a6a6e17bad96e3cbc6ea9361bcb5dd6d76e4..e4b9ee0ed6c4ea05ae9e61947c6f629cf385febd 100644 (file)
@@ -188,9 +188,11 @@ int value_find(
                        vals[i], nval == NULL ? val : nval, &text );
 
                if( rc == LDAP_SUCCESS && match == 0 ) {
+                       ber_bvfree( nval );
                        return LDAP_SUCCESS;
                }
        }
 
+       ber_bvfree( nval );
        return LDAP_NO_SUCH_ATTRIBUTE;
 }
index d3017932e12c19b190bba068ed031082b4ca3cc9..5425258fad277df46670337ebf8da66074212cd7 100644 (file)
@@ -40,5 +40,5 @@ RETSIGTYPE
 do_admin( int sig )
 {
     sglob->rq->rq_dump( sglob->rq );
-    (void) SIGNAL( sig, do_admin );
+    (void) SIGNAL_REINSTALL( sig, do_admin );
 }
index d91a70aa234497b6585bec88ea8c272b7b580e52..670ceeb8ae49bcf75fee1fee58599afa402bb64c 100644 (file)
@@ -173,12 +173,12 @@ strtok_quote(
            } else {
                inquote = 1;
            }
-           SAFEMEMCPY( next, next + 1, strlen( next + 1 ) + 1 );
+           AC_MEMCPY( next, next + 1, strlen( next + 1 ) + 1 );
            break;
 
        case '\\':
            if ( next[1] )
-               SAFEMEMCPY( next, next + 1, strlen( next + 1 ) + 1 );
+               AC_MEMCPY( next, next + 1, strlen( next + 1 ) + 1 );
            next++;             /* dont parse the escaped character */
            break;
 
index 75c1afed027b74da2036f8bc638b748c3adeab35..90b89bbe1c258df4165e6674c50de21739ceb847 100644 (file)
@@ -144,7 +144,7 @@ set_shutdown(int sig)
        (sglob->replicas[ i ])->ri_wake( sglob->replicas[ i ]);
     }
     sglob->rq->rq_unlock( sglob->rq );                 /* unlock queue */
-    (void) SIGNAL( sig, set_shutdown );        /* reinstall handlers */
+    (void) SIGNAL_REINSTALL( sig, set_shutdown );      /* reinstall handlers */
 }
 
 
@@ -156,7 +156,7 @@ set_shutdown(int sig)
 RETSIGTYPE
 do_nothing(int sig)
 {
-    (void) SIGNAL( sig, do_nothing );
+    (void) SIGNAL_REINSTALL( sig, do_nothing );
 }
 
 
index df1780c49e060c902ff1d806ce7a1509af56f481..2718ede4e8da32d1fc1c5aef1de53c0f7abd4c7b 100644 (file)
@@ -184,7 +184,7 @@ Re_parse(
            break;
        case T_DN:
            re->re_dn = ch_malloc( len + 1 );
-               memcpy( re->re_dn, value, len );
+               AC_MEMCPY( re->re_dn, value, len );
                re->re_dn[ len ]='\0';
            state |= GOT_DN;
            break;
@@ -234,7 +234,7 @@ Re_parse(
        re->re_mods[ nml ].mi_type = strdup( type );
        if ( value != NULL ) {
            re->re_mods[ nml ].mi_val = ch_malloc( len + 1 );
-               memcpy( re->re_mods[ nml ].mi_val, value, len );
+               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 {
index 9e9db59baf92dc6999c0ffec6148a6fd7985bfcf..58992bfb7143400daae7a707e02e310b851b5298 100644 (file)
@@ -21,7 +21,8 @@ suffix                "o=University of Michigan, c=US"
 directory      ./test-db
 rootdn         "cn=Manager, o=University of Michigan, c=US"
 rootpw         secret
-index          cn,sn,uid       pres,eq
+index          objectClass     eq
+index          cn,sn,uid       pres,eq,sub
 lastmod                on
 defaultaccess  none
 
index b95d3932c3621cc728b5b2c8eb6130243e542bea..bdd60db8109997f5d476b0d04962de0190bf73c6 100644 (file)
@@ -9,6 +9,9 @@ schemacheck     on
 pidfile     ./test-db/slapd.pid
 argsfile    ./test-db/slapd.args
 
+sasl-secprops noanonymous
+#sasl-secprops none
+
 #######################################################################
 # ldbm database definitions
 #######################################################################
index 8d862673b795d59ac8604ffe449d29794a5996e9..f3d7e044b101ed1af73184cc06216602a921ec8f 100644 (file)
@@ -21,6 +21,3 @@ suffix                "o=University of Michigan, c=US"
 directory      ./test-db
 rootdn         "cn=Manager, o=University of Michigan, c=US"
 rootpw         secret
-index          cn,sn,uid       pres,eq
-dbnosync
-dbnolocking
index b6d152ba4489a4ff6b4fc28ced409d78c54abbc6..0aebb564d0d1bb6b41f8adfd7be785e200ddfb15 100644 (file)
@@ -22,6 +22,7 @@ suffix                "o=SGI, c=US"
 directory      ./test-db
 rootdn         "cn=Manager, o=SGI, c=US"
 rootpw         secret
+index          objectClass     eq
 index          uid                     pres,eq,approx
 index          gidNumber               pres,eq,approx
 index          uidNumber               pres,eq,approx
index 29fa8e28243f482cf13550d41afc92af259d071a..2b1681c989834cd221512adb48ff04a295469854 100644 (file)
@@ -23,7 +23,8 @@ suffix                "o=University of Michigan, c=US"
 directory      ./test-db
 rootdn         "cn=Manager, o=University of Michigan, c=US"
 rootpw         secret
-index          cn,sn,uid       pres,eq
+index          objectClass     eq
+index          cn,sn,uid       pres,eq,sub
 lastmod                on
 defaultaccess  none
 
index 9182fa48f6025f0efe01cb2bd5bca6349898174d..714e4e097ec27127c5837ba2174fb50d7c77668c 100644 (file)
@@ -25,5 +25,6 @@ suffix                "o=University of Mich, c=US"
 directory      ./test-repl
 rootdn         "cn=Manager, o=University of Mich, c=US"
 rootpw         secret
-index          cn,sn,uid       pres,eq
+index          objectClass     eq
+index          cn,sn,uid       pres,eq,sub
 lastmod                on
index 76df58f818018320b39e4fcc8e9aa8b829bb23ea..57098f378673837bf77cbe6c55847289ae0aa796 100644 (file)
@@ -23,7 +23,8 @@ suffix                "o=University of Michigan, c=US"
 directory      ./test-db
 rootdn         "cn=Manager, o=University of Michigan, c=US"
 rootpw         secret
-index          cn,sn,uid       pres,eq
+index          objectClass     eq
+index          cn,sn,uid       pres,eq,sub
 lastmod                on
 
 replogfile     ./test-db/slapd.replog
index d821427d2ec98257582537e0a5a472f2e65c6205..ee7fea837b26b262889f7d85915247cdec6274e4 100644 (file)
@@ -26,5 +26,6 @@ rootdn                "cn=Replica, o=University of Michigan, c=US"
 rootpw         secret
 updatedn       "cn=Replica, o=University of Michigan, c=US"
 updateref      "ldap://localhost:9009/o=University%20of%20Michigan,c=US"
-index          cn,sn,uid       pres,eq
+index          objectClass     eq
+index          cn,sn,uid       pres,eq,sub
 lastmod                on
diff --git a/tests/data/slapd.conf b/tests/data/slapd.conf
new file mode 100644 (file)
index 0000000..0cac379
--- /dev/null
@@ -0,0 +1,28 @@
+# $OpenLDAP$
+#
+# stand-alone slapd config -- for testing
+#      with indexing
+#
+#include               ./data/slapd.at.conf
+#include               ./data/slapd.oc.conf
+include ./schema/core.schema
+include ./schema/cosine.schema
+include ./schema/inetorgperson.schema
+#include ./schema/nis.schema
+schemacheck    on
+pidfile     ./test-db/slapd.pid
+argsfile    ./test-db/slapd.args
+
+#######################################################################
+# ldbm database definitions
+#######################################################################
+
+database       ldbm
+suffix         "o=University of Michigan, c=US"
+directory      ./test-db
+rootdn         "cn=Manager, o=University of Michigan, c=US"
+rootpw         secret
+index          objectclass     eq
+index          cn,sn,uid       pres,eq,sub
+dbnosync
+dbnolocking
index b555f71d64e5124a45c0b31b2743a4c0383e17ad..09849483e08be48e3e87a32f447b121a057b062a 100644 (file)
@@ -173,7 +173,7 @@ addmodifyop( LDAPMod ***pmodsp, int modop, char *attr, char *value, int vlen )
                        perror( "malloc" );
                        exit( EXIT_FAILURE );
            }
-           SAFEMEMCPY( bvp->bv_val, value, vlen );
+           AC_MEMCPY( bvp->bv_val, value, vlen );
            bvp->bv_val[ vlen ] = '\0';
     }
 }
index f88faf8e964d1586da166fc2f4bdb29e876561c6..6a513fa7a5cd80e8acc10acf9dea9a3672f73dd8 100755 (executable)
@@ -13,7 +13,8 @@ if test "$BACKEND" = "bdb2" ; then
        REFSLAVECONF=$DATADIR/slapd-bdb2-ref-slave.conf
        TIMING="-t"
 else
-       CONF=$DATADIR/slapd-master.conf
+       CONF=$DATADIR/slapd.conf
+       MCONF=$DATADIR/slapd-master.conf
        PWCONF=$DATADIR/slapd-pw.conf
        ACLCONF=$DATADIR/slapd-acl.conf
        MASTERCONF=$DATADIR/slapd-repl-master.conf
@@ -21,26 +22,27 @@ else
        REFSLAVECONF=$DATADIR/slapd-ref-slave.conf
 fi
 
-if test "$LDAP_PROTO" ; then
-       PROTO="-P $LDAP_PROTO"
-fi
+TOOLARGS="-x $LDAP_TOOLARGS"
+TOOLPROTO="-P 3"
 
 PASSWDCONF=$DATADIR/slapd-passwd.conf
 
 CLIENTDIR=../clients/tools
 #CLIENTDIR=/usr/local/bin
 
-LDIF2LDBM="../servers/slapd/tools/slapadd $LDAP_VERBOSE"
+SLAPADD="../servers/slapd/tools/slapadd $LDAP_VERBOSE"
+SLAPCAT="../servers/slapd/tools/slapcat $LDAP_VERBOSE"
+SLAPINDEX="../servers/slapd/tools/slapindex $LDAP_VERBOSE"
 
-#CMP=cmp
-CMP="diff -i -q"
+CMP="diff -i"
+CMPOUT=/dev/null
 SLAPD=../servers/slapd/slapd
 SLURPD=../servers/slurpd/slurpd
-LDAPPASSWD="$CLIENTDIR/ldappasswd"
-LDAPSEARCH="$CLIENTDIR/ldapsearch $PROTO -LLL"
-LDAPMODIFY="$CLIENTDIR/ldapmodify $PROTO"
-LDAPADD="$CLIENTDIR/ldapadd $PROTO"
-LDAPMODRDN="$CLIENTDIR/ldapmodrdn $PROTO"
+LDAPPASSWD="$CLIENTDIR/ldappasswd $TOOLARGS"
+LDAPSEARCH="$CLIENTDIR/ldapsearch $TOOLPROTO $TOOLARGS -LLL"
+LDAPMODIFY="$CLIENTDIR/ldapmodify $TOOLPROTO $TOOLARGS"
+LDAPADD="$CLIENTDIR/ldapadd $TOOLPROTO $TOOLARGS"
+LDAPMODRDN="$CLIENTDIR/ldapmodrdn $TOOLPROTO $TOOLARGS"
 SLAPDTESTER=$PROGDIR/slapd-tester
 LVL=${SLAPD_DEBUG-5}
 ADDR=127.0.0.1
index 442c62fa1cac5dbf2b3eba287108ae05cdb673bc..da66c86d128dc4f7afba6ee2c6cd4b427cdd0517 100755 (executable)
@@ -27,7 +27,7 @@ echo "Cleaning up in $DBDIR..."
 rm -f $DBDIR/[!C]*
 
 echo "Running slapadd to build slapd database..."
-$LDIF2LDBM -f $NIS_CONF -l $NIS_LDIF
+$SLAPADD -f $NIS_CONF -l $NIS_LDIF
 RC=$?
 if [ $RC != 0 ]; then
        echo "slapadd failed!"
index efe811eae7663c5852145224385c617648f6fd5f..6cada5e4320810cf603e0484636efdcabf4b0b67 100755 (executable)
@@ -21,7 +21,7 @@ echo "Cleaning up in $DBDIR..."
 rm -f $DBDIR/[!C]*
 
 echo "Running slapadd to build slapd database..."
-$LDIF2LDBM -f $CONF -l $LDIF
+$SLAPADD -f $CONF -l $LDIF
 RC=$?
 if test $RC != 0 ; then
        echo "slapadd failed ($RC)!"
@@ -34,8 +34,7 @@ PID=$!
 
 echo "Using ldapsearch to retrieve all the entries..."
 for i in 0 1 2 3 4 5; do
-       $LDAPSEARCH -S "" -b "$BASEDN" -h localhost -p $PORT \
-               'objectClass=*' > $SEARCHOUT 2>&1
+       $LDAPSEARCH -S "" -b "$BASEDN" -h localhost:$PORT > $SEARCHOUT 2>&1
        RC=$?
        if test $RC = 1 ; then
                echo "Waiting 5 seconds for slapd to start..."
@@ -55,7 +54,7 @@ echo "Filtering ldapsearch results..."
 echo "Filtering original ldif used to create database..."
 . $SRCDIR/scripts/acfilter.sh < $LDIF > $LDIFFLT
 echo "Comparing filter output..."
-$CMP $SEARCHFLT $LDIFFLT
+$CMP $SEARCHFLT $LDIFFLT > $CMPOUT
 
 if test $? != 0 ; then
        echo "comparison failed - database was not created correctly"
index fdf62cb97d4267c3e0c889207f34d92e0e43d33c..8846768828ae443735ce84249a84eca56bacc214 100755 (executable)
@@ -58,7 +58,7 @@ echo "Filtering ldapsearch results..."
 echo "Filtering original ldif used to create database..."
 . $SRCDIR/scripts/acfilter.sh < $LDIF > $LDIFFLT
 echo "Comparing filter output..."
-$CMP $SEARCHFLT $LDIFFLT
+$CMP $SEARCHFLT $LDIFFLT > $CMPOUT
 
 if test $? != 0 ; then
        echo "comparison failed - database was not created correctly"
index bced8e1fbb5b7ed2204d4ca8a2c05a58a7cc458a..dadad8a17968bbb97e7613ae614e174551708b5b 100755 (executable)
@@ -18,13 +18,21 @@ echo "Cleaning up in $DBDIR..."
 rm -f $DBDIR/[!C]*
 
 echo "Running slapadd to build slapd database..."
-$LDIF2LDBM -f $CONF -l $LDIF
+$SLAPADD -f $MCONF -l $LDIF
 RC=$?
 if test $RC != 0 ; then
        echo "slapadd failed ($RC)!"
        exit $RC
 fi
 
+echo "Running slapindex to index slapd database..."
+$SLAPINDEX -f $CONF
+RC=$?
+if test $RC != 0 ; then
+       echo "slapindex failed ($RC)!"
+       exit $RC
+fi
+
 echo "Starting slapd on TCP/IP port $PORT..."
 $SLAPD -f $CONF -h $MASTERURI -d $LVL $TIMING > $MASTERLOG 2>&1 &
 PID=$!
@@ -93,7 +101,7 @@ echo "Filtering ldapsearch results..."
 echo "Filtering original ldif used to create database..."
 . $SRCDIR/scripts/acfilter.sh < $LDIF > $LDIFFLT
 echo "Comparing filter output..."
-$CMP $SEARCHFLT $LDIFFLT
+$CMP $SEARCHFLT $LDIFFLT > $CMPOUT
 
 if test $? != 0 ; then
        echo "Comparison failed"
index f485007de75ed098c3081187c3ed79466268343a..6bd4e9e7d4b3cd210ed76ba3c8462fe00ab3ebf0 100755 (executable)
@@ -18,7 +18,7 @@ echo "Cleaning up in $DBDIR..."
 rm -f $DBDIR/[!C]*
 
 echo "Running slapadd to build slapd database..."
-$LDIF2LDBM -f $CONF -l $LDIF
+$SLAPADD -f $CONF -l $LDIF
 RC=$?
 if test $RC != 0 ; then
        echo "slapadd failed ($RC)!"
@@ -135,7 +135,7 @@ echo "Filtering ldapsearch results..."
 echo "Filtering original ldif used to create database..."
 . $SRCDIR/scripts/acfilter.sh < $LDIF > $LDIFFLT
 echo "Comparing filter output..."
-$CMP $SEARCHFLT $LDIFFLT
+$CMP $SEARCHFLT $LDIFFLT > $CMPOUT
 
 if test $? != 0 ; then
        echo "comparison failed - modify operations did not complete correctly"
index f72ccfdf6adec3ce34da6f0c62eba7f07d3df9ac..9029a1c2976d654642426e46ae69af14b3cf4fda 100755 (executable)
@@ -18,7 +18,7 @@ echo "Cleaning up in $DBDIR..."
 rm -f $DBDIR/[!C]*
 
 echo "Running slapadd to build slapd database..."
-$LDIF2LDBM -f $CONF -l $LDIF
+$SLAPADD -f $CONF -l $LDIF
 RC=$?
 if test $RC != 0 ; then
        echo "slapadd failed ($RC)!"
@@ -91,7 +91,7 @@ echo "Filtering ldapsearch results..."
 echo "Filtering original ldif used to create database..."
 . $SRCDIR/scripts/acfilter.sh < $LDIF > $LDIFFLT
 echo "Comparing filter output..."
-$CMP $SEARCHFLT $LDIFFLT
+$CMP $SEARCHFLT $LDIFFLT > $CMPOUT
 
 if test $? != 0 ; then
        echo "comparison failed - modrdn operations did not complete correctly"
@@ -118,7 +118,7 @@ echo "Filtering ldapsearch results..."
 echo "Filtering original ldif used to create database..."
 . $SRCDIR/scripts/acfilter.sh < $LDIF > $LDIFFLT
 echo "Comparing filter output..."
-$CMP $SEARCHFLT $LDIFFLT
+$CMP $SEARCHFLT $LDIFFLT > $CMPOUT
 
 if test $? != 0 ; then
        echo "comparison failed - modrdn operations did not complete correctly"
@@ -138,7 +138,7 @@ if test $RC != 0 ; then
        echo "ldapsearch failed ($RC)!"
        exit $RC
 fi
-$CMP $SEARCHOUT /dev/null
+$CMP $SEARCHOUT /dev/null > $CMPOUT
 if test $? != 0 ; then
        echo "failure: ldapsearch found attribute that was to be removed!"
        kill -HUP $PID
@@ -162,7 +162,7 @@ echo "Filtering ldapsearch results..."
 echo "Filtering original ldif used to create database..."
 . $SRCDIR/scripts/acfilter.sh < $LDIF > $LDIFFLT
 echo "Comparing filter output..."
-$CMP $SEARCHFLT $LDIFFLT
+$CMP $SEARCHFLT $LDIFFLT > $CMPOUT
 
 if test $? != 0 ; then
        echo "comparison failed - modrdn operations did not complete correctly"
@@ -203,7 +203,7 @@ echo "Filtering ldapsearch results..."
 echo "Filtering original ldif used to create database..."
 . $SRCDIR/scripts/acfilter.sh < $LDIF > $LDIFFLT
 echo "Comparing filter output..."
-$CMP $SEARCHFLT $LDIFFLT
+$CMP $SEARCHFLT $LDIFFLT > $CMPOUT
 
 kill -HUP $PID
 if test $? != 0 ; then
index a9defa4414a573f149aa24fa47954abb78bcd5f1..6c0b1a0dcdf498bed35fb0364347d068f4f4ad33 100755 (executable)
@@ -18,7 +18,7 @@ echo "Cleaning up in $DBDIR..."
 rm -f $DBDIR/[!C]*
 
 echo "Running slapadd to build slapd database..."
-$LDIF2LDBM -f $CONF -l $LDIF
+$SLAPADD -f $CONF -l $LDIF
 RC=$?
 if test $RC != 0 ; then
        echo "slapadd failed ($RC)!"
@@ -131,7 +131,7 @@ echo "Filtering ldapsearch results..."
 echo "Filtering original ldif used to create database..."
 . $SRCDIR/scripts/acfilter.sh < $LDIF > $LDIFFLT
 echo "Comparing filter output..."
-$CMP $SEARCHFLT $LDIFFLT
+$CMP $SEARCHFLT $LDIFFLT > $CMPOUT
 
 if test $? != 0 ; then
        echo "comparison failed - modify operations did not complete correctly"
index f71a002120478966c48aaad01df0bd37a4a48fed..870e68398531b9e7a69d7b00638a7bda658123f3 100755 (executable)
@@ -174,7 +174,7 @@ echo "Filtering original ldif used to create database..."
 . $SRCDIR/scripts/acfilter.sh < $LDIF > $LDIFFLT
 
 echo "Comparing retrieved entries from master and slave..."
-$CMP $SEARCHFLT $LDIFFLT
+$CMP $SEARCHFLT $LDIFFLT > $CMPOUT
 
 if test $? != 0 ; then
        echo "test failed - master and slave databases differ"
index 8110d37e6182aca0bb04d37da531f4e1b18c2e36..ec93723ad2a0de83061b93b401a5580198add368 100755 (executable)
@@ -21,7 +21,7 @@ echo "Cleaning up in $DBDIR..."
 rm -f $DBDIR/[!C]*
 
 echo "Running slapadd to build slapd database..."
-$LDIF2LDBM -f $CONF -l $LDIF
+$SLAPADD -f $CONF -l $LDIF
 RC=$?
 if test $RC != 0 ; then
        echo "slapadd failed ($RC)!"
@@ -72,7 +72,7 @@ echo "Filtering ldapsearch results..."
 echo "Filtering original ldif used to create database..."
 . $SRCDIR/scripts/acfilter.sh < $LDIF > $LDIFFLT
 echo "Comparing filter output..."
-$CMP $SEARCHFLT $LDIFFLT
+$CMP $SEARCHFLT $LDIFFLT > $CMPOUT
 
 if test $? != 0 ; then
        echo "comparison failed - database was not created correctly"
index 745c9cff996a20757ea6dc37f88fb1e900775496..e6f650a266d09789e7a6f43ef0b1a4096c6952d5 100755 (executable)
@@ -23,7 +23,7 @@ rm -f $DBDIR/[!C]*
 rm -f $REPLDIR/[!C]*
 
 echo "Running slapadd to build slapd database..."
-$LDIF2LDBM -f $CONF -l $LDIF
+$SLAPADD -f $CONF -l $LDIF
 RC=$?
 if test $RC != 0 ; then
        echo "slapadd failed ($RC)!"
@@ -113,7 +113,7 @@ echo "Filtering ldapsearch results..."
 echo "Filtering original ldif used to create database..."
 . $SRCDIR/scripts/acfilter.sh < $LDIF > $LDIFFLT
 echo "Comparing filter output..."
-$CMP $SEARCHFLT $LDIFFLT
+$CMP $SEARCHFLT $LDIFFLT > $CMPOUT
 
 if test $? != 0 ; then
        echo "Comparison failed"