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);
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 ) {
}
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 );
}
}
- 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 );
}
}
--- /dev/null
+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$
-.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
.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
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
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.
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
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
.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
.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>
.B compare <pathname> <argument>...
.nf
COMPARE
-opid: <operation ID>
-msgid: <message ID>
+msgid: <message id>
<repeat { "suffix:" <database suffix DN> }>
dn: <DN>
<attribute>: <value>
.B delete <pathname> <argument>...
.nf
DELETE
-opid: <operation ID>
-msgid: <message ID>
+msgid: <message id>
<repeat { "suffix:" <database suffix DN> }>
dn: <DN>
.fi
.B modify <pathname> <argument>...
.nf
MODIFY
-opid: <operation ID>
-msgid: <message ID>
+msgid: <message id>
<repeat { "suffix:" <database suffix DN> }>
dn: <DN>
<repeat {
.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>
.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>
.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
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
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 ) {
--- /dev/null
+/* $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 */
+}
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",
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;
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;
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 );
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 ) {
break;
default:
- return( LDAP_PARAM_ERROR );
+ return LDAP_PARAM_ERROR;
}
bv->bv_val = LDAP_MALLOC( l + 1 );
+/* $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;
+}
--- /dev/null
+/* $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;
+}
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 ) {
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 */
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;
+/* $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 );
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 );
}
}
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;
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 );
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 );
}
}
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 );
}
ldap_sort_values(
LDAP *ld,
char **vals,
- int (*cmp)()
+ int (*cmp) (LDAP_CONST void *, LDAP_CONST void *)
)
{
int nel;
--- /dev/null
+/*
+ * 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);
+}
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)
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)
--- /dev/null
+/*
+ * 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);
+}
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
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
{
(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);
(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);
/* 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;
+ }
}
/*
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 );
#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,
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;
}
/* 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 */
/* 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 );
/* 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 );
/* 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 );
/* 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 );
/* 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 );
/* 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 );
/* 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 );
/* 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 : "") );
#include <ac/string.h>
#include <ac/ctype.h>
+#include <ac/signal.h>
#include <ac/socket.h>
#include <ac/errno.h>
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;
"%s: line %d: old objectclass format not supported.\n",
fname, lineno, 0 );
#endif
-
}
/* specify an attribute type */
}
}
+#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;
#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
}
#endif
+ slap_daemon.sd_nactives++;
+
FD_SET( s, &slap_daemon.sd_actives );
FD_SET( s, &slap_daemon.sd_readers );
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",
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) {
}
+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
}
}
+#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 );
#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;
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;
Backend *be,
Connection *conn,
Operation *op,
- Entry *e,
+ Attribute *a,
MatchingRuleAssertion *mra,
char ***e_flags
);
Backend *be,
Connection *conn,
Operation *op,
- Entry *e,
+ Attribute *a,
ValuesReturnFilter *f,
char ***e_flags
);
Backend *be,
Connection *conn,
Operation *op,
- Entry *e,
+ Attribute *a,
AttributeDescription *desc,
char ***e_flags
);
Backend *be,
Connection *conn,
Operation *op,
- Entry *e,
+ Attribute *a,
AttributeAssertion *ava,
int type,
char ***e_flags
Backend *be,
Connection *conn,
Operation *op,
- Entry *e,
+ Attribute *a,
char ***e_flags
)
{
#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;
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;
#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;
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;
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;
#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;
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;
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 ) ) {
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;
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 ) ) {
(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);
(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);
--- /dev/null
+/* 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
#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;
}
Backend *be,
Connection *conn,
Operation *op,
- Entry *e,
+ Attribute *a,
char ***e_flags );
/*
/* 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 ));
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;
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
/* 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 ) {
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;
}
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,
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;
}
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
"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' "
"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 }
};
"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 */
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' "
"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 */
"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' "
"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' "
"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' "
"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
"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' "
"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
"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 "
#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
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 :) */
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",
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"
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];
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);
/*
* 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;
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;
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
/*
--- /dev/null
+/* 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