]> git.sur5r.net Git - openldap/commitdiff
updates from HEAD
authorKurt Zeilenga <kurt@openldap.org>
Wed, 5 Jun 2002 22:07:20 +0000 (22:07 +0000)
committerKurt Zeilenga <kurt@openldap.org>
Wed, 5 Jun 2002 22:07:20 +0000 (22:07 +0000)
44 files changed:
clients/tools/ldapsearch.c
doc/devel/args [new file with mode: 0644]
doc/man/man1/ldapdelete.1
doc/man/man3/ldap_error.3
doc/man/man5/slapd-shell.5
doc/man/man5/slapd.conf.5
libraries/libldap/controls.c
libraries/libldap/dnssrv.c [new file with mode: 0644]
libraries/libldap/error.c
libraries/libldap/extended.c
libraries/libldap/getdn.c
libraries/libldap/getentry.c
libraries/libldap/references.c [new file with mode: 0644]
libraries/libldap/result.c
libraries/libldap/sasl.c
libraries/libldap/sort.c
libraries/libldap/sortctrl.c [new file with mode: 0644]
libraries/libldap/url.c
libraries/libldap/vlvctrl.c [new file with mode: 0644]
libraries/libldap_r/tpool.c
libraries/liblutil/entropy.c
servers/slapd/at.c
servers/slapd/back-ldbm/modify.c
servers/slapd/back-shell/abandon.c
servers/slapd/back-shell/add.c
servers/slapd/back-shell/bind.c
servers/slapd/back-shell/compare.c
servers/slapd/back-shell/delete.c
servers/slapd/back-shell/modify.c
servers/slapd/back-shell/modrdn.c
servers/slapd/back-shell/search.c
servers/slapd/back-shell/unbind.c
servers/slapd/config.c
servers/slapd/daemon.c
servers/slapd/matchedValues.c
servers/slapd/mr.c
servers/slapd/oc.c [new file with mode: 0644]
servers/slapd/passwd.c
servers/slapd/proto-slap.h
servers/slapd/result.c
servers/slapd/schema_prep.c
servers/slapd/schemaparse.c
servers/slapd/slap.h
servers/slapd/syntax.c [new file with mode: 0644]

index bf76dbdfdd0f608898474a955752c99381e4f938..868ac0697fa3f53b1929dba8ff4925b2633d2f9b 100644 (file)
@@ -186,9 +186,14 @@ main( int argc, char **argv )
        int                     referrals, timelimit, sizelimit, debug;
        int             authmethod, version, want_bindpw;
        LDAP            *ld = NULL;
+       int             valuesReturnFilter;
+       BerElement      *ber;
+       struct berval   *bvalp;
+       char    *vrFilter  = NULL, *control  = NULL, *s;
+
 
        infile = NULL;
-       debug = verbose = not = vals2tmp = referrals =
+       debug = verbose = not = vals2tmp = referrals = valuesReturnFilter =
                attrsonly = manageDSAit = ldif = want_bindpw = 0;
 
        lutil_log_initialize(argc, argv);
@@ -222,7 +227,7 @@ main( int argc, char **argv )
 
     prog = (prog = strrchr(argv[0], *LDAP_DIRSEP)) == NULL ? argv[0] : prog + 1;
 
-       while (( i = getopt( argc, argv, "Aa:b:F:f:Ll:S:s:T:tuz:"
+       while (( i = getopt( argc, argv, "Aa:b:E:F:f:Ll:S:s:T:tuz:"
                "Cd:D:h:H:IkKMnO:p:P:QR:U:vw:WxX:Y:Z")) != EOF )
        {
        switch( i ) {
@@ -254,6 +259,47 @@ main( int argc, char **argv )
                }
                infile = strdup( optarg );
                break;
+       case 'E': /* controls */
+               if( version == LDAP_VERSION2 ) {
+                       fprintf( stderr, "%s: -C incompatible with LDAPv%d\n",
+                               prog, version );
+                       return EXIT_FAILURE;
+               }
+
+               /* should be extended to support comma separated list of
+                *      key/value pairs:  -E foo=123,bar=567
+                */
+
+               control = strdup( optarg );
+               if ( (s = strchr( control, '=' )) == NULL ) {
+                       return EXIT_FAILURE;
+               }
+
+               *s++ = '\0';
+               if ( strcasecmp( control, "mv" ) == 0 ) {
+                       /* ValuesReturnFilter control */
+                       if (valuesReturnFilter!=0) {
+                               fprintf( stderr, "ValuesReturnFilter previously specified");
+                               return EXIT_FAILURE;
+                       }
+
+                       if ( *s == '!' ){
+                               s++;
+                               valuesReturnFilter=2;
+                       } else {
+                               valuesReturnFilter=1;
+                       }
+
+                       vrFilter = s;
+                       version = LDAP_VERSION3;
+                       break;
+
+               } else {
+                       fprintf( stderr, "Invalid control name: %s\n", control );
+                       usage(prog);
+                       return EXIT_FAILURE;
+               }
+
        case 'F':       /* uri prefix */
                if( urlpre ) free( urlpre );
                urlpre = strdup( optarg );
@@ -829,24 +875,56 @@ main( int argc, char **argv )
                }
        }
 
-       if ( manageDSAit ) {
+       if ( manageDSAit || valuesReturnFilter ) {
                int err;
-               LDAPControl c;
-               LDAPControl *ctrls[2];
-               ctrls[0] = &c;
-               ctrls[1] = NULL;
+               int i=0;
+               LDAPControl c1,c2;
+               LDAPControl *ctrls[3];
+               
+               if ( manageDSAit ) {
+                       ctrls[i++]=&c1;
+                       ctrls[i] = NULL;
+
+                       c1.ldctl_oid = LDAP_CONTROL_MANAGEDSAIT;
+                       c1.ldctl_value.bv_val = NULL;
+                       c1.ldctl_value.bv_len = 0;
+                       c1.ldctl_iscritical = manageDSAit > 1;
+               }
 
-               c.ldctl_oid = LDAP_CONTROL_MANAGEDSAIT;
-               c.ldctl_value.bv_val = NULL;
-               c.ldctl_value.bv_len = 0;
-               c.ldctl_iscritical = manageDSAit > 1;
+               if ( valuesReturnFilter ) {
+                       struct berval *bvalp;
+                       ctrls[i++]=&c2;
+                       ctrls[i] = NULL;
 
+                       c2.ldctl_oid = LDAP_CONTROL_VALUESRETURNFILTER;
+                       c2.ldctl_iscritical = valuesReturnFilter > 1;
+                   
+                       if (( ber = ber_alloc_t(LBER_USE_DER)) == NULL ) 
+                               exit( EXIT_FAILURE );
+
+                       if ( err = put_vrFilter(ber, vrFilter)==-1 ) {
+                               ber_free( ber, 1 );
+                               fprintf( stderr, "Bad ValuesReturnFilter: %s\n", vrFilter );
+                               exit( EXIT_FAILURE );
+                       }
+
+                       if ( ber_flatten( ber, &bvalp ) == LBER_ERROR ) 
+                               return LDAP_NO_MEMORY;
+
+                       c2.ldctl_value=(*bvalp);
+
+               }
+       
                err = ldap_set_option( ld, LDAP_OPT_SERVER_CONTROLS, ctrls );
 
+               ber_bvfree(bvalp);
+               ber_free( ber, 1 );
+
                if( err != LDAP_OPT_SUCCESS ) {
-                       fprintf( stderr, "Could not set ManageDSAit %scontrol\n",
-                               c.ldctl_iscritical ? "critical " : "" );
-                       if( c.ldctl_iscritical ) {
+                       fprintf( stderr, "Could not set %scontrols\n",
+                               (c1.ldctl_iscritical || c2.ldctl_iscritical)
+                               ? "critical " : "" );
+                       if( c1.ldctl_iscritical && c2.ldctl_iscritical ) {
                                exit( EXIT_FAILURE );
                        }
                }
diff --git a/doc/devel/args b/doc/devel/args
new file mode 100644 (file)
index 0000000..ea02cfa
--- /dev/null
@@ -0,0 +1,62 @@
+Tools           ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
+ldapdelete       *CDE *HI*K M*OPQR  U*WXYZ  cdef*h**k *n*p*    vwx*
+ldapmodify       *CDEF*HI*K M*OPQR  U*WXYZabcdef*h**k *n*p*r t vwx*
+ldapmodrdn       *CDE *HI*K M*OPQR  U*WXYZ  cdef*h**k *n*p*rs  vwx*
+ldappasswd      A*CDE *HI*   *O QRS U*WXYZa  de *h**  * * * s  vwx*  
+ldapsearch      A*CDE *HI*KLM*OPQRSTU*WXYZab*def*h**kl*n*p* stuvwx*z
+
+Other Clients   ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
+fax500                               *         f h    m
+finger                               *      c  f  i  l  p    t   x
+go500                   I            *     bcd f     l  p    t   x
+go500gw                 I      P     *    a cd f h   l  p    t   x
+mail500           C                  *       d f h   lm        v
+rcpt500                             U*    abc  f h   l  p   st     z
+rp500                                *    ab d f                 x z
+ud                 D                 *      cd f     l  p   s uv
+
+
+* reserved
+       GJNgijmoqy
+
+* General flags:
+       -C Chase Referrals
+       -D Bind DN
+       -E CommandSpecific Extensions   (e.g., -E <[!]oid[=options]>*)
+       -e General Extensions                   (e.g., -e <[!]oid[=options]>*)
+       -H URI
+       -P protocol version
+       -V version information
+       -W prompt for bind password
+       -d debug
+       -h host
+       -n no-op
+       -p port
+       -v verbose
+       -w Bind password
+
+
+* LDAPv3 Only 
+       -x simple bind (not recommended excepting for
+               anonymous access, w/ -ZZ, or with ldaps://.
+
+       -M ManageDSAIT
+       -Z StartTLS
+
+       -Y SASL Mechanism (defaults to "best")
+       -R SASL Realm (defaults to empty)
+       -O SASL Security Options (defaults to "noanonymous,noplain")
+       -U SASL Authentication Identity (defaults to USER)
+       -X SASL Authorization Identity (defaults to empty)
+
+       -I SASL interactive mode (default: automatic)
+       -Q SASL quiet mode (default: automatic)
+
+
+* LDAPv2+ Only (DEPRECATED)
+       -K LDAPv2 Kerberos Bind (Step 1 only)
+       -k LDAPv2 Kerberos Bind
+
+
+---
+$OpenLDAP$
index ea2f4726c2b77dbd9ff95265dac797e3a0073873..1969b20cc37e8cebe9f39de1f80bee9123e3ba23 100644 (file)
@@ -1,20 +1,61 @@
-.TH LDAPDELETE 1 "13 November 1995" "U-M LDAP LDVERSION"
+.TH LDAPDELETE 1 "20 August 2001" "OpenLDAP LDVERSION"
+.\" $OpenLDAP$
+.\" Copyright 1998-2002 The OpenLDAP Foundation All Rights Reserved.
+.\" Copying restrictions apply.  See COPYRIGHT/LICENSE.
 .SH NAME
-ldapdelete \- ldap delete entry tool
+ldapdelete \- LDAP delete entry tool
 .SH SYNOPSIS
 .B ldapdelete
-.B [\-n]
-.B [\-v]
-.B [\-k]
-.B [\-K]
-.B [\-c]
-.B [\-d debuglevel]
-.B [\-f file]
-.B [\-D binddn]
-.B [\-w passwd]
-.B [\-h ldaphost]
-.B [\-p ldapport]
-.B [dn]...
+[\c
+.BR \-n ]
+[\c
+.BR \-v ]
+[\c
+.BR \-k ]
+[\c
+.BR \-K ]
+[\c
+.BR \-c ]
+[\c
+.BR \-C ]
+[\c
+.BR \-M[M] ]
+[\c
+.BI \-d \ debuglevel\fR]
+[\c
+.BI \-f \ file\fR]
+[\c
+.BI \-D \ binddn\fR]
+[\c
+.BR \-W ]
+[\c
+.BI \-w \ passwd\fR]
+[\c
+.BI \-H \ ldapuri\fR]
+[\c
+.BI \-h \ ldaphost\fR]
+[\c
+.BI \-P \ 2\fR\||\|\fI3\fR]
+[\c
+.BI \-p \ ldapport\fR]
+[\c
+.BR \-O \ security-properties ]
+[\c
+.BI \-U \ authcid\fR]
+[\c
+.BR \-x ]
+[\c
+.BR \-I ]
+[\c
+.BR \-Q ]
+[\c
+.BI \-X \ authzid\fR]
+[\c
+.BI \-Y \ mech\fR]
+[\c
+.BR \-Z[Z] ]
+[\c
+.IR dn ]...
 .SH DESCRIPTION
 .I ldapdelete
 is a shell-accessible interface to the
@@ -23,9 +64,10 @@ library call.
 .LP
 .B ldapdelete
 opens a connection to an LDAP server, binds, and deletes one or more
-entries.  If one or more \fIdn\fP arguments are provided, entries with
-those Distinguished Names are deleted.  Each \fIdn\fP should be a
-string-represented DN as defined in RFC 1779.  If no \fIdn\fP arguments
+entries.  If one or more \fIDN\fP arguments are provided, entries with
+those Distinguished Names are deleted.  Each \fIDN\fP should be provided
+using the LDAPv3 string representation as defined in RFC 2253.
+If no \fIdn\fP arguments
 are provided, a list of DNs is read from standard input (or from
 \fIfile\fP if the -f flag is used).
 .SH OPTIONS
@@ -38,16 +80,19 @@ debugging in conjunction with -v.
 Use verbose mode, with many diagnostics written to standard output.
 .TP
 .B \-k
-Use Kerberos authentication instead of simple authentication.  It is
+Use Kerberos IV authentication instead of simple authentication.  It is
 assumed that you already have a valid ticket granting ticket. This option
 only has effect if
 . B ldapdelete
-is compiled with KERBEROS defined.
+is compiled with Kerberos support.
 .TP
 .B \-K
-Same as \-k, but only does step 1 of the kerberos bind.  This is useful
+Same as \-k, but only does step 1 of the Kerberos IV bind.  This is useful
 when connecting to a slapd and there is no x500dsa.hostname principal
-registered with your kerberos servers.
+registered with your Kerberos Domain Controller(s).
+.TP
+.B \-C
+Automatically chase referrals.
 .TP
 .B \-c
 Continuous operation mode.  Errors  are  reported,  but
@@ -55,55 +100,110 @@ Continuous operation mode.  Errors  are  reported,  but
 will  continue  with  deletions.   The default is to exit after
 reporting an error.
 .TP
-.B \-d debuglevel
+.B \-M[M]
+Enable manage DSA IT control.
+.B \-MM
+makes control critical.
+.TP
+.BI \-d \ debuglevel
 Set the LDAP debugging level to \fIdebuglevel\fP.
 .B ldapdelete
 must be compiled with LDAP_DEBUG defined for this option to have any effect.
 .TP
-.B \-f file
-Read a series of lines from \fIfile\fP, performing one LDAP search for
-each line.  In this case, the \fIfilter\fP given on the command line
-is treated as a pattern where the first occurrence of \fB%s\fP is
-replaced with a line from \fIfile\fP.
+.BI \-f \ file
+Read a series of DNs from \fIfile\fP, one per line, performing an
+LDAP delete for each.
+.TP
+.B \-x 
+Use simple authentication instead of SASL.
+.TP
+.BI \-D \ binddn
+Use the Distinguished Name \fIbinddn\fP to bind to the LDAP directory.
 .TP
-.B \-D binddn
-Use \fIbinddn\fP to bind to the X.500 directory. \fIbinddn\fP should be
-a string-represented DN as defined in RFC 1779.
+.B \-W
+Prompt for simple authentication.
+This is used instead of specifying the password on the command line.
 .TP
-.B \-w passwd
+.BI \-w \ passwd
 Use \fIpasswd\fP as the password for simple authentication.
 .TP
-.B \-h ldaphost
+.BI \-H \ ldapuri
+Specify URI(s) referring to the ldap server(s).
+.TP
+.BI \-h \ ldaphost
 Specify an alternate host on which the ldap server is running.
+Deprecated in favor of -H.
 .TP
-.B \-p ldapport
+.BI \-p \ ldapport
 Specify an alternate TCP port where the ldap server is listening.
+Deprecated in favor of -H.
+.TP
+.BI \-P \ 2\fR\||\|\fI3
+Specify the LDAP protocol version to use.
+.TP
+.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
+.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 \ authcid
+Specify the authentication ID for SASL bind. The form of the identity depends on the
+actual SASL mechanism used.
+.TP
+.BI \-X \ authzid
+Specify the requested authorization ID for SASL bind.
+.I authzid
+must be one of the following formats:
+.B dn:\c
+.I <distinguished name>
+or
+.B u:\c
+.I <username>
+.TP
+.BI \-Y \ mech
+Specify the SASL mechanism to be used for authentication. If it's not
+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.
 .SH EXAMPLE
 The following command:
 .LP
 .nf
-    ldapdelete "cn=Delete Me, o=University of Michigan, c=US"
+    ldapdelete "cn=Delete Me,dc=example,dc=com"
 .fi
 .LP
-will attempt to delete the entry named with commonName "Delete Me"
-directly below the University of Michigan organizational entry.  Of
-course it would probably be necessary to supply a \fIbinddn\fP and
-\fIpasswd\fP for deletion to be allowed (see the -D and -w options).
+will attempt to delete the entry named "cn=Delete Me,dc=example,dc=com".
+Of course it would probably be necessary to supply authentication
+credentials.
 .SH DIAGNOSTICS
 Exit status is 0 if no errors occur.  Errors result in a non-zero exit
 status and a diagnostic message being written to standard error.
 .SH "SEE ALSO"
+.BR ldap.conf (5),
 .BR ldapadd (1),
 .BR ldapmodify (1),
 .BR ldapmodrdn (1),
 .BR ldapsearch (1),
 .BR ldap (3),
 .BR ldap_delete (3)
-.LP
-Kille, S.,
-.IR "A String Representation of Distinguished Names",
-.SM RFC
-1779,
-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/).
+.B     OpenLDAP
+is derived from University of Michigan LDAP 3.3 Release.  
index da99aa62319312a47ee961735815de3098834654..f19e7ff6e3945b403b78d35439ef00fd9d3fb3cd 100644 (file)
@@ -193,8 +193,7 @@ An invalid filter was supplied to ldap_search() (e.g., unbalanced
 parentheses).
 .TP
 .SM LDAP_PARAM_ERROR
-An ldap routine was called with a bad parameter (e.g., a NULL ld
-pointer, etc.).
+An ldap routine was called with a bad parameter.
 .TP
 .SM LDAP_NO_MEMORY
 An memory allocation (e.g., malloc(3) or other dynamic memory
index 0beee6d65781911b3c1ea7457c2c91e5e9d55250..a880f68c6a04232b14ca769e621403838cd44521 100644 (file)
@@ -15,10 +15,8 @@ make it easy to tie an existing database to the
 front-end.
 .SH WARNING
 .B "This backend's calling conventions have changed since OpenLDAP 2.0."
-The operations receive a new "opid:" (operation ID) line, to be used
-instead of "msgid:".
-The "msgid:" line will be removed in a future version.
-Also, abandon now gets a new "abandonid:" line.
+The abandon operation now gets a new "pid:" line.
+The "msgid:" lines will be removed in a future version.
 .SH CONFIGURATION
 These
 .B slapd.conf
@@ -36,17 +34,15 @@ Each option is followed by the input lines that the program receives:
 .B abandon  <pathname> <argument>...
 .nf
 ABANDON
-opid: <operation ID>
 msgid: <message ID of operation to abandon>
 <repeat { "suffix:" <database suffix DN> }>
-abandonid: <operation ID of operation to abandon>
+pid: <process ID of operation to abandon>
 .fi
 .TP
 .B add      <pathname> <argument>...
 .nf
 ADD
-opid: <operation ID>
-msgid: <message ID>
+msgid: <message id>
 <repeat { "suffix:" <database suffix DN> }>
 <entry in LDIF format>
 .fi
@@ -54,8 +50,7 @@ msgid: <message ID>
 .B bind     <pathname> <argument>...
 .nf
 BIND
-opid: <operation ID>
-msgid: <message ID>
+msgid: <message id>
 <repeat { "suffix:" <database suffix DN> }>
 dn: <DN>
 method: <method number>
@@ -66,8 +61,7 @@ cred: <credentials>
 .B compare  <pathname> <argument>...
 .nf
 COMPARE
-opid: <operation ID>
-msgid: <message ID>
+msgid: <message id>
 <repeat { "suffix:" <database suffix DN> }>
 dn: <DN>
 <attribute>: <value>
@@ -76,8 +70,7 @@ dn: <DN>
 .B delete   <pathname> <argument>...
 .nf
 DELETE
-opid: <operation ID>
-msgid: <message ID>
+msgid: <message id>
 <repeat { "suffix:" <database suffix DN> }>
 dn: <DN>
 .fi
@@ -85,8 +78,7 @@ dn: <DN>
 .B modify   <pathname> <argument>...
 .nf
 MODIFY
-opid: <operation ID>
-msgid: <message ID>
+msgid: <message id>
 <repeat { "suffix:" <database suffix DN> }>
 dn: <DN>
 <repeat {
@@ -99,8 +91,7 @@ dn: <DN>
 .B modrdn   <pathname> <argument>...
 .nf
 MODRDN
-opid: <operation ID>
-msgid: <message ID>
+msgid: <message id>
 <repeat { "suffix:" <database suffix DN> }>
 dn: <DN>
 newrdn: <new RDN>
@@ -111,8 +102,7 @@ deleteoldrdn: <0 or 1>
 .B search   <pathname> <argument>...
 .nf
 SEARCH
-opid: <operation ID>
-msgid: <message ID>
+msgid: <message id>
 <repeat { "suffix:" <database suffix DN> }>
 base: <base DN>
 scope: <0-2, see ldap.h>
@@ -127,16 +117,11 @@ attrs: <"all" or space-separated attribute list>
 .B unbind   <pathname> <argument>...
 .nf
 UNBIND
-opid: <operation ID>
-msgid: <message ID>
+msgid: <message id>
 <repeat { "suffix:" <database suffix DN> }>
 dn: <bound DN>
 .fi
 .LP
-An
-.I operation ID
-is a "connection ID/message ID" string identifying an operation.
-.LP
 Note that you need only supply configuration lines for those commands you
 want the backend to handle.
 Operations for which a command is not supplied will be refused with an
index 3c9ed2bc52eb6192b694abd87c5d3eedfde80700..9a22026da77d5778075ade89b820cb4fceac56e0 100644 (file)
@@ -204,6 +204,22 @@ disables Start TLS from forcing session to anonymous status (see also
 disables StartTLS if authenticated (see also
 .BR tls_2_anon ).
 .TP
+.B gentlehup { on | off }
+A SIGHUP signal will only cause a 'gentle' shutdown-attempt:
+.B Slapd
+will stop listening for new connections, but will not close the
+connections to the current clients.  It terminates when all clients
+have closed their connections (if they ever do), or \- as before \-
+if it receives a SIGTERM signal.  This can be useful if you wish to
+terminate the server and start a new
+.B slapd
+server
+.B with another database,
+without disrupting the currently active clients.
+The default is off.  You may wish to use
+.B idletimeout
+along with this option.
+.TP
 .B idletimeout <integer>
 Specify the number of seconds to wait before forcibly closing
 an idle client connection.  A idletimeout of 0 disables this
index 9925357b0c2065a50d6764155424bd0f5b47eea2..76c2799236133b46dc3e2dcc760936d29b8e37cf 100644 (file)
@@ -413,9 +413,8 @@ ldap_create_control(
        LDAPControl *ctrl;
        struct berval *bvalp;
 
-       if ( requestOID == NULL || ctrlp == NULL ) {
-               return LDAP_PARAM_ERROR;
-       }
+       assert( requestOID != NULL );
+       assert( ctrlp != NULL );
 
        ctrl = (LDAPControl *) LDAP_MALLOC( sizeof(LDAPControl) );
        if ( ctrl == NULL ) {
diff --git a/libraries/libldap/dnssrv.c b/libraries/libldap/dnssrv.c
new file mode 100644 (file)
index 0000000..1a763c9
--- /dev/null
@@ -0,0 +1,304 @@
+/* $OpenLDAP$ */
+/*
+ * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+
+/*
+ * locate LDAP servers using DNS SRV records.
+ * Location code based on MIT Kerberos KDC location code.
+ */
+#include "portable.h"
+
+#include <stdio.h>
+
+#include <ac/stdlib.h>
+
+#include <ac/param.h>
+#include <ac/socket.h>
+#include <ac/string.h>
+#include <ac/time.h>
+
+#include "ldap-int.h"
+
+#ifdef HAVE_ARPA_NAMESER_H
+#include <arpa/nameser.h>
+#endif
+#ifdef HAVE_RESOLV_H
+#include <resolv.h>
+#endif
+
+/* Sometimes this is not defined. */
+#ifndef T_SRV
+#define T_SRV            33
+#endif                         /* T_SRV */
+
+int ldap_dn2domain(
+       LDAP_CONST char *dn_in,
+       char **domainp)
+{
+       int i;
+       char *domain = NULL;
+       char **dn;
+
+       if( dn_in == NULL || domainp == NULL ) {
+               return -1;
+       }
+
+       dn = ldap_explode_dn( dn_in, 0 );
+
+       if( dn == NULL ) {
+               return -2;
+       }
+
+       for( i=0; dn[i] != NULL; i++ ) {
+               char ** rdn = ldap_explode_rdn( dn[i], 0 );
+
+               if( rdn == NULL || *rdn == NULL ) {
+                       LDAP_FREE( rdn );
+                       LDAP_FREE( domain );
+                       LDAP_VFREE( dn );
+                       return -3;
+               }
+
+
+               if( rdn[1] == NULL ) {
+                       /*
+                        * single-valued RDN
+                        */
+                       char *dc;
+
+#define LDAP_DC "dc="
+#define LDAP_DCOID "0.9.2342.19200300.100.1.25="
+
+                       if( strncasecmp( rdn[0],
+                               LDAP_DC, sizeof(LDAP_DC)-1 ) == 0 )
+                       {
+                               dc = &rdn[0][sizeof(LDAP_DC)-1];
+
+                       } else if( strncmp( rdn[0],
+                               LDAP_DCOID, sizeof(LDAP_DCOID)-1 ) == 0 )
+                       {
+                               dc = &rdn[0][sizeof(LDAP_DCOID)-1];
+
+                       } else {
+                               dc = NULL;
+                       }
+
+                       if( dc != NULL ) {
+                               char *ndomain;
+
+                               if( *dc == '\0' ) {
+                                       /* dc value is empty! */
+                                       LDAP_FREE( rdn );
+                                       LDAP_FREE( domain );
+                                       LDAP_VFREE( dn );
+                                       LDAP_VFREE( rdn );
+                                       return -4;
+                               }
+
+                               ndomain = LDAP_REALLOC( domain,
+                                       ( domain == NULL ? 0 : strlen(domain) )
+                                       + strlen(dc) + sizeof(".") );
+
+                               if( ndomain == NULL ) {
+                                       LDAP_FREE( rdn );
+                                       LDAP_FREE( domain );
+                                       LDAP_VFREE( dn );
+                                       LDAP_VFREE( rdn );
+                                       return -5;
+                               }
+
+                               if( domain == NULL ) {
+                                       ndomain[0] = '\0';
+                               } else {
+                                       strcat( ndomain, "." );
+                               }
+
+                               strcat( ndomain, dc );
+
+                               domain = ndomain;
+                               continue;
+                       }
+               }
+
+               /*
+                * multi-valued RDN or fall thru
+                */
+
+               LDAP_VFREE( rdn );
+               LDAP_FREE( domain );
+               domain = NULL;
+       } 
+
+       if( domain != NULL &&  *domain == '\0' ) {
+               LDAP_FREE( domain );
+               domain = NULL;
+       }
+
+       *domainp = domain;
+       return 0;
+}
+
+int ldap_domain2dn(
+       LDAP_CONST char *domain_in,
+       char **dnp)
+{
+    char *domain, *s, *tok_r, *dn;
+    size_t loc;
+
+    if (domain_in == NULL || dnp == NULL) {
+       return LDAP_NO_MEMORY;
+    }
+    domain = LDAP_STRDUP(domain_in);
+    if (domain == NULL) {
+       return LDAP_NO_MEMORY;
+    }
+    dn = NULL;
+    loc = 0;
+
+    for (s = ldap_pvt_strtok(domain, ".", &tok_r);
+        s != NULL;
+        s = ldap_pvt_strtok(NULL, ".", &tok_r)) {
+       size_t len = strlen(s);
+
+       dn = (char *) LDAP_REALLOC(dn, loc + sizeof(",dc=") + len );
+       if (dn == NULL) {
+           LDAP_FREE(domain);
+           return LDAP_NO_MEMORY;
+       }
+       if (loc > 0) {
+           /* not first time. */
+           strcpy(dn + loc, ",");
+           loc++;
+       }
+       strcpy(dn + loc, "dc=");
+       loc += sizeof("dc=")-1;
+
+       strcpy(dn + loc, s);
+       loc += len;
+    }
+
+    LDAP_FREE(domain);
+
+    *dnp = dn;
+
+    return LDAP_SUCCESS;
+}
+
+/*
+ * Lookup and return LDAP servers for domain (using the DNS
+ * SRV record _ldap._tcp.domain).
+ */
+int ldap_domain2hostlist(
+       LDAP_CONST char *domain,
+       char **list )
+{
+#ifdef HAVE_RES_QUERY
+    char *request;
+    char *hostlist = NULL;
+    int rc, len, cur = 0;
+    unsigned char reply[1024];
+
+       assert( domain != NULL );
+       assert( list != NULL );
+
+       if( *domain == '\0' ) {
+               return LDAP_PARAM_ERROR;
+       }
+
+    request = LDAP_MALLOC(strlen(domain) + sizeof("_ldap._tcp."));
+    if (request == NULL) {
+               return LDAP_NO_MEMORY;
+    }
+    sprintf(request, "_ldap._tcp.%s", domain);
+
+#ifdef LDAP_R_COMPILE
+    ldap_pvt_thread_mutex_lock(&ldap_int_resolv_mutex);
+#endif
+
+    rc = LDAP_UNAVAILABLE;
+    len = res_query(request, C_IN, T_SRV, reply, sizeof(reply));
+    if (len >= 0) {
+       unsigned char *p;
+       char host[1024];
+       int status;
+       u_short port;
+       /* int priority, weight; */
+
+       /* Parse out query */
+       p = reply;
+       p += sizeof(HEADER);
+       status = dn_expand(reply, reply + len, p, host, sizeof(host));
+       if (status < 0) {
+           goto out;
+       }
+       p += status;
+       p += 4;
+
+       while (p < reply + len) {
+           int type, class, ttl, size;
+           status = dn_expand(reply, reply + len, p, host, sizeof(host));
+           if (status < 0) {
+               goto out;
+           }
+           p += status;
+           type = (p[0] << 8) | p[1];
+           p += 2;
+           class = (p[0] << 8) | p[1];
+           p += 2;
+           ttl = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
+           p += 4;
+           size = (p[0] << 8) | p[1];
+           p += 2;
+           if (type == T_SRV) {
+               int buflen;
+               status = dn_expand(reply, reply + len, p + 6, host, sizeof(host));
+               if (status < 0) {
+                   goto out;
+               }
+               /* ignore priority and weight for now */
+               /* priority = (p[0] << 8) | p[1]; */
+               /* weight = (p[2] << 8) | p[3]; */
+               port = (p[4] << 8) | p[5];
+
+               buflen = strlen(host) + sizeof(":65355");
+               hostlist = (char *) LDAP_REALLOC(hostlist, cur + buflen);
+               if (hostlist == NULL) {
+                   rc = LDAP_NO_MEMORY;
+                   goto out;
+               }
+               if (cur > 0) {
+                   /* not first time around */
+                   hostlist[cur++] = ' ';
+               }
+               cur += sprintf(&hostlist[cur], "%s:%hd", host, port);
+           }
+           p += size;
+       }
+    }
+    if (hostlist == NULL) {
+       /* No LDAP servers found in DNS. */
+       rc = LDAP_UNAVAILABLE;
+       goto out;
+    }
+
+    rc = LDAP_SUCCESS;
+       *list = hostlist;
+
+  out:
+#ifdef LDAP_R_COMPILE
+    ldap_pvt_thread_mutex_unlock(&ldap_int_resolv_mutex);
+#endif
+
+    if (request != NULL) {
+       LDAP_FREE(request);
+    }
+    if (rc != LDAP_SUCCESS && hostlist != NULL) {
+       LDAP_FREE(hostlist);
+    }
+    return rc;
+#else
+    return LDAP_NOT_SUPPORTED;
+#endif /* HAVE_RES_QUERY */
+}
index 8fc685b25f330ff17ba2a49e8c20590af7650334..3569887747de5e16b2c0d3ecf7f2d87736a1722f 100644 (file)
@@ -172,11 +172,6 @@ ldap_perror( LDAP *ld, LDAP_CONST char *str )
        assert( LDAP_VALID( ld ) );
        assert( str );
 
-       if ( ld == NULL ) {
-               fprintf( stderr, "ldap_perror: invalid session handle\n" );
-               return;
-       }
-
        e = ldap_int_error( ld->ld_errno );
 
        fprintf( stderr, "%s: %s (%d)\n",
@@ -257,10 +252,6 @@ ldap_parse_result(
        assert( LDAP_VALID( ld ) );
        assert( r != NULL );
 
-       if ( ld == NULL || r == NULL ) {
-               return LDAP_PARAM_ERROR;
-       }
-
        if(errcodep != NULL) *errcodep = LDAP_SUCCESS;
        if(matcheddnp != NULL) *matcheddnp = NULL;
        if(errmsgp != NULL) *errmsgp = NULL;
index 58bffe86205d41c491081e00c118669fbb5c5b73..74e31281ca592d0464906b10ea07ea706d1ebc60 100644 (file)
@@ -60,11 +60,6 @@ ldap_extended_operation(
                return( ld->ld_errno );
        }
 
-       if( reqoid == NULL || *reqoid == '\0' || msgidp == NULL ) {
-               ld->ld_errno = LDAP_PARAM_ERROR;
-               return( ld->ld_errno );
-       }
-
        /* create a message to send */
        if ( (ber = ldap_alloc_ber_with_options( ld )) == NULL ) {
                ld->ld_errno = LDAP_NO_MEMORY;
@@ -132,11 +127,6 @@ ldap_extended_operation_s(
        assert( reqoid != NULL || *reqoid == '\0' );
        assert( retoidp != NULL || retdatap != NULL );
 
-       if( retoidp == NULL || retdatap == NULL ) {
-               ld->ld_errno = LDAP_PARAM_ERROR;
-               return( ld->ld_errno );
-       }
-
     rc = ldap_extended_operation( ld, reqoid, reqdata,
                sctrls, cctrls, &msgid );
         
index bec27bc7da976d604480652f8fc4f733f99e5bb1..4dd2279ee5fd0ab31748b52fb4eca7e39aa5c5cf 100644 (file)
@@ -90,10 +90,9 @@ ldap_get_dn( LDAP *ld, LDAPMessage *entry )
        Debug( LDAP_DEBUG_TRACE, "ldap_get_dn\n", 0, 0, 0 );
 #endif
 
-       if ( entry == NULL ) {
-               ld->ld_errno = LDAP_PARAM_ERROR;
-               return( NULL );
-       }
+       assert( ld != NULL );
+       assert( LDAP_VALID(ld) );
+       assert( entry != NULL );
 
        tmp = *entry->lm_ber;   /* struct copy */
        if ( ber_scanf( &tmp, "{a" /*}*/, &dn ) == LBER_ERROR ) {
@@ -2878,7 +2877,7 @@ ldap_rdn2bv( LDAPRDN *rdn, struct berval *bv, unsigned flags )
                break;
 
        default:
-               return( LDAP_PARAM_ERROR );
+               return LDAP_PARAM_ERROR;
        }
 
        bv->bv_val = LDAP_MALLOC( l + 1 );
index f3f896e7b8675eed8abe012c6a4f80c5d95b868a..b75a4403f4e787efcffc57c15f2665bcaca5dd88 100644 (file)
+/* $OpenLDAP$ */
 /*
+ * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+/*  Portions
  *  Copyright (c) 1990 Regents of the University of Michigan.
  *  All rights reserved.
  *
  *  getentry.c
  */
 
-#ifndef lint 
-static char copyright[] = "@(#) Copyright (c) 1990 Regents of the University of Michigan.\nAll rights reserved.\n";
-#endif
+#include "portable.h"
 
 #include <stdio.h>
-#include <ctype.h>
-#include <string.h>
-#ifdef MACOS
-#include <stdlib.h>
-#include "macos.h"
-#else /* MACOS */
-#if defined( DOS ) || defined( _WIN32 )
-#include <malloc.h>
-#include "msdos.h"
-#else /* DOS */
-#include <sys/types.h>
-#include <sys/socket.h>
-#endif /* DOS */
-#endif /* MACOS */
-
-#include "lber.h"
-#include "ldap.h"
+#include <ac/stdlib.h>
+
+#include <ac/socket.h>
+#include <ac/string.h>
+#include <ac/time.h>
+
+#include "ldap-int.h"
 
 /* ARGSUSED */
 LDAPMessage *
 ldap_first_entry( LDAP *ld, LDAPMessage *chain )
 {
-       return( chain == NULLMSG || chain->lm_msgtype == LDAP_RES_SEARCH_RESULT
-           ? NULLMSG : chain );
+       assert( ld != NULL );
+       assert( LDAP_VALID( ld ) );
+       assert( chain != NULL );
+
+       if( ld == NULL || chain == NULL ) {
+               return NULL;
+       }
+
+       return chain->lm_msgtype == LDAP_RES_SEARCH_ENTRY
+               ? chain
+               : ldap_next_entry( ld, chain );
 }
 
-/* ARGSUSED */
-LDAPMessage *ldap_next_entry( LDAP *ld, LDAPMessage *entry )
+LDAPMessage *
+ldap_next_entry( LDAP *ld, LDAPMessage *entry )
 {
-       if ( entry == NULLMSG || entry->lm_chain == NULLMSG
-           || entry->lm_chain->lm_msgtype == LDAP_RES_SEARCH_RESULT )
-               return( NULLMSG );
+       assert( ld != NULL );
+       assert( LDAP_VALID( ld ) );
+       assert( entry != NULL );
 
-       return( entry->lm_chain );
+       if ( ld == NULL || entry == NULL ) {
+               return NULL;
+       }
+
+       for (
+               entry = entry->lm_chain;
+               entry != NULL;
+               entry = entry->lm_chain )
+       {
+               if( entry->lm_msgtype == LDAP_RES_SEARCH_ENTRY ) {
+                       return( entry );
+               }
+       }
+
+       return( NULL );
 }
 
-/* ARGSUSED */
 int
 ldap_count_entries( LDAP *ld, LDAPMessage *chain )
 {
        int     i;
 
-       for ( i = 0; chain != NULL && chain->lm_msgtype
-           != LDAP_RES_SEARCH_RESULT; chain = chain->lm_chain )
-               i++;
+       assert( ld != NULL );
+       assert( LDAP_VALID( ld ) );
+
+       if ( ld == NULL ) {
+               return -1;
+       }
+
+       for ( i = 0; chain != NULL; chain = chain->lm_chain ) {
+               if( chain->lm_msgtype == LDAP_RES_SEARCH_ENTRY ) {
+                       i++;
+               }
+       }
 
        return( i );
 }
+
+int
+ldap_get_entry_controls(
+       LDAP *ld,
+       LDAPMessage *entry, 
+       LDAPControl ***sctrls )
+{
+       int rc;
+       BerElement be;
+
+       assert( ld != NULL );
+       assert( LDAP_VALID( ld ) );
+       assert( entry != NULL );
+       assert( sctrls != NULL );
+
+       if ( entry->lm_msgtype != LDAP_RES_SEARCH_ENTRY ) {
+               return LDAP_PARAM_ERROR;
+       }
+
+       /* make a local copy of the BerElement */
+       AC_MEMCPY(&be, entry->lm_ber, sizeof(be));
+
+       if ( ber_scanf( &be, "{xx" /*}*/ ) == LBER_ERROR ) {
+               rc = LDAP_DECODING_ERROR;
+               goto cleanup_and_return;
+       }
+
+       rc = ldap_int_get_controls( &be, sctrls );
+
+cleanup_and_return:
+       if( rc != LDAP_SUCCESS ) {
+               ld->ld_errno = rc;
+
+               if( ld->ld_matched != NULL ) {
+                       LDAP_FREE( ld->ld_matched );
+                       ld->ld_matched = NULL;
+               }
+
+               if( ld->ld_error != NULL ) {
+                       LDAP_FREE( ld->ld_error );
+                       ld->ld_error = NULL;
+               }
+       }
+
+       return rc;
+}
diff --git a/libraries/libldap/references.c b/libraries/libldap/references.c
new file mode 100644 (file)
index 0000000..2aae3f4
--- /dev/null
@@ -0,0 +1,146 @@
+/* $OpenLDAP$ */
+/*
+ * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+/*
+ *  references.c
+ */
+
+#include "portable.h"
+
+#include <stdio.h>
+
+#include <ac/stdlib.h>
+
+#include <ac/socket.h>
+#include <ac/string.h>
+#include <ac/time.h>
+
+#include "ldap-int.h"
+
+LDAPMessage *
+ldap_first_reference( LDAP *ld, LDAPMessage *chain )
+{
+       assert( ld != NULL );
+       assert( LDAP_VALID( ld ) );
+       assert( chain !=  NULL );
+
+       return chain->lm_msgtype == LDAP_RES_SEARCH_REFERENCE
+               ? chain
+               : ldap_next_reference( ld, chain );
+}
+
+LDAPMessage *
+ldap_next_reference( LDAP *ld, LDAPMessage *ref )
+{
+       assert( ld != NULL );
+       assert( LDAP_VALID( ld ) );
+       assert( ref !=  NULL );
+
+       for (
+               ref = ref->lm_chain;
+               ref != NULL;
+               ref = ref->lm_chain )
+       {
+               if( ref->lm_msgtype == LDAP_RES_SEARCH_REFERENCE ) {
+                       return( ref );
+               }
+       }
+
+       return( NULL );
+}
+
+int
+ldap_count_references( LDAP *ld, LDAPMessage *chain )
+{
+       int     i;
+
+       assert( ld != NULL );
+       assert( LDAP_VALID( ld ) );
+       assert( chain !=  NULL );
+
+       if ( ld == NULL ) {
+               return -1;
+       }
+
+       
+       for ( i = 0; chain != NULL; chain = chain->lm_chain ) {
+               if( chain->lm_msgtype == LDAP_RES_SEARCH_REFERENCE ) {
+                       i++;
+               }
+       }
+
+       return( i );
+}
+
+int
+ldap_parse_reference( 
+       LDAP            *ld,    
+       LDAPMessage     *ref,
+       char            ***referralsp,
+       LDAPControl     ***serverctrls,
+       int             freeit)
+{
+       BerElement be;
+       char **refs = NULL;
+       int rc;
+
+       assert( ld != NULL );
+       assert( LDAP_VALID( ld ) );
+       assert( ref !=  NULL );
+
+       if( ref->lm_msgtype != LDAP_RES_SEARCH_REFERENCE ) {
+               return LDAP_PARAM_ERROR;
+       }
+
+       /* make a private copy of BerElement */
+       AC_MEMCPY(&be, ref->lm_ber, sizeof(be));
+       
+       if ( ber_scanf( &be, "{v" /*}*/, &refs ) == LBER_ERROR ) {
+               rc = LDAP_DECODING_ERROR;
+               goto free_and_return;
+       }
+
+       if ( serverctrls == NULL ) {
+               rc = LDAP_SUCCESS;
+               goto free_and_return;
+       }
+
+       if ( ber_scanf( &be, /*{*/ "}" ) == LBER_ERROR ) {
+               rc = LDAP_DECODING_ERROR;
+               goto free_and_return;
+       }
+
+       rc = ldap_int_get_controls( &be, serverctrls );
+
+free_and_return:
+
+       if( referralsp != NULL ) {
+               /* provide references regradless of return code */
+               *referralsp = refs;
+
+       } else {
+               LDAP_VFREE( refs );
+       }
+
+       if( freeit ) {
+               ldap_msgfree( ref );
+       }
+
+       if( rc != LDAP_SUCCESS ) {
+               ld->ld_errno = rc;
+
+               if( ld->ld_matched != NULL ) {
+                       LDAP_FREE( ld->ld_matched );
+                       ld->ld_matched = NULL;
+               }
+
+               if( ld->ld_error != NULL ) {
+                       LDAP_FREE( ld->ld_error );
+                       ld->ld_error = NULL;
+               }
+       }
+
+       return rc;
+}
index f409afcc9ebedccb2e94b91edbe2e76f62bcfb5e..a1ee317cf6d31e78de76eb77fbcf554ba7674300 100644 (file)
@@ -103,15 +103,6 @@ ldap_result(
        Debug( LDAP_DEBUG_TRACE, "ldap_result msgid %d\n", msgid, 0, 0 );
 #endif
 
-       if( ld == NULL ) {
-               return -1;
-       }
-
-       if( result == NULL ) {
-               ld->ld_errno = LDAP_PARAM_ERROR;
-               return -1;
-       }
-
     lm = chkResponseList(ld, msgid, all);
 
        if ( lm == NULL ) {
index 93a52472f8e41630b0b8f01847e36cae27f9a7a9..0164bc962fc02d9ee660f12aa032dceb39d73cbc 100644 (file)
@@ -75,11 +75,6 @@ ldap_sasl_bind(
        rc = ldap_int_client_controls( ld, cctrls );
        if( rc != LDAP_SUCCESS ) return rc;
 
-       if( msgidp == NULL ) {
-               ld->ld_errno = LDAP_PARAM_ERROR;
-               return ld->ld_errno;
-       }
-
        if( mechanism == LDAP_SASL_SIMPLE ) {
                if( dn == NULL && cred != NULL ) {
                        /* use default binddn */
@@ -269,10 +264,6 @@ ldap_parse_sasl_bind_result(
        assert( LDAP_VALID( ld ) );
        assert( res != NULL );
 
-       if ( ld == NULL || res == NULL ) {
-               return LDAP_PARAM_ERROR;
-       }
-
        if( servercredp != NULL ) {
                if( ld->ld_version < LDAP_VERSION2 ) {
                        return LDAP_NOT_SUPPORTED;
index ee5d549c895f9d459d99b1febd98553aa37a45f7..84557eb33a8d248d0ddbbdf884da9494c14c3d1d 100644 (file)
@@ -1,4 +1,9 @@
+/* $OpenLDAP$ */
 /*
+ * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+/* Portions
  * Copyright (c) 1994 Regents of the University of Michigan.
  * All rights reserved.
  *
  * sort.c:  LDAP library entry and value sort routines
  */
 
+#include "portable.h"
+
 #include <stdio.h>
-#include <ctype.h>
-#include <string.h>
-#include <stdlib.h>
-#ifdef MACOS
-#include "macos.h"
-#else /* MACOS */
-#ifdef DOS
-#include <malloc.h>
-#include "msdos.h"
-#endif /* DOS */
-#endif /* MACOS */
-
-#include "lber.h"
-#include "ldap.h"
+#include <ac/stdlib.h>
+
+#include <ac/ctype.h>
+#include <ac/string.h>
+#include <ac/time.h>
+
+
+#include "ldap-int.h"
 
 struct entrything {
        char            **et_vals;
        LDAPMessage     *et_msg;
+       int             (*et_cmp_fn) LDAP_P((const char *a, const char *b));
 };
 
-#ifndef NEEDPROTOS
-static int     (*et_cmp_fn)();
-static int     et_cmp();
-#else /* !NEEDPROTOS */
-static int     (*et_cmp_fn)( char *a, char *b );
-static int     et_cmp( void *aa, void *bb);
-#endif /* !NEEDPROTOS */
+static int     et_cmp LDAP_P(( const void *aa, const void *bb));
+
 
 int
 ldap_sort_strcasecmp(
-    char       **a,
-    char       **b
+       LDAP_CONST void *a,
+       LDAP_CONST void *b
 )
 {
-       return( strcasecmp( *a, *b ) );
+       return( strcasecmp( *(char *const *)a, *(char *const *)b ) );
 }
 
 static int
 et_cmp(
-       void    *aa,
-       void    *bb
+       const void      *aa,
+       const void      *bb
 )
 {
        int                     i, rc;
-       struct entrything       *a = (struct entrything *)aa;
-       struct entrything       *b = (struct entrything *)bb;
+       const struct entrything *a = (const struct entrything *)aa;
+       const struct entrything *b = (const struct entrything *)bb;
 
        if ( a->et_vals == NULL && b->et_vals == NULL )
                return( 0 );
@@ -68,8 +65,7 @@ et_cmp(
                return( 1 );
 
        for ( i = 0; a->et_vals[i] && b->et_vals[i]; i++ ) {
-               if ( (rc = (*et_cmp_fn)( a->et_vals[i], b->et_vals[i] ))
-                   != 0 ) {
+               if ( (rc = a->et_cmp_fn( a->et_vals[i], b->et_vals[i] )) != 0 ) {
                        return( rc );
                }
        }
@@ -85,8 +81,8 @@ int
 ldap_sort_entries(
     LDAP       *ld,
     LDAPMessage        **chain,
-    char       *attr,          /* NULL => sort by DN */
-    int                (*cmp)()
+    LDAP_CONST char    *attr,          /* NULL => sort by DN */
+    int                (*cmp) (LDAP_CONST  char *, LDAP_CONST char *)
 )
 {
        int                     i, count;
@@ -94,9 +90,19 @@ ldap_sort_entries(
        LDAPMessage             *e, *last;
        LDAPMessage             **ep;
 
+       assert( ld != NULL );
+
        count = ldap_count_entries( ld, *chain );
 
-       if ( (et = (struct entrything *) malloc( count *
+       if ( count < 0 ) {
+               return -1;
+
+       } else if ( count < 2 ) {
+               /* zero or one entries -- already sorted! */
+               return 0;
+       }
+
+       if ( (et = (struct entrything *) LDAP_MALLOC( count *
            sizeof(struct entrything) )) == NULL ) {
                ld->ld_errno = LDAP_NO_MEMORY;
                return( -1 );
@@ -104,13 +110,14 @@ ldap_sort_entries(
 
        e = *chain;
        for ( i = 0; i < count; i++ ) {
+               et[i].et_cmp_fn = cmp;
                et[i].et_msg = e;
                if ( attr == NULL ) {
                        char    *dn;
 
                        dn = ldap_get_dn( ld, e );
                        et[i].et_vals = ldap_explode_dn( dn, 1 );
-                       free( dn );
+                       LDAP_FREE( dn );
                } else {
                        et[i].et_vals = ldap_get_values( ld, e, attr );
                }
@@ -119,18 +126,17 @@ ldap_sort_entries(
        }
        last = e;
 
-       et_cmp_fn = cmp;
-       qsort( et, count, sizeof(struct entrything), (void *) et_cmp );
+       qsort( et, count, sizeof(struct entrything), et_cmp );
 
        ep = chain;
        for ( i = 0; i < count; i++ ) {
                *ep = et[i].et_msg;
                ep = &(*ep)->lm_chain;
 
-               ldap_value_free( et[i].et_vals );
+               LDAP_VFREE( et[i].et_vals );
        }
        *ep = last;
-       free( (char *) et );
+       LDAP_FREE( (char *) et );
 
        return( 0 );
 }
@@ -139,7 +145,7 @@ int
 ldap_sort_values(
     LDAP       *ld,
     char       **vals,
-    int                (*cmp)()
+    int                (*cmp) (LDAP_CONST void *, LDAP_CONST void *)
 )
 {
        int     nel;
diff --git a/libraries/libldap/sortctrl.c b/libraries/libldap/sortctrl.c
new file mode 100644 (file)
index 0000000..f215a83
--- /dev/null
@@ -0,0 +1,466 @@
+/*
+ * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+/* Adapted for inclusion into OpenLDAP by Kurt D. Zeilenga */
+/*---
+ * Copyright (C) 1999, 2000 Novell, Inc. All Rights Reserved.
+ *
+ * THIS WORK IS SUBJECT TO U.S. AND INTERNATIONAL COPYRIGHT LAWS AND
+ * TREATIES. USE, MODIFICATION, AND REDISTRIBUTION OF THIS WORK IS SUBJECT
+ * TO VERSION 2.0.1 OF THE OPENLDAP PUBLIC LICENSE, A COPY OF WHICH IS
+ * AVAILABLE AT HTTP://WWW.OPENLDAP.ORG/LICENSE.HTML OR IN THE FILE "LICENSE"
+ * IN THE TOP-LEVEL DIRECTORY OF THE DISTRIBUTION. ANY USE OR EXPLOITATION
+ * OF THIS WORK OTHER THAN AS AUTHORIZED IN VERSION 2.0.1 OF THE OPENLDAP
+ * PUBLIC LICENSE, OR OTHER PRIOR WRITTEN CONSENT FROM NOVELL, COULD SUBJECT
+ * THE PERPETRATOR TO CRIMINAL AND CIVIL LIABILITY.
+ *
+ *---*/
+
+#include "portable.h"
+
+#include <stdio.h>
+#include <ac/stdlib.h>
+#include <ac/string.h>
+#include <ac/time.h>
+
+#include "ldap-int.h"
+
+#define LDAP_MATCHRULE_IDENTIFIER      0x80L
+#define LDAP_REVERSEORDER_IDENTIFIER   0x81L
+#define LDAP_ATTRTYPES_IDENTIFIER      0x80L
+
+
+
+/* ---------------------------------------------------------------------------
+   countKeys
+   
+   Internal function to determine the number of keys in the string.
+   
+   keyString  (IN) String of items separated by whitespace.
+   ---------------------------------------------------------------------------*/
+
+static int countKeys(char *keyString)
+{
+       char *p = keyString;
+       int count = 0;
+
+       for (;;)
+       {
+               while (LDAP_SPACE(*p))           /* Skip leading whitespace */
+                       p++;
+
+               if (*p == '\0')                 /* End of string? */
+                       return count;
+
+               count++;                                /* Found start of a key */
+
+               while (!LDAP_SPACE(*p)) /* Skip till next space or end of string. */
+                       if (*p++ == '\0')
+                               return count;
+       }
+}
+
+
+/* ---------------------------------------------------------------------------
+   readNextKey
+   
+   Internal function to parse the next sort key in the string.
+   Allocate an LDAPSortKey structure and initialize it with
+   attribute name, reverse flag, and matching rule OID.
+
+   Each sort key in the string has the format:
+         [whitespace][-]attribute[:[OID]]
+
+   pNextKey    (IN/OUT) Points to the next key in the sortkey string to parse.
+                                               The pointer is updated to point to the next character
+                                               after the sortkey being parsed.
+                                               
+   key         (OUT)    Points to the address of an LDAPSortKey stucture
+                                               which has been allocated by this routine and
+                                               initialized with information from the next sortkey.                        
+   ---------------------------------------------------------------------------*/
+
+static int readNextKey( char **pNextKey, LDAPSortKey **key)
+{
+       char *p = *pNextKey;
+       int rev = 0;
+       char *attrStart;
+       int attrLen;
+       char *oidStart = NULL;
+       int oidLen = 0;
+
+       /* Skip leading white space. */
+       while (LDAP_SPACE(*p))
+               p++;
+
+       if (*p == '-')           /* Check if the reverse flag is present. */
+       {
+               rev=1;
+               p++;
+       }
+
+       /* We're now positioned at the start of the attribute. */
+       attrStart = p;
+
+       /* Get the length of the attribute until the next whitespace or ":". */
+       attrLen = strcspn(p, " \t:");
+       p += attrLen;
+
+       if (attrLen == 0)        /* If no attribute name was present, quit. */
+               return LDAP_PARAM_ERROR;
+
+       if (*p == ':')
+       {
+               oidStart = ++p;                          /* Start of the OID, after the colon */
+               oidLen = strcspn(p, " \t");      /* Get length of OID till next whitespace */
+               p += oidLen;
+       }
+
+       *pNextKey = p;           /* Update argument to point to next key */
+
+       /* Allocate an LDAPSortKey structure */
+       *key = LDAP_MALLOC(sizeof(LDAPSortKey));
+       if (*key == NULL) return LDAP_NO_MEMORY;
+
+       /* Allocate memory for the attribute and copy to it. */
+       (*key)->attributeType = LDAP_MALLOC(attrLen+1);
+       if ((*key)->attributeType == NULL) {
+               LDAP_FREE(*key);
+               return LDAP_NO_MEMORY;
+       }
+
+       strncpy((*key)->attributeType, attrStart, attrLen);
+       (*key)->attributeType[attrLen] = 0;
+
+       /* If present, allocate memory for the OID and copy to it. */
+       if (oidLen) {
+               (*key)->orderingRule = LDAP_MALLOC(oidLen+1);
+               if ((*key)->orderingRule == NULL) {
+                       LDAP_FREE((*key)->attributeType);
+                       LDAP_FREE(*key);
+                       return LDAP_NO_MEMORY;
+               }
+               strncpy((*key)->orderingRule, oidStart, oidLen);
+               (*key)->orderingRule[oidLen] = 0;
+
+       } else {
+               (*key)->orderingRule = NULL;
+       }
+
+       (*key)->reverseOrder = rev;
+
+       return LDAP_SUCCESS;
+}
+
+
+/* ---------------------------------------------------------------------------
+   ldap_create_sort_keylist
+   
+   Create an array of pointers to LDAPSortKey structures, containing the
+   information specified by the string representation of one or more
+   sort keys.
+   
+   sortKeyList    (OUT) Points to a null-terminated array of pointers to
+                                               LDAPSortKey structures allocated by this routine.
+                                               This memory SHOULD be freed by the calling program
+                                               using ldap_free_sort_keylist().
+                                               
+   keyString      (IN)  Points to a string of one or more sort keys.                      
+   
+   ---------------------------------------------------------------------------*/
+
+int
+ldap_create_sort_keylist ( LDAPSortKey ***sortKeyList, char *keyString )
+{
+       int         numKeys, rc, i;
+       char        *nextKey;
+       LDAPSortKey **keyList = NULL;
+
+       assert( sortKeyList != NULL );
+       assert( keyString != NULL );
+
+       *sortKeyList = NULL;
+
+       /* Determine the number of sort keys so we can allocate memory. */
+       if (( numKeys = countKeys(keyString)) == 0) {
+               return LDAP_PARAM_ERROR;
+       }
+
+       /* Allocate the array of pointers.  Initialize to NULL. */
+       keyList=(LDAPSortKey**)LBER_CALLOC(numKeys+1, sizeof(LDAPSortKey*));
+       if ( keyList == NULL) return LDAP_NO_MEMORY;
+
+       /* For each sort key in the string, create an LDAPSortKey structure
+          and add it to the list.
+       */
+       nextKey = keyString;              /* Points to the next key in the string */
+       for (i=0; i < numKeys; i++) {
+               rc = readNextKey(&nextKey, &keyList[i]);
+
+               if (rc != LDAP_SUCCESS) {
+                       ldap_free_sort_keylist(keyList);
+                       return rc;
+               }
+       }
+
+       *sortKeyList = keyList;
+       return LDAP_SUCCESS;
+}
+
+
+/* ---------------------------------------------------------------------------
+   ldap_free_sort_keylist
+   
+   Frees the sort key structures created by ldap_create_sort_keylist().
+   Frees the memory referenced by the LDAPSortKey structures,
+   the LDAPSortKey structures themselves, and the array of pointers
+   to the structures.
+   
+   keyList     (IN) Points to an array of pointers to LDAPSortKey structures.
+   ---------------------------------------------------------------------------*/
+
+void
+ldap_free_sort_keylist ( LDAPSortKey **keyList )
+{
+       int i;
+       LDAPSortKey *nextKeyp;
+
+       if (keyList == NULL) return;
+
+       i=0;
+       while ( 0 != (nextKeyp = keyList[i++]) ) {
+               if (nextKeyp->attributeType) {
+                       LBER_FREE(nextKeyp->attributeType);
+               }
+
+               if (nextKeyp->orderingRule != NULL) {
+                       LBER_FREE(nextKeyp->orderingRule);
+               }
+
+               LBER_FREE(nextKeyp);
+       }
+
+       LBER_FREE(keyList);
+}
+
+
+/* ---------------------------------------------------------------------------
+   ldap_create_sort_control
+   
+   Create and encode the server-side sort control.
+   
+   ld          (IN) An LDAP session handle, as obtained from a call to
+                                       ldap_init().
+
+   keyList     (IN) Points to a null-terminated array of pointers to
+                                       LDAPSortKey structures, containing a description of
+                                       each of the sort keys to be used.  The description
+                                       consists of an attribute name, ascending/descending flag,
+                                       and an optional matching rule (OID) to use.
+                          
+   isCritical  (IN) 0 - Indicates the control is not critical to the operation.
+                                       non-zero - The control is critical to the operation.
+                                        
+   ctrlp      (OUT) Returns a pointer to the LDAPControl created.  This control
+                                       SHOULD be freed by calling ldap_control_free() when done.
+   
+   
+   Ber encoding
+   
+   SortKeyList ::= SEQUENCE OF SEQUENCE {
+                  attributeType   AttributeDescription,
+                  orderingRule    [0] MatchingRuleId OPTIONAL,
+                  reverseOrder    [1] BOOLEAN DEFAULT FALSE }
+   
+   ---------------------------------------------------------------------------*/
+
+int
+ldap_create_sort_control (
+       LDAP *ld,
+       LDAPSortKey **keyList,
+       int isCritical,
+       LDAPControl **ctrlp )
+{
+       int         i;
+       BerElement  *ber;
+       ber_tag_t tag;
+
+
+       if ( (ld == NULL) || (keyList == NULL) || (ctrlp == NULL) ) {
+               ld->ld_errno = LDAP_PARAM_ERROR;
+               return(ld->ld_errno);
+       }
+
+       if ((ber = ldap_alloc_ber_with_options(ld)) == NULL) {
+               ld->ld_errno = LDAP_NO_MEMORY;
+               return( ld->ld_errno );
+       }
+
+       tag = ber_printf(ber, "{" /*}*/);
+       if (tag == LBER_ERROR) goto exit;
+
+       for (i = 0; keyList[i] != NULL; i++) {
+               tag = ber_printf(ber, "{s" /*}*/, (keyList[i])->attributeType);
+               if (tag == LBER_ERROR) goto exit;
+
+               if ((keyList[i])->orderingRule != NULL) {
+                       tag = ber_printf( ber, "ts",
+                               LDAP_MATCHRULE_IDENTIFIER,
+                               (keyList[i])->orderingRule );
+
+                       if( tag == LBER_ERROR ) goto exit;
+               }
+
+               if ((keyList[i])->reverseOrder) {
+                       tag = ber_printf(ber, "tb",
+                               LDAP_REVERSEORDER_IDENTIFIER,
+                               (keyList[i])->reverseOrder );
+
+                       if( tag == LBER_ERROR ) goto exit;
+               }
+
+               tag = ber_printf(ber, /*{*/ "N}");
+               if( tag == LBER_ERROR ) goto exit;
+       }
+
+       tag = ber_printf(ber, /*{*/ "N}");
+       if( tag == LBER_ERROR ) goto exit;
+
+       ld->ld_errno = ldap_create_control( LDAP_CONTROL_SORTREQUEST,
+               ber, isCritical, ctrlp);
+
+       ber_free(ber, 1);
+
+       return(ld->ld_errno);
+
+exit:
+       ber_free(ber, 1);
+       ld->ld_errno =  LDAP_ENCODING_ERROR;
+       return(ld->ld_errno);
+}
+
+
+/* ---------------------------------------------------------------------------
+   ldap_parse_sort_control
+   
+   Decode the server-side sort control return information.
+
+   ld          (IN) An LDAP session handle, as obtained from a call to
+                                       ldap_init().
+
+   ctrls       (IN) The address of a NULL-terminated array of LDAPControl
+                                       structures, typically obtained by a call to
+                                       ldap_parse_result().
+                                 
+   returnCode (OUT) This result parameter is filled in with the sort control
+                                       result code.  This parameter MUST not be NULL.
+                                 
+   attribute  (OUT) If an error occured the server may return a string
+                                       indicating the first attribute in the sortkey list
+                                       that was in error.  If a string is returned, the memory
+                                       should be freed with ldap_memfree.  If this parameter is
+                                       NULL, no string is returned.
+   
+                          
+   Ber encoding for sort control
+        
+        SortResult ::= SEQUENCE {
+               sortResult  ENUMERATED {
+                       success                   (0), -- results are sorted
+                       operationsError           (1), -- server internal failure
+                       timeLimitExceeded         (3), -- timelimit reached before
+                                                                                  -- sorting was completed
+                       strongAuthRequired        (8), -- refused to return sorted
+                                                                                  -- results via insecure
+                                                                                  -- protocol
+                       adminLimitExceeded       (11), -- too many matching entries
+                                                                                  -- for the server to sort
+                       noSuchAttribute          (16), -- unrecognized attribute
+                                                                                  -- type in sort key
+                       inappropriateMatching    (18), -- unrecognized or inappro-
+                                                                                  -- priate matching rule in
+                                                                                  -- sort key
+                       insufficientAccessRights (50), -- refused to return sorted
+                                                                                  -- results to this client
+                       busy                     (51), -- too busy to process
+                       unwillingToPerform       (53), -- unable to sort
+                       other                    (80)
+                       },
+         attributeType [0] AttributeDescription OPTIONAL }
+   ---------------------------------------------------------------------------*/
+
+int
+ldap_parse_sort_control(
+       LDAP           *ld,
+       LDAPControl    **ctrls,
+       unsigned long  *returnCode,
+       char           **attribute )
+{
+       BerElement *ber;
+       LDAPControl *pControl;
+       int i;
+       ber_tag_t tag, berTag;
+       ber_len_t berLen;
+
+       if (ld == NULL) {
+               ld->ld_errno = LDAP_PARAM_ERROR;
+               return(ld->ld_errno);
+       }
+
+       if (ctrls == NULL) {
+               ld->ld_errno =  LDAP_CONTROL_NOT_FOUND;
+               return(ld->ld_errno);
+       }
+
+       if (attribute) {
+               *attribute = NULL;
+       }
+
+       /* Search the list of control responses for a sort control. */
+       for (i=0; ctrls[i]; i++) {
+               pControl = ctrls[i];
+               if (!strcmp(LDAP_CONTROL_SORTRESPONSE, pControl->ldctl_oid))
+                       goto foundSortControl;
+       }
+
+       /* No sort control was found. */
+       ld->ld_errno = LDAP_CONTROL_NOT_FOUND;
+       return(ld->ld_errno);
+
+foundSortControl:
+       /* Create a BerElement from the berval returned in the control. */
+       ber = ber_init(&pControl->ldctl_value);
+
+       if (ber == NULL) {
+               ld->ld_errno = LDAP_NO_MEMORY;
+               return(ld->ld_errno);
+       }
+
+       /* Extract the result code from the control. */
+       tag = ber_scanf(ber, "{e" /*}*/, returnCode);
+
+       if( tag == LBER_ERROR ) {
+               ber_free(ber, 1);
+               ld->ld_errno = LDAP_DECODING_ERROR;
+               return(ld->ld_errno);
+       }
+
+       /* If caller wants the attribute name, and if it's present in the control,
+          extract the attribute name which caused the error. */
+       if (attribute && (LDAP_ATTRTYPES_IDENTIFIER == ber_peek_tag(ber, &berLen)))
+       {
+               tag = ber_scanf(ber, "ta", &berTag, attribute);
+
+               if (tag == LBER_ERROR ) {
+                       ber_free(ber, 1);
+                       ld->ld_errno = LDAP_DECODING_ERROR;
+                       return(ld->ld_errno);
+               }
+       }
+
+       ber_free(ber,1);
+
+       ld->ld_errno = LDAP_SUCCESS;
+       return(ld->ld_errno);
+}
index 97059170b7d214db18b30fe4d1e417de65933ef9..e7985dae6b74079fc2314c8c9433fce455aab0fc 100644 (file)
@@ -886,10 +886,10 @@ ldap_url_parselist (LDAPURLDesc **ludlist, const char *url )
        LDAPURLDesc *ludp;
        char **urls;
 
-       *ludlist = NULL;
+       assert( ludlist != NULL );
+       assert( url != NULL );
 
-       if (url == NULL)
-               return LDAP_PARAM_ERROR;
+       *ludlist = NULL;
 
        urls = ldap_str2charray(url, ", ");
        if (urls == NULL)
@@ -923,10 +923,10 @@ ldap_url_parsehosts(
        LDAPURLDesc *ludp;
        char **specs, *p;
 
-       *ludlist = NULL;
+       assert( ludlist != NULL );
+       assert( hosts != NULL );
 
-       if (hosts == NULL)
-               return LDAP_PARAM_ERROR;
+       *ludlist = NULL;
 
        specs = ldap_str2charray(hosts, ", ");
        if (specs == NULL)
diff --git a/libraries/libldap/vlvctrl.c b/libraries/libldap/vlvctrl.c
new file mode 100644 (file)
index 0000000..0ee5ed2
--- /dev/null
@@ -0,0 +1,277 @@
+/*
+ * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+/* Adapted for inclusion into OpenLDAP by Kurt D. Zeilenga */
+/*---
+ * Copyright (C) 1999, 2000 Novell, Inc. All Rights Reserved.
+ *
+ * THIS WORK IS SUBJECT TO U.S. AND INTERNATIONAL COPYRIGHT LAWS AND
+ * TREATIES. USE, MODIFICATION, AND REDISTRIBUTION OF THIS WORK IS SUBJECT
+ * TO VERSION 2.0.1 OF THE OPENLDAP PUBLIC LICENSE, A COPY OF WHICH IS
+ * AVAILABLE AT HTTP://WWW.OPENLDAP.ORG/LICENSE.HTML OR IN THE FILE "LICENSE"
+ * IN THE TOP-LEVEL DIRECTORY OF THE DISTRIBUTION. ANY USE OR EXPLOITATION
+ * OF THIS WORK OTHER THAN AS AUTHORIZED IN VERSION 2.0.1 OF THE OPENLDAP
+ * PUBLIC LICENSE, OR OTHER PRIOR WRITTEN CONSENT FROM NOVELL, COULD SUBJECT
+ * THE PERPETRATOR TO CRIMINAL AND CIVIL LIABILITY.
+ *---*/
+
+#include "portable.h"
+
+#include <stdio.h>
+#include <ac/stdlib.h>
+#include <ac/string.h>
+#include <ac/time.h>
+
+#include "ldap-int.h"
+
+#define LDAP_VLVBYINDEX_IDENTIFIER     0xa0L
+#define LDAP_VLVBYVALUE_IDENTIFIER     0x81L
+#define LDAP_VLVCONTEXT_IDENTIFIER     0x04L
+
+
+/*---
+   ldap_create_vlv_control
+   
+   Create and encode the Virtual List View control.
+
+   ld        (IN)  An LDAP session handle, as obtained from a call to
+                                  ldap_init().
+   
+   vlvinfop  (IN)  The address of an LDAPVLVInfo structure whose contents 
+                                  are used to construct the value of the control
+                                  that is created.
+   
+   ctrlp     (OUT) A result parameter that will be assigned the address
+                                  of an LDAPControl structure that contains the 
+                                  VirtualListViewRequest control created by this function.
+                                  The memory occupied by the LDAPControl structure
+                                  SHOULD be freed when it is no longer in use by
+                                  calling ldap_control_free().
+                                         
+   
+   Ber encoding
+   
+   VirtualListViewRequest ::= SEQUENCE {
+               beforeCount  INTEGER (0 .. maxInt),
+               afterCount   INTEGER (0 .. maxInt),
+               CHOICE {
+                               byoffset [0] SEQUENCE, {
+                               offset        INTEGER (0 .. maxInt),
+                               contentCount  INTEGER (0 .. maxInt) }
+                               [1] greaterThanOrEqual assertionValue }
+               contextID     OCTET STRING OPTIONAL }
+         
+   
+   Note:  The first time the VLV control is created, the ldvlv_context
+                 field of the LDAPVLVInfo structure should be set to NULL.
+                 The context obtained from calling ldap_parse_vlv_control()
+                 should be used as the context in the next ldap_create_vlv_control
+                 call.
+
+ ---*/
+
+int
+ldap_create_vlv_control( LDAP *ld,
+                                                LDAPVLVInfo *vlvinfop,
+                                                LDAPControl **ctrlp )
+{
+       ber_tag_t tag;
+       BerElement *ber;
+
+       assert( ld != NULL );
+       assert( LDAP_VALID( ld ) );
+       assert( vlvinfop != NULL );
+       assert( ctrlp != NULL );
+
+       if ((ber = ldap_alloc_ber_with_options(ld)) == NULL) {
+               ld->ld_errno = LDAP_NO_MEMORY;
+               return(LDAP_NO_MEMORY);
+       }
+
+       tag = ber_printf(ber, "{ii" /*}*/,
+               vlvinfop->ldvlv_before_count,
+               vlvinfop->ldvlv_after_count);
+       if( tag == LBER_ERROR ) goto exit;
+
+       if (vlvinfop->ldvlv_attrvalue == NULL) {
+               tag = ber_printf(ber, "t{iiN}",
+                       LDAP_VLVBYINDEX_IDENTIFIER,
+                       vlvinfop->ldvlv_offset,
+                       vlvinfop->ldvlv_count);
+               if( tag == LBER_ERROR ) goto exit;
+
+       } else {
+               tag = ber_printf(ber, "tO",
+                       LDAP_VLVBYVALUE_IDENTIFIER,
+                       vlvinfop->ldvlv_attrvalue);
+               if( tag == LBER_ERROR ) goto exit;
+       }
+
+       if (vlvinfop->ldvlv_context) {
+               tag = ber_printf(ber, "tO",
+                       LDAP_VLVCONTEXT_IDENTIFIER,
+                       vlvinfop->ldvlv_context);
+               if( tag == LBER_ERROR ) goto exit;
+       }
+
+       tag = ber_printf(ber, /*{*/ "N}"); 
+       if( tag == LBER_ERROR ) goto exit;
+
+       ld->ld_errno = ldap_create_control(     LDAP_CONTROL_VLVREQUEST,
+               ber, 1, ctrlp);
+
+       ber_free(ber, 1);
+       return(ld->ld_errno);
+
+exit:
+       ber_free(ber, 1);
+       ld->ld_errno = LDAP_ENCODING_ERROR;
+       return(ld->ld_errno);
+}
+
+
+/*---
+   ldap_parse_vlv_control
+   
+   Decode the Virtual List View control return information.
+
+   ld           (IN)   An LDAP session handle.
+   
+   ctrls        (IN)   The address of a NULL-terminated array of 
+                                          LDAPControl structures, typically obtained 
+                                          by a call to ldap_parse_result().
+   
+   target_posp (OUT)  This result parameter is filled in with the list
+                                          index of the target entry.  If this parameter is
+                                          NULL, the target position is not returned.
+   
+   list_countp  (OUT)  This result parameter is filled in with the server's
+                                          estimate of the size of the list.  If this parameter
+                                          is NULL, the size is not returned.
+   
+   contextp     (OUT)  This result parameter is filled in with the address
+                                          of a struct berval that contains the server-
+                                          generated context identifier if one was returned by
+                                          the server.  If the server did not return a context
+                                          identifier, this parameter will be set to NULL, even
+                                          if an error occured.
+                                          The returned context SHOULD be used in the next call
+                                          to create a VLV sort control.  The struct berval
+                                          returned SHOULD be disposed of by calling ber_bvfree()
+                                          when it is no longer needed.  If NULL is passed for
+                                          contextp, the context identifier is not returned.
+   
+   errcodep     (OUT)  This result parameter is filled in with the VLV
+                                          result code.  If this parameter is NULL, the result
+                                          code is not returned.  
+   
+   
+   Ber encoding
+   
+   VirtualListViewResponse ::= SEQUENCE {
+               targetPosition    INTEGER (0 .. maxInt),
+               contentCount     INTEGER (0 .. maxInt),
+               virtualListViewResult ENUMERATED {
+               success (0),
+               operatonsError (1),
+               unwillingToPerform (53),
+               insufficientAccessRights (50),
+               busy (51),
+               timeLimitExceeded (3),
+               adminLimitExceeded (11),
+               sortControlMissing (60),
+               offsetRangeError (61),
+               other (80) },
+               contextID     OCTET STRING OPTIONAL }
+   
+---*/
+
+int
+ldap_parse_vlv_control(
+       LDAP           *ld,
+       LDAPControl    **ctrls,
+       unsigned long  *target_posp,
+       unsigned long  *list_countp,
+       struct berval  **contextp,
+       int            *errcodep )
+{
+       BerElement  *ber;
+       LDAPControl *pControl;
+       int i;
+       unsigned long pos, count, err;
+       ber_tag_t tag, berTag;
+       ber_len_t berLen;
+
+       assert( ld != NULL );
+       assert( LDAP_VALID( ld ) );
+
+       if (contextp) {
+               *contextp = NULL;        /* Make sure we return a NULL if error occurs. */
+       }
+
+       if (ctrls == NULL) {
+               ld->ld_errno = LDAP_CONTROL_NOT_FOUND;
+               return(ld->ld_errno);
+       }
+
+       /* Search the list of control responses for a VLV control. */
+       for (i=0; ctrls[i]; i++) {
+               pControl = ctrls[i];
+               if (!strcmp(LDAP_CONTROL_VLVRESPONSE, pControl->ldctl_oid))
+                       goto foundVLVControl;
+       }
+
+       /* No sort control was found. */
+       ld->ld_errno = LDAP_CONTROL_NOT_FOUND;
+       return(ld->ld_errno);
+
+foundVLVControl:
+       /* Create a BerElement from the berval returned in the control. */
+       ber = ber_init(&pControl->ldctl_value);
+
+       if (ber == NULL) {
+               ld->ld_errno = LDAP_NO_MEMORY;
+               return(ld->ld_errno);
+       }
+
+       /* Extract the data returned in the control. */
+       tag = ber_scanf(ber, "{iie" /*}*/, &pos, &count, &err);
+
+       if( tag == LBER_ERROR) {
+               ber_free(ber, 1);
+               ld->ld_errno = LDAP_DECODING_ERROR;
+               return(ld->ld_errno);
+       }
+
+
+       /* Since the context is the last item encoded, if caller doesn't want
+          it returned, don't decode it. */
+       if (contextp) {
+               if (LDAP_VLVCONTEXT_IDENTIFIER == ber_peek_tag(ber, &berLen)) {
+                       tag = ber_scanf(ber, "tO", &berTag, contextp);
+
+                       if( tag == LBER_ERROR) {
+                               ber_free(ber, 1);
+                               ld->ld_errno = LDAP_DECODING_ERROR;
+                               return(ld->ld_errno);
+                       }
+               }
+       }
+
+       ber_free(ber, 1);
+
+       /* Return data to the caller for items that were requested. */
+       if (target_posp) {
+               *target_posp = pos;
+       }
+       if (list_countp) {
+               *list_countp = count;
+       }
+       if (errcodep) {
+               *errcodep = err;
+       }
+
+       ld->ld_errno = LDAP_SUCCESS;
+       return(ld->ld_errno);
+}
index 923a1b9ce4e23c94e543c87b1e8fab17288e8744..d48a8e9370da48f0a852abc627dc43eb71fc7f96 100644 (file)
@@ -399,7 +399,11 @@ ldap_int_thread_pool_wrapper (
                ldap_pvt_thread_mutex_unlock(&pool->ltp_mutex);
 
                (ctx->ltc_start_routine)(ctx->ltc_arg);
+
+               ldap_pvt_thread_mutex_lock(&pool->ltp_mutex);
                LDAP_SLIST_INSERT_HEAD(&pool->ltp_free_list, ctx, ltc_next.l);
+               ldap_pvt_thread_mutex_unlock(&pool->ltp_mutex);
+
                ldap_pvt_thread_yield();
 
                /* if we use an idle timer, here's
index cd379c67246abdf878a57de454cef4123ba8aa20..74d3f3210ab8b875d5400428b230a376b47a061e 100644 (file)
@@ -36,21 +36,27 @@ int lutil_entropy( unsigned char *buf, ber_len_t nbytes )
        if( nbytes == 0 ) return 0;
 
 #ifdef URANDOM_DEVICE
+#define URANDOM_NREADS 4
        /* Linux and *BSD offer a urandom device */
        {
-               int rc, fd;
+               int rc, fd, n=0;
 
                fd = open( URANDOM_DEVICE, O_RDONLY );
 
                if( fd < 0 ) return -1;
 
-               rc = read( fd, buf, nbytes );
-               close(fd);
+               do {
+                       rc = read( fd, buf, nbytes );
+                       if( rc <= 0 ) break;
 
-               /* should return nbytes */
-               if( rc != nbytes ) return -1;
+                       buf+=rc;
+                       nbytes-=rc;
 
-               return 0;
+                       if( ++n >= URANDOM_NREADS ) break;
+               } while( nbytes > 0 );
+
+               close(fd);
+               return nbytes > 0 ? -1 : 0;
        }
 #elif PROV_RSA_FULL
        {
index 91015007b94ca9a67790bfedee2debd82fce4353..ef73fe7b454554212388a20266fccaf6486dbc6c 100644 (file)
@@ -235,7 +235,7 @@ at_insert(
                                 (AVL_DUP) avl_dup_error ) ) {
                        *err = sat->sat_oid;
                        ldap_memfree(air);
-                       return SLAP_SCHERR_DUP_ATTR;
+                       return SLAP_SCHERR_ATTR_DUP;
                }
                /* FIX: temporal consistency check */
                at_bvfind(&air->air_name);
@@ -253,7 +253,7 @@ at_insert(
                                         (AVL_DUP) avl_dup_error ) ) {
                                *err = *names;
                                ldap_memfree(air);
-                               return SLAP_SCHERR_DUP_ATTR;
+                               return SLAP_SCHERR_ATTR_DUP;
                        }
                        /* FIX: temporal consistency check */
                        at_bvfind(&air->air_name);
@@ -371,6 +371,11 @@ at_add(
                        /* subtypes must have same usage as their SUP */
                        return SLAP_SCHERR_ATTR_BAD_USAGE;
                }
+
+               if ( sat->sat_flags & SLAP_AT_FINAL ) {
+                       /* cannot subtype a "final" attribute type */
+                       return SLAP_SCHERR_ATTR_BAD_SUP;
+               }
        }
 
        /*
@@ -467,6 +472,9 @@ at_schema_info( Entry *e )
                if ( ldap_attributetype2bv( &at->sat_atype, vals ) == NULL ) {
                        return -1;
                }
+
+               if( at->sat_flags & SLAP_AT_HIDE ) continue;
+
 #if 0
                Debug( LDAP_DEBUG_TRACE, "Merging at [%ld] %s\n",
                       (long) vals[0].bv_len, vals[0].bv_val, 0 );
index 2dfb9be680593217a56ba282277498279f4fd17e..03f81b1687aa2675d3faa87f8f9577538e062331 100644 (file)
@@ -110,7 +110,6 @@ int ldbm_modify_internal(
 #endif
 
                        rc = modify_replace_values( e, mod, text, textbuf, textlen );
-                       assert( rc != LDAP_TYPE_OR_VALUE_EXISTS );
                        if( rc != LDAP_SUCCESS ) {
 #ifdef NEW_LOGGING
                                LDAP_LOG(( "backend", LDAP_LEVEL_INFO,
index cae990af5bd83f4bcfeb3cb6d949dbe6ebdf770a..3f0f6ed28d998aa9f2d8c0ad6e7d77c9763f3553 100644 (file)
@@ -38,24 +38,11 @@ shell_back_abandon(
                                break;
                        }
                }
-               if( pid == -1 ) {
-                       LDAP_STAILQ_FOREACH( o, &conn->c_pending_ops, o_next ) {
-                               if ( o->o_msgid == msgid ) {
-                                       pid = (pid_t) o->o_private;
-                                       break;
-                               }
-                       }
-               }
                ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
+       }
 
-               if ( pid != -1 ) {
-                       Debug( LDAP_DEBUG_ARGS, "shell killing pid %d\n",
-                              (int) pid, 0, 0 );
-                       kill( pid, SIGTERM );
-               } else {
-                       Debug( LDAP_DEBUG_ARGS, "shell could not find op %d\n",
-                           msgid, 0, 0 );
-               }
+       if ( pid == -1 ) {
+               Debug( LDAP_DEBUG_ARGS, "shell could not find op %d\n", msgid, 0, 0 );
                return 0;
        }
 
@@ -65,10 +52,9 @@ shell_back_abandon(
 
        /* write out the request to the abandon process */
        fprintf( wfp, "ABANDON\n" );
-       fprintf( wfp, "opid: %ld/%ld\n", op->o_connid, (long) op->o_msgid );
        fprintf( wfp, "msgid: %d\n", msgid );
        print_suffixes( wfp, be );
-       fprintf( wfp, "abandonid: %ld/%d\n", op->o_connid, msgid );
+       fprintf( wfp, "pid: %ld\n", (long) pid );
        fclose( wfp );
 
        /* no result from abandon */
index 134416866b6cdeb547e72fd76b857708dfb3bb20..1d08c0c0887def0ccf79e7c07e10fd1396e39c3e 100644 (file)
@@ -41,7 +41,6 @@ shell_back_add(
 
        /* write out the request to the add process */
        fprintf( wfp, "ADD\n" );
-       fprintf( wfp, "opid: %ld/%ld\n", op->o_connid, (long) op->o_msgid );
        fprintf( wfp, "msgid: %ld\n", (long) op->o_msgid );
        print_suffixes( wfp, be );
        ldap_pvt_thread_mutex_lock( &entry2str_mutex );
index fe36059215e8317cc303aa4fcfa248a03a3bfcad..e41c06c1f2f46214810be2ff28391054595f1368 100644 (file)
@@ -46,7 +46,6 @@ shell_back_bind(
 
        /* write out the request to the bind process */
        fprintf( wfp, "BIND\n" );
-       fprintf( wfp, "opid: %ld/%ld\n", op->o_connid, (long) op->o_msgid );
        fprintf( wfp, "msgid: %ld\n", (long) op->o_msgid );
        print_suffixes( wfp, be );
        fprintf( wfp, "dn: %s\n", dn->bv_val );
index b5ef2d24eb83fe2719344162f97d7aa1cc4e9c32..4b19e8f37488df695178bf7d78306d867abafd4b 100644 (file)
@@ -48,7 +48,6 @@ shell_back_compare(
 
        /* write out the request to the compare process */
        fprintf( wfp, "COMPARE\n" );
-       fprintf( wfp, "opid: %ld/%ld\n", op->o_connid, (long) op->o_msgid );
        fprintf( wfp, "msgid: %ld\n", (long) op->o_msgid );
        print_suffixes( wfp, be );
        fprintf( wfp, "dn: %s\n", dn->bv_val );
index e675f8062e0110289ca75bd66aed1d2f344433d6..6d3b27908d6437ee9996729887d0e747a2b7ba13 100644 (file)
@@ -42,7 +42,6 @@ shell_back_delete(
 
        /* write out the request to the delete process */
        fprintf( wfp, "DELETE\n" );
-       fprintf( wfp, "opid: %ld/%ld\n", op->o_connid, (long) op->o_msgid );
        fprintf( wfp, "msgid: %ld\n", (long) op->o_msgid );
        print_suffixes( wfp, be );
        fprintf( wfp, "dn: %s\n", dn->bv_val );
index 5acddbe994d9173753832b8d301e2905045d048f..0b1719eddd971602a0a176135db8bc3e28862927 100644 (file)
@@ -45,7 +45,6 @@ shell_back_modify(
 
        /* write out the request to the modify process */
        fprintf( wfp, "MODIFY\n" );
-       fprintf( wfp, "opid: %ld/%ld\n", op->o_connid, (long) op->o_msgid );
        fprintf( wfp, "msgid: %ld\n", (long) op->o_msgid );
        print_suffixes( wfp, be );
        fprintf( wfp, "dn: %s\n", dn->bv_val );
index e2c7d64d5f046b7c921c30179a57b5f38915e3a4..68bfed97957e5ef9f7c0c57db5c20fff13905d95 100644 (file)
@@ -60,7 +60,6 @@ shell_back_modrdn(
 
        /* write out the request to the modrdn process */
        fprintf( wfp, "MODRDN\n" );
-       fprintf( wfp, "opid: %ld/%ld\n", op->o_connid, (long) op->o_msgid );
        fprintf( wfp, "msgid: %ld\n", (long) op->o_msgid );
        print_suffixes( wfp, be );
        fprintf( wfp, "dn: %s\n", dn->bv_val );
index a1579e20e215e31c5291f1528a96efc7c19a504e..c8c1118172449f9ccc9bb587bdcc6410817087a8 100644 (file)
@@ -51,7 +51,6 @@ shell_back_search(
 
        /* write out the request to the search process */
        fprintf( wfp, "SEARCH\n" );
-       fprintf( wfp, "opid: %ld/%ld\n", op->o_connid, (long) op->o_msgid );
        fprintf( wfp, "msgid: %ld\n", (long) op->o_msgid );
        print_suffixes( wfp, be );
        fprintf( wfp, "base: %s\n", base->bv_val );
index a4327f99e2066b2f73b64e6817528140de3aa30e..e54173d7bac16a4f4211c3be7e118dce9967970a 100644 (file)
@@ -36,7 +36,6 @@ shell_back_unbind(
 
        /* write out the request to the unbind process */
        fprintf( wfp, "UNBIND\n" );
-       fprintf( wfp, "opid: %ld/%ld\n", op->o_connid, (long) op->o_msgid );
        fprintf( wfp, "msgid: %ld\n", (long) op->o_msgid );
        print_suffixes( wfp, be );
        fprintf( wfp, "dn: %s\n", (conn->c_dn.bv_len ? conn->c_dn.bv_val : "") );
index 23a4599f06db5cd63229b62a8b70530d4ba89b56..d89f9cb21b395cc0b5b23678346ec0156a04ab83 100644 (file)
@@ -11,6 +11,7 @@
 
 #include <ac/string.h>
 #include <ac/ctype.h>
+#include <ac/signal.h>
 #include <ac/socket.h>
 #include <ac/errno.h>
 
@@ -40,6 +41,7 @@ slap_mask_t           global_disallows = 0;
 slap_mask_t            global_requires = 0;
 slap_ssf_set_t global_ssf_set;
 char           *replogfile;
+int            global_gentlehup = 0;
 int            global_idletimeout = 0;
 char   *global_host = NULL;
 char   *global_realm = NULL;
@@ -1651,7 +1653,6 @@ read_config( const char *fname )
                                       "%s: line %d: old objectclass format not supported.\n",
                                       fname, lineno, 0 );
 #endif
-
                        }
 
                /* specify an attribute type */
@@ -2039,6 +2040,22 @@ read_config( const char *fname )
                                }
                        }
 
+#ifdef SIGHUP
+               /* turn on/off gentle SIGHUP handling */
+               } else if ( strcasecmp( cargv[0], "gentlehup" ) == 0 ) {
+                       if ( cargc < 2 ) {
+                               Debug( LDAP_DEBUG_ANY,
+    "%s: line %d: missing on|off in \"gentlehup <on|off>\" line\n",
+                                   fname, lineno, 0 );
+                               return( 1 );
+                       }
+                       if ( strcasecmp( cargv[1], "off" ) == 0 ) {
+                               global_gentlehup = 0;
+                       } else {
+                               global_gentlehup = 1;
+                       }
+#endif
+
                /* set idle timeout value */
                } else if ( strcasecmp( cargv[0], "idletimeout" ) == 0 ) {
                        int i;
index 2ab0fa769ff440d01a274ad3dab7c4eb701dc4e1..3dc4cdbcf1baff1e096801430229fbf0868d2233 100644 (file)
@@ -55,12 +55,12 @@ do { if (w) tcp_write( wake_sds[1], "0", 1 ); } while(0)
 #ifndef HAVE_WINSOCK
 static
 #endif
-volatile sig_atomic_t slapd_shutdown = 0;
+volatile sig_atomic_t slapd_shutdown = 0, slapd_gentle_shutdown = 0;
 
 static struct slap_daemon {
        ldap_pvt_thread_mutex_t sd_mutex;
 
-       int sd_nactives;
+       ber_socket_t sd_nactives;
 
 #ifndef HAVE_WINSOCK
        /* In winsock, accept() returns values higher than dtblsize
@@ -192,6 +192,8 @@ static void slapd_add(ber_socket_t s) {
        }
 #endif
 
+       slap_daemon.sd_nactives++;
+
        FD_SET( s, &slap_daemon.sd_actives );
        FD_SET( s, &slap_daemon.sd_readers );
 
@@ -216,6 +218,8 @@ static void slapd_add(ber_socket_t s) {
 void slapd_remove(ber_socket_t s, int wake) {
        ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
 
+       slap_daemon.sd_nactives--;
+
 #ifdef NEW_LOGGING
        LDAP_LOG(( "connection", LDAP_LEVEL_DETAIL1,
                   "slapd_remove: removing %ld%s%s\n",
@@ -233,7 +237,7 @@ void slapd_remove(ber_socket_t s, int wake) {
        FD_CLR( s, &slap_daemon.sd_writers );
 
        ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
-       WAKE_LISTENER(wake);
+       WAKE_LISTENER(wake || slapd_gentle_shutdown < 0);
 }
 
 void slapd_clr_write(ber_socket_t s, int wake) {
@@ -980,6 +984,34 @@ slapd_daemon_destroy(void)
 }
 
 
+static void
+close_listeners(
+       int remove
+)
+{
+       int l;
+
+       for ( l = 0; slap_listeners[l] != NULL; l++ ) {
+               if ( remove )
+                       slapd_remove( slap_listeners[l]->sl_sd, 0 );
+               if ( slap_listeners[l]->sl_sd != AC_SOCKET_INVALID ) {
+#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_LOCAL */
+                       slapd_close( slap_listeners[l]->sl_sd );
+               }
+               if ( slap_listeners[l]->sl_url )
+                       free ( slap_listeners[l]->sl_url );
+               if ( slap_listeners[l]->sl_name )
+                       free ( slap_listeners[l]->sl_name );
+               free ( slap_listeners[l] );
+               slap_listeners[l] = NULL;
+       }
+}
+
+
 static void *
 slapd_daemon_task(
        void *ptr
@@ -1066,6 +1098,26 @@ slapd_daemon_task(
                        }
                }
 
+#ifdef SIGHUP
+               if( slapd_gentle_shutdown ) {
+                       ber_socket_t active;
+
+                       if( slapd_gentle_shutdown > 0 ) {
+                               Debug( LDAP_DEBUG_ANY, "slapd gentle shutdown\n", 0, 0, 0 );
+                               close_listeners( 1 );
+                               slapd_gentle_shutdown = -1;
+                       }
+
+                       ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
+                       active = slap_daemon.sd_nactives;
+                       ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
+                       if( active == 0 ) {
+                               slapd_shutdown = -1;
+                               break;
+                       }
+               }
+#endif
+
                FD_ZERO( &writefds );
                FD_ZERO( &readfds );
 
@@ -1716,21 +1768,8 @@ slapd_daemon_task(
 #endif
        }
 
-       for ( l = 0; slap_listeners[l] != NULL; l++ ) {
-               if ( slap_listeners[l]->sl_sd != AC_SOCKET_INVALID ) {
-#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_LOCAL */
-                       slapd_close( slap_listeners[l]->sl_sd );
-               }
-               if ( slap_listeners[l]->sl_url )
-                       free ( slap_listeners[l]->sl_url );
-               if ( slap_listeners[l]->sl_name )
-                       free ( slap_listeners[l]->sl_name );
-               free ( slap_listeners[l] );
-       }
+       if( slapd_gentle_shutdown >= 0 )
+               close_listeners ( 0 );
        free ( slap_listeners );
        slap_listeners = NULL;
 
@@ -1862,6 +1901,11 @@ slap_sig_shutdown( int sig )
                  0, 0, 0);
 #endif
        else
+#endif
+#ifdef SIGHUP
+       if (sig == SIGHUP && global_gentlehup && slapd_gentle_shutdown == 0)
+               slapd_gentle_shutdown = 1;
+       else
 #endif
        slapd_shutdown = 1;
 
index ac953f111e33976a3ea062f1fa2ac1a34496e598..56bd29667b491b59dc3e40bd258be1e43a5266a5 100644 (file)
@@ -23,7 +23,7 @@ static int test_mra_vrFilter(
        Backend         *be,
        Connection      *conn,
        Operation       *op,
-       Entry           *e,
+       Attribute       *a,
        MatchingRuleAssertion *mra,
        char            ***e_flags
 );
@@ -33,7 +33,7 @@ test_substrings_vrFilter(
        Backend         *be,
        Connection      *conn,
        Operation       *op,
-       Entry           *e,
+       Attribute       *a,
        ValuesReturnFilter *f,
        char            ***e_flags
 );
@@ -43,7 +43,7 @@ test_presence_vrFilter(
        Backend         *be,
        Connection      *conn,
        Operation       *op,
-       Entry           *e,
+       Attribute       *a,
        AttributeDescription *desc,
        char            ***e_flags
 );
@@ -53,7 +53,7 @@ test_ava_vrFilter(
        Backend         *be,
        Connection      *conn,
        Operation       *op,
-       Entry           *e,
+       Attribute       *a,
        AttributeAssertion *ava,
        int             type,
        char            ***e_flags
@@ -65,7 +65,7 @@ filter_matched_values(
        Backend         *be,
        Connection      *conn,
        Operation       *op,
-       Entry           *e,
+       Attribute       *a,
        char            ***e_flags
 )
 {
@@ -108,7 +108,7 @@ filter_matched_values(
 #else
                        Debug( LDAP_DEBUG_FILTER, "     EQUALITY\n", 0, 0, 0 );
 #endif
-                       rc = test_ava_vrFilter( be, conn, op, e, f->f_ava,
+                       rc = test_ava_vrFilter( be, conn, op, a, f->f_ava,
                                LDAP_FILTER_EQUALITY, e_flags );
                        if( rc == -1 ) {
                                return rc;
@@ -123,7 +123,7 @@ filter_matched_values(
                        Debug( LDAP_DEBUG_FILTER, "     SUBSTRINGS\n", 0, 0, 0 );
 #endif
 
-                       rc = test_substrings_vrFilter( be, conn, op, e,
+                       rc = test_substrings_vrFilter( be, conn, op, a,
                                f, e_flags );
                        if( rc == -1 ) {
                                return rc;
@@ -137,7 +137,7 @@ filter_matched_values(
 #else
                        Debug( LDAP_DEBUG_FILTER, "     PRESENT\n", 0, 0, 0 );
 #endif
-                       rc = test_presence_vrFilter( be, conn, op, e,
+                       rc = test_presence_vrFilter( be, conn, op, a,
                                f->f_desc, e_flags );
                        if( rc == -1 ) {
                                return rc;
@@ -145,7 +145,7 @@ filter_matched_values(
                        break;
 
                case LDAP_FILTER_GE:
-                       rc = test_ava_vrFilter( be, conn, op, e, f->f_ava,
+                       rc = test_ava_vrFilter( be, conn, op, a, f->f_ava,
                                LDAP_FILTER_GE, e_flags );
                        if( rc == -1 ) {
                                return rc;
@@ -153,7 +153,7 @@ filter_matched_values(
                        break;
 
                case LDAP_FILTER_LE:
-                       rc = test_ava_vrFilter( be, conn, op, e, f->f_ava,
+                       rc = test_ava_vrFilter( be, conn, op, a, f->f_ava,
                                LDAP_FILTER_LE, e_flags );
                        if( rc == -1 ) {
                                return rc;
@@ -167,7 +167,7 @@ filter_matched_values(
 #else
                        Debug( LDAP_DEBUG_FILTER, "     EXT\n", 0, 0, 0 );
 #endif
-                       rc = test_mra_vrFilter( be, conn, op, e,
+                       rc = test_mra_vrFilter( be, conn, op, a,
                                f->f_mra, e_flags );
                        if( rc == -1 ) {
                                return rc;
@@ -198,25 +198,18 @@ filter_matched_values(
 
 static int
 test_ava_vrFilter(
-               Backend         *be,
+       Backend         *be,
        Connection      *conn,
-               Operation       *op,
-               Entry           *e,
+       Operation       *op,
+       Attribute       *a,
        AttributeAssertion *ava,
-               int             type,
-               char            ***e_flags
+       int             type,
+       char            ***e_flags
 )
 {
        int             i, j;
-       Attribute       *a;
-
-       if ( !access_allowed( be, conn, op, e,
-               ava->aa_desc, &ava->aa_value, ACL_SEARCH, NULL ) )
-       {
-               return LDAP_INSUFFICIENT_ACCESS;
-       }
 
-       for (a = e->e_attrs, i=0; a != NULL; a = a->a_next, i++ ) {
+       for ( i=0; a != NULL; a = a->a_next, i++ ) {
 
                MatchingRule *mr;
                struct berval *bv;
@@ -287,22 +280,17 @@ test_ava_vrFilter(
 
 static int
 test_presence_vrFilter(
-               Backend         *be,
-               Connection      *conn,
-               Operation       *op,
-               Entry           *e,
-               AttributeDescription *desc,
-               char            ***e_flags
+       Backend         *be,
+       Connection      *conn,
+       Operation       *op,
+       Attribute       *a,
+       AttributeDescription *desc,
+       char            ***e_flags
 )
 {
        int i, j;
-       Attribute       *a;
 
-       if ( !access_allowed( be, conn, op, e, desc, NULL, ACL_SEARCH, NULL ) ) {
-               return LDAP_INSUFFICIENT_ACCESS;
-       }
-
-       for (a = e->e_attrs, i=0; a != NULL; a = a->a_next, i++ ) {
+       for ( i=0; a != NULL; a = a->a_next, i++ ) {
                struct berval *bv;
 
                if ( !is_ad_subtype( a->a_desc, desc ) ) {
@@ -318,24 +306,17 @@ test_presence_vrFilter(
 
 static int
 test_substrings_vrFilter(
-               Backend         *be,
-               Connection      *conn,
-               Operation       *op,
-               Entry           *e,
-               ValuesReturnFilter *f,
-               char            ***e_flags
+       Backend         *be,
+       Connection      *conn,
+       Operation       *op,
+       Attribute       *a,
+       ValuesReturnFilter *f,
+       char            ***e_flags
 )
 {
        int i, j;
-       Attribute       *a;
-
-       if ( !access_allowed( be, conn, op, e,
-               f->f_sub_desc, NULL, ACL_SEARCH, NULL ) )
-       {
-               return LDAP_INSUFFICIENT_ACCESS;
-       }
 
-       for (a = e->e_attrs, i=0; a != NULL; a = a->a_next, i++ ) {
+       for ( i=0; a != NULL; a = a->a_next, i++ ) {
                MatchingRule *mr = a->a_desc->ad_type->sat_substr;
                struct berval *bv;
 
@@ -373,21 +354,14 @@ static int test_mra_vrFilter(
        Backend         *be,
        Connection      *conn,
        Operation       *op,
-       Entry           *e,
+       Attribute       *a,
        MatchingRuleAssertion *mra,
        char            ***e_flags
 )
 {
        int i, j;
-       Attribute       *a;
-
-       if( !access_allowed( be, conn, op, e,
-               mra->ma_desc, &mra->ma_value, ACL_SEARCH, NULL ) )
-       {
-               return LDAP_INSUFFICIENT_ACCESS;
-       }
 
-       for (a = e->e_attrs, i=0; a != NULL; a = a->a_next, i++ ) {
+       for ( i=0; a != NULL; a = a->a_next, i++ ) {
                struct berval *bv;
        
                if ( !is_ad_subtype( a->a_desc, mra->ma_desc ) ) {
index e1af29d0c88fbee2205347a255571b63422f67a5..f8e788b6e0082d66acd4d2b0676a08588e42c915 100644 (file)
@@ -108,7 +108,7 @@ mr_insert(
                                 (AVL_DUP) avl_dup_error ) ) {
                        *err = smr->smr_oid;
                        ldap_memfree(mir);
-                       return SLAP_SCHERR_DUP_RULE;
+                       return SLAP_SCHERR_MR_DUP;
                }
                /* FIX: temporal consistency check */
                mr_bvfind(&mir->mir_name);
@@ -125,7 +125,7 @@ mr_insert(
                                         (AVL_DUP) avl_dup_error ) ) {
                                *err = *names;
                                ldap_memfree(mir);
-                               return SLAP_SCHERR_DUP_RULE;
+                               return SLAP_SCHERR_MR_DUP;
                        }
                        /* FIX: temporal consistency check */
                        mr_bvfind(&mir->mir_name);
diff --git a/servers/slapd/oc.c b/servers/slapd/oc.c
new file mode 100644 (file)
index 0000000..02f6ea4
--- /dev/null
@@ -0,0 +1,512 @@
+/* oc.c - object class routines */
+/* $OpenLDAP$ */
+/*
+ * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+
+#include "portable.h"
+
+#include <stdio.h>
+
+#include <ac/ctype.h>
+#include <ac/string.h>
+#include <ac/socket.h>
+
+#include "slap.h"
+#include "ldap_pvt.h"
+
+int is_object_subclass(
+       ObjectClass *sup,
+       ObjectClass *sub )
+{
+       int i;
+
+       if( sub == NULL || sup == NULL ) return 0;
+
+#if 1
+       Debug( LDAP_DEBUG_TRACE, "is_object_subclass(%s,%s) %d\n",
+               sup->soc_oid, sub->soc_oid, sup == sub );
+#endif
+
+       if( sup == sub ) {
+               return 1;
+       }
+
+       if( sub->soc_sups == NULL ) {
+               return 0;
+       }
+
+       for( i=0; sub->soc_sups[i] != NULL; i++ ) {
+               if( is_object_subclass( sup, sub->soc_sups[i] ) ) {
+                       return 1;
+               }
+       }
+
+       return 0;
+}
+
+int is_entry_objectclass(
+       Entry*  e,
+       ObjectClass *oc,
+       int set_flags )
+{
+       Attribute *attr;
+       struct berval *bv;
+       AttributeDescription *objectClass = slap_schema.si_ad_objectClass;
+       assert(!( e == NULL || oc == NULL ));
+
+       if( e == NULL || oc == NULL ) {
+               return 0;
+       }
+
+       if( set_flags && ( e->e_ocflags & SLAP_OC__END )) {
+               return (e->e_ocflags & oc->soc_flags) ? 1 : 0;
+       }
+
+       /*
+        * find objectClass attribute
+        */
+       attr = attr_find(e->e_attrs, objectClass);
+
+       if( attr == NULL ) {
+               /* no objectClass attribute */
+#ifdef NEW_LOGGING
+               LDAP_LOG(( "operation", LDAP_LEVEL_ERR, "is_entry_objectclass: "
+                       "dn(%s), oid (%s), no objectClass attribute.\n",
+                       e->e_dn == NULL ? "" : e->e_dn,
+                       oc->soc_oclass.oc_oid ));
+#else
+               Debug( LDAP_DEBUG_ANY, "is_entry_objectclass(\"%s\", \"%s\") "
+                       "no objectClass attribute\n",
+                       e->e_dn == NULL ? "" : e->e_dn,
+                       oc->soc_oclass.oc_oid, 0 );
+#endif
+
+               return 0;
+       }
+
+       for( bv=attr->a_vals; bv->bv_val; bv++ ) {
+               ObjectClass *objectClass = oc_bvfind( bv );
+
+               if ( objectClass == oc && !set_flags ) {
+                       return 1;
+               }
+               
+               if ( objectClass != NULL ) {
+                       e->e_ocflags |= objectClass->soc_flags;
+               }
+       }
+       e->e_ocflags |= SLAP_OC__END;   /* We've finished this */
+
+       return (e->e_ocflags & oc->soc_flags);
+}
+
+
+struct oindexrec {
+       struct berval   oir_name;
+       ObjectClass     *oir_oc;
+};
+
+static Avlnode *oc_index = NULL;
+static ObjectClass *oc_list = NULL;
+
+static int
+oc_index_cmp(
+    struct oindexrec   *oir1,
+    struct oindexrec   *oir2 )
+{
+       int i = oir1->oir_name.bv_len - oir2->oir_name.bv_len;
+       if (i)
+               return i;
+       return strcasecmp( oir1->oir_name.bv_val, oir2->oir_name.bv_val );
+}
+
+static int
+oc_index_name_cmp(
+    struct berval      *name,
+    struct oindexrec   *oir )
+{
+       int i = name->bv_len - oir->oir_name.bv_len;
+       if (i)
+               return i;
+       return strncasecmp( name->bv_val, oir->oir_name.bv_val, name->bv_len );
+}
+
+ObjectClass *
+oc_find( const char *ocname )
+{
+       struct berval bv;
+
+       bv.bv_val = (char *)ocname;
+       bv.bv_len = strlen( ocname );
+
+       return( oc_bvfind( &bv ) );
+}
+
+ObjectClass *
+oc_bvfind( struct berval *ocname )
+{
+       struct oindexrec        *oir;
+
+       oir = (struct oindexrec *) avl_find( oc_index, ocname,
+            (AVL_CMP) oc_index_name_cmp );
+
+       if ( oir != NULL ) {
+               return( oir->oir_oc );
+       }
+
+       return( NULL );
+}
+
+static int
+oc_create_required(
+    ObjectClass                *soc,
+    char               **attrs,
+       int                     *op,
+    const char         **err )
+{
+       char            **attrs1;
+       AttributeType   *sat;
+       AttributeType   **satp;
+       int             i;
+
+       if ( attrs ) {
+               attrs1 = attrs;
+               while ( *attrs1 ) {
+                       sat = at_find(*attrs1);
+                       if ( !sat ) {
+                               *err = *attrs1;
+                               return SLAP_SCHERR_ATTR_NOT_FOUND;
+                       }
+
+                       if( is_at_operational( sat )) (*op)++;
+
+                       if ( at_find_in_list(sat, soc->soc_required) < 0) {
+                               if ( at_append_to_list(sat, &soc->soc_required) ) {
+                                       *err = *attrs1;
+                                       return SLAP_SCHERR_OUTOFMEM;
+                               }
+                       }
+                       attrs1++;
+               }
+               /* Now delete duplicates from the allowed list */
+               for ( satp = soc->soc_required; *satp; satp++ ) {
+                       i = at_find_in_list(*satp,soc->soc_allowed);
+                       if ( i >= 0 ) {
+                               at_delete_from_list(i, &soc->soc_allowed);
+                       }
+               }
+       }
+       return 0;
+}
+
+static int
+oc_create_allowed(
+    ObjectClass                *soc,
+    char               **attrs,
+       int                     *op,
+    const char         **err )
+{
+       char            **attrs1;
+       AttributeType   *sat;
+
+       if ( attrs ) {
+               attrs1 = attrs;
+               while ( *attrs1 ) {
+                       sat = at_find(*attrs1);
+                       if ( !sat ) {
+                               *err = *attrs1;
+                               return SLAP_SCHERR_ATTR_NOT_FOUND;
+                       }
+
+                       if( is_at_operational( sat )) (*op)++;
+
+                       if ( at_find_in_list(sat, soc->soc_required) < 0 &&
+                            at_find_in_list(sat, soc->soc_allowed) < 0 ) {
+                               if ( at_append_to_list(sat, &soc->soc_allowed) ) {
+                                       *err = *attrs1;
+                                       return SLAP_SCHERR_OUTOFMEM;
+                               }
+                       }
+                       attrs1++;
+               }
+       }
+       return 0;
+}
+
+static int
+oc_add_sups(
+    ObjectClass                *soc,
+    char                       **sups,
+       int                     *op,
+    const char         **err )
+{
+       int             code;
+       ObjectClass     *soc1;
+       int             nsups;
+       char    **sups1;
+       int             add_sups = 0;
+
+       if ( sups ) {
+               if ( !soc->soc_sups ) {
+                       /* We are at the first recursive level */
+                       add_sups = 1;
+                       nsups = 1;
+                       sups1 = sups;
+                       while ( *sups1 ) {
+                               nsups++;
+                               sups1++;
+                       }
+                       soc->soc_sups = (ObjectClass **)ch_calloc(nsups,
+                                         sizeof(ObjectClass *));
+               }
+
+               nsups = 0;
+               sups1 = sups;
+               while ( *sups1 ) {
+                       soc1 = oc_find(*sups1);
+                       if ( !soc1 ) {
+                               *err = *sups1;
+                               return SLAP_SCHERR_CLASS_NOT_FOUND;
+                       }
+
+                       /* check object class usage
+                        * abstract classes can only sup abstract classes 
+                        * structural classes can not sup auxiliary classes
+                        * auxiliary classes can not sup structural classes
+                        */
+                       if( soc->soc_kind != soc1->soc_kind
+                               && soc1->soc_kind != LDAP_SCHEMA_ABSTRACT )
+                       {
+                               *err = *sups1;
+                               return SLAP_SCHERR_CLASS_BAD_USAGE;
+                       }
+
+                       if( soc->soc_flags & SLAP_OC_OPERATIONAL ) (*op)++;
+
+                       if ( add_sups ) {
+                               soc->soc_sups[nsups] = soc1;
+                       }
+
+                       code = oc_add_sups( soc, soc1->soc_sup_oids, op, err );
+                       if ( code ) return code;
+
+                       code = oc_create_required( soc, soc1->soc_at_oids_must, op, err );
+                       if ( code ) return code;
+
+                       code = oc_create_allowed( soc, soc1->soc_at_oids_may, op, err );
+                       if ( code ) return code;
+
+                       nsups++;
+                       sups1++;
+               }
+       }
+
+       return 0;
+}
+
+void
+oc_destroy( void )
+{
+       ObjectClass *o, *n;
+
+       avl_free(oc_index, ldap_memfree);
+       for (o=oc_list; o; o=n)
+       {
+               n = o->soc_next;
+               if (o->soc_sups) ldap_memfree(o->soc_sups);
+               if (o->soc_required) ldap_memfree(o->soc_required);
+               if (o->soc_allowed) ldap_memfree(o->soc_allowed);
+               ldap_objectclass_free((LDAPObjectClass *)o);
+       }
+}
+
+static int
+oc_insert(
+    ObjectClass                *soc,
+    const char         **err
+)
+{
+       ObjectClass     **ocp;
+       struct oindexrec        *oir;
+       char                    **names;
+
+       ocp = &oc_list;
+       while ( *ocp != NULL ) {
+               ocp = &(*ocp)->soc_next;
+       }
+       *ocp = soc;
+
+       if ( soc->soc_oid ) {
+               oir = (struct oindexrec *)
+                       ch_calloc( 1, sizeof(struct oindexrec) );
+               oir->oir_name.bv_val = soc->soc_oid;
+               oir->oir_name.bv_len = strlen( soc->soc_oid );
+               oir->oir_oc = soc;
+
+               assert( oir->oir_name.bv_val );
+               assert( oir->oir_oc );
+
+               if ( avl_insert( &oc_index, (caddr_t) oir,
+                                (AVL_CMP) oc_index_cmp,
+                                (AVL_DUP) avl_dup_error ) )
+               {
+                       *err = soc->soc_oid;
+                       ldap_memfree(oir);
+                       return SLAP_SCHERR_CLASS_DUP;
+               }
+
+               /* FIX: temporal consistency check */
+               assert( oc_bvfind(&oir->oir_name) != NULL );
+       }
+
+       if ( (names = soc->soc_names) ) {
+               while ( *names ) {
+                       oir = (struct oindexrec *)
+                               ch_calloc( 1, sizeof(struct oindexrec) );
+                       oir->oir_name.bv_val = *names;
+                       oir->oir_name.bv_len = strlen( *names );
+                       oir->oir_oc = soc;
+
+                       assert( oir->oir_name.bv_val );
+                       assert( oir->oir_oc );
+
+                       if ( avl_insert( &oc_index, (caddr_t) oir,
+                                        (AVL_CMP) oc_index_cmp,
+                                        (AVL_DUP) avl_dup_error ) )
+                       {
+                               *err = *names;
+                               ldap_memfree(oir);
+                               return SLAP_SCHERR_CLASS_DUP;
+                       }
+
+                       /* FIX: temporal consistency check */
+                       assert( oc_bvfind(&oir->oir_name) != NULL );
+
+                       names++;
+               }
+       }
+
+       return 0;
+}
+
+int
+oc_add(
+    LDAPObjectClass    *oc,
+       int user,
+    const char         **err
+)
+{
+       ObjectClass     *soc;
+       int             code;
+       int             op = 0;
+
+       if ( oc->oc_names != NULL ) {
+               int i;
+
+               for( i=0; oc->oc_names[i]; i++ ) {
+                       if( !slap_valid_descr( oc->oc_names[i] ) ) {
+                               return SLAP_SCHERR_BAD_DESCR;
+                       }
+               }
+       }
+
+       if ( !OID_LEADCHAR( oc->oc_oid[0] )) {
+               /* Expand OID macros */
+               char *oid = oidm_find( oc->oc_oid );
+               if ( !oid ) {
+                       *err = oc->oc_oid;
+                       return SLAP_SCHERR_OIDM;
+               }
+               if ( oid != oc->oc_oid ) {
+                       ldap_memfree( oc->oc_oid );
+                       oc->oc_oid = oid;
+               }
+       }
+
+       soc = (ObjectClass *) ch_calloc( 1, sizeof(ObjectClass) );
+       AC_MEMCPY( &soc->soc_oclass, oc, sizeof(LDAPObjectClass) );
+
+       if( soc->soc_sup_oids == NULL &&
+               soc->soc_kind == LDAP_SCHEMA_STRUCTURAL )
+       {
+               /* structural object classes implicitly inherit from 'top' */
+               static char *top_oids[] = { SLAPD_TOP_OID, NULL };
+               code = oc_add_sups( soc, top_oids, &op, err );
+       } else {
+               code = oc_add_sups( soc, soc->soc_sup_oids, &op, err );
+       }
+
+       if ( code != 0 ) return code;
+
+       code = oc_create_required( soc, soc->soc_at_oids_must, &op, err );
+       if ( code != 0 ) return code;
+
+       code = oc_create_allowed( soc, soc->soc_at_oids_may, &op, err );
+       if ( code != 0 ) return code;
+
+       if( user && op ) return SLAP_SCHERR_CLASS_BAD_SUP;
+
+       code = oc_insert(soc,err);
+       return code;
+}
+
+#ifdef LDAP_DEBUG
+
+static void
+oc_print( ObjectClass *oc )
+{
+       int     i;
+       const char *mid;
+
+       printf( "objectclass %s\n", ldap_objectclass2name( &oc->soc_oclass ) );
+       if ( oc->soc_required != NULL ) {
+               mid = "\trequires ";
+               for ( i = 0; oc->soc_required[i] != NULL; i++, mid = "," )
+                       printf( "%s%s", mid,
+                               ldap_attributetype2name( &oc->soc_required[i]->sat_atype ) );
+               printf( "\n" );
+       }
+       if ( oc->soc_allowed != NULL ) {
+               mid = "\tallows ";
+               for ( i = 0; oc->soc_allowed[i] != NULL; i++, mid = "," )
+                       printf( "%s%s", mid,
+                               ldap_attributetype2name( &oc->soc_allowed[i]->sat_atype ) );
+               printf( "\n" );
+       }
+}
+
+#endif
+
+
+#if defined( SLAPD_SCHEMA_DN )
+
+int
+oc_schema_info( Entry *e )
+{
+       struct berval   vals[2];
+       ObjectClass     *oc;
+
+       AttributeDescription *ad_objectClasses = slap_schema.si_ad_objectClasses;
+
+       vals[1].bv_val = NULL;
+
+       for ( oc = oc_list; oc; oc = oc->soc_next ) {
+               if ( ldap_objectclass2bv( &oc->soc_oclass, vals ) == NULL ) {
+                       return -1;
+               }
+
+               if( oc->soc_flags & SLAP_OC_HIDE ) continue;
+
+#if 0
+               Debug( LDAP_DEBUG_TRACE, "Merging oc [%ld] %s\n",
+              (long) vals[0].bv_len, vals[0].bv_val, 0 );
+#endif
+               attr_merge( e, ad_objectClasses, vals );
+               ldap_memfree( vals[0].bv_val );
+       }
+       return 0;
+}
+
+#endif
index 3a8ddd9c1dce03b616542d9c6722393ac9fc2d99..94cbeac0cf2d7631efd2376b40dd7655c4cde281 100644 (file)
@@ -321,13 +321,17 @@ slap_passwd_hash(
 #endif
 
        tmp = lutil_passwd_hash( cred , hash );
-       assert( tmp != NULL );
        
 #if defined( SLAPD_CRYPT ) || defined( SLAPD_SPASSWD )
        ldap_pvt_thread_mutex_unlock( &passwd_mutex );
 #endif
+
+       if( tmp == NULL ) {
+               new->bv_len = 0;
+               new->bv_val = NULL;
+       }
+
        *new = *tmp;
        free( tmp );
-
        return;
 }
index 7b2a65a980508f7dbfd1eb8cbf9b184ab1266f71..f80e53969a21dd3834cff7738131e54a3ca21bb5 100644 (file)
@@ -526,7 +526,7 @@ LDAP_SLAPD_F (int) filter_matched_values(
        Backend         *be,
        Connection      *conn,
        Operation       *op,
-       Entry           *e,
+       Attribute       *a,
        char            ***e_flags );
 
 /*
@@ -626,6 +626,7 @@ LDAP_SLAPD_F (void) mra_free LDAP_P((
 /* oc.c */
 LDAP_SLAPD_F (int) oc_add LDAP_P((
        LDAPObjectClass *oc,
+       int user,
        const char **err));
 LDAP_SLAPD_F (void) oc_destroy LDAP_P(( void ));
 
@@ -1016,6 +1017,7 @@ LDAP_SLAPD_V (const char)         Versionstr[];
 LDAP_SLAPD_V (struct slap_limits_set)          deflimit;
 
 LDAP_SLAPD_V (slap_access_t)   global_default_access;
+LDAP_SLAPD_V (int)             global_gentlehup;
 LDAP_SLAPD_V (int)             global_idletimeout;
 LDAP_SLAPD_V (int)             global_schemacheck;
 LDAP_SLAPD_V (char *)  global_host;
index 83906f6418c7538558df630128cc334b8479e640..140e4a6d6cb22625602992aad41171dcebc28fa5 100644 (file)
@@ -744,9 +744,9 @@ send_search_entry(
                e_flags[i] = a_flags; 
        }
 
-       if ( op->vrFilter != NULL ){
+       if ( op->vrFilter != NULL ){ 
 
-               rc = filter_matched_values(be, conn, op, e, &e_flags) ; 
+               rc = filter_matched_values(be, conn, op, e->e_attrs, &e_flags) ; 
            
                if ( rc == -1 ) {
 #ifdef NEW_LOGGING
@@ -917,8 +917,51 @@ send_search_entry(
        /* eventually will loop through generated operational attributes */
        /* only have subschemaSubentry implemented */
        aa = backend_operational( be, conn, op, e, attrs, opattrs );
+
+       for ( a = aa, i=0; a != NULL; a = a->a_next ) i++;
+       e_flags = ch_malloc ( i * sizeof(a_flags) );
        
-       for (a = aa ; a != NULL; a = a->a_next ) {
+       for ( a = aa, i=0; a != NULL; a = a->a_next, i++ ) {
+               for ( j = 0; a->a_vals[j].bv_val != NULL; j++ );
+
+               a_flags = ch_calloc ( j, sizeof(char) );
+               /* If no ValuesReturnFilter control return everything */
+               if ( op->vrFilter == NULL ){
+                   memset(a_flags, 1, j);
+               }
+               e_flags[i] = a_flags; 
+       }
+
+       if ( op->vrFilter != NULL ){ 
+
+               rc = filter_matched_values(be, conn, op, aa, &e_flags) ; 
+           
+               if ( rc == -1 ) {
+#ifdef NEW_LOGGING
+                       LDAP_LOG(( "operation", LDAP_LEVEL_ERR,
+                               "send_search_entry: conn %lu "
+                               "matched values filtering failed\n",
+                               conn ? conn->c_connid : 0 ));
+#else
+               Debug( LDAP_DEBUG_ANY,
+                               "matched values filtering failed\n", 0, 0, 0 );
+#endif
+                       ber_free( ber, 1 );
+
+                       /* free e_flags */
+                       for ( a = aa, i=0; a != NULL; a = a->a_next, i++ ) {
+                               free( e_flags[i] );
+                       }
+                       free( e_flags );
+
+                       send_ldap_result( conn, op, LDAP_OTHER,
+                               NULL, "matched values filtering error", 
+                               NULL, NULL );
+                       goto error_return;
+               }
+       }
+
+       for (a = aa, j=0; a != NULL; a = a->a_next, j++ ) {
                AttributeDescription *desc = a->a_desc;
 
                if ( attrs == NULL ) {
@@ -974,6 +1017,12 @@ send_search_entry(
                        ber_free_buf( ber );
                        send_ldap_result( conn, op, LDAP_OTHER,
                            NULL, "encoding description error", NULL, NULL );
+                       /* free e_flags */
+                       for ( a = aa, i=0; a != NULL; a = a->a_next, i++ ) {
+                               free( e_flags[i] );
+                       }
+                       free( e_flags );
+
                        attrs_free( aa );
                        goto error_return;
                }
@@ -1000,6 +1049,10 @@ send_search_entry(
                                        continue;
                                }
 
+                               if ( e_flags[j][i] == 0 ){
+                                       continue;
+                               }
+
                                if (( rc = ber_printf( ber, "O", &a->a_vals[i] )) == -1 ) {
 #ifdef NEW_LOGGING
                                        LDAP_LOG(( "operation", LDAP_LEVEL_ERR,
@@ -1016,6 +1069,12 @@ send_search_entry(
                                        send_ldap_result( conn, op, LDAP_OTHER,
                                                NULL, "encoding values error", 
                                                NULL, NULL );
+                                       /* free e_flags */
+                                       for ( a = aa, i=0; a != NULL; a = a->a_next, i++ ) {
+                                               free( e_flags[i] );
+                                       }
+                                       free( e_flags );
+
                                        attrs_free( aa );
                                        goto error_return;
                                }
@@ -1035,13 +1094,24 @@ send_search_entry(
                        ber_free_buf( ber );
                        send_ldap_result( conn, op, LDAP_OTHER,
                            NULL, "encode end error", NULL, NULL );
+                       /* free e_flags */
+                       for ( a = aa, i=0; a != NULL; a = a->a_next, i++ ) {
+                               free( e_flags[i] );
+                       }
+                       free( e_flags );
+
                        attrs_free( aa );
                        goto error_return;
                }
        }
 
-       attrs_free( aa );
+       /* free e_flags */
+       for ( a = aa, i=0; a != NULL; a = a->a_next, i++ ) {
+               free( e_flags[i] );
+       }
+       free( e_flags );
 
+       attrs_free( aa );
        rc = ber_printf( ber, /*{{{*/ "}N}N}" );
 
 #ifdef LDAP_CONNECTIONLESS
index 33d11278f740de9c98281c9ee5f3616bf37ec450..184aad8d155b8dd4d3fa1ce4ce8ee396839dac86 100644 (file)
@@ -162,28 +162,29 @@ static struct slap_schema_oc_map {
                        "NAME 'extensibleObject' "
                        "DESC 'RFC2252: extensible object' "
                        "SUP top AUXILIARY )",
-               0, 0, offsetof(struct slap_internal_schema, si_oc_extensibleObject) },
+               0, SLAP_OC_OPERATIONAL,
+               offsetof(struct slap_internal_schema, si_oc_extensibleObject) },
        { "alias", "( 2.5.6.1 NAME 'alias' "
                        "DESC 'RFC2256: an alias' "
                        "SUP top STRUCTURAL "
                        "MUST aliasedObjectName )",
-               aliasObjectClass, SLAP_OC_ALIAS,
+               aliasObjectClass, SLAP_OC_ALIAS|SLAP_OC_OPERATIONAL,
                offsetof(struct slap_internal_schema, si_oc_alias) },
        { "referral", "( 2.16.840.1.113730.3.2.6 NAME 'referral' "
                        "DESC 'namedref: named subordinate referral' "
                        "SUP top STRUCTURAL MUST ref )",
-               referralObjectClass, SLAP_OC_REFERRAL,
+               referralObjectClass, SLAP_OC_REFERRAL|SLAP_OC_OPERATIONAL,
                offsetof(struct slap_internal_schema, si_oc_referral) },
        { "LDAProotDSE", "( 1.3.6.1.4.1.4203.1.4.1 "
                        "NAME ( 'OpenLDAProotDSE' 'LDAProotDSE' ) "
                        "DESC 'OpenLDAP Root DSE object' "
                        "SUP top STRUCTURAL MAY cn )",
-               rootDseObjectClass, 0,
+               rootDseObjectClass, SLAP_OC_OPERATIONAL,
                offsetof(struct slap_internal_schema, si_oc_rootdse) },
        { "subentry", "( 2.5.20.0 NAME 'subentry' "
                        "SUP top STRUCTURAL "
                        "MUST ( cn $ subtreeSpecification ) )",
-               subentryObjectClass, SLAP_OC_SUBENTRY,
+               subentryObjectClass, SLAP_OC_SUBENTRY|SLAP_OC_OPERATIONAL,
                offsetof(struct slap_internal_schema, si_oc_subentry) },
        { "subschema", "( 2.5.20.1 NAME 'subschema' "
                "DESC 'RFC2252: controlling subschema (sub)entry' "
@@ -191,13 +192,14 @@ static struct slap_schema_oc_map {
                "MAY ( dITStructureRules $ nameForms $ ditContentRules $ "
                        "objectClasses $ attributeTypes $ matchingRules $ "
                        "matchingRuleUse ) )",
-               subentryObjectClass, 0,
+               subentryObjectClass, SLAP_OC_OPERATIONAL,
                offsetof(struct slap_internal_schema, si_oc_subschema) },
        { "monitor", "( 1.3.6.1.4.1.4203.666.3.2 NAME 'monitor' "
                "DESC 'OpenLDAP system monitoring' "
                "STRUCTURAL "
                "MUST cn )",
-               0, 0, offsetof(struct slap_internal_schema, si_oc_monitor) },
+               0, SLAP_OC_OPERATIONAL,
+               offsetof(struct slap_internal_schema, si_oc_monitor) },
        { NULL, NULL, NULL, 0, 0 }
 };
 
@@ -222,7 +224,7 @@ static struct slap_schema_ad_map {
                        "DESC 'RFC2256: object classes of the entity' "
                        "EQUALITY objectIdentifierMatch "
                        "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
-               NULL, 0, objectClassMatch, NULL, NULL,
+               NULL, SLAP_AT_FINAL, objectClassMatch, NULL, NULL,
                offsetof(struct slap_internal_schema, si_ad_objectClass) },
 
        /* user entry operational attributes */
@@ -278,6 +280,21 @@ static struct slap_schema_ad_map {
                NULL, 0, NULL, NULL, NULL,
                offsetof(struct slap_internal_schema, si_ad_subschemaSubentry) },
 
+       { "entryUUID", "( 1.3.6.1.4.1.4203.666.1.6 NAME 'entryUUID' "   
+                       "DESC 'LCUP/LDUP: universally unique identifier' "
+                       "EQUALITY octetStringMatch "
+                       "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40{64} "
+                       "SINGLE-VALUE NO-USER-MODIFICATION USAGE directoryOperation )",
+               NULL, SLAP_AT_HIDE, NULL, NULL, NULL,
+               offsetof(struct slap_internal_schema, si_ad_entryUUID) },
+       { "entryCSN", "( 1.3.6.1.4.1.4203.666.1.7 NAME 'entryCSN' "
+                       "DESC 'LCUP/LDUP: change sequence number' "
+                       "EQUALITY octetStringMatch "
+                       "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40{64} "
+                       "SINGLE-VALUE NO-USER-MODIFICATION USAGE directoryOperation )",
+               NULL, SLAP_AT_HIDE, NULL, NULL, NULL,
+               offsetof(struct slap_internal_schema, si_ad_entryCSN) },
+
        /* root DSE attributes */
        { "altServer", "( 1.3.6.1.4.1.1466.101.120.6 NAME 'altServer' "
                        "DESC 'RFC2252: alternative servers' "
@@ -344,13 +361,13 @@ static struct slap_schema_ad_map {
                        "EQUALITY objectIdentifierMatch "
                        "USAGE directoryOperation "
                        "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
-               administrativeRoleAttribute, 0, NULL, NULL, NULL,
+               administrativeRoleAttribute, SLAP_AT_HIDE, NULL, NULL, NULL,
                offsetof(struct slap_internal_schema, si_ad_administrativeRole) },
        { "subtreeSpecification", "( 2.5.18.6 NAME 'subtreeSpecification' "
                        "SINGLE-VALUE "
                        "USAGE directoryOperation "
                        "SYNTAX 1.3.6.1.4.1.1466.115.121.1.45 )",
-               subentryAttribute, 0, NULL, NULL, NULL,
+               subentryAttribute, SLAP_AT_HIDE, NULL, NULL, NULL,
                offsetof(struct slap_internal_schema, si_ad_subtreeSpecification) },
 
        /* subschema subentry attributes */
@@ -359,13 +376,13 @@ static struct slap_schema_ad_map {
                        "EQUALITY integerFirstComponentMatch "
                        "SYNTAX 1.3.6.1.4.1.1466.115.121.1.17 "
                        "USAGE directoryOperation ) ",
-               subentryAttribute, 0, NULL, NULL, NULL,
+               subentryAttribute, SLAP_AT_HIDE, NULL, NULL, NULL,
                offsetof(struct slap_internal_schema, si_ad_ditStructureRules) },
        { "ditContentRules", "( 2.5.21.2 NAME 'dITContentRules' "
                        "DESC 'RFC2252: DIT content rules' "
                        "EQUALITY objectIdentifierFirstComponentMatch "
                        "SYNTAX 1.3.6.1.4.1.1466.115.121.1.16 USAGE directoryOperation )",
-               subentryAttribute, 0, NULL, NULL, NULL,
+               subentryAttribute, SLAP_AT_HIDE, NULL, NULL, NULL,
                offsetof(struct slap_internal_schema, si_ad_ditContentRules) },
        { "matchingRules", "( 2.5.21.4 NAME 'matchingRules' "
                        "DESC 'RFC2252: matching rules' "
@@ -389,13 +406,13 @@ static struct slap_schema_ad_map {
                        "DESC 'RFC2252: name forms ' "
                        "EQUALITY objectIdentifierFirstComponentMatch "
                        "SYNTAX 1.3.6.1.4.1.1466.115.121.1.35 USAGE directoryOperation )",
-               subentryAttribute, 0, NULL, NULL, NULL,
+               subentryAttribute, SLAP_AT_HIDE, NULL, NULL, NULL,
                offsetof(struct slap_internal_schema, si_ad_nameForms) },
        { "matchingRuleUse", "( 2.5.21.8 NAME 'matchingRuleUse' "
                        "DESC 'RFC2252: matching rule uses' "
                        "EQUALITY objectIdentifierFirstComponentMatch "
                        "SYNTAX 1.3.6.1.4.1.1466.115.121.1.31 USAGE directoryOperation )",
-               subentryAttribute, 0, NULL, NULL, NULL,
+               subentryAttribute, SLAP_AT_HIDE, NULL, NULL, NULL,
                offsetof(struct slap_internal_schema, si_ad_matchingRuleUse) },
 
        { "ldapSyntaxes", "( 1.3.6.1.4.1.1466.101.120.16 NAME 'ldapSyntaxes' "
@@ -411,7 +428,7 @@ static struct slap_schema_ad_map {
                        "DESC 'RFC2256: name of aliased object' "
                        "EQUALITY distinguishedNameMatch "
                        "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 SINGLE-VALUE )",
-               aliasAttribute, 0, NULL, NULL, NULL,
+               aliasAttribute, SLAP_AT_FINAL, NULL, NULL, NULL,
                offsetof(struct slap_internal_schema, si_ad_aliasedObjectName) },
        { "ref", "( 2.16.840.1.113730.3.1.34 NAME 'ref' "
                        "DESC 'namedref: subordinate referral URL' "
@@ -427,14 +444,14 @@ static struct slap_schema_ad_map {
                        "DESC 'OpenLDAP ACL entry pseudo-attribute' "
                        "SYNTAX 1.3.6.1.4.1.4203.1.1.1 "
                        "SINGLE-VALUE NO-USER-MODIFICATION USAGE dSAOperation )",
-               NULL, 0, NULL, NULL, NULL,
+               NULL, SLAP_AT_HIDE, NULL, NULL, NULL,
                offsetof(struct slap_internal_schema, si_ad_entry) },
        { "children", "( 1.3.6.1.4.1.4203.1.3.2 "
                        "NAME 'children' "
                        "DESC 'OpenLDAP ACL children pseudo-attribute' "
                        "SYNTAX 1.3.6.1.4.1.4203.1.1.1 "
                        "SINGLE-VALUE NO-USER-MODIFICATION USAGE dSAOperation )",
-               NULL, 0, NULL, NULL, NULL,
+               NULL, SLAP_AT_HIDE, NULL, NULL, NULL,
                offsetof(struct slap_internal_schema, si_ad_children) },
 
 #ifdef SLAPD_ACI_ENABLED
@@ -453,14 +470,14 @@ static struct slap_schema_ad_map {
                        "DESC 'RFC2256: common supertype of DN attributes' "
                        "EQUALITY distinguishedNameMatch "
                        "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
-               NULL, 0, NULL, NULL, NULL,
+               NULL, SLAP_AT_ABSTRACT, NULL, NULL, NULL,
                offsetof(struct slap_internal_schema, si_ad_distinguishedName) },
        { "name", "( 2.5.4.41 NAME 'name' "
                        "DESC 'RFC2256: common supertype of name attributes' "
                        "EQUALITY caseIgnoreMatch "
                        "SUBSTR caseIgnoreSubstringsMatch "
                        "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{32768} )",
-               NULL, 0, NULL, NULL, NULL,
+               NULL, SLAP_AT_ABSTRACT, NULL, NULL, NULL,
                offsetof(struct slap_internal_schema, si_ad_name) },
        { "cn", "( 2.5.4.3 NAME ( 'cn' 'commonName' ) "
                        "DESC 'RFC2256: common name(s) for which the entity is known by' "
@@ -471,7 +488,7 @@ static struct slap_schema_ad_map {
                        "DESC 'RFC2256/2307: password of user' "
                        "EQUALITY octetStringMatch "
                        "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40{128} )",
-               NULL, 0, NULL, NULL, NULL,
+               NULL, SLAP_AT_FINAL, NULL, NULL, NULL,
                offsetof(struct slap_internal_schema, si_ad_userPassword) },
 
 #ifdef SLAPD_AUTHPASSWD
@@ -480,7 +497,7 @@ static struct slap_schema_ad_map {
                        "DESC 'RFC3112: authentication password attribute' "
                        "EQUALITY 1.3.6.1.4.1.4203.1.2.2 "
                        "SYNTAX 1.3.6.1.4.1.4203.1.1.2 )",
-               NULL, 0,
+               NULL, SLAP_AT_FINAL,
                NULL, NULL, NULL,
                offsetof(struct slap_internal_schema, si_ad_authPassword) },
        { "supportedAuthPasswordSchemes", "( 1.3.6.1.4.1.4203.1.3.3 "
@@ -494,7 +511,7 @@ static struct slap_schema_ad_map {
 #endif
 #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND
        { "krbName", NULL,
-               NULL, 0, NULL, NULL, NULL,
+               NULL, SLAP_AT_FINAL, NULL, NULL, NULL,
                offsetof(struct slap_internal_schema, si_ad_krbName) },
 #endif
 
@@ -510,7 +527,8 @@ static AttributeType slap_at_undefined = {
        NULL, /* subtypes */
        NULL, NULL, NULL, NULL, /* matching rules */
        NULL, /* syntax (this may need to be defined) */
-       (AttributeTypeSchemaCheckFN *) 0, 0, /* schema check function/mask */
+       (AttributeTypeSchemaCheckFN *) 0, /* schema check function */
+       SLAP_AT_ABSTRACT|SLAP_AT_FINAL, /* mask */
        NULL, /* next */
        NULL /* attribute description */
        /* mutex (don't know how to initialize it :) */
@@ -663,7 +681,7 @@ slap_schema_load( void )
                                return LDAP_OTHER;
                        }
 
-                       code = oc_add(oc,&err);
+                       code = oc_add(oc,0,&err);
                        if ( code ) {
                                fprintf( stderr, "slap_schema_load: "
                                        "%s: %s: \"%s\"\n",
index 171bd3473edf39ea434574af4be6cb4838efb645..10e92f827cb260fa4a791324a507b29323094ab2 100644 (file)
@@ -21,22 +21,23 @@ int global_schemacheck = 1; /* schemacheck ON is default */
 static void            oc_usage(void); 
 static void            at_usage(void);
 
-static char *const err2text[SLAP_SCHERR_LAST+1] = {
-       "Success",
+static char *const err2text[] = {
        "Out of memory",
        "ObjectClass not found",
        "ObjectClass inappropriate SUPerior",
+       "ObjectClass operational",
+       "Duplicate objectClass",
        "AttributeType not found",
        "AttributeType inappropriate USAGE",
-       "Duplicate objectClass",
+       "AttributeType inappropriate SUPerior",
+       "AttributeType SYNTAX or SUPerior required",
        "Duplicate attributeType",
-       "Duplicate ldapSyntax",
-       "Duplicate matchingRule",
-       "OID or name required",
-       "SYNTAX or SUPerior required",
        "MatchingRule not found",
+       "Duplicate matchingRule",
        "Syntax not found",
        "Syntax required",
+       "Duplicate ldapSyntax",
+       "OID or name required",
        "Qualifier not supported",
        "Invalid NAME",
        "OID could not be expanded"
@@ -45,7 +46,7 @@ static char *const err2text[SLAP_SCHERR_LAST+1] = {
 char *
 scherr2str(int code)
 {
-       if ( code < 0 || code >= (int)(sizeof(err2text)/sizeof(char *)) ) {
+       if ( code < 0 || SLAP_SCHERR_LAST < code ) {
                return "Unknown error";
        } else {
                return err2text[code];
@@ -118,7 +119,7 @@ parse_oc(
                return 1;
        }
 
-       code = oc_add(oc,&err);
+       code = oc_add(oc,1,&err);
        if ( code ) {
                fprintf( stderr, "%s: line %d: %s: \"%s\"\n",
                         fname, lineno, scherr2str(code), err);
index 62ddc37bccb77009bf1f9f0368ce91f4fd0e65b4..1437f35cc4279e7dcde36f81f143bb0a8752305b 100644 (file)
@@ -218,24 +218,26 @@ typedef struct slap_ssf_set {
 /*
  * represents schema information for a database
  */
-#define SLAP_SCHERR_OUTOFMEM           1
-#define SLAP_SCHERR_CLASS_NOT_FOUND    2
-#define SLAP_SCHERR_CLASS_BAD_USAGE    3
-#define SLAP_SCHERR_ATTR_NOT_FOUND     4
-#define SLAP_SCHERR_ATTR_BAD_USAGE     5
-#define SLAP_SCHERR_DUP_CLASS          6
-#define SLAP_SCHERR_DUP_ATTR           7
-#define SLAP_SCHERR_DUP_SYNTAX         8
-#define SLAP_SCHERR_DUP_RULE           9
-#define SLAP_SCHERR_NO_NAME            10
-#define SLAP_SCHERR_ATTR_INCOMPLETE    11
-#define SLAP_SCHERR_MR_NOT_FOUND       12
-#define SLAP_SCHERR_SYN_NOT_FOUND      13
-#define SLAP_SCHERR_MR_INCOMPLETE      14
-#define SLAP_SCHERR_NOT_SUPPORTED      15
-#define SLAP_SCHERR_BAD_DESCR          16
-#define SLAP_SCHERR_OIDM                       17
-#define SLAP_SCHERR_LAST                       SLAP_SCHERR_OIDM
+#define SLAP_SCHERR_OUTOFMEM                   1
+#define SLAP_SCHERR_CLASS_NOT_FOUND            2
+#define SLAP_SCHERR_CLASS_BAD_USAGE            3
+#define SLAP_SCHERR_CLASS_BAD_SUP              4
+#define SLAP_SCHERR_CLASS_DUP                  5
+#define SLAP_SCHERR_ATTR_NOT_FOUND             6
+#define SLAP_SCHERR_ATTR_BAD_USAGE             7
+#define SLAP_SCHERR_ATTR_BAD_SUP               8
+#define SLAP_SCHERR_ATTR_INCOMPLETE            9
+#define SLAP_SCHERR_ATTR_DUP                   10
+#define SLAP_SCHERR_MR_NOT_FOUND               11
+#define SLAP_SCHERR_MR_INCOMPLETE              12
+#define SLAP_SCHERR_MR_DUP                             13
+#define SLAP_SCHERR_SYN_NOT_FOUND              14
+#define SLAP_SCHERR_SYN_DUP                            15
+#define SLAP_SCHERR_NO_NAME                            16
+#define SLAP_SCHERR_NOT_SUPPORTED              17
+#define SLAP_SCHERR_BAD_DESCR                  18
+#define SLAP_SCHERR_OIDM                               19
+#define SLAP_SCHERR_LAST                               SLAP_SCHERR_OIDM
 
 typedef union slap_sockaddr {
        struct sockaddr sa_addr;
@@ -431,6 +433,11 @@ typedef struct slap_attribute_type {
        Syntax                                  *sat_syntax;
 
        AttributeTypeSchemaCheckFN      *sat_check;
+
+#define SLAP_AT_NONE           0x0000U
+#define SLAP_AT_ABSTRACT       0x0100U /* cannot be instantiated */
+#define SLAP_AT_FINAL          0x0200U /* cannot be subtyped */
+#define SLAP_AT_HIDE           0x8000U /* hide attribute */
        slap_mask_t                                     sat_flags;
 
        struct slap_attribute_type      *sat_next;
@@ -489,13 +496,15 @@ typedef struct slap_object_class {
        struct slap_object_class        *soc_next;
 } ObjectClass;
 
-#define        SLAP_OC_ALIAS           0x01
-#define        SLAP_OC_REFERRAL        0x02
-#define        SLAP_OC_SUBENTRY        0x04
-#define        SLAP_OC_DYNAMICOBJECT   0x08
-#define        SLAP_OC_COLLECTIVEATTRIBUTESUBENTRY     0x10
-#define        SLAP_OC__MASK           0x1F
-#define        SLAP_OC__END            0x20
+#define        SLAP_OC_ALIAS           0x0001
+#define        SLAP_OC_REFERRAL        0x0002
+#define        SLAP_OC_SUBENTRY        0x0004
+#define        SLAP_OC_DYNAMICOBJECT   0x0008
+#define        SLAP_OC_COLLECTIVEATTRIBUTESUBENTRY     0x0010
+#define        SLAP_OC__MASK           0x001F
+#define        SLAP_OC__END            0x0020
+#define SLAP_OC_OPERATIONAL    0x4000
+#define SLAP_OC_HIDE           0x8000
 
 #ifdef LDAP_EXTENDED_SCHEMA
 /*
diff --git a/servers/slapd/syntax.c b/servers/slapd/syntax.c
new file mode 100644 (file)
index 0000000..eea2e1b
--- /dev/null
@@ -0,0 +1,240 @@
+/* syntax.c - routines to manage syntax definitions */
+/* $OpenLDAP$ */
+/*
+ * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+
+#include "portable.h"
+
+#include <stdio.h>
+
+#include <ac/ctype.h>
+#include <ac/string.h>
+#include <ac/socket.h>
+
+#include "slap.h"
+#include "ldap_pvt.h"
+
+
+struct sindexrec {
+       char            *sir_name;
+       Syntax          *sir_syn;
+};
+
+static Avlnode *syn_index = NULL;
+static Syntax *syn_list = NULL;
+
+static int
+syn_index_cmp(
+    struct sindexrec   *sir1,
+    struct sindexrec   *sir2
+)
+{
+       return (strcmp( sir1->sir_name, sir2->sir_name ));
+}
+
+static int
+syn_index_name_cmp(
+    const char         *name,
+    struct sindexrec   *sir
+)
+{
+       return (strcmp( name, sir->sir_name ));
+}
+
+Syntax *
+syn_find( const char *synname )
+{
+       struct sindexrec        *sir = NULL;
+
+       if ( (sir = (struct sindexrec *) avl_find( syn_index, synname,
+           (AVL_CMP) syn_index_name_cmp )) != NULL ) {
+               return( sir->sir_syn );
+       }
+       return( NULL );
+}
+
+Syntax *
+syn_find_desc( const char *syndesc, int *len )
+{
+       Syntax          *synp;
+
+       for (synp = syn_list; synp; synp = synp->ssyn_next)
+               if ((*len = dscompare( synp->ssyn_syn.syn_desc, syndesc, '{')))
+                       return synp;
+       return( NULL );
+}
+
+void
+syn_destroy( void )
+{
+       Syntax *s, *n;
+
+       avl_free(syn_index, ldap_memfree);
+       for (s=syn_list; s; s=n) {
+               n = s->ssyn_next;
+               ldap_syntax_free((LDAPSyntax *)s);
+       }
+}
+
+static int
+syn_insert(
+    Syntax             *ssyn,
+    const char         **err
+)
+{
+       Syntax          **synp;
+       struct sindexrec        *sir;
+
+       synp = &syn_list;
+       while ( *synp != NULL ) {
+               synp = &(*synp)->ssyn_next;
+       }
+       *synp = ssyn;
+
+       if ( ssyn->ssyn_oid ) {
+               sir = (struct sindexrec *)
+                       ch_calloc( 1, sizeof(struct sindexrec) );
+               sir->sir_name = ssyn->ssyn_oid;
+               sir->sir_syn = ssyn;
+               if ( avl_insert( &syn_index, (caddr_t) sir,
+                                (AVL_CMP) syn_index_cmp,
+                                (AVL_DUP) avl_dup_error ) ) {
+                       *err = ssyn->ssyn_oid;
+                       ldap_memfree(sir);
+                       return SLAP_SCHERR_SYN_DUP;
+               }
+               /* FIX: temporal consistency check */
+               syn_find(sir->sir_name);
+       }
+       return 0;
+}
+
+int
+syn_add(
+    LDAPSyntax         *syn,
+       unsigned flags,
+    slap_syntax_validate_func  *validate,
+    slap_syntax_transform_func *normalize,
+    slap_syntax_transform_func *pretty,
+#ifdef SLAPD_BINARY_CONVERSION
+    slap_syntax_transform_func *ber2str,
+    slap_syntax_transform_func *str2ber,
+#endif
+    const char         **err
+)
+{
+       Syntax          *ssyn;
+       int             code;
+
+       ssyn = (Syntax *) ch_calloc( 1, sizeof(Syntax) );
+
+       AC_MEMCPY( &ssyn->ssyn_syn, syn, sizeof(LDAPSyntax) );
+
+       ssyn->ssyn_next = NULL;
+
+       ssyn->ssyn_oidlen = strlen(syn->syn_oid);
+       ssyn->ssyn_flags = flags;
+       ssyn->ssyn_validate = validate;
+       ssyn->ssyn_normalize = normalize;
+       ssyn->ssyn_pretty = pretty;
+
+#ifdef SLAPD_BINARY_CONVERSION
+       ssyn->ssyn_ber2str = ber2str;
+       ssyn->ssyn_str2ber = str2ber;
+#endif
+
+       code = syn_insert(ssyn, err);
+       return code;
+}
+
+int
+register_syntax(
+       const char * desc,
+       unsigned flags,
+       slap_syntax_validate_func *validate,
+       slap_syntax_transform_func *normalize,
+       slap_syntax_transform_func *pretty )
+{
+       LDAPSyntax      *syn;
+       int             code;
+       const char      *err;
+
+       syn = ldap_str2syntax( desc, &code, &err, LDAP_SCHEMA_ALLOW_ALL);
+       if ( !syn ) {
+#ifdef NEW_LOGGING
+               LDAP_LOG(( "schema", LDAP_LEVEL_ERR,
+                          "register_syntax: Error - %s before %s in %s.\n",
+                          ldap_scherr2str(code), err, desc ));
+#else
+               Debug( LDAP_DEBUG_ANY, "Error in register_syntax: %s before %s in %s\n",
+                   ldap_scherr2str(code), err, desc );
+#endif
+
+               return( -1 );
+       }
+
+       code = syn_add( syn, flags, validate, normalize, pretty, &err );
+
+       ldap_memfree( syn );
+
+       if ( code ) {
+#ifdef NEW_LOGGING
+               LDAP_LOG(( "schema", LDAP_LEVEL_ERR,
+                          "register_syntax: Error - %s %s in %s\n",
+                          scherr2str(code), err, desc ));
+#else
+               Debug( LDAP_DEBUG_ANY, "Error in register_syntax: %s %s in %s\n",
+                   scherr2str(code), err, desc );
+#endif
+
+               return( -1 );
+       }
+
+       return( 0 );
+}
+
+#if defined( SLAPD_SCHEMA_DN )
+
+int
+syn_schema_info( Entry *e )
+{
+       struct berval   vals[2];
+       Syntax          *syn;
+
+       AttributeDescription *ad_ldapSyntaxes = slap_schema.si_ad_ldapSyntaxes;
+
+       vals[1].bv_val = NULL;
+
+       for ( syn = syn_list; syn; syn = syn->ssyn_next ) {
+               if ( ! syn->ssyn_validate ) {
+                       /* skip syntaxes without validators */
+                       continue;
+               }
+               if ( syn->ssyn_flags & SLAP_SYNTAX_HIDE ) {
+                       /* hide syntaxes */
+                       continue;
+               }
+
+               if ( ldap_syntax2bv( &syn->ssyn_syn, vals ) == NULL ) {
+                       return -1;
+               }
+#if 0
+#ifdef NEW_LOGGING
+               LDAP_LOG(( "schema", LDAP_LEVEL_ENTRY,
+                          "syn_schema_info: Merging syn [%ld] %s\n",
+                          (long)vals[0].bv_len, vals[0].bv_val ));
+#else
+               Debug( LDAP_DEBUG_TRACE, "Merging syn [%ld] %s\n",
+              (long) vals[0].bv_len, vals[0].bv_val, 0 );
+#endif
+
+#endif
+               attr_merge( e, ad_ldapSyntaxes, vals );
+               ldap_memfree( vals[0].bv_val );
+       }
+       return 0;
+}
+
+#endif