---
-Portions Copyright 1999-2005 Howard Y.H. Chu.
-Portions Copyright 1999-2005 Symas Corporation.
+Portions Copyright 1999-2007 Howard Y.H. Chu.
+Portions Copyright 1999-2007 Symas Corporation.
Portions Copyright 1998-2003 Hallvard B. Furuseth.
+Portions Copyright 2007 Gavin Henry
+Portions Copyright 2007 Suretec Systems
All rights reserved.
Redistribution and use in source and binary forms, with or without
SLAPD:
BDB and HDB backends require Sleepycat Berkeley DB 4.2 or later
- SLURPD:
- LTHREAD compatible thread package
- [POSIX threads, Mach Cthreads, select others]
-
CLIENTS/CONTRIB ware:
Depends on package. See per package README.
# configuration script generated by Autoconf, and is distributable
# under the same distributions terms as OpenLDAP itself.
-## Copyright 1998-2007 The OpenLDAP Foundation.
+## Portions Copyright 1998-2007 The OpenLDAP Foundation.
## All rights reserved.
##
## Redistribution and use in source and binary forms, with or without
# configuration script generated by Autoconf, and is distributable
# under the same distributions terms as OpenLDAP itself.
-## Copyright 1998-2007 The OpenLDAP Foundation.
+## Portions Copyright 1998-2007 The OpenLDAP Foundation.
## All rights reserved.
##
## Redistribution and use in source and binary forms, with or without
# This file is distributed with OpenLDAP Software, which contains a
# configuration script generated by Autoconf, and is distributable
-# under the same distributions terms as OpenLDAP inself.
+# under the same distributions terms as OpenLDAP itself.
-## Copyright 1998-2007 The OpenLDAP Foundation.
+## Portions Copyright 1998-2007 The OpenLDAP Foundation.
## All rights reserved.
##
## Redistribution and use in source and binary forms, with or without
done
rm -f conftest*
])
+ test "$ol_cv_mkdep" = no && OL_MKDEP=":"
else
cc_cv_mkdep=yes
OL_MKDEP_FLAGS="${MKDEP_FLAGS}"
}
#if (DB_VERSION_MAJOR > 3) || (DB_VERSION_MINOR >= 1)
- rc = env->open( env, NULL, flags, 0 );
+ rc = (env->open)( env, NULL, flags, 0 );
#else
- rc = env->open( env, NULL, NULL, flags, 0 );
+ rc = (env->open)( env, NULL, NULL, flags, 0 );
#endif
if ( rc == 0 ) {
])
dnl
dnl ====================================================================
-dnl Check if GDBM library exists
-dnl Check for gdbm_open in standard libraries or -lgdbm
-dnl
-dnl defines ol_cv_lib_gdbm to 'yes' or '-lgdbm' or 'no'
-dnl 'yes' implies gdbm_open is in $LIBS
-dnl
-dnl uses:
-dnl AC_CHECK_FUNC(gdbm_open)
-dnl AC_CHECK_LIB(gdbm,gdbm_open)
-dnl
-AC_DEFUN([OL_LIB_GDBM],
-[AC_CACHE_CHECK(for GDBM library, [ol_cv_lib_gdbm],
-[ ol_LIBS="$LIBS"
- AC_CHECK_FUNC(gdbm_open,[ol_cv_lib_gdbm=yes], [
- AC_CHECK_LIB(gdbm,gdbm_open,[ol_cv_lib_gdbm=-lgdbm],[ol_cv_lib_gdbm=no])
- ])
- LIBS="$ol_LIBS"
-])
-])dnl
-dnl
-dnl --------------------------------------------------------------------
-dnl Check if GDBM exists
-dnl
-dnl defines ol_cv_gdbm to 'yes' or 'no'
-dnl
-dnl uses:
-dnl OL_LIB_GDBM
-dnl AC_CHECK_HEADERS(gdbm.h)
-dnl
-AC_DEFUN([OL_GDBM],
-[AC_REQUIRE([OL_LIB_GDBM])
- AC_CHECK_HEADERS(gdbm.h)
- AC_CACHE_CHECK(for db, [ol_cv_gdbm], [
- if test $ol_cv_lib_gdbm = no || test $ac_cv_header_gdbm_h = no ; then
- ol_cv_gdbm=no
- else
- ol_cv_gdbm=yes
- fi
-])
- if test $ol_cv_gdbm = yes ; then
- AC_DEFINE(HAVE_GDBM,1, [define if GNU DBM is available])
- fi
-])dnl
-dnl
-dnl ====================================================================
-dnl Check if MDBM library exists
-dnl Check for mdbm_open in standard libraries or -lmdbm
-dnl
-dnl defines ol_cv_lib_mdbm to 'yes' or '-lmdbm' or 'no'
-dnl 'yes' implies mdbm_open is in $LIBS
-dnl
-dnl uses:
-dnl AC_CHECK_FUNC(mdbm_set_chain)
-dnl AC_CHECK_LIB(mdbm,mdbm_set_chain)
-dnl
-AC_DEFUN([OL_LIB_MDBM],
-[AC_CACHE_CHECK(for MDBM library, [ol_cv_lib_mdbm],
-[ ol_LIBS="$LIBS"
- AC_CHECK_FUNC(mdbm_set_chain,[ol_cv_lib_mdbm=yes], [
- AC_CHECK_LIB(mdbm,mdbm_set_chain,[ol_cv_lib_mdbm=-lmdbm],[ol_cv_lib_mdbm=no])
- ])
- LIBS="$ol_LIBS"
-])
-])dnl
-dnl
-dnl --------------------------------------------------------------------
-dnl Check if MDBM exists
-dnl
-dnl defines ol_cv_mdbm to 'yes' or 'no'
-dnl
-dnl uses:
-dnl OL_LIB_MDBM
-dnl AC_CHECK_HEADERS(mdbm.h)
-dnl
-AC_DEFUN([OL_MDBM],
-[AC_REQUIRE([OL_LIB_MDBM])
- AC_CHECK_HEADERS(mdbm.h)
- AC_CACHE_CHECK(for db, [ol_cv_mdbm], [
- if test $ol_cv_lib_mdbm = no || test $ac_cv_header_mdbm_h = no ; then
- ol_cv_mdbm=no
- else
- ol_cv_mdbm=yes
- fi
-])
- if test $ol_cv_mdbm = yes ; then
- AC_DEFINE(HAVE_MDBM,1, [define if MDBM is available])
- fi
-])dnl
-dnl
-dnl ====================================================================
-dnl Check if NDBM library exists
-dnl Check for dbm_open in standard libraries or -lndbm or -ldbm
-dnl
-dnl defines ol_cv_lib_ndbm to 'yes' or '-lndbm' or -ldbm or 'no'
-dnl 'yes' implies ndbm_open is in $LIBS
-dnl
-dnl uses:
-dnl AC_CHECK_FUNC(dbm_open)
-dnl AC_CHECK_LIB(ndbm,dbm_open)
-dnl AC_CHECK_LIB(dbm,dbm_open)
-dnl
-dnl restrictions:
-dnl should also check SVR4 case: dbm_open() in -lucb but that
-dnl would requiring dealing with -L/usr/ucblib
-dnl
-AC_DEFUN([OL_LIB_NDBM],
-[AC_CACHE_CHECK(for NDBM library, [ol_cv_lib_ndbm],
-[ ol_LIBS="$LIBS"
- AC_CHECK_FUNC(dbm_open,[ol_cv_lib_ndbm=yes], [
- AC_CHECK_LIB(ndbm,dbm_open,[ol_cv_lib_ndbm=-lndbm], [
- AC_CHECK_LIB(dbm,dbm_open,[ol_cv_lib_ndbm=-ldbm],
- [ol_cv_lib_ndbm=no])dnl
- ])
- ])
- LIBS="$ol_LIBS"
-])
-])dnl
-dnl
-dnl --------------------------------------------------------------------
-dnl Check if NDBM exists
-dnl
-dnl defines ol_cv_ndbm to 'yes' or 'no'
-dnl
-dnl uses:
-dnl OL_LIB_NDBM
-dnl AC_CHECK_HEADERS(ndbm.h)
-dnl
-dnl restrictions:
-dnl Doesn't handle SVR4 case (see above)
-dnl
-AC_DEFUN([OL_NDBM],
-[AC_REQUIRE([OL_LIB_NDBM])
- AC_CHECK_HEADERS(ndbm.h)
- AC_CACHE_CHECK(for db, [ol_cv_ndbm], [
- if test $ol_cv_lib_ndbm = no || test $ac_cv_header_ndbm_h = no ; then
- ol_cv_ndbm=no
- else
- ol_cv_ndbm=yes
- fi
-])
- if test $ol_cv_ndbm = yes ; then
- AC_DEFINE(HAVE_NDBM,1, [define if NDBM is available])
- fi
-])dnl
-dnl
-dnl ====================================================================
dnl Check POSIX Thread version
dnl
dnl defines ol_cv_pthread_version to 4, 5, 6, 7, 8, 10, depending on the
LDAP_L = $(LDAP_LIBLUTIL_A) \
$(LDAP_LIBLDAP_LA) $(LDAP_LIBLBER_LA)
-SLURPD_L = $(LDAP_LIBLUTIL_A) \
- $(LDAP_LIBLDAP_R_LA) $(LDAP_LIBLBER_LA)
SLAPD_L = $(LDAP_LIBLUNICODE_A) $(LDAP_LIBREWRITE_A) \
- $(SLURPD_L)
+ $(LDAP_LIBLUTIL_A) $(LDAP_LIBLDAP_R_LA) $(LDAP_LIBLBER_LA)
WRAP_LIBS = @WRAP_LIBS@
# AutoConfig generated
SLAPD_SQL_LIBS = @SLAPD_SQL_LIBS@
SLAPD_LIBS = @SLAPD_LIBS@ @SLAPD_PERL_LDFLAGS@ @SLAPD_SQL_LDFLAGS@ @SLAPD_SQL_LIBS@ @SLAPD_SLP_LIBS@ @SLAPD_GMP_LIBS@ $(ICU_LIBS)
-SLURPD_LIBS = @SLURPD_LIBS@
# Our Defaults
CC = $(AC_CC)
#include <ac/unistd.h>
#include <ac/errno.h>
#include <ac/time.h>
+#include <ac/socket.h>
#ifdef HAVE_CYRUS_SASL
#ifdef HAVE_SASL_SASL_H
static int chainingResolve = -1;
static int chainingContinuation = -1;
#endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
+#ifdef LDAP_CONTROL_X_SESSION_TRACKING
+static int sessionTracking = 0;
+struct berval stValue;
+#endif /* LDAP_CONTROL_X_SESSION_TRACKING */
+
+LDAPControl *unknown_ctrls = NULL;
+int unknown_ctrls_num = 0;
/* options */
struct timeval nettimeout = { -1 , 0 };
static int gotintr;
static int abcan;
+
+#ifdef LDAP_CONTROL_X_SESSION_TRACKING
+static int
+st_value( LDAP *ld, struct berval *value )
+{
+ char *ip = NULL, *name = NULL;
+ struct berval id = { 0 };
+ char namebuf[ MAXHOSTNAMELEN ];
+
+ if ( gethostname( namebuf, sizeof( namebuf ) ) == 0 ) {
+ struct hostent *h;
+ struct in_addr addr;
+
+ name = namebuf;
+
+ h = gethostbyname( name );
+ if ( h != NULL ) {
+ AC_MEMCPY( &addr, h->h_addr, sizeof( addr ) );
+ ip = inet_ntoa( addr );
+ }
+ }
+
+#ifdef HAVE_CYRUS_SASL
+ if ( sasl_authz_id != NULL ) {
+ ber_str2bv( sasl_authz_id, 0, 0, &id );
+
+ } else if ( sasl_authc_id != NULL ) {
+ ber_str2bv( sasl_authc_id, 0, 0, &id );
+
+ } else
+#endif /* HAVE_CYRUS_SASL */
+ if ( binddn != NULL ) {
+ ber_str2bv( binddn, 0, 0, &id );
+ }
+
+ if ( ldap_create_session_tracking_value( ld,
+ ip, name, LDAP_CONTROL_X_SESSION_TRACKING_USERNAME,
+ &id, &stValue ) )
+ {
+ fprintf( stderr, _("Session tracking control encoding error!\n") );
+ return -1;
+ }
+
+ return 0;
+}
+#endif /* LDAP_CONTROL_X_SESSION_TRACKING */
+
RETSIGTYPE
do_sig( int sig )
{
{
static const char *const descriptions[] = {
N_(" -c continuous operation mode (do not stop on errors)\n"),
-N_(" -C chase referrals (anonymously)\n"),
N_(" -d level set LDAP debugging level to `level'\n"),
N_(" -D binddn bind DN\n"),
N_(" -e [!]<ext>[=<extparam>] general extensions (! indicates criticality)\n")
#endif
N_(" [!]postread[=<attrs>] (a comma-separated attribute list)\n")
N_(" [!]preread[=<attrs>] (a comma-separated attribute list)\n")
-#ifdef LDAP_DEVEL
N_(" [!]relax\n")
-#endif
+#ifdef LDAP_CONTROL_X_SESSION_TRACKING
+N_(" [!]sessiontracking\n")
+#endif /* LDAP_CONTROL_X_SESSION_TRACKING */
N_(" abandon, cancel, ignore (SIGINT sends abandon/cancel,\n"
" or ignores response; if critical, doesn't wait for SIGINT.\n"
" not really controls)\n")
N_(" -f file read operations from `file'\n"),
N_(" -h host LDAP server\n"),
-N_(" -H URI LDAP Uniform Resource Indentifier(s)\n"),
+N_(" -H URI LDAP Uniform Resource Identifier(s)\n"),
N_(" -I use SASL Interactive mode\n"),
N_(" -M enable Manage DSA IT control (-MM to make critical)\n"),
N_(" -n show what would be done but don't actually do it\n"),
N_(" -o <opt>[=<optparam] general options\n"),
N_(" nettimeout=<timeout> (in seconds, or \"none\" or \"max\")\n"),
N_(" -p port port on LDAP server\n"),
-N_(" -P version procotol version (default: 3)\n"),
+N_(" -P version protocol version (default: 3)\n"),
N_(" -Q use SASL Quiet mode\n"),
N_(" -R realm SASL realm\n"),
N_(" -U authcid SASL authentication identity\n"),
}
binddn = ber_strdup( optarg );
break;
- case 'e': /* general extensions (controls and such) */
+ case 'e': /* general extensions (controls and such) */
/* should be extended to support comma separated list of
* [!]key[=value] parameters, e.g. -e !foo,bar=567
*/
gotintr = abcan;
}
+#ifdef LDAP_CONTROL_X_SESSION_TRACKING
+ } else if ( strcasecmp( control, "sessiontracking" ) == 0 ) {
+ if ( sessionTracking ) {
+ fprintf( stderr, "%s: session tracking can be only specified once\n", prog );
+ exit( EXIT_FAILURE );
+ }
+ sessionTracking = 1;
+#endif /* LDAP_CONTROL_X_SESSION_TRACKING */
+
+ } else if ( tool_is_oid( control ) ) {
+ LDAPControl *tmpctrls, ctrl;
+
+ tmpctrls = (LDAPControl *)realloc( unknown_ctrls,
+ (unknown_ctrls_num + 1)*sizeof( LDAPControl ) );
+ if ( tmpctrls == NULL ) {
+ fprintf( stderr, "%s: no memory?\n", prog );
+ exit( EXIT_FAILURE );
+ }
+ unknown_ctrls = tmpctrls;
+ ctrl.ldctl_oid = control;
+ ctrl.ldctl_value.bv_val = NULL;
+ ctrl.ldctl_value.bv_len = 0;
+ ctrl.ldctl_iscritical = crit;
+
+ if ( cvalue != NULL ) {
+ struct berval bv;
+ size_t len = strlen( cvalue );
+ int retcode;
+
+ bv.bv_len = LUTIL_BASE64_DECODE_LEN( len );
+ bv.bv_val = ber_memalloc( bv.bv_len + 1 );
+
+ retcode = lutil_b64_pton( cvalue,
+ (unsigned char *)bv.bv_val,
+ bv.bv_len );
+
+ if ( retcode == -1 || retcode > bv.bv_len ) {
+ fprintf( stderr, "Unable to parse value of general control %s\n",
+ control );
+ usage();
+ }
+
+ bv.bv_len = retcode;
+ ctrl.ldctl_value = bv;
+ }
+
+ unknown_ctrls[ unknown_ctrls_num ] = ctrl;
+ unknown_ctrls_num++;
+
} else {
fprintf( stderr, "Invalid general control name: %s\n",
control );
#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
chaining ||
#endif
+#ifdef LDAP_CONTROL_X_SESSION_TRACKING
+ sessionTracking ||
+#endif /* LDAP_CONTROL_X_SESSION_TRACKING */
noop || ppolicy || preread || postread )
{
fprintf( stderr, "%s: -e/-M incompatible with LDAPv2\n", prog );
url.lud_scope = LDAP_SCOPE_DEFAULT;
ldapuri = ldap_url_desc2str( &url );
+
+ } else if ( ldapuri != NULL ) {
+ LDAPURLDesc *ludlist, **ludp;
+ char **urls = NULL;
+ int nurls = 0;
+
+ rc = ldap_url_parselist( &ludlist, ldapuri );
+ if ( rc != LDAP_URL_SUCCESS ) {
+ fprintf( stderr,
+ "Could not parse LDAP URI(s)=%s (%d)\n",
+ ldapuri, rc );
+ exit( EXIT_FAILURE );
+ }
+
+ for ( ludp = &ludlist; *ludp != NULL; ) {
+ LDAPURLDesc *lud = *ludp;
+ char **tmp;
+
+ if ( lud->lud_dn != NULL && lud->lud_dn[ 0 ] != '\0' &&
+ ( lud->lud_host == NULL || lud->lud_host[0] == '\0' ) )
+ {
+ /* if no host but a DN is provided,
+ * use DNS SRV to gather the host list
+ * and turn it into a list of URIs
+ * using the scheme provided */
+ char *domain = NULL,
+ *hostlist = NULL,
+ **hosts = NULL;
+ int i,
+ len_proto = strlen( lud->lud_scheme );
+
+ if ( ldap_dn2domain( lud->lud_dn, &domain )
+ || domain == NULL )
+ {
+ fprintf( stderr,
+ "DNS SRV: Could not turn "
+ "DN=\"%s\" into a domain\n",
+ lud->lud_dn );
+ goto dnssrv_free;
+ }
+
+ rc = ldap_domain2hostlist( domain, &hostlist );
+ if ( rc ) {
+ fprintf( stderr,
+ "DNS SRV: Could not turn "
+ "domain=%s into a hostlist\n",
+ domain );
+ goto dnssrv_free;
+ }
+
+ hosts = ldap_str2charray( hostlist, " " );
+ if ( hosts == NULL ) {
+ fprintf( stderr,
+ "DNS SRV: Could not parse "
+ "hostlist=\"%s\"\n",
+ hostlist );
+ goto dnssrv_free;
+ }
+
+ for ( i = 0; hosts[ i ] != NULL; i++ )
+ /* count'em */ ;
+
+ tmp = (char **)realloc( urls, sizeof( char * ) * ( nurls + i + 1 ) );
+ if ( tmp == NULL ) {
+ fprintf( stderr,
+ "DNS SRV: out of memory?\n" );
+ goto dnssrv_free;
+ }
+ urls = tmp;
+ urls[ nurls ] = NULL;
+
+ for ( i = 0; hosts[ i ] != NULL; i++ ) {
+ size_t len = len_proto
+ + STRLENOF( "://" )
+ + strlen( hosts[ i ] )
+ + 1;
+
+ urls[ nurls + i + 1 ] = NULL;
+ urls[ nurls + i ] = (char *)malloc( sizeof( char ) * len );
+ if ( urls[ nurls + i ] == NULL ) {
+ fprintf( stderr,
+ "DNS SRV: out of memory?\n" );
+ goto dnssrv_free;
+ }
+
+ snprintf( urls[ nurls + i ], len, "%s://%s",
+ lud->lud_scheme, hosts[ i ] );
+ }
+ nurls += i;
+
+dnssrv_free:;
+ ber_memvfree( (void **)hosts );
+ ber_memfree( hostlist );
+ ber_memfree( domain );
+
+ } else {
+ tmp = (char **)realloc( urls, sizeof( char * ) * ( nurls + 2 ) );
+ if ( tmp == NULL ) {
+ fprintf( stderr,
+ "DNS SRV: out of memory?\n" );
+ break;
+ }
+ urls = tmp;
+ urls[ nurls + 1 ] = NULL;
+
+ urls[ nurls ] = ldap_url_desc2str( lud );
+ if ( urls[ nurls ] == NULL ) {
+ fprintf( stderr,
+ "DNS SRV: out of memory?\n" );
+ break;
+ }
+ nurls++;
+ }
+
+ *ludp = lud->lud_next;
+
+ lud->lud_next = NULL;
+ ldap_free_urldesc( lud );
+ }
+
+ if ( ludlist != NULL ) {
+ ldap_free_urllist( ludlist );
+ exit( EXIT_FAILURE );
+
+ } else if ( urls == NULL ) {
+ exit( EXIT_FAILURE );
+ }
+
+ ldap_memfree( ldapuri );
+ ldapuri = ldap_charray2str( urls, " " );
+ ber_memvfree( (void **)urls );
}
if ( verbose ) {
tool_bind( LDAP *ld )
{
LDAPControl **sctrlsp = NULL;
- LDAPControl *sctrls[2];
+ LDAPControl *sctrls[3];
+ LDAPControl sctrl[3];
int nsctrls = 0;
#ifdef LDAP_CONTROL_PASSWORDPOLICYREQUEST
- LDAPControl c;
if ( ppolicy ) {
+ LDAPControl c;
c.ldctl_oid = LDAP_CONTROL_PASSWORDPOLICYREQUEST;
c.ldctl_value.bv_val = NULL;
c.ldctl_value.bv_len = 0;
c.ldctl_iscritical = 0;
- sctrls[nsctrls] = &c;
+ sctrl[nsctrls] = c;
+ sctrls[nsctrls] = &sctrl[nsctrls];
sctrls[++nsctrls] = NULL;
}
#endif
+#ifdef LDAP_CONTROL_X_SESSION_TRACKING
+ if ( sessionTracking ) {
+ LDAPControl c;
+
+ if (stValue.bv_val == NULL && st_value( ld, &stValue ) ) {
+ exit( EXIT_FAILURE );
+ }
+
+ c.ldctl_oid = LDAP_CONTROL_X_SESSION_TRACKING;
+ c.ldctl_iscritical = 0;
+ ber_dupbv( &c.ldctl_value, &stValue );
+
+ sctrl[nsctrls] = c;
+ sctrls[nsctrls] = &sctrl[nsctrls];
+ sctrls[++nsctrls] = NULL;
+ }
+#endif /* LDAP_CONTROL_X_SESSION_TRACKING */
+
if ( nsctrls ) {
sctrlsp = sctrls;
}
rc = ldap_parse_result( ld, result, &err, &matched, &info, &refs,
&ctrls, 1 );
if ( rc != LDAP_SUCCESS ) {
- tool_perror( "ldap_bind parse result", rc, NULL, NULL, NULL, NULL );
+ tool_perror( "ldap_bind parse result", rc, NULL, matched, info, refs );
exit( LDAP_LOCAL_ERROR );
}
int expire, grace, len = 0;
LDAPPasswordPolicyError pErr = -1;
- ctrl = ldap_find_control( LDAP_CONTROL_PASSWORDPOLICYRESPONSE,
- ctrls );
+ ctrl = ldap_control_find( LDAP_CONTROL_PASSWORDPOLICYRESPONSE,
+ ctrls, NULL );
if ( ctrl && ldap_parse_passwordpolicy_control( ld, ctrl,
&expire, &grace, &pErr ) == LDAP_SUCCESS )
tool_server_controls( LDAP *ld, LDAPControl *extra_c, int count )
{
int i = 0, j, crit = 0, err;
- LDAPControl c[10], **ctrls;
+ LDAPControl c[16], **ctrls;
if ( ! ( assertctl
|| authzid
|| manageDIT
|| manageDSAit
|| noop
+#ifdef LDAP_CONTROL_PASSWORDPOLICYREQUEST
+ || ppolicy
+#endif
|| preread
|| postread
#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
|| chaining
#endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
- || count ) )
+#ifdef LDAP_CONTROL_X_SESSION_TRACKING
+ || sessionTracking
+#endif /* LDAP_CONTROL_X_SESSION_TRACKING */
+ || count
+ || unknown_ctrls_num ) )
{
return;
}
- ctrls = (LDAPControl**) malloc(sizeof(c) + (count+1)*sizeof(LDAPControl*));
+ ctrls = (LDAPControl**) malloc(sizeof(c) + (count + unknown_ctrls_num + 1)*sizeof(LDAPControl*));
if ( ctrls == NULL ) {
fprintf( stderr, "No memory\n" );
exit( EXIT_FAILURE );
i++;
}
+#ifdef LDAP_CONTROL_PASSWORDPOLICYREQUEST
+ if ( ppolicy ) {
+ c[i].ldctl_oid = LDAP_CONTROL_PASSWORDPOLICYREQUEST;
+ BER_BVZERO( &c[i].ldctl_value );
+ c[i].ldctl_iscritical = 0;
+ ctrls[i] = &c[i];
+ i++;
+ }
+#endif
+
if ( preread ) {
char berbuf[LBER_ELEMENT_SIZEOF];
BerElement *ber = (BerElement *)berbuf;
}
#endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
+#ifdef LDAP_CONTROL_X_SESSION_TRACKING
+ if ( sessionTracking ) {
+ if ( stValue.bv_val == NULL && st_value( ld, &stValue ) ) {
+ exit( EXIT_FAILURE );
+ }
+
+ c[i].ldctl_oid = LDAP_CONTROL_X_SESSION_TRACKING;
+ c[i].ldctl_iscritical = 0;
+ ber_dupbv( &c[i].ldctl_value, &stValue );
+
+ ctrls[i] = &c[i];
+ i++;
+ }
+#endif /* LDAP_CONTROL_X_SESSION_TRACKING */
+
while ( count-- ) {
ctrls[i++] = extra_c++;
}
+ for ( count = 0; count < unknown_ctrls_num; count++ ) {
+ ctrls[i++] = &unknown_ctrls[count];
+ }
ctrls[i] = NULL;
err = ldap_set_option( ld, LDAP_OPT_SERVER_CONTROLS, ctrls );
if ( pperr != PP_noError ) {
ptr += snprintf( ptr, sizeof( buf ) - ( ptr - buf ),
- "%serror=%s", ptr == buf ? "" : " ",
+ "%serror=%d (%s)", ptr == buf ? "" : " ",
+ pperr,
ldap_passwordpolicy_err2txt( pperr ) );
}
char *str;
int j;
+ /* FIXME: there might be cases where a control has NULL OID;
+ * this makes little sense, especially when returned by the
+ * server, but libldap happily allows it */
+ if ( ctrls[i]->ldctl_oid == NULL ) {
+ continue;
+ }
+
len = ldif ? 2 : 0;
len += strlen( ctrls[i]->ldctl_oid );
? sizeof("true") : sizeof("false");
/* convert to base64 */
- if ( ctrls[i]->ldctl_value.bv_len ) {
+ if ( !BER_BVISNULL( &ctrls[i]->ldctl_value ) ) {
b64.bv_len = LUTIL_BASE64_ENCODE_LEN(
ctrls[i]->ldctl_value.bv_len ) + 1;
b64.bv_val = ber_memalloc( b64.bv_len + 1 );
char *matcheddn;
char *text;
char **refs;
+ LDAPControl **ctrls = NULL;
if ( dont ) {
return LDAP_SUCCESS;
}
}
- rc = ldap_parse_result( ld, res, &code, &matcheddn, &text, &refs, NULL, 1 );
+ rc = ldap_parse_result( ld, res, &code, &matcheddn, &text, &refs, &ctrls, 1 );
if( rc != LDAP_SUCCESS ) {
fprintf( stderr, "%s: ldap_parse_result: %s (%d)\n",
}
}
- ber_memfree( text );
- ber_memfree( matcheddn );
- ber_memvfree( (void **) refs );
-
/* if we were told to be quiet, use the return value. */
if ( !quiet ) {
if ( code == LDAP_COMPARE_TRUE ) {
}
}
+ if ( ctrls ) {
+ tool_print_ctrls( ld, ctrls );
+ ldap_controls_free( ctrls );
+ }
+
+ ber_memfree( text );
+ ber_memfree( matcheddn );
+ ber_memvfree( (void **) refs );
+
return( code );
}
int id;
int rc, code;
char *matcheddn = NULL, *text = NULL, **refs = NULL;
+ LDAPControl **ctrls = NULL;
LDAPMessage *res;
if ( verbose ) {
}
}
- rc = ldap_parse_result( ld, res, &code, &matcheddn, &text, &refs, NULL, 1 );
+ rc = ldap_parse_result( ld, res, &code, &matcheddn, &text, &refs, &ctrls, 1 );
if( rc != LDAP_SUCCESS ) {
fprintf( stderr, "%s: ldap_parse_result: %s (%d)\n",
}
}
+ if (ctrls) {
+ tool_print_ctrls( ld, ctrls );
+ ldap_controls_free( ctrls );
+ }
+
ber_memfree( text );
ber_memfree( matcheddn );
ber_memvfree( (void **) refs );
main( int argc, char *argv[] )
{
int rc;
- char *user = NULL;
LDAP *ld = NULL;
char *matcheddn = NULL, *text = NULL, **refs = NULL;
+ LDAPControl **ctrls = NULL;
int id, code;
LDAPMessage *res;
argc -= optind;
if ( strcasecmp( argv[ 0 ], "whoami" ) == 0 ) {
- switch ( argc ) {
- case 2:
- user = argv[ 1 ];
-
- case 1:
- break;
-
- default:
- fprintf( stderr, "need [user]\n\n" );
- usage();
- }
-
tool_server_controls( ld, NULL, 0 );
rc = ldap_whoami( ld, NULL, NULL, &id );
}
rc = ldap_parse_result( ld, res,
- &code, &matcheddn, &text, &refs, NULL, 0 );
+ &code, &matcheddn, &text, &refs, &ctrls, 0 );
if ( rc == LDAP_SUCCESS ) {
rc = code;
}
}
}
+ if (ctrls) {
+ tool_print_ctrls( ld, ctrls );
+ ldap_controls_free( ctrls );
+ }
+
ber_memfree( text );
ber_memfree( matcheddn );
ber_memvfree( (void **) refs );
static struct berval BV_MODOPREPLACE = BER_BVC("replace");
static struct berval BV_MODOPDELETE = BER_BVC("delete");
static struct berval BV_MODOPINCREMENT = BER_BVC("increment");
-static struct berval BV_MODSEP = BER_BVC("-");
static struct berval BV_NEWRDN = BER_BVC("newrdn");
static struct berval BV_DELETEOLDRDN = BER_BVC("deleteoldrdn");
static struct berval BV_NEWSUP = BER_BVC("newsuperior");
fprintf( rejfp, "\n%s\n", rejbuf );
}
- if (rejfp) free( rejbuf );
+ if (rejfp) ber_memfree( rejbuf );
}
- free( rbuf );
+ ber_memfree( rbuf );
#ifdef LDAP_X_TXN
if( retval == 0 && txn ) {
if ( matched ) ldap_memfree( matched );
if ( text ) ber_memvfree( (void **)refs );
- if ( ctrls != NULL ) {
+ if ( ctrls ) {
tool_print_ctrls( ld, ctrls );
ldap_controls_free( ctrls );
}
{
int rc, code, id;
char *matcheddn=NULL, *text=NULL, **refs=NULL;
+ LDAPControl **ctrls = NULL;
LDAPMessage *res;
if ( verbose ) {
}
}
- rc = ldap_parse_result( ld, res, &code, &matcheddn, &text, &refs, NULL, 1 );
+ rc = ldap_parse_result( ld, res, &code, &matcheddn, &text, &refs, &ctrls, 1 );
if( rc != LDAP_SUCCESS ) {
fprintf( stderr, "%s: ldap_parse_result: %s (%d)\n",
}
}
+ if (ctrls) {
+ tool_print_ctrls( ld, ctrls );
+ ldap_controls_free( ctrls );
+ }
+
ber_memfree( text );
ber_memfree( matcheddn );
ber_memvfree( (void **) refs );
char *matcheddn = NULL, *text = NULL, **refs = NULL;
char *retoid = NULL;
struct berval *retdata = NULL;
+ LDAPControl **ctrls = NULL;
tool_init( TOOL_PASSWD );
prog = lutil_progname( "ldappasswd", argc, argv );
goto done;
}
+ tool_server_controls( ld, NULL, 0);
+
rc = ldap_extended_operation( ld,
LDAP_EXOP_MODIFY_PASSWD, bv.bv_val ? &bv : NULL,
NULL, NULL, &id );
}
rc = ldap_parse_result( ld, res,
- &code, &matcheddn, &text, &refs, NULL, 0 );
+ &code, &matcheddn, &text, &refs, &ctrls, 0 );
if( rc != LDAP_SUCCESS ) {
tool_perror( "ldap_parse_result", rc, NULL, NULL, NULL, NULL );
rc = EXIT_FAILURE;
ber_free( ber, 1 );
- } else if ( newpw.bv_val == NULL ) {
+ } else if ( code == LDAP_SUCCESS && newpw.bv_val == NULL ) {
tool_perror( "ldap_parse_extended_result", LDAP_DECODING_ERROR,
" new password expected", NULL, NULL, NULL );
}
- if( verbose || code != LDAP_SUCCESS || matcheddn || text || refs ) {
+skip:
+ if( verbose || code != LDAP_SUCCESS ||
+ matcheddn || text || refs || ctrls )
+ {
printf( _("Result: %s (%d)\n"), ldap_err2string( code ), code );
if( text && *text ) {
printf(_("Referral: %s\n"), refs[i] );
}
}
+
+ if( ctrls ) {
+ tool_print_ctrls( ld, ctrls );
+ ldap_controls_free( ctrls );
+ }
}
ber_memfree( text );
ber_memfree( retoid );
ber_bvfree( retdata );
- rc = ldap_search_s( ld, binddn, LDAP_SCOPE_BASE, "(objectclass=*)",
- NULL, 0, &res );
-
rc = ( code == LDAP_SUCCESS ) ? EXIT_SUCCESS : EXIT_FAILURE;
done:
main( int argc, char *argv[] )
{
int rc;
- char *user = NULL;
-
LDAP *ld = NULL;
-
char *matcheddn = NULL, *text = NULL, **refs = NULL;
char *retoid = NULL;
struct berval *retdata = NULL;
int id, code = 0;
LDAPMessage *res;
+ LDAPControl **ctrls = NULL;
tool_init( TOOL_WHOAMI );
prog = lutil_progname( "ldapwhoami", argc, argv );
tool_args( argc, argv );
- if( argc - optind > 1 ) {
+ if( argc - optind > 0 ) {
usage();
- } else if ( argc - optind == 1 ) {
- user = strdup( argv[optind] );
- } else {
- user = NULL;
}
if ( pw_file || want_bindpw ) {
rc = ldap_whoami( ld, NULL, NULL, &id );
if( rc != LDAP_SUCCESS ) {
- tool_perror( "ldap_extended_operation", rc, NULL, NULL, NULL, NULL );
+ tool_perror( "ldap_whoami", rc, NULL, NULL, NULL, NULL );
rc = EXIT_FAILURE;
goto skip;
}
}
rc = ldap_parse_result( ld, res,
- &code, &matcheddn, &text, &refs, NULL, 0 );
+ &code, &matcheddn, &text, &refs, &ctrls, 0 );
if ( rc == LDAP_SUCCESS ) {
rc = code;
}
}
- if( verbose || ( code != LDAP_SUCCESS ) || matcheddn || text || refs ) {
+skip:
+ if ( verbose || ( code != LDAP_SUCCESS ) ||
+ matcheddn || text || refs || ctrls )
+ {
printf( _("Result: %s (%d)\n"), ldap_err2string( code ), code );
if( text && *text ) {
printf(_("Referral: %s\n"), refs[i] );
}
}
+
+ if (ctrls) {
+ tool_print_ctrls( ld, ctrls );
+ ldap_controls_free( ctrls );
+ }
}
ber_memfree( text );
ber_memfree( retoid );
ber_bvfree( retdata );
-skip:
/* disconnect from server */
tool_unbind( ld );
tool_destroy();
#! /bin/sh
-# From configure.in OpenLDAP: pkg/ldap/configure.in,v 1.631.2.4 2006/10/19 20:06:32 kurt Exp .
+# From configure.in OpenLDAP: pkg/ldap/configure.in,v 1.658 2007/07/02 13:15:31 hallvard Exp .
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.59.
#
# include <unistd.h>
#endif"
-ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS build build_cpu build_vendor build_os host host_cpu host_vendor host_os target target_cpu target_vendor target_os INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA CYGPATH_W PACKAGE VERSION ACLOCAL AUTOCONF AUTOMAKE AUTOHEADER MAKEINFO install_sh STRIP ac_ct_STRIP INSTALL_STRIP_PROGRAM mkdir_p AWK SET_MAKE am__leading_dot AMTAR am__tar am__untar OPENLDAP_LIBRELEASE OPENLDAP_LIBVERSION OPENLDAP_RELEASE_DATE top_builddir ldap_subdir CC AR CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT DEPDIR am__include am__quote AMDEP_TRUE AMDEP_FALSE AMDEPBACKSLASH CCDEPMODE am__fastdepCC_TRUE am__fastdepCC_FALSE EGREP LN_S ECHO ac_ct_AR RANLIB ac_ct_RANLIB DLLTOOL ac_ct_DLLTOOL AS ac_ct_AS OBJDUMP ac_ct_OBJDUMP CPP LIBTOOL PERLBIN OL_MKDEP OL_MKDEP_FLAGS LTSTATIC LIBOBJS LIBSRCS PLAT WITH_SASL WITH_TLS WITH_MODULES_ENABLED WITH_ACI_ENABLED BUILD_THREAD BUILD_LIBS_DYNAMIC BUILD_SLAPD BUILD_SLAPI SLAPD_SLAPI_DEPEND BUILD_BDB BUILD_DNSSRV BUILD_HDB BUILD_LDAP BUILD_META BUILD_MONITOR BUILD_NULL BUILD_PASSWD BUILD_RELAY BUILD_PERL BUILD_SHELL BUILD_SQL BUILD_ACCESSLOG BUILD_AUDITLOG BUILD_CONSTRAINT BUILD_DDS BUILD_DENYOP BUILD_DYNGROUP BUILD_DYNLIST BUILD_LASTMOD BUILD_PPOLICY BUILD_PROXYCACHE BUILD_REFINT BUILD_RETCODE BUILD_RWM BUILD_SEQMOD BUILD_SYNCPROV BUILD_TRANSLUCENT BUILD_UNIQUE BUILD_VALSORT BUILD_SLURPD LDAP_LIBS SLAPD_LIBS SLURPD_LIBS BDB_LIBS LTHREAD_LIBS LUTIL_LIBS WRAP_LIBS SLAPD_MODULES_CPPFLAGS SLAPD_MODULES_LDFLAGS SLAPD_NO_STATIC SLAPD_STATIC_BACKENDS SLAPD_DYNAMIC_BACKENDS SLAPD_STATIC_OVERLAYS SLAPD_DYNAMIC_OVERLAYS PERL_CPPFLAGS SLAPD_PERL_LDFLAGS MOD_PERL_LDFLAGS KRB4_LIBS KRB5_LIBS SASL_LIBS TLS_LIBS MODULES_LIBS SLAPI_LIBS LIBSLAPI LIBSLAPITOOLS AUTH_LIBS ICU_LIBS SLAPD_SLP_LIBS SLAPD_GMP_LIBS SLAPD_SQL_LDFLAGS SLAPD_SQL_LIBS SLAPD_SQL_INCLUDES LTLIBOBJS'
+ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS build build_cpu build_vendor build_os host host_cpu host_vendor host_os target target_cpu target_vendor target_os INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA CYGPATH_W PACKAGE VERSION ACLOCAL AUTOCONF AUTOMAKE AUTOHEADER MAKEINFO install_sh STRIP ac_ct_STRIP INSTALL_STRIP_PROGRAM mkdir_p AWK SET_MAKE am__leading_dot AMTAR am__tar am__untar OPENLDAP_LIBRELEASE OPENLDAP_LIBVERSION OPENLDAP_RELEASE_DATE top_builddir ldap_subdir CC AR CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT DEPDIR am__include am__quote AMDEP_TRUE AMDEP_FALSE AMDEPBACKSLASH CCDEPMODE am__fastdepCC_TRUE am__fastdepCC_FALSE EGREP LN_S ECHO ac_ct_AR RANLIB ac_ct_RANLIB DLLTOOL ac_ct_DLLTOOL AS ac_ct_AS OBJDUMP ac_ct_OBJDUMP CPP LIBTOOL PERLBIN OL_MKDEP OL_MKDEP_FLAGS LTSTATIC LIBOBJS LIBSRCS PLAT WITH_SASL WITH_TLS WITH_MODULES_ENABLED WITH_ACI_ENABLED BUILD_THREAD BUILD_LIBS_DYNAMIC BUILD_SLAPD BUILD_SLAPI SLAPD_SLAPI_DEPEND BUILD_BDB BUILD_DNSSRV BUILD_HDB BUILD_LDAP BUILD_META BUILD_MONITOR BUILD_NULL BUILD_PASSWD BUILD_RELAY BUILD_PERL BUILD_SHELL BUILD_SQL BUILD_ACCESSLOG BUILD_AUDITLOG BUILD_CONSTRAINT BUILD_DDS BUILD_DENYOP BUILD_DYNGROUP BUILD_DYNLIST BUILD_LASTMOD BUILD_PPOLICY BUILD_PROXYCACHE BUILD_REFINT BUILD_RETCODE BUILD_RWM BUILD_SEQMOD BUILD_SYNCPROV BUILD_TRANSLUCENT BUILD_UNIQUE BUILD_VALSORT LDAP_LIBS SLAPD_LIBS BDB_LIBS LTHREAD_LIBS LUTIL_LIBS WRAP_LIBS SLAPD_MODULES_CPPFLAGS SLAPD_MODULES_LDFLAGS SLAPD_NO_STATIC SLAPD_STATIC_BACKENDS SLAPD_DYNAMIC_BACKENDS SLAPD_STATIC_OVERLAYS SLAPD_DYNAMIC_OVERLAYS PERL_CPPFLAGS SLAPD_PERL_LDFLAGS MOD_PERL_LDFLAGS KRB4_LIBS KRB5_LIBS SASL_LIBS TLS_LIBS MODULES_LIBS SLAPI_LIBS LIBSLAPI LIBSLAPITOOLS AUTH_LIBS ICU_LIBS SLAPD_SLP_LIBS SLAPD_GMP_LIBS SLAPD_SQL_LDFLAGS SLAPD_SQL_LIBS SLAPD_SQL_INCLUDES LTLIBOBJS'
ac_subst_files=''
# Initialize some variables set by options.
--enable-dds Dynamic Directory Services overlay no|yes|mod [no]
--enable-dyngroup Dynamic Group overlay no|yes|mod [no]
--enable-dynlist Dynamic List overlay no|yes|mod [no]
+ --enable-memberof Reverse Group Membership overlay no|yes|mod [no]
--enable-ppolicy Password Policy overlay no|yes|mod [no]
--enable-proxycache Proxy Cache overlay no|yes|mod [no]
--enable-refint Referential Integrity overlay no|yes|mod [no]
--enable-unique Attribute Uniqueness overlay no|yes|mod [no]
--enable-valsort Value Sorting overlay no|yes|mod [no]
-SLURPD (Replication Daemon) Options:
- --enable-slurpd enable building slurpd [auto]
-
Library Generation & Linking Options
--enable-static[=PKGS]
build static libraries [default=yes]
--with-cyrus-sasl with Cyrus SASL support [auto]
--with-fetch with fetch(3) URL support [auto]
--with-threads with threads [auto]
- --with-tls with TLS/SSL support [auto]
+ --with-tls with TLS/SSL support auto|openssl|gnutls [auto]
--with-yielding-select with implicitly yielding select [auto]
--with-mp with multiple precision statistics auto|longlong|long|bignum|gmp [auto]
--with-odbc with specific ODBC support iodbc|unixodbc|auto [auto]
SHTOOL="$ac_cv_shtool"
-TB="`$SHTOOL echo -e '%B' 2>/dev/null`"
-TN="`$SHTOOL echo -e '%b' 2>/dev/null`"
+TB="" TN=""
+if test -t 1; then
+ TB="`$SHTOOL echo -e '%B' 2>/dev/null`"
+ TN="`$SHTOOL echo -e '%b' 2>/dev/null`"
+fi
OPENLDAP_CVS=""
if test -d $ac_aux_dir/CVS; then
withval="$with_tls"
ol_arg=invalid
- for ol_val in auto openssl yes no ; do
+ for ol_val in auto openssl gnutls yes no ; do
if test "$withval" = "$ol_val" ; then
ol_arg="$ol_val"
fi
dds \
dyngroup \
dynlist \
+ memberof \
ppolicy \
proxycache \
refint \
fi;
# end --enable-dynlist
+# OpenLDAP --enable-memberof
+
+ # Check whether --enable-memberof or --disable-memberof was given.
+if test "${enable_memberof+set}" = set; then
+ enableval="$enable_memberof"
+
+ ol_arg=invalid
+ for ol_val in no yes mod ; do
+ if test "$enableval" = "$ol_val" ; then
+ ol_arg="$ol_val"
+ fi
+ done
+ if test "$ol_arg" = "invalid" ; then
+ { { echo "$as_me:$LINENO: error: bad value $enableval for --enable-memberof" >&5
+echo "$as_me: error: bad value $enableval for --enable-memberof" >&2;}
+ { (exit 1); exit 1; }; }
+ fi
+ ol_enable_memberof="$ol_arg"
+
+else
+ ol_enable_memberof=${ol_enable_overlays:-no}
+fi;
+# end --enable-memberof
+
# OpenLDAP --enable-ppolicy
# Check whether --enable-ppolicy or --disable-ppolicy was given.
# end --enable-valsort
-# Check whether --enable-xxslurpdoptions or --disable-xxslurpdoptions was given.
-if test "${enable_xxslurpdoptions+set}" = set; then
- enableval="$enable_xxslurpdoptions"
-
-fi;
-# OpenLDAP --enable-slurpd
-
- # Check whether --enable-slurpd or --disable-slurpd was given.
-if test "${enable_slurpd+set}" = set; then
- enableval="$enable_slurpd"
-
- ol_arg=invalid
- for ol_val in auto yes no ; do
- if test "$enableval" = "$ol_val" ; then
- ol_arg="$ol_val"
- fi
- done
- if test "$ol_arg" = "invalid" ; then
- { { echo "$as_me:$LINENO: error: bad value $enableval for --enable-slurpd" >&5
-echo "$as_me: error: bad value $enableval for --enable-slurpd" >&2;}
- { (exit 1); exit 1; }; }
- fi
- ol_enable_slurpd="$ol_arg"
-
-else
- ol_enable_slurpd=auto
-fi;
-# end --enable-slurpd
-
# Check whether --enable-xxliboptions or --disable-xxliboptions was given.
if test "${enable_xxliboptions+set}" = set; then
enableval="$enable_xxliboptions"
if test $ol_enable_aci != no ; then
{ echo "$as_me:$LINENO: WARNING: slapd disabled, ignoring --enable-aci argument" >&5
echo "$as_me: WARNING: slapd disabled, ignoring --enable-aci argument" >&2;}
- fi
- if test $ol_enable_slurpd = yes ; then
- { { echo "$as_me:$LINENO: error: slurpd requires slapd" >&5
-echo "$as_me: error: slurpd requires slapd" >&2;}
- { (exit 1); exit 1; }; }
fi
if test $ol_enable_rewrite = yes ; then
{ echo "$as_me:$LINENO: WARNING: slapd disabled, ignoring --enable-rewrite argument" >&5
ol_enable_aci=no
ol_enable_wrappers=no
- ol_enable_slurpd=no
-
ol_enable_rewrite=no
elif test $ol_enable_modules != yes &&
{ (exit 1); exit 1; }; }
fi
-if test $ol_enable_slurpd = yes ; then
- if test $ol_with_threads = no ; then
- { { echo "$as_me:$LINENO: error: slurpd requires threads" >&5
-echo "$as_me: error: slurpd requires threads" >&2;}
- { (exit 1); exit 1; }; }
- fi
-fi
-
if test $ol_enable_lmpasswd = yes ; then
if test $ol_with_tls = no ; then
{ { echo "$as_me:$LINENO: error: LAN Manager passwords require OpenSSL" >&5
LUTIL_LIBS=
SLAPD_LIBS=
-SLURPD_LIBS=
BUILD_SLAPD=no
-BUILD_SLURPD=no
BUILD_THREAD=no
;;
*-*-irix6*)
# Find out which ABI we are using.
- echo '#line 5616 "configure"' > conftest.$ac_ext
+ echo '#line 5596 "configure"' > conftest.$ac_ext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
(eval $ac_compile) 2>&5
ac_status=$?
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:7596: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:7576: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
- echo "$as_me:7600: \$? = $ac_status" >&5
+ echo "$as_me:7580: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings other than the usual output.
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:7858: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:7838: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
- echo "$as_me:7862: \$? = $ac_status" >&5
+ echo "$as_me:7842: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings other than the usual output.
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:7920: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:7900: $lt_compile\"" >&5)
(eval "$lt_compile" 2>out/conftest.err)
ac_status=$?
cat out/conftest.err >&5
- echo "$as_me:7924: \$? = $ac_status" >&5
+ echo "$as_me:7904: \$? = $ac_status" >&5
if (exit $ac_status) && test -s out/conftest2.$ac_objext
then
# The compiler can only warn and ignore the option if not recognized
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<EOF
-#line 10168 "configure"
+#line 10148 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<EOF
-#line 10266 "configure"
+#line 10246 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
fi
echo "$as_me:$LINENO: result: $ol_cv_mkdep" >&5
echo "${ECHO_T}$ol_cv_mkdep" >&6
+ test "$ol_cv_mkdep" = no && OL_MKDEP=":"
else
cc_cv_mkdep=yes
OL_MKDEP_FLAGS="${MKDEP_FLAGS}"
+
+
+
sysexits.h \
sys/file.h \
sys/filio.h \
+ sys/fstyp.h \
sys/errno.h \
sys/ioctl.h \
sys/param.h \
+ sys/privgrp.h \
sys/resource.h \
sys/select.h \
sys/socket.h \
sys/time.h \
sys/types.h \
sys/uio.h \
+ sys/vmount.h \
syslog.h \
termios.h \
unistd.h \
fi
if test $have_uuid = no ; then
- echo "$as_me:$LINENO: checking to see if -lrpcrt4 is needed for win32 UUID support" >&5
-echo $ECHO_N "checking to see if -lrpcrt4 is needed for win32 UUID support... $ECHO_C" >&6
- save_LIBS="$LIBS"
- LIBS="$LIBS -lrpcrt4"
- cat >conftest.$ac_ext <<_ACEOF
+
+for ac_header in uuid/uuid.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+else
+ # Is the header compilable?
+echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h. */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h. */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_header_compiler=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
- int __stdcall UuidCreate(void *);
- int __stdcall UuidToStringA(void *,void **);
+ac_header_compiler=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6
+# Is the header present?
+echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <$ac_header>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_c_preproc_warn_flag
+ ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+ ac_header_preproc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_preproc=no
+fi
+rm -f conftest.err conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6
+
+# So? What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+ yes:no: )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+ ac_header_preproc=yes
+ ;;
+ no:yes:* )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+ (
+ cat <<\_ASBOX
+## --------------------------------------------- ##
+## Report this to <http://www.openldap.org/its/> ##
+## --------------------------------------------- ##
+_ASBOX
+ ) |
+ sed "s/^/$as_me: WARNING: /" >&2
+ ;;
+esac
+echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ eval "$as_ac_Header=\$ac_header_preproc"
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+ if test $ac_cv_header_uuid_uuid_h = yes ; then
+ save_LIBS="$LIBS"
+ echo "$as_me:$LINENO: checking for library containing uuid_generate" >&5
+echo $ECHO_N "checking for library containing uuid_generate... $ECHO_C" >&6
+if test "${ac_cv_search_uuid_generate+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_func_search_save_LIBS=$LIBS
+ac_cv_search_uuid_generate=no
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char uuid_generate ();
int
main ()
{
+uuid_generate ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_search_uuid_generate="none required"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
- UuidCreate(0);
- UuidToStringA(0,0);
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+if test "$ac_cv_search_uuid_generate" = no; then
+ for ac_lib in uuid; do
+ LIBS="-l$ac_lib $ac_func_search_save_LIBS"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char uuid_generate ();
+int
+main ()
+{
+uuid_generate ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_search_uuid_generate="-l$ac_lib"
+break
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ done
+fi
+LIBS=$ac_func_search_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_search_uuid_generate" >&5
+echo "${ECHO_T}$ac_cv_search_uuid_generate" >&6
+if test "$ac_cv_search_uuid_generate" != no; then
+ test "$ac_cv_search_uuid_generate" = "none required" || LIBS="$ac_cv_search_uuid_generate $LIBS"
+ have_uuid=yes
+else
+ :
+fi
+
+ LIBS="$save_LIBS"
+
+ if test have_uuid = yes ; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_UUID_GENERATE 1
+_ACEOF
+
+
+ test "$ac_cv_search_uuid_generate" = "none required" || \
+ SLAPD_LIBS="$SLAPD_LIBS $ac_cv_search_uuid_generate"
+ fi
+ fi
+fi
+
+if test $have_uuid = no ; then
+ echo "$as_me:$LINENO: checking to see if -lrpcrt4 is needed for win32 UUID support" >&5
+echo $ECHO_N "checking to see if -lrpcrt4 is needed for win32 UUID support... $ECHO_C" >&6
+ save_LIBS="$LIBS"
+ LIBS="$LIBS -lrpcrt4"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+ int __stdcall UuidCreate(void *);
+ int __stdcall UuidToStringA(void *,void **);
+
+int
+main ()
+{
+
+ UuidCreate(0);
+ UuidToStringA(0,0);
;
return 0;
fi
fi
+if test $ol_link_tls = no ; then
+ if test $ol_with_tls = gnutls || test $ol_with_tls = auto ; then
+
+for ac_header in gnutls/gnutls.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+else
+ # Is the header compilable?
+echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_header_compiler=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_header_compiler=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6
+
+# Is the header present?
+echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <$ac_header>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_c_preproc_warn_flag
+ ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+ ac_header_preproc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_preproc=no
+fi
+rm -f conftest.err conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6
+
+# So? What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+ yes:no: )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+ ac_header_preproc=yes
+ ;;
+ no:yes:* )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+ (
+ cat <<\_ASBOX
+## --------------------------------------------- ##
+## Report this to <http://www.openldap.org/its/> ##
+## --------------------------------------------- ##
+_ASBOX
+ ) |
+ sed "s/^/$as_me: WARNING: /" >&2
+ ;;
+esac
+echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ eval "$as_ac_Header=\$ac_header_preproc"
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+ if test $ac_cv_header_gnutls_gnutls_h = yes ; then
+ echo "$as_me:$LINENO: checking for gnutls_init in -lgnutls" >&5
+echo $ECHO_N "checking for gnutls_init in -lgnutls... $ECHO_C" >&6
+if test "${ac_cv_lib_gnutls_gnutls_init+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lgnutls $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char gnutls_init ();
+int
+main ()
+{
+gnutls_init ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_lib_gnutls_gnutls_init=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_gnutls_gnutls_init=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_gnutls_gnutls_init" >&5
+echo "${ECHO_T}$ac_cv_lib_gnutls_gnutls_init" >&6
+if test $ac_cv_lib_gnutls_gnutls_init = yes; then
+ have_gnutls=yes
+else
+ have_gnutls=no
+fi
+
+
+ if test $have_gnutls = yes ; then
+ ol_with_tls=gnutls
+ ol_link_tls=yes
+
+ TLS_LIBS="-lgnutls"
+
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_GNUTLS 1
+_ACEOF
+
+ fi
+ fi
+ fi
+fi
+
WITH_TLS=no
if test $ol_link_tls = yes ; then
#endif
/* make sure task runs first */
-#if HAVE_THR_YIELD
+#ifdef HAVE_THR_YIELD
thr_yield();
#elif defined( HAVE_SCHED_YIELD )
sched_yield();
}
#if (DB_VERSION_MAJOR > 3) || (DB_VERSION_MINOR >= 1)
- rc = env->open( env, NULL, flags, 0 );
+ rc = (env->open)( env, NULL, flags, 0 );
#else
- rc = env->open( env, NULL, NULL, flags, 0 );
+ rc = (env->open)( env, NULL, NULL, flags, 0 );
#endif
if ( rc == 0 ) {
fi
+
echo "$as_me:$LINENO: checking for socklen_t" >&5
echo $ECHO_N "checking for socklen_t... $ECHO_C" >&6
if test "${ac_cv_type_socklen_t+set}" = set; then
#include <sys/socket.h>
#endif
-
int
main ()
{
fi
echo "$as_me:$LINENO: result: $ac_cv_type_socklen_t" >&5
echo "${ECHO_T}$ac_cv_type_socklen_t" >&6
-if test $ac_cv_type_socklen_t = yes; then
- :
+
+
+echo "$as_me:$LINENO: checking the type of arg 3 to accept()" >&5
+echo $ECHO_N "checking the type of arg 3 to accept()... $ECHO_C" >&6
+if test "${ol_cv_type_ber_socklen_t+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+ set socklen_t int unsigned "unsigned long" long size_t
+ test "$ac_cv_type_socklen_t" = yes || shift
+ ol_cv_type_ber_socklen_t=$1 guessing="guessing "
+ for lentype in "$@" ; do for addrtype in "struct sockaddr" void ; do
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+extern int accept(int s, $addrtype *ap, $lentype *lp);
+
+int
+main ()
+{
+
+accept(0, (struct sockaddr *) 0, ($lentype *) 0);
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ol_cv_type_ber_socklen_t=$lentype guessing= ; break 2
else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ done ; done
+fi
+
+echo "$as_me:$LINENO: result: $guessing$ol_cv_type_ber_socklen_t *" >&5
+echo "${ECHO_T}$guessing$ol_cv_type_ber_socklen_t *" >&6
cat >>confdefs.h <<_ACEOF
-#define socklen_t int
+#define ber_socklen_t $ol_cv_type_ber_socklen_t
+_ACEOF
+
+
+if test "$ac_cv_type_socklen_t" != yes; then
+
+cat >>confdefs.h <<_ACEOF
+#define socklen_t $ol_cv_type_ber_socklen_t
_ACEOF
fi
main ()
{
static struct msghdr ac_aggr;
-if (sizeof ac_aggr.msg_accrightslen)
+if (sizeof ac_aggr.msg_accrightslen)
+return 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_member_struct_msghdr_msg_accrightslen=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_member_struct_msghdr_msg_accrightslen=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_member_struct_msghdr_msg_accrightslen" >&5
+echo "${ECHO_T}$ac_cv_member_struct_msghdr_msg_accrightslen" >&6
+if test $ac_cv_member_struct_msghdr_msg_accrightslen = yes; then
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTSLEN 1
+_ACEOF
+
+
+fi
+
+ if test "$ac_cv_member_struct_msghdr_msg_accrightslen" != yes; then
+ echo "$as_me:$LINENO: checking for struct msghdr.msg_control" >&5
+echo $ECHO_N "checking for struct msghdr.msg_control... $ECHO_C" >&6
+if test "${ac_cv_member_struct_msghdr_msg_control+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+
+int
+main ()
+{
+static struct msghdr ac_aggr;
+if (ac_aggr.msg_control)
+return 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_member_struct_msghdr_msg_control=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+
+int
+main ()
+{
+static struct msghdr ac_aggr;
+if (sizeof ac_aggr.msg_control)
return 0;
;
return 0;
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); }; }; then
- ac_cv_member_struct_msghdr_msg_accrightslen=yes
+ ac_cv_member_struct_msghdr_msg_control=yes
else
echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
-ac_cv_member_struct_msghdr_msg_accrightslen=no
+ac_cv_member_struct_msghdr_msg_control=no
fi
rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
fi
rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
fi
-echo "$as_me:$LINENO: result: $ac_cv_member_struct_msghdr_msg_accrightslen" >&5
-echo "${ECHO_T}$ac_cv_member_struct_msghdr_msg_accrightslen" >&6
-if test $ac_cv_member_struct_msghdr_msg_accrightslen = yes; then
+echo "$as_me:$LINENO: result: $ac_cv_member_struct_msghdr_msg_control" >&5
+echo "${ECHO_T}$ac_cv_member_struct_msghdr_msg_control" >&6
+if test $ac_cv_member_struct_msghdr_msg_control = yes; then
cat >>confdefs.h <<_ACEOF
-#define HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTSLEN 1
+#define HAVE_STRUCT_MSGHDR_MSG_CONTROL 1
_ACEOF
fi
- if test "$ac_cv_member_struct_msghdr_msg_accrightslen" != yes; then
- echo "$as_me:$LINENO: checking for struct msghdr.msg_control" >&5
-echo $ECHO_N "checking for struct msghdr.msg_control... $ECHO_C" >&6
-if test "${ac_cv_member_struct_msghdr_msg_control+set}" = set; then
+ fi
+ echo "$as_me:$LINENO: checking for struct stat.st_fstype" >&5
+echo $ECHO_N "checking for struct stat.st_fstype... $ECHO_C" >&6
+if test "${ac_cv_member_struct_stat_st_fstype+set}" = set; then
echo $ECHO_N "(cached) $ECHO_C" >&6
else
cat >conftest.$ac_ext <<_ACEOF
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h. */
$ac_includes_default
-#ifdef HAVE_SYS_SOCKET_H
-#include <sys/socket.h>
-#endif
-
int
main ()
{
-static struct msghdr ac_aggr;
-if (ac_aggr.msg_control)
+static struct stat ac_aggr;
+if (ac_aggr.st_fstype)
return 0;
;
return 0;
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); }; }; then
- ac_cv_member_struct_msghdr_msg_control=yes
+ ac_cv_member_struct_stat_st_fstype=yes
else
echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h. */
$ac_includes_default
-#ifdef HAVE_SYS_SOCKET_H
-#include <sys/socket.h>
-#endif
+int
+main ()
+{
+static struct stat ac_aggr;
+if (sizeof ac_aggr.st_fstype)
+return 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_member_struct_stat_st_fstype=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+ac_cv_member_struct_stat_st_fstype=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_member_struct_stat_st_fstype" >&5
+echo "${ECHO_T}$ac_cv_member_struct_stat_st_fstype" >&6
+if test $ac_cv_member_struct_stat_st_fstype = yes; then
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_STRUCT_STAT_ST_FSTYPE 1
+_ACEOF
+
+
+fi
+echo "$as_me:$LINENO: checking for struct stat.st_vfstype" >&5
+echo $ECHO_N "checking for struct stat.st_vfstype... $ECHO_C" >&6
+if test "${ac_cv_member_struct_stat_st_vfstype+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
int
main ()
{
-static struct msghdr ac_aggr;
-if (sizeof ac_aggr.msg_control)
+static struct stat ac_aggr;
+if (ac_aggr.st_vfstype)
return 0;
;
return 0;
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); }; }; then
- ac_cv_member_struct_msghdr_msg_control=yes
+ ac_cv_member_struct_stat_st_vfstype=yes
else
echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
-ac_cv_member_struct_msghdr_msg_control=no
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+static struct stat ac_aggr;
+if (sizeof ac_aggr.st_vfstype)
+return 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_member_struct_stat_st_vfstype=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_member_struct_stat_st_vfstype=no
fi
rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
fi
rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
fi
-echo "$as_me:$LINENO: result: $ac_cv_member_struct_msghdr_msg_control" >&5
-echo "${ECHO_T}$ac_cv_member_struct_msghdr_msg_control" >&6
-if test $ac_cv_member_struct_msghdr_msg_control = yes; then
+echo "$as_me:$LINENO: result: $ac_cv_member_struct_stat_st_vfstype" >&5
+echo "${ECHO_T}$ac_cv_member_struct_stat_st_vfstype" >&6
+if test $ac_cv_member_struct_stat_st_vfstype = yes; then
cat >>confdefs.h <<_ACEOF
-#define HAVE_STRUCT_MSGHDR_MSG_CONTROL 1
+#define HAVE_STRUCT_STAT_ST_VFSTYPE 1
_ACEOF
fi
+ if test "$ac_cv_member_struct_stat_st_fstype" = yes; then
+ cat >conftest.$ac_ext <<_ACEOF
+struct stat st; char *ptr=st.st_fstype;
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_STRUCT_STAT_ST_FSTYPE_CHAR 1
+_ACEOF
+
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_STRUCT_STAT_ST_FSTYPE_INT 1
+_ACEOF
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
fi
fi
LIBSRCS="$LIBSRCS getpeereid.c"
fi
+if test "$ol_enable_memberof" != no ; then
+ BUILD_MEMBEROF=$ol_enable_memberof
+ if test "$ol_enable_memberof" = mod ; then
+ MFLAG=SLAPD_MOD_DYNAMIC
+ SLAPD_DYNAMIC_OVERLAYS="$SLAPD_DYNAMIC_OVERLAYS memberof.la"
+ else
+ MFLAG=SLAPD_MOD_STATIC
+ SLAPD_STATIC_OVERLAYS="$SLAPD_STATIC_OVERLAYS memberof.o"
+ fi
+
+cat >>confdefs.h <<_ACEOF
+#define SLAPD_OVER_MEMBEROF $MFLAG
+_ACEOF
+
+fi
+
if test "$ol_enable_ppolicy" != no ; then
BUILD_PPOLICY=$ol_enable_ppolicy
if test "$ol_enable_ppolicy" = mod ; then
fi
-if test "$ol_enable_slurpd" != no &&
- test "$ol_link_threads" != no &&
- test $BUILD_SLAPD = yes ; then
- BUILD_SLURPD=yes
-fi
-
if test "$ol_enable_rewrite" != no ; then
cat >>confdefs.h <<\_ACEOF
-
-
fi;
- ac_config_files="$ac_config_files Makefile:build/top.mk:Makefile.in:build/dir.mk doc/Makefile:build/top.mk:doc/Makefile.in:build/dir.mk doc/man/Makefile:build/top.mk:doc/man/Makefile.in:build/dir.mk doc/man/man1/Makefile:build/top.mk:doc/man/man1/Makefile.in:build/man.mk doc/man/man3/Makefile:build/top.mk:doc/man/man3/Makefile.in:build/man.mk doc/man/man5/Makefile:build/top.mk:doc/man/man5/Makefile.in:build/man.mk doc/man/man8/Makefile:build/top.mk:doc/man/man8/Makefile.in:build/man.mk clients/Makefile:build/top.mk:clients/Makefile.in:build/dir.mk clients/tools/Makefile:build/top.mk:clients/tools/Makefile.in:build/rules.mk include/Makefile:build/top.mk:include/Makefile.in libraries/Makefile:build/top.mk:libraries/Makefile.in:build/dir.mk libraries/liblber/Makefile:build/top.mk:libraries/liblber/Makefile.in:build/lib.mk:build/lib-shared.mk libraries/libldap/Makefile:build/top.mk:libraries/libldap/Makefile.in:build/lib.mk:build/lib-shared.mk libraries/libldap_r/Makefile:build/top.mk:libraries/libldap_r/Makefile.in:build/lib.mk:build/lib-shared.mk libraries/liblunicode/Makefile:build/top.mk:libraries/liblunicode/Makefile.in:build/lib.mk:build/lib-static.mk libraries/liblutil/Makefile:build/top.mk:libraries/liblutil/Makefile.in:build/lib.mk:build/lib-static.mk libraries/librewrite/Makefile:build/top.mk:libraries/librewrite/Makefile.in:build/lib.mk:build/lib-static.mk servers/Makefile:build/top.mk:servers/Makefile.in:build/dir.mk servers/slapd/Makefile:build/top.mk:servers/slapd/Makefile.in:build/srv.mk servers/slapd/back-bdb/Makefile:build/top.mk:servers/slapd/back-bdb/Makefile.in:build/mod.mk servers/slapd/back-dnssrv/Makefile:build/top.mk:servers/slapd/back-dnssrv/Makefile.in:build/mod.mk servers/slapd/back-hdb/Makefile:build/top.mk:servers/slapd/back-hdb/Makefile.in:build/mod.mk servers/slapd/back-ldap/Makefile:build/top.mk:servers/slapd/back-ldap/Makefile.in:build/mod.mk servers/slapd/back-ldif/Makefile:build/top.mk:servers/slapd/back-ldif/Makefile.in:build/mod.mk servers/slapd/back-meta/Makefile:build/top.mk:servers/slapd/back-meta/Makefile.in:build/mod.mk servers/slapd/back-monitor/Makefile:build/top.mk:servers/slapd/back-monitor/Makefile.in:build/mod.mk servers/slapd/back-null/Makefile:build/top.mk:servers/slapd/back-null/Makefile.in:build/mod.mk servers/slapd/back-passwd/Makefile:build/top.mk:servers/slapd/back-passwd/Makefile.in:build/mod.mk servers/slapd/back-perl/Makefile:build/top.mk:servers/slapd/back-perl/Makefile.in:build/mod.mk servers/slapd/back-relay/Makefile:build/top.mk:servers/slapd/back-relay/Makefile.in:build/mod.mk servers/slapd/back-shell/Makefile:build/top.mk:servers/slapd/back-shell/Makefile.in:build/mod.mk servers/slapd/back-sql/Makefile:build/top.mk:servers/slapd/back-sql/Makefile.in:build/mod.mk servers/slapd/shell-backends/Makefile:build/top.mk:servers/slapd/shell-backends/Makefile.in:build/srv.mk servers/slapd/slapi/Makefile:build/top.mk:servers/slapd/slapi/Makefile.in:build/lib.mk:build/lib-shared.mk servers/slapd/overlays/Makefile:build/top.mk:servers/slapd/overlays/Makefile.in:build/lib.mk servers/slurpd/Makefile:build/top.mk:servers/slurpd/Makefile.in:build/srv.mk tests/Makefile:build/top.mk:tests/Makefile.in:build/dir.mk tests/run tests/progs/Makefile:build/top.mk:tests/progs/Makefile.in:build/rules.mk"
+ ac_config_files="$ac_config_files Makefile:build/top.mk:Makefile.in:build/dir.mk doc/Makefile:build/top.mk:doc/Makefile.in:build/dir.mk doc/man/Makefile:build/top.mk:doc/man/Makefile.in:build/dir.mk doc/man/man1/Makefile:build/top.mk:doc/man/man1/Makefile.in:build/man.mk doc/man/man3/Makefile:build/top.mk:doc/man/man3/Makefile.in:build/man.mk doc/man/man5/Makefile:build/top.mk:doc/man/man5/Makefile.in:build/man.mk doc/man/man8/Makefile:build/top.mk:doc/man/man8/Makefile.in:build/man.mk clients/Makefile:build/top.mk:clients/Makefile.in:build/dir.mk clients/tools/Makefile:build/top.mk:clients/tools/Makefile.in:build/rules.mk include/Makefile:build/top.mk:include/Makefile.in libraries/Makefile:build/top.mk:libraries/Makefile.in:build/dir.mk libraries/liblber/Makefile:build/top.mk:libraries/liblber/Makefile.in:build/lib.mk:build/lib-shared.mk libraries/libldap/Makefile:build/top.mk:libraries/libldap/Makefile.in:build/lib.mk:build/lib-shared.mk libraries/libldap_r/Makefile:build/top.mk:libraries/libldap_r/Makefile.in:build/lib.mk:build/lib-shared.mk libraries/liblunicode/Makefile:build/top.mk:libraries/liblunicode/Makefile.in:build/lib.mk:build/lib-static.mk libraries/liblutil/Makefile:build/top.mk:libraries/liblutil/Makefile.in:build/lib.mk:build/lib-static.mk libraries/librewrite/Makefile:build/top.mk:libraries/librewrite/Makefile.in:build/lib.mk:build/lib-static.mk servers/Makefile:build/top.mk:servers/Makefile.in:build/dir.mk servers/slapd/Makefile:build/top.mk:servers/slapd/Makefile.in:build/srv.mk servers/slapd/back-bdb/Makefile:build/top.mk:servers/slapd/back-bdb/Makefile.in:build/mod.mk servers/slapd/back-dnssrv/Makefile:build/top.mk:servers/slapd/back-dnssrv/Makefile.in:build/mod.mk servers/slapd/back-hdb/Makefile:build/top.mk:servers/slapd/back-hdb/Makefile.in:build/mod.mk servers/slapd/back-ldap/Makefile:build/top.mk:servers/slapd/back-ldap/Makefile.in:build/mod.mk servers/slapd/back-ldif/Makefile:build/top.mk:servers/slapd/back-ldif/Makefile.in:build/mod.mk servers/slapd/back-meta/Makefile:build/top.mk:servers/slapd/back-meta/Makefile.in:build/mod.mk servers/slapd/back-monitor/Makefile:build/top.mk:servers/slapd/back-monitor/Makefile.in:build/mod.mk servers/slapd/back-null/Makefile:build/top.mk:servers/slapd/back-null/Makefile.in:build/mod.mk servers/slapd/back-passwd/Makefile:build/top.mk:servers/slapd/back-passwd/Makefile.in:build/mod.mk servers/slapd/back-perl/Makefile:build/top.mk:servers/slapd/back-perl/Makefile.in:build/mod.mk servers/slapd/back-relay/Makefile:build/top.mk:servers/slapd/back-relay/Makefile.in:build/mod.mk servers/slapd/back-shell/Makefile:build/top.mk:servers/slapd/back-shell/Makefile.in:build/mod.mk servers/slapd/back-sql/Makefile:build/top.mk:servers/slapd/back-sql/Makefile.in:build/mod.mk servers/slapd/shell-backends/Makefile:build/top.mk:servers/slapd/shell-backends/Makefile.in:build/srv.mk servers/slapd/slapi/Makefile:build/top.mk:servers/slapd/slapi/Makefile.in:build/lib.mk:build/lib-shared.mk servers/slapd/overlays/Makefile:build/top.mk:servers/slapd/overlays/Makefile.in:build/lib.mk tests/Makefile:build/top.mk:tests/Makefile.in:build/dir.mk tests/run tests/progs/Makefile:build/top.mk:tests/progs/Makefile.in:build/rules.mk"
ac_config_commands="$ac_config_commands default"
"servers/slapd/shell-backends/Makefile" ) CONFIG_FILES="$CONFIG_FILES servers/slapd/shell-backends/Makefile:build/top.mk:servers/slapd/shell-backends/Makefile.in:build/srv.mk" ;;
"servers/slapd/slapi/Makefile" ) CONFIG_FILES="$CONFIG_FILES servers/slapd/slapi/Makefile:build/top.mk:servers/slapd/slapi/Makefile.in:build/lib.mk:build/lib-shared.mk" ;;
"servers/slapd/overlays/Makefile" ) CONFIG_FILES="$CONFIG_FILES servers/slapd/overlays/Makefile:build/top.mk:servers/slapd/overlays/Makefile.in:build/lib.mk" ;;
- "servers/slurpd/Makefile" ) CONFIG_FILES="$CONFIG_FILES servers/slurpd/Makefile:build/top.mk:servers/slurpd/Makefile.in:build/srv.mk" ;;
"tests/Makefile" ) CONFIG_FILES="$CONFIG_FILES tests/Makefile:build/top.mk:tests/Makefile.in:build/dir.mk" ;;
"tests/run" ) CONFIG_FILES="$CONFIG_FILES tests/run" ;;
"tests/progs/Makefile" ) CONFIG_FILES="$CONFIG_FILES tests/progs/Makefile:build/top.mk:tests/progs/Makefile.in:build/rules.mk" ;;
s,@BUILD_TRANSLUCENT@,$BUILD_TRANSLUCENT,;t t
s,@BUILD_UNIQUE@,$BUILD_UNIQUE,;t t
s,@BUILD_VALSORT@,$BUILD_VALSORT,;t t
-s,@BUILD_SLURPD@,$BUILD_SLURPD,;t t
s,@LDAP_LIBS@,$LDAP_LIBS,;t t
s,@SLAPD_LIBS@,$SLAPD_LIBS,;t t
-s,@SLURPD_LIBS@,$SLURPD_LIBS,;t t
s,@BDB_LIBS@,$BDB_LIBS,;t t
s,@LTHREAD_LIBS@,$LTHREAD_LIBS,;t t
s,@LUTIL_LIBS@,$LUTIL_LIBS,;t t
/* end of generated file */
ENDX
-echo Please run \"make depend\" to build dependencies
+if test "${ol_cv_mkdep}" = no; then
+ echo '(Do not "make depend"; we do not know how to build dependencies)'
+else
+ echo 'Please run "make depend" to build dependencies'
+fi
;;
esac
done
SHTOOL="$ac_cv_shtool"
dnl AC_SUBST(SHTOOL)dnl
-TB="`$SHTOOL echo -e '%B' 2>/dev/null`"
-TN="`$SHTOOL echo -e '%b' 2>/dev/null`"
+TB="" TN=""
+if test -t 1; then
+ TB="`$SHTOOL echo -e '%B' 2>/dev/null`"
+ TN="`$SHTOOL echo -e '%b' 2>/dev/null`"
+fi
OPENLDAP_CVS=""
if test -d $ac_aux_dir/CVS; then
auto, [auto yes no] )
OL_ARG_WITH(threads,[ --with-threads with threads],
auto, [auto nt posix mach pth lwp yes no manual] )
-OL_ARG_WITH(tls,[ --with-tls with TLS/SSL support],
- auto, [auto openssl yes no] )
+OL_ARG_WITH(tls,[ --with-tls with TLS/SSL support auto|openssl|gnutls],
+ auto, [auto openssl gnutls yes no] )
OL_ARG_WITH(yielding_select,
[ --with-yielding-select with implicitly yielding select],
auto, [auto yes no manual] )
dds \
dyngroup \
dynlist \
+ memberof \
ppolicy \
proxycache \
refint \
no, [no yes mod], ol_enable_overlays)
OL_ARG_ENABLE(dynlist,[ --enable-dynlist Dynamic List overlay],
no, [no yes mod], ol_enable_overlays)
+OL_ARG_ENABLE(memberof,[ --enable-memberof Reverse Group Membership overlay],
+ no, [no yes mod], ol_enable_overlays)
OL_ARG_ENABLE(ppolicy,[ --enable-ppolicy Password Policy overlay],
no, [no yes mod], ol_enable_overlays)
OL_ARG_ENABLE(proxycache,[ --enable-proxycache Proxy Cache overlay],
OL_ARG_ENABLE(valsort,[ --enable-valsort Value Sorting overlay],
no, [no yes mod], ol_enable_overlays)
-dnl ----------------------------------------------------------------
-dnl SLURPD OPTIONS
-AC_ARG_ENABLE(xxslurpdoptions,[
-SLURPD (Replication Daemon) Options:])
-OL_ARG_ENABLE(slurpd,[ --enable-slurpd enable building slurpd], auto)dnl
-
dnl ----------------------------------------------------------------
AC_ARG_ENABLE(xxliboptions,[
Library Generation & Linking Options])
if test $ol_enable_aci != no ; then
AC_MSG_WARN([slapd disabled, ignoring --enable-aci argument])
fi
- if test $ol_enable_slurpd = yes ; then
- AC_MSG_ERROR([slurpd requires slapd])
- fi
if test $ol_enable_rewrite = yes ; then
AC_MSG_WARN([slapd disabled, ignoring --enable-rewrite argument])
fi
ol_enable_aci=no
ol_enable_wrappers=no
- ol_enable_slurpd=no
-
ol_enable_rewrite=no
elif test $ol_enable_modules != yes &&
AC_MSG_ERROR([--enable-meta requires --enable-ldap])
fi
-if test $ol_enable_slurpd = yes ; then
- dnl SLURPD was specifically enabled
- if test $ol_with_threads = no ; then
- AC_MSG_ERROR([slurpd requires threads])
- fi
-fi
-
if test $ol_enable_lmpasswd = yes ; then
if test $ol_with_tls = no ; then
AC_MSG_ERROR([LAN Manager passwords require OpenSSL])
LUTIL_LIBS=
SLAPD_LIBS=
-SLURPD_LIBS=
BUILD_SLAPD=no
-BUILD_SLURPD=no
BUILD_THREAD=no
sysexits.h \
sys/file.h \
sys/filio.h \
+ sys/fstyp.h \
sys/errno.h \
sys/ioctl.h \
sys/param.h \
+ sys/privgrp.h \
sys/resource.h \
sys/select.h \
sys/socket.h \
sys/time.h \
sys/types.h \
sys/uio.h \
+ sys/vmount.h \
syslog.h \
termios.h \
unistd.h \
AC_CHECK_HEADERS(sys/uuid.h)
if test $ac_cv_header_sys_uuid_h = yes ; then
save_LIBS="$LIBS"
- AC_SEARCH_LIBS(uuid_to_str, uuid, [have_uuid=yes], :)
+ AC_SEARCH_LIBS([uuid_to_str], [uuid], [have_uuid=yes], :)
LIBS="$save_LIBS"
if test have_uuid = yes ; then
fi
fi
+dnl Look for uuid_generate
+if test $have_uuid = no ; then
+ AC_CHECK_HEADERS(uuid/uuid.h)
+ if test $ac_cv_header_uuid_uuid_h = yes ; then
+ save_LIBS="$LIBS"
+ AC_SEARCH_LIBS([uuid_generate], [uuid], [have_uuid=yes], :)
+ LIBS="$save_LIBS"
+
+ if test have_uuid = yes ; then
+ AC_DEFINE(HAVE_UUID_GENERATE,1,
+ [define if you have uuid_generate()])
+
+ test "$ac_cv_search_uuid_generate" = "none required" || \
+ SLAPD_LIBS="$SLAPD_LIBS $ac_cv_search_uuid_generate"
+ fi
+ fi
+fi
+
dnl For windows, check for the need of RPCRT for UUID function support
if test $have_uuid = no ; then
AC_MSG_CHECKING(to see if -lrpcrt4 is needed for win32 UUID support)
fi
fi
+if test $ol_link_tls = no ; then
+ if test $ol_with_tls = gnutls || test $ol_with_tls = auto ; then
+ AC_CHECK_HEADERS(gnutls/gnutls.h)
+
+ if test $ac_cv_header_gnutls_gnutls_h = yes ; then
+ AC_CHECK_LIB(gnutls, gnutls_init,
+ [have_gnutls=yes], [have_gnutls=no])
+
+ if test $have_gnutls = yes ; then
+ ol_with_tls=gnutls
+ ol_link_tls=yes
+
+ TLS_LIBS="-lgnutls"
+
+ AC_DEFINE(HAVE_GNUTLS, 1,
+ [define if you have GNUtls])
+ fi
+ fi
+ fi
+fi
+
WITH_TLS=no
if test $ol_link_tls = yes ; then
AC_DEFINE(HAVE_TLS, 1, [define if you have TLS])
#endif
/* make sure task runs first */
-#if HAVE_THR_YIELD
+#ifdef HAVE_THR_YIELD
thr_yield();
#elif defined( HAVE_SCHED_YIELD )
sched_yield();
AC_CHECK_TYPES([long long])
AC_CHECK_TYPES([ptrdiff_t])
-AC_CHECK_TYPE([socklen_t],,
- [AC_DEFINE_UNQUOTED([socklen_t], [int],
- [Define to `int' if <sys/socket.h> does not define.])],
- [$ac_includes_default
+
+AC_CHECK_TYPE([socklen_t],,, [$ac_includes_default
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif])
+
+dnl socklen_t-like type in accept(), default socklen_t or int:
+dnl - The OS might define socklen_t without using it. POSIX moved from
+dnl int to size_t to socklen_t, hoping to stay at a 32-bit type, and
+dnl HP-UX now has selectors for what to use.
+dnl - On Solaris 2.8 the prototype has void *len, but the default is OK.
+AC_MSG_CHECKING([the type of arg 3 to accept()])
+AC_CACHE_VAL(ol_cv_type_ber_socklen_t, [
+ set socklen_t int unsigned "unsigned long" long size_t
+ test "$ac_cv_type_socklen_t" = yes || shift
+ ol_cv_type_ber_socklen_t=$1 guessing="guessing "
+ for lentype in "$@" ; do for addrtype in "struct sockaddr" void ; do
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([$ac_includes_default
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
- ])
+extern int accept(int s, $addrtype *ap, $lentype *lp);
+], [
+accept(0, (struct sockaddr *) 0, ($lentype *) 0);
+])], [ol_cv_type_ber_socklen_t=$lentype guessing= ; break 2])
+ done ; done])
+AC_MSG_RESULT([$guessing$ol_cv_type_ber_socklen_t *])
+AC_DEFINE_UNQUOTED(ber_socklen_t, $ol_cv_type_ber_socklen_t,
+ [Define to the type of arg 3 for `accept'.])
+
+dnl Modules should use ber_socklen_t, not socklen_t. Define socklen_t
+dnl for the time being anyway, for backwards compatibility.
+if test "$ac_cv_type_socklen_t" != yes; then
+ AC_DEFINE_UNQUOTED([socklen_t], [$ol_cv_type_ber_socklen_t],
+ [Define like ber_socklen_t if <sys/socket.h> does not define.])
+fi
+
AC_TYPE_SIGNAL
#include <sys/socket.h>
#endif])
fi
+ AC_CHECK_MEMBERS([struct stat.st_fstype, struct stat.st_vfstype])
+ if test "$ac_cv_member_struct_stat_st_fstype" = yes; then
+ AC_COMPILE_IFELSE([struct stat st; char *ptr=st.st_fstype;],
+ AC_DEFINE([HAVE_STRUCT_STAT_ST_FSTYPE_CHAR],1,[define to 1 if st_fstype is char *]),
+ AC_DEFINE([HAVE_STRUCT_STAT_ST_FSTYPE_INT],1,[define to 1 if st_fstype is int]))
+ fi
fi
LIBSRCS="$LIBSRCS getpeereid.c"
fi
AC_DEFINE_UNQUOTED(SLAPD_OVER_DYNLIST,$MFLAG,[define for Dynamic List overlay])
fi
+if test "$ol_enable_memberof" != no ; then
+ BUILD_MEMBEROF=$ol_enable_memberof
+ if test "$ol_enable_memberof" = mod ; then
+ MFLAG=SLAPD_MOD_DYNAMIC
+ SLAPD_DYNAMIC_OVERLAYS="$SLAPD_DYNAMIC_OVERLAYS memberof.la"
+ else
+ MFLAG=SLAPD_MOD_STATIC
+ SLAPD_STATIC_OVERLAYS="$SLAPD_STATIC_OVERLAYS memberof.o"
+ fi
+ AC_DEFINE_UNQUOTED(SLAPD_OVER_MEMBEROF,$MFLAG,[define for Reverse Group Membership overlay])
+fi
+
if test "$ol_enable_ppolicy" != no ; then
BUILD_PPOLICY=$ol_enable_ppolicy
if test "$ol_enable_ppolicy" = mod ; then
AC_DEFINE_UNQUOTED(SLAPD_OVER_VALSORT,$MFLAG,[define for Value Sorting overlay])
fi
-if test "$ol_enable_slurpd" != no &&
- test "$ol_link_threads" != no &&
- test $BUILD_SLAPD = yes ; then
- BUILD_SLURPD=yes
-fi
-
if test "$ol_enable_rewrite" != no ; then
AC_DEFINE(ENABLE_REWRITE,1,[define to enable rewriting in back-ldap and back-meta])
BUILD_REWRITE=yes
AC_SUBST(BUILD_TRANSLUCENT)
AC_SUBST(BUILD_UNIQUE)
AC_SUBST(BUILD_VALSORT)
-AC_SUBST(BUILD_SLURPD)
AC_SUBST(LDAP_LIBS)
AC_SUBST(SLAPD_LIBS)
-AC_SUBST(SLURPD_LIBS)
AC_SUBST(BDB_LIBS)
AC_SUBST(LTHREAD_LIBS)
AC_SUBST(LUTIL_LIBS)
[servers/slapd/shell-backends/Makefile:build/top.mk:servers/slapd/shell-backends/Makefile.in:build/srv.mk]
[servers/slapd/slapi/Makefile:build/top.mk:servers/slapd/slapi/Makefile.in:build/lib.mk:build/lib-shared.mk]
[servers/slapd/overlays/Makefile:build/top.mk:servers/slapd/overlays/Makefile.in:build/lib.mk]
-[servers/slurpd/Makefile:build/top.mk:servers/slurpd/Makefile.in:build/srv.mk]
[tests/Makefile:build/top.mk:tests/Makefile.in:build/dir.mk]
[tests/run]
[tests/progs/Makefile:build/top.mk:tests/progs/Makefile.in:build/rules.mk])
/* end of generated file */
ENDX
-echo Please run \"make depend\" to build dependencies
+if test "${ol_cv_mkdep}" = no; then
+ echo '(Do not "make depend"; we do not know how to build dependencies)'
+else
+ echo 'Please run "make depend" to build dependencies'
+fi
]],[[
STATIC_BACKENDS="$SLAPD_STATIC_BACKENDS"
STATIC_OVERLAYS="$SLAPD_STATIC_OVERLAYS"
#ifndef _AC_TIME_H
#define _AC_TIME_H
-#if TIME_WITH_SYS_TIME
+#ifdef TIME_WITH_SYS_TIME
# include <sys/time.h>
# include <time.h>
-#elif HAVE_SYS_TIME_H
+#elif defined HAVE_SYS_TIME_H
# include <sys/time.h>
# ifdef HAVE_SYS_TIMEB_H
# include <sys/timeb.h>
case "$with_tk" in
yes)
- if test -f $exec_prefix/lib/tkConfig.sh -a $exec_prefix/lib/tkxConfig.sh
+ if test -f $exec_prefix/lib/tkConfig.sh &&
+ test -f $exec_prefix/lib/tkxConfig.sh
then
:
else
case "$with_tk" in
yes)
- if test -f $exec_prefix/lib/tkConfig.sh -a $exec_prefix/lib/tkxConfig.sh
+ if test -f $exec_prefix/lib/tkConfig.sh &&
+ test -f $exec_prefix/lib/tkxConfig.sh
then
:
else
}
ldap = ldap_init (ldapHost, ldapPort);
-#if LDAP_OPT_PROTOCOL_VERSION
+#ifdef LDAP_OPT_PROTOCOL_VERSION
if (version != -1)
ldap_set_option(ldap, LDAP_OPT_PROTOCOL_VERSION, &version);
#endif
return TCL_ERROR;
}
-#if UMICH_LDAP
+#ifdef UMICH_LDAP
ldap->ld_deref = LDAP_DEREF_NEVER; /* Turn off alias dereferencing */
#endif
--- /dev/null
+Copyright (C) Virginia Tech, David Hawes.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted only as authorized by the OpenLDAP
+Public License.
+
+A copy of this license is available in file LICENSE in the
+top-level directory of the distribution or, alternatively, at
+http://www.OpenLDAP.org/license.html.
--- /dev/null
+The OpenLDAP Public License
+ Version 2.8, 17 August 2003
+
+ Redistribution and use of this software and associated documentation
+ ("Software"), with or without modification, are permitted provided
+ that the following conditions are met:
+
+ 1. Redistributions in source form must retain copyright statements
+ and notices,
+
+ 2. Redistributions in binary form must reproduce applicable copyright
+ statements and notices, this list of conditions, and the following
+ disclaimer in the documentation and/or other materials provided
+ with the distribution, and
+
+ 3. Redistributions must contain a verbatim copy of this document.
+
+The OpenLDAP Foundation may revise this license from time to time.
+Each revision is distinguished by a version number. You may use
+this Software under terms of this license revision or under the
+terms of any subsequent revision of the license.
+
+THIS SOFTWARE IS PROVIDED BY THE OPENLDAP FOUNDATION AND ITS
+CONTRIBUTORS ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+SHALL THE OPENLDAP FOUNDATION, ITS CONTRIBUTORS, OR THE AUTHOR(S)
+OR OWNER(S) OF THE SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+
+The names of the authors and copyright holders must not be used in
+advertising or otherwise to promote the sale, use or other dealing
+in this Software without specific, written prior permission. Title
+to copyright in this Software shall at all times remain with copyright
+holders.
+
+OpenLDAP is a registered trademark of the OpenLDAP Foundation.
+
+Copyright 1999-2003 The OpenLDAP Foundation, Redwood City,
+California, USA. All Rights Reserved. Permission to copy and
+distribute verbatim copies of this document is granted.
--- /dev/null
+OPENLDAP_SRC=/usr/local/src/openldap-2.3.32
+CPPFLAGS+=-I${OPENLDAP_SRC}/include -I${OPENLDAP_SRC}/servers/slapd
+LDFLAGS+=-L/usr/local/openldap-2.3.32/lib
+CC=gcc
+
+all: addpartial-overlay.so
+
+addpartial-overlay.so: addpartial-overlay.c
+ $(CC) -shared $(CPPFLAGS) $(LDFLAGS) -Wall -o $@ $?
+
+clean:
+ rm addpartial-overlay.so
--- /dev/null
+addpartial Overlay README
+
+DESCRIPTION
+ This package contains an OpenLDAP overlay called "addpartial" that
+ intercepts add requests, determines if the entry exists, determines what
+ attributes, if any, have changed, and modifies those attributes. If the
+ entry does not exist, the add request falls through and proceeds normally.
+ If the entry exists but no changes have been detected, the client receives
+ LDAP_SUCCESS (I suppose it is debatable what to do in this case, but this is
+ the most clean for my use. The LDAP_SUCCESS lets me know that the entry I
+ sent slapd == the entry already in my slapd DB. Perhaps this behavior
+ should be configurable in the future).
+
+ When a change is found, the addpartial overlay will replace all values for
+ the attribute (if an attribute does not exist in the new entry but exists
+ in the entry in the slapd DB, a replace will be done with an empty list of
+ values).
+
+ Once a modify takes place, the addpartial overlay will write changes to the
+ replog (using the slap_replog_cb). If you are using syncrepl for
+ replication, the syncprov overlay will properly process the change, provided
+ that addpartial is the first overlay to run. Please see the CAVEATS for
+ more specifics about this.
+
+ The addpartial overlay makes it easy to replicate full entries to a slapd
+ instance without worrying about the differences between entries or even if
+ the entry exists. Using ldapadd to add entries, the addpartial overlay can
+ compare about 500 records per second. The intent of the addpartial overlay
+ is to make it easy to replicate records from a source that is not an LDAP
+ instance, such as a database. The overlay is also useful in places where it
+ is easier to create full entries rather than comparing an entry with an
+ entry that must be retrieved (with ldapsearch or similar) from an existing
+ slapd DB to find changes.
+
+ The addpartial overlay has been used in production since August 2004 and has
+ processed millions of records without incident.
+
+BUILDING
+ A Makefile is included, please set your OPENLDAP_SRC directory properly.
+
+INSTALLATION
+ After compiling the addpartial overlay, add the following to your
+ slapd.conf:
+
+ ### slapd.conf
+ ...
+ moduleload /path/to/addpartial-overlay.so
+ ...
+ # after database directive...
+ # this overlay should be the last overlay in the config file to ensure that
+ # it properly intercepts the add request
+ overlay addpartial
+ ...
+ ### end slapd.conf
+
+CAVEATS
+ - In order to ensure that addpartial does what it needs to do, it should be
+ the last overlay configured so it will run before the other overlays.
+ This is especially important if you are using syncrepl, as the modify that
+ addpartial does will muck with the locking that takes place in the
+ syncprov overlay.
--- /dev/null
+/**
+ * $Id: addpartial-overlay.c 5376 2007-01-26 20:03:13Z dhawes $
+ *
+ * Copyright (C) 2004 Virginia Tech, David Hawes.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted only as authorized by the OpenLDAP
+ * Public License.
+ *
+ * A copy of this license is available in file LICENSE in the
+ * top-level directory of the distribution or, alternatively, at
+ * http://www.OpenLDAP.org/license.html.
+ *
+ * SEE LICENSE FOR MORE INFORMATION
+ *
+ * Author: David H. Hawes, Jr.
+ * Email: dhawes@vt.edu
+ * Version: $Revision: 5376 $
+ * Updated: $Date: 2007-01-26 15:03:13 -0500 (Fri, 26 Jan 2007) $
+ *
+ * addpartial-overlay
+ *
+ * This is an OpenLDAP overlay that intercepts ADD requests, determines if a
+ * change has actually taken place for that record, and then performs a modify
+ * request for those values that have changed (modified, added, deleted). If
+ * the record has not changed in any way, it is ignored. If the record does not
+ * exist, the record falls through to the normal add mechanism. This overlay is
+ * useful for replicating from sources that are not LDAPs where it is easier to
+ * build entire records than to determine the changes (i.e. a database).
+ */
+
+#include "portable.h"
+#include <stdio.h>
+#include <ac/string.h>
+#include <ac/socket.h>
+#include "slap.h"
+#include <unistd.h>
+#include <lutil.h>
+
+static int addpartial_search_cb( Operation *op, SlapReply *rs);
+static int collect_error_msg_cb( Operation *op, SlapReply *rs);
+
+static slap_overinst addpartial;
+
+/**
+ * The meat of the overlay. Search for the record, determine changes, take
+ * action or fall through.
+ */
+static int addpartial_add( Operation *op, SlapReply *rs)
+{
+ Operation nop = *op;
+ SlapReply nrs = { REP_RESULT };
+ Filter *filter = NULL;
+ Entry *toAdd = NULL;
+ struct berval fstr = BER_BVNULL;
+ slap_callback cb = { NULL, addpartial_search_cb, NULL, NULL };
+ slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
+ int rc;
+
+ toAdd = op->oq_add.rs_e;
+
+ Debug(LDAP_DEBUG_TRACE, "%s: toAdd->e_nname.bv_val: %s\n",
+ addpartial.on_bi.bi_type, toAdd->e_nname.bv_val,0);
+
+ /* if the user doesn't have access, fall through to the normal ADD */
+ if(!access_allowed(op, toAdd, slap_schema.si_ad_entry,
+ NULL, ACL_WRITE, NULL))
+ {
+ return SLAP_CB_CONTINUE;
+ }
+
+ rs->sr_text = NULL;
+
+ nop.o_callback = &cb;
+ op->o_bd->bd_info = (BackendInfo *) on->on_info;
+ nop.o_tag = LDAP_REQ_SEARCH;
+ nop.o_ctrls = NULL;
+
+ filter = str2filter("(objectclass=*)");
+ filter2bv(filter, &fstr);
+
+ nop.ors_scope = LDAP_SCOPE_BASE;
+ nop.ors_deref = LDAP_DEREF_NEVER;
+ nop.ors_slimit = -1;//SLAP_NO_LIMIT;
+ nop.ors_tlimit = -1;//SLAP_NO_LIMIT;
+ nop.ors_attrsonly = 0;
+ nop.ors_attrs = slap_anlist_no_attrs;
+ nop.ors_filter = filter;
+ nop.ors_filterstr = fstr;
+
+ memset(&nrs, 0, sizeof(nrs));
+ nrs.sr_type = REP_RESULT;
+ nrs.sr_err = LDAP_SUCCESS;
+ nrs.sr_entry = NULL;
+ nrs.sr_flags |= REP_ENTRY_MUSTBEFREED;
+ nrs.sr_text = NULL;
+
+ Debug(LDAP_DEBUG_TRACE, "%s: performing search\n", addpartial.on_bi.bi_type,
+ 0,0);
+
+ if(nop.o_bd->be_search)
+ {
+ rc = nop.o_bd->be_search(&nop, &nrs);
+ Debug(LDAP_DEBUG_TRACE, "%s: search performed\n",
+ addpartial.on_bi.bi_type,0,0);
+ }
+ else
+ {
+ Debug(LDAP_DEBUG_TRACE, "%s: backend missing search function\n",
+ addpartial.on_bi.bi_type,0,0);
+ }
+
+ if(filter)
+ filter_free(filter);
+ if(fstr.bv_val)
+ ch_free(fstr.bv_val);
+
+ if(rc != LDAP_SUCCESS)
+ return SLAP_CB_CONTINUE;
+ else
+ {
+ Entry *found = NULL;
+ Debug(LDAP_DEBUG_TRACE, "%s: found the dn\n", addpartial.on_bi.bi_type,
+ 0,0);
+ found = (Entry *) cb.sc_private;
+
+ if(found)
+ {
+ Attribute *attr = NULL;
+ Attribute *at = NULL;
+ int ret;
+ Modifications *mods = NULL;
+ Modifications **modtail = &mods;
+ Modifications *mod = NULL;
+
+ Debug(LDAP_DEBUG_TRACE, "%s: have an entry!\n",
+ addpartial.on_bi.bi_type,0,0);
+
+ /* determine if the changes are in the found entry */
+ for(attr = toAdd->e_attrs; attr; attr = attr->a_next)
+ {
+ if(attr->a_desc->ad_type->sat_atype.at_usage != 0) continue;
+
+ at = attr_find(found->e_attrs, attr->a_desc);
+ if(!at)
+ {
+ Debug(LDAP_DEBUG_TRACE, "%s: Attribute %s not found!\n",
+ addpartial.on_bi.bi_type,
+ attr->a_desc->ad_cname.bv_val,0);
+ mod = (Modifications *) ch_malloc(sizeof(
+ Modifications));
+ mod->sml_flags = 0;
+ mod->sml_op = LDAP_MOD_REPLACE | LDAP_MOD_BVALUES;
+ mod->sml_op &= LDAP_MOD_OP;
+ mod->sml_next = NULL;
+ mod->sml_desc = attr->a_desc;
+ mod->sml_type.bv_val = attr->a_desc->ad_cname.bv_val;
+ mod->sml_type.bv_len = strlen(mod->sml_type.bv_val);
+ mod->sml_values = attr->a_vals;
+ mod->sml_nvalues = attr->a_nvals;
+ *modtail = mod;
+ modtail = &mod->sml_next;
+ }
+ else
+ {
+ MatchingRule *mr = attr->a_desc->ad_type->sat_equality;
+ struct berval *bv;
+ const char *text;
+ int acount , bcount;
+ Debug(LDAP_DEBUG_TRACE, "%s: Attribute %s found\n",
+ addpartial.on_bi.bi_type,
+ attr->a_desc->ad_cname.bv_val,0);
+
+ for(bv = attr->a_vals, acount = 0; bv->bv_val != NULL;
+ bv++, acount++)
+ {
+ /* count num values for attr */
+ }
+ for(bv = at->a_vals, bcount = 0; bv->bv_val != NULL;
+ bv++, bcount++)
+ {
+ /* count num values for attr */
+ }
+ if(acount != bcount)
+ {
+ Debug(LDAP_DEBUG_TRACE, "%s: acount != bcount, %s\n",
+ addpartial.on_bi.bi_type,
+ "replace all",0);
+ mod = (Modifications *) ch_malloc(sizeof(
+ Modifications));
+ mod->sml_flags = 0;
+ mod->sml_op = LDAP_MOD_REPLACE | LDAP_MOD_BVALUES;
+ mod->sml_op &= LDAP_MOD_OP;
+ mod->sml_next = NULL;
+ mod->sml_desc = attr->a_desc;
+ mod->sml_type.bv_val = attr->a_desc->ad_cname.bv_val;
+ mod->sml_type.bv_len = strlen(mod->sml_type.bv_val);
+ mod->sml_values = attr->a_vals;
+ mod->sml_nvalues = attr->a_nvals;
+ *modtail = mod;
+ modtail = &mod->sml_next;
+ continue;
+ }
+
+ for(bv = attr->a_vals; bv->bv_val != NULL; bv++)
+ {
+ struct berval *v;
+ ret = -1;
+
+ for(v = at->a_vals; v->bv_val != NULL; v++)
+ {
+ int r;
+ if(mr && ((r = value_match(&ret, attr->a_desc, mr,
+ SLAP_MR_VALUE_OF_ASSERTION_SYNTAX,
+ bv, v, &text)) == 0))
+ {
+ if(ret == 0)
+ break;
+ }
+ else
+ {
+ Debug(LDAP_DEBUG_TRACE,
+ "%s: \tvalue DNE, r: %d \n",
+ addpartial.on_bi.bi_type,
+ r,0);
+ ret = strcmp(bv->bv_val, v->bv_val);
+ if(ret == 0)
+ break;
+ }
+ }
+
+ if(ret == 0)
+ {
+ Debug(LDAP_DEBUG_TRACE,
+ "%s: \tvalue %s exists, ret: %d\n",
+ addpartial.on_bi.bi_type, bv->bv_val, ret);
+ }
+ else
+ {
+ Debug(LDAP_DEBUG_TRACE,
+ "%s: \tvalue %s DNE, ret: %d\n",
+ addpartial.on_bi.bi_type, bv->bv_val, ret);
+ mod = (Modifications *) ch_malloc(sizeof(
+ Modifications));
+ mod->sml_flags = 0;
+ mod->sml_op = LDAP_MOD_REPLACE | LDAP_MOD_BVALUES;
+ mod->sml_op &= LDAP_MOD_OP;
+ mod->sml_next = NULL;
+ mod->sml_desc = attr->a_desc;
+ mod->sml_type.bv_val =
+ attr->a_desc->ad_cname.bv_val;
+ mod->sml_type.bv_len = strlen(mod->sml_type.bv_val);
+ mod->sml_values = attr->a_vals;
+ mod->sml_nvalues = attr->a_nvals;
+ *modtail = mod;
+ modtail = &mod->sml_next;
+ break;
+ }
+ }
+ }
+ }
+
+ /* determine if any attributes were deleted */
+ for(attr = found->e_attrs; attr; attr = attr->a_next)
+ {
+ if(attr->a_desc->ad_type->sat_atype.at_usage != 0) continue;
+
+ at = NULL;
+ at = attr_find(toAdd->e_attrs, attr->a_desc);
+ if(!at)
+ {
+ Debug(LDAP_DEBUG_TRACE,
+ "%s: Attribute %s not found in new entry!!!\n",
+ addpartial.on_bi.bi_type,
+ attr->a_desc->ad_cname.bv_val, 0);
+ mod = (Modifications *) ch_malloc(sizeof(
+ Modifications));
+ mod->sml_flags = 0;
+ mod->sml_op = LDAP_MOD_REPLACE;
+ mod->sml_next = NULL;
+ mod->sml_desc = attr->a_desc;
+ mod->sml_type.bv_val =
+ attr->a_desc->ad_cname.bv_val;
+ mod->sml_type.bv_len = strlen(mod->sml_type.bv_val);
+ mod->sml_values = NULL;
+ mod->sml_nvalues = NULL;
+ *modtail = mod;
+ modtail = &mod->sml_next;
+ }
+ else
+ {
+ Debug(LDAP_DEBUG_TRACE,
+ "%s: Attribute %s found in new entry\n",
+ addpartial.on_bi.bi_type,
+ at->a_desc->ad_cname.bv_val, 0);
+ }
+ }
+
+ if(mods)
+ {
+ Debug(LDAP_DEBUG_TRACE, "%s: mods to do...\n",
+ addpartial.on_bi.bi_type, 0, 0);
+ if(nop.o_bd->be_modify)
+ {
+ Modifications *m = NULL;
+ int modcount;
+ slap_callback cb2 = { NULL, slap_replog_cb, NULL, NULL };
+ slap_callback nullcb = { NULL, collect_error_msg_cb,
+ NULL, NULL };
+ char textbuf[SLAP_TEXT_BUFLEN];
+ size_t textlen = sizeof textbuf;
+
+ memset(&nrs, 0, sizeof(nrs));
+ nrs.sr_type = REP_RESULT;
+ nrs.sr_err = LDAP_SUCCESS;
+ nrs.sr_entry = NULL;
+ nrs.sr_text = NULL;
+
+ nop.o_tag = LDAP_REQ_MODIFY;
+ nop.orm_modlist = mods;
+ cb2.sc_next = &nullcb;
+ nop.o_callback = &cb2;
+ nop.o_bd->bd_info = (BackendInfo *) on->on_info;
+
+ for(m = mods, modcount = 0; m; m = m->sml_next,
+ modcount++)
+ {
+ /* count number of mods */
+ }
+
+ Debug(LDAP_DEBUG_TRACE, "%s: number of mods: %d\n",
+ addpartial.on_bi.bi_type, modcount, 0);
+
+ rc = (nop.o_bd->be_modify)(&nop, &nrs);
+
+ if(rc == LDAP_SUCCESS)
+ {
+ Debug(LDAP_DEBUG_TRACE,
+ "%s: modify successful\n",
+ addpartial.on_bi.bi_type, 0, 0);
+ }
+ else
+ {
+ Debug(LDAP_DEBUG_TRACE, "%s: modify unsuccessful: %d\n",
+ addpartial.on_bi.bi_type, rc, 0);
+ rs->sr_err = rc;
+ if(nrs.sr_text)
+ {
+ rs->sr_text = nullcb.sc_private;
+ }
+ }
+
+ Debug(LDAP_DEBUG_TRACE, "%s: freeing mods...\n",
+ addpartial.on_bi.bi_type, 0, 0);
+
+ if(mods != NULL)
+ {
+ Modifications *toDel;
+
+ for(toDel = mods; toDel; toDel = mods)
+ {
+ mods = mods->sml_next;
+ ch_free(toDel);
+ }
+ }
+ }
+ }
+ else
+ {
+ Debug(LDAP_DEBUG_TRACE, "%s: no mods to process\n",
+ addpartial.on_bi.bi_type, 0, 0);
+ }
+
+ if(found != NULL) ;
+ entry_free(found);
+ }
+ else
+ {
+ Debug(LDAP_DEBUG_TRACE, "%s: no entry!\n",
+ addpartial.on_bi.bi_type, 0, 0);
+ }
+
+ op->o_callback = NULL;
+ send_ldap_result( op, rs );
+ ch_free((void *)rs->sr_text);
+ rs->sr_text = NULL;
+
+ return LDAP_SUCCESS;
+ }
+}
+
+static int addpartial_search_cb( Operation *op, SlapReply *rs)
+{
+ Entry *entry = NULL;
+
+ if(rs->sr_type != REP_SEARCH) return 0;
+
+ Debug(LDAP_DEBUG_TRACE, "%s: addpartial_search_cb\n",
+ addpartial.on_bi.bi_type, 0, 0);
+
+ if(rs->sr_entry)
+ {
+ Debug(LDAP_DEBUG_TRACE, "%s: dn found: %s\n",
+ addpartial.on_bi.bi_type, rs->sr_entry->e_nname.bv_val, 0);
+ entry = rs->sr_entry;
+ op->o_callback->sc_private = (void *) entry_dup(entry);
+ }
+
+ return 0;
+}
+
+static int collect_error_msg_cb( Operation *op, SlapReply *rs)
+{
+ if(rs->sr_text)
+ {
+ op->o_callback->sc_private = (void *) ch_strdup(rs->sr_text);
+ }
+
+ return LDAP_SUCCESS;
+}
+
+int addpartial_init()
+{
+ addpartial.on_bi.bi_type = "addpartial";
+ addpartial.on_bi.bi_op_add = addpartial_add;
+
+ return (overlay_register(&addpartial));
+}
+
+int init_module(int argc, char *argv[])
+{
+ return addpartial_init();
+}
#include <ac/string.h>
#include "slap.h"
+#include "config.h"
#define SLAP_OVER_VERSION_REQUIRE(major,minor,patch) \
( \
}
static int
-allop_db_destroy( BackendDB *be )
+allop_db_destroy( BackendDB *be, ConfigReply *cr )
{
slap_overinst *on = (slap_overinst *)be->bd_info;
allop_t *ao = (allop_t *)on->on_bi.bi_private;
* <http://www.OpenLDAP.org/license.html>.
*/
+#include "portable.h"
+
#include <stdio.h>
#include <lber.h>
#include <lber_pvt.h> /* BER_BVC definition */
#include "lutil.h"
+#include <ldap_pvt_thread.h>
#include <ac/string.h>
#include <ac/unistd.h>
static LUTIL_PASSWD_CHK_FUNC chk_radius;
static const struct berval scheme = BER_BVC("{RADIUS}");
static char *config_filename;
+static ldap_pvt_thread_mutex_t libradius_mutex;
static int
chk_radius(
return LUTIL_PASSWD_ERR; /* passwd must behave like a string */
}
+ ldap_pvt_thread_mutex_lock( &libradius_mutex );
+
h = rad_auth_open();
if ( h == NULL ) {
+ ldap_pvt_thread_mutex_unlock( &libradius_mutex );
return LUTIL_PASSWD_ERR;
}
goto done;
}
- if ( rad_send_request( h ) == RAD_ACCESS_ACCEPT ) {
+ switch ( rad_send_request( h ) ) {
+ case RAD_ACCESS_ACCEPT:
rc = LUTIL_PASSWD_OK;
+ break;
+
+ case RAD_ACCESS_REJECT:
+ rc = LUTIL_PASSWD_ERR;
+ break;
+
+ case RAD_ACCESS_CHALLENGE:
+ rc = LUTIL_PASSWD_ERR;
+ break;
+
+ case -1:
+ /* no valid response is received */
+ break;
}
done:;
rad_close( h );
+ ldap_pvt_thread_mutex_unlock( &libradius_mutex );
return rc;
}
+int
+term_module()
+{
+ return ldap_pvt_thread_mutex_destroy( &libradius_mutex );
+}
+
int
init_module( int argc, char *argv[] )
{
}
}
+ ldap_pvt_thread_mutex_init( &libradius_mutex );
+
return lutil_passwd_add( (struct berval *)&scheme, chk_radius, NULL );
}
}
static int
-smbk5pwd_db_init(BackendDB *be)
+smbk5pwd_db_init(BackendDB *be, ConfigReply *cr)
{
slap_overinst *on = (slap_overinst *)be->bd_info;
smbk5pwd_t *pi;
}
static int
-smbk5pwd_db_open(BackendDB *be)
+smbk5pwd_db_open(BackendDB *be, ConfigReply *cr)
{
slap_overinst *on = (slap_overinst *)be->bd_info;
smbk5pwd_t *pi = (smbk5pwd_t *)on->on_bi.bi_private;
}
static int
-smbk5pwd_db_destroy(BackendDB *be)
+smbk5pwd_db_destroy(BackendDB *be, ConfigReply *cr)
{
slap_overinst *on = (slap_overinst *)be->bd_info;
smbk5pwd_t *pi = (smbk5pwd_t *)on->on_bi.bi_private;
-v verbose
---
-$Header$
+$OpenLDAP$
--- /dev/null
+
+
+
+Network Working Group S. Haripriya
+Internet-Draft Jaimon. Jose, Ed.
+Updates: 02 (if approved) Jim. Sermersheim
+Intended status: Standards Track Novell, Inc.
+Expires: July 9, 2007 January 5, 2007
+
+
+ LDAP: Dynamic Groups for LDAPv3
+ draft-haripriya-dynamicgroup-02
+
+Status of this Memo
+
+ By submitting this Internet-Draft, each author represents that any
+ applicable patent or other IPR claims of which he or she is aware
+ have been or will be disclosed, and any of which he or she becomes
+ aware will be disclosed, in accordance with Section 6 of BCP 79.
+
+ Internet-Drafts are working documents of the Internet Engineering
+ Task Force (IETF), its areas, and its working groups. Note that
+ other groups may also distribute working documents as Internet-
+ Drafts.
+
+ Internet-Drafts are draft documents valid for a maximum of six months
+ and may be updated, replaced, or obsoleted by other documents at any
+ time. It is inappropriate to use Internet-Drafts as reference
+ material or to cite them other than as "work in progress."
+
+ The list of current Internet-Drafts can be accessed at
+ http://www.ietf.org/ietf/1id-abstracts.txt.
+
+ The list of Internet-Draft Shadow Directories can be accessed at
+ http://www.ietf.org/shadow.html.
+
+ This Internet-Draft will expire on July 9, 2007.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2007).
+
+
+
+
+
+
+
+
+
+
+
+
+
+Haripriya, et al. Expires July 9, 2007 [Page 1]
+\f
+Internet-Draft LDAP: Dynamic Groups for LDAPv3 January 2007
+
+
+Abstract
+
+ This document describes the requirements, semantics, schema elements,
+ and operations needed for a dynamic group feature in LDAP. A dynamic
+ group is defined here as a group object with a membership list of
+ distinguished names that is dynamically generated using LDAP search
+ criteria. The dynamic membership list may then be interrogated by
+ LDAP search and compare operations, and may also be used to find the
+ groups that an object is a member of. This feature eliminates a huge
+ amount of the administrative effort required today for maintaining
+ group memberships and role-based operations in large enterprises.
+
+
+Table of Contents
+
+ 1. Conventions used in this document . . . . . . . . . . . . . . 4
+ 2. Introduction . . . . . . . . . . . . . . . . . . . . . . . . . 5
+ 3. Requirements of a dynamic group feature . . . . . . . . . . . 6
+ 4. Schema and Semantic Definitions for Dynamic Groups . . . . . . 7
+ 4.1. Object Classes . . . . . . . . . . . . . . . . . . . . . . 7
+ 4.1.1. dynamicGroup . . . . . . . . . . . . . . . . . . . . . 7
+ 4.1.2. dynamicGroupOfUniqueNames . . . . . . . . . . . . . . 7
+ 4.1.3. dynamicGroupAux . . . . . . . . . . . . . . . . . . . 7
+ 4.1.4. dynamicGroupOfUniqueNamesAux . . . . . . . . . . . . . 7
+ 4.2. Attributes . . . . . . . . . . . . . . . . . . . . . . . . 8
+ 4.2.1. memberQueryURL . . . . . . . . . . . . . . . . . . . . 8
+ 4.2.2. excludedMember . . . . . . . . . . . . . . . . . . . . 11
+ 4.3. member . . . . . . . . . . . . . . . . . . . . . . . . . . 11
+ 4.4. uniqueMember . . . . . . . . . . . . . . . . . . . . . . . 11
+ 4.5. dgIdentity . . . . . . . . . . . . . . . . . . . . . . . . 11
+ 4.5.1. dgIdentity - Security implications . . . . . . . . . . 12
+ 5. Advertisement of support for dynamic groups . . . . . . . . . 13
+ 6. Dynamic Group Operations . . . . . . . . . . . . . . . . . . . 14
+ 6.1. Existing Operations . . . . . . . . . . . . . . . . . . . 14
+ 6.1.1. Access to resources in the directory . . . . . . . . . 14
+ 6.1.2. Reading a dynamic group object . . . . . . . . . . . . 14
+ 6.1.3. 'Is Member Of' functionality . . . . . . . . . . . . . 15
+ 6.2. New Extensions . . . . . . . . . . . . . . . . . . . . . . 16
+ 6.2.1. Managing the static members of a dynamic group . . . . 16
+ 7. Performance Considerations . . . . . . . . . . . . . . . . . . 17
+ 7.1. Caching of Dynamic Members . . . . . . . . . . . . . . . . 17
+ 8. Security Considerations . . . . . . . . . . . . . . . . . . . 18
+ 9. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 19
+ 10. Conclusions . . . . . . . . . . . . . . . . . . . . . . . . . 20
+ 11. Normative References . . . . . . . . . . . . . . . . . . . . . 21
+ Appendix A. Example Values for memberQueryURL . . . . . . . . . . 22
+ Appendix B. Acknowledgments . . . . . . . . . . . . . . . . . . . 23
+ Authors' Addresses . . . . . . . . . . . . . . . . . . . . . . . . 24
+
+
+
+Haripriya, et al. Expires July 9, 2007 [Page 2]
+\f
+Internet-Draft LDAP: Dynamic Groups for LDAPv3 January 2007
+
+
+ Intellectual Property and Copyright Statements . . . . . . . . . . 25
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Haripriya, et al. Expires July 9, 2007 [Page 3]
+\f
+Internet-Draft LDAP: Dynamic Groups for LDAPv3 January 2007
+
+
+1. Conventions used in this document
+
+ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
+ "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
+ document are to be interpreted as described in [1].
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Haripriya, et al. Expires July 9, 2007 [Page 4]
+\f
+Internet-Draft LDAP: Dynamic Groups for LDAPv3 January 2007
+
+
+2. Introduction
+
+ The LDAP schema described in [4] defines two object classes:
+ 'groupOfNames', and 'groupOfUniqueNames', that hold a static list of
+ distinguished names in their 'member' or 'uniqueMember' attributes
+ respectively, and are typically used to describe a group of objects
+ for various functions. These grouping functions range from simple
+ group membership applications such as email distribution lists to
+ describing common authorization for a set of users The administration
+ and updating of these membership lists must be done by specifically
+ modifying the DN values in the member or uniqueMember attributes.
+ Thus, each time a change in membership happens, a process must exist
+ which adds or removes the particular entry's DN from the member
+ attribute. For example, consider an organization, where the access
+ to its facilities is controlled by membership in a directory group.
+ Assume that all employees in a department have been added to the
+ group that provides access to the required department facility. If
+ an employee moves from one department to another, the administrator
+ must remove the employee from one group and add him to another.
+ Similarly consider an organization that wants to provide access to
+ its facility, to both interns and employees on weekdays, but only to
+ employees on weekends. It would be effort-consuming to achieve this
+ with static groups.
+
+ "Dynamic groups" are like normal groups, but they let one specify
+ criteria to be used for evaluating membership to a group; the
+ membership of the group is determined dynamically by the directory
+ servers involved. This lets the group administrator define the
+ membership in terms of attributes, and let the DSAs worry about who
+ are the actual members. This solution is more scalable and reduces
+ administrative costs. This can also supplement static groups in LDAP
+ to provide flexibility to the user.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Haripriya, et al. Expires July 9, 2007 [Page 5]
+\f
+Internet-Draft LDAP: Dynamic Groups for LDAPv3 January 2007
+
+
+3. Requirements of a dynamic group feature
+
+ The following requirements SHOULD be met by a proposal for the
+ dynamic groups feature:
+
+ 1. Creation and administration of dynamic groups should be done
+ using normal LDAP operations.
+
+ 2. Applications must be able to use dynamic groups in the same way
+ that they are able to use static groups for listing members and
+ for membership evaluation.
+
+ 3. Interrogation of a dynamic group's membership should be done
+ using normal LDAP operations, and should be consistent. This
+ means that all authorization identities with the same permission
+ to the membership attribute of a dynamic group (such as 'read')
+ should be presented with the same membership list.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Haripriya, et al. Expires July 9, 2007 [Page 6]
+\f
+Internet-Draft LDAP: Dynamic Groups for LDAPv3 January 2007
+
+
+4. Schema and Semantic Definitions for Dynamic Groups
+
+ The dynamic group classes are defined by the following schema
+
+4.1. Object Classes
+
+ The following object classes MUST be supported, and their semantics
+ understood by the server, for it to support the dynamic groups
+ feature.
+
+4.1.1. dynamicGroup
+
+ ( <OID.TBD> NAME 'dynamicGroup' SUP groupOfNames STRUCTURAL MAY
+ (memberQueryURL $ excludedMember $ dgIdentity ))
+
+ This structural object class is used to create a dynamic group
+ object. It is derived from groupOfNames, which is defined in [4].
+
+4.1.2. dynamicGroupOfUniqueNames
+
+ ( <OID.TBD> NAME 'dynamicGroupOfUniqueNames' SUP groupOfUniqueNames
+ STRUCTURAL MAY (memberQueryURL $ excludedMember $ dgIdentity ))
+
+ This structural object class is used to create a dynamic group object
+ whose membership list is held in a uniqueMember attribute. It is
+ derived from groupOfUniqueNames, which is defined in [4].
+
+4.1.3. dynamicGroupAux
+
+ ( <OID.TBD> NAME 'dynamicGroupAux' SUP groupOfNames AUXILIARY MAY
+ (memberQueryURL $ excludedMember $ dgIdentity ))
+
+ This auxiliary object class is used to convert an existing object to
+ a dynamic group or to create an object of another object class but
+ with dynamic group capabilities. This is derived from groupOfNames
+ which is defined in [4].
+
+4.1.4. dynamicGroupOfUniqueNamesAux
+
+ ( <OID.TBD> NAME 'dynamicGroupOfUniqueNamesAux' SUP groupOfUniqueNames
+ AUXILIARY MAY (memberQueryURL $ excludedMember $ dgIdentity ))
+
+ This auxiliary object class is used to convert an existing object to
+ a dynamic group of unique names or to create an object of another
+ object class but with dynamic group capabilities. This is derived
+ from groupOfUniqueNames which is defined in [4].
+
+
+
+
+
+Haripriya, et al. Expires July 9, 2007 [Page 7]
+\f
+Internet-Draft LDAP: Dynamic Groups for LDAPv3 January 2007
+
+
+4.2. Attributes
+
+ The following attribute names MUST be supported by the server.
+
+4.2.1. memberQueryURL
+
+ This attribute describes the membership of the list using an LDAPURL
+ [3].
+
+ (<OID.TBD> NAME 'memberQueryURL' SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
+
+ The value of memberQueryURL is encoded as an LDAPURL [3]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Haripriya, et al. Expires July 9, 2007 [Page 8]
+\f
+Internet-Draft LDAP: Dynamic Groups for LDAPv3 January 2007
+
+
+ The BNF from [3] is listed here for reference.
+ldapurl = scheme COLON SLASH SLASH [host [COLON port]] [SLASH dn
+ [QUESTION [attributes] [QUESTION [scope] [QUESTION [filter] [QUESTION
+ extensions]]]]]
+ ; <host> and <port> are defined
+ ; in Sections 3.2.2 and 3.2.3
+ ; of [RFC3986].
+ ; <filter> is from Section 3 of
+ ; [RFC4515], subject to the
+ ; provisions of the
+ ; "Percent-Encoding" section
+ ; below.
+scheme = "ldap"
+dn = distinguishedName ; From Section 3 of [RFC4514],
+ ; subject to the provisions of
+ ; the "Percent-Encoding"
+ ; section below.
+attributes = attrdesc *(COMMA attrdesc)
+attrdesc = selector *(COMMA selector)
+selector = attributeSelector ; From Section 4.5.1 of
+ ; [RFC4511], subject to the
+ ; provisions of the
+ ; "Percent-Encoding" section
+ ; below.
+scope = "base" / "one" / "sub"
+extensions = extension *(COMMA extension)
+extension = [EXCLAMATION] extype [EQUALS exvalue]
+extype = oid ; From section 1.4 of [RFC4512].
+exvalue = LDAPString ; From section 4.1.2 of
+ ; [RFC4511], subject to the
+ ; provisions of the
+ ; "Percent-Encoding" section
+ ; below.
+EXCLAMATION = %x21 ; exclamation mark ("!")
+SLASH = %x2F ; forward slash ("/")
+COLON = %x3A ; colon (":")
+QUESTION = %x3F ; question mark ("?")
+
+
+ For the purpose of evaluating dynamic members, the directory server
+ uses only the dn, scope, filter and extensions fields. All remaining
+ fields are ignored if specified. If other fields are specified, the
+ server SHALL ignore them and MAY omit them when presenting the value
+ to a client. The dn is used to specify the base dn from which to
+ start the search for dynamic members. The scope specifies the scope
+ with respect to the dn in which to search for dynamic members. The
+ filter specifies the criteria with which to select objects for
+ dynamic membership.
+
+
+
+Haripriya, et al. Expires July 9, 2007 [Page 9]
+\f
+Internet-Draft LDAP: Dynamic Groups for LDAPv3 January 2007
+
+
+4.2.1.1. The x-chain extension
+
+ A new extension is defined for use of the memberQueryURL in dynamic
+ groups, named 'x-chain'. x-chain does not take a value. When x-chain
+ is present, the server must follow any search continuation references
+ to other servers while searching for dynamic members. When x-chain
+ is absent, the dynamic members computed will be only those that are
+ present on the server from which the search is made. A directory
+ server supporting the memberQueryURL MAY support the x-chain
+ extension, thus the x-chain extension could be critical or non-
+ critical as specified by the '!' prefix to the extension type.
+
+4.2.1.2. Semantics of multiple values for memberQueryURL
+
+ The memberQueryURL MAY have multiple values, and in that case, the
+ members of the dynamic group will be the union of the members
+ computed using each individual URL value. This is useful in
+ specifying a group membership that is made up from subtrees rooted at
+ different base DNs, and possibly using different filters.
+
+4.2.1.3. Condition of membership
+
+ An object O is a member of a dynamic group G if and only if
+
+ (( O is a value of the 'member' or 'uniqueMember' attribute of G)
+
+ OR
+
+ (( O is selected by the membership criteria specified in the
+ 'memberQueryURL' attribute values of G)
+
+ AND
+
+ ( O is not listed in the 'excludedMember' attribute of G) ))
+
+ If a member M of a dynamic group G happens to be a dynamic or a
+ static group, the static or dynamic members of M SHALL NOT be
+ considered as members of G. M is a member of G though.
+
+ The last condition is imposed because
+
+ o Recursively evaluating members of members may degrade the
+ performance of the server drastically.
+
+ o Looping may occur particularly in situations where the search
+ chains across multiple-servers.
+
+
+
+
+
+Haripriya, et al. Expires July 9, 2007 [Page 10]
+\f
+Internet-Draft LDAP: Dynamic Groups for LDAPv3 January 2007
+
+
+ o Dynamic membership assertions (compare operation) cannot be
+ optimized if recursive memberships are allowed. Without
+ recursion, comparisons can be made light-weight.
+
+4.2.2. excludedMember
+
+ ( <OID.TBD> NAME 'excludedMember' SUP distinguishedName )
+
+ This attribute is used to exclude entries from being a dynamic member
+ of a dynamic group. Thus an entry is a dynamic member of a dynamic
+ group if and only if it is selected by the member criteria specified
+ by the 'memberQueryURL' attribute or explicitly added to the member
+ or uniqueMember attribute, and it is not listed in the
+ 'excludedMember' attribute.
+
+4.3. member
+
+ ( 2.5.4.31 NAME 'member' SUP distinguishedName )
+
+ Defined in [4], this attribute is overloaded when used in the context
+ of a dynamic group. It is used to explicitly specify static members
+ of a dynamic group. If the same entry is listed in both the 'member'
+ and 'excludedMember' attributes, the 'member' overrides the
+ 'excludedMember', and the entry is considered to be a member of the
+ group. This attribute is also used to interrogate both the static
+ and dynamic member values of a dynamic group object. Subclasses of
+ this attribute are NOT considered in this manner.
+
+4.4. uniqueMember
+
+ ( 2.5.4.32 NAME 'uniqueMember' SUP distinguishedName )
+
+ Defined in [4], this attribute is overloaded when used in the context
+ of a dynamic group. It is used to specify the static members of a
+ dynamic group. If the same entry is listed in both the
+ 'uniqueMember' and 'excludedMember' attributes, the 'uniqueMember'
+ overrides the 'excludedMember', and the entry is considered to be a
+ member of the group. This attribute is also used to interrogate both
+ the static and dynamic member values of a dynamic group object.
+ Subclasses of this attribute are NOT considered in this manner.
+
+4.5. dgIdentity
+
+ ( <OID.TBD> NAME 'identity' SUP distinguishedName SINGLE-VALUE )
+
+ In order to provide consistent results when processing the search
+ criteria, the server must use a single authorization identity. If
+ the authorization of the bound identity is used, the membership list
+
+
+
+Haripriya, et al. Expires July 9, 2007 [Page 11]
+\f
+Internet-Draft LDAP: Dynamic Groups for LDAPv3 January 2007
+
+
+ will vary, from identity to identity due to differing access
+ controls. This may either be done by the server authenticating as
+ the dgIdentity prior to performing a search or compare operation, or
+ may be done by simply assuming the authorization of the dgIdentity
+ when performing those operations. As server implementations vary, so
+ may the mechanisms to achieve consistent results through the use of
+ the dgIdentity. In the case that the server authenticates as the
+ dgIdentity, it may be required by the server that this identity have
+ proper authentication credentials, and it may be required that this
+ identity reside in the DIB of the local server.
+
+ In the absence of an identity value, or in case the identity value
+ cannot be used, the server will process the memberQueryURL as the
+ anonymous identity. This attribute MAY be supported, and represents
+ the identity the server will use for processing the memberQueryURL.
+
+4.5.1. dgIdentity - Security implications
+
+ Because this attribute indirectly but effectively grants anyone with
+ read or compare access to the member or uniqueMember attribute
+ sufficient permission to gain a DN result set from the
+ memberQueryURL, server implementations SHOULD NOT allow this
+ attribute to be populated with the DN of any object that is not
+ administered by the identity making the change to this attribute.
+ For purposes of this document, to "administer an object" indicates
+ that the administrative identity has the ability to fully update the
+ access control mechanism in place the object in question. As of this
+ writing, there is no way to describe further what it means to be
+ fully able to administer the access control mechanism for an object,
+ so this definition is left as implementation-specific.
+
+ This requirement will allow an entity that has privileges to
+ administer a particular subtree (meaning that entity can add, delete,
+ and update objects in that subtree), to place in the dgIdentity DNs
+ of only those objects it administers.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Haripriya, et al. Expires July 9, 2007 [Page 12]
+\f
+Internet-Draft LDAP: Dynamic Groups for LDAPv3 January 2007
+
+
+5. Advertisement of support for dynamic groups
+
+ If the dynamic groups schema is not present on an LDAP server, it
+ MUST be assumed that the dynamic groups feature is not supported.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Haripriya, et al. Expires July 9, 2007 [Page 13]
+\f
+Internet-Draft LDAP: Dynamic Groups for LDAPv3 January 2007
+
+
+6. Dynamic Group Operations
+
+6.1. Existing Operations
+
+ The following operations SHOULD expose the dynamic groups
+ functionality. These operations do not require any change in the
+ LDAP protocol to be exchanged between the client and server.
+
+6.1.1. Access to resources in the directory
+
+ If access control items are set on a target resource object in the
+ directory, with the subject being a dynamic group object, then all
+ the members of the group object, including the dynamic members, will
+ get the same permissions on the target entry. This would be the most
+ useful application of dynamic groups as seen by an administrator
+ because it lets the server control access to resources based on
+ dynamic membership to a trustee (subject of ACI) of the resource.
+ The way to specify a dynamic ACL is currently implementation
+ specific, as there is no common ACL definition for LDAP, and hence
+ will be dealt with in a separate document or later (TO BE DONE).
+
+6.1.2. Reading a dynamic group object
+
+ When the member attributes of a dynamic group object is listed by the
+ client using an LDAP search operation, the member values returned
+ SHOULD contain both the static and dynamic members of the group
+ object. This functionality will not require a change to the
+ protocol, and the clients need not be aware of dynamic groups to
+ exploit this functionality. This feature is useful for clients that
+ determine access privileges to a resource by themselves, by reading
+ the members of a group object. It will also be useful to
+ administrators who want to see the result of the query URL that they
+ set on the dynamic group entry. Note that this overloads the
+ semantics of the 'member' and 'uniqueMember' attributes. This could
+ lead to some surprises for the client .
+
+ for example: Clients that read the member attribute of a dynamic
+ group object and then attempt to remove values (which were dynamic)
+ could get an error specifying such a value was not there.
+
+ Example:
+
+ Let cn=dg1,o=myorg be a dynamic group object with the following
+ attributes stored in the directory.
+
+
+
+
+
+
+
+Haripriya, et al. Expires July 9, 2007 [Page 14]
+\f
+Internet-Draft LDAP: Dynamic Groups for LDAPv3 January 2007
+
+
+ member: cn=admin,o=myorg
+
+ excludedMember: cn=guest,ou=finance,o=myorg
+
+ excludedMember: cn=robin,ou=finance,o=myorg
+
+ memberQueryURL:
+ ldap:///ou=finance,o=myorg??sub?(objectclass=organizationalPerson)
+
+ If there are 5 organizationalPerson objects under ou=finance,o=myorg
+ with common names bob, alice, john, robin, and guest, then the output
+ of a base-scope LDAP search at cn=dg1,o=myorg, with the attribute
+ list containing 'member' will be as follows:
+
+ dn: cn=dg1,o=myorg
+
+ member: cn=admin,o=myorg
+
+ member: cn=bob,ou=finance,o=myorg
+
+ member: cn=alice,ou=finance,o=myorg
+
+ member: cn=john,ou=finance,o=myorg
+
+6.1.3. 'Is Member Of' functionality
+
+ The LDAP compare operation allows one to discover whether a given DN
+ is in the membership list of a dynamic group. Again, the server
+ SHOULD produce consistent results among different authorization
+ identities when processing this request, as long as those identities
+ have the same access to the member or uniqueMember attribute. Using
+ the data from the example in Section 6.1.2, a compare on
+ cn=dg1,o=myorg, for the AVA member=cn=bob,ou=finance,o=myorg would
+ result in a response of compareTrue (assuming the bound identity was
+ authorized to compare the member attribute of cn=dg1,o=myorg).
+
+ Likewise, a search operation that contains an equalityMatch or
+ presence filter, naming the member or uniqueMember attribute as the
+ attribute (such as (member= cn=bob,ou=finance,o=myorg), or
+ (member=*)), will cause the server to evaluate this filter against
+ the rules given in Section 4.2.1.3 in the event that the search is
+ performed on a dynamic group object. As of this writing, no other
+ matching rules exist for the distinguished name syntax, thus no
+ requirements beyond equalityMatch are given here.
+
+
+
+
+
+
+
+Haripriya, et al. Expires July 9, 2007 [Page 15]
+\f
+Internet-Draft LDAP: Dynamic Groups for LDAPv3 January 2007
+
+
+6.2. New Extensions
+
+ The following new extensions are added for dynamic group support.
+
+6.2.1. Managing the static members of a dynamic group
+
+ Because a dynamic group overloads the semantics of the member and
+ uniqueMember attributes, a mechanism is needed to retrieve the static
+ values found in these attributes for management purposes. To serve
+ this need, a new attribute option is defined here called 'x-static'.
+ Attribute options are discussed in Section 2.5 of [2]. This option
+ SHALL only be specified with the 'member' or 'uniqueMember'
+ attribute. When the LDAP server does not understand the semantics of
+ this option on a given attribute, the option SHOULD be ignored. This
+ attribute option is only used to affect the transmitted values, and
+ does not impose sub-typing semantics on the attribute.
+
+ This option MAY be specified by a client during a search request in
+ the list of attributes to be returned, i.e. member;x-static. In this
+ case, the server SHALL only return those members of the dynamic group
+ that are statically listed as values of the member or uniqueMember
+ attribute. The evaluation process listed in Section 9 SHALL NOT be
+ used to populate the values to be returned.
+
+ This option MAY be specified is either an equalityMatch or presence
+ search filter. In this case, the server evaluates only the values
+ statically listed in the member or uniqueMember attribute, and does
+ not apply the evaluation process listed in Section 9.
+
+ This option MAY be specified in update operations such as add and
+ modify, but SHOULD be ignored, as its presence is semantically the
+ same as its non-presence.
+
+ Note to user: Performing a search to read a dynamic group, with a
+ filter item such as (member=*), and specifying member;x-static, may
+ result in a search result entry that has no member attribute. This
+ may seem counter-intuitive.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Haripriya, et al. Expires July 9, 2007 [Page 16]
+\f
+Internet-Draft LDAP: Dynamic Groups for LDAPv3 January 2007
+
+
+7. Performance Considerations
+
+ When the x-chain extension is present on the memberQueryURL, the
+ server MUST follow any search continuation references to other
+ servers while searching for dynamic members. This may be expensive
+ and slow in a true distributed environment. The dynamicGroup
+ implementation can consider a distributed caching feature to improve
+ the performance. An outline of such a distributed caching is given
+ below.
+
+7.1. Caching of Dynamic Members
+
+ Since the dynamic members of a group are computed every time the
+ group is accessed, the performance could be affected. An
+ implementation of dynamic groups can get around this problem by
+ caching the computed members of a dynamic group locally and using the
+ cached data subsequently. One way to do this is to create pseudo-
+ objects for each dynamic group on every server that holds an object
+ that is a dynamic member of the group. With this, the computation of
+ the dynamic members of a group reduces to the task of reading the
+ pseudo-objects from each server. These pseudo-objects need to be
+ linked from the original dynamic group to speed up the member
+ computation. Also, since these are cached objects, appropriate
+ timeouts need to be associated with the cache after which the cache
+ should be invalidated or refreshed
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Haripriya, et al. Expires July 9, 2007 [Page 17]
+\f
+Internet-Draft LDAP: Dynamic Groups for LDAPv3 January 2007
+
+
+8. Security Considerations
+
+ This document discusses the use of one object as the identity
+ (Section 4.5) with which to read information for another object. If
+ the creation of the dgIdentity attribute is uncontrolled, an intruder
+ could potentially create a dynamic group with the identity of, say,
+ the administrator, to be able to read the directory as the
+ administrator, and see information which would be otherwise
+ unavailable to him. Thus, a person adding an object as identity of a
+ dynamic group should have appropriate permissions on the object being
+ added as identity.
+
+ This document also discusses using dynamic memberships to provide
+ access for resources in a directory. As the dynamic members are not
+ created by the administrator, there could be surprises for the
+ administrator in the form of certain objects getting access to
+ certain resources through dynamic membership, which the administrator
+ never intended. So the administrator should be wary of such
+ problems. The administrator could view the memberships and make sure
+ that anybody who is not supposed to be a member of a group is added
+ to the excludedMember list.
+
+ Denial of service attacks can be launched on an LDAP server, by
+ repeatedly searching for a dynamic group with a large membership list
+ and listing the member attribute. A more effective form of denial of
+ service attack could be launched by making searches of the form
+ (member="somedn") at the top of tree and closing the client
+ connection as soon as the search starts. Some administrative limits
+ be imposed to avoid such situations.
+
+ The dynamic groups feature could be potentially misused by a user to
+ circumvent any administrative size-limit restriction placed on the
+ server. In order to search an LDAP server and obtain the names of
+ all the objects on the server irrespective of admin size-limit
+ restriction on the server, the LDAP user could create a dynamic group
+ with a memberQueryURL which matches all objects in the tree, and list
+ just that one object.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Haripriya, et al. Expires July 9, 2007 [Page 18]
+\f
+Internet-Draft LDAP: Dynamic Groups for LDAPv3 January 2007
+
+
+9. IANA Considerations
+
+ There are no IANA considerations.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Haripriya, et al. Expires July 9, 2007 [Page 19]
+\f
+Internet-Draft LDAP: Dynamic Groups for LDAPv3 January 2007
+
+
+10. Conclusions
+
+ This document discusses the syntax, semantics and usage of dynamic
+ groups in LDAPv3.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Haripriya, et al. Expires July 9, 2007 [Page 20]
+\f
+Internet-Draft LDAP: Dynamic Groups for LDAPv3 January 2007
+
+
+11. Normative References
+
+ [1] Bradner, S., "Key words for use in RFCs to Indicate Requirement
+ Levels", BCP 14, RFC 2119, March 1997.
+
+ [2] Zeilenga, K., "Lightweight Directory Access Protocol (LDAP):
+ Directory Information Models", RFC 4512, June 2006.
+
+ [3] Smith, M. and T. Howes, "Lightweight Directory Access Protocol
+ (LDAP): Uniform Resource Locator", RFC 4516, June 2006.
+
+ [4] Sciberras, A., "Lightweight Directory Access Protocol (LDAP):
+ Schema for User Applications", RFC 4519, June 2006.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Haripriya, et al. Expires July 9, 2007 [Page 21]
+\f
+Internet-Draft LDAP: Dynamic Groups for LDAPv3 January 2007
+
+
+Appendix A. Example Values for memberQueryURL
+
+ 1. This memberQueryURL value specifies the membership criteria for a
+ dynamic group entry as "all inetorgperson entries that also have
+ their title attribute set to 'manager', and are in the DIT-wide
+ subtree under ou=hr,o=myorg ".
+
+ memberQueryURL: ldap:///
+ ou=hr,o=myorg??sub?(&
+ (objectclass=inetorgperson)(title=manager))? x-chain
+
+ 2. This value lets the user specify the membership criteria for a
+ dynamic group entry as "all entries on the local server, that
+ either have unix accounts or belong to the unix department, and
+ are under the engineering container ".
+
+ memberQueryURL: ldap:///ou=eng,o=myorg??sub?
+ (|(objectclass=posixaccount)(department=unix))
+
+ 3. These values let the user specify the membership criteria as "all
+ inetorgperson entries on the local server, in either the
+ ou=eng,o=myorg or ou=support,o=myorg" subtrees.
+
+ memberQueryURL:
+ ldap:///ou=eng,o=myorg??sub?(objectclass=inetorgperson)
+
+ memberQueryURL:
+ ldap:///ou=support,o=myorg??sub?(objectclass=inetorgperson)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Haripriya, et al. Expires July 9, 2007 [Page 22]
+\f
+Internet-Draft LDAP: Dynamic Groups for LDAPv3 January 2007
+
+
+Appendix B. Acknowledgments
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Haripriya, et al. Expires July 9, 2007 [Page 23]
+\f
+Internet-Draft LDAP: Dynamic Groups for LDAPv3 January 2007
+
+
+Authors' Addresses
+
+ Haripriya S
+ Novell, Inc.
+ 49/1 & 49/3 Garvebhavi Palya,
+ 7th Mile, Hosur Road
+ Bangalore, Karnataka 560068
+ India
+
+ Email: sharipriya@novell.com
+
+
+ Jaimon Jose (editor)
+ Novell, Inc.
+ 49/1 & 49/3 Garvebhavi Palya,
+ 7th Mile, Hosur Road
+ Bangalore, Karnataka 560068
+ India
+
+ Email: jjaimon@novell.com
+
+
+ Jim Sermersheim
+ Novell, Inc.
+ 1800 South Novell Place
+ Provo, Utah 84606
+ US
+
+ Email: jimse@novell.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Haripriya, et al. Expires July 9, 2007 [Page 24]
+\f
+Internet-Draft LDAP: Dynamic Groups for LDAPv3 January 2007
+
+
+Full Copyright Statement
+
+ Copyright (C) The Internet Society (2007).
+
+ This document is subject to the rights, licenses and restrictions
+ contained in BCP 78, and except as set forth therein, the authors
+ retain all their rights.
+
+ This document and the information contained herein are provided on an
+ "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS
+ OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND THE INTERNET
+ ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED,
+ INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE
+ INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED
+ WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+
+Intellectual Property
+
+ The IETF takes no position regarding the validity or scope of any
+ Intellectual Property Rights or other rights that might be claimed to
+ pertain to the implementation or use of the technology described in
+ this document or the extent to which any license under such rights
+ might or might not be available; nor does it represent that it has
+ made any independent effort to identify any such rights. Information
+ on the procedures with respect to rights in RFC documents can be
+ found in BCP 78 and BCP 79.
+
+ Copies of IPR disclosures made to the IETF Secretariat and any
+ assurances of licenses to be made available, or the result of an
+ attempt made to obtain a general license or permission for the use of
+ such proprietary rights by implementers or users of this
+ specification can be obtained from the IETF on-line IPR repository at
+ http://www.ietf.org/ipr.
+
+ The IETF invites any interested party to bring to its attention any
+ copyrights, patents or patent applications, or other proprietary
+ rights that may cover technology that may be required to implement
+ this standard. Please address the information to the IETF at
+ ietf-ipr@ietf.org.
+
+
+Acknowledgment
+
+ Funding for the RFC Editor function is provided by the IETF
+ Administrative Support Activity (IASA).
+
+
+
+
+
+Haripriya, et al. Expires July 9, 2007 [Page 25]
+\f
--- /dev/null
+
+
+
+Network Working Group M. Wahl
+Internet-Draft Informed Control Inc.
+Intended status: Standards Track May 9, 2007
+Expires: November 10, 2007
+
+
+ LDAP Session Tracking Control
+ draft-wahl-ldap-session-03
+
+Status of this Memo
+
+ By submitting this Internet-Draft, each author represents that any
+ applicable patent or other IPR claims of which he or she is aware
+ have been or will be disclosed, and any of which he or she becomes
+ aware will be disclosed, in accordance with Section 6 of BCP 79.
+
+ Internet-Drafts are working documents of the Internet Engineering
+ Task Force (IETF), its areas, and its working groups. Note that
+ other groups may also distribute working documents as Internet-
+ Drafts.
+
+ Internet-Drafts are draft documents valid for a maximum of six months
+ and may be updated, replaced, or obsoleted by other documents at any
+ time. It is inappropriate to use Internet-Drafts as reference
+ material or to cite them other than as "work in progress."
+
+ The list of current Internet-Drafts can be accessed at
+ http://www.ietf.org/ietf/1id-abstracts.txt.
+
+ The list of Internet-Draft Shadow Directories can be accessed at
+ http://www.ietf.org/shadow.html.
+
+ This Internet-Draft will expire on November 10, 2007.
+
+Copyright Notice
+
+ Copyright (C) The IETF Trust (2007).
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Wahl Expires November 10, 2007 [Page 1]
+\f
+Internet-Draft LDAP Session Tracking Control May 2007
+
+
+Abstract
+
+ Many network devices, application servers, and middleware components
+ of a enterprise software infrastructure generate some form of session
+ tracking identifiers, which are useful when analyzing activity and
+ accounting logs to group activity relating to a particular session.
+ This document discusses how Lightweight Directory Access Protocol
+ version 3 (LDAP) clients can include session tracking identifiers
+ with their LDAP requests. This information is provided through
+ controls in the requests the clients send to LDAP servers. The LDAP
+ server receiving these controls can include the session tracking
+ identifiers in the log messages it writes, enabling LDAP requests in
+ the LDAP server's logs to be correlated with activity in logs of
+ other components in the infrastructure. The control also enables
+ session tracking information to be generated by LDAP servers and
+ returned to clients and other servers. Three formats of session
+ tracking identifiers are defined in this document.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Wahl Expires November 10, 2007 [Page 2]
+\f
+Internet-Draft LDAP Session Tracking Control May 2007
+
+
+1. Introduction
+
+ The majority of directory server implementations produce access logs
+ detailing each request they receive. These logs can be read using
+ log parsing tools or specialized log viewer applications. Typically
+ it will be possible, for each request logged by a directory server,
+ to determine the bind DN (or possibly another form of authentication
+ identity) of the client which sent the request to the server, and
+ many servers also log the IP address of the client that sent the
+ request.
+
+ In the original OSI architecture, it was envisaged that users might
+ interact with a directory service through specialized applications,
+ known as Directory User Agents, which were the clients of the
+ Directory Access Protocol. Similarly, in early Internet directory
+ deployments, a majority of LDAP clients were desktop applications,
+ that used the LDAP protocol to search an enterprise directory for
+ address book/contact information.
+
+ Today, the majority of LDAP clients are embedded within middleware
+ and server applications. Legacy address book protocols might be
+ gatewayed into LDAP, or a server might consult an LDAP server in
+ order to check a user's password or obtain their preferences. While
+ the LDAP requests might result from a user's activity somewhere on
+ the network, it is rare for the user to be 'driving' the LDAP client,
+ and in most cases the user performing the activity is unaware that
+ LDAP requests are being generated on their behalf.
+
+ However, this information is important to directory system
+ administrators and auditors. They may wish to determine who is
+ making use of the directory service, or track the source of unusual
+ requests.
+
+ When a directory server administrator reviews a log file produced by
+ a directory server that has been accessed only by clients that are
+ themselves middleware, where the end user does not interact with the
+ middleware directly, only through other kinds of servers (e.g.
+ application servers or remote access servers), it will be difficult
+ to correlate between the directory server's log and the logs of the
+ servers which made use of this directory to determine why the LDAP
+ requests were made and who were responsible for causing them.
+
+ Reasons for this include:
+
+ o Directory servers are capable of performing many hundreds of
+ requests per second or more, and even with time synchronization
+ between the systems on which the directory server and middleware
+ are deployed, times of requests might not be logged accurately
+
+
+
+Wahl Expires November 10, 2007 [Page 3]
+\f
+Internet-Draft LDAP Session Tracking Control May 2007
+
+
+ enough to be able to correlate based on time: the server's logs
+ might be only to 1-second resolution.
+
+ o A single function on a middleware server, such as "authenticate a
+ user", may result in multiple LDAP requests being generated in
+ order to perform that request.
+
+ o Many high performance middleware servers implement connection
+ pooling, managing a set of persistent connections to each
+ directory server and multiplexing operations across the
+ connections. Each connection will have the same source IP address
+ and bind DN. If a particular activity causes multiple LDAP
+ requests to be generated, each LDAP request might be sent on a
+ different connection. Also, as LDAP is an asynchronous protocol,
+ middleware servers may have more than one request in progress on
+ each connection, asynchronously sending requests to the directory
+ server on each connection and processing the responses in whatever
+ order they are received.
+
+ This document defines a new control for use in LDAPv3 [1] operation
+ requests. This control contains session tracking information that
+ can be used to correlate log information present in the directory
+ server's log with the logs of other middleware servers.
+
+ The words "MUST", "SHOULD" and "MAY" are used as defined in RFC 2119
+ [2].
+
+1.1. Motivation for session tracking
+
+ A typical enterprise deployment with an application indirectly
+ relying upon the directory might resemble:
+
+
+ +------+ +--------+ +----------+ +--------+
+ | User | | Appli- | | Auth./ | LDAP | LDAP |
+ | +-----+ cation +-------+ Identity +------+ Server |
+ | | | Server | | Provider | | |
+ | A | | B | | C | | D |
+ +------+ +--------+ +----------+ +--------+
+
+
+ In this diagram, a user (A) makes some request of an application
+ server (B). The application server might rely on an integrated or
+ external authentication provider in order to check the user's
+ authentication credentials, or might use an identity provider to
+ obtain profile information about the user. This request might be
+ made through an API or a protocol other than LDAP, e.g. RADIUS,
+ Kerberos, SMB, etc. The authentication/identity provider (C) would
+
+
+
+Wahl Expires November 10, 2007 [Page 4]
+\f
+Internet-Draft LDAP Session Tracking Control May 2007
+
+
+ generate one or more LDAP requests and send them to an LDAP server
+ (D).
+
+ The LDAP server has the following information already available to it
+ through the LDAP protocol: the IP address and authentication
+ credentials of the authentication/identity provider (C). If the
+ provider has included the Proxy Authorization Control [11], then the
+ LDAP server might also receive the Distinguished Name or
+ authorization identity of either the user (A) or the application
+ server (B), depending on how the authentication/identity provider (C)
+ uses the directory. In order to obtain this distinguished name
+ however, the authentication/identity provider (C) might need to
+ perform one or more LDAP search or bind requests. If there is no
+ entry in the directory corresponding to the identity of the user (A)
+ or the application server (B), then there is no way in the base LDAP
+ specification or the Proxy Authorization Control for the
+ authentication/identity provider (C) to describe the user (A) or the
+ application server (B) to the LDAP server (D).
+
+ If either the application server (B) or the authentication/identity
+ provider (C) have generated a session identifier for tracking the
+ interactions of the user (A) for a particular session, then it is
+ useful to include this information with the requests made to the
+ directory server, so that this session identifier will show up in the
+ directory server's logs. That is the purpose of the control defined
+ in the next section.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Wahl Expires November 10, 2007 [Page 5]
+\f
+Internet-Draft LDAP Session Tracking Control May 2007
+
+
+2. Control definition
+
+ There is currently no standard way of describing a session: there are
+ many different formats for a session identifier, and each application
+ that tracks sessions typically has its own semantics for what a
+ session means. Thus, a control is defined using an extensible model,
+ in order to incorporate many different application's concepts and
+ formats of a session tracking identifier.
+
+ The value of the session identifier control encapsulates the
+ following four pieces of information: sessionSourceIp,
+ sessionSourceName, formatOID and sessionTrackingIdentifier.
+
+ The sessionSourceIp field is a US-ASCII string encoding of an IPv4 or
+ IPv6 [3] address of the component of the system which has generated a
+ session tracking identifier. The purpose of this field is to enable
+ the directory server administrator, even if they do not have a log
+ parser that understands a particular session tracking identifier
+ format, to at least be able to identify the server that manages the
+ session. Note that there is no guarantee of IP-level connectivity
+ between the directory server and the system which generated the
+ tracking identifier, and if Network Address Translation is being
+ used, the IP address in this field might be from a private use
+ address range.
+
+ The sessionSourceName field is a UTF-8 [4] encoded ISO 10646 [5] text
+ string. This field describes the component of the system which has
+ generated a session tracking identifier. The format of this field is
+ determined by the formatOID (discussed below); examples of contents
+ of a sessionSourceName field might be a hostname, a distinguished
+ name, or a web service address. This contents of this field is not
+ intended to identify an end user; instead it identifies the server
+ using a name other than the server's IP address.
+
+ The formatOID is a US-ASCII encoded dotted decimal representation of
+ an OBJECT IDENTIFIER. The OBJECT IDENTIFIER indicates the scheme
+ that is used to generate the sessionSourceName and
+ sessionTrackingIdentifier fields. As there is currently no standard
+ scheme for session information, it is expected that there will be
+ many different formats carried within this control. The OBJECT
+ IDENTIFIERs for three formats are presented in this document.
+
+ The sessionTrackingIdentifier field is a UTF-8 encoded ISO 10646
+ string. The session identifier SHOULD be limited to whitespace and
+ printable characters; non-printing and control characters SHOULD NOT
+ be used, and byte sequences that are not legal UTF-8 MUST NOT be
+ used. The syntax of the session identifier and its semantics (e.g.,
+ how values are compared for equality) are governed by the formatOID.
+
+
+
+Wahl Expires November 10, 2007 [Page 6]
+\f
+Internet-Draft LDAP Session Tracking Control May 2007
+
+
+ For example, the session identifier might be a simple string encoding
+ of a decimal counter, a username, a timestamp, a fragment of XML, or
+ it might be something else, depending on the format.
+
+2.1. Formal definition
+
+ This document defines a single LDAP control.
+
+ The controlType is 1.3.6.1.4.1.21008.108.63.1, the criticality MUST
+ be either FALSE or absent, and the controlValue MUST be present. The
+ controlValue OCTET STRING is always present and contains the bytes of
+ the BER [6] encoding of a value of the ASN.1 data type
+ SessionIdentifierControlValue, defined as follows:
+
+ LDAP-Session-Identifier-Control
+ DEFINITIONS IMPLICIT TAGS ::=
+ BEGIN
+
+ LDAPString ::= OCTET STRING -- UTF-8 encoded
+ LDAPOID ::= OCTET STRING -- Constrained to numericoid
+
+ SessionIdentifierControlValue ::= SEQUENCE {
+ sessionSourceIp LDAPString,
+ sessionSourceName LDAPString,
+ formatOID LDAPOID,
+ sessionTrackingIdentifier LDAPString
+ }
+
+ END
+
+ The sessionSourceIp element SHOULD NOT be longer than 42 characters
+ (the length necessary for a string representation of an IPv6
+ address), and MUST NOT be longer than 128 characters. Each character
+ will be encoded into a single byte. If the IP address of the system
+ which generated the session tracking identifier is not known, the
+ sessionSourceIp element SHOULD be of zero length.
+
+ The sessionSourceName element SHOULD NOT be longer than 1024
+ characters, and MUST NOT be longer than 65536 bytes. Note that in
+ the UTF-8 encoding a character MAY be encoded into more than one
+ byte. If no other addressing information about that system is known
+ or relevant to the format, the sessionSourceName element SHOULD be of
+ zero length.
+
+ The formatOID element MUST contain only the US-ASCII encodings of the
+ ISO 10646 characters FULL STOP and DIGIT ZERO through DIGIT NINE
+ (0x2E, 0x30-0x39). The formatOID element MUST NOT be of zero length,
+ and SHOULD NOT be longer than 1024 characters.
+
+
+
+Wahl Expires November 10, 2007 [Page 7]
+\f
+Internet-Draft LDAP Session Tracking Control May 2007
+
+
+ The sessionTrackingIdentifier field MAY be of zero length (although
+ this might not be useful). There is no upper bound on the
+ sessionTrackingIdentifier, but it is suggested that values SHOULD NOT
+ be longer than 65536 characters without prior agreement with the
+ directory server administrator. Note that in the UTF-8 encoding a
+ character MAY be encoded into more than one byte.
+
+2.2. Use in LDAP
+
+ The control MAY be included in any LDAP operation. The control has
+ order-dependent semantics.
+
+ A client might place the control on a message with a bindRequest,
+ searchRequest, modifyRequest, addRequest, delRequest, modDNRequest,
+ compareRequest or extendedReq. A client MAY include multiple
+ controls of this type in a single request. This enables the client
+ to incorporate multiple distinct session tracking identifiers with
+ different formats.
+
+ When a network service is proxying or chaining LDAP, in which the
+ service receives an incoming LDAP request from a client and from this
+ generates one or more requests to other LDAP servers, the service
+ SHOULD include any controls of this type that it received from
+ clients in requests it generates, without modification. A service
+ MAY silently remove a control if that control would violate security
+ policy. If the service has its own session state identifier, it
+ SHOULD include the session identifier control it generates in the
+ Controls SEQUENCE after any session identifier controls received by
+ clients. (If there are multiple proxies involved, each will add
+ their own session state to the end of the controls list).
+
+ A server might place the control on message with a bindResponse,
+ searchResDone, modifyResponse, addResponse, delResponse,
+ modDNResponse, compareResponse, extendedResp or intermediateResponse.
+ The server can include the control in the response regardless of
+ whether the client included a control in the request or not. (The
+ control in a response is unsolicited, and a client which does not
+ recognize the control or a session tracking format can safely ignore
+ the control, as discussed in the following section). A server MAY
+ include multiple controls of this type in a response.
+
+2.3. Extensibility considerations
+
+ The following section of this document defines 3 possible formats,
+ and it is expected that applications MAY define their own formats to
+ represent session tracking identifiers already implemented.
+
+ An application developer or server developer who wishes to transfer
+
+
+
+Wahl Expires November 10, 2007 [Page 8]
+\f
+Internet-Draft LDAP Session Tracking Control May 2007
+
+
+ their implementation's format for session tracking identifier within
+ an LDAP control MUST choose a new, unique, OBJECT IDENTIFIER to
+ represent this format.
+
+ The format determines the semantics of the sessionSourceName string,
+ and the sessionTrackingIdentifier string.
+
+ In general, when an LDAP server that has session tracking logging
+ enabled receives one or more of these controls with a request, the
+ server SHOULD include all fields of all of the controls with the
+ logging information for the request.
+
+ A LDAP server that supports third-party or extensible log parsing
+ tools SHOULD NOT reject or ignore a control if the formatOID value is
+ not recognized, as it is expected that applications may include
+ session tracking identifiers and want to make this information
+ available to log parsers for correlation purposes, even if the
+ directory server does not need to make any use of this information.
+
+ However, if the LDAP server does not recognize the control, the
+ control is not properly formatted, or the LDAP client is not
+ authorized to use this control, the LDAP server SHOULD ignore the
+ control and process the request as if the control had not been
+ included.
+
+ When an LDAP client receives a response that includes this control,
+ the behavior depends on the client implementation. Clients SHOULD
+ silently ignore controls with formats they do not recognize, and
+ process the response as if the control had not been included.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Wahl Expires November 10, 2007 [Page 9]
+\f
+Internet-Draft LDAP Session Tracking Control May 2007
+
+
+3. Session tracking format definitions
+
+ This section defines three session tracking formats that can be used
+ within the session tracking control: two for RADIUS accounting, and
+ one based on usernames. Other formats can be defined in other
+ documents.
+
+3.1. Formats for use with RADIUS accounting
+
+ This section defines two possible session tracking formats, that can
+ be used in LDAP clients that are part of or used by RADIUS servers
+ [7].
+
+ With formatOID set to 1.3.6.1.4.1.21008.108.63.1.1 within the control
+ value, the sessionTrackingIdentifier SHOULD contain the value of the
+ Acct-Session-Id RADIUS attribute (type 44), as defined in RFC 2866
+ [8]. (RFC 2866 section 5.5 states that the Acct-Session-Id SHOULD
+ contain UTF-8 encoded ISO 10646 characters.)
+
+ With formatOID set to 1.3.6.1.4.1.21008.108.63.1.2 within the control
+ value, the sessionTrackingIdentifier SHOULD contain the value of the
+ Acct-Multi-Session-Id RADIUS attribute (type 50), as defined in RFC
+ 2866 [8]. (RFC 2866 section 5.11 states that the
+ Acct-Multi-Session-Id SHOULD contain UTF-8 encoded ISO 10646
+ characters.)
+
+ In both of these two formats, the value of the sessionSourceIp field
+ SHOULD contain either a string encoding value of the IPv4 address
+ from the NAS-IP-Address RADIUS attribute (type 4), or a string
+ encoding of the IPv6 address from the value of the NAS-IPv6-Address
+ RADIUS attribute (type 95) as defined in RFC 3162 [9]. The value of
+ the sessionSourceName field SHOULD contain a string encoding the
+ value of the NAS-Identifier RADIUS attribute (type 32), if present,
+ or be of zero length if the NAS-Identifier RADIUS attribute was not
+ provided or was not in a recognized format.
+
+3.2. Format for username accounting
+
+ This section defines another possible session tracking format that
+ can be used in LDAP clients that are part of applications which
+ identify users with simple string usernames.
+
+ With formatOID set to 1.3.6.1.4.1.21008.108.63.1.3 within the control
+ value, the sessionTrackingIdentifier SHOULD contain a username that
+ has already been authenticated by the application that is generating
+ the session. This format SHOULD NOT be used for purported names,
+ where the application has not verified that the username is valid.
+
+
+
+
+Wahl Expires November 10, 2007 [Page 10]
+\f
+Internet-Draft LDAP Session Tracking Control May 2007
+
+
+ The sessionSourceName field SHOULD contain the hostname where that
+ application is running, or be of zero length if the hostname is not
+ known.
+
+ The username SHOULD be a SASL authorization identity string, as
+ described in section 3.4.1 of RFC 4422 [10]. It is expected that
+ these usernames are not globally unique, but are only unique within
+ the context of a particular application or particular enterprise. A
+ username need not be a distinguished name, and an implementation
+ receiving a control in this format MUST NOT assume that the contents
+ of the sessionTrackingIdentifier can be parsed as a distinguished
+ name.
+
+ A control with this format differs from the Proxied Authorization
+ Control as defined in RFC 4370 [11], as the presence of this session
+ identifier control on a request SHOULD NOT influence the directory
+ server's access control decision of whether or how to perform that
+ request.
+
+ Note that this format does not provide any information to
+ differentiate between multiple sessions or periods of interaction by
+ the same user. It is primarily intended for deployments which merely
+ need to be able to tie each directory operation to they identity of
+ the user whose activities caused the operation request to be
+ generated, even if the user might not even be represented in the
+ directory where the operations are being performed.
+
+3.2.1. Example
+
+ For example, if an application server "app.example.com" with IPv4
+ address "192.0.2.1" had authenticated an user with name "bloggs", and
+ then sent a search request to the LDAP directory in order to obtain
+ some public information on service configuration intending to provide
+ it to that user, the application might include a session identifier
+ control. The SessionIdentifierControlValue would have the following
+ ASN.1 value prior to encoding:
+
+
+ { -- SEQUENCE
+ "192.0.2.1", -- sessionSourceIp
+ "app.example.com", -- sessionSourceName
+ "1.3.6.1.4.1.21008.108.63.1.3", -- formatOID
+ "bloggs" -- sessionTrackingIdentifier
+ }
+
+
+
+
+
+
+
+Wahl Expires November 10, 2007 [Page 11]
+\f
+Internet-Draft LDAP Session Tracking Control May 2007
+
+
+ The session identifier control would be sent with controlType
+ 1.3.6.1.4.1.21008.108.63.1, criticality FALSE, and the controlValue
+ the BER encoding of the SessionIdentifierControlValue. The control
+ included with the LDAP request would resemble:
+
+
+ { -- SEQUENCE
+ "1.3.6.1.4.1.21008.108.63.1", -- controlType
+ FALSE, -- criticality
+ '304204093139322e302e322e31040f6170702e6578616d706c652e636f6d
+ 041c312e332e362e312e342e312e32313030382e3130382e36332e312e33
+ 0406626c6f676773'H -- controlValue
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Wahl Expires November 10, 2007 [Page 12]
+\f
+Internet-Draft LDAP Session Tracking Control May 2007
+
+
+4. Security Considerations
+
+ The session identifier controls used in this document are not
+ intended as a security control or proxy authentication mechanism, and
+ SHOULD NOT be used within a directory server to influence the
+ operation processing behavior.
+
+ Malicious clients might attempt to provide false or misleading
+ information in directory server logs through the use of this control.
+ LDAP servers SHOULD implement access checks which limit whether
+ session identifier information provided by a client is logged. LDAP
+ servers which implement this control SHOULD permit the administrator
+ of the directory server to configure that this control is ignored
+ unless the request containing the control was received from a client
+ that been authenticated. LDAP servers which implement this control
+ SHOULD permit the administrator of the directory server to configure
+ that this control is ignored unless the client is authorized to use
+ this or related controls, such as the Proxied Authorization Control
+ [11]. Session identifier information from clients which do not meet
+ the server's access check requirement SHOULD be silently discarded.
+
+ In some formats, session tracking identifiers may contain personal-
+ identifiable information, such as usernames or client IP addresses.
+ Unless data link, network or transport level encryption is being
+ used, this information might be visible to attackers monitoring the
+ network segments across which this information is being transmitted.
+ Implementations of LDAP clients which include this control in
+ requests sent to directory servers SHOULD support the use of
+ underlying security services that establish connection
+ confidentiality before the control is sent, such as a SASL mechanism
+ that negotiates a security layer, or the Start TLS operation.
+
+ Correlation of activities across multiple servers can enable
+ administrators and monitoring tools to construct a more accurate
+ picture of user behavior. In particular, this tracking control could
+ be used to determine the set of applications and services with which
+ a particular user has had interactions. Thus, this control would not
+ be appropriate to deployments intending to anonymize directory
+ requests. Session formats containing personal identifiable
+ information SHOULD NOT be used between systems in different
+ organizations where there is no existing agreement between those
+ organizations on privacy protection.
+
+ A value of the session tracking control might contain internal IP
+ addresses, hostnames and other identifiers that reveal the structure
+ of an enterprise network. A network service that generates its own
+ sessions SHOULD NOT send a session tracking control to a directory
+ server that is under different administration or in a different
+
+
+
+Wahl Expires November 10, 2007 [Page 13]
+\f
+Internet-Draft LDAP Session Tracking Control May 2007
+
+
+ security enclave from itself. A network service that is an LDAP
+ client and also either receives requests over another protocol that
+ contains session tracking identifiers or is proxying incoming LDAP
+ requests SHOULD NOT forward received session tracking identifiers to
+ a directory server that is under different administration or in a
+ different security enclave from itself. A packet inspecting firewall
+ that permits outgoing LDAP requests from an enterprise network SHOULD
+ silently remove any session tracking controls from requests that are
+ being sent to directory servers outside of the enterprise network for
+ which there is not a preexisting policy configured to allow the
+ session tracking control to be sent to that directory server.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Wahl Expires November 10, 2007 [Page 14]
+\f
+Internet-Draft LDAP Session Tracking Control May 2007
+
+
+5. IANA Considerations
+
+ This control will be registered as follows:
+
+ Subject: Request for LDAP Protocol Mechanism Registration
+
+ Object Identifier: 1.3.6.1.4.1.21008.108.63.1
+
+ Description: Session Tracking Identifier
+
+ Person & email address to contact for further information:
+ Mark Wahl <Mark.Wahl@informed-control.com>
+
+ Usage: Control
+
+ Specification: (I-D) RFC XXXX
+
+ Author/Change Controller: Mark Wahl
+
+
+ The OBJECT IDENTIFIER for particular session identifier formats
+ defined for other applications need not be registered with IANA.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Wahl Expires November 10, 2007 [Page 15]
+\f
+Internet-Draft LDAP Session Tracking Control May 2007
+
+
+6. Acknowledgments
+
+ This control was inspired by conversations with Greg Lavender. Neil
+ Wilson provided useful feedback on this document.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Wahl Expires November 10, 2007 [Page 16]
+\f
+Internet-Draft LDAP Session Tracking Control May 2007
+
+
+7. References
+
+7.1. Normative References
+
+ [1] Zeilenga, K., "Lightweight Directory Access Protocol (LDAP):
+ Technical Specification Road Map", RFC 4510, June 2006.
+
+ [2] Bradner, S., "Key words for use in RFCs to Indicate Requirement
+ Levels", RFC 2119, BCP 14, March 1997.
+
+ [3] Hinden, R., "IP Version 6 Addressing Architecture", RFC 1884,
+ January 1996.
+
+ [4] Yergeau, F., "UTF-8, a transformation format of ISO 10646",
+ RFC 3629, November 2003.
+
+ [5] "Universal Multiple-Octet Coded Character Set (UCS) -
+ Architecture and Basic Multilingual Plane, ISO/IEC 10646-1:
+ 1993".
+
+ [6] "ITU-T Rec. X.690 (07/2002) | ISO/IEC 8825-1:2002, "Information
+ technology - ASN.1 encoding rules: Specification of Basic
+ Encoding Rules (BER), Canonical Encoding Rules (CER) and
+ Distinguished Encoding Rules (DER)", 2002.".
+
+ [7] Rigney, C., "Remote Authentication Dial In User Service
+ (RADIUS)", RFC 2865, June 2000.
+
+ [8] Rigney, C., "RADIUS Accounting", RFC 2866, June 2000.
+
+ [9] Aboba, B., "RADIUS and IPv6", RFC 3162, August 2001.
+
+ [10] Melnikov, A., "Simple Authentication and Security Layer
+ (SASL)", RFC 4422, June 2006.
+
+7.2. Informative References
+
+ [11] Weltman, R., "Lightweight Directory Access Protocol (LDAP)
+ Proxied Authorization Control", RFC 4370, February 2006.
+
+
+
+
+
+
+
+
+
+
+
+
+Wahl Expires November 10, 2007 [Page 17]
+\f
+Internet-Draft LDAP Session Tracking Control May 2007
+
+
+Appendix A. Copyright
+
+ Copyright (C) The IETF Trust (2007). This document is subject to the
+ rights, licenses and restrictions contained in BCP 78, and except as
+ set forth therein, the authors retain all their rights. This
+ document and the information contained herein are provided on an "AS
+ IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS OR
+ IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND THE INTERNET
+ ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED,
+ INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE
+ INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED
+ WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Wahl Expires November 10, 2007 [Page 18]
+\f
+Internet-Draft LDAP Session Tracking Control May 2007
+
+
+Author's Address
+
+ Mark Wahl
+ Informed Control Inc.
+ PO Box 90626
+ Austin, TX 78709
+ US
+
+ Email: mark.wahl@informed-control.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Wahl Expires November 10, 2007 [Page 19]
+\f
+Internet-Draft LDAP Session Tracking Control May 2007
+
+
+Full Copyright Statement
+
+ Copyright (C) The IETF Trust (2007).
+
+ This document is subject to the rights, licenses and restrictions
+ contained in BCP 78, and except as set forth therein, the authors
+ retain all their rights.
+
+ This document and the information contained herein are provided on an
+ "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS
+ OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY, THE IETF TRUST AND
+ THE INTERNET ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS
+ OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF
+ THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED
+ WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+
+Intellectual Property
+
+ The IETF takes no position regarding the validity or scope of any
+ Intellectual Property Rights or other rights that might be claimed to
+ pertain to the implementation or use of the technology described in
+ this document or the extent to which any license under such rights
+ might or might not be available; nor does it represent that it has
+ made any independent effort to identify any such rights. Information
+ on the procedures with respect to rights in RFC documents can be
+ found in BCP 78 and BCP 79.
+
+ Copies of IPR disclosures made to the IETF Secretariat and any
+ assurances of licenses to be made available, or the result of an
+ attempt made to obtain a general license or permission for the use of
+ such proprietary rights by implementers or users of this
+ specification can be obtained from the IETF on-line IPR repository at
+ http://www.ietf.org/ipr.
+
+ The IETF invites any interested party to bring to its attention any
+ copyrights, patents or patent applications, or other proprietary
+ rights that may cover technology that may be required to implement
+ this standard. Please address the information to the IETF at
+ ietf-ipr@ietf.org.
+
+
+Acknowledgment
+
+ Funding for the RFC Editor function is provided by the IETF
+ Administrative Support Activity (IASA).
+
+
+
+
+
+Wahl Expires November 10, 2007 [Page 20]
+\f
INTERNET-DRAFT Kurt D. Zeilenga
-Intended Category: Standard Track OpenLDAP Foundation
-Expires in six months 5 March 2006
+Intended Category: Standard Track Isode Limited
+Expires in six months 14 February 2007
The LDAP Don't Use Copy Control
- <draft-zeilenga-ldap-dontusecopy-02.txt>
+ <draft-zeilenga-ldap-dontusecopy-04.txt>
Status of this Memo
document. Distribution of this memo is unlimited. Technical
discussion of this document will take place on the IETF LDAP
Extensions mailing list <ldapext@ietf.org>. Please send editorial
- comments directly to the author <Kurt@OpenLDAP.org>.
+ comments directly to the author <Kurt.Zeilenga@Isode.COM>.
By submitting this Internet-Draft, each author represents that any
applicable patent or other IPR claims of which he or she is aware have
or to cite them other than as "work in progress."
The list of current Internet-Drafts can be accessed at
- http://www.ietf.org/1id-abstracts.html
+ http://www.ietf.org/1id-abstracts.html.
The list of Internet-Draft Shadow Directories can be accessed at
- http://www.ietf.org/shadow.html
+ http://www.ietf.org/shadow.html.
- Copyright (C) The Internet Society (2006). All Rights Reserved.
+ Copyright (C) The IETF Trust (2007). All Rights Reserved.
Please see the Full Copyright section near the end of this document
for more information.
Zeilenga LDAP Don't Use Copy Control [Page 1]
\f
-INTERNET-DRAFT draft-zeilenga-ldap-dontusecopy-02 5 March 2006
+INTERNET-DRAFT draft-zeilenga-ldap-dontusecopy-04 14 February 2007
Abstract
1. Background and Intended Usage
This document defines the Lightweight Directory Access Protocol (LDAP)
- [Roadmap] Don't Use Copy control extension. The control may be
+ [RFC4510] Don't Use Copy control extension. The control may be
attached to request messages to indicate that copied (replicated or
cached) information [X.500] should not be used in providing service.
This control is based upon the X.511 [X.511] dontUseCopy service
3. The Don't Use Copy Control
- The Don't Use Copy control is an LDAP Control [Protocol] whose
+ The Don't Use Copy control is an LDAP Control [RFC4511] whose
controlType is IANA-ASSIGNED-OID and controlValue is absent. The
criticality MUST be TRUE. There is no corresponding response control.
The control is appropriate for both LDAP interrogation operations,
- including Compare and Search operations [Protocol]. It is
+ including Compare and Search operations [RFC4511]. It is
inappropriate for all other operations, including Abandon, Bind,
- Delete, Modify, ModifyDN, StartTLS, and Unbind operations [Protocol].
+ Delete, Modify, ModifyDN, StartTLS, and Unbind operations [RFC4511].
When the control is attached to an LDAP request, the requested
operation MUST NOT be performed on copied information. That is, the
Zeilenga LDAP Don't Use Copy Control [Page 2]
\f
-INTERNET-DRAFT draft-zeilenga-ldap-dontusecopy-02 5 March 2006
+INTERNET-DRAFT draft-zeilenga-ldap-dontusecopy-04 14 February 2007
is not available (either locally or through chaining), the server MUST
be better able to service the request or return an appropriate result
code (e.g., unwillingToPerform).
+ Servers implementing this technical specification SHOULD publish the
+ object identifier IANA-ASSIGNED-OID as a value of the
+ 'supportedControl' attribute [RFC4512] in their root DSE. A server
+ MAY choose to advertise this extension only when the client is
+ authorized to use it.
+
4. Security Considerations
consider whether use of copied information, in particular security and
policy information, may result insecure behavior.
- Security considerations for the base operations [Protocol] extended by
+ Security considerations for the base operations [RFC4511] extended by
this control, as well as general LDAP security considerations
- [Roadmap], generally apply to implementation and use of this
+ [RFC4510], generally apply to implementation and use of this
extension.
5.1. Object Identifier
It is requested that IANA assign upon Standards Action an LDAP Object
- Identifier [BCP64bis] to identify the LDAP Don't Use Copy Control
+ Identifier [RFC4520] to identify the LDAP Don't Use Copy Control
defined in this document.
Subject: Request for LDAP Object Identifier Registration
Person & email address to contact for further information:
- Kurt Zeilenga <kurt@OpenLDAP.org>
+ Kurt Zeilenga <Kurt.Zeilenga@Isode.COM>
Specification: RFC XXXX
Author/Change Controller: IESG
Comments:
5.2 LDAP Protocol Mechanism
- Registration of this protocol mechanism [BCP64bis] is requested.
+ Registration of this protocol mechanism [RFC4520] is requested.
Subject: Request for LDAP Protocol Mechanism Registration
- Object Identifier: IANA-ASSIGNED-OID
- Description: Don't Use Copy Control
- Person & email address to contact for further information:
- Kurt Zeilenga <kurt@openldap.org>
- Usage: Control
- Specification: RFC XXXX
Zeilenga LDAP Don't Use Copy Control [Page 3]
\f
-INTERNET-DRAFT draft-zeilenga-ldap-dontusecopy-02 5 March 2006
+INTERNET-DRAFT draft-zeilenga-ldap-dontusecopy-04 14 February 2007
+ Object Identifier: IANA-ASSIGNED-OID
+ Description: Don't Use Copy Control
+ Person & email address to contact for further information:
+ Kurt Zeilenga <Kurt.Zeilenga@Isode.COM>
+ Usage: Control
+ Specification: RFC XXXX
Author/Change Controller: IESG
Comments: none
6. Author's Address
Kurt D. Zeilenga
- OpenLDAP Foundation
+ Isode Limited
- Email: Kurt@OpenLDAP.org
+ Email: Kurt.Zeilenga@Isode.COM
7. References
[RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
Requirement Levels", BCP 14 (also RFC 2119), March 1997.
- [Roadmap] Zeilenga, K. (editor), "LDAP: Technical Specification
- Road Map", draft-ietf-ldapbis-roadmap-xx.txt, a work in
- progress.
+ [RFC4510] Zeilenga, K. (editor), "LDAP: Technical Specification
+ Road Map", RFC 4510, June 2006.
+
+ [RFC4511] Sermersheim, J. (editor), "LDAP: The Protocol", RFC
+ 4511, June 2006.
- [Protocol] Sermersheim, J. (editor), "LDAP: The Protocol",
- draft-ietf-ldapbis-protocol-xx.txt, a work in progress.
+ [RFC4512] Zeilenga, K. (editor), "LDAP: Directory Information
+ Models", RFC 4512, June 2006.
7.2. Informative References
-- Overview of concepts, models and services,"
X.500(1993) (also ISO/IEC 9594-1:1994).
+
+
+
+Zeilenga LDAP Don't Use Copy Control [Page 4]
+\f
+INTERNET-DRAFT draft-zeilenga-ldap-dontusecopy-04 14 February 2007
+
+
[X.511] International Telecommunication Union -
Telecommunication Standardization Sector, "The
Directory: Abstract Service Definition", X.511(1993)
(also ISO/IEC 9594-3:1993).
- [BCP64bis] Zeilenga, K., "IANA Considerations for LDAP",
- draft-ietf-ldapbis-bcp64-xx.txt, a work in progress.
-
-
+ [RFC4520] Zeilenga, K., "Internet Assigned Numbers Authority
+ (IANA) Considerations for the Lightweight Directory
+ Access Protocol (LDAP)", RFC 4520, BCP 64, June 2006.
-Zeilenga LDAP Don't Use Copy Control [Page 4]
-\f
-INTERNET-DRAFT draft-zeilenga-ldap-dontusecopy-02 5 March 2006
-
-Intellectual Property Rights
+Intellectual Property
The IETF takes no position regarding the validity or scope of any
Intellectual Property Rights or other rights that might be claimed to
Full Copyright
- Copyright (C) The Internet Society (2006).
+ Copyright (C) The IETF Trust (2007).
This document is subject to the rights, licenses and restrictions
contained in BCP 78, and except as set forth therein, the authors
This document and the information contained herein are provided on an
"AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS
- OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND THE INTERNET
- ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED,
- INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE
- INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED
+ OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY, THE IETF TRUST AND
+
+
+
+Zeilenga LDAP Don't Use Copy Control [Page 5]
+\f
+INTERNET-DRAFT draft-zeilenga-ldap-dontusecopy-04 14 February 2007
+
+
+ THE INTERNET ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS
+ OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF
+ THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED
WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
-Zeilenga LDAP Don't Use Copy Control [Page 5]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Zeilenga LDAP Don't Use Copy Control [Page 6]
\f
+++ /dev/null
-
-
-
-
-
-
-INTERNET-DRAFT Kurt D. Zeilenga
-Intended Category: Experimental OpenLDAP Foundation
-Expires in six months 27 February 2006
-
-
-
- The LDAP Manage Directory Information Tree Control
- <draft-zeilenga-ldap-managedit-00.txt>
-
-
-Status of this Memo
-
- This document is intended to be, after appropriate review and
- revision, submitted to the RFC Editor for publication as an
- Experimental document. Distribution of this memo is unlimited.
- Technical discussion of this document will take place on the IETF LDAP
- Extensions mailing list <ldapext@ietf.org>. Please send editorial
- comments directly to the author <Kurt@OpenLDAP.org>.
-
- By submitting this Internet-Draft, each author represents that any
- applicable patent or other IPR claims of which he or she is aware have
- been or will be disclosed, and any of which he or she becomes aware
- will be disclosed, in accordance with Section 6 of BCP 79.
-
- Internet-Drafts are working documents of the Internet Engineering Task
- Force (IETF), its areas, and its working groups. Note that other
- groups may also distribute working documents as Internet-Drafts.
-
- Internet-Drafts are draft documents valid for a maximum of six months
- and may be updated, replaced, or obsoleted by other documents at any
- time. It is inappropriate to use Internet-Drafts as reference material
- or to cite them other than as "work in progress."
-
- The list of current Internet-Drafts can be accessed at
- http://www.ietf.org/1id-abstracts.html
-
- The list of Internet-Draft Shadow Directories can be accessed at
- http://www.ietf.org/shadow.html
-
-
- Copyright (C) The Internet Society (2006). All Rights Reserved.
-
- Please see the Full Copyright section near the end of this document
- for more information.
-
-
-
-
-
-
-
-Zeilenga LDAP Manage DIT Control [Page 1]
-\f
-INTERNET-DRAFT draft-zeilenga-ldap-managedit-00 27 February 2006
-
-
-Abstract
-
- This document defines the Lightweight Directory Access Protocol (LDAP)
- Manage Directory Information Tree (DIT) Control which allows a
- directory user agent (a client) to request the directory service
- temporarily relax enforcement of constraints of the X.500 models.
-
-
-1. Background and Intended Use
-
- Directory servers accessible via Lightweight Directory Access Protocol
- (LDAP) [Roadmap] are expected to act in accordance with the X.500
- series of ITU-T Recommendations. In particular, servers are expected
- to ensure the X.500 data and service models are not violated.
-
- An LDAP server is expected to prevent modification of the structural
- object class of an object [Models]. That is, the X.500 models do not
- allow a 'person' object to be transformed into an
- 'organizationalPerson' object through modification of the object.
- Instead, the 'person' object must be deleted and then a new
- 'organizationalPerson' object created in its place. This approach,
- aside from being inconvient, is problematic for a number reasons.
- First, as LDAP does not have a standardized method for performing the
- two operations in a single transaction, the intermediate directory
- state (after the delete, before the add) is visible to other clients,
- which may lead to undesirable client behavior. Second, attributes
- such as entryUUID [entryUUID] will reflect the object was replaced,
- not transformed.
-
- An LDAP server is expected to prevent clients from modifying values of
- NO-USER-MODIFICATION attributes [Models]. For instance, an entry is
- not allowed to assign or modify the value of the entryUUID attribute.
- However, where an administrator is restoring a previously existing
- object, for instance when repartitioning data between directory
- servers or when migrating from one vendor server product to another,
- it may be desirable to allow the client to assign or modify the value
- of the entryUUID attribute.
-
- This document specifies the Manage Directory Information Tree (DIT)
- control. The Manage DIT control may be attached to LDAP requests to
- update the DIT to request DIT restrictions be temporarily relaxed
- during the performance of the requested DIT update. The server is
- however to ensure the resulting directory state is valid.
-
- Use of this control is expected that use of this extension will be
- restricted by administrative and/or access controls. It is intended
- to be used by directory administrators.
-
-
-
-
-Zeilenga LDAP Manage DIT Control [Page 2]
-\f
-INTERNET-DRAFT draft-zeilenga-ldap-managedit-00 27 February 2006
-
-
- This extension is considered experimental as it is not yet clear
- whether it adequately addresses directory administrators' needs for
- flexible mechanisms for managing directory objects. It is hoped that
- after suitable amount of time, either this extension or a suitable
- replacement will be standardization.
-
-
-1.1. Terminology
-
- Protocol elements are described using ASN.1 [X.680] with implicit
- tags. The term "BER-encoded" means the element is to be encoded using
- the Basic Encoding Rules [X.690] under the restrictions detailed in
- Section 5.2 of [Protocol].
-
- The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
- "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
- document are to be interpreted as described in BCP 14 [RFC2119].
-
- DSA stands for Directory System Agent, a server. DSE stands for DSA-
- specific Entry.
-
-
-2. The Manage DIT Control
-
- The Manage DIT control is an LDAP Control [Protocol] whose controlType
- is IANA-ASSIGNED-OID, controlValue is empty, and the criticality of
- TRUE.
-
- There is no corresponding response control.
-
- The control is appropriate for all LDAP update requests, including
- add, delete, modify, and modifyDN (rename) [Protocol].
-
- The presence of the Manage DIT control in an LDAP update request
- indicates the server temporarily relax X.500 model contraints during
- performance of the directory update.
-
- The server may restrict use of this control and/or limit the extent of
- the relaxation provided based upon local policy or factors.
-
- The server is obligated to ensure the resulting directory state is
- consistent with the X.500 models. For instance, the server ensure
- that values of attributes conform to the value syntax.
-
- It is noted that while this extension may be used to add or modify
- objects in a manner which violate the controlling subschema, the
- presence of objects in the DIT is not inconsistent with the X.500
- models. For instance, an object created prior to establshment of a
-
-
-
-Zeilenga LDAP Manage DIT Control [Page 3]
-\f
-INTERNET-DRAFT draft-zeilenga-ldap-managedit-00 27 February 2006
-
-
- DIT content rule may contain an attribute now precluded by the current
- controlling DIT Content Rule.
-
- Servers implementing this technical specification SHOULD publish the
- object identifier IANA-ASSIGNED-OID as a value of the
- 'supportedControl' attribute [Models] in their root DSE. A server MAY
- choose to advertise this extension only when the client is authorized
- to use it.
-
-
-3. Use Cases
-
-3.1. Object metamorphism
-
- In absence of this control, an attempt to modify an object's
- 'objectClass' in a manner which cause a change in the structural
- object class of the object would normally lead to an
- objectClassModsProhibited error [Protocol]. The presence of the
- Manage DIT control in the modify request requests the change be
- allowed. If the server is willing and able to allow the change in the
- structural object class of the object.
-
- For instance, to change an 'organization' object into an
- 'organizationalUnit' object, a client could issue the following LDAP
- request:
-
- dn: o=Unit,dc=example,dc=net
- control: IANA-ASSIGNED-OID
- changetype: modify
- delete: objectClass
- objectClass: organization
- -
- add: objectClass
- objectClass: organizationalUnit
- -
-
- In this case, the server is expected to either effect the requested
- change in the structural object class, including updating of the value
- of the structural object class, or fail the operation.
-
-
-3.2. Inactive Attribute Types
-
- In absence of the Manage DIT control, an attempt to add or modify
- values to an attribute whose type has been marked inactive in the
- controlling subschema (its attribute type description contains the
- OBSOLETE field) [Models] normally results in a failure.
-
-
-
-
-Zeilenga LDAP Manage DIT Control [Page 4]
-\f
-INTERNET-DRAFT draft-zeilenga-ldap-managedit-00 27 February 2006
-
-
- In the presence of the Manage DIT control, the server performs the
- update operation as if the attribute's type is marked active in the
- controlling subschema (its attribute type description does not contain
- the OBSOLETE field).
-
-
-3.3. DIT Content Rules
-
- In absence of the Manage DIT control, an attempt to include the name
- (or OID) of an auxiliary class to an object's 'objectClass' which is
- not allowed by the controlling DIT Content Rule would be disallowed
- [Models]. Additionally, an attempt to add values of an attribute not
- allowed (or explicitly precluded) by the DIT Content Rule would fail.
-
- In presence of the Manage DIT control, the server performs the update
- operation as if the controlling DIT Content Rule allowed any and all
- known auxiliary classses to be present and allowed any and all known
- attributes to be present (and precluded no attributes).
-
-
-3.4. DIT Structure Rules and Name Forms
-
- In absence of the Manage DIT control, the service enforces DIT
- structure rules and name form requirements of the controlling
- subschema [Models].
-
- In the presence of the Manage DIT control, the server performs the
- update operation ignoring all DIT structure rules and name forms in
- the controlling subschema.
-
-
-3.5. Modification of Nonconformant Objects
-
- It is also noted that in absense of this control, modification of an
- object which presently violates the controlling subschema will fail
- unless the modification would result in the object conforming to the
- controlling subschema. That is, modifications of an non-conformant
- object should result in a conformant object.
-
- In the presence of this control, modifications of a non-conformant
- object need not result in a conformant object.
-
-
-3.6. NO-USER-MODIFICATION attribute modification
-
- In absence of this control, an attempt to modify values of a
- NO-USER-MODIFICATION attribute would normally lead to a
- constraintViolation or other appropriate error [Protocol]. In the
-
-
-
-Zeilenga LDAP Manage DIT Control [Page 5]
-\f
-INTERNET-DRAFT draft-zeilenga-ldap-managedit-00 27 February 2006
-
-
- presence of the Manage DIT control in the update request requests the
- modification be allowed.
-
- Relaxation of the NO-USER-MODIFICATION constraint is not appropriate
- for some operational attribute types. For instance, as the value of
- the 'structuralObjectClass' is derived by the values of the
- 'objectClass' attribute, the 'structuralObjectClass' attribute type's
- NO-USER-MODIFICATION contraint MUST NOT be relaxed. To effect a
- change in the structuralObjectClass class, values of objectClass
- should be changed as discussed in Section 3.1. Other attributes for
- which the NO-USER-MODIFICATION constraint should not be relaxed
- include 'entryDN' [EntryDN], 'subschemaSubentry' [Models], and
- 'collectiveAttributeSubentries' [RFC3671].
-
- The subsections of this section discuss modification of various
- operational attributes where their NO-USER-MODIFICATION constraint may
- be relaxed. Future documents may specify where NO-USER-MODIFICATION
- constraints on other operational attribute may be relaxed. In absence
- of a document detailing that the NO-USER-MODIFICATION constraint on a
- particular operational attribute may be relaxed, implementors SHOULD
- assume relaxation of the constraint is not appropriate for that
- attribute.
-
-
-3.1.1. entryUUID
-
- To provide a value for the 'entryUUID' attribute on entry creation,
- the client should issue an LDAP Add request with a Manage DIT control
- providing the desired value. For instance:
-
- dn: ou=Unit,dc=example,dc=net
- control: IANA-ASSIGNED-OID
- changetype: add
- objectClass: organizationalUnit
- ou: Unit
- entryUUID: 597ae2f6-16a6-1027-98f4-d28b5365dc14
-
- In this case, the server is either to add the entry using the
- provided 'entryUUID' value or fail the request.
-
- To provide a replacement value for the 'entryUUID' after entry
- creation, the client should issue an LDAP Modify request with a
- Manage DIT control including an approrpiate change. For instance:
-
- dn: ou=Unit,dc=example,dc=net
- control: IANA-ASSIGNED-OID
- changetype: modify
- replace: entryUUID
-
-
-
-Zeilenga LDAP Manage DIT Control [Page 6]
-\f
-INTERNET-DRAFT draft-zeilenga-ldap-managedit-00 27 February 2006
-
-
- entryUUID: 597ae2f6-16a6-1027-98f4-d28b5365dc14
- -
-
- In this case, the server is either to replace the 'entryUUID' value
- as requested or fail the request.
-
-
-3.2.2. createTimestamp
-
- To provide a value for the 'createTimestamp' attribute on entry
- creation, the client should issue an LDAP Add request with a Manage
- DIT control providing the desired 'createTimestamp' value. For
- instance:
-
- dn: ou=Unit,dc=example,dc=net
- control: IANA-ASSIGNED-OID
- changetype: add
- objectClass: organizationalUnit
- ou: Unit
- createTimestamp: 20060101000000Z
-
- In this case, the server is either to add the entry using the
- provided 'createTimestamp' value or fail the request.
-
- To provide a replacement value for the 'createTimestamp' after
- entry creation, the client should issue an LDAP Modify request with
- a Manage DIT control including an approrpiate change. For instance:
-
- dn: ou=Unit,dc=example,dc=net
- control: IANA-ASSIGNED-OID
- changetype: modify
- replace: createTimestamp
- createTimestamp: 20060101000000Z
- -
-
- In this case, the server is either to replace the 'createTimestamp'
- value as requested or fail the request.
-
- The server should ensure the requested 'createTimestamp' value is
- appropriate. In particular, it should fail the request if the
- requested 'createTimestamp' value is in the future or is greater
- than the value of the 'modifyTimestamp' attribute.
-
-
-3.2.3. modifyTimestamp
-
- To provide a value for the 'modifyTimestamp' attribute on entry
- creation, the client should issue an LDAP Add request with a Manage
-
-
-
-Zeilenga LDAP Manage DIT Control [Page 7]
-\f
-INTERNET-DRAFT draft-zeilenga-ldap-managedit-00 27 February 2006
-
-
- DIT control providing the desired 'modifyTimestamp' value. For
- instance:
-
- dn: ou=Unit,dc=example,dc=net
- control: IANA-ASSIGNED-OID
- changetype: add
- objectClass: organizationalUnit
- ou: Unit
- modifyTimestamp: 20060101000000Z
-
- In this case, the server is either to add the entry using
- the provided 'modifyTimestamp' value or fail the request.
-
- To provide a replacement value for the 'modifyTimestamp' after
- entry creation, the client should issue an LDAP Modify
- request with a Manage DIT control including an approrpiate
- change. For instance:
-
- dn: ou=Unit,dc=example,dc=net
- control: IANA-ASSIGNED-OID
- changetype: modify
- replace: modifyTimestamp
- modifyTimestamp: 20060101000000Z
- -
-
- In this case, the server is either to replace the 'modifyTimestamp'
- value as requested or fail the request.
-
- The server should ensure the requested 'modifyTimestamp' value is
- appropriate. In particular, it should fail the request if the
- requested 'modifyTimestamp' value is in the future or is less than
- the value of the 'createTimestamp' attribute.
-
-
- 3.2.3. creatorsName and modifiersName
-
- To provide a value for the 'creatorsName' and/or 'modifiersName'
- attribute on entry creation, the client should issue an LDAP Add
- request with a Manage DIT control providing the desired values.
- For instance:
-
- dn: ou=Unit,dc=example,dc=net
- control: IANA-ASSIGNED-OID
- changetype: add
- objectClass: organizationalUnit
- ou: Unit
- creatorsName: cn=Jane Doe,dc=example,net
- modifiersName: cn=Jane Doe,dc=example,net
-
-
-
-Zeilenga LDAP Manage DIT Control [Page 8]
-\f
-INTERNET-DRAFT draft-zeilenga-ldap-managedit-00 27 February 2006
-
-
- In this case, the server is either to add the entry using
- the provided values or fail the request.
-
- To provide a replacement values after entry creation for either of
- the 'creatorsName' or 'modifiersName' attributes or both, the
- client should issue an LDAP Modify request with a Manage DIT control
- including the approrpiate changes. For instance:
-
- dn: ou=Unit,dc=example,dc=net
- control: IANA-ASSIGNED-OID
- changetype: modify
- replace: creatorsName
- creatorsName: cn=Jane Doe,dc=example,net
- -
- replace: modifiersName
- modifiersName: cn=Jane Doe,dc=example,net
- -
-
- In this case, the server is either to replace the provided
- values as requested or fail the request.
-
-
-4. Security Considerations
-
- Use of this extension should be subject to appropriate administrative
- and access controls. Use of this mechanism is intended to be
- restricted to directory administrators.
-
- Security considerations for the base operations [Protocol] extended
- by this control, as well as general LDAP security considerations
- [Roadmap], generally apply to implementation and use of this
- extension.
-
-
-5. IANA Considerations
-
-5.1. Object Identifier
-
- It is requested that IANA assign a LDAP Object Identifier [BCP64bis]
- to identify the LDAP Assertion Control defined in this document.
-
- Subject: Request for LDAP Object Identifier Registration
- Person & email address to contact for further information:
- Kurt Zeilenga <kurt@OpenLDAP.org>
- Specification: RFC XXXX
- Author/Change Controller: Kurt Zeilenga <kurt@openldap.org>
- Comments: Identifies the LDAP Manage DIT Control
-
-
-
-
-Zeilenga LDAP Manage DIT Control [Page 9]
-\f
-INTERNET-DRAFT draft-zeilenga-ldap-managedit-00 27 February 2006
-
-
-5.2 LDAP Protocol Mechanism
-
- Registration of this protocol mechanism [BCP64bis] is requested.
-
- Subject: Request for LDAP Protocol Mechanism Registration
- Object Identifier: IANA-ASSIGNED-OID
- Description: Manage DIT Control
- Person & email address to contact for further information:
- Kurt Zeilenga <kurt@openldap.org>
- Usage: Control
- Specification: RFC XXXX
- Author/Change Controller: Kurt Zeilenga <kurt@openldap.org>
- Comments: none
-
-
-6. Author's Address
-
- Kurt D. Zeilenga
- OpenLDAP Foundation
-
- Email: Kurt@OpenLDAP.org
-
-
-7. References
-
- [[Note to the RFC Editor: please replace the citation tags used in
- referencing Internet-Drafts with tags of the form RFCnnnn where
- possible.]]
-
-
-7.1. Normative References
-
- [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
- Requirement Levels", BCP 14 (also RFC 2119), March 1997.
-
- [Roadmap] Zeilenga, K. (editor), "LDAP: Technical Specification
- Road Map", draft-ietf-ldapbis-roadmap-xx.txt, a work in
- progress.
-
- [Models] Zeilenga, K. (editor), "LDAP: Directory Information
- Models", draft-ietf-ldapbis-models-xx.txt, a work in
- progress.
-
-
-
-7.2. Informative References
-
- [BCP64bis] Zeilenga, K., "IANA Considerations for LDAP",
-
-
-
-Zeilenga LDAP Manage DIT Control [Page 10]
-\f
-INTERNET-DRAFT draft-zeilenga-ldap-managedit-00 27 February 2006
-
-
- draft-ietf-ldapbis-bcp64-xx.txt, a work in progress.
-
- [EntryUUID] Zeilenga, K., "The LDAP EntryUUID Operational
- Attribute", draft-zeilenga-ldap-uuid-xx.txt, a work in
- progress.
-
- [RFC2849] Good, G., "The LDAP Data Interchange Format (LDIF) -
- Technical Specification", RFC 2849, June 2000.
-
-
-
-Intellectual Property Rights
-
- The IETF takes no position regarding the validity or scope of any
- Intellectual Property Rights or other rights that might be claimed to
- pertain to the implementation or use of the technology described in
- this document or the extent to which any license under such rights
- might or might not be available; nor does it represent that it has
- made any independent effort to identify any such rights. Information
- on the procedures with respect to rights in RFC documents can be found
- in BCP 78 and BCP 79.
-
- Copies of IPR disclosures made to the IETF Secretariat and any
- assurances of licenses to be made available, or the result of an
- attempt made to obtain a general license or permission for the use of
- such proprietary rights by implementers or users of this specification
- can be obtained from the IETF on-line IPR repository at
- http://www.ietf.org/ipr.
-
- The IETF invites any interested party to bring to its attention any
- copyrights, patents or patent applications, or other proprietary
- rights that may cover technology that may be required to implement
- this standard. Please address the information to the IETF at
- ietf-ipr@ietf.org.
-
-
-
-Full Copyright
-
- Copyright (C) The Internet Society (2006).
-
- This document is subject to the rights, licenses and restrictions
- contained in BCP 78, and except as set forth therein, the authors
- retain all their rights.
-
- This document and the information contained herein are provided on an
- "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS
- OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND THE INTERNET
-
-
-
-Zeilenga LDAP Manage DIT Control [Page 11]
-\f
-INTERNET-DRAFT draft-zeilenga-ldap-managedit-00 27 February 2006
-
-
- ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED,
- INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE
- INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED
- WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Zeilenga LDAP Manage DIT Control [Page 12]
-\f
INTERNET-DRAFT Kurt D. Zeilenga
-Intended Category: Standard Track OpenLDAP Foundation
-Expires in six months 5 March 2006
+Intended Category: Standard Track Isode Limited
+Expires in six months 14 February 2007
The LDAP No-Op Control
- <draft-zeilenga-ldap-noop-08.txt>
+ <draft-zeilenga-ldap-noop-10.txt>
Status of this Memo
document. Distribution of this memo is unlimited. Technical
discussion of this document will take place on the IETF LDAP
Extensions mailing list <ldapext@ietf.org>. Please send editorial
- comments directly to the author <Kurt@OpenLDAP.org>.
+ comments directly to the author <Kurt.Zeilenga@Isode.COM>.
By submitting this Internet-Draft, each author represents that any
applicable patent or other IPR claims of which he or she is aware have
or to cite them other than as "work in progress."
The list of current Internet-Drafts can be accessed at
- http://www.ietf.org/1id-abstracts.html
+ http://www.ietf.org/1id-abstracts.html.
The list of Internet-Draft Shadow Directories can be accessed at
- http://www.ietf.org/shadow.html
+ http://www.ietf.org/shadow.html.
- Copyright (C) The Internet Society (2006). All Rights Reserved.
+ Copyright (C) The IETF Trust (2007). All Rights Reserved.
Please see the Full Copyright section near the end of this document
for more information.
Zeilenga LDAP No-Op Control [Page 1]
\f
-INTERNET-DRAFT draft-zeilenga-ldap-noop-08 5 March 2006
+INTERNET-DRAFT draft-zeilenga-ldap-noop-10 14 February 2007
Abstract
1. Overview
It is often desirable to be able to determine if a directory operation
- [Protocol] would successful complete or not without having the normal
+ [RFC4511] would successful complete or not without having the normal
effect of the operation take place. For example, an administrative
client might want to verify that new user could update their entry
(and not other entries) without the directory actually being updated.
auditing tools.
This document defines the Lightweight Directory Access Protocol (LDAP)
- [Roadmap] No-Op control extension. The presence of the No-Op control
+ [RFC4510] No-Op control extension. The presence of the No-Op control
in an operation request message disables its normal effect upon the
directory which operation would otherwise have. Instead of updating
the directory and returning the normal indication of success, the
noOperation resultCode (introduced below).
For example, when the No-Op control is present in a LDAP modify
- operation [Protocol], the server is do all processing necessary to
+ operation [RFC4511], the server is do all processing necessary to
perform the operation without actually updating the directory. If it
detects an error during this processing, it returns a non-success
(other than noOperation) resultCode as it normally would. Otherwise,
Zeilenga LDAP No-Op Control [Page 2]
\f
-INTERNET-DRAFT draft-zeilenga-ldap-noop-08 5 March 2006
+INTERNET-DRAFT draft-zeilenga-ldap-noop-10 14 February 2007
2. No-Op Control
- The No-Op control is an LDAP Control [Protocol] whose controlType is
+ The No-Op control is an LDAP Control [RFC4511] whose controlType is
IANA-ASSIGNED-OID and controlValue is absent. Clients MUST provide a
criticality value of TRUE to prevent unintended modification of the
directory.
The control is appropriate for request messages of LDAP Add, Delete,
- Modify and ModifyDN operations [Protocol]. The control is also
+ Modify and ModifyDN operations [RFC4511]. The control is also
appropriate for requests of extended operations which update the
directory (or other data stores), such as Password Modify Extended
Operation [RFC3062]. There is no corresponding response control.
Servers SHOULD indicate their support for this control by providing
IANA-ASSIGNED-OID as a value of the 'supportedControl' attribute type
- [Models] in their root DSE entry. A server MAY choose to advertise
+ [RFC4512] in their root DSE entry. A server MAY choose to advertise
this extension only when the client is authorized to use this
operation.
tools.
Implementors of this LDAP extension should be familiar with security
- considerations applicable to the LDAP operations [Protocol] extended
- by this control, as well as general LDAP security considerations
+ considerations applicable to the LDAP operations [RFC4511] extended by
+ this control, as well as general LDAP security considerations
[Roadmap].
Zeilenga LDAP No-Op Control [Page 3]
\f
-INTERNET-DRAFT draft-zeilenga-ldap-noop-08 5 March 2006
+INTERNET-DRAFT draft-zeilenga-ldap-noop-10 14 February 2007
4. IANA Considerations
4.1. Object Identifier
- It is requested that IANA assign an LDAP Object Identifier [BCP64bis]
+ It is requested that IANA assign an LDAP Object Identifier [RFC4520]
to identify the LDAP No-Op Control defined in this document.
Subject: Request for LDAP Object Identifier Registration
Person & email address to contact for further information:
- Kurt Zeilenga <kurt@OpenLDAP.org>
+ Kurt Zeilenga <Kurt.Zeilenga@Isode.COM>
Specification: RFC XXXX
Author/Change Controller: IESG
Comments:
4.2 LDAP Protocol Mechanism
- Registration of this protocol mechanism is requested [RFC3383].
+ Registration of this protocol mechanism is requested [RFC4520].
Subject: Request for LDAP Protocol Mechanism Registration
Object Identifier: IANA-ASSIGNED-OID
Description: No-Op Control
Person & email address to contact for further information:
- Kurt Zeilenga <kurt@openldap.org>
+ Kurt Zeilenga <Kurt.Zeilenga@Isode.COM>
Usage: Control
Specification: RFC XXXX
Author/Change Controller: IESG
Subject: LDAP Result Code Registration
Person & email address to contact for further information:
- Kurt Zeilenga <kurt@OpenLDAP.org>
+ Kurt Zeilenga <Kurt.Zeilenga@Isode.COM>
Result Code Name: noOperation
Specification: RFC XXXX
Author/Change Controller: IESG
5. Author's Address
Kurt D. Zeilenga
- OpenLDAP Foundation
+ Isode Limited
Zeilenga LDAP No-Op Control [Page 4]
\f
-INTERNET-DRAFT draft-zeilenga-ldap-noop-08 5 March 2006
+INTERNET-DRAFT draft-zeilenga-ldap-noop-10 14 February 2007
- Email: Kurt@OpenLDAP.org
+ Email: Kurt.Zeilenga@Isode.COM
6. References
[RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
Requirement Levels", BCP 14 (also RFC 2119), March 1997.
- [Protocol] Sermersheim, J. (editor), "LDAP: The Protocol",
- draft-ietf-ldapbis-protocol-xx.txt, a work in progress.
+ [RFC4510] Zeilenga, K. (editor), "LDAP: Technical Specification
+ Road Map", RFC 4510, June 2006.
- [Roadmap] Zeilenga, K. (editor), "LDAP: Technical Specification
- Road Map", draft-ietf-ldapbis-roadmap-xx.txt, a work in
- progress.
+ [RFC4511] Sermersheim, J. (editor), "LDAP: The Protocol", RFC
+ 4511, June 2006.
- [Models] Zeilenga, K. (editor), "LDAP: Directory Information
- Models", draft-ietf-ldapbis-models-xx.txt, a work in
- progress.
+ [RFC4512] Zeilenga, K. (editor), "LDAP: Directory Information
+ Models", RFC 4512, June 2006.
6.2. Informative References
[RFC3062] Zeilenga, K., "LDAP Password Modify Extended Operation",
RFC 3062, February 2000.
- [BCP64bis] Zeilenga, K., "IANA Considerations for LDAP",
- draft-ietf-ldapbis-bcp64-xx.txt, a work in progress.
+ [RFC4520] Zeilenga, K., "Internet Assigned Numbers Authority
+ (IANA) Considerations for the Lightweight Directory
+ Access Protocol (LDAP)", RFC 4520, BCP 64, June 2006.
-Intellectual Property Rights
+Intellectual Property
The IETF takes no position regarding the validity or scope of any
+ Intellectual Property Rights or other rights that might be claimed to
Zeilenga LDAP No-Op Control [Page 5]
\f
-INTERNET-DRAFT draft-zeilenga-ldap-noop-08 5 March 2006
+INTERNET-DRAFT draft-zeilenga-ldap-noop-10 14 February 2007
- Intellectual Property Rights or other rights that might be claimed to
pertain to the implementation or use of the technology described in
this document or the extent to which any license under such rights
might or might not be available; nor does it represent that it has
Full Copyright
- Copyright (C) The Internet Society (2006).
+ Copyright (C) The IETF Trust (2007).
This document is subject to the rights, licenses and restrictions
contained in BCP 78, and except as set forth therein, the authors
This document and the information contained herein are provided on an
"AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS
- OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND THE INTERNET
- ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED,
- INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE
- INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED
+ OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY, THE IETF TRUST AND
+ THE INTERNET ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS
+ OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF
+ THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED
WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
Zeilenga LDAP No-Op Control [Page 6]
\f
--- /dev/null
+
+
+
+
+
+
+INTERNET-DRAFT Kurt D. Zeilenga
+Intended Category: Experimental Isode Limited
+Expires in six months 14 February 2007
+
+
+
+ The LDAP Relax Rules Control
+ <draft-zeilenga-ldap-relax-01.txt>
+
+
+Status of this Memo
+
+ This document is intended to be, after appropriate review and
+ revision, submitted to the RFC Editor for publication as an
+ Experimental document. Distribution of this memo is unlimited.
+ Technical discussion of this document will take place on the IETF LDAP
+ Extensions mailing list <ldapext@ietf.org>. Please send editorial
+ comments directly to the author <Kurt.Zeilenga@Isode.COM>.
+
+ This document replaces draft-zeilenga-ldap-managedit-xx.txt.
+
+ By submitting this Internet-Draft, each author represents that any
+ applicable patent or other IPR claims of which he or she is aware have
+ been or will be disclosed, and any of which he or she becomes aware
+ will be disclosed, in accordance with Section 6 of BCP 79.
+
+ Internet-Drafts are working documents of the Internet Engineering Task
+ Force (IETF), its areas, and its working groups. Note that other
+ groups may also distribute working documents as Internet-Drafts.
+
+ Internet-Drafts are draft documents valid for a maximum of six months
+ and may be updated, replaced, or obsoleted by other documents at any
+ time. It is inappropriate to use Internet-Drafts as reference material
+ or to cite them other than as "work in progress."
+
+ The list of current Internet-Drafts can be accessed at
+ http://www.ietf.org/1id-abstracts.html.
+
+ The list of Internet-Draft Shadow Directories can be accessed at
+ http://www.ietf.org/shadow.html.
+
+
+ Copyright (C) The IETF Trust (2007). All Rights Reserved.
+
+ Please see the Full Copyright section near the end of this document
+ for more information.
+
+
+
+
+
+Zeilenga LDAP Relax Rules Control [Page 1]
+\f
+INTERNET-DRAFT draft-zeilenga-ldap-relax-01 14 February 2007
+
+
+Abstract
+
+ This document defines the Lightweight Directory Access Protocol (LDAP)
+ Relax Rules Control which allows a directory user agent (a client) to
+ request the directory service temporarily relax enforcement of various
+ data and service model rules.
+
+
+1. Background and Intended Use
+
+ Directory servers accessible via Lightweight Directory Access Protocol
+ (LDAP) [RFC4510] are expected to act in accordance with the X.500
+ [X.500] series of ITU-T Recommendations. In particular, servers are
+ expected to ensure the X.500 data and service models are not violated.
+
+ An LDAP server is expected to prevent modification of the structural
+ object class of an object [RFC4512]. That is, the X.500 models do not
+ allow a 'person' object to be transformed into an
+ 'organizationalPerson' object through modification of the object.
+ Instead, the 'person' object must be deleted and then a new
+ 'organizationalPerson' object created in its place. This approach,
+ aside from being inconvient, is problematic for a number reasons.
+ First, as LDAP does not have a standardized method for performing the
+ two operations in a single transaction, the intermediate directory
+ state (after the delete, before the add) is visible to other clients,
+ which may lead to undesirable client behavior. Second, attributes
+ such as 'entryUUID' [RFC4530] will reflect the object was replaced,
+ not transformed.
+
+ An LDAP server is expected to prevent clients from modifying values of
+ NO-USER-MODIFICATION attributes [RFC4512]. For instance, an entry is
+ not allowed to assign or modify the value of the 'entryUUID'
+ attribute. However, where an administrator is restoring a previously
+ existing object, for instance when repartitioning data between
+ directory servers or when migrating from one vendor server product to
+ another, it may be desirable to allow the client to assign or modify
+ the value of the 'entryUUID' attribute.
+
+ This document defines the LDAP Relax Rules control. This control may
+ be attached to LDAP requests to update the Directory Information Tree
+ (DIT) to request various data and service rules be temporarily relaxed
+ during the performance of the requested DIT update. The server is
+ however to ensure the resulting directory state is valid.
+
+ Use of this control is expected that use of this extension will be
+ restricted by administrative and/or access controls. It is intended
+ to be used primarily by directory administrators.
+
+
+
+
+Zeilenga LDAP Relax Rules Control [Page 2]
+\f
+INTERNET-DRAFT draft-zeilenga-ldap-relax-01 14 February 2007
+
+
+ This extension is considered experimental as it is not yet clear
+ whether it adequately addresses directory administrators' needs for
+ flexible mechanisms for managing directory objects. It is hoped that
+ after suitable amount of time, either this extension or a suitable
+ replacement will be standardization.
+
+
+1.1. Terminology
+
+ Protocol elements are described using ASN.1 [X.680] with implicit
+ tags. The term "BER-encoded" means the element is to be encoded using
+ the Basic Encoding Rules [X.690] under the restrictions detailed in
+ Section 5.1 of [RFC4511].
+
+ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
+ "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
+ document are to be interpreted as described in BCP 14 [RFC2119].
+
+ DSA stands for Directory System Agent, a server. DSE stands for
+ DSA-specific Entry.
+
+
+2. The Relax Rules Control
+
+ The Relax Rules control is an LDAP Control [RFC4511] whose controlType
+ is IANA-ASSIGNED-OID, controlValue is empty, and the criticality of
+ TRUE.
+
+ There is no corresponding response control.
+
+ The control is appropriate for all LDAP update requests, including
+ add, delete, modify, and modifyDN (rename) [RFC4511].
+
+ The presence of the Rules Rules control in an LDAP update request
+ indicates the server temporarily relax X.500 model contraints during
+ performance of the directory update.
+
+ The server may restrict use of this control and/or limit the extent of
+ the relaxation provided based upon local policy or factors.
+
+ The server is obligated to ensure the resulting directory state is
+ consistent with the X.500 models. For instance, the server ensure
+ that values of attributes conform to the value syntax.
+
+ It is noted that while this extension may be used to add or modify
+ objects in a manner which violate the controlling subschema, the
+ presence of objects in the DIT is not inconsistent with the X.500
+ models. For instance, an object created prior to establshment of a
+
+
+
+Zeilenga LDAP Relax Rules Control [Page 3]
+\f
+INTERNET-DRAFT draft-zeilenga-ldap-relax-01 14 February 2007
+
+
+ DIT content rule may contain an attribute now precluded by the current
+ controlling DIT Content Rule.
+
+ Servers implementing this technical specification SHOULD publish the
+ object identifier IANA-ASSIGNED-OID as a value of the
+ 'supportedControl' attribute [RFC4512] in their root DSE. A server
+ MAY choose to advertise this extension only when the client is
+ authorized to use it.
+
+
+3. Use Cases
+
+3.1. Object metamorphism
+
+ In absence of this control, an attempt to modify an object's
+ 'objectClass' in a manner which cause a change in the structural
+ object class of the object would normally lead to an
+ objectClassModsProhibited error [RFC4511]. The presence of the Relax
+ Rules control in the modify request requests the change be allowed.
+ If the server is willing and able to allow the change in the
+ structural object class of the object.
+
+ For instance, to change an 'organization' object into an
+ 'organizationalUnit' object, a client could issue the following LDAP
+ request:
+
+ dn: o=Unit,dc=example,dc=net
+ control: IANA-ASSIGNED-OID
+ changetype: modify
+ delete: objectClass
+ objectClass: organization
+ -
+ add: objectClass
+ objectClass: organizationalUnit
+ -
+
+ In this case, the server is expected to either effect the requested
+ change in the structural object class, including updating of the value
+ of the structural object class, or fail the operation.
+
+
+3.2. Inactive Attribute Types
+
+ In absence of the Relax Rules control, an attempt to add or modify
+ values to an attribute whose type has been marked inactive in the
+ controlling subschema (its attribute type description contains the
+ OBSOLETE field) [RFC4512] normally results in a failure.
+
+
+
+
+Zeilenga LDAP Relax Rules Control [Page 4]
+\f
+INTERNET-DRAFT draft-zeilenga-ldap-relax-01 14 February 2007
+
+
+ In the presence of the Relax Rules control, the server performs the
+ update operation as if the attribute's type is marked active in the
+ controlling subschema (its attribute type description does not contain
+ the OBSOLETE field).
+
+
+3.3. DIT Content Rules
+
+ In absence of the Relax Rules control, an attempt to include the name
+ (or OID) of an auxiliary class to an object's 'objectClass' which is
+ not allowed by the controlling DIT Content Rule would be disallowed
+ [RFC4512]. Additionally, an attempt to add values of an attribute
+ not allowed (or explicitly precluded) by the DIT Content Rule would
+ fail.
+
+ In presence of the Relax Rules control, the server performs the update
+ operation as if the controlling DIT Content Rule allowed any and all
+ known auxiliary classses to be present and allowed any and all known
+ attributes to be present (and precluded no attributes).
+
+
+3.4. DIT Structure Rules and Name Forms
+
+ In absence of the Relax Rules control, the service enforces DIT
+ structure rules and name form requirements of the controlling
+ subschema [RFC4512].
+
+ In the presence of the Relax Rules control, the server performs the
+ update operation ignoring all DIT structure rules and name forms in
+ the controlling subschema.
+
+
+3.5. Modification of Nonconformant Objects
+
+ It is also noted that in absense of this control, modification of an
+ object which presently violates the controlling subschema will fail
+ unless the modification would result in the object conforming to the
+ controlling subschema. That is, modifications of an non-conformant
+ object should result in a conformant object.
+
+ In the presence of this control, modifications of a non-conformant
+ object need not result in a conformant object.
+
+
+3.6. NO-USER-MODIFICATION attribute modification
+
+ In absence of this control, an attempt to modify values of a
+ NO-USER-MODIFICATION attribute [RFC4512] would normally lead to a
+
+
+
+Zeilenga LDAP Relax Rules Control [Page 5]
+\f
+INTERNET-DRAFT draft-zeilenga-ldap-relax-01 14 February 2007
+
+
+ constraintViolation or other appropriate error [RFC4511]. In the
+ presence of the Relax Rules control in the update request requests the
+ modification be allowed.
+
+ Relaxation of the NO-USER-MODIFICATION constraint is not appropriate
+ for some operational attribute types. For instance, as the value of
+ the 'structuralObjectClass' is derived by the values of the
+ 'objectClass' attribute, the 'structuralObjectClass' attribute type's
+ NO-USER-MODIFICATION contraint MUST NOT be relaxed. To effect a
+ change in the structuralObjectClass class, values of objectClass
+ should be changed as discussed in Section 3.1. Other attributes for
+ which the NO-USER-MODIFICATION constraint should not be relaxed
+ include 'subschemaSubentry' [RFC4512] and
+ 'collectiveAttributeSubentries' [RFC3671].
+
+ The subsections of this section discuss modification of various
+ operational attributes where their NO-USER-MODIFICATION constraint may
+ be relaxed. Future documents may specify where NO-USER-MODIFICATION
+ constraints on other operational attribute may be relaxed. In absence
+ of a document detailing that the NO-USER-MODIFICATION constraint on a
+ particular operational attribute may be relaxed, implementors SHOULD
+ assume relaxation of the constraint is not appropriate for that
+ attribute.
+
+
+3.1.1. 'entryUUID' attribute
+
+ To provide a value for the 'entryUUID' [RFC4530] attribute on entry
+ creation, the client should issue an LDAP Add request with a Relax
+ Rules control providing the desired value. For instance:
+
+ dn: ou=Unit,dc=example,dc=net
+ control: IANA-ASSIGNED-OID
+ changetype: add
+ objectClass: organizationalUnit
+ ou: Unit
+ entryUUID: 597ae2f6-16a6-1027-98f4-d28b5365dc14
+
+ In this case, the server is either to add the entry using the
+ provided 'entryUUID' value or fail the request.
+
+ To provide a replacement value for the 'entryUUID' after entry
+ creation, the client should issue an LDAP Modify request with a
+ Relax Rules control including an approrpiate change. For instance:
+
+ dn: ou=Unit,dc=example,dc=net
+ control: IANA-ASSIGNED-OID
+ changetype: modify
+
+
+
+Zeilenga LDAP Relax Rules Control [Page 6]
+\f
+INTERNET-DRAFT draft-zeilenga-ldap-relax-01 14 February 2007
+
+
+ replace: entryUUID
+ entryUUID: 597ae2f6-16a6-1027-98f4-d28b5365dc14
+ -
+
+ In this case, the server is either to replace the 'entryUUID' value
+ as requested or fail the request.
+
+
+3.2.2. createTimestamp
+
+ To provide a value for the 'createTimestamp' [RFC4512] attribute
+ on entry creation, the client should issue an LDAP Add request with
+ a Relax Rules control providing the desired 'createTimestamp'
+ value. For instance:
+
+ dn: ou=Unit,dc=example,dc=net
+ control: IANA-ASSIGNED-OID
+ changetype: add
+ objectClass: organizationalUnit
+ ou: Unit
+ createTimestamp: 20060101000000Z
+
+ In this case, the server is either to add the entry using the
+ provided 'createTimestamp' value or fail the request.
+
+ To provide a replacement value for the 'createTimestamp' after
+ entry creation, the client should issue an LDAP Modify request with
+ a Relax Rules control including an approrpiate change. For instance:
+
+ dn: ou=Unit,dc=example,dc=net
+ control: IANA-ASSIGNED-OID
+ changetype: modify
+ replace: createTimestamp
+ createTimestamp: 20060101000000Z
+ -
+
+ In this case, the server is either to replace the 'createTimestamp'
+ value as requested or fail the request.
+
+ The server should ensure the requested 'createTimestamp' value is
+ appropriate. In particular, it should fail the request if the
+ requested 'createTimestamp' value is in the future or is greater
+ than the value of the 'modifyTimestamp' attribute.
+
+
+3.2.3. modifyTimestamp
+
+ To provide a value for the 'modifyTimestamp' [RFC4512] attribute
+
+
+
+Zeilenga LDAP Relax Rules Control [Page 7]
+\f
+INTERNET-DRAFT draft-zeilenga-ldap-relax-01 14 February 2007
+
+
+ on entry creation, the client should issue an LDAP Add request with
+ a Relax Rules control providing the desired 'modifyTimestamp'
+ value. For instance:
+
+ dn: ou=Unit,dc=example,dc=net
+ control: IANA-ASSIGNED-OID
+ changetype: add
+ objectClass: organizationalUnit
+ ou: Unit
+ modifyTimestamp: 20060101000000Z
+
+ In this case, the server is either to add the entry using
+ the provided 'modifyTimestamp' value or fail the request.
+
+ To provide a replacement value for the 'modifyTimestamp' after
+ entry creation, the client should issue an LDAP Modify
+ request with a Relax Rules control including an approrpiate
+ change. For instance:
+
+ dn: ou=Unit,dc=example,dc=net
+ control: IANA-ASSIGNED-OID
+ changetype: modify
+ replace: modifyTimestamp
+ modifyTimestamp: 20060101000000Z
+ -
+
+ In this case, the server is either to replace the 'modifyTimestamp'
+ value as requested or fail the request.
+
+ The server should ensure the requested 'modifyTimestamp' value is
+ appropriate. In particular, it should fail the request if the
+ requested 'modifyTimestamp' value is in the future or is less than
+ the value of the 'createTimestamp' attribute.
+
+
+ 3.2.3. creatorsName and modifiersName
+
+ To provide a value for the 'creatorsName' and/or 'modifiersName'
+ [RFC4512] attribute on entry creation, the client should issue an
+ LDAP Add request with a Relax Rules control providing the desired
+ values. For instance:
+
+ dn: ou=Unit,dc=example,dc=net
+ control: IANA-ASSIGNED-OID
+ changetype: add
+ objectClass: organizationalUnit
+ ou: Unit
+ creatorsName: cn=Jane Doe,dc=example,net
+
+
+
+Zeilenga LDAP Relax Rules Control [Page 8]
+\f
+INTERNET-DRAFT draft-zeilenga-ldap-relax-01 14 February 2007
+
+
+ modifiersName: cn=Jane Doe,dc=example,net
+
+ In this case, the server is either to add the entry using
+ the provided values or fail the request.
+
+ To provide a replacement values after entry creation for either of
+ the 'creatorsName' or 'modifiersName' attributes or both, the
+ client should issue an LDAP Modify request with a Relax Rules control
+ including the approrpiate changes. For instance:
+
+ dn: ou=Unit,dc=example,dc=net
+ control: IANA-ASSIGNED-OID
+ changetype: modify
+ replace: creatorsName
+ creatorsName: cn=Jane Doe,dc=example,net
+ -
+ replace: modifiersName
+ modifiersName: cn=Jane Doe,dc=example,net
+ -
+
+ In this case, the server is either to replace the provided
+ values as requested or fail the request.
+
+
+4. Security Considerations
+
+ Use of this extension should be subject to appropriate administrative
+ and access controls. Use of this mechanism is intended to be
+ restricted to directory administrators.
+
+ Security considerations for the base operations [RFC4511] extended
+ by this control, as well as general LDAP security considerations
+ [RFC4510], generally apply to implementation and use of this
+ extension.
+
+
+5. IANA Considerations
+
+5.1. Object Identifier
+
+ It is requested that the IANA assign a LDAP Object Identifier
+ [RFC4520] to identify the LDAP Relax Rules Control defined in this
+ document.
+
+ Subject: Request for LDAP Object Identifier Registration
+ Person & email address to contact for further information:
+ Kurt Zeilenga <Kurt.Zeilenga@Isode.COM>
+ Specification: RFC XXXX
+
+
+
+Zeilenga LDAP Relax Rules Control [Page 9]
+\f
+INTERNET-DRAFT draft-zeilenga-ldap-relax-01 14 February 2007
+
+
+ Author/Change Controller: Kurt Zeilenga <Kurt.Zeilenga@Isode.COM>
+ Comments: Identifies the LDAP Relax Rules Control
+
+5.2 LDAP Protocol Mechanism
+
+ Registration of this protocol mechanism [RFC4520] is requested.
+
+ Subject: Request for LDAP Protocol Mechanism Registration
+ Object Identifier: IANA-ASSIGNED-OID
+ Description: Relax Rules Control
+ Person & email address to contact for further information:
+ Kurt Zeilenga <Kurt.Zeilenga@Isode.COM>
+ Usage: Control
+ Specification: RFC XXXX
+ Author/Change Controller: Kurt Zeilenga <Kurt.Zeilenga@Isode.COM>
+ Comments: none
+
+
+6. Author's Address
+
+ Kurt D. Zeilenga
+ Isode Limited
+
+ Email: Kurt.Zeilenga@Isode.COM
+
+
+7. References
+
+ [[Note to the RFC Editor: please replace the citation tags used in
+ referencing Internet-Drafts with tags of the form RFCnnnn where
+ possible.]]
+
+
+7.1. Normative References
+
+ [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
+ Requirement Levels", BCP 14 (also RFC 2119), March 1997.
+
+ [RFC3671] Zeilenga, K., "Collective Attributes in LDAP", RFC 3671,
+ December 2003.
+
+ [RFC4510] Zeilenga, K. (editor), "LDAP: Technical Specification
+ Road Map", RFC 4510, June 2006.
+
+ [RFC4511] Sermersheim, J. (editor), "LDAP: The Protocol", RFC
+ 4511, June 2006.
+
+ [RFC4512] Zeilenga, K. (editor), "LDAP: Directory Information
+
+
+
+Zeilenga LDAP Relax Rules Control [Page 10]
+\f
+INTERNET-DRAFT draft-zeilenga-ldap-relax-01 14 February 2007
+
+
+ Models", RFC 4512, June 2006.
+
+ [RFC4530] Zeilenga, K., "Lightweight Directory Access Protocol
+ (LDAP) entryUUID Operational Attribute", RFC 4530, June
+ 2006.
+
+ [X.500] International Telecommunication Union -
+ Telecommunication Standardization Sector, "The Directory
+ -- Overview of concepts, models and services,"
+ X.500(1993) (also ISO/IEC 9594-1:1994).
+
+
+7.2. Informative References
+
+ [RFC4520] Zeilenga, K., "Internet Assigned Numbers Authority
+ (IANA) Considerations for the Lightweight Directory
+ Access Protocol (LDAP)", RFC 4520, BCP 64, June 2006.
+
+
+
+Intellectual Property
+
+ The IETF takes no position regarding the validity or scope of any
+ Intellectual Property Rights or other rights that might be claimed to
+ pertain to the implementation or use of the technology described in
+ this document or the extent to which any license under such rights
+ might or might not be available; nor does it represent that it has
+ made any independent effort to identify any such rights. Information
+ on the procedures with respect to rights in RFC documents can be found
+ in BCP 78 and BCP 79.
+
+ Copies of IPR disclosures made to the IETF Secretariat and any
+ assurances of licenses to be made available, or the result of an
+ attempt made to obtain a general license or permission for the use of
+ such proprietary rights by implementers or users of this specification
+ can be obtained from the IETF on-line IPR repository at
+ http://www.ietf.org/ipr.
+
+ The IETF invites any interested party to bring to its attention any
+ copyrights, patents or patent applications, or other proprietary
+ rights that may cover technology that may be required to implement
+ this standard. Please address the information to the IETF at
+ ietf-ipr@ietf.org.
+
+
+
+Full Copyright
+
+
+
+
+Zeilenga LDAP Relax Rules Control [Page 11]
+\f
+INTERNET-DRAFT draft-zeilenga-ldap-relax-01 14 February 2007
+
+
+ Copyright (C) The IETF Trust (2007).
+
+ This document is subject to the rights, licenses and restrictions
+ contained in BCP 78, and except as set forth therein, the authors
+ retain all their rights.
+
+ This document and the information contained herein are provided on an
+ "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS
+ OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY, THE IETF TRUST AND
+ THE INTERNET ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS
+ OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF
+ THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED
+ WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Zeilenga LDAP Relax Rules Control [Page 12]
+\f
.BI \-y \ passwdfile
Use complete contents of \fIpasswdfile\fP as the password for
simple authentication.
+Note that \fIcomplete\fP means that any leading or trailing whitespaces,
+including newlines, will be considered part of the password and,
+unlike other software, they will not be stripped.
+As a consequence, passwords stored in files by commands like
+.BR echo (1)
+will not behave as expected, since
+.BR echo (1)
+by default appends a trailing newline to the echoed string.
+The recommended portable way to store a cleartext password in a file
+for use with this option is to use
+.BR slappasswd (8)
+with \fI{CLEARTEXT}\fP as hash and the option \fI\-n\fP.
.TP
.BI \-H \ ldapuri
Specify URI(s) referring to the ldap server(s); only the protocol/host/port
[\c
.BR \-r ]
[\c
+.BI \-s \ newsup\fR]
+[\c
.BR \-n ]
[\c
.BR \-v ]
.B \-r
Remove old RDN values from the entry. Default is to keep old values.
.TP
+.BI \-s \ newsup
+Specify a new superior entry. (I.e., move the target entry and make it a
+child of the new superior.) This option is not supported in LDAPv2.
+.TP
.B \-n
Show what would be done, but don't actually change entries. Useful for
debugging in conjunction with -v.
Read a series of lines from \fIfile\fP, performing one LDAP search for
each line. In this case, the \fIfilter\fP given on the command line
is treated as a pattern where the first and only occurrence of \fB%s\fP
-is replaced with a line from \fIfile\fP. Any other occurence of the
+is replaced with a line from \fIfile\fP. Any other occurrence of the
the \fB%\fP character in the pattern will be regarded as an error.
Where it is desired that the search filter include a \fB%\fP character,
the character should be encoded as \fB\\25\fP (see RFC 4515).
simple authentication.
.TP
.BI \-H \ ldapuri
-Specify URI(s) referring to the ldap server(s); only the protocol/host/port
-fields are allowed; a list of URI, separated by whitespace or commas
-is expected.
+Specify URI(s) referring to the ldap server(s);
+a list of URI, separated by whitespace or commas is expected;
+only the protocol/host/port fields are allowed.
+As an exception, if no host/port is specified, but a DN is,
+the DN is used to look up the corresponding host(s) using the
+DNS SRV records, according to RFC 2782. The DN must be a non-empty
+sequence of AVAs whose attribute type is "dc" (domain component),
+and must be escaped according to RFC 2396.
.TP
.BI \-h \ ldaphost
Specify an alternate host on which the ldap server is running.
Deprecated interfaces generally remain in the library. The macro
LDAP_DEPRECATED can be defined to a non-zero value
(e.g., -DLDAP_DEPRECATED=1) when compiling program designed to use
-deprecated interaces. It is recommended that developers writing new
+deprecated interfaces. It is recommended that developers writing new
programs, or updating old programs, avoid use of deprecated interfaces.
Over time, it is expected that documentation (and, eventually, support) for
deprecated interfaces to be eliminated.
.\" Copyright 1998-2007 The OpenLDAP Foundation All Rights Reserved.
.\" Copying restrictions apply. See COPYRIGHT/LICENSE.
.SH NAME
-ber_get_next, ber_skip_tag, ber_peek_tag, ber_scanf, ber_get_int,
-ber_get_enum, ber_get_stringb, ber_get_stringa, ber_get_stringal,
-ber_get_stringbv, ber_get_null, ber_get_boolean, ber_get_bitstring,
-ber_first_element, ber_next_element
-\- LBER simplified Basic Encoding Rules library routines for decoding
+ber_get_next, ber_skip_tag, ber_peek_tag, ber_scanf, ber_get_int, ber_get_enum, ber_get_stringb, ber_get_stringa, ber_get_stringal, ber_get_stringbv, ber_get_null, ber_get_boolean, ber_get_bitstring, ber_first_element, ber_next_element \- OpenLDAP LBER simplified Basic Encoding Rules library routines for decoding
.SH LIBRARY
OpenLDAP LBER (liblber, -llber)
.SH SYNOPSIS
.\" Copyright 1998-2007 The OpenLDAP Foundation All Rights Reserved.
.\" Copying restrictions apply. See COPYRIGHT/LICENSE.
.SH NAME
-ber_alloc_t, ber_flush, ber_flush2, ber_printf, ber_put_int, ber_put_enum, ber_put_ostring, ber_put_string, ber_put_null, ber_put_boolean, ber_put_bitstring, ber_start_seq, ber_start_set, ber_put_seq, ber_put_set \- LBER simplified Basic Encoding Rules library routines for encoding
+ber_alloc_t, ber_flush, ber_flush2, ber_printf, ber_put_int, ber_put_enum, ber_put_ostring, ber_put_string, ber_put_null, ber_put_boolean, ber_put_bitstring, ber_start_seq, ber_start_set, ber_put_seq, ber_put_set \- OpenLDAP LBER simplified Basic Encoding Rules library routines for encoding
.SH LIBRARY
OpenLDAP LBER (liblber, -llber)
.SH SYNOPSIS
.\" Copyright 1998-2007 The OpenLDAP Foundation All Rights Reserved.
.\" Copying restrictions apply. See COPYRIGHT/LICENSE.
.SH NAME
-ber_memalloc, ber_memcalloc, ber_memrealloc, ber_memfree, ber_memvfree \- LBER memory allocators
+ber_memalloc, ber_memcalloc, ber_memrealloc, ber_memfree, ber_memvfree \- OpenLDAP LBER memory allocators
.SH LIBRARY
OpenLDAP LBER (liblber, -llber)
.SH SYNOPSIS
.\" Copyright 1998-2007 The OpenLDAP Foundation All Rights Reserved.
.\" Copying restrictions apply. See COPYRIGHT/LICENSE.
.SH NAME
-ber_sockbuf_alloc, ber_sockbuf_free, ber_sockbuf_ctrl, ber_sockbuf_add_io,
-ber_sockbuf_remove_io, Sockbuf_IO \- LBER I/O infrastructure
+ber_sockbuf_alloc, ber_sockbuf_free, ber_sockbuf_ctrl, ber_sockbuf_add_io, ber_sockbuf_remove_io, Sockbuf_IO \- OpenLDAP LBER I/O infrastructure
.SH LIBRARY
OpenLDAP LBER (liblber, -llber)
.SH SYNOPSIS
.\" Copyright 1998-2007 The OpenLDAP Foundation All Rights Reserved.
.\" Copying restrictions apply. See COPYRIGHT/LICENSE.
.SH NAME
-ber_int_t, ber_uint_t, ber_len_t, ber_slen_t, ber_tag_t,
-struct berval, BerValue, BerVarray, BerElement,
-ber_bvfree, ber_bvecfree, ber_bvecadd, ber_bvarray_free, ber_bvarray_add,
-ber_bvdup, ber_dupbv, ber_bvstr, ber_bvstrdup, ber_str2bv,
-ber_alloc_t, ber_init, ber_init2, ber_free
-\- LBER types and allocation functions
+ber_int_t, ber_uint_t, ber_len_t, ber_slen_t, ber_tag_t, struct berval, BerValue, BerVarray, BerElement, ber_bvfree, ber_bvecfree, ber_bvecadd, ber_bvarray_free, ber_bvarray_add, ber_bvdup, ber_dupbv, ber_bvstr, ber_bvstrdup, ber_str2bv, ber_alloc_t, ber_init, ber_init2, ber_free \- OpenLDAP LBER types and allocation functions
.SH LIBRARY
OpenLDAP LBER (liblber, -llber)
.SH SYNOPSIS
.B bv_len
octets.
.B bv_val
-is not necessarily terminated by a NUL (zero) octet.
+is not necessarily terminated by a NULL (zero) octet.
.BR ber_bvfree ()
frees a BerValue, pointed to by \fIbv\fP, returned from this API. If \fIbv\fP
is NULL, the routine does nothing.
.\" Copyright 1998-2007 The OpenLDAP Foundation All Rights Reserved.
.\" Copying restrictions apply. See COPYRIGHT/LICENSE.
.SH NAME
-ldap - OpenLDAP Lightweight Directory Access Protocol API
+ldap \- OpenLDAP Lightweight Directory Access Protocol API
.SH LIBRARY
OpenLDAP LDAP (libldap, -lldap)
.SH SYNOPSIS
constructed by hand and should conform to RFC 4515 UTF\-8
string representation.
.LP
-LDAP URL are to be passed to routines are expected to conform
+LDAP URLs to be passed to routines are expected to conform
to RFC 4516 format. The
.BR ldap_url (3)
routines can be used to work with LDAP URLs.
+.LP
+LDAP controls to be passed to routines can be manipulated using the
+.BR ldap_controls (3)
+routines.
.SH DISPLAYING RESULTS
Results obtained from the search routines can be output by hand,
by calling
.SM ldap_err2string(3)
convert LDAP error indication to a string
.TP
+.SM ldap_extended_operation(3)
+asynchronously perform an arbitrary extended operation
+.TP
+.SM ldap_extended_operation_s(3)
+synchronously perform an arbitrary extended operation
+.TP
.SM ldap_first_attribute(3)
return first attribute name in an entry
.TP
.B ldap_unbind_ext()
and
.B ldap_unbind_ext_s()
-allows the operations to sepicify controls.
+allows the operations to specify controls.
.SH ERRORS
Asynchronous routines will return -1 in case of error, setting the
\fIld_errno\fP parameter of the \fIld\fP structure. Synchronous
.\" Copyright 1998-2007 The OpenLDAP Foundation All Rights Reserved.
.\" Copying restrictions apply. See COPYRIGHT/LICENSE.
.SH NAME
-ldap_create_control, ldap_find_control, ldap_control_free, ldap_controls_free \- LDAP control manipulation routines
+ldap_control_create, ldap_control_find, ldap_control_dup,
+ldap_controls_dup, ldap_control_free, ldap_controls_free
+\- LDAP control manipulation routines
.SH LIBRARY
OpenLDAP LDAP (libldap, -lldap)
.SH SYNOPSIS
.B #include <ldap.h>
.LP
-.BI "int ldap_create_control(LDAP_CONST char *" OID ", BerElement *" ber ", int " iscritical ", LDAPControl **" ctrlp ");"
+.BI "int ldap_control_create(const char *" oid ", int " iscritical ", struct berval *" value ", int " dupval ", LDAPControl **" ctrlp ");"
.LP
-.BI "LDAPControl *ldap_find_control(LDAP_CONST char *" OID ", LDAPControl **" ctrls ");"
+.BI "LDAPControl *ldap_control_find( const char *" oid ", LDAPControl **" ctrls ", LDAPControl ***" nextctrlp ");"
+.LP
+.BI "LDAPControl *ldap_control_dup(LDAPControl *" ctrl ");"
+.LP
+.BI "LDAPControl **ldap_controls_dup(LDAPControl **" ctrls ");"
.LP
.BI "void ldap_control_free(LDAPControl *" ctrl ");"
.LP
.BI "void ldap_controls_free(LDAPControl **" ctrls ");"
.SH DESCRIPTION
These routines are used to manipulate structures used for LDAP controls.
-.BR ldap_create_control ()
+
+.BR ldap_control_create ()
creates a control with the specified
.I OID
using the contents of the
-.I ber
-parameter for the control value, if any. The
+.I value
+parameter for the control value, if any. The content of
+.I value
+is duplicated if
+.I dupval
+is non-zero. The
.I iscritical
-parameter should be non-zero for a critical control. The created control
+parameter must be non-zero for a critical control. The created control
is returned in the
.I ctrlp
-parameter. The routine returns
+parameter. The routine returns
.B LDAP_SUCCESS
on success or some other error code on failure.
-.BR ldap_find_control ()
-searches the
+The content of
+.IR value ,
+for supported control types, can be prepared using helpers provided
+by this implementation of libldap, usually in the form
+.BR "ldap_create_<control name>_control_value" ().
+Otherwise, it can be BER-encoded using the functionalities of liblber.
+
+.BR ldap_control_find ()
+searches the NULL-terminated
.I ctrls
array for a control whose OID matches the
-.I OID
-parameter. The routine returns a pointer to the control if found,
+.I oid
+parameter. The routine returns a pointer to the control if found,
NULL otherwise.
+If the parameter
+.I nextctrlp
+is not NULL, on return it will point to the next control
+in the array, and can be passed to the
+.BR ldap_control_find ()
+routine for subsequent calls, to find further occurrences of the same
+control type.
+The use of this function is discouraged; the recommended way of handling
+controls in responses consists in going through the array of controls,
+dealing with each of them in the returned order, since it could matter.
+
+.BR ldap_control_dup ()
+duplicates an individual control structure, and
+.BR ldap_controls_dup ()
+duplicates a NULL-terminated array of controls.
+
.BR ldap_control_free ()
frees an individual control structure, and
.BR ldap_controls_free ()
-frees an array of controls.
+frees a NULL-terminated array of controls.
+
.SH SEE ALSO
.BR ldap (3),
.BR ldap_error (3)
-ldap_create_control.3
-ldap_find_control.3
+ldap_control_create.3
+ldap_control_find.3
+ldap_control_dup.3
+ldap_controls_dup.3
ldap_control_free.3
ldap_controls_free.3
.\" Copyright 1998-2007 The OpenLDAP Foundation All Rights Reserved.
.\" Copying restrictions apply. See COPYRIGHT/LICENSE.
.SH NAME
-ldap_first_message, ldap_next_message, ldap_count_messages \- Stepping
-through messages in a result chain
+ldap_first_message, ldap_next_message, ldap_count_messages \- Stepping through messages in a result chain
.SH LIBRARY
OpenLDAP LDAP (libldap, -lldap)
.SH SYNOPSIS
.\" Copyright 1998-2007 The OpenLDAP Foundation All Rights Reserved.
.\" Copying restrictions apply. See COPYRIGHT/LICENSE.
.SH NAME
-ldap_first_reference, ldap_next_reference, ldap_count_references \- Stepping
-through continuation references in a result chain
+ldap_first_reference, ldap_next_reference, ldap_count_references \- Stepping through continuation references in a result chain
.SH LIBRARY
OpenLDAP LDAP (libldap, -lldap)
.SH SYNOPSIS
in an infinite timeout, which is the default.
.TP
.B LDAP_OPT_DEREF
-Sets/gets the value that defines when alias deferencing must occur.
+Sets/gets the value that defines when alias dereferencing must occur.
.BR outvalue
and
.BR invalue
.B LDAP_OPT_HOST_NAME
Sets/gets a space-separated list of hosts to be contacted by the library
when trying to establish a connection.
-This is now deprecated in favour of
+This is now deprecated in favor of
.BR LDAP_OPT_URI .
.BR outvalue
must be a
.\" Copyright 1998-2007 The OpenLDAP Foundation All Rights Reserved.
.\" Copying restrictions apply. See COPYRIGHT/LICENSE.
.SH NAME
-ldap_parse_sort_control \- Decodes the information returned from a search operation
-that used a server-side sort control.
+ldap_parse_sort_control \- Decode the information returned from a search operation that used a server-side sort control
.SH LIBRARY
OpenLDAP LDAP (libldap, -lldap)
.SH SYNOPSIS
.\" Copyright 1998-2007 The OpenLDAP Foundation All Rights Reserved.
.\" Copying restrictions apply. See COPYRIGHT/LICENSE.
.SH NAME
-ldap_parse_vlv_control \- Decodes the information returned from a search operation that
-used a VLV (virtual list view) control.
+ldap_parse_vlv_control \- Decode the information returned from a search operation that used a VLV (virtual list view) control
.SH LIBRARY
OpenLDAP LDAP (libldap, -lldap)
.SH SYNOPSIS
not returned. You should use this returned context in the next call to
create a VLV control. When the berval structure is no longer needed, you should
free the memory by calling the \fIber_bvfree function.e\fP
-\fIerrcodep\fP is an output paremeter, which points to the result code returned
+\fIerrcodep\fP is an output parameter, which points to the result code returned
by the server. If this parameter is NULL, the result code is not returned.
.LP
See
.B ldap_rename
works just like
.B ldap_rename_s,
-but the operation is asynchornous. It returns the message id of the request
+but the operation is asynchronous. It returns the message id of the request
it initiated. The result of this operation can be obtained by calling
.BR ldap_result(3).
.SH ERRORS
routine is used to wait for and return the result of
an operation previously initiated by one of the LDAP asynchronous
operation routines (e.g.,
-.BR ldap_search (3),
-.BR ldap_modify (3),
+.BR ldap_search_ext (3),
+.BR ldap_modify_ext (3),
etc.). Those routines all return -1 in case of error, and an
invocation identifier upon successful initiation of the operation. The
invocation identifier is picked by the library and is guaranteed to be
LDAP_RES_MODDN (0x6d)
LDAP_RES_COMPARE (0x6f)
LDAP_RES_EXTENDED (0x78)
- LDAP_RES_EXTENDED_PARTIAL (0x79)
+ LDAP_RES_INTERMEDIATE (0x79)
.fi
.LP
The
result(s) by
.B ldap_result()
or
-.BR ldap_search_s (3)
+.BR ldap_search_ext_s (3)
and friends.
It takes a pointer to the result or result chain to be freed and returns
the type of the last message in the chain.
return -1 on error.
.SH SEE ALSO
.BR ldap (3),
-.BR ldap_search (3),
.BR ldap_first_message (3),
.BR select (2)
.SH ACKNOWLEDGEMENTS
.\" Copyright 2000-2007 The OpenLDAP Foundation All Rights Reserved.
.\" Copying restrictions apply. See COPYRIGHT/LICENSE.
.SH NAME
-ldap_str2syntax, ldap_syntax2str, ldap_syntax2name, ldap_syntax_free,
-ldap_str2matchingrule, ldap_matchingrule2str, ldap_matchingrule2name,
-ldap_matchingrule_free,
-ldap_str2attributetype, ldap_attributetype2str,
-ldap_attributetype2name, ldap_attributetype_free,
-ldap_str2objectclass, ldap_objectclass2str, ldap_objectclass2name,
-ldap_objectclass_free,
-ldap_scherr2str \- Schema definition handling routines
+ldap_str2syntax, ldap_syntax2str, ldap_syntax2name, ldap_syntax_free, ldap_str2matchingrule, ldap_matchingrule2str, ldap_matchingrule2name, ldap_matchingrule_free, ldap_str2attributetype, ldap_attributetype2str, ldap_attributetype2name, ldap_attributetype_free, ldap_str2objectclass, ldap_objectclass2str, ldap_objectclass2name, ldap_objectclass_free, ldap_scherr2str \- Schema definition handling routines
.SH LIBRARY
OpenLDAP LDAP (libldap, -lldap)
.SH SYNOPSIS
all user attributes to be returned.
The description "+"(LDAP_ALL_OPERATIONAL_ATTRIBUTES) may be used to
request all operational attributes to be returned. Note that this
-requires the server to suppor the LDAP All Operational Attribute
+requires the server to support the LDAP All Operational Attribute
extension.
To request no attributes, the description "1.1" (LDAP_NO_ATTRS)
should be listed by itself.
.\" Copyright 1998-2007 The OpenLDAP Foundation All Rights Reserved.
.\" Copying restrictions apply. See COPYRIGHT/LICENSE.
.SH NAME
-LDAP sorting routines (deprecated)
+ldap_sort_entries, ldap_sort_values, ldap_sort_strcasecmp \- LDAP sorting routines (deprecated)
.SH LIBRARY
OpenLDAP LDAP (libldap, -lldap)
.SH DESCRIPTION
.nf
.B #include <ldap_sync.h>
.LP
-.BI "int ldap_sync_init(ldap_sync_t *" ls ", int " mode ", int " cancel ");"
+.BI "int ldap_sync_init(ldap_sync_t *" ls ", int " mode ");"
.LP
-.BI "int ldap_sync_init_refresh_only(ldap_sync_t *" ls ", int " cancel ");"
+.BI "int ldap_sync_init_refresh_only(ldap_sync_t *" ls ");"
.LP
-.BI "int ldap_sync_init_refresh_and_persist(ldap_sync_t *" ls ", int " cancel ");"
+.BI "int ldap_sync_init_refresh_and_persist(ldap_sync_t *" ls ");"
.LP
.BI "int ldap_sync_poll(ldap_sync_t *" ls ");"
.LP
the client should start polling.
Except for the
.BR LDAP_SYNC_CAPI_PRESENTS_IDSET
-and LDAP_SYNC_CAPI_DELETES_IDSET
+and
+.BR LDAP_SYNC_CAPI_DELETES_IDSET
cases,
.BR syncUUIDs
is NULL.
After that, the caller is responsible for setting up the
connection (member
.BR ls_ld ),
-evetually setting up transport security (TLS),
+eventually setting up transport security (TLS),
for binding and any other initialization.
The caller must also fill all the documented search-related fields
of the
.\" Copyright 1998-2007 The OpenLDAP Foundation All Rights Reserved.
.\" Copying restrictions apply. See COPYRIGHT/LICENSE.
.SH NAME
-ldap_is_ldap_url,
-ldap_url_parse,
-ldap_free_urldesc \- LDAP Uniform Resource Locator routines
+ldap_is_ldap_url, ldap_url_parse, ldap_free_urldesc \- LDAP Uniform Resource Locator routines
.SH LIBRARY
OpenLDAP LDAP (libldap, -lldap)
.SH SYNOPSIS
.B TLS_CACERT
is always used before
.B TLS_CACERTDIR.
+This parameter is ignored with GNUtls.
.TP
.B TLS_CERT <filename>
Specifies the file that contains the client certificate.
Specifies the file to obtain random bits from when /dev/[u]random is
not available. Generally set to the name of the EGD/PRNGD socket.
The environment variable RANDFILE can also be used to specify the filename.
+This parameter is ignored with GNUtls.
.TP
.B TLS_REQCERT <level>
Specifies what checks to perform on server certificates in a TLS session,
used to verify if the server certificates have not been revoked. This
requires
.B TLS_CACERTDIR
-parameter to be set.
+parameter to be set. This parameter is ignored with GNUtls.
.B <level>
can be specified as one of the following keywords:
.RS
.B all
Check the CRL for a whole certificate chain
.RE
+.TP
+.B TLS_CRLFILE <filename>
+Specifies the file containing a Certificate Revocation List to be used
+to verify if the server certificates have not been revoked. This
+parameter is only supported with GNUtls.
.SH "ENVIRONMENT VARIABLES"
.TP
LDAPNOINIT
.BR ldapadd (1),
.BR ldapmodify (1),
.BR slapadd (8),
+.BR slapcat (8),
+.BR slapd-ldif (5),
.BR slapd.replog (5).
.LP
"LDAP Data Interchange Format," Good, G., RFC 2849.
.\" Copying restrictions apply. See COPYRIGHT/LICENSE.
.\" $OpenLDAP$
.SH NAME
-\fBslapd-bdb\fP, \fBslapd-hdb\fP \- Berkeley DB backends to \fBslapd\fP
+slapd-bdb, slapd-hdb \- Berkeley DB backends to slapd
.SH SYNOPSIS
.B ETCDIR/slapd.conf
.SH DESCRIPTION
is the recommended primary backend for a normal
.B slapd
database.
-It uses the Sleepycat Berkeley DB (BDB) package to store data.
+It uses the Oracle Berkeley DB (BDB) package to store data.
It makes extensive use of indexing and caching to speed data access.
.LP
\fBhdb\fP is a variant of the \fBbdb\fP backend that uses a
In this case, the modified data is discarded and a subsequent search
will return a different result.
.TP
+.BI dncachesize \ <integer>
+Specify the maximum number of DNs in the in-memory DN cache. The
+default is twice the \fBcachesize\fP. Ideally this cache should be
+large enough to contain the DNs of every entry in the database.
+.TP
.BI idlcachesize \ <integer>
Specify the size of the in-memory index cache, in index slots. The
default is zero. A larger value will speed up frequent searches of
Berkeley DB documentation.
.SH ACKNOWLEDGEMENTS
.so ../Project
+Originally begun by Kurt Zeilenga. Caching mechanisms originally designed
+by Jong-Hyuk Choi. Completion and subsequent work, as well as
+back-hdb, by Howard Chu.
.\" Copying restrictions apply. See COPYRIGHT/LICENSE.
.\" $OpenLDAP$
.SH NAME
-slapd-config \- configuration backend
+slapd-config \- configuration backend to slapd
.SH SYNOPSIS
ETCDIR/slapd.d
.SH DESCRIPTION
.B minssf
option description. The default is 71.
.TP
+.B olcLogFile: <filename>
+Specify a file for recording debug log messages. By default these messages
+only go to stderr and are not recorded anywhere else. Specifying a logfile
+copies messages to both stderr and the logfile.
+.TP
.B olcLogLevel: <integer> [...]
Specify the level at which debugging statements and operation
statistics should be syslogged (currently logged to the
They must be considered subsystems rather than increasingly verbose
log levels.
Some messages with higher priority are logged regardless
-of the configured loglevel as soon as some logging is configured,
-otherwise anything is logged at all.
+of the configured loglevel as soon as any logging is configured.
Log levels are additive, and available levels are:
.RS
.RS
.BR slapd (8)
cannot find a local database to handle a request.
If multiple values are specified, each url is provided.
-.\" slurpd-related keywords are all deprecated
-.\".TP
-.\".B replica-argsfile
-.\"The ( absolute ) name of a file that will hold the
-.\".B slurpd
-.\"server's command line options
-.\"if started without the debugging command line option.
-.\"If it appears after a
-.\".B replogfile
-.\"directive, the args file is specific to the
-.\".BR slurpd (8)
-.\"instance that handles that replication log.
-.\".TP
-.\".B replica-pidfile
-.\"The ( absolute ) name of a file that will hold the
-.\".B slurpd
-.\"server's process ID ( see
-.\".BR getpid (2)
-.\") if started without the debugging command line option.
-.\"If it appears after a
-.\".B replogfile
-.\"directive, the pid file is specific to the
-.\".BR slurpd (8)
-.\"instance that handles that replication log.
-.\".TP
-.\".B replicationinterval
-.\"The number of seconds
-.\".B slurpd
-.\"waits before checking the replogfile for changes.
-.\"If it appears after a
-.\".B replogfile
-.\"directive, the replication interval is specific to the
-.\".BR slurpd (8)
-.\"instance that handles that replication log.
.TP
.B olcReverseLookup: TRUE | FALSE
Enable/disable client name unverified reverse lookup (default is
Specify the name of an LDIF(5) file containing user defined attributes
for the root DSE. These attributes are returned in addition to the
attributes normally produced by slapd.
+
+The root DSE is an entry with information about the server and its
+capabilities, in operational attributes.
+It has the empty DN, and can be read with e.g.:
+.ti +4
+ldapsearch -x -b "" -s base "+"
+.br
+See RFC 4512 section 5.1 for details.
.TP
.B olcSaslHost: <fqdn>
Used to specify the fully qualified domain name used for SASL processing.
olcTLSCipherSuite: HIGH:MEDIUM:+SSLv2
-To check what ciphers a given spec selects, use:
+To check what ciphers a given spec selects in OpenSSL, use:
+
+.nf
+ openssl ciphers -v <cipher-suite-spec>
+.fi
-openssl ciphers -v <cipher-suite-spec>
+To obtain the list of ciphers in GNUtls use:
+
+.nf
+ gnutls-cli -l
+.fi
.TP
.B olcTLSCACertificateFile: <filename>
Specifies the file that contains certificates for all of the Certificate
Specifies the path of a directory that contains Certificate Authority
certificates in separate individual files. Usually only one of this
or the olcTLSCACertificateFile is defined. If both are specified, both
-locations will be used.
+locations will be used. This directive is not supported
+when using GNUtls.
.TP
.B olcTLSCertificateFile: <filename>
Specifies the file that contains the
Anonymous Diffie-Hellman key exchanges in certain non-default cipher suites.
You should append "!ADH" to your cipher suites if you have changed them
from the default, otherwise no certificate exchanges or verification will
-be done.
+be done. When using GNUtls these parameters are always generated randomly
+so this directive is ignored.
.TP
.B olcTLSRandFile: <filename>
Specifies the file to obtain random bits from when /dev/[u]random
is not available. Generally set to the name of the EGD/PRNGD socket.
The environment variable RANDFILE can also be used to specify the filename.
+This directive is ignored with GNUtls.
.TP
.B olcTLSVerifyClient: <level>
Specifies what checks to perform on client certificates in an
used to verify if the client certificates have not been revoked. This
requires
.B olcTLSCACertificatePath
-parameter to be set.
+parameter to be set. This parameter is ignored with GNUtls.
.B <level>
can be specified as one of the following keywords:
.RS
.B all
Check the CRL for a whole certificate chain
.RE
+.TP
+.B olcTLSCRLFile: <filename>
+Specifies a file containing a Certificate Revocation List to be used
+for verifying that certificates have not been revoked. This parameter
+is only valid when using GNUtls.
.SH DYNAMIC MODULE OPTIONS
If
.B slapd
type of backend. All of the Global Database Options may also be
used here.
.TP
+.B olcHidden: TRUE | FALSE
+Controls whether the database will be used to answer
+queries. A database that is hidden will never be
+selected to answer any queries, and any suffix configured
+on the database will be ignored in checks for conflicts
+with other databases. By default, olcHidden is FALSE.
+.TP
.B olcLastMod: TRUE | FALSE
Controls whether
.B slapd
This option puts a replica database into "mirror" mode. Update
operations will be accepted from any user, not just the updatedn. The
database must already be configured as syncrepl consumer
-before this keyword may be set. This mode must be used with extreme
-care, as it does not offer any consistency guarantees. This feature
-is intended to be used with an external frontend that guarantees that
-writes are only directed to a single master, switching to an alternate
-server only if the original master goes down.
+before this keyword may be set. This mode also requires a
+.B olcServerID
+(see above) to be configured.
By default, this setting is FALSE.
.TP
.B olcPlugin: <plugin_type> <lib_path> <init_function> [<arguments>]
Configure a SLAPI plugin. See the
.BR slapd.plugin (5)
manpage for more details.
-.\".HP
-.\".hy 0
-.\".B replica uri=ldap[s]://<hostname>[:port]|host=<hostname>[:port]
-.\".B [starttls=yes|critical]
-.\".B [suffix=<suffix> [...]]
-.\".B bindmethod=simple|sasl [binddn=<simple DN>] [credentials=<simple password>]
-.\".B [saslmech=<SASL mech>] [secprops=<properties>] [realm=<realm>]
-.\".B [authcId=<authentication ID>] [authzId=<authorization ID>]
-.\".B [attrs[!]=<attr list>]
-.\".RS
-.\"Specify a replication site for this database. Refer to the "OpenLDAP
-.\"Administrator's Guide" for detailed information on setting up a replicated
-.\".B slapd
-.\"directory service. Zero or more
-.\".B suffix
-.\"instances can be used to select the subtrees that will be replicated
-.\"(defaults to all the database).
-.\".B host
-.\"is deprecated in favor of the
-.\".B uri
-.\"option.
-.\".B uri
-.\"allows the replica LDAP server to be specified as an LDAP URI.
-.\"A
-.\".B bindmethod
-.\"of
-.\".B simple
-.\"requires the options
-.\".B binddn
-.\"and
-.\".B credentials
-.\"and should only be used when adequate security services
-.\"(e.g TLS or IPSEC) are in place. A
-.\".B bindmethod
-.\"of
-.\".B sasl
-.\"requires the option
-.\".B saslmech.
-.\"Specific security properties (as with the
-.\".B sasl-secprops
-.\"keyword above) for a SASL bind can be set with the
-.\".B secprops
-.\"option. A non-default SASL realm can be set with the
-.\".B realm
-.\"option.
-.\"If the
-.\".B mechanism
-.\"will use Kerberos, a kerberos instance should be given in
-.\".B authcId.
-.\"An
-.\".B attr list
-.\"can be given after the
-.\".B attrs
-.\"keyword to allow the selective replication of the listed attributes only;
-.\"if the optional
-.\".B !
-.\"mark is used, the list is considered exclusive, i.e. the listed attributes
-.\"are not replicated.
-.\"If an objectClass is listed, all the related attributes
-.\"are (are not) replicated.
-.\".RE
-.\".TP
-.\".B replogfile <filename>
-.\"Specify the name of the replication log file to log changes to.
-.\"The replication log is typically written by
-.\".BR slapd (8)
-.\"and read by
-.\".BR slurpd (8).
-.\"See
-.\".BR slapd.replog (5)
-.\"for more information. The specified file should be located
-.\"in a directory with limited read/write/execute access as the replication
-.\"logs may contain sensitive information.
.TP
.B olcRootDN: <dn>
Specify the distinguished name that is not subject to access control
This option is only applicable in a slave
database.
It specifies the DN permitted to update (subject to access controls)
-the replica (typically, this is the DN
-.BR slurpd (8)
-binds to update the replica). Generally, this DN
+the replica. It is only needed in certain push-mode
+replication scenarios. Generally, this DN
.I should not
be the same as the
.B rootdn
.BR slapdn (8),
.BR slapindex (8),
.BR slappasswd (8),
-.BR slaptest (8),
-.BR slurpd (8).
+.BR slaptest (8).
.LP
"OpenLDAP Administrator's Guide" (http://www.OpenLDAP.org/doc/admin/)
.SH ACKNOWLEDGEMENTS
is set to
.IR yes .
+.TP
+.B session\-tracking\-request {NO|yes}
+Adds session tracking control for all requests.
+The client's IP and hostname, and the identity associated to each request,
+if known, are sent to the remote server for informational purposes.
+This directive is incompatible with setting \fIprotocol\-version\fP to 2.
+
.TP
.B single\-conn {NO|yes}
Discards current cached connection when the client rebinds.
.\" Copying restrictions apply. See COPYRIGHT/LICENSE.
.\" $OpenLDAP$
.SH NAME
-slapd-ldbm \- LDBM backend to slapd
+slapd-ldbm \- Discontinued LDBM backend to slapd
.SH SYNOPSIS
ETCDIR/slapd.conf
.SH DESCRIPTION
-The LDBM backend to
-.BR slapd (8)
-is an easy\-to\-configure but obsolete database backend. It does not
-offer the data durability features of the BDB and HDB backends and
-hence is considered deprecated in favor of these robust backends.
-LDBM uses lightweight non\-transactional data interfaces, such as those
-provided by GDBM or Berkeley DB, to store data. It makes extensive
-use of indexing and caching to speed data access.
-.SH CONFIGURATION
-These
-.B slapd.conf
-options apply to the LDBM backend database.
-That is, they must follow a "database ldbm" line and come before any
-subsequent "backend" or "database" lines.
-Other database options are described in the
-.BR slapd.conf (5)
-manual page.
-.TP
-.B cachesize <integer>
-Specify the size in entries of the in-memory cache maintained
-by the LDBM backend database instance.
-The default is 1000 entries.
-.TP
-.B dbcachesize <integer>
-Specify the size in bytes of the in-memory cache associated with each
-open index file.
-If not supported by the underlying database method, this option is
-ignored without comment.
-The default is 100000 bytes.
-.TP
-.B dbnolocking
-Specify that no database locking should be performed.
-Enabling this option may improve performance at the expense of data security.
-Do NOT run any slap tools while slapd is running.
-.TP
-.B dbnosync
-Specify that on-disk database contents should not be immediately
-synchronized with in memory changes.
-Enabling this option may improve performance at the expense of data
-security.
-.TP
-.B dbsync <frequency> <maxdelays> <delayinterval>
-Flush dirty database buffers to disk every
-.B <seconds>
-seconds.
-Implies
-.B dbnosync
-(ie. individual updates are no longer written to disk).
-It attempts to avoid syncs during periods of peak activity by waiting
-.B <delayinterval>
-seconds if the server is busy, repeating this delay up to
-.B <maxdelays>
-times before proceeding.
-It is an attempt to provide higher write performance with some amount
-of data security.
-Note that it may still be possible to get an inconsistent database if
-the underlying engine fills its cache and writes out individual pages
-and slapd crashes or is killed before the next sync.
-.B <maxdelays>
-and
-.B <delayinterval>
-are optional and default to
-.B 12
-and
-.B 5
-respectively, giving a total elapsed delay of 60 seconds before a sync
-will occur.
-.B <maxdelays>
-may be zero, and
-.B <delayinterval>
-must be 1 or greater.
-.TP
-.B directory <directory>
-Specify the directory where the LDBM files containing this database and
-associated indexes live.
-A separate directory must be specified for each database.
-The default is
-.BR LOCALSTATEDIR/openldap-data .
-.TP
-.B
-index {<attrlist>|default} [pres,eq,approx,sub,<special>]
-Specify the indexes to maintain for the given attribute (or
-list of attributes).
-Some attributes only support a subset of indexes.
-If only an <attr> is given, the indices specified for \fBdefault\fR
-are maintained.
-Note that setting a default does not imply that all attributes will be
-indexed. Also, for best performance, an
-.B eq
-index should always be configured for the
-.B objectClass
-attribute.
+LDBM was the original database backend to
+.BR slapd (8),
+and was supported up to OpenLDAP 2.3.
+It has been superseded by the more robust BDB and HDB backends.
-A number of special index parameters may be specified.
-The index type
-.B sub
-can be decomposed into
-.BR subinitial ,
-.BR subany ,\ and
-.B subfinal
-indices.
-The special type
-.B notags
-(or
-.BR nolang )
-may be specified to disallow use of this index by subtypes with tagging
-options (such as language options).
-The special type
-.B nosubtypes
-may be specified to disallow use of this index by named subtypes.
-Note: changing index settings requires rebuilding indices, see
-.BR slapindex (8).
-.TP
-.B mode <integer>
-Specify the file protection mode that newly created database
-index files should have.
-The default is 0600.
-.SH ACCESS CONTROL
-The
-.B ldbm
-backend honors access control semantics as indicated in
-.BR slapd.access (5).
-.SH FILES
-.TP
-ETCDIR/slapd.conf
-default slapd configuration file
.SH SEE ALSO
-.BR slapd.conf (5),
.BR slapd (8),
-.BR slapadd (8),
-.BR slapcat (8),
-.BR slapindex (8).
+.BR slapd-bdb (5),
+.BR slapd.backends (5).
.SH ACKNOWLEDGEMENTS
.so ../Project
.\" and maybe manual pages for librewrite.
.\"
.SH NAME
-slapd-meta \- metadirectory backend
+slapd-meta \- metadirectory backend to slapd
.SH SYNOPSIS
ETCDIR/slapd.conf
.SH DESCRIPTION
is set to
.IR yes .
+.TP
+.B session\-tracking\-request {NO|yes}
+Adds session tracking control for all requests.
+The client's IP and hostname, and the identity associated to each request,
+if known, are sent to the remote server for informational purposes.
+This directive is incompatible with setting \fIprotocol\-version\fP to 2.
+If set before any target specification, it affects all targets, unless
+overridden by any per-target directive.
+
.TP
.B single\-conn {NO|yes}
Discards current cached connection when the client rebinds.
.LP
.RS
.nf
-access to dn="<dn>" attr=<attr>
+access to dn="<dn>" attrs=<attr>
by dnattr=<dnattr> read
by * none
.fi
.\" Copying restrictions apply. See COPYRIGHT/LICENSE.
.\" $OpenLDAP$
.SH NAME
-.B slapd-monitor
-\- Monitor backend to slapd
+slapd-monitor \- Monitor backend to slapd
.SH SYNOPSIS
ETCDIR/slapd.conf
.SH DESCRIPTION
manual page.
.TP
.B bind <on/off>
-Allow binds as DNs in this backend's suffix.
+Allow binds as any DN in this backend's suffix, with any password.
The default is "off".
.SH EXAMPLE
Here is a possible slapd.conf extract using the Null backend:
instance into a virtual naming context, with attributeType
and objectClass manipulation, if required.
It requires the
-.B rwm
-.BR overlay .
+.BR slapo-rwm (5)
+overlay.
.LP
This backend and the above mentioned overlay are experimental.
.SH CONFIGURATION
.BR slapd.conf (5)
manual page; only the
.B suffix
-directive is required by the
+directive is allowed by the
.I relay
backend.
.TP
-.B relay <real naming context> [massage]
+.B relay <real naming context>
The naming context of the database that is presented
under a virtual naming context.
The presence of this directive implies that one specific database,
i.e. the one serving the
.BR "real naming context" ,
will be presented under a virtual naming context.
-This directive automatically instantiates the
-.IR "rwm overlay" .
-If the optional
-.B massage
-keyword is present, the suffix massaging is automatically
-configured as well; otherwise, specific massaging instructions
-are required by means of the
-.I rewrite
-directives described in
-.BR slapo-rwm (5).
+
+.SH MASSAGING
+The
+.B relay
+database does not automatically rewrite the naming context
+of requests and responses.
+For this purpose, the
+.BR slapo-rwm (5)
+overlay must be explicitly instantiated, and configured
+as appropriate.
+Usually, the
+.B rwm-suffixmassage
+directive suffices if only naming context rewriting is required.
.SH ACCESS RULES
One important issue is that access rules are based on the identity
Moreover, since
.B back-relay
bypasses the real database frontend operations by short-circuiting
-operations thru the internal backend API, the original database
+operations through the internal backend API, the original database
access rules do not apply but in selected cases, i.e. when the
backend itself applies access control.
As a consequence, the instances of the relay database must provide
databases based on details of the virtual naming context,
e.g. groups on one database and persons on another.
.LP
-.SH Caveats
-The
-.B rwm overlay
-is experimental.
-.LP
.SH EXAMPLES
To implement a plain virtual naming context mapping
that refers to a single database, use
.LP
.nf
- database relay
- suffix "dc=virtual,dc=naming,dc=context"
- relay "dc=real,dc=naming,dc=context" massage
+ database relay
+ suffix "dc=virtual,dc=naming,dc=context"
+ relay "dc=real,dc=naming,dc=context"
+ overlay rwm
+ rwm-suffixmassage "dc=real,dc=naming,dc=context"
.fi
.LP
To implement a plain virtual naming context mapping
that looks up the real naming context for each operation, use
.LP
.nf
- database relay
- suffix "dc=virtual,dc=naming,dc=context"
- overlay rwm
- suffixmassage "dc=real,dc=naming,dc=context"
+ database relay
+ suffix "dc=virtual,dc=naming,dc=context"
+ overlay rwm
+ rwm-suffixmassage "dc=real,dc=naming,dc=context"
.fi
.LP
This is useful, for instance, to relay different databases that
back from the real to the virtual naming context, use
.LP
.nf
- database relay
- suffix "dc=virtual,dc=naming,dc=context"
- relay "dc=real,dc=naming,dc=context"
- rewriteEngine on
- rewriteContext default
- rewriteRule "dc=virtual,dc=naming,dc=context"
- "dc=real,dc=naming,dc=context" ":@"
- rewriteContext searchFilter
- rewriteContext searchEntryDN
- rewriteContext searchAttrDN
- rewriteContext matchedDN
+ database relay
+ suffix "dc=virtual,dc=naming,dc=context"
+ relay "dc=real,dc=naming,dc=context"
+ overlay rwm
+ rwm-rewriteEngine on
+ rwm-rewriteContext default
+ rwm-rewriteRule "dc=virtual,dc=naming,dc=context"
+ "dc=real,dc=naming,dc=context" ":@"
+ rwm-rewriteContext searchFilter
+ rwm-rewriteContext searchEntryDN
+ rwm-rewriteContext searchAttrDN
+ rwm-rewriteContext matchedDN
.fi
.LP
-Note that the virtual database is bound to a single real database,
-so the
-.B rwm overlay
-is automatically instantiated, but the rewrite rules
-are written explicitly to map all the virtual to real
-naming context data flow, but none of the real to virtual.
+Note that the
+.BR slapo-rwm (5)
+overlay is instantiated, but the rewrite rules are written explicitly,
+rather than automatically as with the
+.B rwm-suffixmassage
+statement, to map all the virtual to real naming context data flow,
+but none of the real to virtual.
.LP
Access rules:
.LP
.nf
- database bdb
- suffix "dc=example,dc=com"
+ database bdb
+ suffix "dc=example,dc=com"
# skip...
access to dn.subtree="dc=example,dc=com"
by dn.exact="cn=Supervisor,dc=example,dc=com" write
by * read
- database relay
- suffix "o=Example,c=US"
- relay "dc=example,dc=com" massage
+ database relay
+ suffix "o=Example,c=US"
+ relay "dc=example,dc=com"
+ overlay rwm
+ rwm-suffixmassage "dc=example,dc=com"
# skip ...
access to dn.subtree="o=Example,c=US"
by dn.exact="cn=Supervisor,dc=example,dc=com" write
and \fBstrcast_func\fP in "HELPER CONFIGURATION" for details.
.TP
-.B use_subtree_shortcut { NO | yes }
+.B use_subtree_shortcut { YES | no }
Do not use the subtree condition when the searchBase is the database
suffix, and the scope is subtree; rather collect all entries.
(where underscores mean spaces, ASCII 0x20 char) corresponds
to its prettified counterpart "First_Last"; this is not currently
honored by back-sql if non-prettified data is written via RDBMS;
-when non-prettified data is written thru back-sql, the prettified
+when non-prettified data is written through back-sql, the prettified
values are actually used instead.
.LP
.BR slapd.conf (5)
file contains configuration information for the
.BR slapd (8)
-daemon. This configuration file is also used by the
-.BR slurpd (8)
-replication daemon and by the SLAPD tools
+daemon. This configuration file is also used by the SLAPD tools
.BR slapacl (8),
.BR slapadd (8),
.BR slapauth (8),
.B bdb
This is the recommended primary backend for a normal slapd database.
It takes care to configure it properly.
-It uses the transactional database interface of the Sleepycat Berkeley
+It uses the transactional database interface of the Oracle Berkeley
DB (BDB) package to store data.
.TP
.B config
.B ETCDIR/slapd.conf
contains configuration information for the
.BR slapd (8)
-daemon. This configuration file is also used by the
-.BR slurpd (8)
-replication daemon and by the SLAPD tools
+daemon. This configuration file is also used by the SLAPD tools
.BR slapacl (8),
.BR slapadd (8),
.BR slapauth (8),
lookup. The default is 2. For example, with the default values, a search
using this filter "cn=*abcdefgh*" would generate index lookups for
"abcd", "cdef", and "efgh".
-
-.\"-- NEW_LOGGING option --
-.\".TP
-.\".B logfile <filename>
-.\"Specify a file for recording debug log messages. By default these messages
-.\"only go to stderr and are not recorded anywhere else. Specifying a logfile
-.\"copies messages to both stderr and the logfile.
.TP
.B localSSF <SSF>
Specifies the Security Strength Factor (SSF) to be given local LDAP sessions,
.B minssf
option description. The default is 71.
.TP
+.B logfile <filename>
+Specify a file for recording debug log messages. By default these messages
+only go to stderr and are not recorded anywhere else. Specifying a logfile
+copies messages to both stderr and the logfile.
+.TP
.B loglevel <integer> [...]
Specify the level at which debugging statements and operation
statistics should be syslogged (currently logged to the
They must be considered subsystems rather than increasingly verbose
log levels.
Some messages with higher priority are logged regardless
-of the configured loglevel as soon as some logging is configured,
-otherwise anything is logged at all.
+of the configured loglevel as soon as any logging is configured.
Log levels are additive, and available levels are:
.RS
.RS
.TP
.B 256
.B (0x100 stats)
-stats log connections/operations/results
+connections, LDAP operations, results (recommended)
.TP
.B 512
.B (0x200 stats2)
.BR none ,
or the equivalent integer representation, causes those messages
that are logged regardless of the configured loglevel to be logged.
-In fact, if no loglevel (or a 0 level) is defined, no logging occurs,
+In fact, if loglevel is set to 0, no logging occurs,
so at least the
.B none
level is required to have high priority messages logged.
+
+The loglevel defaults to \fBstats\fP.
+This level should usually also be included when using other loglevels, to
+help analyze the logs.
.RE
.TP
.B moduleload <filename>
cannot find a local database to handle a request.
If specified multiple times, each url is provided.
.TP
-.B replica-argsfile
-The ( absolute ) name of a file that will hold the
-.B slurpd
-server's command line options
-if started without the debugging command line option.
-If it appears after a
-.B replogfile
-directive, the args file is specific to the
-.BR slurpd (8)
-instance that handles that replication log.
-.TP
-.B replica-pidfile
-The ( absolute ) name of a file that will hold the
-.B slurpd
-server's process ID ( see
-.BR getpid (2)
-) if started without the debugging command line option.
-If it appears after a
-.B replogfile
-directive, the pid file is specific to the
-.BR slurpd (8)
-instance that handles that replication log.
-.TP
-.B replicationinterval
-The number of seconds
-.B slurpd
-waits before checking the replogfile for changes.
-If it appears after a
-.B replogfile
-directive, the replication interval is specific to the
-.BR slurpd (8)
-instance that handles that replication log.
-.TP
.B require <conditions>
Specify a set of conditions (separated by white space) to
require (default none).
Specify the name of an LDIF(5) file containing user defined attributes
for the root DSE. These attributes are returned in addition to the
attributes normally produced by slapd.
+
+The root DSE is an entry with information about the server and its
+capabilities, in operational attributes.
+It has the empty DN, and can be read with e.g.:
+.ti +4
+ldapsearch -x -b "" -s base "+"
+.br
+See RFC 4512 section 5.1 for details.
.TP
.B sasl-host <fqdn>
Used to specify the fully qualified domain name used for SASL processing.
e.g. ldapi:// (and eventually IPSEC). It is not normally used.
.TP
.B serverID <integer> [<URL>]
-Specify an integer ID from 0 to 4095 for this server. These IDs are
+Specify an integer ID from 0 to 4095 for this server (limited
+to 3 hexadecimal digits).
+These IDs are
required when using multimaster replication and each master must have a
unique ID. If the URL is provided, this directive may be specified
multiple times, providing a complete list of participating servers
To check what ciphers a given spec selects, use:
-openssl ciphers -v <cipher-suite-spec>
+.nf
+ openssl ciphers -v <cipher-suite-spec>
+.fi
+
+To obtain the list of ciphers in GNUtls use:
+
+.nf
+ gnutls-cli -l
+.fi
+
.TP
.B TLSCACertificateFile <filename>
Specifies the file that contains certificates for all of the Certificate
.B TLSCACertificatePath <path>
Specifies the path of a directory that contains Certificate Authority
certificates in separate individual files. Usually only one of this
-or the TLSCACertificateFile is used.
+or the TLSCACertificateFile is used. This directive is not supported
+when using GNUtls.
.TP
.B TLSCertificateFile <filename>
Specifies the file that contains the
Anonymous Diffie-Hellman key exchanges in certain non-default cipher suites.
You should append "!ADH" to your cipher suites if you have changed them
from the default, otherwise no certificate exchanges or verification will
-be done.
+be done. When using GNUtls these parameters are always generated randomly so
+this directive is ignored.
.TP
.B TLSRandFile <filename>
Specifies the file to obtain random bits from when /dev/[u]random
is not available. Generally set to the name of the EGD/PRNGD socket.
The environment variable RANDFILE can also be used to specify the filename.
+This directive is ignored with GNUtls.
.TP
.B TLSVerifyClient <level>
Specifies what checks to perform on client certificates in an
used to verify if the client certificates have not been revoked. This
requires
.B TLSCACertificatePath
-parameter to be set.
+parameter to be set. This directive is ignored with GNUtls.
.B <level>
can be specified as one of the following keywords:
.RS
.B all
Check the CRL for a whole certificate chain
.RE
+.TP
+.B TLSCRLFile <filename>
+Specifies a file containing a Certificate Revocation List to be used
+for verifying that certificates have not been revoked. This directive is
+only valid when using GNUtls.
.SH GENERAL BACKEND OPTIONS
Options in this section only apply to the configuration file section
for the specified backend. They are supported by every
.BR dnssrv ,
.BR hdb ,
.BR ldap ,
-.BR ldbm ,
.BR ldif ,
.BR meta ,
.BR monitor ,
.BR dnssrv ,
.BR hdb ,
.BR ldap ,
-.BR ldbm ,
.BR ldif ,
.BR meta ,
.BR monitor ,
.BR sql ,
depending on which backend will serve the database.
.TP
+.B hidden on | off
+Controls whether the database will be used to answer
+queries. A database that is hidden will never be
+selected to answer any queries, and any suffix configured
+on the database will be ignored in checks for conflicts
+with other databases. By default, hidden is off.
+.TP
.B lastmod on | off
Controls whether
.B slapd
.B mirrormode on | off
This option puts a replica database into "mirror" mode. Update
operations will be accepted from any user, not just the updatedn. The
-database must already be configured as a slurpd or syncrepl consumer
-before this keyword may be set. This mode must be used with extreme
-care, as it does not offer any consistency guarantees. This feature
-is intended to be used with an external frontend that guarantees that
-writes are only directed to a single master, switching to an alternate
-server only if the original master goes down.
+database must already be configured as a syncrepl consumer
+before this keyword may be set. This mode also requires a
+.B serverID
+(see above) to be configured.
By default, mirrormode is off.
.TP
.B overlay <overlay-name>
will receive control last of all. See the
.BR slapd.overlays (5)
manual page for an overview of the available overlays.
+Note that all of the database's
+regular settings should be configured before any overlay settings.
.TP
.B readonly on | off
This option puts the database into "read-only" mode. Any attempts to
are (are not) replicated.
.RE
.TP
-.B replogfile <filename>
-Specify the name of the replication log file to log changes to.
-The replication log is typically written by
-.BR slapd (8)
-and read by
-.BR slurpd (8).
-See
-.BR slapd.replog (5)
-for more information. The specified file should be located
-in a directory with limited read/write/execute access as the replication
-logs may contain sensitive information.
-.TP
.B restrict <oplist>
Specify a whitespace separated list of operations that are restricted.
If defined inside a database specification, restrictions apply only
identifies the current
.B syncrepl
directive within the replication consumer site.
-It is a non-negative integer having no more than three digits.
+It is a non-negative integer not greater than 4095 (limited
+to three hexadecimal digits).
.B provider
specifies the replication provider site containing the master content
.B credentials
and should only be used when adequate security services
(e.g. TLS or IPSEC) are in place.
+.B REMEMBER: simple bind credentials must be in cleartext!
A
.B bindmethod
of
.TP
.B updatedn <dn>
This option is only applicable in a slave
-database updated using
-.BR slurpd(8).
+database.
It specifies the DN permitted to update (subject to access controls)
-the replica (typically, this is the DN
-.BR slurpd (8)
-binds to update the replica). Generally, this DN
+the replica. It is only needed in certain push-mode
+replication scenarios. Generally, this DN
.I should not
be the same as the
.B rootdn
.BR slapdn (8),
.BR slapindex (8),
.BR slappasswd (8),
-.BR slaptest (8),
-.BR slurpd (8).
+.BR slaptest (8).
.LP
"OpenLDAP Administrator's Guide" (http://www.OpenLDAP.org/doc/admin/)
.SH ACKNOWLEDGEMENTS
have been returned, either when configured by the server or when
requested by the client.
.TP
+.B constraint
+Constraint.
+This overlay enforces a regular expression constraint on all values
+of specified attributes. It is used to enforce a more rigorous
+syntax when the underlying attribute syntax is too general.
+.TP
+.B dds
+Dynamic Directory Services.
+This overlay supports dynamic objects, which have a limited life after
+which they expire and are automatically deleted.
+.TP
.B dyngroup
Dynamic Group.
This is a demo overlay which extends the Compare operation to detect
This overlay can be used with a backend database such as
.BR slapd-bdb (5)
to enforce the uniqueness of some or all attributes within a subtree.
+.TP
+.B valsort
+Value Sorting.
+This overlay can be used to enforce a specific order for the values
+of an attribute when it is returned in a search.
.SH FILES
.TP
ETCDIR/slapd.conf
.BR slapo\-accesslog (5),
.BR slapo\-auditlog (5),
.BR slapo\-chain (5),
+.BR slapo\-constraint (5),
+.BR slapo\-dds (5),
+.BR slapo\-dyngroup (5),
.BR slapo\-dynlist (5),
.BR slapo\-pcache (5),
.BR slapo\-ppolicy (5),
.BR slapo\-syncprov (5),
.BR slapo\-translucent (5),
.BR slapo\-unique (5).
+.BR slapo\-valsort (5).
.BR slapd\-config (5),
.BR slapd.conf (5),
.BR slapd.backends (5),
.BR slapd.conf (5)
file contains configuration information for the
.BR slapd (8)
-daemon. This configuration file is also used by the
-.BR slurpd (8)
-replication daemon and by the SLAPD tools
+daemon. This configuration file is also used by the SLAPD tools
.BR slapadd (8),
.BR slapcat (8),
and
+++ /dev/null
-.TH SLAPD.REPLOG 5 "RELEASEDATE" "OpenLDAP LDVERSION"
-.\" $OpenLDAP$
-.\" Copyright 1998-2007 The OpenLDAP Foundation All Rights Reserved.
-.\" Copying restrictions apply. See COPYRIGHT/LICENSE.
-.SH NAME
-slapd.replog \- slapd replication log format
-.SH SYNOPSIS
-slapd.replog
-slapd.replog.lock
-.SH DESCRIPTION
-.LP
-The file slapd.replog is produced by the stand-alone LDAP daemon,
-.BR slapd (8),
-when changes are made to its local database that are to be
-propagated to one or more replica
-.IR slapd s.
-The file consists of
-zero or more records, each one corresponding to a change, addition,
-or deletion from the
-.I slapd
-database. The file is meant to be read
-and processed by
-.BR slurpd (8),
-the stand-alone LDAP update replication daemon. The records are
-separated by a blank line. Each record has the following format.
-.LP
-The record begins with one or more lines indicating the replicas
-to which the change is to be propagated:
-.LP
-.nf
- replica: <hostname[:portnumber]>
-.fi
-.LP
-Next, the time the change took place given, as the number of seconds since
-00:00:00 GMT, Jan. 1, 1970, with an optional decimal extension, in order
-to make times unique. Note that slapd does not make times unique, but
-slurpd makes all times unique in its copies of the replog files.
-.LP
-.nf
- time: <integer[.integer]>
-.fi
-.LP
-Next, the distinguished name of the entry being changed is given:
-.LP
-.nf
- dn: <distinguishedname>
-.fi
-.LP
-Next, the type of change being made is given:
-.LP
-.nf
- changetype: <[modify|add|delete|modrdn]>
-.fi
-.LP
-Finally, the change information itself is given, the format of which
-depends on what kind of change was specified above. For a \fIchangetype\fP
-of \fImodify\fP, the format is one or more of the following:
-.LP
-.nf
- add: <attributetype>
- <attributetype>: <value1>
- <attributetype>: <value2>
- ...
- -
-.fi
-.LP
-Or, for a replace modification:
-.LP
-.nf
- replace: <attributetype>
- <attributetype>: <value1>
- <attributetype>: <value2>
- ...
- -
-.fi
-.LP
-Or, for a delete modification:
-.LP
-.nf
- delete: <attributetype>
- <attributetype>: <value1>
- <attributetype>: <value2>
- ...
- -
-.fi
-.LP
-If no \fIattributetype\fP lines are given, the entire attribute is to be
-deleted.
-.LP
-For a \fIchangetype\fP of \fIadd\fP, the format is:
-.LP
-.nf
- <attributetype1>: <value1>
- <attributetype1>: <value2>
- ...
- <attributetypeN>: <value1>
- <attributetypeN>: <value2>
-.fi
-.LP
-For a \fIchangetype\fP of \fImodrdn\fP, the format is:
-.LP
-.nf
- newrdn: <newrdn>
- deleteoldrdn: 0 | 1
-.fi
-.LP
-where a value of 1 for deleteoldrdn means to delete the values
-forming the old rdn from the entry, and a value of 0 means to
-leave the values as non-distinguished attributes in the entry.
-.LP
-For a \fIchangetype\fP of \fIdelete\fP, no additional information
-is needed in the record.
-.LP
-The format of the values is the LDAP Directory Interchange Format
-described in
-.BR ldif (5).
-.LP
-Access to the \fIslapd.replog\fP file is synchronized through the
-use of
-.BR flock (3)
-on the file \fIslapd.replog.lock\fP. Any process
-reading or writing this file should obey this locking convention.
-.SH EXAMPLE
-The following sample \fIslapd.replog\fP file contains information
-on one of each type of change.
-.LP
-.nf
- replica: truelies.rs.itd.umich.edu
- replica: judgmentday.rs.itd.umich.edu
- time: 797612941
- dn: cn=Babs Jensen,dc=example,dc=com
- changetype: add
- objectclass: person
- cn: babs
- cn: babs jensen
- sn: jensen
-
- replica: truelies.rs.itd.umich.edu
- replica: judgmentday.rs.itd.umich.edu
- time: 797612973
- dn: cn=Babs Jensen,dc=example,dc=com
- changetype: modify
- add: description
- description: the fabulous babs
-
- replica: truelies.rs.itd.umich.edu
- replica: judgmentday.rs.itd.umich.edu
- time: 797613020
- dn: cn=Babs Jensen,dc=example,dc=com
- changetype: modrdn
- newrdn: cn=Barbara J Jensen
- deleteoldrdn: 0
-.fi
-.SH FILES
-.TP
-slapd.replog
-slapd replication log file
-.TP
-slapd.replog.lock
-lockfile for slapd.replog
-.SH SEE ALSO
-.BR ldap (3),
-.BR ldif (5),
-.BR slapd (8),
-.BR slurpd (8)
-.SH ACKNOWLEDGEMENTS
-.so ../Project
.\" Copying restrictions apply. See COPYRIGHT/LICENSE.
.\" $OpenLDAP$
.SH NAME
-slapo-accesslog \- Access Logging overlay
+slapo-accesslog \- Access Logging overlay to slapd
.SH SYNOPSIS
ETCDIR/slapd.conf
.SH DESCRIPTION
.\" Copying restrictions apply. See COPYRIGHT/LICENSE.
.\" $OpenLDAP$
.SH NAME
-slapo-auditlog \- Audit Logging overlay
+slapo-auditlog \- Audit Logging overlay to slapd
.SH SYNOPSIS
ETCDIR/slapd.conf
.SH DESCRIPTION
.\" Copying restrictions apply. See the COPYRIGHT file.
.\" $OpenLDAP$
.SH NAME
-slapo-chain \- chain overlay
+slapo-chain \- chain overlay to slapd
.SH SYNOPSIS
ETCDIR/slapd.conf
.SH DESCRIPTION
--- /dev/null
+.TH SLAPO-CONSTRAINT 5 "RELEASEDATE" "OpenLDAP LDVERSION"
+.\" Copyright 2005-2006 Hewlett-Packard Company
+.\" Copying restrictions apply. See COPYRIGHT/LICENSE.
+.SH NAME
+slapo-constraint \- Attribute Constraint Overlay to slapd
+.SH SYNOPSIS
+ETCDIR/slapd.conf
+.SH DESCRIPTION
+The constraint overlay is used to enforce a regular expression
+constraint on all values of specified attributes. Attributes can
+have multiple constraints placed upon them, and all must be satisfied
+when modifying an attribute value under constraint.
+.LP
+This overlay is intended to be used to force syntactic regularity upon
+certain string represented data which have well known canonical forms,
+like telephone numbers, post codes, FQDNs, etc.
+.SH CONFIGURATION
+This
+.B slapd.conf
+option applies to the constraint overlay.
+It should appear after the
+.B overlay
+directive.
+.TP
+.B constraint_attribute <attribute_name> <type> <value>
+Specifies the constraint which should apply to the attribute named as
+the first parameter.
+At the moment only one type of constraint is supported -
+.B
+regex.
+The parameter following the
+.B
+regex
+type is a Unix style regular expression (See
+.B
+regex(7))
+
+Any attempt to add or modify an attribute named as part of the
+constraint overlay specification which does not fit the regular
+expression constraint listed will fail with a
+LDAP_CONSTRAINT_VIOLATION error.
+.SH EXAMPLES
+.B
+constraint_attribute mail regex ^[:alnum:]+@mydomain.com$
+
+A specification like the above would reject any
+.B
+mail
+attribute which did not look like
+.B
+<alpha-numeric string>@mydomain.com
+.SH FILES
+.TP
+ETCDIR/slapd.conf
+default slapd configuration file
+.SH SEE ALSO
+.BR slapd.conf (5).
.\" Copying restrictions apply. See the COPYRIGHT file.
.\" $OpenLDAP$
.SH NAME
-slapo-dds \- dds overlay
+slapo-dds \- Dynamic Directory Services overlay to slapd
.SH SYNOPSIS
ETCDIR/slapd.conf
.SH DESCRIPTION
The name
.B dds
stands for
-Dynamic Dyrectory Services.
+Dynamic Directory Services.
It allows to define dynamic objects, characterized by the
.B dynamicObject
objectClass.
-Dynamic objects have a limited life, determined by a time-to-live (TTL)
-that can be refreshed by means of a specific
+
+Dynamic objects have a limited lifetime, determined by a time-to-live
+(TTL) that can be refreshed by means of a specific
.B refresh
extended operation.
This operation allows to set the Client Refresh Period (CRP),
dynamic object from expiration.
The expiration time is computed by adding the requested TTL to the
current time.
-When dynamic objects reach the end of their life without being
-further refreshed, they are automatically deleted; there is no guarantee
-of immediate deletion, but clients should not count over it.
-Dynamic objects can have subordinates, provided they also are dynamic
+When dynamic objects reach the end of their lifetime without being
+further refreshed, they are automatically deleted.
+There is no guarantee of immediate deletion, so clients should not count
+on it.
+
+Dynamic objects can have subordinates, provided these also are dynamic
objects.
-RFC 2589 does not specify what should the behavior of a dynamic
-directory service be when a dynamic object with (dynamic) subordinates
+RFC 2589 does not specify what the behavior of a dynamic directory
+service should be when a dynamic object with (dynamic) subordinates
expires.
-In this implementation, the life of dynamic objects with subordinates
-is prolonged until all the dynamic subordinates expired.
+In this implementation, the lifetime of dynamic objects with subordinates
+is prolonged until all the dynamic subordinates expire.
This
operations.
Since its use may result in many internal entry lookups, adds
and deletes, it should be best used in conjunction with backends
-that have resonably good write performances.
+that have reasonably good write performances.
.LP
The config directives that are specific to the
.TP
.B dds\-max\-ttl <ttl>
-Specifies the max TTL value; this is the default TTL newly created
+Specifies the max TTL value.
+This is also the default TTL newly created
dynamic objects receive, unless
.B dds\-default\-ttl
is set.
-When the client with a refresh exop requests a TTL higher than it,
-sizeLimitExceeded is returned.
+When the client with a refresh extended operation requests a TTL higher
+than it, sizeLimitExceeded is returned.
This value must be between 86400 (1 day, the default) and 31557600
(1 year plus 6 hours, as per RFC 2589).
.TP
.B dds\-min\-ttl <ttl>
Specifies the min TTL value; clients requesting a lower TTL by means
-of the refresh exop actually obtain this value as CRP.
+of the refresh extended operation actually obtain this value as CRP.
If set to 0 (the default), no lower limit is set.
.TP
.B dds\-tolerance <ttl>
Specifies an extra time that is added to the timer that actually wakes up
the thread that will delete an expired dynamic object.
-So the nominal life of the entry is that specified in the
+So the nominal lifetime of the entry is that specified in the
.B entryTtl
-attribute, but its life will actually be
-.BR " entryTtl + tolerance " .
-Note that there is no guarantee that the life of a dynamic object will be
+attribute, but its lifetime will actually be
+.BR "entryTtl + tolerance" .
+Note that there is no guarantee that the lifetime of a dynamic object
+will be
.I exactly
the requested TTL; due to implementation details, it may be longer, which
is allowed by RFC 2589.
.B dds\-max\-dynamicObjects <num>
Specifies the maximum number of dynamic objects that can simultaneously exist
within a naming context.
-This allows to limit the amount of resources (mostly in terms of runqueue size)
-that are used by dynamic objects.
+This allows to limit the amount of resources (mostly in terms of
+run-queue size) that are used by dynamic objects.
By default, no limit is set.
.TP
to it is possible.
So the
.B dds
-overlay turns refresh exops into an internal modification to the value
-of the
+overlay turns refresh extended operation into an internal modification to
+the value of the
.B entryTtl
attribute with the
.B manageDIT
RFC 2589 recommends that anonymous clients should not be allowed to refresh
a dynamic object.
-This cn be implemented by appropriately crafting access control to obtain
+This can be implemented by appropriately crafting access control to obtain
the desired effect.
Example: restrict refresh to authenticated clients
object expiration, while replicas simply see the dynamic object as a plain
object.
-When using slurpd replication, one needs to explicitly exclude the
+When replicating these objects, one needs to explicitly exclude the
.B dynamicObject
class and the
.B entryTtl
.BR entryExpireTimestamp ,
that contains the expiration timestamp. This must be excluded from
replication as well.
-In
-.BR slapd.conf (5),
-add the following \fIexclusion list\fP to each
-.B replica
-statement:
-
-.RS
-.nf
-replica ...
- attrs!=@dynamicObject,entryTtl,entryExpireTimestamp
-.fi
-.RE
-When using syncrepl, the quick and dirty solution is to set
+The quick and dirty solution is to set
.B schemacheck=off
+in the syncrepl configuration
and, optionally, exclude the operational attributes from replication, using
.RS
--- /dev/null
+.TH SLAPO-DYNGROUP 5 "RELEASEDATE" "OpenLDAP LDVERSION"
+.\" Copyright 2005-2007 The OpenLDAP Foundation All Rights Reserved.
+.\" Copying restrictions apply. See COPYRIGHT/LICENSE.
+.\" $OpenLDAP$
+.SH NAME
+slapo-dyngroup \- Dynamic Group overlay to slapd
+.SH SYNOPSIS
+ETCDIR/slapd.conf
+.SH DESCRIPTION
+The Dynamic Group overlay allows clients to use LDAP Compare operations
+to test the membership of a dynamic group the same way they would check
+against a static group. Compare operations targeting a group's static
+member attribute will be intercepted and tested against the configured
+dynamic group's URL attribute.
+.LP
+Note that this intercept only happens if the actual
+Compare operation does not return a LDAP_COMPARE_TRUE result. So if a
+group has both static and dynamic members, the static member list will
+be checked first.
+.SH CONFIGURATION
+This
+.B slapd.conf
+option applies to the Dynamic Group overlay.
+It should appear after the
+.B overlay
+directive.
+.TP
+.B attrpair <memberAttr> <URLattr>
+Specify the attributes to be compared. A compare operation on the
+.I memberAttr
+will cause the
+.I URLattr
+to be evaluated for the result.
+.SH EXAMPLES
+.nf
+ database bdb
+ ...
+ overlay dyngroup
+ attrpair member memberURL
+.fi
+.SH FILES
+.TP
+ETCDIR/slapd.conf
+default slapd configuration file
+.SH SEE ALSO
+.BR slapd.conf (5).
+.SH AUTHOR
+Howard Chu
.\" Copying restrictions apply. See the COPYRIGHT file.
.\" $OpenLDAP$
.SH NAME
-slapo-dynlist \- Dynamic List overlay
+slapo-dynlist \- Dynamic List overlay to slapd
.SH SYNOPSIS
ETCDIR/slapd.conf
.SH DESCRIPTION
.LP
This
.B slapd.conf
-configuration option is define for the dynlist overlay. It may have multiple
+configuration option is defined for the dynlist overlay. It may have multiple
occurrences, and it must appear after the
.B overlay
directive.
The value
.B <URL-ad>
-is the name of the attributeDescription that cointains the URI that is
+is the name of the attributeDescription that contains the URI that is
expanded by the overlay; if none is present, no expansion occurs.
If the intersection of the attributes requested by the search operation
(or the asserted attribute for compares) and the attributes listed
with well-defined patterns, one should consider adding a proxycache
later on in the overlay stack.
+.SH AUTHORIZATION
+By default the expansions are performed using the identity of the current
+LDAP user. This identity may be overridden by setting the
+.B dgIdentity
+attribute to the DN of another LDAP user. In that case the dgIdentity
+will be used when expanding the URIs in the object. Setting the dgIdentity
+to a zero-length string will cause the expansions to be performed
+anonymously. Note that the dgIdentity attribute is defined in the
+.B dyngroup
+schema, and this schema must be loaded before the dgIdentity
+authorization feature may be used.
+
.SH EXAMPLE
This example collects all the email addresses of a database into a single
entry; first of all, make sure that slapd.conf contains the directives:
.fi
.LP
+A dynamic group with dgIdentity authorization could be created with an
+entry like
+.LP
+.nf
+ dn: cn=Dynamic Group,ou=Groups,dc=example,dc=com
+ objectClass: groupOfURLs
+ objectClass: dgIdentityAux
+ cn: Dynamic Group
+ memberURL: ldap:///ou=People,dc=example,dc=com??sub?(objectClass=person)
+ dgIdentity: cn=Group Proxy,ou=Services,dc=example,dc=com
+.fi
+
.SH FILES
.TP
ETCDIR/slapd.conf
--- /dev/null
+.TH SLAPO-MEMBEROF 5 "RELEASEDATE" "OpenLDAP LDVERSION"
+.\" Copyright 1998-2007 The OpenLDAP Foundation, All Rights Reserved.
+.\" Copying restrictions apply. See the COPYRIGHT file.
+.\" $OpenLDAP$
+.SH NAME
+slapo-memberof \- Reverse Group Membership overlay to slapd
+.SH SYNOPSIS
+ETCDIR/slapd.conf
+.SH DESCRIPTION
+The
+.B memberof
+overlay to
+.BR slapd (8)
+allows automatic reverse group membership maintenance.
+Any time a group entry is modified, its members are modified as appropriate
+in order to keep a DN-valued "is member of" attribute updated with the DN
+of the group.
+
+.SH CONFIGURATION
+The config directives that are specific to the
+.B memberof
+overlay must be prefixed by
+.BR memberof\- ,
+to avoid potential conflicts with directives specific to the underlying
+database or to other stacked overlays.
+
+.TP
+.B overlay memberof
+This directive adds the memberof overlay to the current database; see
+.BR slapd.conf (5)
+for details.
+
+.LP
+The following
+.B slapd.conf
+configuration options are defined for the memberofoverlay.
+
+.TP
+.B memberof-group-oc <group-oc>
+The value
+.B <group-oc>
+is the name of the objectClass that triggers the reverse group membership
+update.
+It defaults to \fIgroupOfNames\fP.
+
+.TP
+.B memberof-member-ad <member-ad>
+The value
+.B <member-ad>
+is the name of the attribute that contains the names of the members
+in the group objects; it must be DN-valued.
+It defaults to \fImember\fP.
+
+.TP
+.B memberof-memberof-ad <memberof-ad>
+The value
+.B <memberof-ad>
+is the name of the attribute that contains the names of the groups
+an entry is member of; it must be DN-valued. Its contents are
+automatically updated by the overlay.
+It defaults to \fImemberOf\fP.
+
+.TP
+.B memberof-dn <dn>
+The value
+.B <dn>
+contains the DN that is used as \fImodifiersName\fP for internal
+modifications performed to update the reverse group membership.
+It defaults to the \fIrootdn\fP of the underlying database.
+
+.TP
+.B memberof-dangling {ignore, drop, error}
+This option determines the behavior of the overlay when, during
+a modification, it encounters dangling references.
+The default is
+.BR ignore ,
+which may leave dangling references.
+Other options are
+.BR drop ,
+which discards those modifications that would result in dangling
+references, and
+.BR error ,
+which causes modifications that would result in dangling references
+to fail.
+
+.TP
+.B memberof-refint {true|FALSE}
+This option determines whether the overlay will try to preserve
+referential integrity or not.
+If set to
+.BR TRUE ,
+when an entry containing values of the "is member of" attribute is modified,
+the corresponding groups are modified as well.
+
+.LP
+The memberof overlay may be used with any backend that provides full
+read-write functionality, but it is mainly intended for use
+with local storage backends.
+
+.SH FILES
+.TP
+ETCDIR/slapd.conf
+default slapd configuration file
+.SH SEE ALSO
+.BR slapd.conf (5),
+.BR slapd (8).
+The
+.BR slapo-memberof (5)
+overlay supports dynamic configuration via
+.BR back-config .
+.SH ACKNOWLEDGEMENTS
+.P
+This module was written in 2005 by Pierangelo Masarati for SysNet s.n.c.
+
.\" Copyright 2001, Pierangelo Masarati, All rights reserved. <ando@sys-net.it>
.\" $OpenLDAP$
.SH NAME
-slapo-pcache \- proxycache overlay
+slapo-pcache \- proxycache overlay to slapd
.SH SYNOPSIS
ETCDIR/slapd.conf
.SH DESCRIPTION
.RS
proxycache \fBbdb 10000 1 50 100\fP
.RE
+
.TP
.B proxycachequeries <queries>
Specify the maximum number of queries to cache. The default is 10000.
+.TP
+.B proxysavequeries { TRUE | FALSE }
+Specify whether the cached queries should be saved across restarts
+of the caching proxy, to provide hot startup of the cache. Only non-expired
+queries are reloaded. The default is FALSE.
+
+.BR CAVEAT :
+of course, the configuration of the proxycache must not change
+across restarts; the pcache overlay does not perform any consistency
+checks in this sense.
+In detail, this option should be disabled unless the existing
+.B proxyattrset
+and
+.B proxytemplate
+directives are not changed neither in order nor in contents.
+If new sets and templates are added, or if other details of the pcache
+overlay configuration changed, this feature should not be affected.
+
.TP
.B proxyattrset <index> <attrs...>
Used to associate a set of attributes <attrs..> with an <index>. Each attribute
set is associated with an integer from 0 to <numattrsets>-1. These indices are
used by the \fBproxytemplate\fP directive to define cacheable templates.
+A set of attributes cannot be empty. A set of attributes can contain the
+special attributes "*" (all user attributes), "+" (all operational attributes)
+or both; in the latter case, any other attribute is redundant and should
+be avoided for clarity. A set of attributes can contain "1.1" as the only
+attribute; in this case, only the presence of the entries is cached.
.TP
.B proxytemplate <template_string> <attrset_index> <ttl> [<negttl>]
.\" Copying restrictions apply. See COPYRIGHT/LICENSE.
.TH SLAPO_PPOLICY 5 "RELEASEDATE" "OpenLDAP LDVERSION"
.SH NAME
-slapo-ppolicy \- Password Policy overlay
+slapo-ppolicy \- Password Policy overlay to slapd
.SH SYNOPSIS
ETCDIR/slapd.conf
.SH DESCRIPTION
If the account has been locked, the password may no longer be used to
authenticate the user to the directory. If
.B pwdAccountLockedTime
-is set to zero (0), the user's account has been permanently locked
+is set to 000001010000Z, the user's account has been permanently locked
and may only be unlocked by an administrator.
.LP
.RS 4
.\" Copying restrictions apply. See COPYRIGHT/LICENSE.
.\" $OpenLDAP$
.SH NAME
-slapo-refint \- Referential Integrity overlay
+slapo-refint \- Referential Integrity overlay to slapd
.SH SYNOPSIS
ETCDIR/slapd.conf
.SH DESCRIPTION
.\" Copyright 2001, Pierangelo Masarati, All rights reserved. <ando@sys-net.it>
.\" $OpenLDAP$
.SH NAME
-slapo-retcode \- return code overlay
+slapo-retcode \- return code overlay to slapd
.SH SYNOPSIS
ETCDIR/slapd.conf
.SH DESCRIPTION
.\" and maybe manual pages for librewrite.
.\"
.SH NAME
-slapo-rwm \- rewrite/remap overlay
+slapo-rwm \- rewrite/remap overlay to slapd
.SH SYNOPSIS
ETCDIR/slapd.conf
.SH DESCRIPTION
Also, note that there are DN-related syntaxes (i.e. compound types with
a portion that is DN-valued), like nameAndOptionalUID,
whose values are currently not rewritten.
+.LP
+If the foreign type of an attribute mapping is not defined on the local
+server, it might be desirable to have the attribute values normalized after
+the mapping process. Not normalizing the values can lead to wrong results,
+when the
+.B rwm
+overlay is used together with e.g. the
+.B pcache
+overlay. This normalization can be enabled by means of the
+.B rwm-normalize-mapped-attrs
+directive.
+.TP
+.B rwm-normalize-mapped-attrs {yes|no}
+Set this to "yes", if the
+.B rwm
+overlay should try to normalize the values of attributes that are mapped from
+an attribute type that is unknown to the local server. The default value of
+this setting is "no".
.SH SUFFIX MASSAGING
A basic feature of the
.B rwm
and a real naming context by means of the
.B rwm-suffixmassage
directive.
+This, in conjunction with proxy backends,
+.BR slapd-ldap (5)
+and
+.BR slapd-meta (5),
+or with the relay backend,
+.BR slapd-relay (5),
+allows to create virtual views of databases.
+A distinguishing feature of this overlay is that, when instantiated
+before any database, it can modify the DN of requests
+.I before
+database selection.
+For this reason, rules that rewrite the empty DN ("")
+or the subschemaSubentry DN (usually "cn=subschema"),
+would prevent clients from reading the root DSE or the DSA's schema.
.TP
.B rwm-suffixmassage "[<virtual naming context>]" "<real naming context>"
Shortcut to implement naming context rewriting; the trailing part
.\" Copying restrictions apply. See COPYRIGHT/LICENSE.
.\" $OpenLDAP$
.SH NAME
-slapo-syncprov \- Sync Provider overlay
+slapo-syncprov \- Sync Provider overlay to slapd
.SH SYNOPSIS
ETCDIR/slapd.conf
.SH DESCRIPTION
configured to write the contextCSN into the underlying database to minimize
recovery time after an unclean shutdown.
-Note that due to deadlock constraints in the LDBM database, this overlay
-will only work in RefreshOnly mode, and cannot perform checkpoints, on LDBM.
-
On databases that support inequality indexing, it is helpful to set an
eq index on the entryCSN attribute when using this overlay.
.SH CONFIGURATION
.\" Copying restrictions apply. See COPYRIGHT/LICENSE.
.\" $OpenLDAP$
.SH NAME
-slapo-translucent \- Translucent Proxy overlay
+slapo-translucent \- Translucent Proxy overlay to slapd
.SH SYNOPSIS
ETCDIR/slapd.conf
.SH DESCRIPTION
.\" Copying restrictions apply. See COPYRIGHT/LICENSE.
.\" $OpenLDAP$
.SH NAME
-slapo-unique \- Attribute Uniqueness overlay
+slapo-unique \- Attribute Uniqueness overlay to slapd
.SH SYNOPSIS
ETCDIR/slapd.conf
.SH DESCRIPTION
The Attribute Uniqueness overlay can be used with a backend database such as
.BR slapd-bdb (5)
-to enforce the uniqueness of some or all attributes within a subtree. This
-subtree defaults to the base DN of the database for which the Uniqueness
-overlay is configured.
+to enforce the uniqueness of some or all attributes within a
+scope. This subtree defaults to all objects within the subtree of the
+database for which the Uniqueness overlay is configured.
.LP
Uniqueness is enforced by searching the subtree to ensure that the values of
all attributes presented with an
.B modify
or
.B modrdn
-operation are unique within the subtree.
+operation are unique within the scope.
For example, if uniqueness were enforced for the
.B uid
attribute, the subtree would be searched for any other records which also
.B overlay
directive.
.TP
-.B unique_base <basedn>
-Configure the subtree against which uniqueness searches will be invoked.
+.B unique_uri <[strict ][ignore ]URI[URI...]...>
+Configure the base, attributes, scope, and filter for uniqueness
+checking. Multiple URIs may be specified within a domain, allowing complex selections of objects. Multiple
+.B unique_uri
+statements or
+.B olcUniqueURI
+attributes will create independent domains, each with their own independent lists of URIs and ignore/strict settings.
+
+The LDAP URI syntax is a subset of
+.B RFC-4516,
+and takes the form:
+
+ldap:///[base dn]?[attributes...]?scope[?filter]
+
The
-.B basedn
-defaults to the base DN of the database for which uniqueness is configured.
-.TP
-.B unique_ignore <attribute...>
-Configure one or more attributes for which uniqueness will not be enforced.
-If not configured, all non-operational (eg, system) attributes must be
+.B base dn
+defaults to that of the back-end database. Specified base dns must be within the subtree of the back-end database.
+
+If no
+.B attributes
+are specified, the URI applies to all non-operational attributes.
+
+The
+.B scope
+component is effectively mandatory, because LDAP URIs default to
+.B base
+scope, which is not valid for uniqueness, because groups of one object
+are always unique. Scopes of
+.B sub
+(for subtree) and
+.B one
+for one-level are valid.
+
+The
+.B filter
+component causes the domain to apply uniqueness constraints only to
+matching objects. e.g.
+.B ldap:///?cn?sub?(sn=e*)
+would require unique
+.B cn
+attributes for all objects in the subtree of the back-end database whose
+.B sn
+starts with an e.
+
+It is possible to assert uniqueness upon all non-operational
+attributes except those listed by prepending the keyword
+.B ignore
+If not configured, all non-operational (e.g., system) attributes must be
unique. Note that the
-.B unique_ignore
-list should generally contain the
+.B attributes
+list of an
+.B ignore
+URI should generally contain the
.BR objectClass ,
.BR dc ,
.B ou
.B o
attributes, as these will generally not be unique, nor are they operational
attributes.
+
+It is possible to set strict checking for the uniqueness domain by
+prepending the keyword
+.B strict.
+By default, uniqueness is not enforced
+for null values. Enabling
+.B strict
+mode extends the concept of uniqueness to include null values, such
+that only one attribute within a subtree will be allowed to have a
+null value. Strictness applies to all URIs within a uniqueness
+domain, but some domains may be strict while others are not.
+.LP
+It is not possible to set both URIs and legacy slapo-unique configuration parameters simultaneously. In general, the legacy configuration options control pieces of a single unfiltered subtree domain.
+.TP
+.B unique_base <basedn>
+This legacy configuration parameter should be converted to the
+.B base dn
+component of the above
+.B unique_uri
+style of parameter.
+.TP
+.B unique_ignore <attribute...>
+This legacy configuration parameter should be converted to a
+.B unique_uri
+parameter with
+.B ignore
+keyword as described above.
.TP
.B unique_attributes <attribute...>
-Specify one or more attributes for which uniqueness will be enforced.
-If not specified, all attributes which are not operational (eg, system
-attributes such as
-.B entryUUID )
-or specified via the
-.B unique_ignore
-directive above must be unique within the subtree.
+This legacy configuration parameter should be converted to a
+.B unique_uri
+parameter, as described above.
.TP
.B unique_strict
-By default, uniqueness is not enforced for null values. Enabling
-.B unique_strict
-mode extends the concept of uniqueness to include null values, such that
-only one attribute within a subtree will be allowed to have a null value.
+This legacy configuration parameter should be converted to a
+.B strict
+keyword prepended to a
+.B unique_uri
+parameter, as described above.
.SH CAVEATS
.LP
-The search key is generated with attributes that are non-operational, not
-on the
-.B unique_ignore
-list, and included in the
-.B unique_attributes
-list, in that order. This makes it possible to create interesting and
-unusable configurations. Usually only one of
-.B unique_ignore
-or
-.B unique_attributes
-should be configured; use
-.B unique_ignore
-if the majority of attributes should be unique, and use
-.B unique_attributes
-if only a small set of attributes should be unique.
+.B unique_uri
+cannot be used with the old-style of configuration, and vice versa.
+.B unique_uri
+can implement everything the older system can do, however.
.LP
Typical attributes for the
-.B unique_ignore
-directive are intentionally not hardcoded into the overlay to allow for
+.B ignore ldap:///...
+URIs are intentionally not hardcoded into the overlay to allow for
maximum flexibility in meeting site-specific requirements.
.SH FILES
.TP
.\" Copying restrictions apply. See COPYRIGHT/LICENSE.
.\" $OpenLDAP$
.SH NAME
-slapo-valsort \- Value Sorting overlay
+slapo-valsort \- Value Sorting overlay to slapd
.SH SYNOPSIS
ETCDIR/slapd.conf
.SH DESCRIPTION
.B SBINDIR/slapadd
.B [\-b suffix]
.B [\-c]
-.B [\-g]
.B [\-d level]
.B [\-f slapd.conf]
.B [\-F confdir]
+.B [\-g]
.B [\-j lineno]
.B [\-l ldif-file]
.B [\-n dbnum]
.B [\-o name[=value]
.B [\-q]
+.B [\-s]
+.B [\-S SID]
.B [\-u]
.B [\-v]
.B [\-w]
partial replica. Loading normal objects which do not conform to
schema may result in unexpected and ill behavior.
.TP
+.B \-S " SID"
+Server ID to use in generated entryCSN. Also used for contextCSN
+if `\-w' is set as well. Defaults to 0.
+.TP
.B \-u
enable dry-run (don't write to backend) mode.
.TP
.\" Copyright 2004-2007 The OpenLDAP Foundation All Rights Reserved.
.\" Copying restrictions apply. See COPYRIGHT/LICENSE.
.SH NAME
-slapauth \- Check a list of string-represented IDs for authc/authz.
+slapauth \- Check a list of string-represented IDs for LDAP authc/authz
.SH SYNOPSIS
.B SBINDIR/slapauth
.B [\-d level]
.B \-v
Enable verbose mode.
.SH LIMITATIONS
-In general, your
+For some backend types, your
.BR slapd (8)
should not be running (at least, not in read-write
-mode) when you do this to ensure consistency of the database.
+mode) when you do this to ensure consistency of the database. It is
+always safe to run
+.B slapcat
+with the
+.BR slapd-bdb (5),
+.BR slapd-hdb (5),
+and
+.BR slapd-null (5)
+backends.
.SH EXAMPLES
To make a text backup of your SLAPD database and put it in a file called
.BR ldif ,
.B slapd
will not fork and disassociate from the invoking tty.
.LP
-.B Slapd
-can be configured to provide replicated service for a database with
-the help of
-.BR slurpd ,
-the standalone LDAP update replication daemon.
-See
-.BR slurpd (8)
-for details.
-.LP
See the "OpenLDAP Administrator's Guide" for more details on
.BR slapd .
.SH OPTIONS
that have the values given above.
This allows to specifically query the SLP DAs for LDAP servers holding the
.I production
-tree in case multiple trees are availabe.
+tree in case multiple trees are available.
.RE
.SH EXAMPLES
To start
.BR slapdn (8),
.BR slapindex (8),
.BR slappasswd (8),
-.BR slaptest (8),
-.BR slurpd (8)
+.BR slaptest (8).
.LP
"OpenLDAP Administrator's Guide" (http://www.OpenLDAP.org/doc/admin/)
.SH BUGS
.\" Copyright 2004-2007 The OpenLDAP Foundation All Rights Reserved.
.\" Copying restrictions apply. See COPYRIGHT/LICENSE.
.SH NAME
-slapdn \- Check a list of string-represented DNs based on schema syntax.
+slapdn \- Check a list of string-represented LDAP DNs based on schema syntax
.SH SYNOPSIS
.B SBINDIR/slapdn
.B [\-d level]
.\" Copyright 2004-2007 The OpenLDAP Foundation All Rights Reserved.
.\" Copying restrictions apply. See COPYRIGHT/LICENSE.
.SH NAME
-slaptest \- Check the suitability of the slapd.conf file.
+slaptest \- Check the suitability of the OpenLDAP slapd.conf file
.SH SYNOPSIS
.B SBINDIR/slaptest
.B [\-d level]
.B [\-f slapd.conf]
.B [\-F confdir]
.B [\-o name[=value]
+.B [\-Q]
.B [\-u]
.B [\-v]
.LP
.fi
.TP
-.B \-u
+.BI \-Q
+Be extremely quiet: only the exit code indicates success (0) or not
+(any other value).
+.TP
+.BI \-u
enable dryrun mode (i.e. don't fail if databases cannot be opened,
but config is fine).
.TP
-.B \-v
+.BI \-v
enable verbose mode.
.SH EXAMPLES
To check a
+++ /dev/null
-.TH SLURPD 8C "RELEASEDATE" "OpenLDAP LDVERSION"
-.\" $OpenLDAP$
-.\" Copyright 1998-2007 The OpenLDAP Foundation All Rights Reserved.
-.\" Copying restrictions apply. See COPYRIGHT/LICENSE.
-.SH NAME
-slurpd \- Standalone LDAP Update Replication Daemon
-.SH SYNOPSIS
-.B LIBEXECDIR/slurpd [\-d debug\-level]
-.B [\-f slapd\-config\-file] [\-r slapd\-replog\-file]
-.B [\-t temp\-dir] [\-o]
-.B
-.SH DESCRIPTION
-.LP
-.B Slurpd
-is used to propagate changes from one slapd database to another. If
-slapd is configured to produce a replication log,
-.B slurpd
-reads that
-replication log and sends the changes to the slave
-.B slapd
-instances
-via the LDAP protocol.
-.B slurpd
-is typically invoked at boot time, usually out of
-.BR /etc/rc.local .
-.LP
-Upon startup,
-.B slurpd
-normally forks and disassociates itself from the invoking tty,
-then reads the replication log (given either by the
-.I replogfile
-directive in the
-.B slapd
-config file, or by the
-.RB \- r
-command-line option).
-If the replication log file does not exist or is empty,
-.B slurpd
-goes to sleep. It periodically wakes up and checks to see if there
-are any changes to be propagated.
-.LP
-When
-.B slurpd
-notices that there are changes to propagate to slave
-.B slapd
-instances, it locks the replication log, makes its own private copy,
-releases the lock, and forks one copy of itself for each replica
-.B slapd
-to be updated. Each child process binds to the slave
-.B slapd
-as the
-DN given by the
-.I binddn
-option to the
-.I replica
-directive in the
-.B slapd
-config file, and sends the changes.
-.LP
-See
-.BR slapd (8)
-for details on the standalone LDAP daemon.
-.LP
-Note that slurpd reads
-.B replication
-directive from
-.BR slapd.conf (5),
-but uses
-.BR ldap.conf (5)
-to obtain other configuration settings (such as TLS settings).
-.SH OPTIONS
-.TP
-.BI \-d " debug\-level"
-Turn on debugging as defined by
-.I debug\-level.
-If this option is specified, even with a zero argument,
-.B slurpd
-will not fork or disassociate from the invoking terminal. Some general
-operation and status messages are printed for any value of \fIdebug\-level\fP.
-\fIdebug\-level\fP is taken as a bit string, with each bit corresponding to a
-different kind of debugging information. See <ldap.h> for details.
-.TP
-.BI \-f " slapd\-config\-file"
-Specifies the slapd configuration file. The default is
-.BR ETCDIR/slapd.conf .
-.TP
-.BI \-r " slapd\-replog\-file"
-Specifies the name of the
-.B slapd
-replication logfile. Normally, the name
-of the replication log file is read from the
-.B slapd
-configuration file. The file should be located in a directory
-with limited read/write/execute access.
-The
-.B \-r
-option allows you to override this. In conjunction with the
-.B \-o
-option, you can process a replication log file in a "one\-shot" mode. For
-example, if
-.B slurpd
-has encountered errors in processing a replication log,
-you can run it in one\-shot mode and give the rejection file name as
-the argument to the \-r option, once you've resolved the problem which caused
-the replication to fail.
-.TP
-.B \-o
-Run in "one\-shot" mode. Normally,
-.B slurpd
-processes the replog file
-and then watches for more replication entries to be appended. In
-one\-shot mode,
-.B slurpd
-processes a replication log and exits.
-.TP
-.BI \-t " temp\-dir"
-.B slurpd
-copies the replication log to a working directory before processing it.
-The directory permissions should limit read/write/execute access as
-temporary files may contain sensitive information.
-This option allows you to specify the location of these temporary files.
-The default is
-.BR LOCALSTATEDIR/openldap-slurp .
-.SH EXAMPLES
-To start
-.I slurpd
-and have it fork and detach from the terminal and process
-the replication logs generated by
-.I slapd,
-just type:
-.LP
-.nf
-.ft tt
- LIBEXECDIR/slurpd
-.ft
-.fi
-.LP
-To start
-.I slurpd
-with an alternate
-.I slapd
-configuration file, and turn
-on voluminous debugging which will be printed on standard error, type:
-.LP
-.nf
-.ft tt
- LIBEXECDIR/slurpd -f ETCDIR/slapd.conf -d 255
-.ft
-.fi
-.LP
-.SH "SEE ALSO"
-.BR ldap (3),
-.BR ldap.conf (5),
-.BR slapd.conf (5),
-.BR slapd.replog (5),
-.BR slapd (8)
-.LP
-"OpenLDAP Administrator's Guide" (http://www.OpenLDAP.org/doc/admin/)
-.SH ACKNOWLEDGEMENTS
-.so ../Project
rfc4531.txt LDAP Turn Operation (E)
rfc4532.txt LDAP Who am I? Operation (PS)
rfc4533.txt LDAP Content Sync Operation (E)
+rfc5020.txt LDAP 'entryDN' operational attribute (PS)
Legend:
STD Standard
--- /dev/null
+
+
+
+
+
+
+Network Working Group K. Zeilenga
+Request for Comments: 5020 Isode Limited
+Category: Standards Track August 2007
+
+
+ The Lightweight Directory Access Protocol (LDAP) entryDN
+ Operational Attribute
+
+Status of This Memo
+
+ This document specifies an Internet standards track protocol for the
+ Internet community, and requests discussion and suggestions for
+ improvements. Please refer to the current edition of the "Internet
+ Official Protocol Standards" (STD 1) for the standardization state
+ and status of this protocol. Distribution of this memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The IETF Trust (2007).
+
+Abstract
+
+ This document describes the Lightweight Directory Access Protocol
+ (LDAP) / X.500 'entryDN' operational attribute. The attribute
+ provides a copy of the entry's distinguished name for use in
+ attribute value assertions.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Zeilenga Standards Track [Page 1]
+\f
+RFC 5020 LDAP entryDN August 2007
+
+
+1. Background and Intended Use
+
+ In X.500 Directory Services [X.501], such as those accessible using
+ the Lightweight Directory Access Protocol (LDAP) [RFC4510], an entry
+ is identified by its distinguished name (DN) [RFC4512]. However, as
+ an entry's DN is not an attribute of the entry, it is not possible to
+ perform attribute value assertions [RFC4511] against it.
+
+ This document describes the 'entryDN' operational attribute which
+ holds a copy of the entry's distinguished name. This attribute may
+ be used in search filters. For instance, searching the subtree
+ <dc=example,dc=com> with the filter:
+
+ (entryDN:componentFilterMatch:=or:{
+ item:{ component "3", rule rdnMatch, value "ou=A" },
+ item:{ component "3", rule rdnMatch, value "ou=B" } })
+
+ would return entries in the subtree <ou=A,dc=example,dc=com> and
+ entries in subtree <ou=B,dc=example,dc=com>, but would not return any
+ other entries in the subtree <dc=example,dc=com>.
+
+ In the above paragraph, DNs are presented using the string
+ representation defined in [RFC4514], and the example search filter is
+ presented using the string representation defined in [RFC4515] with
+ whitespace (line breaks and indentation) added to improve
+ readability. The 'componentFilterMatch' and 'rdnMatch' rules are
+ specified in [RFC3687].
+
+ Schema definitions are provided using LDAP description formats
+ [RFC4512]. Definitions provided here are formatted (line wrapped)
+ for readability.
+
+2. 'entryDN' Operational Attribute
+
+ The 'entryDN' operational attribute provides a copy of the entry's
+ current DN.
+
+ The following is an LDAP attribute type description suitable for
+ publication in subschema subentries.
+
+ ( 1.3.6.1.1.20 NAME 'entryDN'
+ DESC 'DN of the entry'
+ EQUALITY distinguishedNameMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.12
+ SINGLE-VALUE
+ NO-USER-MODIFICATION
+ USAGE directoryOperation )
+
+
+
+
+Zeilenga Standards Track [Page 2]
+\f
+RFC 5020 LDAP entryDN August 2007
+
+
+ Note that the DN of the entry cannot be modified through this
+ attribute.
+
+3. Security Considerations
+
+ As this attribute only provides an additional mechanism to access an
+ entry's DN, the introduction of this attribute is not believed to
+ introduce new security considerations.
+
+4. IANA Considerations
+
+4.1. Object Identifier Registration
+
+ IANA has registered (upon Standards Action) an LDAP Object Identifier
+ [RFC4520] for use in this document.
+
+ Subject: Request for LDAP OID Registration
+ Person & email address to contact for further information:
+ Kurt Zeilenga <Kurt.Zeilenga@Isode.COM>
+ Specification: RFC 5020
+ Author/Change Controller: IESG
+ Comments:
+ Identifies the 'entryDN' attribute type
+
+4.2. 'entryDN' Descriptor Registration
+
+ IANA has registered (upon Standards Action) the LDAP 'entryDN'
+ descriptor [RFC4520].
+
+ Subject: Request for LDAP Descriptor Registration
+ Descriptor (short name): entryDN
+ Object Identifier: 1.3.6.1.1.20
+ Person & email address to contact for further information:
+ Kurt Zeilenga <Kurt.Zeilenga@Isode.COM>
+ Usage: Attribute Type
+ Specification: RFC 5020
+ Author/Change Controller: IESG
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Zeilenga Standards Track [Page 3]
+\f
+RFC 5020 LDAP entryDN August 2007
+
+
+5. References
+
+5.1. Normative References
+
+ [RFC4510] Zeilenga, K., Ed., "Lightweight Directory Access Protocol
+ (LDAP): Technical Specification Road Map", RFC 4510, June
+ 2006.
+
+ [RFC4512] Zeilenga, K., Ed., "Lightweight Directory Access Protocol
+ (LDAP): Directory Information Models", RFC 4512, June
+ 2006.
+
+ [X.501] International Telecommunication Union - Telecommunication
+ Standardization Sector, "The Directory -- Models,"
+ X.501(1993) (also ISO/IEC 9594-2:1994).
+
+5.2. Informative References
+
+ [RFC3687] Legg, S., "Lightweight Directory Access Protocol (LDAP)
+ and X.500 Component Matching Rules", RFC 3687, February
+ 2004.
+
+ [RFC4511] Sermersheim, J., Ed., "Lightweight Directory Access
+ Protocol (LDAP): The Protocol", RFC 4511, June 2006.
+
+ [RFC4514] Zeilenga, K., Ed., "Lightweight Directory Access Protocol
+ (LDAP): String Representation of Distinguished Names",
+ RFC 4514, June 2006.
+
+ [RFC4515] Smith, M., Ed., and T. Howes, "Lightweight Directory
+ Access Protocol (LDAP): String Representation of Search
+ Filters", RFC 4515, June 2006.
+
+ [RFC4520] Zeilenga, K., "Internet Assigned Numbers Authority (IANA)
+ Considerations for the Lightweight Directory Access
+ Protocol (LDAP)", BCP 64, RFC 4520, June 2006.
+
+Author's Address
+
+ Kurt D. Zeilenga
+ Isode Limited
+
+ EMail: Kurt.Zeilenga@Isode.COM
+
+
+
+
+
+
+
+
+Zeilenga Standards Track [Page 4]
+\f
+RFC 5020 LDAP entryDN August 2007
+
+
+Full Copyright Statement
+
+ Copyright (C) The IETF Trust (2007).
+
+ This document is subject to the rights, licenses and restrictions
+ contained in BCP 78, and except as set forth therein, the authors
+ retain all their rights.
+
+ This document and the information contained herein are provided on an
+ "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS
+ OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY, THE IETF TRUST AND
+ THE INTERNET ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS
+ OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF
+ THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED
+ WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Intellectual Property
+
+ The IETF takes no position regarding the validity or scope of any
+ Intellectual Property Rights or other rights that might be claimed to
+ pertain to the implementation or use of the technology described in
+ this document or the extent to which any license under such rights
+ might or might not be available; nor does it represent that it has
+ made any independent effort to identify any such rights. Information
+ on the procedures with respect to rights in RFC documents can be
+ found in BCP 78 and BCP 79.
+
+ Copies of IPR disclosures made to the IETF Secretariat and any
+ assurances of licenses to be made available, or the result of an
+ attempt made to obtain a general license or permission for the use of
+ such proprietary rights by implementers or users of this
+ specification can be obtained from the IETF on-line IPR repository at
+ http://www.ietf.org/ipr.
+
+ The IETF invites any interested party to bring to its attention any
+ copyrights, patents or patent applications, or other proprietary
+ rights that may cover technology that may be required to implement
+ this standard. Please address the information to the IETF at
+ ietf-ipr@ietf.org.
+
+Acknowledgement
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+
+
+
+Zeilenga Standards Track [Page 5]
+\f
$(SED) -e 's/\\\\/\\\\\\\\\\\\\\\\/g'`; \
libexecdir=`cygpath -w $(libexecdir) | \
$(SED) -e 's/\\\\/\\\\\\\\\\\\\\\\/g'`; \
+ moduledir=`cygpath -w $(moduledir) | \
+ $(SED) -e 's/\\\\/\\\\\\\\\\\\\\\\/g'`; \
localstatedir=`cygpath -w $(localstatedir) | \
$(SED) -e 's/\\\\/\\\\\\\\\\\\\\\\/g'`; \
else \
bindir=$(bindir); \
sbindir=$(sbindir); \
libexecdir=$(libexecdir); \
+ moduledir=$(moduledir); \
localstatedir=$(localstatedir); \
localedir=$(localedir); \
fi; \
-e "s;%BINDIR%;$$bindir;" \
-e "s;%SBINDIR%;$$sbindir;" \
-e "s;%LIBEXECDIR%;$$libexecdir;" \
+ -e "s;%MODULEDIR%;$$moduledir;" \
-e "s;%RUNDIR%;$$localstatedir;" \
-e "s;%LOCALEDIR%;$$localedir;" \
$(LDAP_CONFIG) >> $@; \
#ifdef __GNUC__
# define alloca __builtin_alloca
#else
-# if HAVE_ALLOCA_H
+# ifdef HAVE_ALLOCA_H
# include <alloca.h>
# else
# ifdef _AIX
#include <ac/unistd.h>
/* crypt() may be defined in a separate include file */
-#if HAVE_CRYPT_H
+#ifdef HAVE_CRYPT_H
# include <crypt.h>
#else
extern char *(crypt)();
#ifndef _AC_DIRENT_H
#define _AC_DIRENT_H
-#if HAVE_DIRENT_H
+#ifdef HAVE_DIRENT_H
# include <dirent.h>
# define NAMLEN(dirent) strlen((dirent)->d_name)
#elif defined(_MSC_VER)
#else
# define dirent direct
# define NAMLEN(dirent) (dirent)->d_namlen
-# if HAVE_SYS_NDIR_H
+# ifdef HAVE_SYS_NDIR_H
# include <sys/ndir.h>
# endif
-# if HAVE_SYS_DIR_H
+# ifdef HAVE_SYS_DIR_H
# include <sys/dir.h>
# endif
-# if HAVE_NDIR_H
+# ifdef HAVE_NDIR_H
# include <ndir.h>
# endif
#endif
/* no sys_errlist */
# define sys_nerr 0
# define sys_errlist ((char **)0)
-#elif DECL_SYS_ERRLIST
+#elif defined( DECL_SYS_ERRLIST )
/* have sys_errlist but need declaration */
LDAP_LIBC_V(int) sys_nerr;
LDAP_LIBC_V(char) *sys_errlist[];
# define tcp_write( s, buf, len ) netwrite( s, buf, len )
# endif /* NCSA */
-#elif HAVE_CLOSESOCKET
+#elif defined(HAVE_CLOSESOCKET)
# define tcp_close( s ) closesocket( s )
# ifdef __BEOS__
# endif
#endif
-#ifndef HAVE_GETPEEREID
-LDAP_LUTIL_F( int ) getpeereid( int s, uid_t *, gid_t * );
+#if defined(LDAP_PF_LOCAL) && \
+ !defined(HAVE_GETPEEREID) && \
+ !defined(HAVE_GETPEERUCRED) && \
+ !defined(SO_PEERCRED) && !defined(LOCAL_PEERCRED) && \
+ defined(HAVE_SENDMSG) && (defined(HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTSLEN) || \
+ defined(HAVE_STRUCT_MSGHDR_MSG_CONTROL))
+# define LDAP_PF_LOCAL_SENDMSG 1
+#endif
+
+#ifdef HAVE_GETPEEREID
+#define LUTIL_GETPEEREID( s, uid, gid, bv ) getpeereid( s, uid, gid )
+#elif defined(LDAP_PF_LOCAL_SENDMSG)
+struct berval;
+LDAP_LUTIL_F( int ) lutil_getpeereid( int s, uid_t *, gid_t *, struct berval *bv );
+#define LUTIL_GETPEEREID( s, uid, gid, bv ) lutil_getpeereid( s, uid, gid, bv )
+#else
+LDAP_LUTIL_F( int ) lutil_getpeereid( int s, uid_t *, gid_t * );
+#define LUTIL_GETPEEREID( s, uid, gid, bv ) lutil_getpeereid( s, uid, gid )
#endif
/* DNS RFC defines max host name as 255. New systems seem to use 1024 */
#ifndef _AC_TERMIOS_H
#define _AC_TERMIOS_H
-#ifdef HAVE_POSIX_TERMIOS
+#ifdef HAVE_TERMIOS_H
#include <termios.h>
#ifdef GCWINSZ_IN_SYS_IOCTL
#ifndef _AC_TIME_H
#define _AC_TIME_H
-#if TIME_WITH_SYS_TIME
+#ifdef TIME_WITH_SYS_TIME
# include <sys/time.h>
# include <time.h>
-#elif HAVE_SYS_TIME_H
+#elif defined(HAVE_SYS_TIME_H)
# include <sys/time.h>
# ifdef HAVE_SYS_TIMEB_H
# include <sys/timeb.h>
#ifndef _AC_UNISTD_H
#define _AC_UNISTD_H
-#if HAVE_SYS_TYPES_H
+#ifdef HAVE_SYS_TYPES_H
# include <sys/types.h>
#endif
-#if HAVE_UNISTD_H
+#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
-#if HAVE_PROCESS_H
+#ifdef HAVE_PROCESS_H
# include <process.h>
#endif
#endif
/* getopt() defines may be in separate include file */
-#if HAVE_GETOPT_H
+#ifdef HAVE_GETOPT_H
# include <getopt.h>
#elif !defined(HAVE_GETOPT)
#include <sys/types.h>
-#if HAVE_SYS_WAIT_H
+#ifdef HAVE_SYS_WAIT_H
# include <sys/wait.h>
#endif
#define LBER_SB_OPT_NEEDS_WRITE 12
#define LBER_SB_OPT_GET_MAX_INCOMING 13
#define LBER_SB_OPT_SET_MAX_INCOMING 14
+
+/* Only meaningful ifdef LDAP_PF_LOCAL_SENDMSG */
+#define LBER_SB_OPT_UNGET_BUF 15
+
/* Largest option used by the library */
-#define LBER_SB_OPT_OPT_MAX 14
+#define LBER_SB_OPT_OPT_MAX 15
/* LBER IO operations stacking levels */
#define LBER_SBIOD_LEVEL_PROVIDER 10
char *buf,
ber_len_t *len ));
+#define LBER_BV_ALLOC 0x01 /* allocate/copy result, otherwise in-place */
+#define LBER_BV_NOTERM 0x02 /* omit NUL-terminator if parsing in-place */
+
LBER_F( ber_tag_t )
ber_get_stringbv LDAP_P((
BerElement *ber,
struct berval *bv,
- int alloc ));
+ int options ));
LBER_F( ber_tag_t )
ber_get_stringa LDAP_P((
LDAP_CONST char *fmt,
... ));
+LBER_F( int )
+ber_decode_oid LDAP_P((
+ struct berval *in,
+ struct berval *out ));
+
/*
* in encode.c
*/
+LBER_F( int )
+ber_encode_oid LDAP_P((
+ struct berval *in,
+ struct berval *out ));
+
typedef int (*BEREncodeCallback) LDAP_P((
BerElement *ber,
void *data ));
* in io.c:
*/
+LBER_F( ber_slen_t )
+ber_skip_data LDAP_P((
+ BerElement *ber,
+ ber_len_t len ));
+
LBER_F( ber_slen_t )
ber_read LDAP_P((
BerElement *ber,
#define LDAP_OPT_X_TLS_CONNECT_ARG 0x600d
#define LDAP_OPT_X_TLS_DHFILE 0x600e
#define LDAP_OPT_X_TLS_NEWCTX 0x600f
+#define LDAP_OPT_X_TLS_CRLFILE 0x6010 /* GNUtls only */
#define LDAP_OPT_X_TLS_NEVER 0
#define LDAP_OPT_X_TLS_HARD 1
#define LDAP_CONTROL_X_SEARCH_OPTIONS "1.2.840.113556.1.4.1340"
#define LDAP_SEARCH_FLAG_DOMAIN_SCOPE 1 /* do not generate referrals */
#define LDAP_SEARCH_FLAG_PHANTOM_ROOT 2 /* search all subordinate NCs */
+#define LDAP_CONTROL_X_TREE_DELETE "1.2.840.113556.1.4.805"
/* MS Active Directory controls - not implemented in slapd(8) */
-#define LDAP_CONTROL_X_TREE_DELETE "1.2.840.113556.1.4.805"
#define LDAP_CONTROL_X_EXTENDED_DN "1.2.840.113556.1.4.529"
+#ifdef LDAP_DEVEL
+/* <draft-wahl-ldap-session> */
+#define LDAP_CONTROL_X_SESSION_TRACKING "1.3.6.1.4.1.21008.108.63.1"
+#define LDAP_CONTROL_X_SESSION_TRACKING_RADIUS_ACCT_SESSION_ID \
+ LDAP_CONTROL_X_SESSION_TRACKING ".1"
+#define LDAP_CONTROL_X_SESSION_TRACKING_RADIUS_ACCT_MULTI_SESSION_ID \
+ LDAP_CONTROL_X_SESSION_TRACKING ".2"
+#define LDAP_CONTROL_X_SESSION_TRACKING_USERNAME \
+ LDAP_CONTROL_X_SESSION_TRACKING ".3"
+#endif /* LDAP_DEVEL */
+
/* various expired works */
/* LDAP Duplicated Entry Control Extension *//* not implemented in slapd(8) */
#define LDAP_CONTROL_DUPENT_REQUEST "2.16.840.1.113719.1.27.101.1"
/*
* in controls.c:
*/
+#if LDAP_DEPRECATED
LDAP_F( int )
-ldap_create_control LDAP_P((
+ldap_create_control LDAP_P(( /* deprecated, use ldap_control_create */
LDAP_CONST char *requestOID,
BerElement *ber,
int iscritical,
LDAPControl **ctrlp ));
LDAP_F( LDAPControl * )
-ldap_find_control LDAP_P((
+ldap_find_control LDAP_P(( /* deprecated, use ldap_control_find */
LDAP_CONST char *oid,
LDAPControl **ctrls ));
+#endif
+
+LDAP_F( int )
+ldap_control_create LDAP_P((
+ LDAP_CONST char *requestOID,
+ int iscritical,
+ struct berval *value,
+ int dupval,
+ LDAPControl **ctrlp ));
+
+LDAP_F( LDAPControl * )
+ldap_control_find LDAP_P((
+ LDAP_CONST char *oid,
+ LDAPControl **ctrls,
+ LDAPControl ***nextctrlp ));
LDAP_F( void )
ldap_control_free LDAP_P((
ldap_controls_free LDAP_P((
LDAPControl **ctrls ));
+LDAP_F( LDAPControl ** )
+ldap_controls_dup LDAP_P((
+ LDAPControl *LDAP_CONST *controls ));
+
+LDAP_F( LDAPControl * )
+ldap_control_dup LDAP_P((
+ LDAP_CONST LDAPControl *c ));
+
/*
* in dnssrv.c:
*/
ldap_sync_poll LDAP_P((
ldap_sync_t *ls ));
+#ifdef LDAP_CONTROL_X_SESSION_TRACKING
+
+/*
+ * in stctrl.c
+ */
+LDAP_F( int )
+ldap_create_session_tracking_value LDAP_P((
+ LDAP *ld,
+ char *sessionSourceIp,
+ char *sessionSourceName,
+ char *formatOID,
+ struct berval *sessionTrackingIdentifier,
+ struct berval *value ));
+
+LDAP_F( int )
+ldap_create_session_tracking LDAP_P((
+ LDAP *ld,
+ char *sessionSourceIp,
+ char *sessionSourceName,
+ char *formatOID,
+ struct berval *sessionTrackingIdentifier,
+ LDAPControl **ctrlp ));
+
+LDAP_F( int )
+ldap_parse_session_tracking_control LDAP_P((
+ LDAP *ld,
+ LDAPControl *ctrl,
+ struct berval *ip,
+ struct berval *name,
+ struct berval *oid,
+ struct berval *id ));
+
+#endif /* LDAP_CONTROL_X_SESSION_TRACKING */
+
LDAP_END_DECL
#endif /* _LDAP_H */
#ifndef LDAP_LIBEXECDIR
#define LDAP_LIBEXECDIR "%LIBEXECDIR%"
#endif
+#ifndef LDAP_MODULEDIR
+#define LDAP_MODULEDIR "%MODULEDIR%"
+#endif
#ifndef LDAP_RUNDIR
#define LDAP_RUNDIR "%RUNDIR%"
#endif
#define LDAP_PVT_URL_PARSE_DEF_PORT (0x02U)
#define LDAP_PVT_URL_PARSE_NOEMPTY_DN (0x04U)
#define LDAP_PVT_URL_PARSE_NODEF_SCOPE (0x08U)
-#define LDAP_PVT_URL_PARSE_HISTORIC (LDAP_PVT_URL_PARSE_NODEF_SCOPE | LDAP_PVT_URL_PARSE_NOEMPTY_HOST | LDAP_PVT_URL_PARSE_DEF_PORT)
+#define LDAP_PVT_URL_PARSE_HISTORIC (LDAP_PVT_URL_PARSE_NODEF_SCOPE | \
+ LDAP_PVT_URL_PARSE_NOEMPTY_HOST | \
+ LDAP_PVT_URL_PARSE_DEF_PORT)
+
LDAP_F( int )
ldap_url_parse_ext LDAP_P((
LDAP_CONST char *url,
struct ldap_url_desc **ludpp,
unsigned flags ));
+LDAP_F (int) ldap_url_parselist LDAP_P(( /* deprecated, use ldap_url_parselist_ext() */
+ struct ldap_url_desc **ludlist,
+ const char *url ));
+
LDAP_F (int) ldap_url_parselist_ext LDAP_P((
struct ldap_url_desc **ludlist,
const char *url,
/* controls.c */
struct ldapcontrol;
-LDAP_F (struct ldapcontrol *) ldap_control_dup LDAP_P((
- const struct ldapcontrol *ctrl ));
-
-LDAP_F (struct ldapcontrol **) ldap_controls_dup LDAP_P((
- struct ldapcontrol *const *ctrls ));
-
+LDAP_F (int)
+ldap_pvt_put_control LDAP_P((
+ const struct ldapcontrol *c,
+ BerElement *ber ));
LDAP_F (int) ldap_pvt_get_controls LDAP_P((
BerElement *be,
struct ldapcontrol ***ctrlsp));
LDAP_F (int) ldap_pvt_tls_accept LDAP_P(( Sockbuf *sb, void *ctx_arg ));
LDAP_F (int) ldap_pvt_tls_inplace LDAP_P(( Sockbuf *sb ));
LDAP_F (void *) ldap_pvt_tls_sb_ctx LDAP_P(( Sockbuf *sb ));
-
-LDAP_F (int) ldap_pvt_tls_init_default_ctx LDAP_P(( void ));
+LDAP_F (void) ldap_pvt_tls_ctx_free LDAP_P(( void * ));
typedef int LDAPDN_rewrite_dummy LDAP_P (( void *dn, unsigned flags ));
* If none is available, unsigned long data is used.
*/
-#if USE_MP_BIGNUM
+#ifdef USE_MP_BIGNUM
/*
* Use OpenSSL's BIGNUM
*/
#define ldap_pvt_mp_clear(mp) \
do { BN_free((mp)); (mp) = 0; } while (0)
-#elif USE_MP_GMP
+#elif defined(USE_MP_GMP)
/*
* Use GNU's multiple precision library
*/
* Use unsigned long long
*/
-#if USE_MP_LONG_LONG
+#ifdef USE_MP_LONG_LONG
typedef unsigned long long ldap_pvt_mp_t;
#define LDAP_PVT_MP_INIT (0LL)
-#elif USE_MP_LONG
+#elif defined(USE_MP_LONG)
typedef unsigned long ldap_pvt_mp_t;
#define LDAP_PVT_MP_INIT (0L)
-#elif HAVE_LONG_LONG
+#elif defined(HAVE_LONG_LONG)
typedef unsigned long long ldap_pvt_mp_t;
#define LDAP_PVT_MP_INIT (0LL)
#else
typedef ldap_int_thread_rmutex_t ldap_pvt_thread_rmutex_t;
#endif /* !LDAP_PVT_THREAD_H_DONE */
-#if 0 && defined(LDAP_DEVEL)
-/* must also be defined in slapd.h */
-#define LDAP_PVT_THREAD_POOL_SEM_LOAD_CONTROL
-#endif
-
#define ldap_pvt_thread_equal ldap_int_thread_equal
LDAP_F( int )
LDAP_LUTIL_F( size_t )
lutil_uuidstr( char *buf, size_t len );
+LDAP_LUTIL_F( int )
+lutil_uuidstr_from_normalized(
+ char *uuid,
+ size_t uuidlen,
+ char *buf,
+ size_t buflen );
+
/* csn.c */
/* use this macro to allocate buffer for lutil_csnstr */
#define LDAP_LUTIL_CSNSTR_BUFSIZE 64
/* Define to 1 if you have the <gmp.h> header file. */
#undef HAVE_GMP_H
+/* define if you have GNUtls */
+#undef HAVE_GNUTLS
+
+/* Define to 1 if you have the <gnutls/gnutls.h> header file. */
+#undef HAVE_GNUTLS_GNUTLS_H
+
/* if you have GNU Pth */
#undef HAVE_GNU_PTH
/* Define to 1 if `st_blksize' is member of `struct stat'. */
#undef HAVE_STRUCT_STAT_ST_BLKSIZE
+/* Define to 1 if `st_fstype' is member of `struct stat'. */
+#undef HAVE_STRUCT_STAT_ST_FSTYPE
+
+/* define to 1 if st_fstype is char * */
+#undef HAVE_STRUCT_STAT_ST_FSTYPE_CHAR
+
+/* define to 1 if st_fstype is int */
+#undef HAVE_STRUCT_STAT_ST_FSTYPE_INT
+
+/* Define to 1 if `st_vfstype' is member of `struct stat'. */
+#undef HAVE_STRUCT_STAT_ST_VFSTYPE
+
/* Define to 1 if you have the <synch.h> header file. */
#undef HAVE_SYNCH_H
/* Define to 1 if you have the <sys/filio.h> header file. */
#undef HAVE_SYS_FILIO_H
+/* Define to 1 if you have the <sys/fstyp.h> header file. */
+#undef HAVE_SYS_FSTYP_H
+
/* Define to 1 if you have the <sys/ioctl.h> header file. */
#undef HAVE_SYS_IOCTL_H
/* Define to 1 if you have the <sys/poll.h> header file. */
#undef HAVE_SYS_POLL_H
+/* Define to 1 if you have the <sys/privgrp.h> header file. */
+#undef HAVE_SYS_PRIVGRP_H
+
/* Define to 1 if you have the <sys/resource.h> header file. */
#undef HAVE_SYS_RESOURCE_H
/* Define to 1 if you have the <sys/uuid.h> header file. */
#undef HAVE_SYS_UUID_H
+/* Define to 1 if you have the <sys/vmount.h> header file. */
+#undef HAVE_SYS_VMOUNT_H
+
/* Define to 1 if you have <sys/wait.h> that is POSIX.1 compatible. */
#undef HAVE_SYS_WAIT_H
/* Define to 1 if you have the <utime.h> header file. */
#undef HAVE_UTIME_H
+/* define if you have uuid_generate() */
+#undef HAVE_UUID_GENERATE
+
/* define if you have uuid_to_str() */
#undef HAVE_UUID_TO_STR
+/* Define to 1 if you have the <uuid/uuid.h> header file. */
+#undef HAVE_UUID_UUID_H
+
/* Define to 1 if you have the `vprintf' function. */
#undef HAVE_VPRINTF
/* define for Dynamic List overlay */
#undef SLAPD_OVER_DYNLIST
+/* define for Reverse Group Membership overlay */
+#undef SLAPD_OVER_MEMBEROF
+
/* define for Password Policy overlay */
#undef SLAPD_OVER_PPOLICY
first (like Motorola and SPARC, unlike Intel and VAX). */
#undef WORDS_BIGENDIAN
+/* Define to the type of arg 3 for `accept'. */
+#undef ber_socklen_t
+
/* Define to `char *' if <sys/types.h> does not define. */
#undef caddr_t
/* define to snprintf routine */
#undef snprintf
-/* Define to `int' if <sys/socket.h> does not define. */
+/* Define like ber_socklen_t if <sys/socket.h> does not define. */
#undef socklen_t
/* Define to `signed int' if <sys/types.h> does not define. */
typedef struct slapi_value Slapi_Value;
typedef struct slapi_valueset Slapi_ValueSet;
typedef struct slapi_filter Slapi_Filter;
-typedef struct slap_backend_db Slapi_Backend;
-typedef struct slap_op Slapi_Operation;
-typedef struct slap_conn Slapi_Connection;
+typedef struct BackendDB Slapi_Backend;
+typedef struct Operation Slapi_Operation;
+typedef struct Connection Slapi_Connection;
typedef struct slapi_dn Slapi_DN;
typedef struct slapi_rdn Slapi_RDN;
typedef struct slapi_mod Slapi_Mod;
len = ber_pvt_ber_write(ber);
}
- sprintf( buf, "ber_dump: buf=0x%08lx ptr=0x%08lx end=0x%08lx len=%ld\n",
- (long) ber->ber_buf,
- (long) ber->ber_ptr,
- (long) ber->ber_end,
+ sprintf( buf, "ber_dump: buf=%p ptr=%p end=%p len=%ld\n",
+ ber->ber_buf,
+ ber->ber_ptr,
+ ber->ber_end,
(long) len );
(void) (*ber_pvt_log_print)( buf );
(*ber_pvt_log_print)( "*** sos dump ***\n" );
while ( sos != NULL ) {
- sprintf( buf, "ber_sos_dump: clen %ld first 0x%lx ptr 0x%lx\n",
+ sprintf( buf, "ber_sos_dump: clen %ld first %p ptr %p\n",
(long) sos->sos_clen,
- (long) sos->sos_first,
- (long) sos->sos_ptr );
+ sos->sos_first,
+ sos->sos_ptr );
(*ber_pvt_log_print)( buf );
sprintf( buf, " current len %ld contents:\n",
ber_int_t *num,
ber_len_t len ));
+/* out->bv_len should be the buffer size on input */
+int
+ber_decode_oid( BerValue *in, BerValue *out )
+{
+ const unsigned char *der;
+ unsigned long val;
+ unsigned val1;
+ ber_len_t i;
+ char *ptr;
+
+ assert( in != NULL );
+ assert( out != NULL );
+
+ /* need 4 chars/inbyte + \0 for input={7f 7f 7f...} */
+ if ( !out->bv_val || (out->bv_len+3)/4 <= in->bv_len )
+ return -1;
+
+ ptr = NULL;
+ der = (unsigned char *) in->bv_val;
+ val = 0;
+ for ( i=0; i < in->bv_len; i++ ) {
+ val |= der[i] & 0x7f;
+ if ( !( der[i] & 0x80 )) {
+ if ( ptr == NULL ) {
+ /* Initial "x.y": val=x*40+y, x<=2, y<40 if x=2 */
+ ptr = out->bv_val;
+ val1 = (val < 80 ? val/40 : 2);
+ val -= val1*40;
+ ptr += sprintf( ptr, "%u", val1 );
+ }
+ ptr += sprintf( ptr, ".%lu", val );
+ val = 0;
+ } else if ( val - 1UL < LBER_OID_COMPONENT_MAX >> 7 ) {
+ val <<= 7;
+ } else {
+ /* val would overflow, or is 0 from invalid initial 0x80 octet */
+ return -1;
+ }
+ }
+ if ( ptr == NULL || val != 0 )
+ return -1;
+
+ out->bv_len = ptr - out->bv_val;
+ return 0;
+}
+
/* return the tag - LBER_DEFAULT returned means trouble */
ber_tag_t
ber_get_tag( BerElement *ber )
case BvOff:
*b->res.ba = ber_memalloc_x( (n+1) * b->siz, b->ber->ber_memctx );
if ( *b->res.ba == NULL ) return LBER_DEFAULT;
- ((struct berval *)((long)(*b->res.ba) + n*b->siz +
+ ((struct berval *)((char *)(*b->res.ba) + n*b->siz +
b->off))->bv_val = NULL;
break;
}
*bvp = bv;
break;
case BvOff:
- *(BerVarray)((long)(*b->res.ba)+n*b->siz+b->off) = bv;
+ *(BerVarray)((char *)(*b->res.ba)+n*b->siz+b->off) = bv;
break;
}
}
}
ber_tag_t
-ber_get_stringbv( BerElement *ber, struct berval *bv, int alloc )
+ber_get_stringbv( BerElement *ber, struct berval *bv, int option )
{
ber_tag_t tag;
return LBER_DEFAULT;
}
- if ( alloc ) {
+ if ( option & LBER_BV_ALLOC ) {
bv->bv_val = (char *) ber_memalloc_x( bv->bv_len + 1,
ber->ber_memctx );
if ( bv->bv_val == NULL ) {
ber->ber_ptr += bv->bv_len;
}
ber->ber_tag = *(unsigned char *)ber->ber_ptr;
- bv->bv_val[bv->bv_len] = '\0';
+ if ( !( option & LBER_BV_NOTERM ))
+ bv->bv_val[bv->bv_len] = '\0';
return tag;
}
ber_tag_t
-ber_get_stringbv_null( BerElement *ber, struct berval *bv, int alloc )
+ber_get_stringbv_null( BerElement *ber, struct berval *bv, int option )
{
ber_tag_t tag;
return tag;
}
- if ( alloc ) {
+ if ( option & LBER_BV_ALLOC ) {
bv->bv_val = (char *) ber_memalloc_x( bv->bv_len + 1,
ber->ber_memctx );
if ( bv->bv_val == NULL ) {
ber->ber_ptr += bv->bv_len;
}
ber->ber_tag = *(unsigned char *)ber->ber_ptr;
- bv->bv_val[bv->bv_len] = '\0';
+ if ( !( option & LBER_BV_NOTERM ))
+ bv->bv_val[bv->bv_len] = '\0';
return tag;
}
assert( buf != NULL );
- tag = ber_get_stringbv( ber, &bv, 1 );
+ tag = ber_get_stringbv( ber, &bv, LBER_BV_ALLOC );
*buf = bv.bv_val;
return tag;
assert( buf != NULL );
- tag = ber_get_stringbv_null( ber, &bv, 1 );
+ tag = ber_get_stringbv_null( ber, &bv, LBER_BV_ALLOC );
*buf = bv.bv_val;
return tag;
return LBER_DEFAULT;
}
- tag = ber_get_stringbv( ber, *bv, 1 );
+ tag = ber_get_stringbv( ber, *bv, LBER_BV_ALLOC );
if ( tag == LBER_DEFAULT ) {
LBER_FREE( *bv );
*bv = NULL;
case 'o': /* octet string in a supplied berval */
bval = va_arg( ap, struct berval * );
- rc = ber_get_stringbv( ber, bval, 1 );
+ rc = ber_get_stringbv( ber, bval, LBER_BV_ALLOC );
break;
case 'O': /* octet string - allocate & include length */
bgbvr cookie = { ChArray };
cookie.ber = ber;
cookie.res.c = va_arg( ap, char *** );
- cookie.alloc = 1;
+ cookie.alloc = LBER_BV_ALLOC;
rc = ber_get_stringbvl( &cookie, NULL );
break;
}
bgbvr cookie = { BvVec };
cookie.ber = ber;
cookie.res.bv = va_arg( ap, struct berval *** );
- cookie.alloc = 1;
+ cookie.alloc = LBER_BV_ALLOC;
rc = ber_get_stringbvl( &cookie, NULL );
break;
}
bgbvr cookie = { BvArray };
cookie.ber = ber;
cookie.res.ba = va_arg( ap, struct berval ** );
- cookie.alloc = 1;
+ cookie.alloc = LBER_BV_ALLOC;
rc = ber_get_stringbvl( &cookie, NULL );
break;
}
#include "portable.h"
+#include <ctype.h>
#include <stdio.h>
#include <ac/stdlib.h>
return rc == i ? i+1 : -1;
}
+/* out->bv_len should be the buffer size on input */
+int
+ber_encode_oid( BerValue *in, BerValue *out )
+{
+ unsigned char *der;
+ unsigned long val1, val;
+ int i, j, len;
+ char *ptr, *end, *inend;
+
+ assert( in != NULL );
+ assert( out != NULL );
+
+ if ( !out->bv_val || out->bv_len < in->bv_len/2 )
+ return -1;
+
+ der = (unsigned char *) out->bv_val;
+ ptr = in->bv_val;
+ inend = ptr + in->bv_len;
+
+ /* OIDs start with <0-1>.<0-39> or 2.<any>, DER-encoded 40*val1+val2 */
+ if ( !isdigit( (unsigned char) *ptr )) return -1;
+ val1 = strtoul( ptr, &end, 10 );
+ if ( end == ptr || val1 > 2 ) return -1;
+ if ( *end++ != '.' || !isdigit( (unsigned char) *end )) return -1;
+ val = strtoul( end, &ptr, 10 );
+ if ( ptr == end ) return -1;
+ if ( val > (val1 < 2 ? 39 : LBER_OID_COMPONENT_MAX - 80) ) return -1;
+ val += val1 * 40;
+
+ for (;;) {
+ if ( ptr > inend ) return -1;
+
+ len = 0;
+ do {
+ der[len++] = (val & 0xff) | 0x80;
+ } while ( (val >>= 7) != 0 );
+ der[0] &= 0x7f;
+ for ( i = 0, j = len; i < --j; i++ ) {
+ unsigned char tmp = der[i];
+ der[i] = der[j];
+ der[j] = tmp;
+ }
+ der += len;
+ if ( ptr == inend )
+ break;
+
+ if ( *ptr++ != '.' ) return -1;
+ if ( !isdigit( (unsigned char) *ptr )) return -1;
+ val = strtoul( ptr, &end, 10 );
+ if ( end == ptr || val > LBER_OID_COMPONENT_MAX ) return -1;
+ ptr = end;
+ }
+
+ out->bv_len = (char *)der - out->bv_val;
+ return 0;
+}
+
static int
ber_put_int_or_enum(
BerElement *ber,
#include "lber-int.h"
#include "ldap_log.h"
+ber_slen_t
+ber_skip_data(
+ BerElement *ber,
+ ber_len_t len )
+{
+ ber_len_t actuallen, nleft;
+
+ assert( ber != NULL );
+
+ assert( LBER_VALID( ber ) );
+
+ nleft = ber_pvt_ber_remaining( ber );
+ actuallen = nleft < len ? nleft : len;
+ ber->ber_ptr += actuallen;
+ ber->ber_tag = *(unsigned char *)ber->ber_ptr;
+
+ return( (ber_slen_t) actuallen );
+}
+
ber_slen_t
ber_read(
BerElement *ber,
void
ber_free( BerElement *ber, int freebuf )
{
-#ifdef LDAP_MEMORY_DEBUG
- assert( ber != NULL );
-#endif
-
if( ber == NULL ) {
+ LDAP_MEMORY_DEBUG_ASSERT( ber != NULL );
return;
}
#ifdef LDAP_MEMORY_DEBUG
LBER_V (long) ber_int_meminuse;
#endif
+#if defined(LDAP_MEMORY_DEBUG) && ((LDAP_MEMORY_DEBUG +0) & 2)
+# define LDAP_MEMORY_DEBUG_ASSERT assert
+#else
+# define LDAP_MEMORY_DEBUG_ASSERT(expr) ((void) 0)
+#endif
struct lber_options {
short lbo_valid;
#define sb_options sb_opts.lbo_options
#define sb_debug sb_opts.lbo_debug
ber_socket_t sb_fd;
+ ber_len_t sb_max_incoming;
unsigned int sb_trans_needs_read:1;
unsigned int sb_trans_needs_write:1;
- ber_len_t sb_max_incoming;
+#ifdef LDAP_PF_LOCAL_SENDMSG
+ char sb_ungetlen;
+ char sb_ungetbuf[8];
+#endif
};
#define SOCKBUF_VALID( sb ) ( (sb)->sb_valid == LBER_VALID_SOCKBUF )
};
+/*
+ * decode.c, encode.c
+ */
+
+/* Simplest OID max-DER-component to implement in both decode and encode */
+#define LBER_OID_COMPONENT_MAX ((unsigned long)-1 - 128)
+
+
/*
* io.c
*/
#include <stdio.h>
#endif
-#if LDAP_MEMORY_DEBUG
+#ifdef LDAP_MEMORY_DEBUG
/*
* LDAP_MEMORY_DEBUG should only be enabled for the purposes of
* debugging memory management within OpenLDAP libraries and slapd.
- * It should only be enabled by an experienced developer as it
- * causes the inclusion of numerous assert()'s, many of which may
- * be triggered by a prefectly valid program.
+ *
+ * It should only be enabled by an experienced developer as it causes
+ * the inclusion of numerous assert()'s, many of which may be triggered
+ * by a prefectly valid program. If LDAP_MEMORY_DEBUG & 2 is true,
+ * that includes asserts known to break both slapd and current clients.
*
* The code behind this macro is subject to change as needed to
* support this testing.
* put allocations/frees together. It is then a simple matter to write a script
* to find any allocations that don't have a buffer free function.
*/
+long ber_int_meminuse = 0;
#ifdef LDAP_MEMORY_TRACE
static ber_int_t sequence = 0;
#endif
{
void *new;
-#ifdef LDAP_MEMORY_DEBUG
- assert( s != 0 );
-#endif
-
if( s == 0 ) {
+ LDAP_MEMORY_DEBUG_ASSERT( s != 0 );
return NULL;
}
{
void *new;
-#ifdef LDAP_MEMORY_DEBUG
- assert( n != 0 && s != 0);
-#endif
-
if( n == 0 || s == 0 ) {
+ LDAP_MEMORY_DEBUG_ASSERT( n != 0 && s != 0);
return NULL;
}
ret = 1;
break;
+ case LBER_SB_OPT_UNGET_BUF:
+#ifdef LDAP_PF_LOCAL_SENDMSG
+ sb->sb_ungetlen = ((struct berval *)arg)->bv_len;
+ if ( sb->sb_ungetlen <= sizeof( sb->sb_ungetbuf )) {
+ AC_MEMCPY( sb->sb_ungetbuf, ((struct berval *)arg)->bv_val,
+ sb->sb_ungetlen );
+ ret = 1;
+ } else {
+ sb->sb_ungetlen = 0;
+ ret = -1;
+ }
+#endif
+ break;
+
default:
ret = sb->sb_iod->sbiod_io->sbi_ctrl( sb->sb_iod, opt, arg );
break;
int
ber_pvt_socket_set_nonblock( ber_socket_t sd, int nb )
{
-#if HAVE_FCNTL
+#ifdef HAVE_FCNTL
int flags = fcntl( sd, F_GETFL);
if( nb ) {
flags |= O_NONBLOCK;
assert( sbiod != NULL);
assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
+#ifdef LDAP_PF_LOCAL_SENDMSG
+ if ( sbiod->sbiod_sb->sb_ungetlen ) {
+ ber_len_t blen = sbiod->sbiod_sb->sb_ungetlen;
+ if ( blen > len )
+ blen = len;
+ AC_MEMCPY( buf, sbiod->sbiod_sb->sb_ungetbuf, blen );
+ buf = (char *) buf + blen;
+ len -= blen;
+ sbiod->sbiod_sb->sb_ungetlen -= blen;
+ if ( sbiod->sbiod_sb->sb_ungetlen ) {
+ AC_MEMCPY( sbiod->sbiod_sb->sb_ungetbuf,
+ sbiod->sbiod_sb->sb_ungetbuf+blen,
+ sbiod->sbiod_sb->sb_ungetlen );
+ }
+ if ( len == 0 )
+ return blen;
+ }
+#endif
return read( sbiod->sbiod_sb->sb_fd, buf, len );
}
sb_dgram_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
{
ber_slen_t rc;
- socklen_t addrlen;
+ ber_socklen_t addrlen;
struct sockaddr *src;
assert( sbiod != NULL );
addrlen = sizeof( struct sockaddr );
src = buf;
- buf += addrlen;
+ buf = (char *) buf + addrlen;
len -= addrlen;
rc = recvfrom( sbiod->sbiod_sb->sb_fd, buf, len, 0, src, &addrlen );
assert( buf != NULL );
dst = buf;
- buf += sizeof( struct sockaddr );
+ buf = (char *) buf + sizeof( struct sockaddr );
len -= sizeof( struct sockaddr );
rc = sendto( sbiod->sbiod_sb->sb_fd, buf, len, 0, dst,
request.c os-ip.c url.c pagectrl.c sortctrl.c vlvctrl.c \
init.c options.c print.c string.c util-int.c schema.c \
charray.c tls.c os-local.c dnssrv.c utf-8.c utf-8-conv.c \
- turn.c ppolicy.c dds.c txn.c ldap_sync.c
+ turn.c ppolicy.c dds.c txn.c ldap_sync.c stctrl.c
OBJS = bind.lo open.lo result.lo error.lo compare.lo search.lo \
controls.lo messages.lo references.lo extended.lo cyrus.lo \
request.lo os-ip.lo url.lo pagectrl.lo sortctrl.lo vlvctrl.lo \
init.lo options.lo print.lo string.lo util-int.lo schema.lo \
charray.lo tls.lo os-local.lo dnssrv.lo utf-8.lo utf-8-conv.lo \
- turn.lo ppolicy.lo dds.lo txn.lo ldap_sync.lo
+ turn.lo ppolicy.lo dds.lo txn.lo ldap_sync.lo stctrl.lo
LDAP_INCDIR= ../../include
LDAP_LIBDIR= ../../libraries
i = ++(ld)->ld_msgid;
#ifdef LDAP_CONNECTIONLESS
if ( LDAP_IS_UDP(ld) ) {
- err = ber_write( ber, ld->ld_options.ldo_peer,
- sizeof(struct sockaddr), 0);
+ struct sockaddr sa = {0};
+ /* dummy, filled with ldo_peer in request.c */
+ err = ber_write( ber, &sa, sizeof(sa), 0 );
}
if ( LDAP_IS_UDP(ld) && ld->ld_options.ldo_version ==
LDAP_VERSION2 )
assert( e != NULL );
e->lm_chain = *list;
- e->lm_chain_tail = (*list)->lm_chain_tail;
+ if ( *list )
+ e->lm_chain_tail = (*list)->lm_chain_tail;
+ else
+ e->lm_chain_tail = e;
*list = e;
}
* }
*/
+int
+ldap_pvt_put_control(
+ const LDAPControl *c,
+ BerElement *ber )
+{
+ if ( ber_printf( ber, "{s" /*}*/, c->ldctl_oid ) == -1 ) {
+ return LDAP_ENCODING_ERROR;
+ }
+
+ if ( c->ldctl_iscritical /* only if true */
+ && ( ber_printf( ber, "b",
+ (ber_int_t) c->ldctl_iscritical ) == -1 ) )
+ {
+ return LDAP_ENCODING_ERROR;
+ }
+
+ if ( !BER_BVISNULL( &c->ldctl_value ) /* only if we have a value */
+ && ( ber_printf( ber, "O", &c->ldctl_value ) == -1 ) )
+ {
+ return LDAP_ENCODING_ERROR;
+ }
+
+ if ( ber_printf( ber, /*{*/"N}" ) == -1 ) {
+ return LDAP_ENCODING_ERROR;
+ }
+
+ return LDAP_SUCCESS;
+}
+
+
/*
* ldap_int_put_controls
*/
}
for( c = ctrls ; *c != NULL; c++ ) {
- if ( ber_printf( ber, "{s" /*}*/,
- (*c)->ldctl_oid ) == -1 )
- {
- ld->ld_errno = LDAP_ENCODING_ERROR;
- return ld->ld_errno;
- }
-
- if( (*c)->ldctl_iscritical /* only if true */
- && ( ber_printf( ber, "b",
- (ber_int_t) (*c)->ldctl_iscritical ) == -1 ) )
- {
- ld->ld_errno = LDAP_ENCODING_ERROR;
- return ld->ld_errno;
- }
-
- if( (*c)->ldctl_value.bv_val != NULL /* only if we have a value */
- && ( ber_printf( ber, "O",
- &((*c)->ldctl_value) ) == -1 ) )
- {
- ld->ld_errno = LDAP_ENCODING_ERROR;
- return ld->ld_errno;
- }
-
-
- if( ber_printf( ber, /*{*/"N}" ) == -1 ) {
- ld->ld_errno = LDAP_ENCODING_ERROR;
+ ld->ld_errno = ldap_pvt_put_control( *c, ber );
+ if ( ld->ld_errno != LDAP_SUCCESS ) {
return ld->ld_errno;
}
}
if( tag == LBER_OCTETSTRING ) {
tag = ber_scanf( ber, "o", &tctrl->ldctl_value );
} else {
- tctrl->ldctl_value.bv_val = NULL;
+ BER_BVZERO( &tctrl->ldctl_value );
}
*ctrls = tctrls;
void
ldap_control_free( LDAPControl *c )
{
-#ifdef LDAP_MEMORY_DEBUG
- assert( c != NULL );
-#endif
+ LDAP_MEMORY_DEBUG_ASSERT( c != NULL );
if ( c != NULL ) {
if( c->ldctl_oid != NULL) {
void
ldap_controls_free( LDAPControl **controls )
{
-#ifdef LDAP_MEMORY_DEBUG
- assert( controls != NULL );
-#endif
+ LDAP_MEMORY_DEBUG_ASSERT( controls != NULL );
if ( controls != NULL ) {
int i;
}
} else {
+ /* FIXME: how can a control have null OID? */
new->ldctl_oid = NULL;
}
return new;
}
-
+/*
+ * Find a LDAPControl - deprecated
+ */
LDAPControl *
ldap_find_control(
LDAP_CONST char *oid,
}
/*
- ldap_create_control
-
- Internal function to create an LDAP control from the encoded BerElement.
-
- requestOID (IN) The OID to use in creating the control.
-
- ber (IN) The encoded BerElement to use in creating the control.
-
- iscritical (IN) 0 - Indicates the control is not critical to the operation.
- non-zero - The control is critical to the operation.
-
- ctrlp (OUT) Returns a pointer to the LDAPControl created. This control
- SHOULD be freed by calling ldap_control_free() when done.
----*/
+ * Find a LDAPControl
+ */
+LDAPControl *
+ldap_control_find(
+ LDAP_CONST char *oid,
+ LDAPControl **ctrls,
+ LDAPControl ***nextctrlp )
+{
+ if ( oid == NULL || ctrls == NULL || *ctrls == NULL ) {
+ return NULL;
+ }
+
+ for( ; *ctrls != NULL; ctrls++ ) {
+ if( strcmp( (*ctrls)->ldctl_oid, oid ) == 0 ) {
+ if ( nextctrlp != NULL ) {
+ *nextctrlp = ctrls + 1;
+ }
+
+ return *ctrls;
+ }
+ }
+
+ if ( nextctrlp != NULL ) {
+ *nextctrlp = NULL;
+ }
+ return NULL;
+}
+
+/*
+ * Create a LDAPControl, optionally from ber - deprecated
+ */
int
ldap_create_control(
LDAP_CONST char *requestOID,
LDAPControl *ctrl;
assert( requestOID != NULL );
- assert( ber != NULL );
assert( ctrlp != NULL );
ctrl = (LDAPControl *) LDAP_MALLOC( sizeof(LDAPControl) );
return LDAP_NO_MEMORY;
}
- if ( ber_flatten2( ber, &ctrl->ldctl_value, 1 ) == -1 ) {
+ BER_BVZERO(&ctrl->ldctl_value);
+ if ( ber && ( ber_flatten2( ber, &ctrl->ldctl_value, 1 ) == -1 )) {
LDAP_FREE( ctrl );
return LDAP_NO_MEMORY;
}
return LDAP_SUCCESS;
}
+/*
+ * Create a LDAPControl, optionally from value
+ */
+int
+ldap_control_create(
+ LDAP_CONST char *requestOID,
+ int iscritical,
+ struct berval *value,
+ int dupval,
+ LDAPControl **ctrlp )
+{
+ LDAPControl *ctrl;
+
+ assert( requestOID != NULL );
+ assert( ctrlp != NULL );
+
+ ctrl = (LDAPControl *) LDAP_CALLOC( sizeof(LDAPControl), 1 );
+ if ( ctrl == NULL ) {
+ return LDAP_NO_MEMORY;
+ }
+
+ ctrl->ldctl_iscritical = iscritical;
+ if ( requestOID != NULL ) {
+ ctrl->ldctl_oid = LDAP_STRDUP( requestOID );
+ if ( ctrl->ldctl_oid == NULL ) {
+ ldap_control_free( ctrl );
+ return LDAP_NO_MEMORY;
+ }
+ }
+
+ if ( value && !BER_BVISNULL( value ) ) {
+ if ( dupval ) {
+ ber_dupbv( &ctrl->ldctl_value, value );
+ if ( BER_BVISNULL( &ctrl->ldctl_value ) ) {
+ ldap_control_free( ctrl );
+ return LDAP_NO_MEMORY;
+ }
+
+ } else {
+ ctrl->ldctl_value = *value;
+ }
+ }
+
+ *ctrlp = ctrl;
+
+ return LDAP_SUCCESS;
+}
+
/*
* check for critical client controls and bitch if present
* if we ever support critical controls, we'll have to
rc = ber_flatten2( ber, &bv, 0 );
if ( rc < 0 ) {
- ld->ld_errno = LDAP_ENCODING_ERROR;
- return ld->ld_errno;
+ rc = ld->ld_errno = LDAP_ENCODING_ERROR;
+ goto done;
}
rc = ldap_extended_operation( ld, LDAP_EXOP_REFRESH, &bv,
sctrls, cctrls, msgidp );
+done:;
ber_free( ber, 1 );
return rc;
if( retoidp != NULL ) *retoidp = NULL;
if( retdatap != NULL ) *retdatap = NULL;
+ if( serverctrls != NULL ) *serverctrls = NULL;
ber = ber_dup( res->lm_ber );
/*
* Length of the (supposedly) AD canonical string representation,
- * accounting for escaped hex of UTF-8 chars
+ * accounting for chars that need to be escaped
*/
static int
strval2ADstrlen( struct berval *val, unsigned flags, ber_len_t *len )
{
- ber_len_t l;
+ ber_len_t l, cl;
char *p;
assert( val != NULL );
return( 0 );
}
- if ( flags & LDAP_AVA_NONPRINTABLE ) {
- /*
- * FIXME: Turn the value into a binary encoded BER?
- */
- return( -1 );
-
- } else {
- for ( l = 0, p = val->bv_val; p[ 0 ]; p++ ) {
- if ( LDAP_DN_NEEDESCAPE_AD( p[ 0 ] ) ) {
- l += 2;
-
- } else {
- l++;
- }
+ for ( l = 0, p = val->bv_val; p[ 0 ]; p += cl ) {
+ cl = LDAP_UTF8_CHARLEN2( p, cl );
+ if ( cl == 0 ) {
+ /* illegal utf-8 char */
+ return -1;
+ } else if ( (cl == 1) && LDAP_DN_NEEDESCAPE_AD( p[ 0 ] ) ) {
+ l += 2;
+ } else {
+ l += cl;
}
}
*len = l;
-
+
return( 0 );
}
/*
- * convert to (supposedly) AD string representation,
- * escaping with hex the UTF-8 stuff;
+ * convert to (supposedly) AD string representation,
* assume the destination has enough room for escaping
*/
static int
strval2ADstr( struct berval *val, char *str, unsigned flags, ber_len_t *len )
{
- ber_len_t s, d;
+ ber_len_t s, d, cl;
assert( val != NULL );
assert( str != NULL );
return( 0 );
}
- if ( flags & LDAP_AVA_NONPRINTABLE ) {
- /*
- * FIXME: Turn the value into a binary encoded BER?
- */
- *len = 0;
- return( -1 );
-
- } else {
-
- /*
- * we assume the string has enough room for the hex encoding
- * of the value
- */
+ /*
+ * we assume the string has enough room for the escaping
+ * of the value
+ */
- for ( s = 0, d = 0; s < val->bv_len; ) {
- if ( LDAP_DN_NEEDESCAPE_AD( val->bv_val[ s ] ) ) {
- str[ d++ ] = '\\';
- }
+ for ( s = 0, d = 0; s < val->bv_len; ) {
+ cl = LDAP_UTF8_CHARLEN2( val->bv_val+s, cl );
+ if ( cl == 0 ) {
+ /* illegal utf-8 char */
+ return -1;
+ } else if ( (cl == 1) && LDAP_DN_NEEDESCAPE_AD(val->bv_val[ s ]) ) {
+ str[ d++ ] = '\\';
+ }
+ for (; cl--;) {
str[ d++ ] = val->bv_val[ s++ ];
}
}
return( rc );
}
-#ifdef HAVE_TLS
-#include <openssl/x509.h>
-#include <openssl/err.h>
-
-/* Convert a structured DN from an X.509 certificate into an LDAPV3 DN.
- * x509_name must be an (X509_NAME *). If func is non-NULL, the
- * constructed DN will use numeric OIDs to identify attributeTypes,
- * and the func() will be invoked to rewrite the DN with the given
- * flags.
- *
- * Otherwise the DN will use shortNames as defined in the OpenSSL
- * library.
- *
- * It's preferable to let slapd do the OID to attributeType mapping,
- * because the OpenSSL tables are known to have many typos in versions
- * up to (at least) 0.9.6c. However, the LDAP client has no schema tables,
- * so we're forced to use OpenSSL's mapping there.
- * -- Howard Chu 2002-04-18
- */
-
-int
-ldap_X509dn2bv( void *x509_name, struct berval *bv, LDAPDN_rewrite_func *func,
- unsigned flags )
-{
- LDAPDN newDN;
- LDAPRDN newRDN;
- LDAPAVA *newAVA, *baseAVA;
- X509_NAME_ENTRY *ne;
- ASN1_OBJECT *obj;
- ASN1_STRING *str;
- char oids[8192], *oidptr = oids, *oidbuf = NULL;
- void *ptrs[2048];
- int i, j, k = 0, navas, nrdns, rc = LDAP_SUCCESS;
- int set = -1;
- size_t dnsize, oidrem = sizeof(oids), oidsize = 0;
- int csize;
-
- struct berval Val;
-
- assert( bv != NULL );
- bv->bv_len = 0;
- bv->bv_val = NULL;
-
- /* Get the number of AVAs. This is not necessarily the same as
- * the number of RDNs.
- */
- navas = X509_NAME_entry_count( x509_name );
-
- /* Get the last element, to see how many RDNs there are */
- ne = X509_NAME_get_entry( x509_name, navas - 1 );
- nrdns = ne->set + 1;
-
- /* Allocate the DN/RDN/AVA stuff as a single block */
- dnsize = sizeof(LDAPRDN) * (nrdns+1);
- dnsize += sizeof(LDAPAVA *) * (navas+nrdns);
- dnsize += sizeof(LDAPAVA) * navas;
- if (dnsize > sizeof(ptrs)) {
- newDN = (LDAPDN)LDAP_MALLOC( dnsize );
- if ( newDN == NULL )
- return LDAP_NO_MEMORY;
- } else {
- newDN = (LDAPDN)(char *)ptrs;
- }
-
- newDN[nrdns] = NULL;
- newRDN = (LDAPRDN)(newDN + nrdns+1);
- newAVA = (LDAPAVA *)(newRDN + navas + nrdns);
- baseAVA = newAVA;
-
- /* Retrieve RDNs in reverse order; LDAP is backwards from X.500. */
- for ( i = nrdns - 1, j = 0; i >= 0; i-- ) {
- ne = X509_NAME_get_entry( x509_name, i );
- obj = X509_NAME_ENTRY_get_object( ne );
- str = X509_NAME_ENTRY_get_data( ne );
-
- /* If set changed, move to next RDN */
- if ( set != ne->set ) {
- /* If this is not the first time, end the
- * previous RDN and advance.
- */
- if ( j > 0 ) {
- newRDN[k] = NULL;
- newRDN += k+1;
- }
- newDN[j++] = newRDN;
-
- k = 0;
- set = ne->set;
- }
- newAVA->la_private = NULL;
- newAVA->la_flags = LDAP_AVA_STRING;
-
- if ( !func ) {
- int n = OBJ_obj2nid( obj );
-
- if (n == NID_undef)
- goto get_oid;
- newAVA->la_attr.bv_val = (char *)OBJ_nid2sn( n );
- newAVA->la_attr.bv_len = strlen( newAVA->la_attr.bv_val );
-#ifdef HAVE_EBCDIC
- newAVA->la_attr.bv_val = LDAP_STRDUP( newAVA->la_attr.bv_val );
- __etoa( newAVA->la_attr.bv_val );
- newAVA->la_flags |= LDAP_AVA_FREE_ATTR;
-#endif
- } else {
-get_oid: newAVA->la_attr.bv_val = oidptr;
- newAVA->la_attr.bv_len = OBJ_obj2txt( oidptr, oidrem, obj, 1 );
-#ifdef HAVE_EBCDIC
- __etoa( newAVA->la_attr.bv_val );
-#endif
- oidptr += newAVA->la_attr.bv_len + 1;
- oidrem -= newAVA->la_attr.bv_len + 1;
-
- /* Running out of OID buffer space? */
- if (oidrem < 128) {
- if ( oidsize == 0 ) {
- oidsize = sizeof(oids) * 2;
- oidrem = oidsize;
- oidbuf = LDAP_MALLOC( oidsize );
- if ( oidbuf == NULL ) goto nomem;
- oidptr = oidbuf;
- } else {
- char *old = oidbuf;
- oidbuf = LDAP_REALLOC( oidbuf, oidsize*2 );
- if ( oidbuf == NULL ) goto nomem;
- /* Buffer moved! Fix AVA pointers */
- if ( old != oidbuf ) {
- LDAPAVA *a;
- long dif = oidbuf - old;
-
- for (a=baseAVA; a<=newAVA; a++){
- if (a->la_attr.bv_val >= old &&
- a->la_attr.bv_val <= (old + oidsize))
- a->la_attr.bv_val += dif;
- }
- }
- oidptr = oidbuf + oidsize - oidrem;
- oidrem += oidsize;
- oidsize *= 2;
- }
- }
- }
- Val.bv_val = (char *) str->data;
- Val.bv_len = str->length;
- switch( str->type ) {
- case V_ASN1_UNIVERSALSTRING:
- /* This uses 32-bit ISO 10646-1 */
- csize = 4; goto to_utf8;
- case V_ASN1_BMPSTRING:
- /* This uses 16-bit ISO 10646-1 */
- csize = 2; goto to_utf8;
- case V_ASN1_T61STRING:
- /* This uses 8-bit, assume ISO 8859-1 */
- csize = 1;
-to_utf8: rc = ldap_ucs_to_utf8s( &Val, csize, &newAVA->la_value );
- newAVA->la_flags |= LDAP_AVA_FREE_VALUE;
- if (rc != LDAP_SUCCESS) goto nomem;
- newAVA->la_flags = LDAP_AVA_NONPRINTABLE;
- break;
- case V_ASN1_UTF8STRING:
- newAVA->la_flags = LDAP_AVA_NONPRINTABLE;
- /* This is already in UTF-8 encoding */
- case V_ASN1_IA5STRING:
- case V_ASN1_PRINTABLESTRING:
- /* These are always 7-bit strings */
- newAVA->la_value = Val;
- default:
- ;
- }
- newRDN[k] = newAVA;
- newAVA++;
- k++;
- }
- newRDN[k] = NULL;
-
- if ( func ) {
- rc = func( newDN, flags, NULL );
- if ( rc != LDAP_SUCCESS )
- goto nomem;
- }
-
- rc = ldap_dn2bv_x( newDN, bv, LDAP_DN_FORMAT_LDAPV3, NULL );
-
-nomem:
- for (;baseAVA < newAVA; baseAVA++) {
- if (baseAVA->la_flags & LDAP_AVA_FREE_ATTR)
- LDAP_FREE( baseAVA->la_attr.bv_val );
- if (baseAVA->la_flags & LDAP_AVA_FREE_VALUE)
- LDAP_FREE( baseAVA->la_value.bv_val );
- }
-
- if ( oidsize != 0 )
- LDAP_FREE( oidbuf );
- if ( newDN != (LDAPDN)(char *) ptrs )
- LDAP_FREE( newDN );
- return rc;
-}
-#endif /* HAVE_TLS */
-
#ifdef HAVE_OPENSSL_CRL
{0, ATTR_TLS, "TLS_CRLCHECK", NULL, LDAP_OPT_X_TLS_CRLCHECK},
#endif
+#ifdef HAVE_GNUTLS
+ {0, ATTR_TLS, "TLS_CRL", NULL, LDAP_OPT_X_TLS_CRLFILE},
+#endif
#endif
#ifdef HAVE_TLS
gopts->ldo_tls_connect_cb = NULL;
gopts->ldo_tls_connect_arg = NULL;
+ gopts->ldo_tls_require_cert = LDAP_OPT_X_TLS_DEMAND;
#endif
gopts->ldo_valid = LDAP_INITIALIZED;
#include <sasl.h>
#endif
-#define SASL_MAX_BUFF_SIZE 65536
+#define SASL_MAX_BUFF_SIZE (0xffffff)
#define SASL_MIN_BUFF_SIZE 4096
#endif
char *lt_cacertfile;
char *lt_cacertdir;
char *lt_ciphersuite;
+#ifdef HAVE_GNUTLS
+ char *lt_crlfile;
+#endif
};
#endif
#define ldo_tls_cacertfile ldo_tls_info.lt_cacertfile
#define ldo_tls_cacertdir ldo_tls_info.lt_cacertdir
#define ldo_tls_ciphersuite ldo_tls_info.lt_ciphersuite
+#define ldo_tls_crlfile ldo_tls_info.lt_crlfile
int ldo_tls_mode;
int ldo_tls_require_cert;
#ifdef HAVE_OPENSSL_CRL
LDAP_F (LDAPURLDesc *) ldap_url_duplist LDAP_P((
LDAPURLDesc *ludlist ));
-LDAP_F (int) ldap_url_parselist LDAP_P((
- LDAPURLDesc **ludlist,
- const char *url ));
-
LDAP_F (int) ldap_url_parsehosts LDAP_P((
LDAPURLDesc **ludlist,
const char *hosts,
# See ldap.conf(5) for details
# This file should be world readable but not world writable.
-#BASE dc=example, dc=com
+#BASE dc=example,dc=com
#URI ldap://ldap.example.com ldap://ldap-master.example.com:666
#SIZELIMIT 12
#include "ldap-int.h"
#ifdef LDAP_SYNC_TRACE
-/*
- * used for debug purposes
- */
-static char *
-print_UUID( char *buf, size_t len, unsigned char *UUID )
-{
- snprintf( buf, len,
- "%02x%02x%02x%02x-%02x%02x-%02x%02x-"
- "%02x%02x-%02x%02x%02x%02x%02x%02x",
- UUID[0],
- UUID[1],
- UUID[2],
- UUID[3],
- UUID[4],
- UUID[5],
- UUID[6],
- UUID[7],
- UUID[8],
- UUID[9],
- UUID[10],
- UUID[11],
- UUID[12],
- UUID[13],
- UUID[14],
- UUID[15] );
- return buf;
-}
-
static const char *
ldap_sync_state2str( int state )
{
for ( i = 0; syncUUIDs[ i ].bv_val != NULL; i++ ) {
char buf[ BUFSIZ ];
fprintf( stderr, "\t\t%s\n",
- print_UUID( buf, sizeof( buf ),
- (unsigned char *)syncUUIDs[ i ].bv_val ) );
+ lutil_uuidstr_from_normalized(
+ syncUUIDs[ i ].bv_val, syncUUIDs[ i ].bv_len,
+ buf, sizeof( buf ) ) );
}
}
#endif /* LDAP_SYNC_TRACE */
#if defined( notyet ) /* && defined( SO_ERROR ) */
{
int so_errno;
- socklen_t dummy = sizeof(so_errno);
+ ber_socklen_t dummy = sizeof(so_errno);
if ( getsockopt( s, SOL_SOCKET, SO_ERROR, &so_errno, &dummy )
== AC_SOCKET_ERROR )
{
struct sockaddr_in sin;
#endif
char ch;
- socklen_t dummy = sizeof(sin);
+ ber_socklen_t dummy = sizeof(sin);
if ( getpeername( s, (struct sockaddr *) &sin, &dummy )
== AC_SOCKET_ERROR )
{
/* This means the connection failed */
if ( FD_ISSET(s, &efds) ) {
int so_errno;
- int dummy = sizeof(so_errno);
+ ber_socklen_t dummy = sizeof(so_errno);
if ( getsockopt( s, SOL_SOCKET, SO_ERROR,
(char *) &so_errno, &dummy ) == AC_SOCKET_ERROR || !so_errno )
{
static int
ldap_pvt_connect(LDAP *ld, ber_socket_t s,
- struct sockaddr *sin, socklen_t addrlen,
+ struct sockaddr *sin, ber_socklen_t addrlen,
int async)
{
int rc, err;
char *
ldap_host_connected_to( Sockbuf *sb, const char *host )
{
- socklen_t len;
+ ber_socklen_t len;
#ifdef LDAP_PF_INET6
struct sockaddr_storage sabuf;
#else
#if defined( notyet ) /* && defined( SO_ERROR ) */
{
int so_errno;
- socklen_t dummy = sizeof(so_errno);
+ ber_socklen_t dummy = sizeof(so_errno);
if ( getsockopt( s, SOL_SOCKET, SO_ERROR, &so_errno, &dummy )
== AC_SOCKET_ERROR )
{
/* error slippery */
struct sockaddr_un sa;
char ch;
- socklen_t dummy = sizeof(sa);
+ ber_socklen_t dummy = sizeof(sa);
if ( getpeername( s, (struct sockaddr *) &sa, &dummy )
== AC_SOCKET_ERROR )
{
}
#undef TRACE
-#if !defined(HAVE_GETPEEREID) && \
- !defined(HAVE_GETPEERUCRED) && \
- !defined(SO_PEERCRED) && !defined(LOCAL_PEERCRED) && \
- defined(HAVE_SENDMSG) && (defined(HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTSLEN) || \
- defined(HAVE_STRUCT_MSGHDR_MSG_CONTROL))
-#define DO_SENDMSG
+#ifdef LDAP_PF_LOCAL_SENDMSG
static const char abandonPDU[] = {LDAP_TAG_MESSAGE, 6,
LDAP_TAG_MSGID, 1, 0, LDAP_REQ_ABANDON, 1, 0};
#endif
{
if ( ldap_pvt_ndelay_off(ld, s) == -1 ) return -1;
-#ifdef DO_SENDMSG
+#ifdef LDAP_PF_LOCAL_SENDMSG
/* Send a dummy message with access rights. Remote side will
- * obtain our uid/gid by fstat'ing this descriptor.
+ * obtain our uid/gid by fstat'ing this descriptor. The
+ * descriptor permissions must match exactly, and we also
+ * send the socket name, which must also match.
*/
sendcred:
{
int fds[2];
+ ber_socklen_t salen = sizeof(*sa);
if (pipe(fds) == 0) {
/* Abandon, noop, has no reply */
struct iovec iov;
msg.msg_accrights = (char *)fds;
msg.msg_accrightslen = sizeof(int);
# endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
+ getpeername( s, sa, &salen );
+ fchmod( fds[0], S_ISUID|S_IRWXU );
+ write( fds[1], sa, salen );
sendmsg( s, &msg, 0 );
close(fds[0]);
close(fds[1]);
if( fd.revents & POLL_WRITE ) {
if ( ldap_pvt_is_socket_ready(ld, s) == -1 ) return -1;
if ( ldap_pvt_ndelay_off(ld, s) == -1 ) return -1;
-#ifdef DO_SENDMSG
+#ifdef LDAP_PF_LOCAL_SENDMSG
goto sendcred;
#else
return ( 0 );
if ( FD_ISSET(s, &wfds) ) {
if ( ldap_pvt_is_socket_ready(ld, s) == -1 ) return -1;
if ( ldap_pvt_ndelay_off(ld, s) == -1 ) return -1;
-#ifdef DO_SENDMSG
+#ifdef LDAP_PF_LOCAL_SENDMSG
goto sendcred;
#else
return ( 0 );
LDAPControl **ctrlp )
{
struct berval value;
- BerElement *ber;
if ( ctrlp == NULL ) {
ld->ld_errno = LDAP_PARAM_ERROR;
ld->ld_errno = ldap_create_page_control_value( ld,
pagesize, cookie, &value );
if ( ld->ld_errno == LDAP_SUCCESS ) {
- if ((ber = ldap_alloc_ber_with_options(ld)) == NULL) {
- ld->ld_errno = LDAP_NO_MEMORY;
- return LDAP_NO_MEMORY;
- }
-
- ld->ld_errno = ldap_create_control( LDAP_CONTROL_PAGEDRESULTS,
- ber, iscritical, ctrlp );
- if ( ld->ld_errno == LDAP_SUCCESS ) {
- (*ctrlp)->ldctl_value = value;
- } else {
+ ld->ld_errno = ldap_control_create( LDAP_CONTROL_PAGEDRESULTS,
+ iscritical, &value, 0, ctrlp );
+ if ( ld->ld_errno != LDAP_SUCCESS ) {
LDAP_FREE( value.bv_val );
}
- ber_free(ber, 1);
}
return ld->ld_errno;
return ld->ld_errno;
}
- c = ldap_find_control( LDAP_CONTROL_PAGEDRESULTS, ctrls );
+ c = ldap_control_find( LDAP_CONTROL_PAGEDRESULTS, ctrls, NULL );
if ( c == NULL ) {
/* No page control was found. */
ld->ld_errno = LDAP_CONTROL_NOT_FOUND;
ldap_create_passwordpolicy_control( LDAP *ld,
LDAPControl **ctrlp )
{
- BerElement *ber;
-
assert( ld != NULL );
assert( LDAP_VALID( ld ) );
assert( ctrlp != NULL );
- if ((ber = ldap_alloc_ber_with_options(ld)) == NULL) {
- ld->ld_errno = LDAP_NO_MEMORY;
- return(LDAP_NO_MEMORY);
- }
-
- ld->ld_errno = ldap_create_control( LDAP_CONTROL_PASSWORDPOLICYREQUEST,
- ber, 0, ctrlp);
+ ld->ld_errno = ldap_control_create( LDAP_CONTROL_PASSWORDPOLICYREQUEST,
+ 0, NULL, 0, ctrlp );
- ber_free(ber, 1);
- return(ld->ld_errno);
+ return ld->ld_errno;
}
ld (IN) An LDAP session handle.
ctrl (IN) The address of an
- LDAPControl structure, typically obtained
- by a call to ldap_find_control().
+ LDAPControl structure, either obtained
+ by running thorugh the list of response controls or
+ by a call to ldap_control_find().
exptimep (OUT) This result parameter is filled in with the number of seconds before
the password will expire, if expiration is imminent
use_connection( ld, lc );
+#ifdef LDAP_CONNECTIONLESS
+ if ( LDAP_IS_UDP( ld )) {
+ BerElement tmpber = *ber;
+ ber_rewind( &tmpber );
+ rc = ber_write( &tmpber, ld->ld_options.ldo_peer,
+ sizeof( struct sockaddr ), 0 );
+ if ( rc == -1 ) {
+ ld->ld_errno = LDAP_ENCODING_ERROR;
+ return rc;
+ }
+ }
+#endif
+
/* If we still have an incomplete write, try to finish it before
* dealing with the new request. If we don't finish here, return
* LDAP_BUSY and let the caller retry later. We only allow a single
async = LDAP_BOOL_GET( &ld->ld_options, LDAP_BOOL_CONNECT_ASYNC );
for ( srvp = srvlist; *srvp != NULL; srvp = &(*srvp)->lud_next ) {
- if ( ldap_int_open_connection( ld, lc, *srvp, async) != -1 )
- {
+ int rc;
+
+ rc = ldap_int_open_connection( ld, lc, *srvp, async );
+ if ( rc != -1 ) {
srv = *srvp;
- if ( ld->ld_urllist_proc ) {
+ if ( ld->ld_urllist_proc && ( !async || rc != -2 ) ) {
ld->ld_urllist_proc( ld, srvlist, srvp, ld->ld_urllist_params );
}
++lc->lconn_refcnt; /* avoid premature free */
ld->ld_defconn = lc;
- Debug( LDAP_DEBUG_TRACE, "anonymous rebind via ldap_bind_s\n", 0, 0, 0);
+ Debug( LDAP_DEBUG_TRACE,
+ "anonymous rebind via ldap_sasl_bind(\"\")\n",
+ 0, 0, 0);
+
#ifdef LDAP_R_COMPILE
ldap_pvt_thread_mutex_unlock( &ld->ld_req_mutex );
ldap_pvt_thread_mutex_unlock( &ld->ld_res_mutex );
break;
default:
- assert( 0 );
+ Debug( LDAP_DEBUG_TRACE,
+ "ldap_new_connection %p: "
+ "unexpected response %d "
+ "from BIND request id=%d\n",
+ (void *) ld, ldap_msgtype( res ), msgid );
+ err = -1;
+ break;
}
}
}
if ( lp == origreq ) {
lp = lp->lr_child;
} else {
- lp = lr->lr_refnext;
+ lp = lp->lr_refnext;
}
}
if ( looped ) {
int rc;
struct timeval tv = { 0 },
tv0 = { 0 },
- *tvp;
- time_t start_time = 0;
- time_t tmp_time;
+ start_time_tv = { 0 },
+ *tvp = NULL;
LDAPConn *lc;
assert( ld != NULL );
}
#endif /* LDAP_DEBUG */
- if ( timeout == NULL ) {
- tvp = NULL;
- } else {
+ if ( timeout != NULL ) {
tv0 = *timeout;
tv = *timeout;
tvp = &tv;
- start_time = time( NULL );
+#ifdef HAVE_GETTIMEOFDAY
+ gettimeofday( &start_time_tv, NULL );
+#else /* ! HAVE_GETTIMEOFDAY */
+ time( &start_time_tv.tv_sec );
+ start_time_tv.tv_usec = 0;
+#endif /* ! HAVE_GETTIMEOFDAY */
}
rc = LDAP_MSG_X_KEEP_LOOKING;
}
if ( rc == LDAP_MSG_X_KEEP_LOOKING && tvp != NULL ) {
- tmp_time = time( NULL );
- tv0.tv_sec -= ( tmp_time - start_time );
- if ( tv0.tv_sec <= 0 ) {
- rc = 0; /* timed out */
+ struct timeval curr_time_tv = { 0 },
+ delta_time_tv = { 0 };
+
+#ifdef HAVE_GETTIMEOFDAY
+ gettimeofday( &curr_time_tv, NULL );
+#else /* ! HAVE_GETTIMEOFDAY */
+ time( &curr_time_tv.tv_sec );
+ curr_time_tv.tv_usec = 0;
+#endif /* ! HAVE_GETTIMEOFDAY */
+
+ /* delta_time = tmp_time - start_time */
+ delta_time_tv.tv_sec = curr_time_tv.tv_sec - start_time_tv.tv_sec;
+ delta_time_tv.tv_usec = curr_time_tv.tv_usec - start_time_tv.tv_usec;
+ if ( delta_time_tv.tv_usec < 0 ) {
+ delta_time_tv.tv_sec--;
+ delta_time_tv.tv_usec += 1000000;
+ }
+
+ /* tv0 < delta_time ? */
+ if ( ( tv0.tv_sec < delta_time_tv.tv_sec ) ||
+ ( ( tv0.tv_sec == delta_time_tv.tv_sec ) && ( tv0.tv_usec < delta_time_tv.tv_usec ) ) )
+ {
+ rc = 0; /* timed out */
ld->ld_errno = LDAP_TIMEOUT;
break;
}
+
+ /* tv0 -= delta_time */
+ tv0.tv_sec -= delta_time_tv.tv_sec;
+ tv0.tv_usec -= delta_time_tv.tv_usec;
+ if ( tv0.tv_usec < 0 ) {
+ tv0.tv_sec--;
+ tv0.tv_usec += 1000000;
+ }
+
tv.tv_sec = tv0.tv_sec;
+ tv.tv_usec = tv0.tv_usec;
+
+ Debug( LDAP_DEBUG_TRACE, "wait4msg ld %p %ld s %ld us to go\n",
+ (void *)ld, (long) tv.tv_sec, (long) tv.tv_usec );
- Debug( LDAP_DEBUG_TRACE, "wait4msg ld %p %ld secs to go\n",
- (void *)ld, (long) tv.tv_sec, 0 );
- start_time = tmp_time;
+ start_time_tv.tv_sec = curr_time_tv.tv_sec;
+ start_time_tv.tv_usec = curr_time_tv.tv_usec;
}
}
LDAP_NEXT_MSGID( ld, *idp );
#ifdef LDAP_CONNECTIONLESS
if ( LDAP_IS_UDP(ld) ) {
- err = ber_write( ber, ld->ld_options.ldo_peer,
- sizeof(struct sockaddr), 0);
+ struct sockaddr sa = {0};
+ /* dummy, filled with ldo_peer in request.c */
+ err = ber_write( ber, &sa, sizeof( sa ), 0 );
}
if ( LDAP_IS_UDP(ld) && ld->ld_options.ldo_version == LDAP_VERSION2) {
char *dn = ld->ld_options.ldo_cldapdn;
LDAPControl **ctrlp )
{
struct berval value;
- BerElement *ber;
assert( ld != NULL );
assert( LDAP_VALID( ld ) );
- if ( ld == NULL ) return LDAP_PARAM_ERROR;
+ if ( ld == NULL ) {
+ return LDAP_PARAM_ERROR;
+ }
+
if ( ctrlp == NULL ) {
ld->ld_errno = LDAP_PARAM_ERROR;
return ld->ld_errno;
ld->ld_errno = ldap_create_sort_control_value( ld, keyList, &value );
if ( ld->ld_errno == LDAP_SUCCESS ) {
- if ((ber = ldap_alloc_ber_with_options(ld)) == NULL) {
- ld->ld_errno = LDAP_NO_MEMORY;
- return LDAP_NO_MEMORY;
- }
-
- ld->ld_errno = ldap_create_control( LDAP_CONTROL_SORTREQUEST,
- ber, isCritical, ctrlp );
- if ( ld->ld_errno == LDAP_SUCCESS ) {
- (*ctrlp)->ldctl_value = value;
- } else {
+ ld->ld_errno = ldap_control_create( LDAP_CONTROL_SORTREQUEST,
+ isCritical, &value, 0, ctrlp );
+ if ( ld->ld_errno != LDAP_SUCCESS ) {
LDAP_FREE( value.bv_val );
}
- ber_free(ber, 1);
}
return ld->ld_errno;
--- /dev/null
+/* $OpenLDAP$ */
+/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
+ *
+ * Copyright 1998-2007 The OpenLDAP Foundation.
+ * Portions Copyright 2007 Pierangelo Masarati.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted only as authorized by the OpenLDAP
+ * Public License.
+ *
+ * A copy of this license is available in the file LICENSE in the
+ * top-level directory of the distribution or, alternatively, at
+ * <http://www.OpenLDAP.org/license.html>.
+ */
+/* ACKNOWLEDGEMENTS:
+ * This work was developed by Pierangelo Masarati for inclusion in
+ * OpenLDAP Software.
+ */
+
+#include "portable.h"
+
+#include <stdio.h>
+#include <ac/stdlib.h>
+#include <ac/string.h>
+#include <ac/time.h>
+
+#include "ldap-int.h"
+
+#ifdef LDAP_CONTROL_X_SESSION_TRACKING
+
+/*
+ * Client-side of <draft-wahl-ldap-session-03>
+ */
+
+int
+ldap_create_session_tracking_value(
+ LDAP *ld,
+ char *sessionSourceIp,
+ char *sessionSourceName,
+ char *formatOID,
+ struct berval *sessionTrackingIdentifier,
+ struct berval *value )
+{
+ BerElement *ber = NULL;
+ ber_tag_t tag;
+
+ struct berval ip, name, oid, id;
+
+ if ( ld == NULL ||
+ formatOID == NULL ||
+ value == NULL )
+ {
+param_error:;
+ if ( ld ) {
+ ld->ld_errno = LDAP_PARAM_ERROR;
+ }
+
+ return LDAP_PARAM_ERROR;
+ }
+
+ assert( LDAP_VALID( ld ) );
+
+ /* check sizes according to I.D. */
+ if ( sessionSourceIp == NULL ) {
+ BER_BVSTR( &ip, "" );
+
+ } else {
+ ber_str2bv( sessionSourceIp, 0, 0, &ip );
+ /* NOTE: we're strict because we don't want
+ * to send out bad data */
+ if ( ip.bv_len > 128 ) goto param_error;
+ }
+
+ if ( sessionSourceName == NULL ) {
+ BER_BVSTR( &name, "" );
+
+ } else {
+ ber_str2bv( sessionSourceName, 0, 0, &name );
+ /* NOTE: we're strict because we don't want
+ * to send out bad data */
+ if ( name.bv_len > 65536 ) goto param_error;
+ }
+
+ ber_str2bv( formatOID, 0, 0, &oid );
+ /* NOTE: we're strict because we don't want
+ * to send out bad data */
+ if ( oid.bv_len > 1024 ) goto param_error;
+
+ if ( sessionTrackingIdentifier == NULL ||
+ sessionTrackingIdentifier->bv_val == NULL )
+ {
+ BER_BVSTR( &id, "" );
+
+ } else {
+ id = *sessionTrackingIdentifier;
+ }
+
+ /* prepare value */
+ value->bv_val = NULL;
+ value->bv_len = 0;
+
+ ber = ldap_alloc_ber_with_options( ld );
+ if ( ber == NULL ) {
+ ld->ld_errno = LDAP_NO_MEMORY;
+ return ld->ld_errno;
+ }
+
+ tag = ber_printf( ber, "{OOOO}", &ip, &name, &oid, &id );
+ if ( tag == LBER_ERROR ) {
+ ld->ld_errno = LDAP_ENCODING_ERROR;
+ goto done;
+ }
+
+ if ( ber_flatten2( ber, value, 1 ) == -1 ) {
+ ld->ld_errno = LDAP_NO_MEMORY;
+ }
+
+done:;
+ if ( ber != NULL ) {
+ ber_free( ber, 1 );
+ }
+
+ return ld->ld_errno;
+}
+
+/*
+ * NOTE: this API is bad; it could be much more efficient...
+ */
+int
+ldap_create_session_tracking_control(
+ LDAP *ld,
+ char *sessionSourceIp,
+ char *sessionSourceName,
+ char *formatOID,
+ struct berval *sessionTrackingIdentifier,
+ LDAPControl **ctrlp )
+{
+ struct berval value;
+
+ if ( ctrlp == NULL ) {
+ ld->ld_errno = LDAP_PARAM_ERROR;
+ return ld->ld_errno;
+ }
+
+ ld->ld_errno = ldap_create_session_tracking_value( ld,
+ sessionSourceIp, sessionSourceName, formatOID,
+ sessionTrackingIdentifier, &value );
+ if ( ld->ld_errno == LDAP_SUCCESS ) {
+ ld->ld_errno = ldap_control_create( LDAP_CONTROL_X_SESSION_TRACKING,
+ 0, &value, 0, ctrlp );
+ if ( ld->ld_errno != LDAP_SUCCESS ) {
+ LDAP_FREE( value.bv_val );
+ }
+ }
+
+ return ld->ld_errno;
+}
+
+int
+ldap_parse_session_tracking_control(
+ LDAP *ld,
+ LDAPControl *ctrl,
+ struct berval *ip,
+ struct berval *name,
+ struct berval *oid,
+ struct berval *id )
+{
+ BerElement *ber;
+ ber_tag_t tag;
+ ber_len_t len;
+
+ if ( ld == NULL ||
+ ctrl == NULL ||
+ ip == NULL ||
+ name == NULL ||
+ oid == NULL ||
+ id == NULL )
+ {
+ if ( ld ) {
+ ld->ld_errno = LDAP_PARAM_ERROR;
+ }
+
+ /* NOTE: we want the caller to get all or nothing;
+ * we could allow some of the pointers to be NULL,
+ * if one does not want part of the data */
+ return LDAP_PARAM_ERROR;
+ }
+
+ BER_BVZERO( ip );
+ BER_BVZERO( name );
+ BER_BVZERO( oid );
+ BER_BVZERO( id );
+
+ ber = ber_init( &ctrl->ldctl_value );
+
+ if ( ber == NULL ) {
+ ld->ld_errno = LDAP_NO_MEMORY;
+ return ld->ld_errno;
+ }
+
+ tag = ber_skip_tag( ber, &len );
+ if ( tag != LBER_SEQUENCE ) {
+ tag = LBER_ERROR;
+ goto error;
+ }
+
+ /* sessionSourceIp */
+ tag = ber_peek_tag( ber, &len );
+ if ( tag == LBER_DEFAULT ) {
+ tag = LBER_ERROR;
+ goto error;
+ }
+
+ if ( len == 0 ) {
+ tag = ber_skip_tag( ber, &len );
+
+ } else {
+ if ( len > 128 ) {
+ /* should be LDAP_DECODING_ERROR,
+ * but we're liberal in what we accept */
+ }
+ tag = ber_scanf( ber, "o", ip );
+ }
+
+ /* sessionSourceName */
+ tag = ber_peek_tag( ber, &len );
+ if ( tag == LBER_DEFAULT ) {
+ tag = LBER_ERROR;
+ goto error;
+ }
+
+ if ( len == 0 ) {
+ tag = ber_skip_tag( ber, &len );
+
+ } else {
+ if ( len > 65536 ) {
+ /* should be LDAP_DECODING_ERROR,
+ * but we're liberal in what we accept */
+ }
+ tag = ber_scanf( ber, "o", name );
+ }
+
+ /* formatOID */
+ tag = ber_peek_tag( ber, &len );
+ if ( tag == LBER_DEFAULT ) {
+ tag = LBER_ERROR;
+ goto error;
+ }
+
+ if ( len == 0 ) {
+ ld->ld_errno = LDAP_DECODING_ERROR;
+ goto error;
+
+ } else {
+ if ( len > 1024 ) {
+ /* should be LDAP_DECODING_ERROR,
+ * but we're liberal in what we accept */
+ }
+ tag = ber_scanf( ber, "o", oid );
+ }
+
+ /* FIXME: should check if it is an OID... leave it to the caller */
+
+ /* sessionTrackingIdentifier */
+ tag = ber_peek_tag( ber, &len );
+ if ( tag == LBER_DEFAULT ) {
+ tag = LBER_ERROR;
+ goto error;
+ }
+
+ if ( len == 0 ) {
+ tag = ber_skip_tag( ber, &len );
+
+ } else {
+#if 0
+ if ( len > 65536 ) {
+ /* should be LDAP_DECODING_ERROR,
+ * but we're liberal in what we accept */
+ }
+#endif
+ tag = ber_scanf( ber, "o", id );
+ }
+
+ /* closure */
+ tag = ber_skip_tag( ber, &len );
+ if ( tag == LBER_DEFAULT && len == 0 ) {
+ tag = 0;
+ }
+
+error:;
+ (void)ber_free( ber, 1 );
+
+ if ( tag == LBER_ERROR ) {
+ return LDAP_DECODING_ERROR;
+ }
+
+ return ld->ld_errno;
+}
+
+#endif /* LDAP_CONTROL_X_SESSION_TRACKING */
char passwd[64], dn[256], rdn[64], attr[64], value[256];
char filter[256], *host, **types;
char **exdn;
- char *usage = "usage: %s [-u] [-h host] [-d level] [-s dnsuffix] [-p port] [-t file] [-T file]\n";
+ static const char usage[] =
+ "usage: %s [-u] [-h host] [-d level] [-s dnsuffix] [-p port] [-t file] [-T file]\n";
int bound, all, scope, attrsonly;
LDAPMessage *res;
LDAPMod **mods, **attrs;
-/* tls.c - Handle tls/ssl using SSLeay or OpenSSL. */
+/* tls.c - Handle tls/ssl using SSLeay, OpenSSL or GNUTLS. */
/* $OpenLDAP$ */
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
*
* top-level directory of the distribution or, alternatively, at
* <http://www.OpenLDAP.org/license.html>.
*/
+/* ACKNOWLEDGEMENTS: GNUTLS support written by Howard Chu and
+ * Matt Backes; sponsored by The Written Word (thewrittenword.com)
+ * and Stanford University (stanford.edu).
+ */
#include "portable.h"
#include "ldap_config.h"
#include <ldap_pvt_thread.h>
#endif
+#ifdef HAVE_GNUTLS
+#include <gnutls/gnutls.h>
+#include <gnutls/x509.h>
+#include <gcrypt.h>
+
+#define DH_BITS (1024)
+
+#else
#ifdef HAVE_OPENSSL_SSL_H
#include <openssl/ssl.h>
#include <openssl/x509v3.h>
#elif defined( HAVE_SSL_H )
#include <ssl.h>
#endif
-
-static int tls_opt_trace = 1;
-static char *tls_opt_randfile = NULL;
+#endif
#define HAS_TLS( sb ) ber_sockbuf_ctrl( sb, LBER_SB_OPT_HAS_IO, \
(void *)&sb_tls_sbio )
+#endif /* HAVE_TLS */
+
+/* RFC2459 minimum required set of supported attribute types
+ * in a certificate DN
+ */
+typedef struct oid_name {
+ struct berval oid;
+ struct berval name;
+} oid_name;
+
+#define CN_OID oids[0].oid.bv_val
+
+static oid_name oids[] = {
+ { BER_BVC("2.5.4.3"), BER_BVC("cn") },
+ { BER_BVC("2.5.4.4"), BER_BVC("sn") },
+ { BER_BVC("2.5.4.6"), BER_BVC("c") },
+ { BER_BVC("2.5.4.7"), BER_BVC("l") },
+ { BER_BVC("2.5.4.8"), BER_BVC("st") },
+ { BER_BVC("2.5.4.10"), BER_BVC("o") },
+ { BER_BVC("2.5.4.11"), BER_BVC("ou") },
+ { BER_BVC("2.5.4.12"), BER_BVC("title") },
+ { BER_BVC("2.5.4.41"), BER_BVC("name") },
+ { BER_BVC("2.5.4.42"), BER_BVC("givenName") },
+ { BER_BVC("2.5.4.43"), BER_BVC("initials") },
+ { BER_BVC("2.5.4.44"), BER_BVC("generationQualifier") },
+ { BER_BVC("2.5.4.46"), BER_BVC("dnQualifier") },
+ { BER_BVC("1.2.840.113549.1.9.1"), BER_BVC("email") },
+ { BER_BVC("0.9.2342.19200300.100.1.25"), BER_BVC("dc") },
+ { BER_BVNULL, BER_BVNULL }
+};
+
+#ifdef HAVE_TLS
+#ifdef HAVE_GNUTLS
+
+typedef struct tls_cipher_suite {
+ const char *name;
+ gnutls_kx_algorithm_t kx;
+ gnutls_cipher_algorithm_t cipher;
+ gnutls_mac_algorithm_t mac;
+ gnutls_protocol_t version;
+} tls_cipher_suite;
+
+static tls_cipher_suite *ciphers;
+static int n_ciphers;
+
+/* sorta replacing SSL_CTX */
+typedef struct tls_ctx {
+ struct ldapoptions *lo;
+ gnutls_certificate_credentials_t cred;
+ gnutls_dh_params_t dh_params;
+ unsigned long verify_depth;
+ int refcount;
+ int *kx_list;
+ int *cipher_list;
+ int *mac_list;
+#ifdef LDAP_R_COMPILE
+ ldap_pvt_thread_mutex_t ref_mutex;
+#endif
+} tls_ctx;
+
+/* sorta replacing SSL */
+typedef struct tls_session {
+ tls_ctx *ctx;
+ gnutls_session_t session;
+ struct berval peer_der_dn;
+} tls_session;
+
+#ifdef LDAP_R_COMPILE
+
+static int
+ldap_pvt_gcry_mutex_init( void **priv )
+{
+ int err = 0;
+ ldap_pvt_thread_mutex_t *lock = LDAP_MALLOC( sizeof( ldap_pvt_thread_mutex_t ));
+
+ if ( !lock )
+ err = ENOMEM;
+ if ( !err ) {
+ err = ldap_pvt_thread_mutex_init( lock );
+ if ( err )
+ LDAP_FREE( lock );
+ else
+ *priv = lock;
+ }
+ return err;
+}
+static int
+ldap_pvt_gcry_mutex_destroy( void **lock )
+{
+ int err = ldap_pvt_thread_mutex_destroy( *lock );
+ LDAP_FREE( *lock );
+ return err;
+}
+static int
+ldap_pvt_gcry_mutex_lock( void **lock )
+{
+ return ldap_pvt_thread_mutex_lock( *lock );
+}
+static int
+ldap_pvt_gcry_mutex_unlock( void **lock )
+{
+ return ldap_pvt_thread_mutex_unlock( *lock );
+}
+
+static struct gcry_thread_cbs ldap_generic_thread_cbs = {
+ GCRY_THREAD_OPTION_USER,
+ NULL,
+ ldap_pvt_gcry_mutex_init,
+ ldap_pvt_gcry_mutex_destroy,
+ ldap_pvt_gcry_mutex_lock,
+ ldap_pvt_gcry_mutex_unlock,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+static void
+tls_init_threads( void )
+{
+ gcry_control (GCRYCTL_SET_THREAD_CBS, &ldap_generic_thread_cbs);
+}
+#endif /* LDAP_R_COMPILE */
+
+void
+ldap_pvt_tls_ctx_free ( void *c )
+{
+ int refcount;
+ tls_ctx *ctx = c;
+
+ if ( !ctx ) return;
+
+#ifdef LDAP_R_COMPILE
+ ldap_pvt_thread_mutex_lock( &ctx->ref_mutex );
+#endif
+ refcount = --ctx->refcount;
+#ifdef LDAP_R_COMPILE
+ ldap_pvt_thread_mutex_unlock( &ctx->ref_mutex );
+#endif
+ if ( refcount )
+ return;
+ LDAP_FREE( ctx->kx_list );
+ gnutls_certificate_free_credentials( ctx->cred );
+ ber_memfree ( ctx );
+}
+
+static void *
+tls_ctx_new ( struct ldapoptions *lo )
+{
+ tls_ctx *ctx;
+
+ ctx = ber_memcalloc ( 1, sizeof (*ctx) );
+ if ( ctx ) {
+ ctx->lo = lo;
+ if ( gnutls_certificate_allocate_credentials( &ctx->cred )) {
+ ber_memfree( ctx );
+ return NULL;
+ }
+ ctx->refcount = 1;
+#ifdef LDAP_R_COMPILE
+ ldap_pvt_thread_mutex_init( &ctx->ref_mutex );
+#endif
+ }
+ return ctx;
+}
+
+static void
+tls_ctx_ref( tls_ctx *ctx )
+{
+#ifdef LDAP_R_COMPILE
+ ldap_pvt_thread_mutex_lock( &ctx->ref_mutex );
+#endif
+ ctx->refcount++;
+#ifdef LDAP_R_COMPILE
+ ldap_pvt_thread_mutex_unlock( &ctx->ref_mutex );
+#endif
+}
+
+tls_session *
+tls_session_new ( tls_ctx * ctx, int is_server )
+{
+ tls_session *session;
+
+ session = ber_memcalloc ( 1, sizeof (*session) );
+ if ( !session )
+ return NULL;
+
+ session->ctx = ctx;
+ gnutls_init( &session->session, is_server ? GNUTLS_SERVER : GNUTLS_CLIENT );
+ gnutls_set_default_priority( session->session );
+ if ( ctx->kx_list ) {
+ gnutls_kx_set_priority( session->session, ctx->kx_list );
+ gnutls_cipher_set_priority( session->session, ctx->cipher_list );
+ gnutls_mac_set_priority( session->session, ctx->mac_list );
+ }
+ if ( ctx->cred )
+ gnutls_credentials_set( session->session, GNUTLS_CRD_CERTIFICATE, ctx->cred );
+
+ if ( is_server ) {
+ int flag = 0;
+ if ( ctx->lo->ldo_tls_require_cert ) {
+ flag = GNUTLS_CERT_REQUEST;
+ if ( ctx->lo->ldo_tls_require_cert == LDAP_OPT_X_TLS_DEMAND ||
+ ctx->lo->ldo_tls_require_cert == LDAP_OPT_X_TLS_HARD )
+ flag = GNUTLS_CERT_REQUIRE;
+ gnutls_certificate_server_set_request( session->session, flag );
+ }
+ }
+ return session;
+}
+
+void
+tls_session_free ( tls_session * session )
+{
+ ber_memfree ( session );
+}
+
+#define tls_session_connect( ssl ) gnutls_handshake( ssl->session )
+#define tls_session_accept( ssl ) gnutls_handshake( ssl->session )
+
+/* suites is a string of colon-separated cipher suite names. */
+static int
+tls_parse_ciphers( tls_ctx *ctx, char *suites )
+{
+ char *ptr, *end;
+ int i, j, len, num;
+ int *list, nkx = 0, ncipher = 0, nmac = 0;
+ int *kx, *cipher, *mac;
+
+ num = 0;
+ ptr = suites;
+ do {
+ end = strchr(ptr, ':');
+ if ( end )
+ len = end - ptr;
+ else
+ len = strlen(ptr);
+ for (i=0; i<n_ciphers; i++) {
+ if ( !strncasecmp( ciphers[i].name, ptr, len )) {
+ num++;
+ break;
+ }
+ }
+ if ( i == n_ciphers ) {
+ /* unrecognized cipher suite */
+ return -1;
+ }
+ } while (end);
+
+ /* Space for all 3 lists */
+ list = LDAP_MALLOC( (num+1) * sizeof(int) * 3 );
+ if ( !list )
+ return -1;
+ kx = list;
+ cipher = kx+num+1;
+ mac = cipher+num+1;
+
+ ptr = suites;
+ do {
+ end = strchr(ptr, ':');
+ if ( end )
+ len = end - ptr;
+ else
+ len = strlen(ptr);
+ for (i=0; i<n_ciphers; i++) {
+ /* For each cipher suite, insert its algorithms into
+ * their respective priority lists. Make sure they
+ * only appear once in each list.
+ */
+ if ( !strncasecmp( ciphers[i].name, ptr, len )) {
+ for (j=0; j<nkx; j++)
+ if ( kx[j] == ciphers[i].kx )
+ break;
+ if ( j == nkx )
+ kx[nkx++] = ciphers[i].kx;
+ for (j=0; j<ncipher; j++)
+ if ( cipher[j] == ciphers[i].cipher )
+ break;
+ if ( j == ncipher )
+ cipher[ncipher++] = ciphers[i].cipher;
+ for (j=0; j<nmac; j++)
+ if ( mac[j] == ciphers[i].mac )
+ break;
+ if ( j == nmac )
+ mac[nmac++] = ciphers[i].mac;
+ break;
+ }
+ }
+ } while (end);
+ kx[nkx] = 0;
+ cipher[ncipher] = 0;
+ mac[nmac] = 0;
+ ctx->kx_list = kx;
+ ctx->cipher_list = cipher;
+ ctx->mac_list = mac;
+ return 0;
+}
+
+#else /* OpenSSL */
+
+typedef SSL_CTX tls_ctx;
+typedef SSL tls_session;
+
+static int tls_opt_trace = 1;
+static char *tls_opt_randfile = NULL;
+
static void tls_report_error( void );
static void tls_info_cb( const SSL *ssl, int where, int ret );
static int tls_verify_cb( int ok, X509_STORE_CTX *ctx );
static int tls_verify_ok( int ok, X509_STORE_CTX *ctx );
static RSA * tls_tmp_rsa_cb( SSL *ssl, int is_export, int key_length );
-static STACK_OF(X509_NAME) * get_ca_list( char * bundle, char * dir );
static DH * tls_tmp_dh_cb( SSL *ssl, int is_export, int key_length );
}
}
-/*
- * an extra mutex for the default ctx.
- */
+static unsigned long tls_thread_self( void )
+{
+ /* FIXME: CRYPTO_set_id_callback only works when ldap_pvt_thread_t
+ * is an integral type that fits in an unsigned long
+ */
-static ldap_pvt_thread_mutex_t tls_def_ctx_mutex;
-static ldap_pvt_thread_mutex_t tls_connect_mutex;
+ /* force an error if the ldap_pvt_thread_t type is too large */
+ enum { ok = sizeof( ldap_pvt_thread_t ) <= sizeof( unsigned long ) };
+ typedef struct { int dummy: ok ? 1 : -1; } Check[ok ? 1 : -1];
+
+ return (unsigned long) ldap_pvt_thread_self();
+}
static void tls_init_threads( void )
{
ldap_pvt_thread_mutex_init( &tls_mutexes[i] );
}
CRYPTO_set_locking_callback( tls_locking_cb );
- CRYPTO_set_id_callback( ldap_pvt_thread_self );
- /* FIXME: CRYPTO_set_id_callback only works when ldap_pvt_thread_t
- * is an integral type that fits in an unsigned long
- */
-
- ldap_pvt_thread_mutex_init( &tls_def_ctx_mutex );
- ldap_pvt_thread_mutex_init( &tls_connect_mutex );
+ CRYPTO_set_id_callback( tls_thread_self );
}
#endif /* LDAP_R_COMPILE */
+void
+ldap_pvt_tls_ctx_free ( void *c )
+{
+
+ SSL_CTX_free( c );
+}
+
+static void *
+tls_ctx_new( struct ldapoptions *lo )
+{
+ return SSL_CTX_new( SSLv23_method() );
+}
+
+static void
+tls_ctx_ref( void *c )
+{
+ SSL_CTX *ctx = c;
+ CRYPTO_add( &ctx->references, 1, CRYPTO_LOCK_SSL_CTX );
+}
+
+static tls_session *
+tls_session_new( tls_ctx *ctx, int is_server )
+{
+ return SSL_new( ctx );
+}
+
+#define tls_session_connect( ssl ) SSL_connect( ssl )
+#define tls_session_accept( ssl ) SSL_accept( ssl )
+
+static STACK_OF(X509_NAME) *
+get_ca_list( char * bundle, char * dir )
+{
+ STACK_OF(X509_NAME) *ca_list = NULL;
+
+ if ( bundle ) {
+ ca_list = SSL_load_client_CA_file( bundle );
+ }
+#if defined(HAVE_DIRENT_H) || defined(dirent)
+ if ( dir ) {
+ int freeit = 0;
+
+ if ( !ca_list ) {
+ ca_list = sk_X509_NAME_new_null();
+ freeit = 1;
+ }
+ if ( !SSL_add_dir_cert_subjects_to_stack( ca_list, dir ) &&
+ freeit ) {
+ sk_X509_NAME_free( ca_list );
+ ca_list = NULL;
+ }
+ }
+#endif
+ return ca_list;
+}
+
+#endif /* HAVE_GNUTLS */
+
+#ifdef LDAP_R_COMPILE
+/*
+ * an extra mutex for the default ctx.
+ */
+static ldap_pvt_thread_mutex_t tls_def_ctx_mutex;
+#endif
+
void
ldap_int_tls_destroy( struct ldapoptions *lo )
{
if ( lo->ldo_tls_ctx ) {
- SSL_CTX_free( lo->ldo_tls_ctx );
+ ldap_pvt_tls_ctx_free( lo->ldo_tls_ctx );
lo->ldo_tls_ctx = NULL;
}
LDAP_FREE( lo->ldo_tls_ciphersuite );
lo->ldo_tls_ciphersuite = NULL;
}
+#ifdef HAVE_GNUTLS
+ if ( lo->ldo_tls_crlfile ) {
+ LDAP_FREE( lo->ldo_tls_crlfile );
+ lo->ldo_tls_crlfile = NULL;
+ }
+#endif
}
/*
ldap_int_tls_destroy( lo );
+#ifdef HAVE_GNUTLS
+ LDAP_FREE( ciphers );
+ ciphers = NULL;
+
+ gnutls_global_deinit();
+#else
EVP_cleanup();
ERR_remove_state(0);
ERR_free_strings();
LDAP_FREE( tls_opt_randfile );
tls_opt_randfile = NULL;
}
+#endif
}
/*
if ( tls_initialized++ ) return 0;
+#ifdef LDAP_R_COMPILE
+ tls_init_threads();
+ ldap_pvt_thread_mutex_init( &tls_def_ctx_mutex );
+#endif
+
+#ifdef HAVE_GNUTLS
+ gnutls_global_init ();
+
+ /* GNUtls cipher suite handling: The library ought to parse suite
+ * names for us, but it doesn't. It will return a list of suite names
+ * that it supports, so we can do parsing ourselves. It ought to tell
+ * us how long the list is, but it doesn't do that either, so we just
+ * have to count it manually...
+ */
+ {
+ int i = 0;
+ tls_cipher_suite *ptr, tmp;
+ char cs_id[2];
+
+ while ( gnutls_cipher_suite_info( i, cs_id, &tmp.kx, &tmp.cipher,
+ &tmp.mac, &tmp.version ))
+ i++;
+ n_ciphers = i;
+
+ /* Store a copy */
+ ciphers = LDAP_MALLOC(n_ciphers * sizeof(tls_cipher_suite));
+ if ( !ciphers )
+ return -1;
+ for ( i=0; i<n_ciphers; i++ ) {
+ ciphers[i].name = gnutls_cipher_suite_info( i, cs_id,
+ &ciphers[i].kx, &ciphers[i].cipher, &ciphers[i].mac,
+ &ciphers[i].version );
+ }
+ }
+
+#else /* !HAVE_GNUTLS */
+
#ifdef HAVE_EBCDIC
{
char *file = LDAP_STRDUP( tls_opt_randfile );
(void) tls_seed_PRNG( tls_opt_randfile );
#endif
-#ifdef LDAP_R_COMPILE
- tls_init_threads();
-#endif
-
SSL_load_error_strings();
SSLeay_add_ssl_algorithms();
/* FIXME: mod_ssl does this */
X509V3_add_standard_extensions();
+
+#endif /* HAVE_GNUTLS */
return 0;
}
static int
ldap_int_tls_init_ctx( struct ldapoptions *lo, int is_server )
{
- STACK_OF(X509_NAME) *calist;
int i, rc = 0;
char *ciphersuite = lo->ldo_tls_ciphersuite;
char *cacertfile = lo->ldo_tls_cacertfile;
char *cacertdir = lo->ldo_tls_cacertdir;
char *certfile = lo->ldo_tls_certfile;
char *keyfile = lo->ldo_tls_keyfile;
+#ifdef HAVE_GNUTLS
+ char *crlfile = lo->ldo_tls_crlfile;
+#else
char *dhfile = lo->ldo_tls_dhfile;
+#endif
if ( lo->ldo_tls_ctx )
return 0;
cacertfile = LDAP_STRDUP( cacertfile );
__atoe( cacertfile );
}
- if ( cacertdir ) {
- cacertdir = LDAP_STRDUP( cacertdir );
- __atoe( cacertdir );
- }
if ( certfile ) {
certfile = LDAP_STRDUP( certfile );
__atoe( certfile );
keyfile = LDAP_STRDUP( keyfile );
__atoe( keyfile );
}
+#ifdef HAVE_GNUTLS
+ if ( crlfile ) {
+ crlfile = LDAP_STRDUP( crlfile );
+ __atoe( crlfile );
+ }
+#else
+ if ( cacertdir ) {
+ cacertdir = LDAP_STRDUP( cacertdir );
+ __atoe( cacertdir );
+ }
if ( dhfile ) {
dhfile = LDAP_STRDUP( dhfile );
__atoe( dhfile );
}
#endif
- lo->ldo_tls_ctx = SSL_CTX_new( SSLv23_method() );
+#endif
+ lo->ldo_tls_ctx = tls_ctx_new( lo );
if ( lo->ldo_tls_ctx == NULL ) {
+#ifdef HAVE_GNUTLS
+ Debug( LDAP_DEBUG_ANY,
+ "TLS: could not allocate default ctx.\n",
+ 0,0,0);
+#else
Debug( LDAP_DEBUG_ANY,
"TLS: could not allocate default ctx (%lu).\n",
ERR_peek_error(),0,0);
+#endif
rc = -1;
goto error_exit;
}
+#ifdef HAVE_GNUTLS
+ if ( lo->ldo_tls_ciphersuite &&
+ tls_parse_ciphers( lo->ldo_tls_ctx,
+ ciphersuite )) {
+ Debug( LDAP_DEBUG_ANY,
+ "TLS: could not set cipher list %s.\n",
+ lo->ldo_tls_ciphersuite, 0, 0 );
+ rc = -1;
+ goto error_exit;
+ }
+
+ if (lo->ldo_tls_cacertdir != NULL) {
+ Debug( LDAP_DEBUG_ANY,
+ "TLS: warning: cacertdir not implemented for gnutls\n",
+ NULL, NULL, NULL );
+ }
+
+ if (lo->ldo_tls_cacertfile != NULL) {
+ rc = gnutls_certificate_set_x509_trust_file(
+ ((tls_ctx*) lo->ldo_tls_ctx)->cred,
+ cacertfile,
+ GNUTLS_X509_FMT_PEM );
+ if ( rc < 0 ) goto error_exit;
+ }
+
+ if ( lo->ldo_tls_certfile && lo->ldo_tls_keyfile ) {
+ rc = gnutls_certificate_set_x509_key_file(
+ ((tls_ctx*) lo->ldo_tls_ctx)->cred,
+ certfile,
+ keyfile,
+ GNUTLS_X509_FMT_PEM );
+ if ( rc ) goto error_exit;
+ } else if ( lo->ldo_tls_certfile || lo->ldo_tls_keyfile ) {
+ Debug( LDAP_DEBUG_ANY,
+ "TLS: only one of certfile and keyfile specified\n",
+ NULL, NULL, NULL );
+ rc = 1;
+ goto error_exit;
+ }
+
+ if ( lo->ldo_tls_dhfile ) {
+ Debug( LDAP_DEBUG_ANY,
+ "TLS: warning: ignoring dhfile\n",
+ NULL, NULL, NULL );
+ }
+
+ if ( lo->ldo_tls_crlfile ) {
+ rc = gnutls_certificate_set_x509_crl_file(
+ ((tls_ctx*) lo->ldo_tls_ctx)->cred,
+ crlfile,
+ GNUTLS_X509_FMT_PEM );
+ if ( rc < 0 ) goto error_exit;
+ }
+ if ( is_server ) {
+ gnutls_dh_params_init (&((tls_ctx*)
+ lo->ldo_tls_ctx)->dh_params);
+ gnutls_dh_params_generate2 (((tls_ctx*)
+ lo->ldo_tls_ctx)->dh_params,
+ DH_BITS);
+ }
+
+#else /* !HAVE_GNUTLS */
+
if ( is_server ) {
SSL_CTX_set_session_id_context( lo->ldo_tls_ctx,
(const unsigned char *) "OpenLDAP", sizeof("OpenLDAP")-1 );
}
if ( is_server ) {
+ STACK_OF(X509_NAME) *calist;
/* List of CA names to send to a client */
calist = get_ca_list( cacertfile, cacertdir );
if ( !calist ) {
}
#endif
+#endif /* HAVE_GNUTLS */
+
error_exit:
if ( rc == -1 && lo->ldo_tls_ctx != NULL ) {
- SSL_CTX_free( lo->ldo_tls_ctx );
+ ldap_pvt_tls_ctx_free( lo->ldo_tls_ctx );
lo->ldo_tls_ctx = NULL;
}
#ifdef HAVE_EBCDIC
LDAP_FREE( ciphersuite );
LDAP_FREE( cacertfile );
- LDAP_FREE( cacertdir );
LDAP_FREE( certfile );
LDAP_FREE( keyfile );
+#ifdef HAVE_GNUTLS
+ LDAP_FREE( crlfile );
+#else
+ LDAP_FREE( cacertdir );
LDAP_FREE( dhfile );
+#endif
#endif
return rc;
}
return rc;
}
-static STACK_OF(X509_NAME) *
-get_ca_list( char * bundle, char * dir )
-{
- STACK_OF(X509_NAME) *ca_list = NULL;
-
- if ( bundle ) {
- ca_list = SSL_load_client_CA_file( bundle );
- }
-#if defined(HAVE_DIRENT_H) || defined(dirent)
- if ( dir ) {
- int freeit = 0;
-
- if ( !ca_list ) {
- ca_list = sk_X509_NAME_new_null();
- freeit = 1;
- }
- if ( !SSL_add_dir_cert_subjects_to_stack( ca_list, dir ) &&
- freeit ) {
- sk_X509_NAME_free( ca_list );
- ca_list = NULL;
- }
- }
-#endif
- return ca_list;
-}
-
-static SSL *
+static tls_session *
alloc_handle( void *ctx_arg, int is_server )
{
- SSL_CTX *ctx;
- SSL *ssl;
+ tls_ctx *ctx;
+ tls_session *ssl;
if ( ctx_arg ) {
- ctx = (SSL_CTX *) ctx_arg;
+ ctx = ctx_arg;
} else {
struct ldapoptions *lo = LDAP_INT_GLOBAL_OPT();
if ( ldap_pvt_tls_init_def_ctx( is_server ) < 0 ) return NULL;
ctx = lo->ldo_tls_ctx;
}
- ssl = SSL_new( ctx );
+ ssl = tls_session_new( ctx, is_server );
if ( ssl == NULL ) {
Debug( LDAP_DEBUG_ANY,"TLS: can't create ssl handle.\n",0,0,0);
return NULL;
}
static int
-update_flags( Sockbuf *sb, SSL * ssl, int rc )
+update_flags( Sockbuf *sb, tls_session * ssl, int rc )
{
- int err = SSL_get_error(ssl, rc);
-
sb->sb_trans_needs_read = 0;
sb->sb_trans_needs_write = 0;
- if (err == SSL_ERROR_WANT_READ) {
+#ifdef HAVE_GNUTLS
+ if ( rc != GNUTLS_E_INTERRUPTED && rc != GNUTLS_E_AGAIN )
+ return 0;
+
+ switch (gnutls_record_get_direction (ssl->session)) {
+ case 0:
+ sb->sb_trans_needs_read = 1;
+ return 1;
+ case 1:
+ sb->sb_trans_needs_write = 1;
+ return 1;
+ }
+#else /* !HAVE_GNUTLS */
+ rc = SSL_get_error(ssl, rc);
+ if (rc == SSL_ERROR_WANT_READ) {
sb->sb_trans_needs_read = 1;
return 1;
- } else if (err == SSL_ERROR_WANT_WRITE) {
+ } else if (rc == SSL_ERROR_WANT_WRITE) {
sb->sb_trans_needs_write = 1;
return 1;
- } else if (err == SSL_ERROR_WANT_CONNECT) {
+ } else if (rc == SSL_ERROR_WANT_CONNECT) {
return 1;
}
+#endif /* HAVE_GNUTLS */
return 0;
}
*/
struct tls_data {
- SSL *ssl;
+ tls_session *ssl;
Sockbuf_IO_Desc *sbiod;
};
-static BIO_METHOD sb_tls_bio_method;
+#ifdef HAVE_GNUTLS
+
+static ssize_t
+sb_gtls_recv( gnutls_transport_ptr_t ptr, void *buf, size_t len )
+{
+ struct tls_data *p;
+
+ if ( buf == NULL || len <= 0 ) return 0;
+
+ p = (struct tls_data *)ptr;
+
+ if ( p == NULL || p->sbiod == NULL ) {
+ return 0;
+ }
+
+ return LBER_SBIOD_READ_NEXT( p->sbiod, buf, len );
+}
+
+static ssize_t
+sb_gtls_send( gnutls_transport_ptr_t ptr, const void *buf, size_t len )
+{
+ struct tls_data *p;
+
+ if ( buf == NULL || len <= 0 ) return 0;
+
+ p = (struct tls_data *)ptr;
+
+ if ( p == NULL || p->sbiod == NULL ) {
+ return 0;
+ }
+
+ return LBER_SBIOD_WRITE_NEXT( p->sbiod, (char *)buf, len );
+}
static int
sb_tls_setup( Sockbuf_IO_Desc *sbiod, void *arg )
{
struct tls_data *p;
- BIO *bio;
+ tls_session *session = arg;
assert( sbiod != NULL );
return -1;
}
- p->ssl = (SSL *)arg;
+ gnutls_transport_set_ptr( session->session, (gnutls_transport_ptr)p );
+ gnutls_transport_set_pull_function( session->session, sb_gtls_recv );
+ gnutls_transport_set_push_function( session->session, sb_gtls_send );
+ p->ssl = arg;
p->sbiod = sbiod;
- bio = BIO_new( &sb_tls_bio_method );
- bio->ptr = (void *)p;
- SSL_set_bio( p->ssl, bio, bio );
sbiod->sbiod_pvt = p;
return 0;
}
assert( sbiod->sbiod_pvt != NULL );
p = (struct tls_data *)sbiod->sbiod_pvt;
- SSL_free( p->ssl );
+ gnutls_deinit ( p->ssl->session );
+ LBER_FREE( p->ssl );
LBER_FREE( sbiod->sbiod_pvt );
sbiod->sbiod_pvt = NULL;
return 0;
assert( sbiod->sbiod_pvt != NULL );
p = (struct tls_data *)sbiod->sbiod_pvt;
- SSL_shutdown( p->ssl );
+ gnutls_bye ( p->ssl->session, GNUTLS_SHUT_RDWR );
return 0;
}
p = (struct tls_data *)sbiod->sbiod_pvt;
if ( opt == LBER_SB_OPT_GET_SSL ) {
- *((SSL **)arg) = p->ssl;
+ *((tls_session **)arg) = p->ssl;
return 1;
-
+
} else if ( opt == LBER_SB_OPT_DATA_READY ) {
- if( SSL_pending( p->ssl ) > 0 ) {
+ if( gnutls_record_check_pending( p->ssl->session ) > 0 ) {
return 1;
}
}
p = (struct tls_data *)sbiod->sbiod_pvt;
- ret = SSL_read( p->ssl, (char *)buf, len );
-#ifdef HAVE_WINSOCK
- errno = WSAGetLastError();
-#endif
- err = SSL_get_error( p->ssl, ret );
- if (err == SSL_ERROR_WANT_READ ) {
+ ret = gnutls_record_recv ( p->ssl->session, buf, len );
+ switch (ret) {
+ case GNUTLS_E_INTERRUPTED:
+ case GNUTLS_E_AGAIN:
sbiod->sbiod_sb->sb_trans_needs_read = 1;
sock_errset(EWOULDBLOCK);
- }
- else
+ ret = 0;
+ break;
+ case GNUTLS_E_REHANDSHAKE:
+ for ( ret = gnutls_handshake ( p->ssl->session );
+ ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN;
+ ret = gnutls_handshake ( p->ssl->session ) );
+ sbiod->sbiod_sb->sb_trans_needs_read = 1;
+ ret = 0;
+ break;
+ default:
sbiod->sbiod_sb->sb_trans_needs_read = 0;
+ }
return ret;
}
p = (struct tls_data *)sbiod->sbiod_pvt;
- ret = SSL_write( p->ssl, (char *)buf, len );
-#ifdef HAVE_WINSOCK
- errno = WSAGetLastError();
-#endif
- err = SSL_get_error( p->ssl, ret );
- if (err == SSL_ERROR_WANT_WRITE ) {
+ ret = gnutls_record_send ( p->ssl->session, (char *)buf, len );
+
+ if ( ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN ) {
sbiod->sbiod_sb->sb_trans_needs_write = 1;
sock_errset(EWOULDBLOCK);
-
+ ret = 0;
} else {
sbiod->sbiod_sb->sb_trans_needs_write = 0;
}
return ret;
}
-static Sockbuf_IO sb_tls_sbio =
-{
- sb_tls_setup, /* sbi_setup */
- sb_tls_remove, /* sbi_remove */
- sb_tls_ctrl, /* sbi_ctrl */
- sb_tls_read, /* sbi_read */
- sb_tls_write, /* sbi_write */
- sb_tls_close /* sbi_close */
-};
+#else /* !HAVE_GNUTLS */
static int
sb_tls_bio_create( BIO *b ) {
}
static int
-sb_tls_bio_puts( BIO *b, const char *str )
+sb_tls_bio_puts( BIO *b, const char *str )
+{
+ return sb_tls_bio_write( b, str, strlen( str ) );
+}
+
+static BIO_METHOD sb_tls_bio_method =
+{
+ ( 100 | 0x400 ), /* it's a source/sink BIO */
+ "sockbuf glue",
+ sb_tls_bio_write,
+ sb_tls_bio_read,
+ sb_tls_bio_puts,
+ sb_tls_bio_gets,
+ sb_tls_bio_ctrl,
+ sb_tls_bio_create,
+ sb_tls_bio_destroy
+};
+
+static int
+sb_tls_setup( Sockbuf_IO_Desc *sbiod, void *arg )
+{
+ struct tls_data *p;
+ BIO *bio;
+
+ assert( sbiod != NULL );
+
+ p = LBER_MALLOC( sizeof( *p ) );
+ if ( p == NULL ) {
+ return -1;
+ }
+
+ p->ssl = (SSL *)arg;
+ p->sbiod = sbiod;
+ bio = BIO_new( &sb_tls_bio_method );
+ bio->ptr = (void *)p;
+ SSL_set_bio( p->ssl, bio, bio );
+ sbiod->sbiod_pvt = p;
+ return 0;
+}
+
+static int
+sb_tls_remove( Sockbuf_IO_Desc *sbiod )
+{
+ struct tls_data *p;
+
+ assert( sbiod != NULL );
+ assert( sbiod->sbiod_pvt != NULL );
+
+ p = (struct tls_data *)sbiod->sbiod_pvt;
+ SSL_free( p->ssl );
+ LBER_FREE( sbiod->sbiod_pvt );
+ sbiod->sbiod_pvt = NULL;
+ return 0;
+}
+
+static int
+sb_tls_close( Sockbuf_IO_Desc *sbiod )
+{
+ struct tls_data *p;
+
+ assert( sbiod != NULL );
+ assert( sbiod->sbiod_pvt != NULL );
+
+ p = (struct tls_data *)sbiod->sbiod_pvt;
+ SSL_shutdown( p->ssl );
+ return 0;
+}
+
+static int
+sb_tls_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg )
+{
+ struct tls_data *p;
+
+ assert( sbiod != NULL );
+ assert( sbiod->sbiod_pvt != NULL );
+
+ p = (struct tls_data *)sbiod->sbiod_pvt;
+
+ if ( opt == LBER_SB_OPT_GET_SSL ) {
+ *((SSL **)arg) = p->ssl;
+ return 1;
+
+ } else if ( opt == LBER_SB_OPT_DATA_READY ) {
+ if( SSL_pending( p->ssl ) > 0 ) {
+ return 1;
+ }
+ }
+
+ return LBER_SBIOD_CTRL_NEXT( sbiod, opt, arg );
+}
+
+static ber_slen_t
+sb_tls_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len)
+{
+ struct tls_data *p;
+ ber_slen_t ret;
+ int err;
+
+ assert( sbiod != NULL );
+ assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
+
+ p = (struct tls_data *)sbiod->sbiod_pvt;
+
+ ret = SSL_read( p->ssl, (char *)buf, len );
+#ifdef HAVE_WINSOCK
+ errno = WSAGetLastError();
+#endif
+ err = SSL_get_error( p->ssl, ret );
+ if (err == SSL_ERROR_WANT_READ ) {
+ sbiod->sbiod_sb->sb_trans_needs_read = 1;
+ sock_errset(EWOULDBLOCK);
+ }
+ else
+ sbiod->sbiod_sb->sb_trans_needs_read = 0;
+ return ret;
+}
+
+static ber_slen_t
+sb_tls_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len)
+{
+ struct tls_data *p;
+ ber_slen_t ret;
+ int err;
+
+ assert( sbiod != NULL );
+ assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
+
+ p = (struct tls_data *)sbiod->sbiod_pvt;
+
+ ret = SSL_write( p->ssl, (char *)buf, len );
+#ifdef HAVE_WINSOCK
+ errno = WSAGetLastError();
+#endif
+ err = SSL_get_error( p->ssl, ret );
+ if (err == SSL_ERROR_WANT_WRITE ) {
+ sbiod->sbiod_sb->sb_trans_needs_write = 1;
+ sock_errset(EWOULDBLOCK);
+
+ } else {
+ sbiod->sbiod_sb->sb_trans_needs_write = 0;
+ }
+ return ret;
+}
+
+#endif
+
+static Sockbuf_IO sb_tls_sbio =
+{
+ sb_tls_setup, /* sbi_setup */
+ sb_tls_remove, /* sbi_remove */
+ sb_tls_ctrl, /* sbi_ctrl */
+ sb_tls_read, /* sbi_read */
+ sb_tls_write, /* sbi_write */
+ sb_tls_close /* sbi_close */
+};
+
+#ifdef HAVE_GNUTLS
+/* Certs are not automatically varified during the handshake */
+static int
+tls_cert_verify( tls_session *ssl )
{
- return sb_tls_bio_write( b, str, strlen( str ) );
+ unsigned int status = 0;
+ int err;
+ time_t now = time(0);
+
+ err = gnutls_certificate_verify_peers2( ssl->session, &status );
+ if ( err < 0 ) {
+ Debug( LDAP_DEBUG_ANY,"TLS: gnutls_certificate_verify_peers2 failed %d\n",
+ err,0,0 );
+ return -1;
+ }
+ if ( status ) {
+ Debug( LDAP_DEBUG_TRACE,"TLS: peer cert untrusted or revoked (0x%x)\n",
+ status, 0,0 );
+ return -1;
+ }
+ if ( gnutls_certificate_expiration_time_peers( ssl->session ) < now ) {
+ Debug( LDAP_DEBUG_ANY, "TLS: peer certificate is expired\n",
+ 0, 0, 0 );
+ return -1;
+ }
+ if ( gnutls_certificate_activation_time_peers( ssl->session ) > now ) {
+ Debug( LDAP_DEBUG_ANY, "TLS: peer certificate not yet active\n",
+ 0, 0, 0 );
+ return -1;
+ }
+ return 0;
}
-
-static BIO_METHOD sb_tls_bio_method =
-{
- ( 100 | 0x400 ), /* it's a source/sink BIO */
- "sockbuf glue",
- sb_tls_bio_write,
- sb_tls_bio_read,
- sb_tls_bio_puts,
- sb_tls_bio_gets,
- sb_tls_bio_ctrl,
- sb_tls_bio_create,
- sb_tls_bio_destroy
-};
+#endif /* HAVE_GNUTLS */
/*
* Call this to do a TLS connect on a sockbuf. ctx_arg can be
{
Sockbuf *sb = conn->lconn_sb;
int err;
- SSL *ssl;
+ tls_session *ssl;
if ( HAS_TLS( sb ) ) {
ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_SSL, (void *)&ssl );
} else {
struct ldapoptions *lo;
- SSL_CTX *ctx;
+ tls_ctx *ctx;
ctx = ld->ld_options.ldo_tls_ctx;
if( ctx == NULL ) {
ctx = lo->ldo_tls_ctx;
ld->ld_options.ldo_tls_ctx = ctx;
- CRYPTO_add( &ctx->references, 1, CRYPTO_LOCK_SSL_CTX );
+ tls_ctx_ref( ctx );
}
if ( ld->ld_options.ldo_tls_connect_cb )
ld->ld_options.ldo_tls_connect_cb( ld, ssl, ctx,
lo->ldo_tls_connect_cb( ld, ssl, ctx, lo->ldo_tls_connect_arg );
}
- err = SSL_connect( ssl );
+ err = tls_session_connect( ssl );
#ifdef HAVE_WINSOCK
errno = WSAGetLastError();
#endif
- if ( err <= 0 ) {
+#ifdef HAVE_GNUTLS
+ if ( err < 0 )
+#else
+ if ( err <= 0 )
+#endif
+ {
if ( update_flags( sb, ssl, err )) {
return 1;
}
- if ((err = ERR_peek_error())) {
- char buf[256];
-
+#ifndef HAVE_GNUTLS
+ if ((err = ERR_peek_error()))
+#endif
+ {
if ( ld->ld_error ) {
LDAP_FREE( ld->ld_error );
}
- ld->ld_error = LDAP_STRDUP(ERR_error_string(err, buf));
+#ifdef HAVE_GNUTLS
+ ld->ld_error = LDAP_STRDUP(gnutls_strerror( err ));
+#else
+ {
+ char buf[256];
+ ld->ld_error = LDAP_STRDUP(ERR_error_string(err, buf));
+ }
+#endif
#ifdef HAVE_EBCDIC
if ( ld->ld_error ) __etoa(ld->ld_error);
#endif
return -1;
}
+#ifdef HAVE_GNUTLS
+ if ( ld->ld_options.ldo_tls_require_cert != LDAP_OPT_X_TLS_NEVER ) {
+ err = tls_cert_verify( ssl );
+ if ( err && ld->ld_options.ldo_tls_require_cert != LDAP_OPT_X_TLS_ALLOW )
+ return err;
+ }
+#endif
+
return 0;
}
ldap_pvt_tls_accept( Sockbuf *sb, void *ctx_arg )
{
int err;
- SSL *ssl;
+ tls_session *ssl;
if ( HAS_TLS( sb ) ) {
ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_SSL, (void *)&ssl );
LBER_SBIOD_LEVEL_TRANSPORT, (void *)ssl );
}
-#ifdef LDAP_R_COMPILE
- ldap_pvt_thread_mutex_lock( &tls_connect_mutex );
-#endif
- err = SSL_accept( ssl );
-#ifdef LDAP_R_COMPILE
- ldap_pvt_thread_mutex_unlock( &tls_connect_mutex );
-#endif
+ err = tls_session_accept( ssl );
#ifdef HAVE_WINSOCK
errno = WSAGetLastError();
#endif
- if ( err <= 0 ) {
+
+#ifdef HAVE_GNUTLS
+ if ( err < 0 )
+#else
+ if ( err <= 0 )
+#endif
+ {
if ( update_flags( sb, ssl, err )) return 1;
+#ifdef HAVE_GNUTLS
+ Debug( LDAP_DEBUG_ANY,"TLS: can't accept: %s.\n",
+ gnutls_strerror( err ),0,0 );
+#else
Debug( LDAP_DEBUG_ANY,"TLS: can't accept.\n",0,0,0 );
-
tls_report_error();
+#endif
ber_sockbuf_remove_io( sb, &sb_tls_sbio,
LBER_SBIOD_LEVEL_TRANSPORT );
#ifdef LDAP_DEBUG
return -1;
}
+#ifdef HAVE_GNUTLS
+ if ( ssl->ctx->lo->ldo_tls_require_cert != LDAP_OPT_X_TLS_NEVER ) {
+ err = tls_cert_verify( ssl );
+ if ( err && ssl->ctx->lo->ldo_tls_require_cert != LDAP_OPT_X_TLS_ALLOW )
+ return err;
+ }
+#endif
return 0;
}
return ldap_pvt_tls_inplace( sb );
}
+#ifdef HAVE_GNUTLS
+static void
+x509_cert_get_dn( struct berval *cert, struct berval *dn, int get_subject )
+{
+ BerElementBuffer berbuf;
+ BerElement *ber = (BerElement *)&berbuf;
+ ber_tag_t tag;
+ ber_len_t len;
+ ber_int_t i;
+
+ ber_init2( ber, cert, LBER_USE_DER );
+ tag = ber_skip_tag( ber, &len ); /* Sequence */
+ tag = ber_skip_tag( ber, &len ); /* Sequence */
+ tag = ber_skip_tag( ber, &len ); /* Context + Constructed (version) */
+ if ( tag == 0xa0 ) /* Version is optional */
+ tag = ber_get_int( ber, &i ); /* Int: Version */
+ tag = ber_get_int( ber, &i ); /* Int: Serial */
+ tag = ber_skip_tag( ber, &len ); /* Sequence: Signature */
+ ber_skip_data( ber, len );
+ if ( !get_subject ) {
+ tag = ber_peek_tag( ber, &len ); /* Sequence: Issuer DN */
+ } else {
+ tag = ber_skip_tag( ber, &len );
+ ber_skip_data( ber, len );
+ tag = ber_skip_tag( ber, &len ); /* Sequence: Validity */
+ ber_skip_data( ber, len );
+ tag = ber_peek_tag( ber, &len ); /* Sequence: Subject DN */
+ }
+ len = ber_ptrlen( ber );
+ dn->bv_val = cert->bv_val + len;
+ dn->bv_len = cert->bv_len - len;
+}
+
+static int
+tls_get_cert_dn( tls_session *session, struct berval *dnbv )
+{
+ if ( !session->peer_der_dn.bv_val ) {
+ const gnutls_datum_t *peer_cert_list;
+ int list_size;
+ struct berval bv;
+
+ peer_cert_list = gnutls_certificate_get_peers( session->session,
+ &list_size );
+ if ( !peer_cert_list ) return LDAP_INVALID_CREDENTIALS;
+
+ bv.bv_len = peer_cert_list->size;
+ bv.bv_val = peer_cert_list->data;
+
+ x509_cert_get_dn( &bv, &session->peer_der_dn, 1 );
+ *dnbv = session->peer_der_dn;
+ }
+ return 0;
+}
+#else /* !HAVE_GNUTLS */
static X509 *
tls_get_cert( SSL *s )
{
return SSL_get_peer_certificate(s);
}
+static int
+tls_get_cert_dn( tls_session *session, struct berval *dnbv )
+{
+ X509_NAME *xn;
+ X509 *x = tls_get_cert( session );
+
+ if ( !x )
+ return LDAP_INVALID_CREDENTIALS;
+
+ xn = X509_get_subject_name(x);
+ dnbv->bv_len = i2d_X509_NAME( xn, NULL );
+ dnbv->bv_val = xn->bytes->data;
+ return 0;
+}
+#endif /* HAVE_GNUTLS */
+
int
ldap_pvt_tls_get_peer_dn( void *s, struct berval *dn,
LDAPDN_rewrite_dummy *func, unsigned flags )
{
- X509 *x;
- X509_NAME *xn;
+ tls_session *session = s;
+ struct berval bvdn;
int rc;
- x = tls_get_cert((SSL *)s);
+ rc = tls_get_cert_dn( session, &bvdn );
+ if ( rc ) return rc;
- if (!x) return LDAP_INVALID_CREDENTIALS;
-
- xn = X509_get_subject_name(x);
- rc = ldap_X509dn2bv(xn, dn, (LDAPDN_rewrite_func *)func, flags);
- X509_free(x);
+ rc = ldap_X509dn2bv( &bvdn, dn,
+ (LDAPDN_rewrite_func *)func, flags);
return rc;
}
-char *
-ldap_pvt_tls_get_peer_hostname( void *s )
+/* what kind of hostname were we given? */
+#define IS_DNS 0
+#define IS_IP4 1
+#define IS_IP6 2
+
+#ifdef HAVE_GNUTLS
+
+int
+ldap_pvt_tls_check_hostname( LDAP *ld, void *s, const char *name_in )
{
- X509 *x;
- X509_NAME *xn;
- char buf[2048], *p;
- int ret;
+ tls_session *session = s;
+ int i, ret;
+ const gnutls_datum_t *peer_cert_list;
+ int list_size;
+ struct berval bv;
+ char altname[NI_MAXHOST];
+ size_t altnamesize;
+
+ gnutls_x509_crt_t cert;
+ gnutls_datum_t *x;
+ const char *name;
+ char *ptr;
+ char *domain = NULL;
+#ifdef LDAP_PF_INET6
+ struct in6_addr addr;
+#else
+ struct in_addr addr;
+#endif
+ int n, len1 = 0, len2 = 0;
+ int ntype = IS_DNS;
+ time_t now = time(0);
- x = tls_get_cert((SSL *)s);
- if (!x) return NULL;
+ if( ldap_int_hostname &&
+ ( !name_in || !strcasecmp( name_in, "localhost" ) ) )
+ {
+ name = ldap_int_hostname;
+ } else {
+ name = name_in;
+ }
+
+ peer_cert_list = gnutls_certificate_get_peers( session->session,
+ &list_size );
+ if ( !peer_cert_list ) {
+ Debug( LDAP_DEBUG_ANY,
+ "TLS: unable to get peer certificate.\n",
+ 0, 0, 0 );
+ /* If this was a fatal condition, things would have
+ * aborted long before now.
+ */
+ return LDAP_SUCCESS;
+ }
+ ret = gnutls_x509_crt_init( &cert );
+ if ( ret < 0 )
+ return LDAP_LOCAL_ERROR;
+ ret = gnutls_x509_crt_import( cert, peer_cert_list, GNUTLS_X509_FMT_DER );
+ if ( ret ) {
+ gnutls_x509_crt_deinit( cert );
+ return LDAP_LOCAL_ERROR;
+ }
+
+#ifdef LDAP_PF_INET6
+ if (name[0] == '[' && strchr(name, ']')) {
+ char *n2 = ldap_strdup(name+1);
+ *strchr(n2, ']') = 2;
+ if (inet_pton(AF_INET6, n2, &addr))
+ ntype = IS_IP6;
+ LDAP_FREE(n2);
+ } else
+#endif
+ if ((ptr = strrchr(name, '.')) && isdigit((unsigned char)ptr[1])) {
+ if (inet_aton(name, (struct in_addr *)&addr)) ntype = IS_IP4;
+ }
- xn = X509_get_subject_name(x);
+ if (ntype == IS_DNS) {
+ len1 = strlen(name);
+ domain = strchr(name, '.');
+ if (domain) {
+ len2 = len1 - (domain-name);
+ }
+ }
- ret = X509_NAME_get_text_by_NID(xn, NID_commonName, buf, sizeof(buf));
- if( ret == -1 ) {
- X509_free(x);
- return NULL;
+ for ( i=0, ret=0; ret >= 0; i++ ) {
+ altnamesize = sizeof(altname);
+ ret = gnutls_x509_crt_get_subject_alt_name( cert, i,
+ altname, &altnamesize, NULL );
+ if ( ret < 0 ) break;
+
+ /* ignore empty */
+ if ( altnamesize == 0 ) continue;
+
+ if ( ret == GNUTLS_SAN_DNSNAME ) {
+ if (ntype != IS_DNS) continue;
+
+ /* Is this an exact match? */
+ if ((len1 == altnamesize) && !strncasecmp(name, altname, len1)) {
+ break;
+ }
+
+ /* Is this a wildcard match? */
+ if (domain && (altname[0] == '*') && (altname[1] == '.') &&
+ (len2 == altnamesize-1) && !strncasecmp(domain, &altname[1], len2))
+ {
+ break;
+ }
+ } else if ( ret == GNUTLS_SAN_IPADDRESS ) {
+ if (ntype == IS_DNS) continue;
+
+#ifdef LDAP_PF_INET6
+ if (ntype == IS_IP6 && altnamesize != sizeof(struct in6_addr)) {
+ continue;
+ } else
+#endif
+ if (ntype == IS_IP4 && altnamesize != sizeof(struct in_addr)) {
+ continue;
+ }
+ if (!memcmp(altname, &addr, altnamesize)) {
+ break;
+ }
+ }
}
+ if ( ret >= 0 ) {
+ ret = LDAP_SUCCESS;
+ } else {
+ altnamesize = sizeof(altname);
+ ret = gnutls_x509_crt_get_dn_by_oid( cert, CN_OID,
+ 0, 0, altname, &altnamesize );
+ if ( ret < 0 ) {
+ Debug( LDAP_DEBUG_ANY,
+ "TLS: unable to get common name from peer certificate.\n",
+ 0, 0, 0 );
+ ret = LDAP_CONNECT_ERROR;
+ if ( ld->ld_error ) {
+ LDAP_FREE( ld->ld_error );
+ }
+ ld->ld_error = LDAP_STRDUP(
+ _("TLS: unable to get CN from peer certificate"));
- p = LDAP_STRDUP(buf);
- X509_free(x);
- return p;
+ } else {
+ ret = LDAP_LOCAL_ERROR;
+ if ( len1 == altnamesize && strncasecmp(name, altname, altnamesize) == 0 ) {
+ ret = LDAP_SUCCESS;
+
+ } else if (( altname[0] == '*' ) && ( altname[1] == '.' )) {
+ /* Is this a wildcard match? */
+ if( domain &&
+ (len2 == altnamesize-1) && !strncasecmp(domain, &altname[1], len2)) {
+ ret = LDAP_SUCCESS;
+ }
+ }
+ }
+
+ if( ret == LDAP_LOCAL_ERROR ) {
+ altname[altnamesize] = '\0';
+ Debug( LDAP_DEBUG_ANY, "TLS: hostname (%s) does not match "
+ "common name in certificate (%s).\n",
+ name, altname, 0 );
+ ret = LDAP_CONNECT_ERROR;
+ if ( ld->ld_error ) {
+ LDAP_FREE( ld->ld_error );
+ }
+ ld->ld_error = LDAP_STRDUP(
+ _("TLS: hostname does not match CN in peer certificate"));
+ }
+ }
+ gnutls_x509_crt_deinit( cert );
+ return ret;
}
-/* what kind of hostname were we given? */
-#define IS_DNS 0
-#define IS_IP4 1
-#define IS_IP6 2
+#else /* !HAVE_GNUTLS */
int
ldap_pvt_tls_check_hostname( LDAP *ld, void *s, const char *name_in )
X509_free(x);
return ret;
}
-
-const char *
-ldap_pvt_tls_get_peer_issuer( void *s )
-{
-#if 0 /* currently unused; see ldap_pvt_tls_get_peer_dn() if needed */
- X509 *x;
- X509_NAME *xn;
- char buf[2048], *p;
-
- x = SSL_get_peer_certificate((SSL *)s);
-
- if (!x) return NULL;
-
- xn = X509_get_issuer_name(x);
- p = LDAP_STRDUP(X509_NAME_oneline(xn, buf, sizeof(buf)));
- X509_free(x);
- return p;
-#else
- return NULL;
#endif
-}
int
ldap_int_tls_config( LDAP *ld, int option, const char *arg )
case LDAP_OPT_X_TLS_RANDOM_FILE:
case LDAP_OPT_X_TLS_CIPHER_SUITE:
case LDAP_OPT_X_TLS_DHFILE:
+#ifdef HAVE_GNUTLS
+ case LDAP_OPT_X_TLS_CRLFILE:
+#endif
return ldap_pvt_tls_set_option( ld, option, (void *) arg );
case LDAP_OPT_X_TLS_REQUIRE_CERT:
case LDAP_OPT_X_TLS_CTX:
*(void **)arg = lo->ldo_tls_ctx;
if ( lo->ldo_tls_ctx ) {
- SSL_CTX *ctx = lo->ldo_tls_ctx;
- CRYPTO_add( &ctx->references, 1, CRYPTO_LOCK_SSL_CTX );
+ tls_ctx_ref( lo->ldo_tls_ctx );
}
break;
case LDAP_OPT_X_TLS_CACERTFILE:
*(char **)arg = lo->ldo_tls_dhfile ?
LDAP_STRDUP( lo->ldo_tls_dhfile ) : NULL;
break;
+#ifdef HAVE_GNUTLS
+ case LDAP_OPT_X_TLS_CRLFILE:
+ *(char **)arg = lo->ldo_tls_crlfile ?
+ LDAP_STRDUP( lo->ldo_tls_crlfile ) : NULL;
+ break;
+#endif
case LDAP_OPT_X_TLS_REQUIRE_CERT:
*(int *)arg = lo->ldo_tls_require_cert;
break;
LDAP_STRDUP( lo->ldo_tls_ciphersuite ) : NULL;
break;
case LDAP_OPT_X_TLS_RANDOM_FILE:
+#ifdef HAVE_OPENSSL
*(char **)arg = tls_opt_randfile ?
LDAP_STRDUP( tls_opt_randfile ) : NULL;
+#else
+ *(char **)arg = NULL;
+#endif
break;
case LDAP_OPT_X_TLS_SSL_CTX: {
void *retval = 0;
case LDAP_OPT_X_TLS_CTX:
if ( lo->ldo_tls_ctx )
- SSL_CTX_free( lo->ldo_tls_ctx );
+ ldap_pvt_tls_ctx_free( lo->ldo_tls_ctx );
lo->ldo_tls_ctx = arg;
- CRYPTO_add( &((SSL_CTX *)arg)->references, 1, CRYPTO_LOCK_SSL_CTX );
+ tls_ctx_ref( lo->ldo_tls_ctx );
return 0;
case LDAP_OPT_X_TLS_CONNECT_CB:
lo->ldo_tls_connect_cb = (LDAP_TLS_CONNECT_CB *)arg;
if ( lo->ldo_tls_dhfile ) LDAP_FREE( lo->ldo_tls_dhfile );
lo->ldo_tls_dhfile = arg ? LDAP_STRDUP( (char *) arg ) : NULL;
return 0;
+#ifdef HAVE_GNUTLS
+ case LDAP_OPT_X_TLS_CRLFILE:
+ if ( lo->ldo_tls_crlfile ) LDAP_FREE( lo->ldo_tls_crlfile );
+ lo->ldo_tls_crlfile = arg ? LDAP_STRDUP( (char *) arg ) : NULL;
+ return 0;
+#endif
case LDAP_OPT_X_TLS_REQUIRE_CERT:
if ( !arg ) return -1;
switch( *(int *) arg ) {
case LDAP_OPT_X_TLS_RANDOM_FILE:
if ( ld != NULL )
return -1;
+#ifdef HAVE_OPENSSL
if (tls_opt_randfile ) LDAP_FREE (tls_opt_randfile );
tls_opt_randfile = arg ? LDAP_STRDUP( (char *) arg ) : NULL;
+#endif
break;
case LDAP_OPT_X_TLS_NEWCTX:
if ( !arg ) return -1;
if ( lo->ldo_tls_ctx )
- SSL_CTX_free( lo->ldo_tls_ctx );
+ ldap_pvt_tls_ctx_free( lo->ldo_tls_ctx );
lo->ldo_tls_ctx = NULL;
return ldap_int_tls_init_ctx( lo, *(int *)arg );
default:
return LDAP_SUCCESS;
}
+#ifdef HAVE_OPENSSL
/* Derived from openssl/apps/s_cb.c */
static void
tls_info_cb( const SSL *ssl, int where, int ret )
}
#endif
+#endif /* HAVE_OPENSSL */
+
void *
ldap_pvt_tls_sb_ctx( Sockbuf *sb )
{
int
ldap_pvt_tls_get_strength( void *s )
{
-#ifdef HAVE_TLS
+#ifdef HAVE_OPENSSL
SSL_CIPHER *c;
c = SSL_get_current_cipher((SSL *)s);
return SSL_CIPHER_get_bits(c, NULL);
+#elif defined(HAVE_GNUTLS)
+ tls_session *session = s;
+ gnutls_cipher_algorithm_t c;
+
+ c = gnutls_cipher_get( session->session );
+ return gnutls_cipher_get_key_size( c );
#else
return 0;
#endif
ldap_pvt_tls_get_my_dn( void *s, struct berval *dn, LDAPDN_rewrite_dummy *func, unsigned flags )
{
#ifdef HAVE_TLS
+ struct berval der_dn;
+ int rc;
+#ifdef HAVE_OPENSSL
X509 *x;
X509_NAME *xn;
- int rc;
x = SSL_get_certificate((SSL *)s);
if (!x) return LDAP_INVALID_CREDENTIALS;
xn = X509_get_subject_name(x);
- rc = ldap_X509dn2bv(xn, dn, (LDAPDN_rewrite_func *)func, flags );
+ der_dn.bv_len = i2d_X509_NAME( xn, NULL );
+ der_dn.bv_val = xn->bytes->data;
+#elif defined(HAVE_GNUTLS)
+ tls_session *session = s;
+ const gnutls_datum_t *x;
+ struct berval bv;
+
+ x = gnutls_certificate_get_ours( session->session );
+
+ if (!x) return LDAP_INVALID_CREDENTIALS;
+
+ bv.bv_val = x->data;
+ bv.bv_len = x->size;
+
+ x509_cert_get_dn( &bv, &der_dn, 1 );
+#endif
+ rc = ldap_X509dn2bv(&der_dn, dn, (LDAPDN_rewrite_func *)func, flags );
return rc;
-#else
+#else /* !HAVE_TLS */
return LDAP_NOT_SUPPORTED;
#endif
}
#endif
}
+/* These tags probably all belong in lber.h, but they're
+ * not normally encountered when processing LDAP, so maybe
+ * they belong somewhere else instead.
+ */
+
+#define LBER_TAG_OID ((ber_tag_t) 0x06UL)
+
+/* Tags for string types used in a DirectoryString.
+ *
+ * Note that IA5string is not one of the defined choices for
+ * DirectoryString in X.520, but it gets used for email AVAs.
+ */
+#define LBER_TAG_UTF8 ((ber_tag_t) 0x0cUL)
+#define LBER_TAG_PRINTABLE ((ber_tag_t) 0x13UL)
+#define LBER_TAG_TELETEX ((ber_tag_t) 0x14UL)
+#define LBER_TAG_IA5 ((ber_tag_t) 0x16UL)
+#define LBER_TAG_UNIVERSAL ((ber_tag_t) 0x1cUL)
+#define LBER_TAG_BMP ((ber_tag_t) 0x1eUL)
+
+static oid_name *
+find_oid( struct berval *oid )
+{
+ int i;
+
+ for ( i=0; !BER_BVISNULL( &oids[i].oid ); i++ ) {
+ if ( oids[i].oid.bv_len != oid->bv_len ) continue;
+ if ( !strcmp( oids[i].oid.bv_val, oid->bv_val ))
+ return &oids[i];
+ }
+ return NULL;
+}
+
+/* Convert a structured DN from an X.509 certificate into an LDAPV3 DN.
+ * x509_name must be raw DER. If func is non-NULL, the
+ * constructed DN will use numeric OIDs to identify attributeTypes,
+ * and the func() will be invoked to rewrite the DN with the given
+ * flags.
+ *
+ * Otherwise the DN will use shortNames from a hardcoded table.
+ */
+int
+ldap_X509dn2bv( void *x509_name, struct berval *bv, LDAPDN_rewrite_func *func,
+ unsigned flags )
+{
+ LDAPDN newDN;
+ LDAPRDN newRDN;
+ LDAPAVA *newAVA, *baseAVA;
+ BerElementBuffer berbuf;
+ BerElement *ber = (BerElement *)&berbuf;
+ char oids[8192], *oidptr = oids, *oidbuf = NULL;
+ void *ptrs[2048];
+ char *dn_end, *rdn_end;
+ int i, navas, nrdns, rc = LDAP_SUCCESS;
+ size_t dnsize, oidrem = sizeof(oids), oidsize = 0;
+ int csize;
+ ber_tag_t tag;
+ ber_len_t len;
+ oid_name *oidname;
+
+ struct berval Oid, Val, oid2, *in = x509_name;
+
+ assert( bv != NULL );
+
+ bv->bv_len = 0;
+ bv->bv_val = NULL;
+
+ navas = 0;
+ nrdns = 0;
+
+ /* A DN is a SEQUENCE of RDNs. An RDN is a SET of AVAs.
+ * An AVA is a SEQUENCE of attr and value.
+ * Count the number of AVAs and RDNs
+ */
+ ber_init2( ber, in, LBER_USE_DER );
+ tag = ber_peek_tag( ber, &len );
+ if ( tag != LBER_SEQUENCE )
+ return LDAP_DECODING_ERROR;
+
+ for ( tag = ber_first_element( ber, &len, &dn_end );
+ tag == LBER_SET;
+ tag = ber_next_element( ber, &len, dn_end )) {
+ nrdns++;
+ for ( tag = ber_first_element( ber, &len, &rdn_end );
+ tag == LBER_SEQUENCE;
+ tag = ber_next_element( ber, &len, rdn_end )) {
+ tag = ber_skip_tag( ber, &len );
+ ber_skip_data( ber, len );
+ navas++;
+ }
+ }
+
+ /* Allocate the DN/RDN/AVA stuff as a single block */
+ dnsize = sizeof(LDAPRDN) * (nrdns+1);
+ dnsize += sizeof(LDAPAVA *) * (navas+nrdns);
+ dnsize += sizeof(LDAPAVA) * navas;
+ if (dnsize > sizeof(ptrs)) {
+ newDN = (LDAPDN)LDAP_MALLOC( dnsize );
+ if ( newDN == NULL )
+ return LDAP_NO_MEMORY;
+ } else {
+ newDN = (LDAPDN)(char *)ptrs;
+ }
+
+ newDN[nrdns] = NULL;
+ newRDN = (LDAPRDN)(newDN + nrdns+1);
+ newAVA = (LDAPAVA *)(newRDN + navas + nrdns);
+ baseAVA = newAVA;
+
+ /* Rewind and start extracting */
+ ber_rewind( ber );
+
+ tag = ber_first_element( ber, &len, &dn_end );
+ for ( i = nrdns - 1; i >= 0; i-- ) {
+ newDN[i] = newRDN;
+
+ for ( tag = ber_first_element( ber, &len, &rdn_end );
+ tag == LBER_SEQUENCE;
+ tag = ber_next_element( ber, &len, rdn_end )) {
+
+ *newRDN++ = newAVA;
+ tag = ber_skip_tag( ber, &len );
+ tag = ber_get_stringbv( ber, &Oid, LBER_BV_NOTERM );
+ if ( tag != LBER_TAG_OID ) {
+ rc = LDAP_DECODING_ERROR;
+ goto nomem;
+ }
+
+ oid2.bv_val = oidptr;
+ oid2.bv_len = oidrem;
+ if ( ber_decode_oid( &Oid, &oid2 ) < 0 ) {
+ rc = LDAP_DECODING_ERROR;
+ goto nomem;
+ }
+ oidname = find_oid( &oid2 );
+ if ( !oidname ) {
+ newAVA->la_attr = oid2;
+ oidptr += oid2.bv_len + 1;
+ oidrem -= oid2.bv_len + 1;
+
+ /* Running out of OID buffer space? */
+ if (oidrem < 128) {
+ if ( oidsize == 0 ) {
+ oidsize = sizeof(oids) * 2;
+ oidrem = oidsize;
+ oidbuf = LDAP_MALLOC( oidsize );
+ if ( oidbuf == NULL ) goto nomem;
+ oidptr = oidbuf;
+ } else {
+ char *old = oidbuf;
+ oidbuf = LDAP_REALLOC( oidbuf, oidsize*2 );
+ if ( oidbuf == NULL ) goto nomem;
+ /* Buffer moved! Fix AVA pointers */
+ if ( old != oidbuf ) {
+ LDAPAVA *a;
+ long dif = oidbuf - old;
+
+ for (a=baseAVA; a<=newAVA; a++){
+ if (a->la_attr.bv_val >= old &&
+ a->la_attr.bv_val <= (old + oidsize))
+ a->la_attr.bv_val += dif;
+ }
+ }
+ oidptr = oidbuf + oidsize - oidrem;
+ oidrem += oidsize;
+ oidsize *= 2;
+ }
+ }
+ } else {
+ if ( func ) {
+ newAVA->la_attr = oidname->oid;
+ } else {
+ newAVA->la_attr = oidname->name;
+ }
+ }
+ tag = ber_get_stringbv( ber, &Val, LBER_BV_NOTERM );
+ switch(tag) {
+ case LBER_TAG_UNIVERSAL:
+ /* This uses 32-bit ISO 10646-1 */
+ csize = 4; goto to_utf8;
+ case LBER_TAG_BMP:
+ /* This uses 16-bit ISO 10646-1 */
+ csize = 2; goto to_utf8;
+ case LBER_TAG_TELETEX:
+ /* This uses 8-bit, assume ISO 8859-1 */
+ csize = 1;
+to_utf8: rc = ldap_ucs_to_utf8s( &Val, csize, &newAVA->la_value );
+ newAVA->la_flags |= LDAP_AVA_FREE_VALUE;
+ if (rc != LDAP_SUCCESS) goto nomem;
+ newAVA->la_flags = LDAP_AVA_NONPRINTABLE;
+ break;
+ case LBER_TAG_UTF8:
+ newAVA->la_flags = LDAP_AVA_NONPRINTABLE;
+ /* This is already in UTF-8 encoding */
+ case LBER_TAG_IA5:
+ case LBER_TAG_PRINTABLE:
+ /* These are always 7-bit strings */
+ newAVA->la_value = Val;
+ default:
+ ;
+ }
+ newAVA->la_private = NULL;
+ newAVA->la_flags = LDAP_AVA_STRING;
+ newAVA++;
+ }
+ *newRDN++ = NULL;
+ tag = ber_next_element( ber, &len, dn_end );
+ }
+
+ if ( func ) {
+ rc = func( newDN, flags, NULL );
+ if ( rc != LDAP_SUCCESS )
+ goto nomem;
+ }
+
+ rc = ldap_dn2bv_x( newDN, bv, LDAP_DN_FORMAT_LDAPV3, NULL );
+
+nomem:
+ for (;baseAVA < newAVA; baseAVA++) {
+ if (baseAVA->la_flags & LDAP_AVA_FREE_ATTR)
+ LDAP_FREE( baseAVA->la_attr.bv_val );
+ if (baseAVA->la_flags & LDAP_AVA_FREE_VALUE)
+ LDAP_FREE( baseAVA->la_value.bv_val );
+ }
+
+ if ( oidsize != 0 )
+ LDAP_FREE( oidbuf );
+ if ( newDN != (LDAPDN)(char *) ptrs )
+ LDAP_FREE( newDN );
+ return rc;
+}
+
/*
* LDAP URLs look like this:
- * ldap[is]://host:port[/[dn[?[attributes][?[scope][?[filter][?exts]]]]]]
+ * ldap[is]://host[:port][/[dn[?[attributes][?[scope][?[filter][?exts]]]]]]
*
* where:
* attributes is a comma separated list
{
int sep = 0;
int len = 0;
+ int is_ipc = 0;
struct berval scope;
- if ( u == NULL ) {
+ if ( u == NULL || u->lud_scheme == NULL ) {
return -1;
}
+ if ( !strcmp( "ldapi", u->lud_scheme )) {
+ is_ipc = 1;
+ }
+
if ( u->lud_exts ) {
len += hex_escape_len_list( u->lud_exts, URLESC_COMMA );
if ( !sep ) {
}
if ( u->lud_filter ) {
- len += hex_escape_len( u->lud_filter, URLESC_NONE );
+ len += hex_escape_len( u->lud_filter, URLESC_NONE );
if ( !sep ) {
sep = 4;
}
}
if ( u->lud_attrs ) {
- len += hex_escape_len_list( u->lud_attrs, URLESC_NONE );
+ len += hex_escape_len_list( u->lud_attrs, URLESC_NONE );
if ( !sep ) {
sep = 2;
}
} else {
if ( u->lud_host && u->lud_host[0] ) {
len += hex_escape_len( u->lud_host, URLESC_SLASH );
+ if ( !is_ipc && strchr( u->lud_host, ':' )) {
+ len += 2; /* IPv6, [] */
+ }
}
}
return len;
}
-int
+static int
desc2str( LDAPURLDesc *u, char *s, int len )
{
int i;
int sep = 0;
int sofar = 0;
+ int is_v6 = 0;
+ int is_ipc = 0;
struct berval scope = BER_BVNULL;
if ( u == NULL ) {
return -1;
}
+ if ( u->lud_scheme && !strcmp( "ldapi", u->lud_scheme )) {
+ is_ipc = 1;
+ }
+
ldap_pvt_scope2bv( u->lud_scope, &scope );
if ( u->lud_exts ) {
sep = 1;
}
+ if ( !is_ipc && u->lud_host && strchr( u->lud_host, ':' )) {
+ is_v6 = 1;
+ }
+
if ( u->lud_port ) {
- len -= sprintf( s, "%s://%s:%d%n", u->lud_scheme,
+ len -= sprintf( s, "%s://%s%s%s:%d%n", u->lud_scheme,
+ is_v6 ? "[" : "",
u->lud_host ? u->lud_host : "",
+ is_v6 ? "]" : "",
u->lud_port, &sofar );
} else {
len -= sprintf( s, "%s://%n", u->lud_scheme, &sofar );
if ( u->lud_host && u->lud_host[0] ) {
+ if ( is_v6 ) {
+ s[sofar++] = '[';
+ len--;
+ }
i = hex_escape( &s[sofar], len, u->lud_host, URLESC_SLASH );
sofar += i;
len -= i;
+ if ( is_v6 ) {
+ s[sofar++] = ']';
+ len--;
+ }
}
}
LDAPURLDesc *ludp;
char *p, *q, *r;
- int i, enclosed;
+ int i, enclosed, proto, is_v6 = 0;
const char *scheme = NULL;
const char *url_tmp;
char *url;
assert( scheme != NULL );
+ proto = ldap_pvt_url_scheme2proto( scheme );
+ if ( proto == -1 ) {
+ return LDAP_URL_ERR_BADSCHEME;
+ }
+
/* make working copy of the remainder of the URL */
url = LDAP_STRDUP( url_tmp );
if ( url == NULL ) {
/* scan forward for '/' that marks end of hostport and begin. of dn */
p = strchr( url, '/' );
+ q = NULL;
if( p != NULL ) {
/* terminate hostport; point to start of dn */
*p++ = '\0';
+ } else {
+ /* check for Novell kludge, see below */
+ p = strchr( url, '?' );
+ if ( p ) {
+ *p++ = '\0';
+ q = p;
+ p = NULL;
+ }
}
- /* IPv6 syntax with [ip address]:port */
- if ( *url == '[' ) {
- r = strchr( url, ']' );
- if ( r == NULL ) {
- LDAP_FREE( url );
- ldap_free_urldesc( ludp );
- return LDAP_URL_ERR_BADURL;
+ if ( proto != LDAP_PROTO_IPC ) {
+ /* IPv6 syntax with [ip address]:port */
+ if ( *url == '[' ) {
+ r = strchr( url, ']' );
+ if ( r == NULL ) {
+ LDAP_FREE( url );
+ ldap_free_urldesc( ludp );
+ return LDAP_URL_ERR_BADURL;
+ }
+ *r++ = '\0';
+ q = strchr( r, ':' );
+ if ( q && q != r ) {
+ LDAP_FREE( url );
+ ldap_free_urldesc( ludp );
+ return LDAP_URL_ERR_BADURL;
+ }
+ is_v6 = 1;
+ } else {
+ q = strchr( url, ':' );
}
- *r++ = '\0';
- q = strchr( r, ':' );
- } else {
- q = strchr( url, ':' );
- }
- if ( q != NULL ) {
- char *next;
+ if ( q != NULL ) {
+ char *next;
- *q++ = '\0';
- ldap_pvt_hex_unescape( q );
+ *q++ = '\0';
+ ldap_pvt_hex_unescape( q );
- if( *q == '\0' ) {
- LDAP_FREE( url );
- ldap_free_urldesc( ludp );
- return LDAP_URL_ERR_BADURL;
- }
+ if( *q == '\0' ) {
+ LDAP_FREE( url );
+ ldap_free_urldesc( ludp );
+ return LDAP_URL_ERR_BADURL;
+ }
- ludp->lud_port = strtol( q, &next, 10 );
- if ( next == q || next[0] != '\0' ) {
- LDAP_FREE( url );
- ldap_free_urldesc( ludp );
- return LDAP_URL_ERR_BADURL;
+ ludp->lud_port = strtol( q, &next, 10 );
+ if ( next == q || next[0] != '\0' ) {
+ LDAP_FREE( url );
+ ldap_free_urldesc( ludp );
+ return LDAP_URL_ERR_BADURL;
+ }
+ /* check for Novell kludge */
+ if ( !p ) {
+ if ( *next != '\0' ) {
+ q = &next[1];
+ } else {
+ q = NULL;
+ }
+ }
}
- }
- if ( ( flags & LDAP_PVT_URL_PARSE_DEF_PORT ) && ludp->lud_port == 0 ) {
- if ( strcmp( ludp->lud_scheme, "ldap" ) == 0 ) {
- ludp->lud_port = LDAP_PORT;
-#ifdef LDAP_CONNECTIONLESS
- } else if ( strcmp( ludp->lud_scheme, "cldap" ) == 0 ) {
- ludp->lud_port = LDAP_PORT;
-#endif
- } else if ( strcmp( ludp->lud_scheme, "ldaps" ) == 0 ) {
- ludp->lud_port = LDAPS_PORT;
+ if ( ( flags & LDAP_PVT_URL_PARSE_DEF_PORT ) && ludp->lud_port == 0 ) {
+ if ( strcmp( ludp->lud_scheme, "ldaps" ) == 0 ) {
+ ludp->lud_port = LDAPS_PORT;
+ } else {
+ ludp->lud_port = LDAP_PORT;
+ }
}
}
ldap_pvt_hex_unescape( url );
/* If [ip address]:port syntax, url is [ip and we skip the [ */
- ludp->lud_host = LDAP_STRDUP( url + ( *url == '[' ) );
+ ludp->lud_host = LDAP_STRDUP( url + is_v6 );
if( ludp->lud_host == NULL ) {
LDAP_FREE( url );
* but we need to account for it. Fortunately it can't be confused with
* anything real.
*/
- if( (p == NULL) && (q != NULL) && ((q = strchr( q, '?')) != NULL)) {
- q++;
+ if( (p == NULL) && (q != NULL) && (*q == '?') ) {
/* ? immediately followed by question */
- if( *q == '?') {
- q++;
- if( *q != '\0' ) {
- /* parse dn part */
- ldap_pvt_hex_unescape( q );
- ludp->lud_dn = LDAP_STRDUP( q );
+ q++;
+ if( *q != '\0' ) {
+ /* parse dn part */
+ ldap_pvt_hex_unescape( q );
+ ludp->lud_dn = LDAP_STRDUP( q );
- } else if ( !( flags & LDAP_PVT_URL_PARSE_NOEMPTY_DN ) ) {
- ludp->lud_dn = LDAP_STRDUP( "" );
+ } else if ( !( flags & LDAP_PVT_URL_PARSE_NOEMPTY_DN ) ) {
+ ludp->lud_dn = LDAP_STRDUP( "" );
- } else {
- check_dn = 0;
- }
+ } else {
+ check_dn = 0;
+ }
- if ( check_dn && ludp->lud_dn == NULL ) {
- LDAP_FREE( url );
- ldap_free_urldesc( ludp );
- return LDAP_URL_ERR_MEM;
- }
+ if ( check_dn && ludp->lud_dn == NULL ) {
+ LDAP_FREE( url );
+ ldap_free_urldesc( ludp );
+ return LDAP_URL_ERR_MEM;
}
}
}
}
+ fprintf( stdout, "URL: %s\n", ldap_url_desc2str( lud ));
+
return EXIT_SUCCESS;
}
LDAPControl **ctrlp )
{
struct berval value;
- BerElement *ber;
if ( ctrlp == NULL ) {
ld->ld_errno = LDAP_PARAM_ERROR;
ld->ld_errno = ldap_create_vlv_control_value( ld, vlvinfop, &value );
if ( ld->ld_errno == LDAP_SUCCESS ) {
- if ((ber = ldap_alloc_ber_with_options(ld)) == NULL) {
- ld->ld_errno = LDAP_NO_MEMORY;
- return LDAP_NO_MEMORY;
- }
- ld->ld_errno = ldap_create_control( LDAP_CONTROL_VLVREQUEST,
- ber, 1, ctrlp );
- if ( ld->ld_errno == LDAP_SUCCESS ) {
- (*ctrlp)->ldctl_value = value;
- } else {
+ ld->ld_errno = ldap_control_create( LDAP_CONTROL_VLVREQUEST,
+ 1, &value, 0, ctrlp );
+ if ( ld->ld_errno != LDAP_SUCCESS ) {
LDAP_FREE( value.bv_val );
}
- ber_free(ber, 1);
}
return ld->ld_errno;
request.c os-ip.c url.c pagectrl.c sortctrl.c vlvctrl.c \
init.c options.c print.c string.c util-int.c schema.c \
charray.c tls.c os-local.c dnssrv.c utf-8.c utf-8-conv.c \
- turn.c ppolicy.c dds.c txn.c ldap_sync.c
+ turn.c ppolicy.c dds.c txn.c ldap_sync.c stctrl.c
SRCS = threads.c rdwr.c rmutex.c tpool.c rq.c \
thr_posix.c thr_cthreads.c thr_thr.c thr_lwp.c thr_nt.c \
thr_pth.c thr_stub.c thr_debug.c
request.lo os-ip.lo url.lo pagectrl.lo sortctrl.lo vlvctrl.lo \
init.lo options.lo print.lo string.lo util-int.lo schema.lo \
charray.lo tls.lo os-local.lo dnssrv.lo utf-8.lo utf-8-conv.lo \
- turn.lo ppolicy.lo dds.lo txn.lo ldap_sync.lo
+ turn.lo ppolicy.lo dds.lo txn.lo ldap_sync.lo stctrl.lo
LDAP_INCDIR= ../../include
LDAP_LIBDIR= ../../libraries
*
* Run-time configuration:
*
- * Setup of memory debugging tools:
+ * Memory debugging tools:
* Tools that report uninitialized memory accesses should disable
* such warnings about the function debug_already_initialized().
* Alternatively, include "noreinit" (below) in $LDAP_THREAD_DEBUG.
if( s != NULL ) {
while( *(s += strspn( s, ", \t\r\n" )) != '\0' ) {
size_t optlen = strcspn( s, ", \t\r\n" );
- const struct option_info_s *oi;
- for( oi = option_info; oi->name; oi++ ) {
- if( strncasecmp( oi->name, s, optlen ) == 0 ) {
- if( oi->name && oi->name[optlen] == '\0' ) {
- *oi->var = oi->val;
- } else {
- fprintf( stderr,
- "== thr_debug: Unknown $%s option '%.*s' ==\n",
- "LDAP_THREAD_DEBUG", (int) optlen, s );
- }
- break;
- }
- }
+ const struct option_info_s *oi = option_info;
+ while( oi->name &&
+ (strncasecmp( oi->name, s, optlen ) || oi->name[optlen]) )
+ oi++;
+ if( oi->name )
+ *oi->var = oi->val;
+ else
+ fprintf( stderr,
+ "== thr_debug: Unknown $%s option '%.*s' ==\n",
+ "LDAP_THREAD_DEBUG", (int) optlen, s );
s += optlen;
}
}
static void debug_noop( void );
static int debug_already_initialized( const ldap_debug_usage_info_t *usage );
-/* Names used to give clearer error messages */
+/* Name used for clearer error message */
#define IS_COPY_OR_MOVED(usage) ((usage)->self != SCRAMBLE( usage ))
-enum { Is_destroyed = 1 };
#define DUMMY_ADDR(usage) \
(wraptype == Wrap_scramble \
free( dummy );
} );
}
- usage->self = SCRAMBLE( usage );
if( wraptype != Wrap_noalloc ) {
unsigned char *dummy = malloc( 1 );
assert( dummy != NULL );
if( wraptype == Wrap_scramble ) {
usage->mem.num = SCRAMBLE( dummy );
+ /* Verify that ptr<->integer casts work on this host */
assert( UNSCRAMBLE_dummyp( usage->mem.num ) == dummy );
} else {
usage->mem.ptr = dummy + wrap_offset;
}
}
+ } else {
+ /* Unused, but set for readability in debugger */
+ usage->mem.ptr = NULL;
}
+ usage->self = SCRAMBLE( usage ); /* If nomem, only for debugger */
usage->magic = ldap_debug_magic;
usage->state = ldap_debug_state_inited;
}
static void
check_usage( const ldap_debug_usage_info_t *usage, const char *msg )
{
+ enum { Is_destroyed = 1 }; /* Name used for clearer error message */
+
if( usage->magic != ldap_debug_magic ) {
ERROR( usage->magic, msg );
return;
{
}
-/* Return true if the resource is initialized and not copied/realloced. */
-/* Valid programs access uninitialized memory here unless "noreinit". */
+/*
+ * Valid programs access uninitialized memory here unless "noreinit".
+ *
+ * Returns true if the resource is initialized and not copied/realloced.
+ */
static int
debug_already_initialized( const ldap_debug_usage_info_t *usage )
{
- return (usage->state == ldap_debug_state_inited &&
- !IS_COPY_OR_MOVED( usage ) &&
- usage->magic == ldap_debug_magic);
+ /*
+ * 'ret' keeps the Valgrind warning "Conditional jump or move
+ * depends on uninitialised value(s)" _inside_ this function.
+ */
+ volatile int ret = 0;
+ if( usage->state == ldap_debug_state_inited )
+ if( !IS_COPY_OR_MOVED( usage ) )
+ if( usage->magic == ldap_debug_magic )
+ ret = 1;
+ return ret;
}
#endif /* LDAP_THREAD_DEBUG_WRAP */
#if !(LDAP_THREAD_DEBUG_THREAD_ID +0)
-typedef int ldap_debug_thread_t;
+typedef void ldap_debug_thread_t;
#define init_thread_info() {}
#define with_thread_info_lock(statements) { statements; }
#define thread_info_detached(t) 0
(thread_info[thread_info_used] = t )->idx = thread_info_used;
}
-ldap_debug_thread_t *
-get_thread_info( ldap_pvt_thread_t *thread, const char *msg )
+static ldap_debug_thread_t *
+get_thread_info( ldap_pvt_thread_t thread, const char *msg )
{
unsigned int i;
ldap_debug_thread_t *t;
for( i = 0; i < thread_info_used; i++ ) {
- if( ldap_pvt_thread_equal( *thread, thread_info[i]->wrapped ) )
+ if( ldap_pvt_thread_equal( thread, thread_info[i]->wrapped ) )
break;
}
ERROR_IF( i == thread_info_used, msg );
thread_exiting( const char *how, const char *msg )
{
ldap_pvt_thread_t thread;
+#if 0 /* Detached threads may exit after ldap_debug_thread_destroy(). */
ERROR_IF( !threading_enabled, msg );
+#endif
thread = ldap_pvt_thread_self();
if( tracethreads ) {
char buf[40];
}
if( threadID ) {
with_thread_info_lock({
- ldap_debug_thread_t *t = get_thread_info(
- &thread, msg );
+ ldap_debug_thread_t *t = get_thread_info( thread, msg );
if( thread_info_detached( t ) )
remove_thread_info( t, msg );
});
}
if( rc ) {
ERROR( rc, "ldap_pvt_thread_create" );
+ if( wrap_threads )
+ free( arg );
} else {
if( tracethreads ) {
char buf[40], buf2[40];
}
if( threadID )
with_thread_info_lock( {
- t = get_thread_info( &thread, "ldap_pvt_thread_join" );
+ t = get_thread_info( thread, "ldap_pvt_thread_join" );
ERROR_IF( thread_info_detached( t ), "ldap_pvt_thread_join" );
} );
rc = ldap_int_thread_join( thread, thread_return );
{
int rc, has_pool;
ERROR_IF( !threading_enabled, "ldap_pvt_thread_pool_submit" );
- has_pool = (tpool != NULL && *tpool != NULL);
+ has_pool = (tpool && *tpool);
rc = ldap_int_thread_pool_submit( tpool, start_routine, arg );
if( has_pool )
ERROR_IF( rc, "ldap_pvt_thread_pool_submit" );
{
int rc, has_pool;
ERROR_IF( !threading_enabled, "ldap_pvt_thread_pool_destroy" );
- has_pool = (tpool != NULL && *tpool != NULL);
+ has_pool = (tpool && *tpool);
rc = ldap_int_thread_pool_destroy( tpool, run_pending );
if( has_pool ) {
if( rc ) {
# define LDAP_INT_THREAD_MUTEXATTR_DEFAULT &mutex_attr
#endif
+#if HAVE_PTHREADS < 7
+#define ERRVAL(val) ((val) < 0 ? errno : 0)
+#else
+#define ERRVAL(val) (val)
+#endif
+
int
ldap_int_thread_initialize( void )
{
{
#ifdef HAVE_PTHREAD_SETCONCURRENCY
return pthread_setconcurrency( n );
-#elif HAVE_THR_SETCONCURRENCY
+#elif defined(HAVE_THR_SETCONCURRENCY)
return thr_setconcurrency( n );
#else
return 0;
{
#ifdef HAVE_PTHREAD_GETCONCURRENCY
return pthread_getconcurrency();
-#elif HAVE_THR_GETCONCURRENCY
+#elif defined(HAVE_THR_GETCONCURRENCY)
return thr_getconcurrency();
#else
return 0;
#else
rtn = pthread_create( thread, &attr, start_routine, arg );
#endif
+
#if HAVE_PTHREADS > 5
pthread_attr_destroy(&attr);
#else
{
#if HAVE_PTHREADS < 7
void *dummy;
-
if (thread_return==NULL)
thread_return=&dummy;
-
- if ( pthread_join( thread, thread_return ) < 0 ) return errno;
- return 0;
-#else
- return pthread_join( thread, thread_return );
#endif
+ return ERRVAL( pthread_join( thread, thread_return ) );
}
int
ldap_pvt_thread_kill( ldap_pvt_thread_t thread, int signo )
{
-#if ( HAVE_PTHREAD_KILL && HAVE_PTHREADS > 6 )
+#if defined(HAVE_PTHREAD_KILL) && HAVE_PTHREADS > 4
/* MacOS 10.1 is detected as v10 but has no pthread_kill() */
- return pthread_kill( thread, signo );
-#elif ( HAVE_PTHREAD_KILL && HAVE_PTHREADS > 4 )
- if ( pthread_kill( thread, signo ) < 0 ) return errno;
- return 0;
+ return ERRVAL( pthread_kill( thread, signo ) );
#else
/* pthread package with DCE */
if (kill( getpid(), signo )<0)
select( 0, NULL, NULL, NULL, &tv );
#endif
return 0;
-#elif HAVE_THR_YIELD
+
+#elif defined(HAVE_THR_YIELD)
thr_yield();
return 0;
#elif HAVE_PTHREADS == 6
pthread_yield(NULL);
return 0;
+
#else
pthread_yield();
return 0;
int
ldap_pvt_thread_cond_init( ldap_pvt_thread_cond_t *cond )
{
-#if HAVE_PTHREADS < 7
- if ( pthread_cond_init( cond, LDAP_INT_THREAD_CONDATTR_DEFAULT ) < 0 )
- return errno;
- return 0;
-#else
- return pthread_cond_init( cond, LDAP_INT_THREAD_CONDATTR_DEFAULT );
-#endif
+ return ERRVAL( pthread_cond_init(
+ cond, LDAP_INT_THREAD_CONDATTR_DEFAULT ) );
}
int
ldap_pvt_thread_cond_destroy( ldap_pvt_thread_cond_t *cond )
{
-#if HAVE_PTHREADS < 7
- if ( pthread_cond_destroy( cond ) < 0 ) return errno;
- return 0;
-#else
- return pthread_cond_destroy( cond );
-#endif
+ return ERRVAL( pthread_cond_destroy( cond ) );
}
int
ldap_pvt_thread_cond_signal( ldap_pvt_thread_cond_t *cond )
{
-#if HAVE_PTHREADS < 7
- if ( pthread_cond_signal( cond ) < 0 ) return errno;
- return 0;
-#else
- return pthread_cond_signal( cond );
-#endif
+ return ERRVAL( pthread_cond_signal( cond ) );
}
int
ldap_pvt_thread_cond_broadcast( ldap_pvt_thread_cond_t *cond )
{
-#if HAVE_PTHREADS < 7
- if ( pthread_cond_broadcast( cond ) < 0 ) return errno;
- return 0;
-#else
- return pthread_cond_broadcast( cond );
-#endif
+ return ERRVAL( pthread_cond_broadcast( cond ) );
}
int
ldap_pvt_thread_cond_wait( ldap_pvt_thread_cond_t *cond,
ldap_pvt_thread_mutex_t *mutex )
{
-#if HAVE_PTHREADS < 7
- if ( pthread_cond_wait( cond, mutex ) < 0 ) return errno;
- return 0;
-#else
- return pthread_cond_wait( cond, mutex );
-#endif
+ return ERRVAL( pthread_cond_wait( cond, mutex ) );
}
int
ldap_pvt_thread_mutex_init( ldap_pvt_thread_mutex_t *mutex )
{
-#if HAVE_PTHREADS < 7
- if ( pthread_mutex_init( mutex, LDAP_INT_THREAD_MUTEXATTR_DEFAULT )<0)
- return errno;
- return 0;
-#else
- return pthread_mutex_init( mutex, LDAP_INT_THREAD_MUTEXATTR_DEFAULT );
-#endif
+ return ERRVAL( pthread_mutex_init(
+ mutex, LDAP_INT_THREAD_MUTEXATTR_DEFAULT ) );
}
int
ldap_pvt_thread_mutex_destroy( ldap_pvt_thread_mutex_t *mutex )
{
-#if HAVE_PTHREADS < 7
- if ( pthread_mutex_destroy( mutex ) < 0 ) return errno;
- return 0;
-#else
- return pthread_mutex_destroy( mutex );
-#endif
+ return ERRVAL( pthread_mutex_destroy( mutex ) );
}
int
ldap_pvt_thread_mutex_lock( ldap_pvt_thread_mutex_t *mutex )
{
-#if HAVE_PTHREADS < 7
- if ( pthread_mutex_lock( mutex ) < 0 ) return errno;
- return 0;
-#else
- return pthread_mutex_lock( mutex );
-#endif
+ return ERRVAL( pthread_mutex_lock( mutex ) );
}
int
ldap_pvt_thread_mutex_trylock( ldap_pvt_thread_mutex_t *mutex )
{
-#if HAVE_PTHREADS < 7
- if ( pthread_mutex_trylock( mutex ) < 0 ) return errno;
- return 0;
-#else
- return pthread_mutex_trylock( mutex );
-#endif
+ return ERRVAL( pthread_mutex_trylock( mutex ) );
}
int
ldap_pvt_thread_mutex_unlock( ldap_pvt_thread_mutex_t *mutex )
{
-#if HAVE_PTHREADS < 7
- if ( pthread_mutex_unlock( mutex ) < 0 ) return errno;
- return 0;
-#else
- return pthread_mutex_unlock( mutex );
-#endif
+ return ERRVAL( pthread_mutex_unlock( mutex ) );
}
ldap_pvt_thread_t ldap_pvt_thread_self( void )
int
ldap_pvt_thread_rdwr_init( ldap_pvt_thread_rdwr_t *rw )
{
-#if HAVE_PTHREADS < 7
- if ( pthread_rwlock_init( rw, NULL ) < 0 ) return errno;
- return 0;
-#else
- return pthread_rwlock_init( rw, NULL );
-#endif
+ return ERRVAL( pthread_rwlock_init( rw, NULL ) );
}
int
ldap_pvt_thread_rdwr_destroy( ldap_pvt_thread_rdwr_t *rw )
{
-#if HAVE_PTHREADS < 7
- if ( pthread_rwlock_destroy( rw ) < 0 ) return errno;
- return 0;
-#else
- return pthread_rwlock_destroy( rw );
-#endif
+ return ERRVAL( pthread_rwlock_destroy( rw ) );
}
int ldap_pvt_thread_rdwr_rlock( ldap_pvt_thread_rdwr_t *rw )
{
-#if HAVE_PTHREADS < 7
- if ( pthread_rwlock_rdlock( rw ) < 0 ) return errno;
- return 0;
-#else
- return pthread_rwlock_rdlock( rw );
-#endif
+ return ERRVAL( pthread_rwlock_rdlock( rw ) );
}
int ldap_pvt_thread_rdwr_rtrylock( ldap_pvt_thread_rdwr_t *rw )
{
-#if HAVE_PTHREADS < 7
- if ( pthread_rwlock_tryrdlock( rw ) < 0 ) return errno;
- return 0;
-#else
- return pthread_rwlock_tryrdlock( rw );
-#endif
+ return ERRVAL( pthread_rwlock_tryrdlock( rw ) );
}
int ldap_pvt_thread_rdwr_runlock( ldap_pvt_thread_rdwr_t *rw )
{
-#if HAVE_PTHREADS < 7
- if ( pthread_rwlock_unlock( rw ) < 0 ) return errno;
- return 0;
-#else
- return pthread_rwlock_unlock( rw );
-#endif
+ return ERRVAL( pthread_rwlock_unlock( rw ) );
}
int ldap_pvt_thread_rdwr_wlock( ldap_pvt_thread_rdwr_t *rw )
{
-#if HAVE_PTHREADS < 7
- if ( pthread_rwlock_wrlock( rw ) < 0 ) return errno;
- return 0;
-#else
- return pthread_rwlock_wrlock( rw );
-#endif
+ return ERRVAL( pthread_rwlock_wrlock( rw ) );
}
int ldap_pvt_thread_rdwr_wtrylock( ldap_pvt_thread_rdwr_t *rw )
{
-#if HAVE_PTHREADS < 7
- if ( pthread_rwlock_trywrlock( rw ) < 0 ) return errno;
- return 0;
-#else
- return pthread_rwlock_trywrlock( rw );
-#endif
+ return ERRVAL( pthread_rwlock_trywrlock( rw ) );
}
int ldap_pvt_thread_rdwr_wunlock( ldap_pvt_thread_rdwr_t *rw )
{
-#if HAVE_PTHREADS < 7
- if ( pthread_rwlock_unlock( rw ) < 0 ) return errno;
- return 0;
-#else
- return pthread_rwlock_unlock( rw );
-#endif
+ return ERRVAL( pthread_rwlock_unlock( rw ) );
}
#endif /* HAVE_PTHREAD_RWLOCK_DESTROY */
typedef enum ldap_int_thread_pool_state_e {
LDAP_INT_THREAD_POOL_RUNNING,
LDAP_INT_THREAD_POOL_FINISHING,
- LDAP_INT_THREAD_POOL_STOPPING,
- LDAP_INT_THREAD_POOL_PAUSING
+ LDAP_INT_THREAD_POOL_STOPPING
} ldap_int_thread_pool_state_t;
+/* Thread-specific key with data and optional free function */
typedef struct ldap_int_thread_key_s {
void *ltk_key;
void *ltk_data;
* We don't expect to use many...
*/
#define MAXKEYS 32
+
+/* Max number of threads */
#define LDAP_MAXTHR 1024 /* must be a power of 2 */
+/* Context: thread ID and thread-specific key/data pairs */
typedef struct ldap_int_thread_userctx_s {
ldap_pvt_thread_t ltu_id;
ldap_int_thread_key_t ltu_key[MAXKEYS];
} ldap_int_thread_userctx_t;
-static ldap_pvt_thread_t tid_zero;
+/* Simple {thread ID -> context} hash table; key=ctx->ltu_id.
+ * Protected by ldap_pvt_thread_pool_mutex except during pauses,
+ * when it is read-only (used by pool_purgekey and pool_context).
+ * Protected by tpool->ltp_mutex during pauses.
+ */
static struct {
- ldap_pvt_thread_t id;
ldap_int_thread_userctx_t *ctx;
+ /* ctx is valid when not NULL or DELETED_THREAD_CTX */
+# define DELETED_THREAD_CTX (&ldap_int_main_thrctx + 1) /* dummy addr */
} thread_keys[LDAP_MAXTHR];
-
-typedef struct ldap_int_thread_ctx_s {
+#define TID_HASH(tid, hash) do { \
+ unsigned const char *ptr_ = (unsigned const char *)&(tid); \
+ unsigned i_; \
+ for (i_ = 0, (hash) = ptr_[0]; ++i_ < sizeof(tid);) \
+ (hash) += ((hash) << 5) ^ ptr_[i_]; \
+} while(0)
+
+
+/* Task for a thread to perform */
+typedef struct ldap_int_thread_task_s {
union {
- LDAP_STAILQ_ENTRY(ldap_int_thread_ctx_s) q;
- LDAP_SLIST_ENTRY(ldap_int_thread_ctx_s) l;
- LDAP_SLIST_ENTRY(ldap_int_thread_ctx_s) al;
- } ltc_next;
- ldap_pvt_thread_start_t *ltc_start_routine;
- void *ltc_arg;
-} ldap_int_thread_ctx_t;
+ LDAP_STAILQ_ENTRY(ldap_int_thread_task_s) q;
+ LDAP_SLIST_ENTRY(ldap_int_thread_task_s) l;
+ } ltt_next;
+ ldap_pvt_thread_start_t *ltt_start_routine;
+ void *ltt_arg;
+} ldap_int_thread_task_t;
struct ldap_int_thread_pool_s {
LDAP_STAILQ_ENTRY(ldap_int_thread_pool_s) ltp_next;
+
+ /* protect members below, and protect thread_keys[] during pauses */
ldap_pvt_thread_mutex_t ltp_mutex;
+
+ /* not paused and something to do for pool_<wrapper/pause/destroy>() */
ldap_pvt_thread_cond_t ltp_cond;
+
+ /* ltp_active_count <= 1 && ltp_pause */
ldap_pvt_thread_cond_t ltp_pcond;
- LDAP_STAILQ_HEAD(tcq, ldap_int_thread_ctx_s) ltp_pending_list;
- LDAP_SLIST_HEAD(tcl, ldap_int_thread_ctx_s) ltp_free_list;
- LDAP_SLIST_HEAD(tclq, ldap_int_thread_ctx_s) ltp_active_list;
+
+ /* pending tasks, and unused task objects */
+ LDAP_STAILQ_HEAD(tcq, ldap_int_thread_task_s) ltp_pending_list;
+ LDAP_SLIST_HEAD(tcl, ldap_int_thread_task_s) ltp_free_list;
+
ldap_int_thread_pool_state_t ltp_state;
- long ltp_max_count;
- long ltp_max_pending;
- long ltp_pending_count;
- long ltp_active_count;
- long ltp_open_count;
- long ltp_starting;
+
+ /* some active request needs to be the sole active request */
+ int ltp_pause;
+
+ long ltp_max_count; /* max number of threads in pool, or 0 */
+ long ltp_max_pending; /* max pending or paused requests, or 0 */
+ long ltp_pending_count; /* pending or paused requests */
+ long ltp_active_count; /* active, not paused requests */
+ long ltp_open_count; /* number of threads */
+ long ltp_starting; /* currenlty starting threads */
};
+static int ldap_int_has_thread_pool = 0;
static LDAP_STAILQ_HEAD(tpq, ldap_int_thread_pool_s)
ldap_int_thread_pool_list =
LDAP_STAILQ_HEAD_INITIALIZER(ldap_int_thread_pool_list);
static void *ldap_int_thread_pool_wrapper( void *pool );
-static ldap_pvt_thread_t ldap_int_main_tid;
-
+/* Context of the main thread */
static ldap_int_thread_userctx_t ldap_int_main_thrctx;
int
ldap_int_thread_pool_startup ( void )
{
- ldap_int_main_tid = ldap_pvt_thread_self();
- ldap_int_main_thrctx.ltu_id = ldap_int_main_tid;
-
+ ldap_int_main_thrctx.ltu_id = ldap_pvt_thread_self();
return ldap_pvt_thread_mutex_init(&ldap_pvt_thread_pool_mutex);
}
return(0);
}
-typedef struct ldap_lazy_sem_t {
- ldap_pvt_thread_mutex_t ls_mutex;
- ldap_pvt_thread_cond_t ls_cond;
- int ls_sem_value;
- /*
- * when more than ls_lazy_count number of resources
- * becmoes available, the thread wating for the resources will
- * be waken up in order to prevent frequent blocking/waking-up
- */
- unsigned int ls_lazy_count;
- /*
- * only one thread(listener) will wait on this semaphore
- * using a flag instead of a list
- */
- int ls_wait;
-} ldap_lazy_sem_t;
-
-ldap_lazy_sem_t* thread_pool_sem = NULL;
-
-int
-ldap_lazy_sem_init( unsigned int value, unsigned int lazyness )
-{
- thread_pool_sem = (ldap_lazy_sem_t*) LDAP_CALLOC(1,
- sizeof( ldap_lazy_sem_t ));
-
- if( thread_pool_sem == NULL ) return -1;
-
- ldap_pvt_thread_mutex_init( &thread_pool_sem->ls_mutex );
- ldap_pvt_thread_cond_init( &thread_pool_sem->ls_cond );
- thread_pool_sem->ls_sem_value = value;
- thread_pool_sem->ls_lazy_count = lazyness;
- thread_pool_sem->ls_wait = 0;
-
- return 0;
-}
-
-/* FIXME: move to some approprite header */
-int ldap_lazy_sem_dec( ldap_lazy_sem_t* ls );
-int ldap_lazy_sem_wait ( ldap_lazy_sem_t* ls );
-
-/*
- * ldap_lazy_sem_wait is used if a caller is blockable(listener).
- * Otherwise use ldap_lazy_sem_dec (worker)
- */
-int
-ldap_lazy_sem_op_submit( ldap_lazy_sem_t* ls )
-{
- if ( ls == NULL ) return -1;
-
- /* only worker thread has its thread ctx */
- if ( ldap_pvt_thread_pool_context() ) {
- /* worker thread */
- return ldap_lazy_sem_dec( ls );
- } else {
- /* listener */
- return ldap_lazy_sem_wait( ls );
- }
-}
-
-/*
- * test if given semaphore's count is zero.
- * If 0, the caller is blocked
- * If not, the count is decremented.
- */
-int
-ldap_lazy_sem_wait ( ldap_lazy_sem_t* ls )
-{
- ldap_pvt_thread_mutex_lock( &ls->ls_mutex );
-
-lazy_sem_retry:
- if ( ls->ls_sem_value <= 0 ) {
- /* no more avaliable resources */
- ls->ls_wait = 1;
- ldap_pvt_thread_cond_wait( &ls->ls_cond, &ls->ls_mutex );
- goto lazy_sem_retry;
- } else {
- /* avaliable resources */
- ls->ls_sem_value--;
- }
-
- ldap_pvt_thread_mutex_unlock( &ls->ls_mutex );
-
- return 0;
-}
-
-/*
- * decrement the count without blocking
- * even when the count becomes less than or equal to 0
- */
-int
-ldap_lazy_sem_dec( ldap_lazy_sem_t* ls )
-{
- ldap_pvt_thread_mutex_lock( &ls->ls_mutex );
-
- ls->ls_sem_value--;
-
- ldap_pvt_thread_mutex_unlock( &ls->ls_mutex );
-
- return 0;
-}
-
-/*
- * Increment the count by one and test if it is greater or
- * equal to lazyness. If it is, wake up a blocked thread.
- */
-int
-ldap_lazy_sem_post( ldap_lazy_sem_t* ls )
-{
- if( ls == NULL ) return (-1);
-
- ldap_pvt_thread_mutex_lock( &ls->ls_mutex );
-
- ls->ls_sem_value++;
- if ( ls->ls_wait ) {
- if ( ls->ls_sem_value >= ls->ls_lazy_count ) {
- ls->ls_wait = 0;
- ldap_pvt_thread_cond_signal( &ls->ls_cond );
- }
- }
-
- ldap_pvt_thread_mutex_unlock( &ls->ls_mutex );
-
- return 0;
-}
+/* Create a thread pool */
int
ldap_pvt_thread_pool_init (
ldap_pvt_thread_pool_t *tpool,
ldap_pvt_thread_pool_t pool;
int rc;
+ /* multiple pools are currently not supported (ITS#4943) */
+ assert(!ldap_int_has_thread_pool);
+
+ if (! (0 <= max_threads && max_threads <= LDAP_MAXTHR))
+ max_threads = 0;
+ if (max_pending < 0)
+ max_pending = 0;
+
*tpool = NULL;
pool = (ldap_pvt_thread_pool_t) LDAP_CALLOC(1,
sizeof(struct ldap_int_thread_pool_s));
rc = ldap_pvt_thread_cond_init(&pool->ltp_pcond);
if (rc != 0)
return(rc);
+
+ ldap_int_has_thread_pool = 1;
pool->ltp_state = LDAP_INT_THREAD_POOL_RUNNING;
pool->ltp_max_count = max_threads;
pool->ltp_max_pending = max_pending;
LDAP_STAILQ_INIT(&pool->ltp_pending_list);
LDAP_SLIST_INIT(&pool->ltp_free_list);
- LDAP_SLIST_INIT(&pool->ltp_active_list);
ldap_pvt_thread_mutex_lock(&ldap_pvt_thread_pool_mutex);
LDAP_STAILQ_INSERT_TAIL(&ldap_int_thread_pool_list, pool, ltp_next);
ldap_pvt_thread_mutex_unlock(&ldap_pvt_thread_pool_mutex);
ldap_pvt_thread_mutex_lock(&ldap_pvt_thread_pool_mutex);
LDAP_STAILQ_REMOVE(ldap_int_thread_pool_list, pool,
ldap_int_thread_pool_s, ltp_next);
+ ldap_int_has_thread_pool = 0;
ldap_pvt_thread_mutex_unlock(&ldap_pvt_thread_pool_mutex);
ldap_pvt_thread_cond_destroy(&pool->ltp_pcond);
ldap_pvt_thread_cond_destroy(&pool->ltp_cond);
return(0);
}
-#define TID_HASH(tid, hash) do { unsigned i; \
- unsigned char *ptr = (unsigned char *)&(tid); \
- for (i=0, hash=0; i<sizeof(tid); i++) hash += ptr[i]; } while(0)
+/* Submit a task to be performed by the thread pool */
int
ldap_pvt_thread_pool_submit (
ldap_pvt_thread_pool_t *tpool,
ldap_pvt_thread_start_t *start_routine, void *arg )
{
struct ldap_int_thread_pool_s *pool;
- ldap_int_thread_ctx_t *ctx;
- int need_thread = 0;
+ ldap_int_thread_task_t *task;
ldap_pvt_thread_t thr;
if (tpool == NULL)
return(-1);
ldap_pvt_thread_mutex_lock(&pool->ltp_mutex);
- if ((pool->ltp_state != LDAP_INT_THREAD_POOL_RUNNING &&
- pool->ltp_state != LDAP_INT_THREAD_POOL_PAUSING)
- || (pool->ltp_max_pending > 0
+ if (pool->ltp_state != LDAP_INT_THREAD_POOL_RUNNING
+ || (pool->ltp_max_pending
&& pool->ltp_pending_count >= pool->ltp_max_pending))
{
ldap_pvt_thread_mutex_unlock(&pool->ltp_mutex);
return(-1);
}
- ctx = LDAP_SLIST_FIRST(&pool->ltp_free_list);
- if (ctx) {
- LDAP_SLIST_REMOVE_HEAD(&pool->ltp_free_list, ltc_next.l);
+
+ task = LDAP_SLIST_FIRST(&pool->ltp_free_list);
+ if (task) {
+ LDAP_SLIST_REMOVE_HEAD(&pool->ltp_free_list, ltt_next.l);
} else {
- ctx = (ldap_int_thread_ctx_t *) LDAP_MALLOC(
- sizeof(ldap_int_thread_ctx_t));
- if (ctx == NULL) {
+ task = (ldap_int_thread_task_t *) LDAP_MALLOC(sizeof(*task));
+ if (task == NULL) {
ldap_pvt_thread_mutex_unlock(&pool->ltp_mutex);
return(-1);
}
}
- ctx->ltc_start_routine = start_routine;
- ctx->ltc_arg = arg;
+ task->ltt_start_routine = start_routine;
+ task->ltt_arg = arg;
pool->ltp_pending_count++;
- LDAP_STAILQ_INSERT_TAIL(&pool->ltp_pending_list, ctx, ltc_next.q);
- if (pool->ltp_state == LDAP_INT_THREAD_POOL_PAUSING) {
+ LDAP_STAILQ_INSERT_TAIL(&pool->ltp_pending_list, task, ltt_next.q);
+ if (pool->ltp_pause) {
ldap_pvt_thread_mutex_unlock(&pool->ltp_mutex);
return(0);
}
ldap_pvt_thread_cond_signal(&pool->ltp_cond);
if (pool->ltp_open_count < pool->ltp_active_count + pool->ltp_pending_count
- && (pool->ltp_open_count < pool->ltp_max_count ||
- pool->ltp_max_count <= 0 ))
+ && (pool->ltp_open_count <
+ (pool->ltp_max_count ? pool->ltp_max_count : LDAP_MAXTHR)))
{
pool->ltp_open_count++;
pool->ltp_starting++;
- need_thread = 1;
- }
- ldap_pvt_thread_mutex_unlock(&pool->ltp_mutex);
-
-#ifdef LDAP_PVT_THREAD_POOL_SEM_LOAD_CONTROL
- ldap_lazy_sem_op_submit( thread_pool_sem );
-#endif
-
- if (need_thread) {
- int rc;
-
- ldap_pvt_thread_mutex_lock(&pool->ltp_mutex);
-
- rc = ldap_pvt_thread_create( &thr, 1,
- ldap_int_thread_pool_wrapper, pool );
- if (rc == 0) {
- int hash;
- pool->ltp_starting--;
-
- /* assign this thread ID to a key slot; start
- * at the thread ID itself (mod LDAP_MAXTHR) and
- * look for an empty slot.
- */
- TID_HASH(thr, hash);
- for (rc = hash & (LDAP_MAXTHR-1);
- !ldap_pvt_thread_equal(thread_keys[rc].id, tid_zero);
- rc = (rc+1) & (LDAP_MAXTHR-1));
- thread_keys[rc].id = thr;
- } else {
+ if (0 != ldap_pvt_thread_create(
+ &thr, 1, ldap_int_thread_pool_wrapper, pool))
+ {
/* couldn't create thread. back out of
* ltp_open_count and check for even worse things.
*/
- pool->ltp_open_count--;
pool->ltp_starting--;
+ pool->ltp_open_count--;
if (pool->ltp_open_count == 0) {
/* no open threads at all?!?
*/
- ldap_int_thread_ctx_t *ptr;
- LDAP_STAILQ_FOREACH(ptr, &pool->ltp_pending_list, ltc_next.q)
- if (ptr == ctx) break;
- if (ptr == ctx) {
- /* no open threads, context not handled, so
- * back out of ltp_pending_count, free the context,
+ ldap_int_thread_task_t *ptr;
+
+ /* let pool_destroy know there are no more threads */
+ ldap_pvt_thread_cond_signal(&pool->ltp_cond);
+
+ LDAP_STAILQ_FOREACH(ptr, &pool->ltp_pending_list, ltt_next.q)
+ if (ptr == task) break;
+ if (ptr == task) {
+ /* no open threads, task not handled, so
+ * back out of ltp_pending_count, free the task,
* report the error.
*/
- LDAP_STAILQ_REMOVE(&pool->ltp_pending_list, ctx,
- ldap_int_thread_ctx_s, ltc_next.q);
- pool->ltp_pending_count++;
+ LDAP_STAILQ_REMOVE(&pool->ltp_pending_list, task,
+ ldap_int_thread_task_s, ltt_next.q);
+ pool->ltp_pending_count--;
ldap_pvt_thread_mutex_unlock(&pool->ltp_mutex);
- LDAP_FREE(ctx);
+ LDAP_FREE(task);
return(-1);
}
}
/* there is another open thread, so this
- * context will be handled eventually.
- * continue on and signal that the context
- * is waiting.
+ * task will be handled eventually.
+ * continue on, we have signalled that
+ * the task is waiting.
*/
}
- ldap_pvt_thread_mutex_unlock(&pool->ltp_mutex);
}
+ ldap_pvt_thread_mutex_unlock(&pool->ltp_mutex);
return(0);
}
+/* Set max #threads. value <= 0 means max supported #threads (LDAP_MAXTHR) */
int
-ldap_pvt_thread_pool_maxthreads ( ldap_pvt_thread_pool_t *tpool, int max_threads )
+ldap_pvt_thread_pool_maxthreads(
+ ldap_pvt_thread_pool_t *tpool,
+ int max_threads )
{
struct ldap_int_thread_pool_s *pool;
+ if (! (0 <= max_threads && max_threads <= LDAP_MAXTHR))
+ max_threads = 0;
+
if (tpool == NULL)
return(-1);
return(0);
}
+/* Inspect the pool */
int
-ldap_pvt_thread_pool_query ( ldap_pvt_thread_pool_t *tpool, ldap_pvt_thread_pool_param_t param, void *value )
+ldap_pvt_thread_pool_query(
+ ldap_pvt_thread_pool_t *tpool,
+ ldap_pvt_thread_pool_param_t param,
+ void *value )
{
struct ldap_int_thread_pool_s *pool;
int count = -1;
{ "running", LDAP_INT_THREAD_POOL_RUNNING },
{ "finishing", LDAP_INT_THREAD_POOL_FINISHING },
{ "stopping", LDAP_INT_THREAD_POOL_STOPPING },
- { "pausing", LDAP_INT_THREAD_POOL_PAUSING },
{ NULL }
};
int i;
- for ( i = 0; str2state[ i ].name != NULL; i++ ) {
- if ( str2state[ i ].state == pool->ltp_state ) {
- break;
+ if ( pool->ltp_pause ) {
+ *((char **)value) = "pausing";
+ } else {
+ for ( i = 0; str2state[ i ].name != NULL; i++ ) {
+ if ( str2state[ i ].state == pool->ltp_state ) {
+ break;
+ }
}
+ *((char **)value) = str2state[ i ].name;
}
- *((char **)value) = str2state[ i ].name;
- if ( str2state[ i ].name != NULL ) {
+ if ( *((char **)value) != NULL ) {
count = -2;
}
} break;
+
+ case LDAP_PVT_THREAD_POOL_PARAM_UNKNOWN:
+ break;
}
ldap_pvt_thread_mutex_unlock( &pool->ltp_mutex );
return rc;
}
+/* Destroy the pool after making its threads finish */
int
ldap_pvt_thread_pool_destroy ( ldap_pvt_thread_pool_t *tpool, int run_pending )
{
struct ldap_int_thread_pool_s *pool, *pptr;
- ldap_int_thread_ctx_t *ctx;
+ ldap_int_thread_task_t *task;
if (tpool == NULL)
return(-1);
? LDAP_INT_THREAD_POOL_FINISHING
: LDAP_INT_THREAD_POOL_STOPPING;
- if ( pool->ltp_open_count ) {
- ldap_pvt_thread_cond_broadcast(&pool->ltp_cond);
+ while (pool->ltp_open_count) {
+ if (!pool->ltp_pause)
+ ldap_pvt_thread_cond_broadcast(&pool->ltp_cond);
ldap_pvt_thread_cond_wait(&pool->ltp_cond, &pool->ltp_mutex);
}
ldap_pvt_thread_mutex_unlock(&pool->ltp_mutex);
- while ((ctx = LDAP_STAILQ_FIRST(&pool->ltp_pending_list)) != NULL)
+ while ((task = LDAP_STAILQ_FIRST(&pool->ltp_pending_list)) != NULL)
{
- LDAP_STAILQ_REMOVE_HEAD(&pool->ltp_pending_list, ltc_next.q);
- LDAP_FREE(ctx);
+ LDAP_STAILQ_REMOVE_HEAD(&pool->ltp_pending_list, ltt_next.q);
+ LDAP_FREE(task);
}
- while ((ctx = LDAP_SLIST_FIRST(&pool->ltp_free_list)) != NULL)
+ while ((task = LDAP_SLIST_FIRST(&pool->ltp_free_list)) != NULL)
{
- LDAP_SLIST_REMOVE_HEAD(&pool->ltp_free_list, ltc_next.l);
- LDAP_FREE(ctx);
+ LDAP_SLIST_REMOVE_HEAD(&pool->ltp_free_list, ltt_next.l);
+ LDAP_FREE(task);
}
ldap_pvt_thread_cond_destroy(&pool->ltp_pcond);
ldap_pvt_thread_cond_destroy(&pool->ltp_cond);
ldap_pvt_thread_mutex_destroy(&pool->ltp_mutex);
LDAP_FREE(pool);
-#ifdef LDAP_PVT_THREAD_POOL_SEM_LOAD_CONTROL
- if ( thread_pool_sem ) {
- LDAP_FREE( thread_pool_sem );
- }
-#endif
+ ldap_int_has_thread_pool = 0;
return(0);
}
+/* Thread loop. Accept and handle submitted tasks. */
static void *
ldap_int_thread_pool_wrapper (
void *xpool )
{
struct ldap_int_thread_pool_s *pool = xpool;
- ldap_int_thread_ctx_t *ctx;
- ldap_int_thread_userctx_t uctx;
- int i, keyslot, hash;
+ ldap_int_thread_task_t *task;
+ ldap_int_thread_userctx_t ctx, *kctx;
+ unsigned i, keyslot, hash;
- if (pool == NULL)
- return NULL;
+ assert(pool != NULL);
for ( i=0; i<MAXKEYS; i++ ) {
- uctx.ltu_key[i].ltk_key = NULL;
+ ctx.ltu_key[i].ltk_key = NULL;
}
- uctx.ltu_id = ldap_pvt_thread_self();
+ ctx.ltu_id = ldap_pvt_thread_self();
+ TID_HASH(ctx.ltu_id, hash);
ldap_pvt_thread_mutex_lock(&pool->ltp_mutex);
- /* store pointer to our keys */
- TID_HASH(uctx.ltu_id, hash);
- for (i = hash & (LDAP_MAXTHR-1);
- !ldap_pvt_thread_equal(thread_keys[i].id, uctx.ltu_id);
- i = (i+1) & (LDAP_MAXTHR-1));
- thread_keys[i].ctx = &uctx;
- keyslot = i;
-
- while (pool->ltp_state != LDAP_INT_THREAD_POOL_STOPPING) {
- ctx = LDAP_STAILQ_FIRST(&pool->ltp_pending_list);
- if (ctx) {
- LDAP_STAILQ_REMOVE_HEAD(&pool->ltp_pending_list, ltc_next.q);
- } else {
+ /* thread_keys[] is read-only when paused */
+ while (pool->ltp_pause)
+ ldap_pvt_thread_cond_wait(&pool->ltp_cond, &pool->ltp_mutex);
+
+ /* find a key slot to give this thread ID and store a
+ * pointer to our keys there; start at the thread ID
+ * itself (mod LDAP_MAXTHR) and look for an empty slot.
+ */
+ ldap_pvt_thread_mutex_lock(&ldap_pvt_thread_pool_mutex);
+ for (keyslot = hash & (LDAP_MAXTHR-1);
+ (kctx = thread_keys[keyslot].ctx) && kctx != DELETED_THREAD_CTX;
+ keyslot = (keyslot+1) & (LDAP_MAXTHR-1));
+ thread_keys[keyslot].ctx = &ctx;
+ ldap_pvt_thread_mutex_unlock(&ldap_pvt_thread_pool_mutex);
+
+ pool->ltp_starting--;
+
+ for (;;) {
+ while (pool->ltp_pause)
+ ldap_pvt_thread_cond_wait(&pool->ltp_cond, &pool->ltp_mutex);
+
+ if (pool->ltp_state == LDAP_INT_THREAD_POOL_STOPPING)
+ break;
+
+ task = LDAP_STAILQ_FIRST(&pool->ltp_pending_list);
+ if (task == NULL) {
if (pool->ltp_state == LDAP_INT_THREAD_POOL_FINISHING)
break;
- if (pool->ltp_max_count > 0
- && pool->ltp_open_count > pool->ltp_max_count)
+
+ if (pool->ltp_open_count >
+ (pool->ltp_max_count ? pool->ltp_max_count : LDAP_MAXTHR))
{
/* too many threads running (can happen if the
* maximum threads value is set during ongoing
* always have at least one thread open). the check
* should be like this:
* if (pool->ltp_open_count > 1 && pool->ltp_starting == 0)
- * check timer, leave thread (break;)
+ * check timer, wait if ltp_pause, leave thread (break;)
*
* Just use pthread_cond_timedwait if we want to
* check idle time.
*/
- if (pool->ltp_state == LDAP_INT_THREAD_POOL_RUNNING
- || pool->ltp_state == LDAP_INT_THREAD_POOL_PAUSING)
- {
- ldap_pvt_thread_cond_wait(&pool->ltp_cond, &pool->ltp_mutex);
- }
-
+ assert(pool->ltp_state == LDAP_INT_THREAD_POOL_RUNNING);
+ ldap_pvt_thread_cond_wait(&pool->ltp_cond, &pool->ltp_mutex);
continue;
}
+ LDAP_STAILQ_REMOVE_HEAD(&pool->ltp_pending_list, ltt_next.q);
pool->ltp_pending_count--;
-
- LDAP_SLIST_INSERT_HEAD(&pool->ltp_active_list, ctx, ltc_next.al);
pool->ltp_active_count++;
ldap_pvt_thread_mutex_unlock(&pool->ltp_mutex);
- ctx->ltc_start_routine(&uctx, ctx->ltc_arg);
+ task->ltt_start_routine(&ctx, task->ltt_arg);
-#ifdef LDAP_PVT_THREAD_POOL_SEM_LOAD_CONTROL
- ldap_lazy_sem_post( thread_pool_sem );
-#endif
ldap_pvt_thread_mutex_lock(&pool->ltp_mutex);
- LDAP_SLIST_REMOVE(&pool->ltp_active_list, ctx,
- ldap_int_thread_ctx_s, ltc_next.al);
- LDAP_SLIST_INSERT_HEAD(&pool->ltp_free_list, ctx, ltc_next.l);
+ LDAP_SLIST_INSERT_HEAD(&pool->ltp_free_list, task, ltt_next.l);
pool->ltp_active_count--;
-
- if (pool->ltp_state == LDAP_INT_THREAD_POOL_PAUSING) {
- if (pool->ltp_active_count < 2) {
- ldap_pvt_thread_cond_signal(&pool->ltp_pcond);
- }
- ldap_pvt_thread_cond_wait(&pool->ltp_cond, &pool->ltp_mutex);
- }
+ /* let pool_pause know when it is the sole active thread */
+ if (pool->ltp_active_count < 2)
+ ldap_pvt_thread_cond_signal(&pool->ltp_pcond);
}
- ldap_pvt_thread_pool_context_reset(&uctx);
+ /* The ltp_mutex lock protects ctx->ltu_key from pool_purgekey()
+ * during this call, since it prevents new pauses. */
+ ldap_pvt_thread_pool_context_reset(&ctx);
- thread_keys[keyslot].ctx = NULL;
- thread_keys[keyslot].id = tid_zero;
+ ldap_pvt_thread_mutex_lock(&ldap_pvt_thread_pool_mutex);
+ thread_keys[keyslot].ctx = DELETED_THREAD_CTX;
+ ldap_pvt_thread_mutex_unlock(&ldap_pvt_thread_pool_mutex);
pool->ltp_open_count--;
-
/* let pool_destroy know we're all done */
if (pool->ltp_open_count < 1)
ldap_pvt_thread_cond_signal(&pool->ltp_cond);
return(NULL);
}
+/* Pause the pool. Return when all other threads are paused. */
int
ldap_pvt_thread_pool_pause (
ldap_pvt_thread_pool_t *tpool )
ldap_pvt_thread_mutex_lock(&pool->ltp_mutex);
/* If someone else has already requested a pause, we have to wait */
- while (pool->ltp_state == LDAP_INT_THREAD_POOL_PAUSING) {
+ if (pool->ltp_pause) {
pool->ltp_pending_count++;
pool->ltp_active_count--;
- ldap_pvt_thread_cond_wait(&pool->ltp_cond, &pool->ltp_mutex);
+ /* let the other pool_pause() know when it can proceed */
+ if (pool->ltp_active_count < 2)
+ ldap_pvt_thread_cond_signal(&pool->ltp_pcond);
+ do {
+ ldap_pvt_thread_cond_wait(&pool->ltp_cond, &pool->ltp_mutex);
+ } while (pool->ltp_pause);
pool->ltp_pending_count--;
pool->ltp_active_count++;
}
- /* Wait for everyone else to finish */
- pool->ltp_state = LDAP_INT_THREAD_POOL_PAUSING;
+
+ /* Wait for everyone else to pause or finish */
+ pool->ltp_pause = 1;
while (pool->ltp_active_count > 1) {
ldap_pvt_thread_cond_wait(&pool->ltp_pcond, &pool->ltp_mutex);
}
+
ldap_pvt_thread_mutex_unlock(&pool->ltp_mutex);
return(0);
}
+/* End a pause */
int
ldap_pvt_thread_pool_resume (
ldap_pvt_thread_pool_t *tpool )
return(0);
ldap_pvt_thread_mutex_lock(&pool->ltp_mutex);
-
- pool->ltp_state = LDAP_INT_THREAD_POOL_RUNNING;
+ pool->ltp_pause = 0;
ldap_pvt_thread_cond_broadcast(&pool->ltp_cond);
ldap_pvt_thread_mutex_unlock(&pool->ltp_mutex);
return(0);
}
+/*
+ * Get the key's data and optionally free function in the given context.
+ */
int ldap_pvt_thread_pool_getkey(
void *xctx,
void *key,
ldap_int_thread_userctx_t *ctx = xctx;
int i;
- if ( !ctx || !data ) return EINVAL;
+ if ( !ctx || !key || !data ) return EINVAL;
for ( i=0; i<MAXKEYS && ctx->ltu_key[i].ltk_key; i++ ) {
if ( ctx->ltu_key[i].ltk_key == key ) {
return ENOENT;
}
+static void
+clear_key_idx( ldap_int_thread_userctx_t *ctx, int i )
+{
+ for ( ; i < MAXKEYS-1 && ctx->ltu_key[i+1].ltk_key; i++ )
+ ctx->ltu_key[i] = ctx->ltu_key[i+1];
+ ctx->ltu_key[i].ltk_key = NULL;
+}
+
+/*
+ * Set or remove data for the key in the given context.
+ * key can be any unique pointer.
+ * kfree() is an optional function to free the data (but not the key):
+ * pool_context_reset() and pool_purgekey() call kfree(key, data),
+ * but pool_setkey() does not. For pool_setkey() it is the caller's
+ * responsibility to free any existing data with the same key.
+ * kfree() must not call functions taking a tpool argument.
+ */
int ldap_pvt_thread_pool_setkey(
void *xctx,
void *key,
ldap_pvt_thread_pool_keyfree_t *kfree )
{
ldap_int_thread_userctx_t *ctx = xctx;
- int i;
+ int i, found;
if ( !ctx || !key ) return EINVAL;
- for ( i=0; i<MAXKEYS; i++ ) {
- if ( !ctx->ltu_key[i].ltk_key || ctx->ltu_key[i].ltk_key == key ) {
- ctx->ltu_key[i].ltk_key = key;
- ctx->ltu_key[i].ltk_data = data;
- ctx->ltu_key[i].ltk_free = kfree;
- return 0;
+ for ( i=found=0; i<MAXKEYS; i++ ) {
+ if ( ctx->ltu_key[i].ltk_key == key ) {
+ found = 1;
+ break;
+ } else if ( !ctx->ltu_key[i].ltk_key ) {
+ break;
}
}
- return ENOMEM;
+
+ if ( data || kfree ) {
+ if ( i>=MAXKEYS )
+ return ENOMEM;
+ ctx->ltu_key[i].ltk_key = key;
+ ctx->ltu_key[i].ltk_data = data;
+ ctx->ltu_key[i].ltk_free = kfree;
+ } else if ( found ) {
+ clear_key_idx( ctx, i );
+ }
+
+ return 0;
}
/* Free all elements with this key, no matter which thread they're in.
int i, j;
ldap_int_thread_userctx_t *ctx;
+ assert ( key != NULL );
+
for ( i=0; i<LDAP_MAXTHR; i++ ) {
- if ( thread_keys[i].ctx ) {
- ctx = thread_keys[i].ctx;
- for ( j=0; j<MAXKEYS; j++ ) {
+ ctx = thread_keys[i].ctx;
+ if ( ctx && ctx != DELETED_THREAD_CTX ) {
+ for ( j=0; j<MAXKEYS && ctx->ltu_key[j].ltk_key; j++ ) {
if ( ctx->ltu_key[j].ltk_key == key ) {
if (ctx->ltu_key[j].ltk_free)
ctx->ltu_key[j].ltk_free( ctx->ltu_key[j].ltk_key,
ctx->ltu_key[j].ltk_data );
- ctx->ltu_key[j].ltk_key = NULL;
- ctx->ltu_key[j].ltk_free = NULL;
+ clear_key_idx( ctx, j );
break;
}
}
}
/*
+ * Find the context of the current thread.
* This is necessary if the caller does not have access to the
* thread context handle (for example, a slapd plugin calling
* slapi_search_internal()). No doubt it is more efficient
void *ldap_pvt_thread_pool_context( )
{
ldap_pvt_thread_t tid;
- int i, hash;
+ unsigned i, hash;
+ ldap_int_thread_userctx_t *ctx;
tid = ldap_pvt_thread_self();
- if ( ldap_pvt_thread_equal( tid, ldap_int_main_tid ))
+ if ( ldap_pvt_thread_equal( tid, ldap_int_main_thrctx.ltu_id ))
return &ldap_int_main_thrctx;
TID_HASH( tid, hash );
- for (i = hash & (LDAP_MAXTHR-1);
- !ldap_pvt_thread_equal(thread_keys[i].id, tid_zero) &&
- !ldap_pvt_thread_equal(thread_keys[i].id, tid);
- i = (i+1) & (LDAP_MAXTHR-1));
+ i = hash &= (LDAP_MAXTHR-1);
+ ldap_pvt_thread_mutex_lock(&ldap_pvt_thread_pool_mutex);
+ do {
+ ctx = thread_keys[i].ctx;
+ if ( ctx == DELETED_THREAD_CTX )
+ continue;
+ if ( !ctx || ldap_pvt_thread_equal(thread_keys[i].ctx->ltu_id, tid) )
+ goto done;
+ } while ( (i = (i+1) & (LDAP_MAXTHR-1)) != hash );
+ ctx = NULL;
+ done:
+ ldap_pvt_thread_mutex_unlock(&ldap_pvt_thread_pool_mutex);
- return thread_keys[i].ctx;
+ return ctx;
}
+/*
+ * Free the context's keys.
+ * Must not call functions taking a tpool argument (because this
+ * thread already holds ltp_mutex when called from pool_wrapper()).
+ */
void ldap_pvt_thread_pool_context_reset( void *vctx )
{
ldap_int_thread_userctx_t *ctx = vctx;
#ifdef HAVE_SYSCONF
nbits = sysconf( _SC_OPEN_MAX );
-#elif HAVE_GETDTABLESIZE
+#elif defined(HAVE_GETDTABLESIZE)
nbits = getdtablesize();
#else
nbits = FD_SETSIZE;
if ( debug == 0 ) {
for ( i = 0; i < 5; i++ ) {
-#if HAVE_THR
+#ifdef HAVE_THR
switch ( fork1() )
#else
switch ( fork() )
char *
lutil_getpass( const char *prompt )
{
-#if !defined(HAVE_POSIX_TERMIOS) && !defined(HAVE_SGTTY_H)
+#if !defined(HAVE_TERMIOS_H) && !defined(HAVE_SGTTY_H)
static char buf[256];
int i, c;
#include <ucred.h>
#endif
+#ifdef LDAP_PF_LOCAL_SENDMSG
+#include <lber.h>
+#ifdef HAVE_SYS_UIO_H
+#include <sys/uio.h>
+#endif
+#include <sys/stat.h>
+#endif
+
#ifdef HAVE_SYS_UCRED_H
#ifdef HAVE_GRP_H
#include <grp.h> /* for NGROUPS on Tru64 5.1 */
#include <sys/ucred.h>
#endif
-#if !defined(HAVE_GETPEERUCRED) && \
- !defined(SO_PEERCRED) && !defined(LOCAL_PEERCRED) && \
- defined(HAVE_SENDMSG) && (defined(HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTSLEN) || \
- defined(HAVE_STRUCT_MSGHDR_MSG_CONTROL))
-#define DO_SENDMSG
-#ifdef HAVE_SYS_UIO_H
-#include <sys/uio.h>
-#endif
-#include <sys/stat.h>
-#endif
-
#include <stdlib.h>
-
-int getpeereid( int s, uid_t *euid, gid_t *egid )
+int lutil_getpeereid( int s, uid_t *euid, gid_t *egid
+#ifdef LDAP_PF_LOCAL_SENDMSG
+ , struct berval *peerbv
+#endif
+ )
{
#ifdef LDAP_PF_LOCAL
#if defined( HAVE_GETPEERUCRED )
#elif defined( SO_PEERCRED )
struct ucred peercred;
- socklen_t peercredlen = sizeof peercred;
+ ber_socklen_t peercredlen = sizeof peercred;
if(( getsockopt( s, SOL_SOCKET, SO_PEERCRED,
(void *)&peercred, &peercredlen ) == 0 )
#elif defined( LOCAL_PEERCRED )
struct xucred peercred;
- socklen_t peercredlen = sizeof peercred;
+ ber_socklen_t peercredlen = sizeof peercred;
if(( getsockopt( s, LOCAL_PEERCRED, 1,
(void *)&peercred, &peercredlen ) == 0 )
*egid = peercred.cr_gid;
return 0;
}
-#elif defined( DO_SENDMSG )
- char dummy[8];
- int err, fd[2];
+#elif defined( LDAP_PF_LOCAL_SENDMSG ) && defined( MSG_WAITALL )
+ int err, fd;
struct iovec iov;
struct msghdr msg = {0};
# ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
# ifndef CMSG_LEN
# define CMSG_LEN(len) (_CMSG_ALIGN(sizeof(struct cmsghdr)) + (len))
# endif
- union {
+ struct {
struct cmsghdr cm;
- unsigned char control[CMSG_SPACE(sizeof(int))];
- } control_un;
+ int fd;
+ } control_st;
struct cmsghdr *cmsg;
# endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
struct stat st;
+ struct sockaddr_un lname, rname;
+ ber_socklen_t llen, rlen;
- msg.msg_name = NULL;
- msg.msg_namelen = 0;
+ rlen = sizeof(rname);
+ llen = sizeof(lname);
+ memset( &lname, 0, sizeof( lname ));
+ getsockname(s, (struct sockaddr *)&lname, &llen);
- iov.iov_base = dummy;
- iov.iov_len = sizeof dummy;
+ iov.iov_base = peerbv->bv_val;
+ iov.iov_len = peerbv->bv_len;
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
+ peerbv->bv_len = 0;
+
# ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
- msg.msg_control = control_un.control;
- msg.msg_controllen = sizeof( control_un.control );
+ msg.msg_control = &control_st;
+ msg.msg_controllen = sizeof( struct cmsghdr ) + sizeof( int ); /* no padding! */
cmsg = CMSG_FIRSTHDR( &msg );
+# else
+ msg.msg_accrights = (char *)&fd;
+ msg.msg_accrightslen = sizeof(fd);
+# endif
/*
* AIX returns a bogus file descriptor if recvmsg() is
* called with MSG_PEEK (is this a bug?). Hence we need
* to receive the Abandon PDU.
*/
- if( recvmsg( s, &msg, MSG_WAITALL ) >= 0 &&
+ err = recvmsg( s, &msg, MSG_WAITALL );
+ if( err >= 0 &&
+# ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
cmsg->cmsg_len == CMSG_LEN( sizeof(int) ) &&
cmsg->cmsg_level == SOL_SOCKET &&
- cmsg->cmsg_type == SCM_RIGHTS )
+ cmsg->cmsg_type == SCM_RIGHTS
# else
- msg.msg_accrights = (char *)fd;
- msg.msg_accrightslen = sizeof(fd);
- if( recvmsg( s, &msg, MSG_PEEK) >= 0 && msg.msg_accrightslen == sizeof(int) )
+ msg.msg_accrightslen == sizeof(int)
# endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL*/
- {
+ ) {
+ int mode = S_IFIFO|S_ISUID|S_IRWXU;
+
/* We must receive a valid descriptor, it must be a pipe,
- * and it must only be accessible by its owner.
+ * it must only be accessible by its owner, and it must
+ * have the name of our socket written on it.
*/
+ peerbv->bv_len = err;
# ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
- fd[0] = (*(int *)CMSG_DATA( cmsg ));
+ fd = (*(int *)CMSG_DATA( cmsg ));
# endif
- err = fstat( fd[0], &st );
- close(fd[0]);
- if( err == 0 && S_ISFIFO(st.st_mode) &&
- ((st.st_mode & (S_IRWXG|S_IRWXO)) == 0))
+ err = fstat( fd, &st );
+ if ( err == 0 )
+ rlen = read(fd, &rname, rlen);
+ close(fd);
+ if( err == 0 && st.st_mode == mode &&
+ llen == rlen && !memcmp(&lname, &rname, llen))
{
*euid = st.st_uid;
*egid = st.st_gid;
}
#elif defined(SOCKCREDSIZE)
struct msghdr msg;
- socklen_t crmsgsize;
+ ber_socklen_t crmsgsize;
void *crmsg;
struct cmsghdr *cmp;
struct sockcred *sc;
fp2 = ldif_open_url( ptr );
if ( fp2 ) {
LDIFFP *lnew = ber_memalloc( sizeof( LDIFFP ));
+ if ( lnew == NULL ) {
+ return 0;
+ }
lnew->prev = lfp->prev;
lnew->fp = lfp->fp;
lfp->prev = lnew;
#undef LOCK_API
-#if HAVE_LOCKF && defined(F_LOCK)
+#if defined(HAVE_LOCKF) && defined(F_LOCK)
# define USE_LOCKF 1
# define LOCK_API "lockf"
#endif
-#if !defined(LOCK_API) && HAVE_FCNTL
+#if !defined(LOCK_API) && defined(HAVE_FCNTL)
# ifdef HAVE_FCNTL_H
# include <fcntl.h>
# endif
# endif
#endif
-#if !defined(LOCK_API) && HAVE_FLOCK
-# if HAVE_SYS_FILE_H
+#if !defined(LOCK_API) && defined(HAVE_FLOCK)
+# ifdef HAVE_SYS_FILE_H
# include <sys/file.h>
# endif
# define USE_FLOCK 1
}
passwd->bv_val = NULL;
- passwd->bv_len = 4196;
+ passwd->bv_len = 4096;
#ifdef HAVE_FSTAT
{
filename );
}
- passwd->bv_len = sb.st_size;
+ if ( sb.st_size )
+ passwd->bv_len = sb.st_size;
}
}
#endif /* HAVE_FSTAT */
void *defaults )
{
lutilSASLdefaults *defs = defaults;
+
+ assert( defs != NULL );
if (defs->mech) ber_memfree(defs->mech);
if (defs->realm) ber_memfree(defs->realm);
return pipe( sds );
#else
struct sockaddr_in si;
- int rc, len = sizeof(si);
+ int rc;
+ ber_socklen_t len = sizeof(si);
ber_socket_t sd;
sd = socket( AF_INET, SOCK_DGRAM, 0 );
#ifdef HAVE_UUID_TO_STR
# include <sys/uuid.h>
+#elif defined( HAVE_UUID_GENERATE )
+# include <uuid/uuid.h>
#elif defined( _WIN32 )
# include <rpc.h>
#else
#include <lutil.h>
/* not needed for Windows */
-#if !defined(HAVE_UUID_TO_STR) && !defined(_WIN32)
+#if !defined(HAVE_UUID_TO_STR) && !defined(HAVE_UUID_GENERATE) && !defined(_WIN32)
static unsigned char *
lutil_eaddr( void )
{
#endif /* ULONG_MAX >= 64 bits || HAVE_LONG_LONG */
-#endif /* !HAVE_UUID_TO_STR && !_WIN32 */
+#endif /* !HAVE_UUID_TO_STR && !HAVE_UUID_GENERATE && !_WIN32 */
/*
** All we really care about is an ISO UUID string. The format of a UUID is:
return l;
+#elif defined( HAVE_UUID_GENERATE )
+ uuid_t uu;
+
+ uuid_generate( uu );
+ uuid_unparse_lower( uu, buf );
+ return strlen( buf );
+
#elif defined( _WIN32 )
UUID uuid;
unsigned char *uuidstr;
#endif
}
+int
+lutil_uuidstr_from_normalized(
+ char *uuid,
+ size_t uuidlen,
+ char *buf,
+ size_t buflen )
+{
+ unsigned char nibble;
+ int i, d = 0;
+
+ assert( uuid != NULL );
+ assert( buf != NULL );
+
+ if ( uuidlen != 16 ) return -1;
+ if ( buflen < 36 ) return -1;
+
+ for ( i = 0; i < 16; i++ ) {
+ if ( i == 4 || i == 6 || i == 8 || i == 10 ) {
+ buf[(i<<1)+d] = '-';
+ d += 1;
+ }
+
+ nibble = (uuid[i] >> 4) & 0xF;
+ if ( nibble < 10 ) {
+ buf[(i<<1)+d] = nibble + '0';
+ } else {
+ buf[(i<<1)+d] = nibble - 10 + 'a';
+ }
+
+ nibble = (uuid[i]) & 0xF;
+ if ( nibble < 10 ) {
+ buf[(i<<1)+d+1] = nibble + '0';
+ } else {
+ buf[(i<<1)+d+1] = nibble - 10 + 'a';
+ }
+ }
+
+ if ( buflen > 36 ) buf[36] = '\0';
+ return 36;
+}
+
#ifdef TEST
int
main(int argc, char **argv)
## top-level directory of the distribution or, alternatively, at
## <http://www.OpenLDAP.org/license.html>.
-SUBDIRS= slapd slurpd
+SUBDIRS= slapd
dn.c compare.c modify.c delete.c modrdn.c ch_malloc.c \
value.c ava.c bind.c unbind.c abandon.c filterentry.c \
phonetic.c acl.c str2filter.c aclparse.c init.c user.c \
- repl.c lock.c controls.c extended.c passwd.c \
+ lock.c controls.c extended.c passwd.c \
schema.c schema_check.c schema_init.c schema_prep.c \
schemaparse.c ad.c at.c mr.c syntax.c oc.c saslauthz.c \
oidm.c starttls.c index.c sets.c referral.c root_dse.c \
dn.o compare.o modify.o delete.o modrdn.o ch_malloc.o \
value.o ava.o bind.o unbind.o abandon.o filterentry.o \
phonetic.o acl.o str2filter.o aclparse.o init.o user.o \
- repl.o lock.o controls.o extended.o passwd.o \
+ lock.o controls.o extended.o passwd.o \
schema.o schema_check.o schema_init.o schema_prep.o \
schemaparse.o ad.o at.o mr.o syntax.o oc.o saslauthz.o \
oidm.o starttls.o index.o sets.o referral.o root_dse.o \
ber_int_t id;
Operation *o;
- Debug( LDAP_DEBUG_TRACE, "do_abandon\n", 0, 0, 0 );
+ Debug( LDAP_DEBUG_TRACE, "%s do_abandon\n",
+ op->o_log_prefix, 0, 0 );
/*
* Parse the abandon request. It looks like this:
*/
if ( ber_scanf( op->o_ber, "i", &id ) == LBER_ERROR ) {
- Debug( LDAP_DEBUG_ANY, "do_abandon: ber_scanf failed\n", 0, 0 ,0 );
+ Debug( LDAP_DEBUG_ANY, "%s do_abandon: ber_scanf failed\n",
+ op->o_log_prefix, 0, 0 );
send_ldap_discon( op, rs, LDAP_PROTOCOL_ERROR, "decoding error" );
return SLAPD_DISCONNECT;
}
op->o_log_prefix, (long) id, 0, 0, 0 );
if( get_ctrls( op, rs, 0 ) != LDAP_SUCCESS ) {
- Debug( LDAP_DEBUG_ANY, "do_abandon: get_ctrls failed\n", 0, 0 ,0 );
+ Debug( LDAP_DEBUG_ANY, "%s do_abandon: get_ctrls failed\n",
+ op->o_log_prefix, 0, 0 );
return rs->sr_err;
}
- Debug( LDAP_DEBUG_ARGS, "do_abandon: id=%ld\n", (long) id, 0 ,0 );
+ Debug( LDAP_DEBUG_ARGS, "%s do_abandon: id=%ld\n",
+ op->o_log_prefix, (long) id, 0 );
if( id <= 0 ) {
- Debug( LDAP_DEBUG_ANY,
- "do_abandon: bad msgid %ld\n", (long) id, 0, 0 );
+ Debug( LDAP_DEBUG_ANY, "%s do_abandon: bad msgid %ld\n",
+ op->o_log_prefix, (long) id, 0 );
return LDAP_SUCCESS;
}
LDAP_STAILQ_FOREACH( o, &op->o_conn->c_pending_ops, o_next ) {
if ( o->o_msgid == id ) {
LDAP_STAILQ_REMOVE( &op->o_conn->c_pending_ops,
- o, slap_op, o_next );
+ o, Operation, o_next );
LDAP_STAILQ_NEXT(o, o_next) = NULL;
op->o_conn->c_n_ops_pending--;
slap_op_free( o );
ldap_pvt_thread_mutex_unlock( &op->o_conn->c_mutex );
- Debug( LDAP_DEBUG_TRACE, "do_abandon: op=%ld %sfound\n",
- (long) id, o ? "" : "not ", 0 );
+ Debug( LDAP_DEBUG_TRACE, "%s do_abandon: op=%ld %sfound\n",
+ op->o_log_prefix,
+ (long) id, o ? "" : "not " );
return rs->sr_err;
}
static slap_syntax_defs_rec aci_syntax_def = {
"( 1.3.6.1.4.1.4203.666.2.1 DESC 'OpenLDAP Experimental ACI' )",
SLAP_SYNTAX_HIDE,
+ NULL,
OpenLDAPaciValidate,
OpenLDAPaciPretty
};
be_orig = op->o_bd;
if ( op->o_bd == NULL ) {
- op->o_bd = select_backend( &op->o_req_ndn, 0, 0 );
+ op->o_bd = select_backend( &op->o_req_ndn, 0 );
if ( op->o_bd == NULL )
op->o_bd = frontendDB;
}
}
}
- if ( bvals ) {
+ if ( bvalsp ) {
p->bvals = slap_set_join( p->cookie, p->bvals,
( '|' | SLAP_SET_RREF ), bvalsp );
}
goto url_done;
}
- op2.o_bd = select_backend( &op2.o_req_ndn, 0, 1 );
+ op2.o_bd = select_backend( &op2.o_req_ndn, 1 );
if ( ( op2.o_bd == NULL ) || ( op2.o_bd->be_search == NULL ) ) {
rc = LDAP_NO_SUCH_OBJECT;
goto url_done;
int prefix; /* NAME is a tag and range prefix */
} Attr_option;
-static Attr_option lang_option = { { sizeof("lang-")-1, "lang-" }, 1 };
+static Attr_option lang_option = { BER_BVC("lang-"), 1 };
/* Options sorted by name, and number of options */
static Attr_option *options = &lang_option;
*text = "zero length option is invalid";
return rtn;
- } else if ( optlen == sizeof("binary")-1 &&
- strncasecmp( opt, "binary", sizeof("binary")-1 ) == 0 )
+ } else if ( optlen == STRLENOF("binary") &&
+ strncasecmp( opt, "binary", STRLENOF("binary") ) == 0 )
{
/* binary option */
if( slap_ad_is_binary( &desc ) ) {
if (desc.ad_tags.bv_len || desc.ad_flags != SLAP_DESC_NONE) {
dlen = desc.ad_type->sat_cname.bv_len + 1;
if (desc.ad_tags.bv_len) {
- dlen += 1+desc.ad_tags.bv_len;
+ dlen += 1 + desc.ad_tags.bv_len;
}
- if( slap_ad_is_binary( &desc ) ) {
- dlen += sizeof(";binary")+desc.ad_tags.bv_len;
+ if ( slap_ad_is_binary( &desc ) ) {
+ dlen += 1 + STRLENOF(";binary") + desc.ad_tags.bv_len;
}
}
lp = NULL;
if( desc.ad_tags.bv_len ) {
lp = desc.ad_tags.bv_val;
- while( strncasecmp(lp, "binary", sizeof("binary")-1) < 0
+ while( strncasecmp(lp, "binary", STRLENOF("binary")) < 0
&& (lp = strchr( lp, ';' )) != NULL )
++lp;
if( lp != desc.ad_tags.bv_val ) {
}
an = ch_realloc( an, ( i + j + 1 ) * sizeof( AttributeName ) );
- BER_BVZERO( &an[i + j].an_name );
anew = an + i;
for ( s = ldap_pvt_strtok( str, brkstr, &lasts );
s != NULL;
s = ldap_pvt_strtok( NULL, brkstr, &lasts ) )
{
+ /* put a stop mark */
+ BER_BVZERO( &anew[1].an_name );
+
anew->an_desc = NULL;
anew->an_oc = NULL;
anew->an_oc_exclude = 0;
return( an );
reterr:
- for ( i = 0; an[i].an_name.bv_val; i++ ) {
- free( an[i].an_name.bv_val );
- }
- free( an );
+ anlist_free( an, 1, NULL );
+
/*
* overwrites input string
* on error!
return NULL;
}
+void
+anlist_free( AttributeName *an, int freename, void *ctx )
+{
+ if ( an == NULL ) {
+ return;
+ }
+
+ if ( freename ) {
+ int i;
+
+ for ( i = 0; an[i].an_name.bv_val; i++ ) {
+ ber_memfree_x( an[i].an_name.bv_val, ctx );
+ }
+ }
+
+ ber_memfree_x( an, ctx );
+}
+
char **anlist2charray_x( AttributeName *an, int dup, void *ctx )
{
char **attrs;
}
an = str2anlist( an, line, brkstr );
if ( an == NULL )
- return NULL;
+ break;
lcur = line;
}
ch_free( line );
int rc = 0;
int freevals = 1;
- Debug( LDAP_DEBUG_TRACE, "do_add\n", 0, 0, 0 );
+ Debug( LDAP_DEBUG_TRACE, "%s do_add\n",
+ op->o_log_prefix, 0, 0 );
+
/*
* Parse the add request. It looks like this:
*
/* get the name */
if ( ber_scanf( ber, "{m", /*}*/ &dn ) == LBER_ERROR ) {
- Debug( LDAP_DEBUG_ANY, "do_add: ber_scanf failed\n", 0, 0, 0 );
+ Debug( LDAP_DEBUG_ANY, "%s do_add: ber_scanf failed\n",
+ op->o_log_prefix, 0, 0 );
send_ldap_discon( op, rs, LDAP_PROTOCOL_ERROR, "decoding error" );
return SLAPD_DISCONNECT;
}
- op->ora_e = entry_alloc();
-
- rs->sr_err = dnPrettyNormal( NULL, &dn, &op->o_req_dn, &op->o_req_ndn,
- op->o_tmpmemctx );
-
- if ( rs->sr_err != LDAP_SUCCESS ) {
- Debug( LDAP_DEBUG_ANY, "do_add: invalid dn (%s)\n", dn.bv_val, 0, 0 );
- send_ldap_error( op, rs, LDAP_INVALID_DN_SYNTAX, "invalid DN" );
- goto done;
- }
-
- ber_dupbv( &op->ora_e->e_name, &op->o_req_dn );
- ber_dupbv( &op->ora_e->e_nname, &op->o_req_ndn );
-
- Debug( LDAP_DEBUG_ARGS, "do_add: dn (%s)\n", op->ora_e->e_dn, 0, 0 );
+ Debug( LDAP_DEBUG_ARGS, "%s do_add: dn (%s)\n",
+ op->o_log_prefix, dn.bv_val, 0 );
/* get the attrs */
for ( tag = ber_first_element( ber, &len, &last ); tag != LBER_DEFAULT;
rtag = ber_scanf( ber, "{m{W}}", &tmp.sml_type, &tmp.sml_values );
if ( rtag == LBER_ERROR ) {
- Debug( LDAP_DEBUG_ANY, "do_add: decoding error\n", 0, 0, 0 );
+ Debug( LDAP_DEBUG_ANY, "%s do_add: decoding error\n",
+ op->o_log_prefix, 0, 0 );
send_ldap_discon( op, rs, LDAP_PROTOCOL_ERROR, "decoding error" );
rs->sr_err = SLAPD_DISCONNECT;
goto done;
}
if ( tmp.sml_values == NULL ) {
- Debug( LDAP_DEBUG_ANY, "no values for type %s\n",
- tmp.sml_type.bv_val, 0, 0 );
+ Debug( LDAP_DEBUG_ANY, "%s do_add: no values for type %s\n",
+ op->o_log_prefix, tmp.sml_type.bv_val, 0 );
send_ldap_error( op, rs, LDAP_PROTOCOL_ERROR,
"no values for attribute type" );
goto done;
}
if ( ber_scanf( ber, /*{*/ "}") == LBER_ERROR ) {
- Debug( LDAP_DEBUG_ANY, "do_add: ber_scanf failed\n", 0, 0, 0 );
+ Debug( LDAP_DEBUG_ANY, "%s do_add: ber_scanf failed\n",
+ op->o_log_prefix, 0, 0 );
send_ldap_discon( op, rs, LDAP_PROTOCOL_ERROR, "decoding error" );
rs->sr_err = SLAPD_DISCONNECT;
goto done;
}
if ( get_ctrls( op, rs, 1 ) != LDAP_SUCCESS ) {
- Debug( LDAP_DEBUG_ANY, "do_add: get_ctrls failed\n", 0, 0, 0 );
+ Debug( LDAP_DEBUG_ANY, "%s do_add: get_ctrls failed\n",
+ op->o_log_prefix, 0, 0 );
goto done;
}
+ rs->sr_err = dnPrettyNormal( NULL, &dn, &op->o_req_dn, &op->o_req_ndn,
+ op->o_tmpmemctx );
+
+ if ( rs->sr_err != LDAP_SUCCESS ) {
+ Debug( LDAP_DEBUG_ANY, "%s do_add: invalid dn (%s)\n",
+ op->o_log_prefix, dn.bv_val, 0 );
+ send_ldap_error( op, rs, LDAP_INVALID_DN_SYNTAX, "invalid DN" );
+ goto done;
+ }
+
+ op->ora_e = entry_alloc();
+ ber_dupbv( &op->ora_e->e_name, &op->o_req_dn );
+ ber_dupbv( &op->ora_e->e_nname, &op->o_req_ndn );
+
+ Statslog( LDAP_DEBUG_STATS, "%s ADD dn=\"%s\"\n",
+ op->o_log_prefix, op->o_req_dn.bv_val, 0, 0, 0 );
+
if ( modlist == NULL ) {
send_ldap_error( op, rs, LDAP_PROTOCOL_ERROR,
"no attributes provided" );
goto done;
}
- Statslog( LDAP_DEBUG_STATS, "%s ADD dn=\"%s\"\n",
- op->o_log_prefix, op->ora_e->e_name.bv_val, 0, 0, 0 );
-
if ( dn_match( &op->ora_e->e_nname, &slap_empty_bv ) ) {
/* protocolError may be a more appropriate error */
send_ldap_error( op, rs, LDAP_ALREADY_EXISTS,
int
fe_op_add( Operation *op, SlapReply *rs )
{
- int manageDSAit;
Modifications **modtail = &op->ora_modlist;
int rc = 0;
BackendDB *op_be, *bd = op->o_bd;
char textbuf[ SLAP_TEXT_BUFLEN ];
size_t textlen = sizeof( textbuf );
- manageDSAit = get_manageDSAit( op );
-
/*
* We could be serving multiple database backends. Select the
* appropriate one, or send a referral to our "referral server"
* if we don't hold it.
*/
- op->o_bd = select_backend( &op->ora_e->e_nname, manageDSAit, 1 );
+ op->o_bd = select_backend( &op->ora_e->e_nname, 1 );
if ( op->o_bd == NULL ) {
op->o_bd = bd;
rs->sr_ref = referral_rewrite( default_referral,
/* If we've got a glued backend, check the real backend */
op_be = op->o_bd;
if ( SLAP_GLUE_INSTANCE( op->o_bd )) {
- op->o_bd = select_backend( &op->ora_e->e_nname, manageDSAit, 0 );
+ op->o_bd = select_backend( &op->ora_e->e_nname, 0 );
}
/* check restrictions */
int repl_user = be_isupdate( op );
if ( !SLAP_SINGLE_SHADOW(op->o_bd) || repl_user ) {
int update = !BER_BVISEMPTY( &op->o_bd->be_update_ndn );
- slap_callback cb = { NULL, slap_replog_cb, NULL, NULL };
op->o_bd = op_be;
send_ldap_result( op, rs );
goto done;
}
-
- cb.sc_next = op->o_callback;
- op->o_callback = &cb;
}
rc = op->o_bd->be_add( op, rs );
#include <ac/assert.h>
#include <sys/types.h>
#include <sys/stat.h>
-#if HAVE_SYS_FILE_H
+#ifdef HAVE_SYS_FILE_H
#include <sys/file.h>
#endif
#include <fcntl.h>
static Avlnode *attr_index = NULL;
static Avlnode *attr_cache = NULL;
-static LDAP_STAILQ_HEAD(ATList, slap_attribute_type) attr_list
+static LDAP_STAILQ_HEAD(ATList, AttributeType) attr_list
= LDAP_STAILQ_HEAD_INITIALIZER(attr_list);
/* Last hardcoded attribute registered */
{
at->sat_flags |= SLAP_AT_DELETED;
- LDAP_STAILQ_REMOVE(&attr_list,at,slap_attribute_type,sat_next);
+ LDAP_STAILQ_REMOVE(&attr_list, at, AttributeType, sat_next);
at_delete_names( at );
}
/* Keep old oid, free new oid;
* Keep old ads, free new ads;
+ * Keep old ad_mutex, free new ad_mutex;
* Keep new everything else, free old
*/
tmp = *old_sat;
tmp.sat_oid = sat->sat_oid;
old_sat->sat_ad = tmp.sat_ad;
tmp.sat_ad = sat->sat_ad;
+ old_sat->sat_ad_mutex = tmp.sat_ad_mutex;
+ tmp.sat_ad_mutex = sat->sat_ad_mutex;
*sat = tmp;
/* Check for basic ad pointing at old cname */
goto error_return;
}
- if( sat->sat_syntax != NULL && sat->sat_syntax != syn ) {
- code = SLAP_SCHERR_ATTR_BAD_SUP;
- goto error_return;
+ if ( sat->sat_syntax != NULL && sat->sat_syntax != syn ) {
+ /* BEWARE: no loop detection! */
+ if ( syn_is_sup( sat->sat_syntax, syn ) ) {
+ code = SLAP_SCHERR_ATTR_BAD_SUP;
+ goto error_return;
+ }
}
sat->sat_syntax = syn;
void
attrs_free( Attribute *a )
{
- Attribute *b, *tail, *next;
-
if ( a ) {
+ Attribute *b = (Attribute *)0xBAD, *tail, *next;
+
+ /* save tail */
tail = a;
do {
next = a->a_next;
} while ( next );
ldap_pvt_thread_mutex_lock( &attr_mutex );
+ /* replace NULL with current attr list and let attr list
+ * start from last attribute returned to list */
tail->a_next = attr_list;
attr_list = b;
ldap_pvt_thread_mutex_unlock( &attr_mutex );
DB_TXN *ltid = NULL, *lt2;
struct bdb_op_info opinfo = {0};
int subentry;
- u_int32_t locker = 0, rlocker = 0;
+ BDB_LOCKER locker = 0, rlocker = 0;
DB_LOCK lock;
int num_retries = 0;
#define BDB_PAGESIZE 4096 /* BDB's original default */
#endif
+/* 4.6.18 redefines cursor->locker */
+#if DB_VERSION_FULL >= 0x04060012
+
+struct __db_locker {
+ u_int32_t id;
+};
+
+typedef struct __db_locker * BDB_LOCKER;
+
+extern int __lock_getlocker(DB_LOCKTAB *lt, u_int32_t locker, int create, DB_LOCKER **ret);
+
+#define CURSOR_SETLOCKER(cursor, id) cursor->locker = id
+#define CURSOR_GETLOCKER(cursor) cursor->locker
+#else
+
+typedef u_int32_t BDB_LOCKER;
+
+#define CURSOR_SETLOCKER(cursor, id) cursor->locker = id
+#define CURSOR_GETLOCKER(cursor) cursor->locker
+
+#endif
+
#define DEFAULT_CACHE_SIZE 1000
/* The default search IDL stack cache depth */
int c_maxsize;
int c_cursize;
int c_minfree;
+ int c_eimax;
int c_eiused; /* EntryInfo's in use */
int c_leaves; /* EntryInfo leaf nodes */
int c_purging;
- u_int32_t c_locker; /* used by lru cleaner */
+ BDB_LOCKER c_locker; /* used by lru cleaner */
ldap_pvt_thread_rdwr_t c_rwlock;
ldap_pvt_thread_mutex_t c_lru_mutex;
ldap_pvt_thread_mutex_t c_count_mutex;
char *bi_db_config_path;
BerVarray bi_db_config;
bdb_monitor_t bi_monitor;
+
+#ifdef BDB_MONITOR_IDX
+ ldap_pvt_thread_mutex_t bi_idx_mutex;
+ Avlnode *bi_idx;
+#endif /* BDB_MONITOR_IDX */
+
int bi_flags;
#define BDB_IS_OPEN 0x01
#define BDB_HAS_CONFIG 0x02
#define bi_id2entry bi_databases[BDB_ID2ENTRY]
#define bi_dn2id bi_databases[BDB_DN2ID]
+
struct bdb_lock_info {
struct bdb_lock_info *bli_next;
ID bli_id;
struct bdb_op_info {
BackendDB* boi_bdb;
DB_TXN* boi_txn;
+ BDB_LOCKER boi_locker;
u_int32_t boi_err;
- u_int32_t boi_locker;
int boi_acl_cache;
struct bdb_lock_info *boi_locks; /* used when no txn */
};
#define DB_OPEN(db, file, name, type, flags, mode) \
- (db)->open(db, file, name, type, flags, mode)
+ ((db)->open)(db, file, name, type, flags, mode)
#if DB_VERSION_MAJOR < 4
#define LOCK_DETECT(env,f,t,a) lock_detect(env, f, t, a)
#if DB_VERSION_FULL >= 0x04010011
#undef DB_OPEN
#define DB_OPEN(db, file, name, type, flags, mode) \
- (db)->open(db, NULL, file, name, type, flags, mode)
+ ((db)->open)(db, NULL, file, name, type, flags, mode)
+#endif
+
+/* BDB 4.6.18 makes locker a struct instead of an int */
+#if DB_VERSION_FULL >= 0x04060012
+#undef TXN_ID
+#define TXN_ID(txn) (txn)->locker
#endif
#endif
AttributeDescription *password = slap_schema.si_ad_userPassword;
- u_int32_t locker;
+ BDB_LOCKER locker;
DB_LOCK lock;
Debug( LDAP_DEBUG_ARGS,
"==> " LDAP_XSTRING(bdb_bind) ": dn: %s\n",
op->o_req_dn.bv_val, 0, 0);
+#ifdef LDAP_DEVEL
/* allow noauth binds */
- if ( op->oq_bind.rb_method == LDAP_AUTH_SIMPLE && be_isroot_pw( op )) {
- ber_dupbv( &op->oq_bind.rb_edn, be_root_dn( op->o_bd ) );
- /* front end will send result */
- return LDAP_SUCCESS;
+ switch ( be_rootdn_bind( op, rs ) ) {
+ case SLAP_CB_CONTINUE:
+ break;
+
+ default:
+ /* in case of success, frontend will send result;
+ * otherwise, be_rootdn_bind() did */
+ return rs->sr_err;
+ }
+
+#else /* traditional */
+ /* allow noauth binds */
+ switch ( be_rootdn_bind( op, NULL ) ) {
+ case LDAP_SUCCESS:
+ /* frontend will send result */
+ return rs->sr_err;
+
+ default:
+ /* give the database a chanche */
+ break;
}
+#endif /* traditional */
rs->sr_err = LOCK_ID(bdb->bi_dbenv, &locker);
switch(rs->sr_err) {
if ( cache->c_eifree ) {
ei = cache->c_eifree;
cache->c_eifree = ei->bei_lrunext;
+ ei->bei_finders = 0;
}
ldap_pvt_thread_mutex_unlock( &cache->c_eifree_mutex );
- ei->bei_finders = 0;
}
if ( !ei ) {
ei = ch_calloc(1, sizeof(EntryInfo));
* alternatives though.
*/
+#if DB_VERSION_FULL >= 0x04060012
+#define BDB_LOCKID(locker) locker->id
+#else
+#define BDB_LOCKID(locker) locker
+#endif
+
/* Atomically release and reacquire a lock */
int
bdb_cache_entry_db_relock(
struct bdb_info *bdb,
- u_int32_t locker,
+ BDB_LOCKER locker,
EntryInfo *ei,
int rw,
int tryOnly,
list[1].lock = *lock;
list[1].mode = rw ? DB_LOCK_WRITE : DB_LOCK_READ;
list[1].obj = &lockobj;
- rc = bdb->bi_dbenv->lock_vec(bdb->bi_dbenv, locker, tryOnly ? DB_LOCK_NOWAIT : 0,
+ rc = bdb->bi_dbenv->lock_vec(bdb->bi_dbenv, BDB_LOCKID(locker), tryOnly ? DB_LOCK_NOWAIT : 0,
list, 2, NULL );
if (rc && !tryOnly) {
}
static int
-bdb_cache_entry_db_lock( struct bdb_info *bdb, u_int32_t locker, EntryInfo *ei,
+bdb_cache_entry_db_lock( struct bdb_info *bdb, BDB_LOCKER locker, EntryInfo *ei,
int rw, int tryOnly, DB_LOCK *lock )
{
#ifdef NO_DB_LOCK
lockobj.data = &ei->bei_id;
lockobj.size = sizeof(ei->bei_id) + 1;
- rc = LOCK_GET(bdb->bi_dbenv, locker, tryOnly ? DB_LOCK_NOWAIT : 0,
+ rc = LOCK_GET(bdb->bi_dbenv, BDB_LOCKID(locker), tryOnly ? DB_LOCK_NOWAIT : 0,
&lockobj, db_rw, lock);
if (rc && !tryOnly) {
Debug( LDAP_DEBUG_TRACE,
hdb_cache_find_parent(
Operation *op,
DB_TXN *txn,
- u_int32_t locker,
+ BDB_LOCKER locker,
ID id,
EntryInfo **res )
{
if ( slapMode & SLAP_TOOL_READONLY )
eimax = 0;
else
- eimax = bdb->bi_cache.c_maxsize * 4;
+ eimax = bdb->bi_cache.c_eimax;
/* Look for an unused entry to remove */
for ( elru = bdb->bi_cache.c_lruhead; elru; elru = elnext ) {
ID id,
EntryInfo **eip,
int islocked,
- u_int32_t locker,
+ BDB_LOCKER locker,
DB_LOCK *lock )
{
struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
EntryInfo *eip,
Entry *e,
struct berval *nrdn,
- u_int32_t locker,
+ BDB_LOCKER locker,
DB_LOCK *lock )
{
EntryInfo *new, ei;
struct bdb_info *bdb,
Entry *e,
Attribute *newAttrs,
- u_int32_t locker,
+ BDB_LOCKER locker,
DB_LOCK *lock )
{
EntryInfo *ei = BEI(e);
struct berval *nrdn,
Entry *new,
EntryInfo *ein,
- u_int32_t locker,
+ BDB_LOCKER locker,
DB_LOCK *lock )
{
EntryInfo *ei = BEI(e), *pei;
bdb_cache_delete(
struct bdb_info *bdb,
Entry *e,
- u_int32_t locker,
+ BDB_LOCKER locker,
DB_LOCK *lock )
{
EntryInfo *ei = BEI(e);
{
EntryInfo *e;
- fprintf( stderr, "LRU circle head: %p\n", cache->c_lruhead );
+ fprintf( stderr, "LRU circle head: %p\n", (void *) cache->c_lruhead );
fprintf( stderr, "LRU circle (tail forward):\n" );
for ( e = cache->c_lrutail; ; ) {
fprintf( stderr, "\t%p, %p id %ld rdn \"%s\"\n",
- e, e->bei_e, e->bei_id, e->bei_nrdn.bv_val );
+ (void *) e, (void *) e->bei_e, e->bei_id, e->bei_nrdn.bv_val );
e = e->bei_lrunext;
if ( e == cache->c_lrutail )
break;
fprintf( stderr, "LRU circle (tail backward):\n" );
for ( e = cache->c_lrutail; ; ) {
fprintf( stderr, "\t%p, %p id %ld rdn \"%s\"\n",
- e, e->bei_e, e->bei_id, e->bei_nrdn.bv_val );
+ (void *) e, (void *) e->bei_e, e->bei_id, e->bei_nrdn.bv_val );
e = e->bei_lruprev;
if ( e == cache->c_lrutail )
break;
bdb_locker_id_free( void *key, void *data )
{
DB_ENV *env = key;
- u_int32_t lockid = (long)data;
+ u_int32_t lockid;
int rc;
+#if DB_VERSION_FULL >= 0x04060012
+ BDB_LOCKER lptr = data;
+ lockid = lptr->id;
+#else
+ lockid = (long)data;
+#endif
rc = XLOCK_ID_FREE( env, lockid );
if ( rc == EINVAL ) {
DB_LOCKREQ lr;
}
int
-bdb_locker_id( Operation *op, DB_ENV *env, u_int32_t *locker )
+bdb_locker_id( Operation *op, DB_ENV *env, BDB_LOCKER *locker )
{
int i, rc;
u_int32_t lockid;
if ( rc != 0) {
return rc;
}
+#if DB_VERSION_FULL >= 0x04060012
+ { BDB_LOCKER lptr;
+ __lock_getlocker( env->lk_handle, lockid, 0, &lptr );
+ data = lptr;
+ }
+#else
data = (void *)((long)lockid);
+#endif
if ( ( rc = ldap_pvt_thread_pool_setkey( ctx, env,
data, bdb_locker_id_free ) ) ) {
XLOCK_ID_FREE( env, lockid );
} else {
lockid = (long)data;
}
+#if DB_VERSION_FULL >= 0x04060012
+ *locker = data;
+#else
*locker = lockid;
+#endif
return 0;
}
#endif /* BDB_REUSE_LOCKERS */
Attribute *a;
int manageDSAit = get_manageDSAit( op );
- u_int32_t locker;
+ BDB_LOCKER locker;
DB_LOCK lock;
rs->sr_err = LOCK_ID(bdb->bi_dbenv, &locker);
"( OLcfgDbAt:1.5 NAME 'olcDbDirtyRead' "
"DESC 'Allow reads of uncommitted data' "
"SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL },
+ { "dncachesize", "size", 2, 2, 0, ARG_INT|ARG_OFFSET,
+ (void *)offsetof(struct bdb_info, bi_cache.c_eimax),
+ "( OLcfgDbAt:1.12 NAME 'olcDbDNcacheSize' "
+ "DESC 'DN cache size' "
+ "SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
{ "idlcachesize", "size", 2, 2, 0, ARG_INT|ARG_OFFSET,
(void *)offsetof(struct bdb_info,bi_idl_cache_max_size),
"( OLcfgDbAt:1.6 NAME 'olcDbIDLcacheSize' "
"olcDbNoSync $ olcDbDirtyRead $ olcDbIDLcacheSize $ "
"olcDbIndex $ olcDbLinearIndex $ olcDbLockDetect $ "
"olcDbMode $ olcDbSearchStack $ olcDbShmKey $ "
- "olcDbCacheFree ) )",
+ "olcDbCacheFree $ olcDbDNcacheSize ) )",
Cft_Database, bdbcfg },
{ NULL, 0, NULL }
};
Connection conn = {0};
OperationBuffer opbuf;
- Operation *op = (Operation *) &opbuf;
+ Operation *op;
DBC *curs;
DBT key, data;
DB_TXN *txn;
DB_LOCK lock;
- u_int32_t locker;
+ BDB_LOCKER locker;
ID id, nid;
EntryInfo *ei;
int rc, getnext = 1;
int i;
- connection_fake_init( &conn, op, ctx );
+ connection_fake_init( &conn, &opbuf, ctx );
+ op = &opbuf.ob_op;
op->o_bd = be;
if ( bdb->bi_flags & BDB_RE_OPEN ) {
bdb->bi_flags ^= BDB_RE_OPEN;
- rc = c->be->bd_info->bi_db_close( c->be );
+ rc = c->be->bd_info->bi_db_close( c->be, NULL );
if ( rc == 0 )
- rc = c->be->bd_info->bi_db_open( c->be );
+ rc = c->be->bd_info->bi_db_open( c->be, NULL );
/* If this fails, we need to restart */
if ( rc ) {
slapd_shutdown = 2;
bdb->bi_db_config_path = NULL;
c->cleanup = bdb_cf_cleanup;
ldap_pvt_thread_pool_purgekey( bdb->bi_dbenv );
- ldap_pvt_thread_pool_purgekey( ((char *)bdb->bi_dbenv) + 1 );
break;
case BDB_NOSYNC:
bdb->bi_dbenv->set_flags( bdb->bi_dbenv, DB_TXN_NOSYNC, 0 );
rc = db->bdi_db->set_flags( db->bdi_db, DB_DUP | DB_DUPSORT );
file = ch_malloc( strlen( name ) + sizeof(BDB_SUFFIX) );
- sprintf( file, "%s" BDB_SUFFIX, name );
+ sprintf( file, "%s%s", name, BDB_SUFFIX );
#ifdef HAVE_EBCDIC
__atoe( file );
struct bdb_op_info opinfo = {0};
ID eid;
- u_int32_t locker = 0;
+ BDB_LOCKER locker = 0;
DB_LOCK lock, plock;
int num_retries = 0;
ctrls[num_ctrls] = 0;
/* allocate CSN */
- if ( BER_BVISEMPTY( &op->o_csn )) {
+ if ( BER_BVISNULL( &op->o_csn ) ) {
struct berval csn;
char csnbuf[LDAP_LUTIL_CSNSTR_BUFSIZE];
struct berval *dn,
EntryInfo **e,
int matched,
- u_int32_t locker,
+ BDB_LOCKER locker,
DB_LOCK *lock )
{
EntryInfo *ei = NULL;
int
bdb_dn2idl(
Operation *op,
- u_int32_t locker,
+ BDB_LOCKER locker,
struct berval *ndn,
EntryInfo *ei,
ID *ids,
hdb_dn2id_parent(
Operation *op,
DB_TXN *txn,
- u_int32_t locker,
+ BDB_LOCKER locker,
EntryInfo *ei,
ID *idp )
{
rc = db->cursor( db, txn, &cursor, bdb->bi_db_opflags );
if ( rc ) return rc;
if ( !txn && locker ) {
- cursor->locker = locker;
+ CURSOR_SETLOCKER(cursor, locker);
}
data.ulen = sizeof(diskNode) + (SLAP_LDAPDN_MAXLEN * 2);
struct dn2id_cookie {
struct bdb_info *bdb;
Operation *op;
- u_int32_t locker;
+ BDB_LOCKER locker;
EntryInfo *ei;
ID *ids;
ID *tmp;
int
hdb_dn2idl(
Operation *op,
- u_int32_t locker,
+ BDB_LOCKER locker,
struct berval *ndn,
EntryInfo *ei,
ID *ids,
static int presence_candidates(
Operation *op,
- u_int32_t locker,
+ BDB_LOCKER locker,
AttributeDescription *desc,
ID *ids );
static int equality_candidates(
Operation *op,
- u_int32_t locker,
+ BDB_LOCKER locker,
AttributeAssertion *ava,
ID *ids,
ID *tmp );
static int inequality_candidates(
Operation *op,
- u_int32_t locker,
+ BDB_LOCKER locker,
AttributeAssertion *ava,
ID *ids,
ID *tmp,
int gtorlt );
static int approx_candidates(
Operation *op,
- u_int32_t locker,
+ BDB_LOCKER locker,
AttributeAssertion *ava,
ID *ids,
ID *tmp );
static int substring_candidates(
Operation *op,
- u_int32_t locker,
+ BDB_LOCKER locker,
SubstringsAssertion *sub,
ID *ids,
ID *tmp );
static int list_candidates(
Operation *op,
- u_int32_t locker,
+ BDB_LOCKER locker,
Filter *flist,
int ftype,
ID *ids,
static int
ext_candidates(
Operation *op,
- u_int32_t locker,
+ BDB_LOCKER locker,
MatchingRuleAssertion *mra,
ID *ids,
ID *tmp,
static int
comp_candidates (
Operation *op,
- u_int32_t locker,
+ BDB_LOCKER locker,
MatchingRuleAssertion *mra,
ComponentFilter *f,
ID *ids,
static int
ava_comp_candidates (
Operation *op,
- u_int32_t locker,
+ BDB_LOCKER locker,
AttributeAssertion *ava,
AttributeAliasing *aa,
ID *ids,
int
bdb_filter_candidates(
Operation *op,
- u_int32_t locker,
+ BDB_LOCKER locker,
Filter *f,
ID *ids,
ID *tmp,
static int
comp_list_candidates(
Operation *op,
- u_int32_t locker,
+ BDB_LOCKER locker,
MatchingRuleAssertion* mra,
ComponentFilter *flist,
int ftype,
static int
comp_equality_candidates (
Operation *op,
- u_int32_t locker,
+ BDB_LOCKER locker,
MatchingRuleAssertion *mra,
ComponentAssertion *ca,
ID *ids,
if( rc != LDAP_SUCCESS ) {
return 0;
}
- if ( db == NULL ) {
- return 0;
- }
if( !mr ) {
return 0;
static int
ava_comp_candidates (
Operation *op,
- u_int32_t locker,
+ BDB_LOCKER locker,
AttributeAssertion *ava,
AttributeAliasing *aa,
ID *ids,
static int
comp_candidates (
Operation *op,
- u_int32_t locker,
+ BDB_LOCKER locker,
MatchingRuleAssertion *mra,
ComponentFilter *f,
ID *ids,
static int
ext_candidates(
Operation *op,
- u_int32_t locker,
+ BDB_LOCKER locker,
MatchingRuleAssertion *mra,
ID *ids,
ID *tmp,
static int
list_candidates(
Operation *op,
- u_int32_t locker,
+ BDB_LOCKER locker,
Filter *flist,
int ftype,
ID *ids,
static int
presence_candidates(
Operation *op,
- u_int32_t locker,
+ BDB_LOCKER locker,
AttributeDescription *desc,
ID *ids )
{
rc = bdb_index_param( op->o_bd, desc, LDAP_FILTER_PRESENT,
&db, &mask, &prefix );
- if( rc != LDAP_SUCCESS ) {
+ if( rc == LDAP_INAPPROPRIATE_MATCHING ) {
+ /* not indexed */
Debug( LDAP_DEBUG_TRACE,
- "<= bdb_presence_candidates: (%s) index_param "
- "returned=%d\n",
- desc->ad_cname.bv_val, rc, 0 );
+ "<= bdb_presence_candidates: (%s) not indexed\n",
+ desc->ad_cname.bv_val, 0, 0 );
return 0;
}
- if( db == NULL ) {
- /* not indexed */
+ if( rc != LDAP_SUCCESS ) {
Debug( LDAP_DEBUG_TRACE,
- "<= bdb_presence_candidates: (%s) not indexed\n",
- desc->ad_cname.bv_val, 0, 0 );
+ "<= bdb_presence_candidates: (%s) index_param "
+ "returned=%d\n",
+ desc->ad_cname.bv_val, rc, 0 );
return 0;
}
static int
equality_candidates(
Operation *op,
- u_int32_t locker,
+ BDB_LOCKER locker,
AttributeAssertion *ava,
ID *ids,
ID *tmp )
rc = bdb_index_param( op->o_bd, ava->aa_desc, LDAP_FILTER_EQUALITY,
&db, &mask, &prefix );
- if( rc != LDAP_SUCCESS ) {
+ if ( rc == LDAP_INAPPROPRIATE_MATCHING ) {
Debug( LDAP_DEBUG_ANY,
- "<= bdb_equality_candidates: (%s) "
- "index_param failed (%d)\n",
- ava->aa_desc->ad_cname.bv_val, rc, 0 );
+ "<= bdb_equality_candidates: (%s) not indexed\n",
+ ava->aa_desc->ad_cname.bv_val, 0, 0 );
return 0;
}
- if ( db == NULL ) {
+ if( rc != LDAP_SUCCESS ) {
Debug( LDAP_DEBUG_ANY,
- "<= bdb_equality_candidates: (%s) not indexed\n",
- ava->aa_desc->ad_cname.bv_val, 0, 0 );
+ "<= bdb_equality_candidates: (%s) "
+ "index_param failed (%d)\n",
+ ava->aa_desc->ad_cname.bv_val, rc, 0 );
return 0;
}
static int
approx_candidates(
Operation *op,
- u_int32_t locker,
+ BDB_LOCKER locker,
AttributeAssertion *ava,
ID *ids,
ID *tmp )
rc = bdb_index_param( op->o_bd, ava->aa_desc, LDAP_FILTER_APPROX,
&db, &mask, &prefix );
- if( rc != LDAP_SUCCESS ) {
+ if ( rc == LDAP_INAPPROPRIATE_MATCHING ) {
Debug( LDAP_DEBUG_ANY,
- "<= bdb_approx_candidates: (%s) "
- "index_param failed (%d)\n",
- ava->aa_desc->ad_cname.bv_val, rc, 0 );
+ "<= bdb_approx_candidates: (%s) not indexed\n",
+ ava->aa_desc->ad_cname.bv_val, 0, 0 );
return 0;
}
- if ( db == NULL ) {
+ if( rc != LDAP_SUCCESS ) {
Debug( LDAP_DEBUG_ANY,
- "<= bdb_approx_candidates: (%s) not indexed\n",
- ava->aa_desc->ad_cname.bv_val, 0, 0 );
+ "<= bdb_approx_candidates: (%s) "
+ "index_param failed (%d)\n",
+ ava->aa_desc->ad_cname.bv_val, rc, 0 );
return 0;
}
static int
substring_candidates(
Operation *op,
- u_int32_t locker,
+ BDB_LOCKER locker,
SubstringsAssertion *sub,
ID *ids,
ID *tmp )
rc = bdb_index_param( op->o_bd, sub->sa_desc, LDAP_FILTER_SUBSTRINGS,
&db, &mask, &prefix );
- if( rc != LDAP_SUCCESS ) {
+ if ( rc == LDAP_INAPPROPRIATE_MATCHING ) {
Debug( LDAP_DEBUG_ANY,
- "<= bdb_substring_candidates: (%s) "
- "index_param failed (%d)\n",
- sub->sa_desc->ad_cname.bv_val, rc, 0 );
+ "<= bdb_substring_candidates: (%s) not indexed\n",
+ sub->sa_desc->ad_cname.bv_val, 0, 0 );
return 0;
}
- if ( db == NULL ) {
+ if( rc != LDAP_SUCCESS ) {
Debug( LDAP_DEBUG_ANY,
- "<= bdb_substring_candidates: (%s) not indexed\n",
- sub->sa_desc->ad_cname.bv_val, 0, 0 );
+ "<= bdb_substring_candidates: (%s) "
+ "index_param failed (%d)\n",
+ sub->sa_desc->ad_cname.bv_val, rc, 0 );
return 0;
}
static int
inequality_candidates(
Operation *op,
- u_int32_t locker,
+ BDB_LOCKER locker,
AttributeAssertion *ava,
ID *ids,
ID *tmp,
rc = bdb_index_param( op->o_bd, ava->aa_desc, LDAP_FILTER_EQUALITY,
&db, &mask, &prefix );
- if( rc != LDAP_SUCCESS ) {
+ if ( rc == LDAP_INAPPROPRIATE_MATCHING ) {
Debug( LDAP_DEBUG_ANY,
- "<= bdb_inequality_candidates: (%s) "
- "index_param failed (%d)\n",
- ava->aa_desc->ad_cname.bv_val, rc, 0 );
+ "<= bdb_inequality_candidates: (%s) not indexed\n",
+ ava->aa_desc->ad_cname.bv_val, 0, 0 );
return 0;
}
- if ( db == NULL ) {
+ if( rc != LDAP_SUCCESS ) {
Debug( LDAP_DEBUG_ANY,
- "<= bdb_inequality_candidates: (%s) not indexed\n",
- ava->aa_desc->ad_cname.bv_val, 0, 0 );
+ "<= bdb_inequality_candidates: (%s) "
+ "index_param failed (%d)\n",
+ ava->aa_desc->ad_cname.bv_val, rc, 0 );
return 0;
}
int bdb_id2entry(
BackendDB *be,
DB_TXN *tid,
- u_int32_t locker,
+ BDB_LOCKER locker,
ID id,
Entry **e )
{
if ( rc ) return rc;
/* Use our own locker if needed */
- if ( !tid && locker )
- cursor->locker = locker;
+ if ( !tid && locker ) {
+ CURSOR_SETLOCKER( cursor, locker );
+ }
/* Get the nattrs / nvals counts first */
data.ulen = data.dlen = sizeof(buf);
data.data = buf;
rc = cursor->c_get( cursor, &key, &data, DB_SET );
- if ( rc ) goto leave;
+ if ( rc ) goto finish;
eh.bv.bv_val = buf;
eh.bv.bv_len = data.size;
rc = entry_header( &eh );
- if ( rc ) goto leave;
+ if ( rc ) goto finish;
/* Get the size */
data.flags ^= DB_DBT_PARTIAL;
data.ulen = 0;
rc = cursor->c_get( cursor, &key, &data, DB_CURRENT );
- if ( rc != DB_BUFFER_SMALL ) goto leave;
+ if ( rc != DB_BUFFER_SMALL ) goto finish;
/* Allocate a block and retrieve the data */
off = eh.data - eh.bv.bv_val;
rc = cursor->c_get( cursor, &key, &data, DB_CURRENT );
-leave:
+finish:
cursor->c_close( cursor );
if( rc != 0 ) {
int rc;
const char *at_name = at ? at->ad_cname.bv_val : "(null)";
- u_int32_t locker = 0;
+ BDB_LOCKER locker = 0;
DB_LOCK lock;
int free_lock_id = 0;
bdb_idl_fetch_key(
BackendDB *be,
DB *db,
- u_int32_t locker,
+ BDB_LOCKER locker,
DBT *key,
ID *ids,
DBC **saved_cursor,
"cursor failed: %s (%d)\n", db_strerror(rc), rc, 0 );
return rc;
}
- cursor->locker = locker;
+ CURSOR_SETLOCKER( cursor, locker );
} else {
cursor = *saved_cursor;
}
{
AttrInfo *ai;
int rc;
- slap_mask_t mask;
+ slap_mask_t mask, type = 0;
DB *db;
ai = index_mask( be, desc, prefixp );
- if( !ai ) {
+ if ( !ai ) {
+#ifdef BDB_MONITOR_IDX
+ switch ( ftype ) {
+ case LDAP_FILTER_PRESENT:
+ type = SLAP_INDEX_PRESENT;
+ break;
+ case LDAP_FILTER_APPROX:
+ type = SLAP_INDEX_APPROX;
+ break;
+ case LDAP_FILTER_EQUALITY:
+ type = SLAP_INDEX_EQUALITY;
+ break;
+ case LDAP_FILTER_SUBSTRINGS:
+ type = SLAP_INDEX_SUBSTR;
+ break;
+ default:
+ return LDAP_INAPPROPRIATE_MATCHING;
+ }
+ bdb_monitor_idx_add( be->be_private, desc, type );
+#endif /* BDB_MONITOR_IDX */
+
return LDAP_INAPPROPRIATE_MATCHING;
}
mask = ai->ai_indexmask;
switch( ftype ) {
case LDAP_FILTER_PRESENT:
+ type = SLAP_INDEX_PRESENT;
if( IS_SLAP_INDEX( mask, SLAP_INDEX_PRESENT ) ) {
*prefixp = presence_key;
goto done;
break;
case LDAP_FILTER_APPROX:
+ type = SLAP_INDEX_APPROX;
if ( desc->ad_type->sat_approx ) {
if( IS_SLAP_INDEX( mask, SLAP_INDEX_APPROX ) ) {
goto done;
/* fall thru */
case LDAP_FILTER_EQUALITY:
+ type = SLAP_INDEX_EQUALITY;
if( IS_SLAP_INDEX( mask, SLAP_INDEX_EQUALITY ) ) {
goto done;
}
break;
case LDAP_FILTER_SUBSTRINGS:
+ type = SLAP_INDEX_SUBSTR;
if( IS_SLAP_INDEX( mask, SLAP_INDEX_SUBSTR ) ) {
goto done;
}
return LDAP_OTHER;
}
+#ifdef BDB_MONITOR_IDX
+ bdb_monitor_idx_add( be->be_private, desc, type );
+#endif /* BDB_MONITOR_IDX */
+
return LDAP_INAPPROPRIATE_MATCHING;
done:
AttrList *al;
int i, rc = 0;
+ /* Never index ID 0 */
+ if ( id == 0 )
+ return 0;
+
for (i=base; i<bdb->bi_nattrs; i+=slap_tool_thread_max) {
ir = ir0 + i;
if ( !ir->ai ) continue;
struct berval value = {0};
#endif
+ /* Never index ID 0 */
+ if ( e->e_id == 0 )
+ return 0;
+
Debug( LDAP_DEBUG_TRACE, "=> index_entry_%s( %ld, \"%s\" )\n",
opid == SLAP_INDEX_DELETE_OP ? "del" : "add",
(long) e->e_id, e->e_dn );
#include <lutil.h>
#include <ldap_rq.h>
#include "alock.h"
+#include "config.h"
static const struct bdbi_database {
char *file;
typedef void * db_malloc(size_t);
typedef void * db_realloc(void *, size_t);
+#define bdb_db_init BDB_SYMBOL(db_init)
+#define bdb_db_open BDB_SYMBOL(db_open)
+#define bdb_db_close BDB_SYMBOL(db_close)
+
static int
-bdb_db_init( BackendDB *be )
+bdb_db_init( BackendDB *be, ConfigReply *cr )
{
struct bdb_info *bdb;
int rc;
ldap_pvt_thread_rdwr_init( &bdb->bi_idl_tree_rwlock );
ldap_pvt_thread_mutex_init( &bdb->bi_idl_tree_lrulock );
- {
- Entry *e = entry_alloc();
- e->e_id = 0;
- e->e_private = &bdb->bi_cache.c_dntree;
- BER_BVSTR( &e->e_name, "" );
- BER_BVSTR( &e->e_nname, "" );
- bdb->bi_cache.c_dntree.bei_e = e;
- }
-
be->be_private = bdb;
be->be_cf_ocs = be->bd_info->bi_cf_ocs;
}
static int
-bdb_db_close( BackendDB *be );
+bdb_db_close( BackendDB *be, ConfigReply *cr );
static int
-bdb_db_open( BackendDB *be )
+bdb_db_open( BackendDB *be, ConfigReply *cr )
{
int rc, i;
struct bdb_info *bdb = (struct bdb_info *) be->be_private;
u_int32_t flags;
char path[MAXPATHLEN];
char *dbhome;
+ Entry *e = NULL;
int do_recover = 0, do_alock_recover = 0;
int alockt, quick = 0;
if ( be->be_suffix == NULL ) {
Debug( LDAP_DEBUG_ANY,
- "bdb_db_open: need suffix\n",
- 0, 0, 0 );
+ LDAP_XSTRING(bdb_db_open) ": need suffix\n",
+ 1, 0, 0 );
return -1;
}
Debug( LDAP_DEBUG_ARGS,
- "bdb_db_open: %s\n",
+ LDAP_XSTRING(bdb_db_open) ": %s\n",
be->be_suffix[0].bv_val, 0, 0 );
#ifndef BDB_MULTIPLE_SUFFIXES
if ( be->be_suffix[1].bv_val ) {
- Debug( LDAP_DEBUG_ANY,
- "bdb_db_open: only one suffix allowed\n", 0, 0, 0 );
+ if (cr) {
+ snprintf(cr->msg, sizeof(cr->msg), "only one suffix allowed");
+ Debug( LDAP_DEBUG_ANY,
+ LDAP_XSTRING(bdb_db_open) ": %s\n", cr->msg, 0, 0 );
+ }
return -1;
}
#endif
rc = stat( bdb->bi_dbenv_home, &stat1 );
if( rc !=0 ) {
Debug( LDAP_DEBUG_ANY,
- "bdb_db_open: Cannot access database directory %s (%d)\n",
+ LDAP_XSTRING(bdb_db_open) ": Cannot access database directory %s (%d)\n",
bdb->bi_dbenv_home, errno, 0 );
- return -1;
+ return -1;
}
/* Perform database use arbitration/recovery logic */
if( rc == ALOCK_RECOVER ) {
Debug( LDAP_DEBUG_ANY,
- "bdb_db_open: unclean shutdown detected;"
+ LDAP_XSTRING(bdb_db_open) ": unclean shutdown detected;"
" attempting recovery.\n",
0, 0, 0 );
do_alock_recover = 1;
do_recover = DB_RECOVER;
} else if( rc == ALOCK_BUSY ) {
Debug( LDAP_DEBUG_ANY,
- "bdb_db_open: database already in use\n",
+ LDAP_XSTRING(bdb_db_open) ": database already in use\n",
0, 0, 0 );
return -1;
} else if( rc != ALOCK_CLEAN ) {
Debug( LDAP_DEBUG_ANY,
- "bdb_db_open: alock package is unstable\n",
+ LDAP_XSTRING(bdb_db_open) ": alock package is unstable\n",
0, 0, 0 );
return -1;
}
if( stat( path, &stat2 ) == 0 ) {
if( stat2.st_mtime < stat1.st_mtime ) {
Debug( LDAP_DEBUG_ANY,
- "bdb_db_open: DB_CONFIG for suffix %s has changed.\n"
+ LDAP_XSTRING(bdb_db_open) ": DB_CONFIG for suffix %s has changed.\n"
"Performing database recovery to activate new settings.\n",
be->be_suffix[0].bv_val, 0, 0 );
do_recover = DB_RECOVER;
}
else {
Debug( LDAP_DEBUG_ANY,
- "bdb_db_open: Warning - No DB_CONFIG file found "
+ LDAP_XSTRING(bdb_db_open) ": Warning - No DB_CONFIG file found "
"in directory %s: (%d)\n"
"Expect poor performance for suffix %s.\n",
bdb->bi_dbenv_home, errno, be->be_suffix[0].bv_val );
*/
if ( do_recover && ( slapMode & SLAP_TOOL_READONLY )) {
Debug( LDAP_DEBUG_ANY,
- "bdb_db_open: Recovery skipped in read-only mode. "
+ LDAP_XSTRING(bdb_db_open) ": Recovery skipped in read-only mode. "
"Run manual recovery if errors are encountered.\n",
0, 0, 0 );
do_recover = 0;
/* An existing environment in Quick mode has nothing to recover. */
if ( alockt && do_recover ) {
Debug( LDAP_DEBUG_ANY,
- "bdb_db_open: cannot recover, database must be reinitialized.\n",
+ LDAP_XSTRING(bdb_db_open) ": cannot recover, database must be reinitialized.\n",
0, 0, 0 );
rc = -1;
goto fail;
rc = db_env_create( &bdb->bi_dbenv, 0 );
if( rc != 0 ) {
Debug( LDAP_DEBUG_ANY,
- "bdb_db_open: db_env_create failed: %s (%d)\n",
+ LDAP_XSTRING(bdb_db_open) ": db_env_create failed: %s (%d)\n",
db_strerror(rc), rc, 0 );
goto fail;
}
* currently requested modes, remove it.
*/
if ( !do_recover && ( alockt ^ quick )) {
+shm_retry:
rc = bdb->bi_dbenv->remove( bdb->bi_dbenv, dbhome, DB_FORCE );
if ( rc ) {
Debug( LDAP_DEBUG_ANY,
- "bdb_db_open: dbenv remove failed: %s (%d)\n",
+ LDAP_XSTRING(bdb_db_open) ": dbenv remove failed: %s (%d)\n",
db_strerror(rc), rc, 0 );
bdb->bi_dbenv = NULL;
goto fail;
rc = db_env_create( &bdb->bi_dbenv, 0 );
if( rc != 0 ) {
Debug( LDAP_DEBUG_ANY,
- "bdb_db_open: db_env_create failed: %s (%d)\n",
+ LDAP_XSTRING(bdb_db_open) ": db_env_create failed: %s (%d)\n",
db_strerror(rc), rc, 0 );
goto fail;
}
bdb->bi_dbenv_xflags, 1);
if( rc != 0 ) {
Debug( LDAP_DEBUG_ANY,
- "bdb_db_open: dbenv_set_flags failed: %s (%d)\n",
+ LDAP_XSTRING(bdb_db_open) ": dbenv_set_flags failed: %s (%d)\n",
db_strerror(rc), rc, 0 );
goto fail;
}
#define BDB_TXN_FLAGS (DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_TXN)
Debug( LDAP_DEBUG_TRACE,
- "bdb_db_open: dbenv_open(%s)\n",
+ LDAP_XSTRING(bdb_db_open) ": dbenv_open(%s)\n",
bdb->bi_dbenv_home, 0, 0);
flags = DB_INIT_MPOOL | DB_CREATE | DB_THREAD;
bdb->bi_dbenv->set_shm_key( bdb->bi_dbenv, bdb->bi_shm_key );
flags |= DB_SYSTEM_MEM;
}
- rc = bdb->bi_dbenv->open( bdb->bi_dbenv, dbhome,
+ rc = (bdb->bi_dbenv->open)( bdb->bi_dbenv, dbhome,
flags | do_recover, bdb->bi_dbenv_mode );
if ( rc ) {
+ /* Regular open failed, probably a missing shm environment.
+ * Start over, do a recovery.
+ */
+ if ( !do_recover && bdb->bi_shm_key ) {
+ bdb->bi_dbenv->close( bdb->bi_dbenv, 0 );
+ rc = db_env_create( &bdb->bi_dbenv, 0 );
+ if( rc == 0 ) {
+ Debug( LDAP_DEBUG_ANY, LDAP_XSTRING(bdb_db_open)
+ ": Shared memory env open failed, assuming stale env\n",
+ 0, 0, 0 );
+ goto shm_retry;
+ }
+ }
Debug( LDAP_DEBUG_ANY,
- "bdb_db_open: Database cannot be %s, err %d. "
+ LDAP_XSTRING(bdb_db_open) ": Database cannot be %s, err %d. "
"Restore from backup!\n",
do_recover ? "recovered" : "opened", rc, 0);
goto fail;
if ( do_alock_recover && alock_recover (&bdb->bi_alock_info) != 0 ) {
Debug( LDAP_DEBUG_ANY,
- "bdb_db_open: alock_recover failed\n",
+ LDAP_XSTRING(bdb_db_open) ": alock_recover failed\n",
0, 0, 0 );
rc = -1;
goto fail;
}
#endif
+ /* Default dncache to 2x entrycache */
+ if ( bdb->bi_cache.c_maxsize && !bdb->bi_cache.c_eimax ) {
+ bdb->bi_cache.c_eimax = bdb->bi_cache.c_maxsize * 2;
+ }
+
if ( bdb->bi_idl_cache_max_size ) {
bdb->bi_idl_tree = NULL;
bdb->bi_idl_cache_size = 0;
rc = db_create( &db->bdi_db, bdb->bi_dbenv, 0 );
if( rc != 0 ) {
Debug( LDAP_DEBUG_ANY,
- "bdb_db_open: db_create(%s) failed: %s (%d)\n",
+ LDAP_XSTRING(bdb_db_open) ": db_create(%s) failed: %s (%d)\n",
bdb->bi_dbenv_home, db_strerror(rc), rc );
goto fail;
}
snprintf( buf, sizeof(buf), "%s/%s",
bdb->bi_dbenv_home, bdbi_databases[i].file );
Debug( LDAP_DEBUG_ANY,
- "bdb_db_open: db_open(%s) failed: %s (%d)\n",
+ LDAP_XSTRING(bdb_db_open) ": db_open(%s) failed: %s (%d)\n",
buf, db_strerror(rc), rc );
db->bdi_db->close( db->bdi_db, 0 );
goto fail;
rc = bdb_last_id( be, NULL );
if( rc != 0 ) {
Debug( LDAP_DEBUG_ANY,
- "bdb_db_open: last_id(%s) failed: %s (%d)\n",
+ LDAP_XSTRING(bdb_db_open) ": last_id(%s) failed: %s (%d)\n",
bdb->bi_dbenv_home, db_strerror(rc), rc );
goto fail;
}
if ( !quick ) {
+#if DB_VERSION_FULL >= 0x04060012
+ u_int32_t lid;
+ XLOCK_ID(bdb->bi_dbenv, &lid);
+ __lock_getlocker(bdb->bi_dbenv->lk_handle, lid, 0, &bdb->bi_cache.c_locker);
+#else
XLOCK_ID(bdb->bi_dbenv, &bdb->bi_cache.c_locker);
+#endif
}
+ entry_prealloc( bdb->bi_cache.c_maxsize );
+ attr_prealloc( bdb->bi_cache.c_maxsize * 20 );
+
+ /* setup for empty-DN contexts */
+ if ( BER_BVISEMPTY( &be->be_nsuffix[0] )) {
+ rc = bdb_id2entry( be, NULL, 0, 0, &e );
+ }
+ if ( !e ) {
+ e = entry_alloc();
+ e->e_id = 0;
+ ber_dupbv( &e->e_name, (struct berval *)&slap_empty_bv );
+ ber_dupbv( &e->e_nname, (struct berval *)&slap_empty_bv );
+ }
+ e->e_ocflags = SLAP_OC_GLUE|SLAP_OC__END;
+ e->e_private = &bdb->bi_cache.c_dntree;
+ bdb->bi_cache.c_dntree.bei_e = e;
+
/* monitor setup */
rc = bdb_monitor_db_open( be );
if ( rc != 0 ) {
bdb->bi_flags |= BDB_IS_OPEN;
- entry_prealloc( bdb->bi_cache.c_maxsize );
- attr_prealloc( bdb->bi_cache.c_maxsize * 20 );
return 0;
fail:
- bdb_db_close( be );
+ bdb_db_close( be, NULL );
return rc;
}
static int
-bdb_db_close( BackendDB *be )
+bdb_db_close( BackendDB *be, ConfigReply *cr )
{
int rc;
struct bdb_info *bdb = (struct bdb_info *) be->be_private;
/* monitor handling */
(void)bdb_monitor_db_close( be );
+ {
+ Entry *e = bdb->bi_cache.c_dntree.bei_e;
+ if ( e ) {
+ bdb->bi_cache.c_dntree.bei_e = NULL;
+ e->e_private = NULL;
+ bdb_entry_return( e );
+ }
+ }
+
bdb->bi_flags &= ~BDB_IS_OPEN;
ber_bvarray_free( bdb->bi_db_config );
if( bdb->bi_dbenv ) {
/* Free cache locker if we enabled locking */
if ( !( slapMode & SLAP_TOOL_QUICK )) {
+#if DB_VERSION_FULL >= 0x04060012
+ XLOCK_ID_FREE(bdb->bi_dbenv, bdb->bi_cache.c_locker->id);
+#else
XLOCK_ID_FREE(bdb->bi_dbenv, bdb->bi_cache.c_locker);
+#endif
bdb->bi_cache.c_locker = 0;
}
#ifdef BDB_REUSE_LOCKERS
}
static int
-bdb_db_destroy( BackendDB *be )
+bdb_db_destroy( BackendDB *be, ConfigReply *cr )
{
struct bdb_info *bdb = (struct bdb_info *) be->be_private;
ldap_pvt_thread_rdwr_destroy( &bdb->bi_idl_tree_rwlock );
ldap_pvt_thread_mutex_destroy( &bdb->bi_idl_tree_lrulock );
- {
- Entry *e;
- e = bdb->bi_cache.c_dntree.bei_e;
- bdb->bi_cache.c_dntree.bei_e = NULL;
- e->e_private = NULL;
- BER_BVZERO( &e->e_name );
- BER_BVZERO( &e->e_nname );
- entry_free( e );
- }
-
ch_free( bdb );
be->be_private = NULL;
bi->bi_tool_entry_reindex = bdb_tool_entry_reindex;
bi->bi_tool_sync = 0;
bi->bi_tool_dn2id_get = bdb_tool_dn2id_get;
- bi->bi_tool_id2entry_get = bdb_tool_id2entry_get;
bi->bi_tool_entry_modify = bdb_tool_entry_modify;
bi->bi_connection_init = 0;
bdb_key_read(
Backend *be,
DB *db,
- u_int32_t locker,
+ BDB_LOCKER locker,
struct berval *k,
ID *ids,
DBC **saved_cursor,
Entry dummy = {0};
int fakeroot = 0;
- u_int32_t locker = 0;
+ BDB_LOCKER locker = 0;
DB_LOCK lock;
int num_retries = 0;
}
/* Modify the entry */
dummy = *e;
- rs->sr_err = bdb_modify_internal( op, lt2, op->oq_modify.rs_modlist,
+ rs->sr_err = bdb_modify_internal( op, lt2, op->orm_modlist,
&dummy, &rs->sr_text, textbuf, textlen );
if( rs->sr_err != LDAP_SUCCESS ) {
} else {
rs->sr_err = LDAP_X_NO_OPERATION;
ltid = NULL;
+ /* Only free attrs if they were dup'd. */
+ if ( dummy.e_attrs == e->e_attrs ) dummy.e_attrs = NULL;
goto return_results;
}
} else {
int manageDSAit = get_manageDSAit( op );
- u_int32_t locker = 0;
+ BDB_LOCKER locker = 0;
DB_LOCK lock, plock, nplock;
int num_retries = 0;
struct berval bv = {0, NULL};
dnNormalize( 0, NULL, NULL, &new_dn, &bv, op->o_tmpmemctx );
ber_dupbv( &new_ndn, &bv );
+ /* FIXME: why not call dnNormalize() w/o ctx? */
+ op->o_tmpfree( bv.bv_val, op->o_tmpmemctx );
}
Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(bdb_modrdn) ": new ndn=%s\n",
static ObjectClass *oc_olmBDBDatabase;
static AttributeDescription *ad_olmBDBEntryCache,
- *ad_olmBDBEntryInfo, *ad_olmBDBIDLCache,
+ *ad_olmBDBDNCache, *ad_olmBDBIDLCache,
*ad_olmDbDirectory;
+#ifdef BDB_MONITOR_IDX
+static int
+bdb_monitor_idx_entry_add(
+ struct bdb_info *bdb,
+ Entry *e );
+
+static AttributeDescription *ad_olmBDBNotIndexed;
+#endif /* BDB_MONITOR_IDX */
+
/*
* NOTE: there's some confusion in monitor OID arc;
* by now, let's consider:
&ad_olmBDBEntryCache },
{ "( olmBDBAttributes:2 "
- "NAME ( 'olmBDBEntryInfo' ) "
- "DESC 'Number of items in EntryInfo Cache' "
+ "NAME ( 'olmBDBDNCache' ) "
+ "DESC 'Number of items in DN Cache' "
"SUP monitorCounter "
"NO-USER-MODIFICATION "
"USAGE dSAOperation )",
- &ad_olmBDBEntryInfo },
+ &ad_olmBDBDNCache },
{ "( olmBDBAttributes:3 "
"NAME ( 'olmBDBIDLCache' ) "
"USAGE dSAOperation )",
&ad_olmDbDirectory },
+#ifdef BDB_MONITOR_IDX
+ { "( olmBDBAttributes:5 "
+ "NAME ( 'olmBDBNotIndexed' ) "
+ "DESC 'Missing indexes resulting from candidate selection' "
+ "SUP monitoredInfo "
+ "NO-USER-MODIFICATION "
+ "USAGE dSAOperation )",
+ &ad_olmBDBNotIndexed },
+#endif /* BDB_MONITOR_IDX */
+
{ NULL }
};
"SUP top AUXILIARY "
"MAY ( "
"olmBDBEntryCache "
- "$ olmBDBEntryInfo "
+ "$ olmBDBDNCache "
"$ olmBDBIDLCache "
"$ olmDbDirectory "
+#ifdef BDB_MONITOR_IDX
+ "$ olmBDBNotIndexed "
+#endif /* BDB_MONITOR_IDX */
") )",
&oc_olmBDBDatabase },
bv.bv_len = snprintf( buf, sizeof( buf ), "%d", bdb->bi_cache.c_cursize );
ber_bvreplace( &a->a_vals[ 0 ], &bv );
- a = attr_find( e->e_attrs, ad_olmBDBEntryInfo );
+ a = attr_find( e->e_attrs, ad_olmBDBDNCache );
assert( a != NULL );
bv.bv_len = snprintf( buf, sizeof( buf ), "%d", bdb->bi_cache.c_eiused );
ber_bvreplace( &a->a_vals[ 0 ], &bv );
bv.bv_len = snprintf( buf, sizeof( buf ), "%d", bdb->bi_idl_cache_size );
ber_bvreplace( &a->a_vals[ 0 ], &bv );
+#ifdef BDB_MONITOR_IDX
+ bdb_monitor_idx_entry_add( bdb, e );
+#endif /* BDB_MONITOR_IDX */
+
return SLAP_CB_CONTINUE;
}
{
struct bdb_info *bdb = (struct bdb_info *) be->be_private;
+ if ( SLAP_GLUE_SUBORDINATE( be ) ) {
+ return 0;
+ }
+
if ( bdb_monitor_initialize() == LDAP_SUCCESS ) {
/* monitoring in back-bdb is on by default */
SLAP_DBFLAGS( be ) |= SLAP_DBFLAG_MONITORING;
}
+#ifdef BDB_MONITOR_IDX
+ bdb->bi_idx = NULL;
+ ldap_pvt_thread_mutex_init( &bdb->bi_idx_mutex );
+#endif /* BDB_MONITOR_IDX */
+
bdb->bi_monitor.bdm_scope = -1;
return 0;
return 0;
}
+ if ( SLAP_GLUE_SUBORDINATE( be ) ) {
+ return 0;
+ }
+
mi = backend_info( "monitor" );
if ( !mi || !mi->bi_extra ) {
SLAP_DBFLAGS( be ) ^= SLAP_DBFLAG_MONITORING;
next->a_nvals = next->a_vals;
next = next->a_next;
- next->a_desc = ad_olmBDBEntryInfo;
+ next->a_desc = ad_olmBDBDNCache;
value_add_one( &next->a_vals, &bv );
next->a_nvals = next->a_vals;
next = next->a_next;
cb->mc_free = bdb_monitor_free;
cb->mc_private = (void *)bdb;
- rc = mbe->register_entry_attrs( NULL, a, cb,
- base, bdb->bi_monitor.bdm_scope, filter );
+ /* make sure the database is registered; then add monitor attributes */
+ rc = mbe->register_database( be );
+ if ( rc == 0 ) {
+ rc = mbe->register_entry_attrs( NULL, a, cb,
+ base, bdb->bi_monitor.bdm_scope, filter );
+ }
cleanup:;
if ( rc != 0 ) {
{
struct bdb_info *bdb = (struct bdb_info *) be->be_private;
+ if ( SLAP_GLUE_SUBORDINATE( be ) ) {
+ return 0;
+ }
+
if ( !BER_BVISNULL( &bdb->bi_monitor.bdm_filter ) ) {
BackendInfo *mi = backend_info( "monitor" );
monitor_extra_t *mbe;
int
bdb_monitor_db_destroy( BackendDB *be )
{
+ if ( SLAP_GLUE_SUBORDINATE( be ) ) {
+ return 0;
+ }
+
+#ifdef BDB_MONITOR_IDX
+ {
+ struct bdb_info *bdb = (struct bdb_info *) be->be_private;
+
+ /* TODO: free tree */
+ ldap_pvt_thread_mutex_destroy( &bdb->bi_idx_mutex );
+ avl_free( bdb->bi_idx, ch_free );
+ }
+#endif /* BDB_MONITOR_IDX */
+
return 0;
}
+
+#ifdef BDB_MONITOR_IDX
+
+#define BDB_MONITOR_IDX_TYPES (4)
+
+typedef struct monitor_idx_t monitor_idx_t;
+
+struct monitor_idx_t {
+ AttributeDescription *idx_ad;
+ unsigned long idx_count[BDB_MONITOR_IDX_TYPES];
+};
+
+static int
+bdb_monitor_bitmask2key( slap_mask_t bitmask )
+{
+ int key;
+
+ for ( key = 0; key < 8*sizeof(slap_mask_t) && !( bitmask & 0x1U ); key++ ) {
+ bitmask >>= 1;
+ }
+
+ return key;
+}
+
+static struct berval idxbv[] = {
+ BER_BVC( "present=" ),
+ BER_BVC( "equality=" ),
+ BER_BVC( "approx=" ),
+ BER_BVC( "substr=" ),
+ BER_BVNULL
+};
+
+static ber_len_t
+bdb_monitor_idx2len( monitor_idx_t *idx )
+{
+ int i;
+ ber_len_t len = 0;
+
+ for ( i = 0; i < BDB_MONITOR_IDX_TYPES; i++ ) {
+ if ( idx->idx_count[ i ] != 0 ) {
+ len += idxbv[i].bv_len;
+ }
+ }
+
+ return len;
+}
+
+static int
+monitor_idx_cmp( const void *p1, const void *p2 )
+{
+ const monitor_idx_t *idx1 = (const monitor_idx_t *)p1;
+ const monitor_idx_t *idx2 = (const monitor_idx_t *)p2;
+
+ return SLAP_PTRCMP( idx1->idx_ad, idx2->idx_ad );
+}
+
+static int
+monitor_idx_dup( void *p1, void *p2 )
+{
+ monitor_idx_t *idx1 = (monitor_idx_t *)p1;
+ monitor_idx_t *idx2 = (monitor_idx_t *)p2;
+
+ return SLAP_PTRCMP( idx1->idx_ad, idx2->idx_ad ) == 0 ? -1 : 0;
+}
+
+int
+bdb_monitor_idx_add(
+ struct bdb_info *bdb,
+ AttributeDescription *desc,
+ slap_mask_t type )
+{
+ monitor_idx_t idx_dummy = { 0 },
+ *idx;
+ int rc = 0, key;
+
+ idx_dummy.idx_ad = desc;
+ key = bdb_monitor_bitmask2key( type ) - 1;
+ if ( key >= BDB_MONITOR_IDX_TYPES ) {
+ /* invalid index type */
+ return -1;
+ }
+
+ ldap_pvt_thread_mutex_lock( &bdb->bi_idx_mutex );
+
+ idx = (monitor_idx_t *)avl_find( bdb->bi_idx,
+ (caddr_t)&idx_dummy, monitor_idx_cmp );
+ if ( idx == NULL ) {
+ idx = (monitor_idx_t *)ch_calloc( sizeof( monitor_idx_t ), 1 );
+ idx->idx_ad = desc;
+ idx->idx_count[ key ] = 1;
+
+ switch ( avl_insert( &bdb->bi_idx, (caddr_t)idx,
+ monitor_idx_cmp, monitor_idx_dup ) )
+ {
+ case 0:
+ break;
+
+ default:
+ ch_free( idx );
+ rc = -1;
+ }
+
+ } else {
+ idx->idx_count[ key ]++;
+ }
+
+ ldap_pvt_thread_mutex_unlock( &bdb->bi_idx_mutex );
+
+ return rc;
+}
+
+static int
+bdb_monitor_idx_apply( void *v_idx, void *v_valp )
+{
+ monitor_idx_t *idx = (monitor_idx_t *)v_idx;
+ BerVarray *valp = (BerVarray *)v_valp;
+
+ struct berval bv;
+ char *ptr;
+ char count_buf[ BDB_MONITOR_IDX_TYPES ][ SLAP_TEXT_BUFLEN ];
+ ber_len_t count_len[ BDB_MONITOR_IDX_TYPES ],
+ idx_len;
+ int i, num = 0;
+
+ idx_len = bdb_monitor_idx2len( idx );
+
+ bv.bv_len = 0;
+ for ( i = 0; i < BDB_MONITOR_IDX_TYPES; i++ ) {
+ if ( idx->idx_count[ i ] == 0 ) {
+ continue;
+ }
+
+ count_len[ i ] = snprintf( count_buf[ i ],
+ sizeof( count_buf[ i ] ), "%lu", idx->idx_count[ i ] );
+ bv.bv_len += count_len[ i ];
+ num++;
+ }
+
+ bv.bv_len += idx->idx_ad->ad_cname.bv_len
+ + num
+ + idx_len;
+ ptr = bv.bv_val = ch_malloc( bv.bv_len + 1 );
+ ptr = lutil_strcopy( ptr, idx->idx_ad->ad_cname.bv_val );
+ for ( i = 0; i < BDB_MONITOR_IDX_TYPES; i++ ) {
+ if ( idx->idx_count[ i ] == 0 ) {
+ continue;
+ }
+
+ ptr[ 0 ] = '#';
+ ++ptr;
+ ptr = lutil_strcopy( ptr, idxbv[ i ].bv_val );
+ ptr = lutil_strcopy( ptr, count_buf[ i ] );
+ }
+
+ ber_bvarray_add( valp, &bv );
+
+ return 0;
+}
+
+static int
+bdb_monitor_idx_entry_add(
+ struct bdb_info *bdb,
+ Entry *e )
+{
+ BerVarray vals = NULL;
+ Attribute *a;
+
+ a = attr_find( e->e_attrs, ad_olmBDBNotIndexed );
+
+ ldap_pvt_thread_mutex_lock( &bdb->bi_idx_mutex );
+
+ avl_apply( bdb->bi_idx, bdb_monitor_idx_apply,
+ &vals, -1, AVL_INORDER );
+
+ ldap_pvt_thread_mutex_unlock( &bdb->bi_idx_mutex );
+
+ if ( vals != NULL ) {
+ if ( a != NULL ) {
+ assert( a->a_nvals == a->a_vals );
+
+ ber_bvarray_free( a->a_vals );
+
+ } else {
+ Attribute **ap;
+
+ for ( ap = &e->e_attrs; *ap != NULL; ap = &(*ap)->a_next )
+ ;
+ *ap = attr_alloc( ad_olmBDBNotIndexed );
+ a = *ap;
+ }
+ a->a_vals = vals;
+ a->a_nvals = a->a_vals;
+ }
+
+ return 0;
+}
+
+#endif /* BDB_MONITOR_IDX */
int bdb_dn2entry LDAP_P(( Operation *op, DB_TXN *tid,
struct berval *dn, EntryInfo **e, int matched,
- u_int32_t locker, DB_LOCK *lock ));
+ BDB_LOCKER locker, DB_LOCK *lock ));
/*
* dn2id.c
int bdb_dn2idl(
Operation *op,
- u_int32_t locker,
+ BDB_LOCKER locker,
struct berval *ndn,
EntryInfo *ei,
ID *ids,
int bdb_dn2id_parent(
Operation *op,
DB_TXN *txn,
- u_int32_t locker,
+ BDB_LOCKER locker,
EntryInfo *ei,
ID *idp );
int bdb_filter_candidates(
Operation *op,
- u_int32_t locker,
+ BDB_LOCKER locker,
Filter *f,
ID *ids,
ID *tmp,
int bdb_id2entry(
BackendDB *be,
DB_TXN *tid,
- u_int32_t locker,
+ BDB_LOCKER locker,
ID id,
Entry **e);
#endif
int bdb_idl_fetch_key(
BackendDB *be,
DB *db,
- u_int32_t locker,
+ BDB_LOCKER locker,
DBT *key,
ID *ids,
DBC **saved_cursor,
bdb_key_read(
Backend *be,
DB *db,
- u_int32_t locker,
+ BDB_LOCKER locker,
struct berval *k,
ID *ids,
DBC **saved_cursor,
int bdb_monitor_db_close( BackendDB *be );
int bdb_monitor_db_destroy( BackendDB *be );
+#ifdef BDB_MONITOR_IDX
+#define bdb_monitor_idx_add BDB_SYMBOL(monitor_idx_add)
+int
+bdb_monitor_idx_add(
+ struct bdb_info *bdb,
+ AttributeDescription *desc,
+ slap_mask_t type );
+#endif /* BDB_MONITOR_IDX */
+
/*
* cache.c
*/
EntryInfo *pei,
Entry *e,
struct berval *nrdn,
- u_int32_t locker,
+ BDB_LOCKER locker,
DB_LOCK *lock
);
int bdb_cache_modrdn(
struct berval *nrdn,
Entry *new,
EntryInfo *ein,
- u_int32_t locker,
+ BDB_LOCKER locker,
DB_LOCK *lock
);
int bdb_cache_modify(
struct bdb_info *bdb,
Entry *e,
Attribute *newAttrs,
- u_int32_t locker,
+ BDB_LOCKER locker,
DB_LOCK *lock
);
int bdb_cache_find_ndn(
ID id,
EntryInfo **eip,
int islocked,
- u_int32_t locker,
+ BDB_LOCKER locker,
DB_LOCK *lock
);
int
bdb_cache_find_parent(
Operation *op,
DB_TXN *txn,
- u_int32_t locker,
+ BDB_LOCKER locker,
ID id,
EntryInfo **res
);
int bdb_cache_delete(
struct bdb_info *bdb,
Entry *e,
- u_int32_t locker,
+ BDB_LOCKER locker,
DB_LOCK *lock
);
void bdb_cache_delete_cleanup(
#define bdb_cache_entry_db_relock BDB_SYMBOL(cache_entry_db_relock)
int bdb_cache_entry_db_relock(
struct bdb_info *bdb,
- u_int32_t locker,
+ BDB_LOCKER locker,
EntryInfo *ei,
int rw,
int tryOnly,
#define bdb_locker_id BDB_SYMBOL(locker_id)
#define bdb_locker_flush BDB_SYMBOL(locker_flush)
-int bdb_locker_id( Operation *op, DB_ENV *env, u_int32_t *locker );
+int bdb_locker_id( Operation *op, DB_ENV *env, BDB_LOCKER *locker );
void bdb_locker_flush( DB_ENV *env );
#define LOCK_ID_FREE(env, locker) ((void)0)
#define bdb_tool_entry_put BDB_SYMBOL(tool_entry_put)
#define bdb_tool_entry_reindex BDB_SYMBOL(tool_entry_reindex)
#define bdb_tool_dn2id_get BDB_SYMBOL(tool_dn2id_get)
-#define bdb_tool_id2entry_get BDB_SYMBOL(tool_id2entry_get)
#define bdb_tool_entry_modify BDB_SYMBOL(tool_entry_modify)
#define bdb_tool_idl_add BDB_SYMBOL(tool_idl_add)
extern BI_tool_entry_put bdb_tool_entry_put;
extern BI_tool_entry_reindex bdb_tool_entry_reindex;
extern BI_tool_dn2id_get bdb_tool_dn2id_get;
-extern BI_tool_id2entry_get bdb_tool_id2entry_get;
extern BI_tool_entry_modify bdb_tool_entry_modify;
int bdb_tool_idl_add( BackendDB *be, DB *db, DB_TXN *txn, DBT *key, ID id );
EntryInfo *ei;
int rc = LDAP_SUCCESS;
- u_int32_t locker;
+ BDB_LOCKER locker;
DB_LOCK lock;
if( op->o_tag == LDAP_REQ_SEARCH ) {
if ( e != NULL ) {
Debug( LDAP_DEBUG_TRACE,
LDAP_XSTRING(bdb_referrals)
- ": op=%ld target=\"%s\" matched=\"%s\"\n",
- (long) op->o_tag, op->o_req_dn.bv_val, e->e_name.bv_val );
+ ": tag=%lu target=\"%s\" matched=\"%s\"\n",
+ (unsigned long)op->o_tag, op->o_req_dn.bv_val, e->e_name.bv_val );
if( is_entry_referral( e ) ) {
BerVarray ref = get_entry_referrals( op, e );
Debug( LDAP_DEBUG_TRACE,
LDAP_XSTRING(bdb_referrals)
- ": op=%ld target=\"%s\" matched=\"%s\"\n",
- (long) op->o_tag, op->o_req_dn.bv_val, e->e_name.bv_val );
+ ": tag=%lu target=\"%s\" matched=\"%s\"\n",
+ (unsigned long)op->o_tag, op->o_req_dn.bv_val, e->e_name.bv_val );
rs->sr_matched = e->e_name.bv_val;
if( rs->sr_ref != NULL ) {
Operation *op,
SlapReply *rs,
Entry *e,
- u_int32_t locker,
+ BDB_LOCKER locker,
ID *ids,
ID *scopes );
SlapReply *rs,
Entry *e,
Entry **matched,
- u_int32_t locker,
+ BDB_LOCKER locker,
DB_LOCK *lock,
ID *tmp,
ID *visited )
Operation *op,
SlapReply *rs,
Entry *e,
- u_int32_t locker,
+ BDB_LOCKER locker,
ID *ids,
ID *scopes,
ID *stack )
ID lastid = NOID;
AttributeName *attrs;
- u_int32_t locker = 0;
+ BDB_LOCKER locker = 0;
DB_LOCK lock;
struct bdb_op_info *opinfo = NULL;
DB_TXN *ltid = NULL;
goto done;
}
+ /* mostly needed by internal searches,
+ * e.g. related to syncrepl, for whom
+ * abandon does not get set... */
+ if ( slapd_shutdown ) {
+ rs->sr_err = LDAP_UNAVAILABLE;
+ send_ldap_disconnect( op, rs );
+ goto done;
+ }
+
/* check time limit */
if ( op->ors_tlimit != SLAP_NO_LIMIT
&& slap_get_time() > stoptime )
Operation *op,
SlapReply *rs,
Entry *e,
- u_int32_t locker,
+ BDB_LOCKER locker,
ID *ids,
ID *scopes )
{
static DBC *cursor = NULL;
static DBT key, data;
static EntryHeader eh;
-static int eoff;
+static ID nid, previd = NOID;
+static char ehbuf[16];
typedef struct dn_id {
ID id;
static ldap_pvt_thread_cond_t bdb_tool_index_cond_main;
static ldap_pvt_thread_cond_t bdb_tool_index_cond_work;
+static ldap_pvt_thread_mutex_t bdb_tool_trickle_mutex;
+static ldap_pvt_thread_cond_t bdb_tool_trickle_cond;
+
static void * bdb_tool_index_task( void *ctx, void *ptr );
+static void * bdb_tool_trickle_task( void *ctx, void *ptr );
int bdb_tool_entry_open(
BackendDB *be, int mode )
/* initialize key and data thangs */
DBTzero( &key );
DBTzero( &data );
- key.flags = DB_DBT_REALLOC;
+ key.flags = DB_DBT_USERMEM;
+ key.data = &nid;
+ key.size = key.ulen = sizeof( nid );
data.flags = DB_DBT_USERMEM;
if (cursor == NULL) {
}
/* Set up for threaded slapindex */
- if (( slapMode & (SLAP_TOOL_QUICK|SLAP_TOOL_READONLY)) == SLAP_TOOL_QUICK
- && bdb->bi_nattrs ) {
+ if (( slapMode & (SLAP_TOOL_QUICK|SLAP_TOOL_READONLY)) == SLAP_TOOL_QUICK ) {
if ( !bdb_tool_info ) {
- int i;
+ ldap_pvt_thread_mutex_init( &bdb_tool_trickle_mutex );
+ ldap_pvt_thread_cond_init( &bdb_tool_trickle_cond );
+ ldap_pvt_thread_pool_submit( &connection_pool, bdb_tool_trickle_task, bdb->bi_dbenv );
+
ldap_pvt_thread_mutex_init( &bdb_tool_index_mutex );
ldap_pvt_thread_cond_init( &bdb_tool_index_cond_main );
ldap_pvt_thread_cond_init( &bdb_tool_index_cond_work );
- bdb_tool_index_threads = ch_malloc( slap_tool_thread_max * sizeof( int ));
- bdb_tool_index_rec = ch_malloc( bdb->bi_nattrs * sizeof( IndexRec ));
- bdb_tool_index_tcount = slap_tool_thread_max - 1;
- for (i=1; i<slap_tool_thread_max; i++) {
- int *ptr = ch_malloc( sizeof( int ));
- *ptr = i;
- ldap_pvt_thread_pool_submit( &connection_pool,
- bdb_tool_index_task, ptr );
+ if ( bdb->bi_nattrs ) {
+ int i;
+ bdb_tool_index_threads = ch_malloc( slap_tool_thread_max * sizeof( int ));
+ bdb_tool_index_rec = ch_malloc( bdb->bi_nattrs * sizeof( IndexRec ));
+ bdb_tool_index_tcount = slap_tool_thread_max - 1;
+ for (i=1; i<slap_tool_thread_max; i++) {
+ int *ptr = ch_malloc( sizeof( int ));
+ *ptr = i;
+ ldap_pvt_thread_pool_submit( &connection_pool,
+ bdb_tool_index_task, ptr );
+ }
}
+ bdb_tool_info = bdb;
}
- bdb_tool_info = bdb;
}
return 0;
{
if ( bdb_tool_info ) {
slapd_shutdown = 1;
+ ldap_pvt_thread_mutex_lock( &bdb_tool_trickle_mutex );
+ ldap_pvt_thread_cond_signal( &bdb_tool_trickle_cond );
+ ldap_pvt_thread_mutex_unlock( &bdb_tool_trickle_mutex );
ldap_pvt_thread_mutex_lock( &bdb_tool_index_mutex );
bdb_tool_index_tcount = slap_tool_thread_max - 1;
ldap_pvt_thread_cond_broadcast( &bdb_tool_index_cond_work );
ldap_pvt_thread_mutex_unlock( &bdb_tool_index_mutex );
}
- if( key.data ) {
- ch_free( key.data );
- key.data = NULL;
- }
if( eh.bv.bv_val ) {
ch_free( eh.bv.bv_val );
eh.bv.bv_val = NULL;
int rc;
ID id;
struct bdb_info *bdb = (struct bdb_info *) be->be_private;
- char buf[16], *dptr;
assert( be != NULL );
assert( slapMode & SLAP_TOOL_MODE );
assert( bdb != NULL );
-
+
/* Get the header */
- data.ulen = data.dlen = sizeof( buf );
- data.data = buf;
+ data.ulen = data.dlen = sizeof( ehbuf );
+ data.data = ehbuf;
data.flags |= DB_DBT_PARTIAL;
rc = cursor->c_get( cursor, &key, &data, DB_NEXT );
}
}
- dptr = eh.bv.bv_val;
- eh.bv.bv_val = buf;
- eh.bv.bv_len = data.size;
- rc = entry_header( &eh );
- eoff = eh.data - eh.bv.bv_val;
- eh.bv.bv_val = dptr;
- if( rc ) {
- return NOID;
- }
-
BDB_DISK2ID( key.data, &id );
+ previd = id;
return id;
}
return ei->bei_id;
}
-int bdb_tool_id2entry_get(
- Backend *be,
- ID id,
- Entry **e
-)
-{
- int rc = bdb_id2entry( be, NULL, 0, id, e );
-
- if ( rc == DB_NOTFOUND && id == 0 ) {
- Entry *dummy = ch_calloc( 1, sizeof(Entry) );
- struct berval gluebv = BER_BVC("glue");
- dummy->e_name.bv_val = ch_strdup( "" );
- dummy->e_nname.bv_val = ch_strdup( "" );
- attr_merge_one( dummy, slap_schema.si_ad_objectClass, &gluebv, NULL );
- attr_merge_one( dummy, slap_schema.si_ad_structuralObjectClass,
- &gluebv, NULL );
- *e = dummy;
- rc = LDAP_SUCCESS;
- }
- return rc;
-}
-
Entry* bdb_tool_entry_get( BackendDB *be, ID id )
{
- int rc;
Entry *e = NULL;
+ char *dptr;
+ int rc, eoff;
assert( be != NULL );
assert( slapMode & SLAP_TOOL_MODE );
+ if ( id != previd ) {
+ data.ulen = data.dlen = sizeof( ehbuf );
+ data.data = ehbuf;
+ data.flags |= DB_DBT_PARTIAL;
+
+ BDB_ID2DISK( id, &nid );
+ rc = cursor->c_get( cursor, &key, &data, DB_SET );
+ if ( rc ) goto done;
+ }
+
+ /* Get the header */
+ dptr = eh.bv.bv_val;
+ eh.bv.bv_val = ehbuf;
+ eh.bv.bv_len = data.size;
+ rc = entry_header( &eh );
+ eoff = eh.data - eh.bv.bv_val;
+ eh.bv.bv_val = dptr;
+ if ( rc ) goto done;
+
/* Get the size */
- data.flags ^= DB_DBT_PARTIAL;
+ data.flags &= ~DB_DBT_PARTIAL;
data.ulen = 0;
rc = cursor->c_get( cursor, &key, &data, DB_CURRENT );
- if ( rc != DB_BUFFER_SMALL ) goto leave;
+ if ( rc != DB_BUFFER_SMALL ) goto done;
/* Allocate a block and retrieve the data */
eh.bv.bv_len = eh.nvals * sizeof( struct berval ) + data.size;
eh.data += eoff;
rc = cursor->c_get( cursor, &key, &data, DB_CURRENT );
- if ( rc ) goto leave;
+ if ( rc ) goto done;
#ifdef SLAP_ZONE_ALLOC
/* FIXME: will add ctx later */
op.o_tmpmemctx = NULL;
op.o_tmpmfuncs = &ch_mfuncs;
- rc = bdb_cache_find_parent( &op, NULL, cursor->locker, id, &ei );
+ rc = bdb_cache_find_parent( &op, NULL, CURSOR_GETLOCKER(cursor), id, &ei );
if ( rc == LDAP_SUCCESS ) {
bdb_cache_entryinfo_unlock( ei );
e->e_private = ei;
}
#endif
}
-leave:
+done:
return e;
}
goto done;
}
+ if (( slapMode & SLAP_TOOL_QUICK ) && (( e->e_id & 0xfff ) == 0xfff )) {
+ ldap_pvt_thread_mutex_lock( &bdb_tool_trickle_mutex );
+ ldap_pvt_thread_cond_signal( &bdb_tool_trickle_cond );
+ ldap_pvt_thread_mutex_unlock( &bdb_tool_trickle_mutex );
+ }
+
if ( !bdb->bi_linear_index )
rc = bdb_tool_index_add( &op, tid, e );
if( rc != 0 ) {
}
#endif
+static void *
+bdb_tool_trickle_task( void *ctx, void *ptr )
+{
+ DB_ENV *env = ptr;
+ int wrote;
+
+ ldap_pvt_thread_mutex_lock( &bdb_tool_trickle_mutex );
+ while ( 1 ) {
+ ldap_pvt_thread_cond_wait( &bdb_tool_trickle_cond,
+ &bdb_tool_trickle_mutex );
+ if ( slapd_shutdown )
+ break;
+ env->memp_trickle( env, 30, &wrote );
+ }
+ ldap_pvt_thread_mutex_unlock( &bdb_tool_trickle_mutex );
+
+ return NULL;
+}
+
static void *
bdb_tool_index_task( void *ctx, void *ptr )
{
int
dnssrv_back_bind(
- Operation *op,
- SlapReply *rs )
+ Operation *op,
+ SlapReply *rs )
{
- Debug( LDAP_DEBUG_TRACE, "DNSSRV: bind %s (%d)\n",
- op->o_req_dn.bv_val == NULL ? "" : op->o_req_dn.bv_val,
- op->oq_bind.rb_method, NULL );
-
- if ( op->oq_bind.rb_method == LDAP_AUTH_SIMPLE &&
- !BER_BVISNULL( &op->oq_bind.rb_cred ) &&
- !BER_BVISEMPTY( &op->oq_bind.rb_cred ) )
+ Debug( LDAP_DEBUG_TRACE, "DNSSRV: bind dn=\"%s\" (%d)\n",
+ BER_BVISNULL( &op->o_req_dn ) ? "" : op->o_req_dn.bv_val,
+ op->orb_method, 0 );
+
+ /* allow rootdn as a means to auth without the need to actually
+ * contact the proxied DSA */
+ switch ( be_rootdn_bind( op, NULL ) ) {
+ case LDAP_SUCCESS:
+ /* frontend will send result */
+ return rs->sr_err;
+
+ default:
+ /* treat failure and like any other bind, otherwise
+ * it could reveal the DN of the rootdn */
+ break;
+ }
+
+ if ( !BER_BVISNULL( &op->orb_cred ) &&
+ !BER_BVISEMPTY( &op->orb_cred ) )
{
+ /* simple bind */
Statslog( LDAP_DEBUG_STATS,
- "%s DNSSRV BIND dn=\"%s\" provided passwd\n",
+ "%s DNSSRV BIND dn=\"%s\" provided cleartext passwd\n",
op->o_log_prefix,
BER_BVISNULL( &op->o_req_dn ) ? "" : op->o_req_dn.bv_val , 0, 0, 0 );
- Debug( LDAP_DEBUG_TRACE,
- "DNSSRV: BIND dn=\"%s\" provided cleartext password\n",
- BER_BVISNULL( &op->o_req_dn ) ? "" : op->o_req_dn.bv_val, 0, 0 );
-
send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
"you shouldn't send strangers your password" );
} else {
+ /* unauthenticated bind */
+ /* NOTE: we're not going to get here anyway:
+ * unauthenticated bind is dealt with by the frontend */
Debug( LDAP_DEBUG_TRACE, "DNSSRV: BIND dn=\"%s\"\n",
BER_BVISNULL( &op->o_req_dn ) ? "" : op->o_req_dn.bv_val, 0, 0 );
#include <stdio.h>
#include <ac/socket.h>
+#include <ac/param.h>
+#include <ac/string.h>
#include "slap.h"
+#include "config.h"
#include "proto-dnssrv.h"
int
int
dnssrv_back_db_init(
- Backend *be )
+ Backend *be,
+ ConfigReply *cr)
{
return 0;
}
int
dnssrv_back_db_destroy(
- Backend *be )
+ Backend *be,
+ ConfigReply *cr )
{
return 0;
}
retry:
ctrls = op->o_ctrls;
- rs->sr_err = ldap_back_proxy_authz_ctrl( &lc->lc_bound_ndn,
- li->li_version, &li->li_idassert, op, rs, &ctrls );
+ rs->sr_err = ldap_back_controls_add( op, rs, lc, &ctrls );
if ( rs->sr_err != LDAP_SUCCESS ) {
send_ldap_result( op, rs );
goto cleanup;
retrying &= ~LDAP_BACK_RETRYING;
if ( ldap_back_retry( &lc, op, rs, LDAP_BACK_SENDERR ) ) {
/* if the identity changed, there might be need to re-authz */
- (void)ldap_back_proxy_authz_ctrl_free( op, &ctrls );
+ (void)ldap_back_controls_free( op, rs, &ctrls );
goto retry;
}
}
cleanup:
- (void)ldap_back_proxy_authz_ctrl_free( op, &ctrls );
+ (void)ldap_back_controls_free( op, rs, &ctrls );
if ( attrs ) {
for ( --i; i >= 0; --i ) {
#define LDAP_BACK_F_QUARANTINE (0x00010000U)
+#ifdef SLAP_CONTROL_X_SESSION_TRACKING
+#define LDAP_BACK_F_ST_REQUEST (0x00020000U)
+#define LDAP_BACK_F_ST_RESPONSE (0x00040000U)
+#endif /* SLAP_CONTROL_X_SESSION_TRACKING */
+
#define LDAP_BACK_ISSET_F(ff,f) ( ( (ff) & (f) ) == (f) )
#define LDAP_BACK_ISMASK_F(ff,m,f) ( ( (ff) & (m) ) == (f) )
#define LDAP_BACK_QUARANTINE(li) LDAP_BACK_ISSET( (li), LDAP_BACK_F_QUARANTINE )
+#ifdef SLAP_CONTROL_X_SESSION_TRACKING
+#define LDAP_BACK_ST_REQUEST(li) LDAP_BACK_ISSET( (li), LDAP_BACK_F_ST_REQUEST)
+#define LDAP_BACK_ST_RESPONSE(li) LDAP_BACK_ISSET( (li), LDAP_BACK_F_ST_RESPONSE)
+#endif /* SLAP_CONTROL_X_SESSION_TRACKING */
+
int li_version;
/* cached connections;
ldapinfo_t *li = (ldapinfo_t *) op->o_bd->be_private;
ldapconn_t *lc;
- int rc = 0;
+ LDAPControl **ctrls = NULL;
+ struct berval save_o_dn;
+ int save_o_do_not_cache,
+ rc = 0;
ber_int_t msgid;
ldap_back_send_t retrying = LDAP_BACK_RETRYING;
+ /* allow rootdn as a means to auth without the need to actually
+ * contact the proxied DSA */
+ switch ( be_rootdn_bind( op, rs ) ) {
+ case SLAP_CB_CONTINUE:
+ break;
+
+ default:
+ return rs->sr_err;
+ }
+
lc = ldap_back_getconn( op, rs, LDAP_BACK_BIND_SERR, NULL, NULL );
if ( !lc ) {
return rs->sr_err;
}
LDAP_BACK_CONN_ISBOUND_CLEAR( lc );
+ /* don't add proxyAuthz; set the bindDN */
+ save_o_dn = op->o_dn;
+ save_o_do_not_cache = op->o_do_not_cache;
+ op->o_dn = op->o_req_dn;
+ op->o_do_not_cache = 1;
+
+ ctrls = op->o_ctrls;
+ rc = ldap_back_controls_add( op, rs, lc, &ctrls );
+ op->o_dn = save_o_dn;
+ op->o_do_not_cache = save_o_do_not_cache;
+ if ( rc != LDAP_SUCCESS ) {
+ send_ldap_result( op, rs );
+ ldap_back_release_conn( li, lc );
+ return( rc );
+ }
+
retry:;
/* method is always LDAP_AUTH_SIMPLE if we got here */
rs->sr_err = ldap_sasl_bind( lc->lc_ld, op->o_req_dn.bv_val,
LDAP_SASL_SIMPLE,
- &op->orb_cred, op->o_ctrls, NULL, &msgid );
+ &op->orb_cred, ctrls, NULL, &msgid );
/* FIXME: should we always retry, or only when piping the bind
* in the "override" connection pool? */
rc = ldap_back_op_result( lc, op, rs, msgid,
}
}
+ ldap_back_controls_free( op, rs, &ctrls );
+
if ( rc == LDAP_SUCCESS ) {
/* If defined, proxyAuthz will be used also when
* back-ldap is the authorizing backend; for this
op->o_ndn = op->o_req_ndn;
}
isproxyauthz = ldap_back_is_proxy_authz( op, rs, sendok, binddn, bindcred );
- if ( isproxyauthz == -1 ) {
- return NULL;
- }
if ( op->o_tag == LDAP_REQ_BIND ) {
op->o_dn = save_o_dn;
op->o_ndn = save_o_ndn;
}
+ if ( isproxyauthz == -1 ) {
+ return NULL;
+ }
lc_curr.lc_local_ndn = op->o_ndn;
/* Explicit binds must not be shared;
ldap_pvt_thread_mutex_unlock( &li->li_quarantine_mutex );
}
+static int
+ldap_back_dobind_cb(
+ Operation *op,
+ SlapReply *rs
+)
+{
+ ber_tag_t *tptr = op->o_callback->sc_private;
+ op->o_tag = *tptr;
+ return SLAP_CB_CONTINUE;
+}
+
/*
* ldap_back_dobind_int
*
isbound,
binding = 0;
ber_int_t msgid;
+ ber_tag_t o_tag = op->o_tag;
+ slap_callback cb = {0};
assert( lcp != NULL );
assert( retries >= 0 );
* then bind as the asserting identity and explicitly
* add the proxyAuthz control to every operation with the
* dn bound to the connection as control value.
- * This is done also if this is the authrizing backend,
+ * This is done also if this is the authorizing backend,
* but the "override" flag is given to idassert.
* It allows to use SASL bind and yet proxyAuthz users
*/
+ op->o_tag = LDAP_REQ_BIND;
+ cb.sc_next = op->o_callback;
+ cb.sc_private = &o_tag;
+ cb.sc_response = ldap_back_dobind_cb;
+ op->o_callback = &cb;
+
if ( LDAP_BACK_CONN_ISIDASSERT( lc ) ) {
if ( BER_BVISEMPTY( &binddn ) && BER_BVISEMPTY( &bindcred ) ) {
/* if we got here, it shouldn't return result */
li->li_acl_authcID.bv_val,
li->li_acl_passwd.bv_val,
NULL );
+ if ( defaults == NULL ) {
+ rs->sr_err = LDAP_OTHER;
+ LDAP_BACK_CONN_ISBOUND_CLEAR( lc );
+ if ( sendok & LDAP_BACK_SENDERR ) {
+ send_ldap_result( op, rs );
+ }
+ goto done;
+ }
rs->sr_err = ldap_sasl_interactive_bind_s( lc->lc_ld,
li->li_acl_authcDN.bv_val,
if ( rs->sr_err != LDAP_SUCCESS &&
( sendok & LDAP_BACK_SENDERR ) )
{
+ if ( op->o_callback == &cb )
+ op->o_callback = cb.sc_next;
+ op->o_tag = o_tag;
rs->sr_text = "Internal proxy bind failure";
send_ldap_result( op, rs );
}
- return 0;
+ rc = 0;
+ goto leave;
}
rc = ldap_back_op_result( lc, op, rs, msgid,
ldap_set_rebind_proc( lc->lc_ld, li->li_rebind_f, lc );
}
+leave:;
+ if ( op->o_callback == &cb )
+ op->o_callback = cb.sc_next;
+ op->o_tag = o_tag;
+
return rc;
}
if ( rc != LDAP_SUCCESS ) {
rs->sr_err = rc;
}
- if ( refs != NULL ) {
- int i;
-
- for ( i = 0; refs[ i ] != NULL; i++ )
- /* count */ ;
- rs->sr_ref = op->o_tmpalloc( sizeof( struct berval ) * ( i + 1 ),
- op->o_tmpmemctx );
- for ( i = 0; refs[ i ] != NULL; i++ ) {
- ber_str2bv( refs[ i ], 0, 0, &rs->sr_ref[ i ] );
+
+ /* RFC 4511: referrals can only appear
+ * if result code is LDAP_REFERRAL */
+ if ( refs != NULL
+ && refs[ 0 ] != NULL
+ && refs[ 0 ][ 0 ] != '\0' )
+ {
+ if ( rs->sr_err != LDAP_REFERRAL ) {
+ Debug( LDAP_DEBUG_ANY,
+ "%s ldap_back_op_result: "
+ "got referrals with err=%d\n",
+ op->o_log_prefix,
+ rs->sr_err, 0 );
+
+ } else {
+ int i;
+
+ for ( i = 0; refs[ i ] != NULL; i++ )
+ /* count */ ;
+ rs->sr_ref = op->o_tmpalloc( sizeof( struct berval ) * ( i + 1 ),
+ op->o_tmpmemctx );
+ for ( i = 0; refs[ i ] != NULL; i++ ) {
+ ber_str2bv( refs[ i ], 0, 0, &rs->sr_ref[ i ] );
+ }
+ BER_BVZERO( &rs->sr_ref[ i ] );
}
- BER_BVZERO( &rs->sr_ref[ i ] );
+
+ } else if ( rs->sr_err == LDAP_REFERRAL ) {
+ Debug( LDAP_DEBUG_ANY,
+ "%s ldap_back_op_result: "
+ "got err=%d with null "
+ "or empty referrals\n",
+ op->o_log_prefix,
+ rs->sr_err, 0 );
+
+ rs->sr_err = LDAP_NO_SUCH_OBJECT;
}
+
if ( ctrls != NULL ) {
rs->sr_ctrls = ctrls;
}
rs->sr_text = NULL;
if ( rs->sr_ref ) {
- assert( refs != NULL );
- ber_memvfree( (void **)refs );
op->o_tmpfree( rs->sr_ref, op->o_tmpmemctx );
rs->sr_ref = NULL;
}
+ if ( refs ) {
+ ber_memvfree( (void **)refs );
+ }
+
if ( ctrls ) {
assert( rs->sr_ctrls != NULL );
ldap_controls_free( ctrls );
li->li_idassert_authcID.bv_val,
li->li_idassert_passwd.bv_val,
authzID.bv_val );
+ if ( defaults == NULL ) {
+ rs->sr_err = LDAP_OTHER;
+ LDAP_BACK_CONN_ISBOUND_CLEAR( lc );
+ if ( sendok & LDAP_BACK_SENDERR ) {
+ send_ldap_result( op, rs );
+ }
+ goto done;
+ }
rs->sr_err = ldap_sasl_interactive_bind_s( lc->lc_ld, binddn->bv_val,
li->li_idassert_sasl_mech.bv_val, NULL, NULL,
*/
int
ldap_back_proxy_authz_ctrl(
+ Operation *op,
+ SlapReply *rs,
struct berval *bound_ndn,
int version,
slap_idassert_t *si,
- Operation *op,
- SlapReply *rs,
- LDAPControl ***pctrls )
+ LDAPControl *ctrl )
{
- LDAPControl **ctrls = NULL;
- int i = 0;
slap_idassert_mode_t mode;
struct berval assertedID,
ndn;
int isroot = 0;
- *pctrls = NULL;
-
- rs->sr_err = LDAP_SUCCESS;
-
- /* don't proxyAuthz if protocol is not LDAPv3 */
- switch ( version ) {
- case LDAP_VERSION3:
- break;
-
- case 0:
- if ( op->o_protocol == 0 || op->o_protocol == LDAP_VERSION3 ) {
- break;
- }
- /* fall thru */
-
- default:
- goto done;
- }
+ rs->sr_err = SLAP_CB_CONTINUE;
/* FIXME: SASL/EXTERNAL over ldapi:// doesn't honor the authcID,
* but if it is not set this test fails. We need a different
authcDN = ndn;
}
rc = slap_sasl_matches( op, si->si_authz,
- &authcDN, & authcDN );
+ &authcDN, &authcDN );
if ( rc != LDAP_SUCCESS ) {
if ( si->si_flags & LDAP_BACK_AUTH_PRESCRIPTIVE ) {
/* ndn is not authorized
goto done;
}
- if ( op->o_ctrls ) {
- for ( i = 0; op->o_ctrls[ i ]; i++ )
- /* just count ctrls */ ;
- }
-
- ctrls = op->o_tmpalloc( sizeof( LDAPControl * ) * (i + 2) + sizeof( LDAPControl ),
- op->o_tmpmemctx );
- ctrls[ 0 ] = (LDAPControl *)&ctrls[ i + 2 ];
-
- ctrls[ 0 ]->ldctl_oid = LDAP_CONTROL_PROXY_AUTHZ;
- ctrls[ 0 ]->ldctl_iscritical = 1;
-
switch ( si->si_mode ) {
/* already in u:ID or dn:DN form */
case LDAP_BACK_IDASSERT_OTHERID:
case LDAP_BACK_IDASSERT_OTHERDN:
- ber_dupbv_x( &ctrls[ 0 ]->ldctl_value, &assertedID, op->o_tmpmemctx );
+ ber_dupbv_x( &ctrl->ldctl_value, &assertedID, op->o_tmpmemctx );
break;
/* needs the dn: prefix */
default:
- ctrls[ 0 ]->ldctl_value.bv_len = assertedID.bv_len + STRLENOF( "dn:" );
- ctrls[ 0 ]->ldctl_value.bv_val = op->o_tmpalloc( ctrls[ 0 ]->ldctl_value.bv_len + 1,
+ ctrl->ldctl_value.bv_len = assertedID.bv_len + STRLENOF( "dn:" );
+ ctrl->ldctl_value.bv_val = op->o_tmpalloc( ctrl->ldctl_value.bv_len + 1,
op->o_tmpmemctx );
- AC_MEMCPY( ctrls[ 0 ]->ldctl_value.bv_val, "dn:", STRLENOF( "dn:" ) );
- AC_MEMCPY( &ctrls[ 0 ]->ldctl_value.bv_val[ STRLENOF( "dn:" ) ],
+ AC_MEMCPY( ctrl->ldctl_value.bv_val, "dn:", STRLENOF( "dn:" ) );
+ AC_MEMCPY( &ctrl->ldctl_value.bv_val[ STRLENOF( "dn:" ) ],
assertedID.bv_val, assertedID.bv_len + 1 );
break;
}
* this hack provides compatibility with those DSAs that
* implement it this way */
if ( si->si_flags & LDAP_BACK_AUTH_OBSOLETE_ENCODING_WORKAROUND ) {
- struct berval authzID = ctrls[ 0 ]->ldctl_value;
+ struct berval authzID = ctrl->ldctl_value;
BerElementBuffer berbuf;
BerElement *ber = (BerElement *)&berbuf;
ber_tag_t tag;
goto free_ber;
}
- if ( ber_flatten2( ber, &ctrls[ 0 ]->ldctl_value, 1 ) == -1 ) {
+ if ( ber_flatten2( ber, &ctrl->ldctl_value, 1 ) == -1 ) {
rs->sr_err = LDAP_OTHER;
goto free_ber;
}
ber_free_buf( ber );
if ( rs->sr_err != LDAP_SUCCESS ) {
- op->o_tmpfree( ctrls, op->o_tmpmemctx );
- ctrls = NULL;
goto done;
}
} else if ( si->si_flags & LDAP_BACK_AUTH_OBSOLETE_PROXY_AUTHZ ) {
- struct berval authzID = ctrls[ 0 ]->ldctl_value,
+ struct berval authzID = ctrl->ldctl_value,
tmp;
BerElementBuffer berbuf;
BerElement *ber = (BerElement *)&berbuf;
ber_tag_t tag;
if ( strncasecmp( authzID.bv_val, "dn:", STRLENOF( "dn:" ) ) != 0 ) {
- op->o_tmpfree( ctrls[ 0 ]->ldctl_value.bv_val, op->o_tmpmemctx );
- op->o_tmpfree( ctrls, op->o_tmpmemctx );
- ctrls = NULL;
rs->sr_err = LDAP_PROTOCOL_ERROR;
goto done;
}
goto free_ber2;
}
- if ( ber_flatten2( ber, &ctrls[ 0 ]->ldctl_value, 1 ) == -1 ) {
+ if ( ber_flatten2( ber, &ctrl->ldctl_value, 1 ) == -1 ) {
rs->sr_err = LDAP_OTHER;
goto free_ber2;
}
ber_free_buf( ber );
if ( rs->sr_err != LDAP_SUCCESS ) {
- op->o_tmpfree( ctrls, op->o_tmpmemctx );
- ctrls = NULL;
goto done;
}
- ctrls[ 0 ]->ldctl_oid = LDAP_CONTROL_OBSOLETE_PROXY_AUTHZ;
+ ctrl->ldctl_oid = LDAP_CONTROL_OBSOLETE_PROXY_AUTHZ;
+ }
+
+done:;
+
+ return rs->sr_err;
+}
+
+/*
+ * Add controls;
+ *
+ * if any needs to be added, it is prepended to existing ones,
+ * in a newly allocated array. The companion function
+ * ldap_back_controls_free() must be used to restore the original
+ * status of op->o_ctrls.
+ */
+int
+ldap_back_controls_add(
+ Operation *op,
+ SlapReply *rs,
+ ldapconn_t *lc,
+ LDAPControl ***pctrls )
+{
+ ldapinfo_t *li = (ldapinfo_t *)op->o_bd->be_private;
+
+ LDAPControl **ctrls = NULL;
+ /* set to the maximum number of controls this backend can add */
+ LDAPControl c[ 2 ] = { 0 };
+ int i = 0, j = 0;
+
+ *pctrls = NULL;
+
+ rs->sr_err = LDAP_SUCCESS;
+
+ /* don't add controls if protocol is not LDAPv3 */
+ switch ( li->li_version ) {
+ case LDAP_VERSION3:
+ break;
+
+ case 0:
+ if ( op->o_protocol == 0 || op->o_protocol == LDAP_VERSION3 ) {
+ break;
+ }
+ /* fall thru */
+
+ default:
+ goto done;
+ }
+
+ /* proxyAuthz for identity assertion */
+ switch ( ldap_back_proxy_authz_ctrl( op, rs, &lc->lc_bound_ndn,
+ li->li_version, &li->li_idassert, &c[ j ] ) )
+ {
+ case SLAP_CB_CONTINUE:
+ break;
+
+ case LDAP_SUCCESS:
+ j++;
+ break;
+
+ default:
+ goto done;
+ }
+
+#ifdef SLAP_CONTROL_X_SESSION_TRACKING
+ /* session tracking */
+ if ( LDAP_BACK_ST_REQUEST( li ) ) {
+ switch ( slap_ctrl_session_tracking_request_add( op, rs, &c[ j ] ) ) {
+ case SLAP_CB_CONTINUE:
+ break;
+
+ case LDAP_SUCCESS:
+ j++;
+ break;
+
+ default:
+ goto done;
+ }
+ }
+#endif /* SLAP_CONTROL_X_SESSION_TRACKING */
+
+ if ( rs->sr_err == SLAP_CB_CONTINUE ) {
+ rs->sr_err = LDAP_SUCCESS;
+ }
+
+ if ( j == 0 ) {
+ goto done;
}
+ if ( op->o_ctrls ) {
+ for ( i = 0; op->o_ctrls[ i ]; i++ )
+ /* just count ctrls */ ;
+ }
+
+ ctrls = op->o_tmpalloc( sizeof( LDAPControl * ) * (i + j + 1) + j * sizeof( LDAPControl ),
+ op->o_tmpmemctx );
+ ctrls[ 0 ] = (LDAPControl *)&ctrls[ i + j + 1 ];
+ *ctrls[ 0 ] = c[ 0 ];
+ for ( i = 1; i < j; i++ ) {
+ ctrls[ i ] = &ctrls[ 0 ][ i ];
+ *ctrls[ i ] = c[ i ];
+ }
+
+ i = 0;
if ( op->o_ctrls ) {
for ( i = 0; op->o_ctrls[ i ]; i++ ) {
- ctrls[ i + 1 ] = op->o_ctrls[ i ];
+ ctrls[ i + j ] = op->o_ctrls[ i ];
}
}
- ctrls[ i + 1 ] = NULL;
+ ctrls[ i + j ] = NULL;
done:;
if ( ctrls == NULL ) {
}
int
-ldap_back_proxy_authz_ctrl_free( Operation *op, LDAPControl ***pctrls )
+ldap_back_controls_free( Operation *op, SlapReply *rs, LDAPControl ***pctrls )
{
LDAPControl **ctrls = *pctrls;
- /* we assume that the first control is the proxyAuthz
- * added by back-ldap, so it's the only one we explicitly
- * free */
+ /* we assume that the controls added by the proxy come first,
+ * so as soon as we find op->o_ctrls[ 0 ] we can stop */
if ( ctrls && ctrls != op->o_ctrls ) {
+ int i;
+
assert( ctrls[ 0 ] != NULL );
- if ( !BER_BVISNULL( &ctrls[ 0 ]->ldctl_value ) ) {
- op->o_tmpfree( ctrls[ 0 ]->ldctl_value.bv_val, op->o_tmpmemctx );
+ for ( i = 0; ctrls[ i ] != NULL; i++ ) {
+ if ( op->o_ctrls && ctrls[ i ] == op->o_ctrls[ 0 ] ) {
+ break;
+ }
+
+ if ( !BER_BVISNULL( &ctrls[ i ]->ldctl_value ) ) {
+ op->o_tmpfree( ctrls[ i ]->ldctl_value.bv_val, op->o_tmpmemctx );
+ }
}
op->o_tmpfree( ctrls, op->o_tmpmemctx );
static int ldap_chain_db_init_one( BackendDB *be );
static int ldap_chain_db_open_one( BackendDB *be );
#define ldap_chain_db_close_one(be) (0)
-#define ldap_chain_db_destroy_one(be) (lback)->bi_db_destroy( (be) )
+#define ldap_chain_db_destroy_one(be, rs) (lback)->bi_db_destroy( (be), (rs) )
typedef struct ldap_chain_cb_t {
ldap_chain_status_t lb_status;
LDAPURLDesc *srv = NULL;
struct berval save_req_dn = op->o_req_dn,
save_req_ndn = op->o_req_ndn,
- dn,
+ dn = BER_BVNULL,
pdn = BER_BVNULL,
ndn = BER_BVNULL;
int temporary = 0;
}
/* normalize DN */
- ber_str2bv( srv->lud_dn, 0, 0, &dn );
- rc = dnPrettyNormal( NULL, &dn, &pdn, &ndn, op->o_tmpmemctx );
- if ( rc == LDAP_SUCCESS ) {
- /* remove DN essentially because later on
- * ldap_initialize() will parse the URL
- * as a comma-separated URL list */
+ rc = LDAP_SUCCESS;
+ srv->lud_scope = LDAP_SCOPE_DEFAULT;
+ if ( srv->lud_dn != NULL ) {
+ ber_str2bv( srv->lud_dn, 0, 0, &dn );
+ rc = dnPrettyNormal( NULL, &dn, &pdn, &ndn, op->o_tmpmemctx );
+ if ( rc == LDAP_SUCCESS ) {
+ /* remove DN essentially because later on
+ * ldap_initialize() will parse the URL
+ * as a comma-separated URL list */
+ srv->lud_dn = "";
+ }
+
+ } else {
srv->lud_dn = "";
- srv->lud_scope = LDAP_SCOPE_DEFAULT;
- li.li_uri = ldap_url_desc2str( srv );
- srv->lud_dn = dn.bv_val;
}
+
+ li.li_uri = ldap_url_desc2str( srv );
+ srv->lud_dn = dn.bv_val;
ldap_free_urldesc( srv );
if ( rc != LDAP_SUCCESS ) {
if ( rc != 0 ) {
lip->li_uri = NULL;
lip->li_bvuri = NULL;
- (void)ldap_chain_db_destroy_one( op->o_bd );
+ (void)ldap_chain_db_destroy_one( op->o_bd, NULL);
goto cleanup;
}
lip->li_uri = NULL;
lip->li_bvuri = NULL;
(void)ldap_chain_db_close_one( op->o_bd );
- (void)ldap_chain_db_destroy_one( op->o_bd );
+ (void)ldap_chain_db_destroy_one( op->o_bd, NULL );
}
further_cleanup:;
}
/* normalize DN */
- ber_str2bv( srv->lud_dn, 0, 0, &dn );
- rc = dnPrettyNormal( NULL, &dn, &pdn, &ndn, op->o_tmpmemctx );
- if ( rc == LDAP_SUCCESS ) {
- /* remove DN essentially because later on
- * ldap_initialize() will parse the URL
- * as a comma-separated URL list */
- srv->lud_dn = "";
- srv->lud_scope = LDAP_SCOPE_DEFAULT;
- li.li_uri = ldap_url_desc2str( srv );
- srv->lud_dn = dn.bv_val;
+ rc = LDAP_INVALID_SYNTAX;
+ if ( srv->lud_dn != NULL ) {
+ ber_str2bv( srv->lud_dn, 0, 0, &dn );
+ rc = dnPrettyNormal( NULL, &dn, &pdn, &ndn, op->o_tmpmemctx );
+ if ( rc == LDAP_SUCCESS ) {
+ /* remove DN essentially because later on
+ * ldap_initialize() will parse the URL
+ * as a comma-separated URL list */
+ srv->lud_dn = "";
+ srv->lud_scope = LDAP_SCOPE_DEFAULT;
+ li.li_uri = ldap_url_desc2str( srv );
+ srv->lud_dn = dn.bv_val;
+ }
}
ldap_free_urldesc( srv );
if ( rc != 0 ) {
lip->li_uri = NULL;
lip->li_bvuri = NULL;
- (void)ldap_chain_db_destroy_one( op->o_bd );
+ (void)ldap_chain_db_destroy_one( op->o_bd, NULL );
goto cleanup;
}
lip->li_uri = NULL;
lip->li_bvuri = NULL;
(void)ldap_chain_db_close_one( op->o_bd );
- (void)ldap_chain_db_destroy_one( op->o_bd );
+ (void)ldap_chain_db_destroy_one( op->o_bd, NULL );
}
further_cleanup:;
slap_callback *sc = op->o_callback,
sc2 = { 0 };
int rc = 0;
- char *text = NULL;
+ const char *text = NULL;
const char *matched;
BerVarray ref;
struct berval ndn = op->o_ndn;
* to send it... */
/* FIXME: what about chaining? */
if ( rc != SLAPD_ABANDON ) {
+ rs->sr_err = rc;
send_ldap_extended( op, rs );
rc = LDAP_SUCCESS;
}
done:;
if ( rc != LDAP_SUCCESS ) {
- (void)ldap_chain_db_destroy_one( ca->be );
+ (void)ldap_chain_db_destroy_one( ca->be, NULL );
ch_free( ca->be );
ca->be = NULL;
}
struct berval bv;
/* FIXME: should not hardcode "olcDatabase" here */
- bv.bv_len = snprintf( lca->ca->msg, sizeof( lca->ca->msg ),
+ bv.bv_len = snprintf( lca->ca->cr_msg, sizeof( lca->ca->cr_msg ),
"olcDatabase={%d}%s", lca->count, lback->bi_type );
- bv.bv_val = lca->ca->msg;
+ bv.bv_val = lca->ca->cr_msg;
lca->ca->be->be_private = (void *)li;
config_build_entry( lca->op, lca->rs, lca->p->e_private, lca->ca,
case CH_MAX_DEPTH:
if ( c->value_int < 0 ) {
- snprintf( c->msg, sizeof( c->msg ),
+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
"<%s> invalid max referral depth %d",
c->argv[0], c->value_int );
Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
- c->log, c->msg, 0 );
+ c->log, c->cr_msg, 0 );
rc = 1;
break;
}
static int
ldap_chain_db_init(
- BackendDB *be )
+ BackendDB *be,
+ ConfigReply *cr )
{
slap_overinst *on = (slap_overinst *)be->bd_info;
ldap_chain_t *lc = NULL;
db.bd_info = lback;
db.be_private = (void *)lc->lc_cfg_li;
- ldap_chain_db_destroy_one( &db );
+ ldap_chain_db_destroy_one( &db, NULL );
lc->lc_cfg_li = NULL;
} else {
lca->be->be_private = (void *)li;
- return lca->func( lca->be );
+ return lca->func( lca->be, NULL );
}
static int
db.bd_info = lback;
db.be_private = lc->lc_common_li;
- rc = func( &db );
+ rc = func( &db, NULL );
if ( rc != 0 ) {
return rc;
static int
ldap_chain_db_open(
- BackendDB *be )
+ BackendDB *be,
+ ConfigReply *cr )
{
slap_overinst *on = (slap_overinst *) be->bd_info;
ldap_chain_t *lc = (ldap_chain_t *)on->on_bi.bi_private;
static int
ldap_chain_db_close(
- BackendDB *be )
+ BackendDB *be,
+ ConfigReply *cr )
{
return ldap_chain_db_func( be, db_close );
}
static int
ldap_chain_db_destroy(
- BackendDB *be )
+ BackendDB *be,
+ ConfigReply *cr )
{
slap_overinst *on = (slap_overinst *) be->bd_info;
ldap_chain_t *lc = (ldap_chain_t *)on->on_bi.bi_private;
be->bd_info = lback;
be->be_private = NULL;
- rc = lback->bi_db_init( be );
+ rc = lback->bi_db_init( be, NULL );
if ( rc != 0 ) {
return rc;
}
be->bd_info = lback;
be->be_private = NULL;
- t = lback->bi_db_init( be );
+ t = lback->bi_db_init( be, NULL );
if ( t != 0 ) {
return t;
}
}
}
- return lback->bi_db_open( be );
+ return lback->bi_db_open( be, NULL );
}
typedef struct ldap_chain_conn_apply_t {
retry:
ctrls = op->o_ctrls;
- rc = ldap_back_proxy_authz_ctrl( &lc->lc_bound_ndn,
- li->li_version, &li->li_idassert, op, rs, &ctrls );
+ rc = ldap_back_controls_add( op, rs, lc, &ctrls );
if ( rc != LDAP_SUCCESS ) {
send_ldap_result( op, rs );
goto cleanup;
retrying &= ~LDAP_BACK_RETRYING;
if ( ldap_back_retry( &lc, op, rs, LDAP_BACK_SENDERR ) ) {
/* if the identity changed, there might be need to re-authz */
- (void)ldap_back_proxy_authz_ctrl_free( op, &ctrls );
+ (void)ldap_back_controls_free( op, rs, &ctrls );
goto retry;
}
}
cleanup:
- (void)ldap_back_proxy_authz_ctrl_free( op, &ctrls );
+ (void)ldap_back_controls_free( op, rs, &ctrls );
if ( lc != NULL ) {
ldap_back_release_conn( li, lc );
LDAP_BACK_CFG_CONNPOOLMAX,
LDAP_BACK_CFG_CANCEL,
LDAP_BACK_CFG_QUARANTINE,
+ LDAP_BACK_CFG_ST_REQUEST,
LDAP_BACK_CFG_REWRITE,
LDAP_BACK_CFG_LAST
"SYNTAX OMsDirectoryString "
"X-ORDERED 'VALUES' )",
NULL, NULL },
- { "rebind-as-user", "NO|yes", 1, 2, 0,
+ { "rebind-as-user", "true|FALSE", 1, 2, 0,
ARG_MAGIC|ARG_ON_OFF|LDAP_BACK_CFG_REBIND,
ldap_back_cf_gen, "( OLcfgDbAt:3.10 "
"NAME 'olcDbRebindAsUser' "
"SYNTAX OMsBoolean "
"SINGLE-VALUE )",
NULL, NULL },
- { "chase-referrals", "YES|no", 2, 2, 0,
+ { "chase-referrals", "true|FALSE", 2, 2, 0,
ARG_MAGIC|ARG_ON_OFF|LDAP_BACK_CFG_CHASE,
ldap_back_cf_gen, "( OLcfgDbAt:3.11 "
"NAME 'olcDbChaseReferrals' "
"SYNTAX OMsBoolean "
"SINGLE-VALUE )",
NULL, NULL },
- { "t-f-support", "NO|yes|discover", 2, 2, 0,
+ { "t-f-support", "true|FALSE|discover", 2, 2, 0,
ARG_MAGIC|LDAP_BACK_CFG_T_F,
ldap_back_cf_gen, "( OLcfgDbAt:3.12 "
"NAME 'olcDbTFSupport' "
"SYNTAX OMsDirectoryString "
"SINGLE-VALUE )",
NULL, NULL },
- { "proxy-whoami", "NO|yes", 1, 2, 0,
+ { "proxy-whoami", "true|FALSE", 1, 2, 0,
ARG_MAGIC|ARG_ON_OFF|LDAP_BACK_CFG_WHOAMI,
ldap_back_cf_gen, "( OLcfgDbAt:3.13 "
"NAME 'olcDbProxyWhoAmI' "
"SYNTAX OMsDirectoryString "
"SINGLE-VALUE )",
NULL, NULL },
- { "idle-timeout", "timeout", 2, 0, 0,
+ { "idle-timeout", "timeout", 2, 2, 0,
ARG_MAGIC|LDAP_BACK_CFG_IDLE_TIMEOUT,
ldap_back_cf_gen, "( OLcfgDbAt:3.15 "
"NAME 'olcDbIdleTimeout' "
"SYNTAX OMsDirectoryString "
"SINGLE-VALUE )",
NULL, NULL },
- { "conn-ttl", "ttl", 2, 0, 0,
+ { "conn-ttl", "ttl", 2, 2, 0,
ARG_MAGIC|LDAP_BACK_CFG_CONN_TTL,
ldap_back_cf_gen, "( OLcfgDbAt:3.16 "
"NAME 'olcDbConnTtl' "
"SYNTAX OMsDirectoryString "
"SINGLE-VALUE )",
NULL, NULL },
- { "network-timeout", "timeout", 2, 0, 0,
+ { "network-timeout", "timeout", 2, 2, 0,
ARG_MAGIC|LDAP_BACK_CFG_NETWORK_TIMEOUT,
ldap_back_cf_gen, "( OLcfgDbAt:3.17 "
"NAME 'olcDbNetworkTimeout' "
"SYNTAX OMsDirectoryString "
"SINGLE-VALUE )",
NULL, NULL },
- { "protocol-version", "version", 2, 0, 0,
+ { "protocol-version", "version", 2, 2, 0,
ARG_MAGIC|ARG_INT|LDAP_BACK_CFG_VERSION,
ldap_back_cf_gen, "( OLcfgDbAt:3.18 "
"NAME 'olcDbProtocolVersion' "
"SYNTAX OMsInteger "
"SINGLE-VALUE )",
NULL, NULL },
- { "single-conn", "TRUE/FALSE", 2, 0, 0,
+ { "single-conn", "true|FALSE", 2, 2, 0,
ARG_MAGIC|ARG_ON_OFF|LDAP_BACK_CFG_SINGLECONN,
ldap_back_cf_gen, "( OLcfgDbAt:3.19 "
"NAME 'olcDbSingleConn' "
"SYNTAX OMsBoolean "
"SINGLE-VALUE )",
NULL, NULL },
- { "cancel", "ABANDON|ignore|exop", 2, 0, 0,
+ { "cancel", "ABANDON|ignore|exop", 2, 2, 0,
ARG_MAGIC|LDAP_BACK_CFG_CANCEL,
ldap_back_cf_gen, "( OLcfgDbAt:3.20 "
"NAME 'olcDbCancel' "
"SYNTAX OMsDirectoryString "
"SINGLE-VALUE )",
NULL, NULL },
- { "quarantine", "retrylist", 2, 0, 0,
+ { "quarantine", "retrylist", 2, 2, 0,
ARG_MAGIC|LDAP_BACK_CFG_QUARANTINE,
ldap_back_cf_gen, "( OLcfgDbAt:3.21 "
"NAME 'olcDbQuarantine' "
"SYNTAX OMsDirectoryString "
"SINGLE-VALUE )",
NULL, NULL },
- { "use-temporary-conn", "TRUE/FALSE", 2, 0, 0,
+ { "use-temporary-conn", "true|FALSE", 2, 2, 0,
ARG_MAGIC|ARG_ON_OFF|LDAP_BACK_CFG_USETEMP,
ldap_back_cf_gen, "( OLcfgDbAt:3.22 "
"NAME 'olcDbUseTemporaryConn' "
"SYNTAX OMsBoolean "
"SINGLE-VALUE )",
NULL, NULL },
- { "conn-pool-max", "<n>", 2, 0, 0,
+ { "conn-pool-max", "<n>", 2, 2, 0,
ARG_MAGIC|ARG_INT|LDAP_BACK_CFG_CONNPOOLMAX,
ldap_back_cf_gen, "( OLcfgDbAt:3.23 "
"NAME 'olcDbConnectionPoolMax' "
"SYNTAX OMsInteger "
"SINGLE-VALUE )",
NULL, NULL },
+#ifdef SLAP_CONTROL_X_SESSION_TRACKING
+ { "session-tracking-request", "true|FALSE", 2, 2, 0,
+ ARG_MAGIC|ARG_ON_OFF|LDAP_BACK_CFG_ST_REQUEST,
+ ldap_back_cf_gen, "( OLcfgDbAt:3.24 "
+ "NAME 'olcDbSessionTrackingRequest' "
+ "DESC 'Add session tracking control to proxied requests' "
+ "SYNTAX OMsBoolean "
+ "SINGLE-VALUE )",
+ NULL, NULL },
+#endif /* SLAP_CONTROL_X_SESSION_TRACKING */
{ "suffixmassage", "[virtual]> <real", 2, 3, 0,
ARG_STRING|ARG_MAGIC|LDAP_BACK_CFG_REWRITE,
ldap_back_cf_gen, NULL, NULL, NULL },
|| strcasecmp( c->argv[ 1 ], "dn.regex:.*" ) == 0 )
{
if ( si->si_authz != NULL ) {
- snprintf( c->msg, sizeof( c->msg ),
+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
"\"idassert-authzFrom <authz>\": "
"\"%s\" conflicts with existing authz rules",
c->argv[ 1 ] );
- Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
return 1;
}
return 0;
} else if ( ( si->si_flags & LDAP_BACK_AUTH_AUTHZ_ALL ) ) {
- snprintf( c->msg, sizeof( c->msg ),
+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
"\"idassert-authzFrom <authz>\": "
"\"<authz>\" conflicts with \"*\"" );
- Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
return 1;
}
ber_str2bv( c->argv[ 1 ], 0, 0, &in );
rc = authzNormalize( 0, NULL, NULL, &in, &bv, NULL );
if ( rc != LDAP_SUCCESS ) {
- snprintf( c->msg, sizeof( c->msg ),
+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
"\"idassert-authzFrom <authz>\": "
"invalid syntax" );
- Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
return 1;
}
j = verb_to_mask( argvi, idassert_mode );
if ( BER_BVISNULL( &idassert_mode[ j ].word ) ) {
- snprintf( c->msg, sizeof( c->msg ),
+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
"\"idassert-bind <args>\": "
"unknown mode \"%s\"",
argvi );
- Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
return 1;
}
if ( strcasecmp( argvi, "native" ) == 0 ) {
if ( si->si_bc.sb_method != LDAP_AUTH_SASL ) {
- snprintf( c->msg, sizeof( c->msg ),
+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
"\"idassert-bind <args>\": "
"authz=\"native\" incompatible "
"with auth method" );
- Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
return 1;
}
si->si_flags |= LDAP_BACK_AUTH_NATIVE_AUTHZ;
si->si_flags &= ~LDAP_BACK_AUTH_NATIVE_AUTHZ;
} else {
- snprintf( c->msg, sizeof( c->msg ),
+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
"\"idassert-bind <args>\": "
"unknown authz \"%s\"",
argvi );
- Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
return 1;
}
int j, err = 0;
if ( flags == NULL ) {
- snprintf( c->msg, sizeof( c->msg ),
+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
"\"idassert-bind <args>\": "
"unable to parse flags \"%s\"",
argvi );
- Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
return 1;
}
}
} else {
- snprintf( c->msg, sizeof( c->msg ),
+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
"\"idassert-bind <args>\": "
"unknown flag \"%s\"",
flags[ j ] );
- Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
err = 1;
break;
}
}
break;
+#ifdef SLAP_CONTROL_X_SESSION_TRACKING
+ case LDAP_BACK_CFG_ST_REQUEST:
+ c->value_int = LDAP_BACK_ST_REQUEST( li );
+ break;
+#endif /* SLAP_CONTROL_X_SESSION_TRACKING */
+
default:
/* FIXME: we need to handle all... */
assert( 0 );
li->li_flags &= ~LDAP_BACK_F_QUARANTINE;
break;
+#ifdef SLAP_CONTROL_X_SESSION_TRACKING
+ case LDAP_BACK_CFG_ST_REQUEST:
+ li->li_flags &= ~LDAP_BACK_F_ST_REQUEST;
+ break;
+#endif /* SLAP_CONTROL_X_SESSION_TRACKING */
+
default:
/* FIXME: we need to handle all... */
assert( 0 );
why = "unknown reason";
break;
}
- snprintf( c->msg, sizeof( c->msg),
+ snprintf( c->cr_msg, sizeof( c->cr_msg),
"unable to parse uri \"%s\" "
"in \"uri <uri>\" line: %s",
c->value_string, why );
- Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
urlrc = 1;
goto done_url;
}
|| tmpludp->lud_filter != NULL
|| tmpludp->lud_exts != NULL )
{
- snprintf( c->msg, sizeof( c->msg ),
+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
"warning, only protocol, "
"host and port allowed "
"in \"uri <uri>\" statement "
"for uri #%d of \"%s\"",
i, c->argv[ 1 ] );
- Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
}
}
urllist[ i ] = ldap_url_desc2str( &tmplud );
if ( urllist[ i ] == NULL ) {
- snprintf( c->msg, sizeof( c->msg),
+ snprintf( c->cr_msg, sizeof( c->cr_msg),
"unable to rebuild uri "
"in \"uri <uri>\" statement "
"for \"%s\"",
c->argv[ 1 ] );
- Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
urlrc = 1;
goto done_url;
}
break;
default:
- snprintf( c->msg, sizeof( c->msg),
+ snprintf( c->cr_msg, sizeof( c->cr_msg),
"\"acl-authcDN <DN>\" incompatible "
"with auth method %d",
li->li_acl_authmethod );
- Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
return 1;
}
if ( !BER_BVISNULL( &li->li_acl_authcDN ) ) {
break;
default:
- snprintf( c->msg, sizeof( c->msg ),
+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
"\"acl-passwd <cred>\" incompatible "
"with auth method %d",
li->li_acl_authmethod );
- Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
return 1;
}
if ( !BER_BVISNULL( &li->li_acl_passwd ) ) {
break;
default:
- snprintf( c->msg, sizeof( c->msg ),
+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
"\"idassert-authcDN <DN>\" incompatible "
"with auth method %d",
li->li_idassert_authmethod );
- Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
return 1;
}
if ( !BER_BVISNULL( &li->li_idassert_authcDN ) ) {
break;
default:
- snprintf( c->msg, sizeof( c->msg ),
+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
"\"idassert-passwd <cred>\" incompatible "
"with auth method %d",
li->li_idassert_authmethod );
- Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
return 1;
}
if ( !BER_BVISNULL( &li->li_idassert_passwd ) ) {
case LDAP_BACK_CFG_IDASSERT_METHOD:
/* no longer supported */
- snprintf( c->msg, sizeof( c->msg ),
+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
"\"idassert-method <args>\": "
"no longer supported; use \"idassert-bind\"" );
- Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
return 1;
case LDAP_BACK_CFG_IDASSERT_BIND:
int rc;
if ( li->li_uri == NULL ) {
- snprintf( c->msg, sizeof( c->msg ),
- "need URI to discover \"cancel\" support "
- "in \"cancel exop-discover\"" );
- Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
+ "need URI to discover absolute filters support "
+ "in \"t-f-support discover\"" );
+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
return 1;
}
unsigned u;
if ( lutil_atoux( &u, c->argv[ i ], 0 ) != 0 ) {
- snprintf( c->msg, sizeof( c->msg),
+ snprintf( c->cr_msg, sizeof( c->cr_msg),
"unable to parse timeout \"%s\"",
c->argv[ i ] );
- Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
return 1;
}
}
if ( slap_cf_aux_table_parse( c->argv[ i ], li->li_timeout, timeout_table, "slapd-ldap timeout" ) ) {
- snprintf( c->msg, sizeof( c->msg),
+ snprintf( c->cr_msg, sizeof( c->cr_msg),
"unable to parse timeout \"%s\"",
c->argv[ i ] );
- Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
return 1;
}
}
unsigned long t;
if ( lutil_parse_time( c->argv[ 1 ], &t ) != 0 ) {
- snprintf( c->msg, sizeof( c->msg),
+ snprintf( c->cr_msg, sizeof( c->cr_msg),
"unable to parse idle timeout \"%s\"",
c->argv[ 1 ] );
- Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
return 1;
}
li->li_idle_timeout = (time_t)t;
unsigned long t;
if ( lutil_parse_time( c->argv[ 1 ], &t ) != 0 ) {
- snprintf( c->msg, sizeof( c->msg),
+ snprintf( c->cr_msg, sizeof( c->cr_msg),
"unable to parse conn ttl\"%s\"",
c->argv[ 1 ] );
- Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
return 1;
}
li->li_conn_ttl = (time_t)t;
unsigned long t;
if ( lutil_parse_time( c->argv[ 1 ], &t ) != 0 ) {
- snprintf( c->msg, sizeof( c->msg),
+ snprintf( c->cr_msg, sizeof( c->cr_msg),
"unable to parse network timeout \"%s\"",
c->argv[ 1 ] );
- Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
return 1;
}
li->li_network_timeout = (time_t)t;
case LDAP_BACK_CFG_VERSION:
if ( c->value_int != 0 && ( c->value_int < LDAP_VERSION_MIN || c->value_int > LDAP_VERSION_MAX ) ) {
- snprintf( c->msg, sizeof( c->msg ),
+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
"unsupported version \"%s\" "
"in \"protocol-version <version>\"",
c->argv[ 1 ] );
- Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
return 1;
}
if ( c->value_int < LDAP_BACK_CONN_PRIV_MIN
|| c->value_int > LDAP_BACK_CONN_PRIV_MAX )
{
- snprintf( c->msg, sizeof( c->msg ),
+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
"invalid max size " "of privileged "
"connections pool \"%s\" "
"in \"conn-pool-max <n> "
c->argv[ 1 ],
LDAP_BACK_CONN_PRIV_MIN,
LDAP_BACK_CONN_PRIV_MAX );
- Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
return 1;
}
li->li_conn_priv_max = c->value_int;
int rc;
if ( li->li_uri == NULL ) {
- snprintf( c->msg, sizeof( c->msg ),
+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
"need URI to discover \"cancel\" support "
"in \"cancel exop-discover\"" );
- Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
return 1;
}
case LDAP_BACK_CFG_QUARANTINE:
if ( LDAP_BACK_QUARANTINE( li ) ) {
- snprintf( c->msg, sizeof( c->msg ),
+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
"quarantine already defined" );
- Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
return 1;
}
rc = slap_retry_info_parse( c->argv[1], &li->li_quarantine,
- c->msg, sizeof( c->msg ) );
+ c->cr_msg, sizeof( c->cr_msg ) );
if ( rc ) {
- Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
} else {
ldap_pvt_thread_mutex_init( &li->li_quarantine_mutex );
}
break;
+#ifdef SLAP_CONTROL_X_SESSION_TRACKING
+ case LDAP_BACK_CFG_ST_REQUEST:
+ if ( c->value_int ) {
+ li->li_flags |= LDAP_BACK_F_ST_REQUEST;
+
+ } else {
+ li->li_flags &= ~LDAP_BACK_F_ST_REQUEST;
+ }
+ break;
+#endif /* SLAP_CONTROL_X_SESSION_TRACKING */
+
case LDAP_BACK_CFG_REWRITE:
- snprintf( c->msg, sizeof( c->msg ),
+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
"rewrite/remap capabilities have been moved "
"to the \"rwm\" overlay; see slapo-rwm(5) "
"for details (hint: add \"overlay rwm\" "
"and prefix all directives with \"rwm-\")" );
- Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
return 1;
default:
retry:
ctrls = op->o_ctrls;
- rc = ldap_back_proxy_authz_ctrl( &lc->lc_bound_ndn,
- li->li_version, &li->li_idassert, op, rs, &ctrls );
+ rc = ldap_back_controls_add( op, rs, lc, &ctrls );
if ( rc != LDAP_SUCCESS ) {
send_ldap_result( op, rs );
rc = rs->sr_err;
retrying &= ~LDAP_BACK_RETRYING;
if ( ldap_back_retry( &lc, op, rs, LDAP_BACK_SENDERR ) ) {
/* if the identity changed, there might be need to re-authz */
- (void)ldap_back_proxy_authz_ctrl_free( op, &ctrls );
+ (void)ldap_back_controls_free( op, rs, &ctrls );
goto retry;
}
}
cleanup:
- (void)ldap_back_proxy_authz_ctrl_free( op, &ctrls );
+ (void)ldap_back_controls_free( op, rs, &ctrls );
if ( lc != NULL ) {
ldap_back_release_conn( li, lc );
static int ldap_distproc_db_init_one( BackendDB *be );
#define ldap_distproc_db_open_one(be) (lback)->bi_db_open( (be) )
#define ldap_distproc_db_close_one(be) (0)
-#define ldap_distproc_db_destroy_one(be) (lback)->bi_db_destroy( (be) )
+#define ldap_distproc_db_destroy_one(be, ca) (lback)->bi_db_destroy( (be), (ca) )
static int
ldap_distproc_parse_ctrl(
done:;
if ( rc != LDAP_SUCCESS ) {
- (void)ldap_distproc_db_destroy_one( ca->be );
+ (void)ldap_distproc_db_destroy_one( ca->be, NULL );
ch_free( ca->be );
ca->be = NULL;
}
struct berval bv;
/* FIXME: should not hardcode "olcDatabase" here */
- bv.bv_len = snprintf( lca->ca->msg, sizeof( lca->ca->msg ),
+ bv.bv_len = snprintf( lca->ca->cr_msg, sizeof( lca->ca->cr_msg ),
"olcDatabase={%d}%s", lca->count, lback->bi_type );
- bv.bv_val = lca->ca->msg;
+ bv.bv_val = lca->ca->cr_msg;
lca->ca->be->be_private = (void *)li;
config_build_entry( lca->op, lca->rs, lca->p->e_private, lca->ca,
static int
ldap_distproc_db_init(
- BackendDB *be )
+ BackendDB *be,
+ ConfigReply *cr )
{
slap_overinst *on = (slap_overinst *)be->bd_info;
ldap_distproc_t *lc = NULL;
db.bd_info = lback;
db.be_private = (void *)lc->lc_cfg_li;
- ldap_distproc_db_destroy_one( &db );
+ ldap_distproc_db_destroy_one( &db, NULL );
lc->lc_cfg_li = NULL;
} else {
lca->be->be_private = (void *)li;
- return lca->func( lca->be );
+ return lca->func( lca->be, NULL );
}
static int
db.bd_info = lback;
db.be_private = lc->lc_common_li;
- rc = func( &db );
+ rc = func( &db, NULL );
if ( rc != 0 ) {
return rc;
static int
ldap_distproc_db_open(
- BackendDB *be )
+ BackendDB *be,
+ ConfigReply *cr )
{
return ldap_distproc_db_func( be, db_open );
}
static int
ldap_distproc_db_close(
- BackendDB *be )
+ BackendDB *be,
+ ConfigReply *cr )
{
return ldap_distproc_db_func( be, db_close );
}
static int
ldap_distproc_db_destroy(
- BackendDB *be )
+ BackendDB *be,
+ ConfigReply *cr )
{
slap_overinst *on = (slap_overinst *) be->bd_info;
ldap_distproc_t *lc = (ldap_distproc_t *)on->on_bi.bi_private;
be->bd_info = lback;
be->be_private = NULL;
- t = lback->bi_db_init( be );
+ t = lback->bi_db_init( be, NULL );
if ( t != 0 ) {
return t;
}
be->bd_info = lback;
be->be_private = NULL;
- t = lback->bi_db_init( be );
+ t = lback->bi_db_init( be, NULL );
if ( t != 0 ) {
return t;
}
#include "back-ldap.h"
#include "lber_pvt.h"
-static BI_op_extended ldap_back_exop_passwd;
-static BI_op_extended ldap_back_exop_generic;
+typedef int (ldap_back_exop_f)( Operation *op, SlapReply *rs, ldapconn_t **lc );
+
+static ldap_back_exop_f ldap_back_exop_passwd;
+static ldap_back_exop_f ldap_back_exop_generic;
static struct exop {
- struct berval oid;
- BI_op_extended *extended;
+ struct berval oid;
+ ldap_back_exop_f *extended;
} exop_table[] = {
{ BER_BVC(LDAP_EXOP_MODIFY_PASSWD), ldap_back_exop_passwd },
{ BER_BVNULL, NULL }
};
static int
-ldap_back_extended_one( Operation *op, SlapReply *rs, BI_op_extended exop )
+ldap_back_extended_one( Operation *op, SlapReply *rs, ldap_back_exop_f exop )
{
ldapinfo_t *li = (ldapinfo_t *) op->o_bd->be_private;
ldapconn_t *lc = NULL;
- LDAPControl **oldctrls = NULL;
+ LDAPControl **ctrls = NULL, **oldctrls = NULL;
int rc;
/* FIXME: this needs to be called here, so it is
return -1;
}
- oldctrls = op->o_ctrls;
- if ( ldap_back_proxy_authz_ctrl( &lc->lc_bound_ndn,
- li->li_version, &li->li_idassert, op, rs, &op->o_ctrls ) )
+ ctrls = op->o_ctrls;
+ if ( ldap_back_controls_add( op, rs, lc, &ctrls ) )
{
op->o_ctrls = oldctrls;
send_ldap_extended( op, rs );
goto done;
}
- rc = exop( op, rs );
+ op->o_ctrls = ctrls;
+ rc = exop( op, rs, &lc );
- if ( op->o_ctrls && op->o_ctrls != oldctrls ) {
- free( op->o_ctrls[ 0 ] );
- free( op->o_ctrls );
- }
op->o_ctrls = oldctrls;
+ (void)ldap_back_controls_free( op, rs, &ctrls );
done:;
if ( lc != NULL ) {
static int
ldap_back_exop_passwd(
- Operation *op,
- SlapReply *rs )
+ Operation *op,
+ SlapReply *rs,
+ ldapconn_t **lcp )
{
ldapinfo_t *li = (ldapinfo_t *) op->o_bd->be_private;
- ldapconn_t *lc = NULL;
+ ldapconn_t *lc = *lcp;
req_pwdexop_s *qpw = &op->oq_pwdexop;
LDAPMessage *res;
ber_int_t msgid;
- int rc, isproxy;
+ int rc, isproxy, freedn = 0;
int do_retry = 1;
- char *text = NULL;
+ char *text = NULL;
+ struct berval dn = op->o_req_dn,
+ ndn = op->o_req_ndn;
+
+ assert( lc != NULL );
+ assert( rs->sr_ctrls == NULL );
+
+ if ( BER_BVISNULL( &ndn ) && op->ore_reqdata != NULL ) {
+ /* NOTE: most of this code is mutuated
+ * from slap_passwd_parse(); we can't call
+ * that function since now the request data
+ * has been destroyed by NULL-terminating
+ * the bervals. Luckily enough, we only need
+ * the first berval... */
+
+ ber_tag_t tag;
+ ber_len_t len = -1;
+ BerElementBuffer berbuf;
+ BerElement *ber = (BerElement *)&berbuf;
+
+ struct berval tmpid = BER_BVNULL;
+
+ if ( op->ore_reqdata->bv_len == 0 ) {
+ return LDAP_PROTOCOL_ERROR;
+ }
- if ( !ldap_back_dobind( &lc, op, rs, LDAP_BACK_SENDERR ) ) {
- return -1;
+ /* ber_init2 uses reqdata directly, doesn't allocate new buffers */
+ ber_init2( ber, op->ore_reqdata, 0 );
+
+ tag = ber_scanf( ber, "{" /*}*/ );
+
+ if ( tag == LBER_ERROR ) {
+ return LDAP_PROTOCOL_ERROR;
+ }
+
+ tag = ber_peek_tag( ber, &len );
+ if ( tag == LDAP_TAG_EXOP_MODIFY_PASSWD_ID ) {
+ tag = ber_scanf( ber, "m", &tmpid );
+
+ if ( tag == LBER_ERROR ) {
+ return LDAP_PROTOCOL_ERROR;
+ }
+ }
+
+ if ( !BER_BVISEMPTY( &tmpid ) ) {
+ rs->sr_err = dnPrettyNormal( NULL, &tmpid, &dn,
+ &ndn, op->o_tmpmemctx );
+ if ( rs->sr_err != LDAP_SUCCESS ) {
+ /* should have been successfully parsed earlier! */
+ return rs->sr_err;
+ }
+ freedn = 1;
+
+ } else {
+ dn = op->o_dn;
+ ndn = op->o_ndn;
+ }
}
- isproxy = ber_bvcmp( &op->o_req_ndn, &op->o_ndn );
+ isproxy = ber_bvcmp( &ndn, &op->o_ndn );
Debug( LDAP_DEBUG_ARGS, "==> ldap_back_exop_passwd(\"%s\")%s\n",
- op->o_req_dn.bv_val, isproxy ? " (proxy)" : "", 0 );
+ dn.bv_val, isproxy ? " (proxy)" : "", 0 );
retry:
- rc = ldap_passwd( lc->lc_ld, isproxy ? &op->o_req_dn : NULL,
+ rc = ldap_passwd( lc->lc_ld, isproxy ? &dn : NULL,
qpw->rs_old.bv_val ? &qpw->rs_old : NULL,
qpw->rs_new.bv_val ? &qpw->rs_new : NULL,
op->o_ctrls, NULL, &msgid );
if ( rc == LDAP_SUCCESS ) {
+ /* TODO: set timeout? */
if ( ldap_result( lc->lc_ld, msgid, LDAP_MSG_ALL, NULL, &res ) == -1 ) {
ldap_get_option( lc->lc_ld, LDAP_OPT_ERROR_NUMBER, &rc );
rs->sr_err = rc;
rc = ldap_parse_result( lc->lc_ld, res, &rs->sr_err,
(char **)&rs->sr_matched,
&text,
- NULL, NULL, 0 );
+ NULL, &rs->sr_ctrls, 0 );
if ( rc == LDAP_SUCCESS ) {
if ( rs->sr_err == LDAP_SUCCESS ) {
ldap_back_quarantine( op, rs );
}
+ if ( freedn ) {
+ op->o_tmpfree( dn.bv_val, op->o_tmpmemctx );
+ op->o_tmpfree( ndn.bv_val, op->o_tmpmemctx );
+ }
+
/* these have to be freed anyway... */
if ( rs->sr_matched ) {
free( (char *)rs->sr_matched );
rs->sr_matched = NULL;
}
+ if ( rs->sr_ctrls ) {
+ ldap_controls_free( rs->sr_ctrls );
+ rs->sr_ctrls = NULL;
+ }
+
if ( text ) {
free( text );
rs->sr_text = NULL;
}
- if ( lc != NULL ) {
- ldap_back_release_conn( li, lc );
+ /* in case, cleanup handler */
+ if ( lc == NULL ) {
+ *lcp = NULL;
}
return rc;
static int
ldap_back_exop_generic(
Operation *op,
- SlapReply *rs )
+ SlapReply *rs,
+ ldapconn_t **lcp )
{
ldapinfo_t *li = (ldapinfo_t *) op->o_bd->be_private;
- ldapconn_t *lc = NULL;
+ ldapconn_t *lc = *lcp;
LDAPMessage *res;
ber_int_t msgid;
int rc;
int do_retry = 1;
- char *text = NULL;
+ char *text = NULL;
- if ( !ldap_back_dobind( &lc, op, rs, LDAP_BACK_SENDERR ) ) {
- return -1;
- }
+ assert( lc != NULL );
+ assert( rs->sr_ctrls == NULL );
Debug( LDAP_DEBUG_ARGS, "==> ldap_back_exop_generic(%s, \"%s\")\n",
op->ore_reqoid.bv_val, op->o_req_dn.bv_val, 0 );
op->o_ctrls, NULL, &msgid );
if ( rc == LDAP_SUCCESS ) {
+ /* TODO: set timeout? */
if ( ldap_result( lc->lc_ld, msgid, LDAP_MSG_ALL, NULL, &res ) == -1 ) {
ldap_get_option( lc->lc_ld, LDAP_OPT_ERROR_NUMBER, &rc );
rs->sr_err = rc;
rc = ldap_parse_result( lc->lc_ld, res, &rs->sr_err,
(char **)&rs->sr_matched,
&text,
- NULL, NULL, 0 );
+ NULL, &rs->sr_ctrls, 0 );
if ( rc == LDAP_SUCCESS ) {
if ( rs->sr_err == LDAP_SUCCESS ) {
rc = ldap_parse_extended_result( lc->lc_ld, res,
rs->sr_matched = NULL;
}
+ if ( rs->sr_ctrls ) {
+ ldap_controls_free( rs->sr_ctrls );
+ rs->sr_ctrls = NULL;
+ }
+
if ( text ) {
free( text );
rs->sr_text = NULL;
}
- if ( lc != NULL ) {
- ldap_back_release_conn( li, lc );
+ /* in case, cleanup handler */
+ if ( lc == NULL ) {
+ *lcp = NULL;
}
return rc;
#include <ac/socket.h>
#include "slap.h"
+#include "config.h"
#include "back-ldap.h"
int
}
int
-ldap_back_db_init( Backend *be )
+ldap_back_db_init( Backend *be, ConfigReply *cr )
{
ldapinfo_t *li;
int rc;
}
int
-ldap_back_db_open( BackendDB *be )
+ldap_back_db_open( BackendDB *be, ConfigReply *cr )
{
ldapinfo_t *li = (ldapinfo_t *)be->be_private;
}
int
-ldap_back_db_close( Backend *be )
+ldap_back_db_close( Backend *be, ConfigReply *cr )
{
int rc = 0;
}
int
-ldap_back_db_destroy( Backend *be )
+ldap_back_db_destroy( Backend *be, ConfigReply *cr )
{
if ( be->be_private ) {
ldapinfo_t *li = ( ldapinfo_t * )be->be_private;
return rs->sr_err;
}
- for ( i = 0, ml = op->oq_modify.rs_modlist; ml; i++, ml = ml->sml_next )
+ for ( i = 0, ml = op->orm_modlist; ml; i++, ml = ml->sml_next )
/* just count mods */ ;
modv = (LDAPMod **)ch_malloc( ( i + 1 )*sizeof( LDAPMod * )
mods = (LDAPMod *)&modv[ i + 1 ];
isupdate = be_shadow_update( op );
- for ( i = 0, ml = op->oq_modify.rs_modlist; ml; ml = ml->sml_next ) {
+ for ( i = 0, ml = op->orm_modlist; ml; ml = ml->sml_next ) {
if ( !isupdate && !get_relax( op ) && ml->sml_desc->ad_type->sat_no_user_mod )
{
continue;
retry:;
ctrls = op->o_ctrls;
- rc = ldap_back_proxy_authz_ctrl( &lc->lc_bound_ndn,
- li->li_version, &li->li_idassert, op, rs, &ctrls );
+ rc = ldap_back_controls_add( op, rs, lc, &ctrls );
if ( rc != LDAP_SUCCESS ) {
send_ldap_result( op, rs );
rc = -1;
retrying &= ~LDAP_BACK_RETRYING;
if ( ldap_back_retry( &lc, op, rs, LDAP_BACK_SENDERR ) ) {
/* if the identity changed, there might be need to re-authz */
- (void)ldap_back_proxy_authz_ctrl_free( op, &ctrls );
+ (void)ldap_back_controls_free( op, rs, &ctrls );
goto retry;
}
}
cleanup:;
- (void)ldap_back_proxy_authz_ctrl_free( op, &ctrls );
+ (void)ldap_back_controls_free( op, rs, &ctrls );
for ( i = 0; modv[ i ]; i++ ) {
ch_free( modv[ i ]->mod_bvalues );
retry:
ctrls = op->o_ctrls;
- rc = ldap_back_proxy_authz_ctrl( &lc->lc_bound_ndn,
- li->li_version, &li->li_idassert, op, rs, &ctrls );
+ rc = ldap_back_controls_add( op, rs, lc, &ctrls );
if ( rc != LDAP_SUCCESS ) {
send_ldap_result( op, rs );
rc = -1;
retrying &= ~LDAP_BACK_RETRYING;
if ( ldap_back_retry( &lc, op, rs, LDAP_BACK_SENDERR ) ) {
/* if the identity changed, there might be need to re-authz */
- (void)ldap_back_proxy_authz_ctrl_free( op, &ctrls );
+ (void)ldap_back_controls_free( op, rs, &ctrls );
goto retry;
}
}
cleanup:
- (void)ldap_back_proxy_authz_ctrl_free( op, &ctrls );
+ (void)ldap_back_controls_free( op, rs, &ctrls );
if ( lc != NULL ) {
ldap_back_release_conn( li, lc );
extern ldapconn_t * ldap_back_conn_delete( ldapinfo_t *li, ldapconn_t *lc );
+#if 0
extern int
ldap_back_proxy_authz_ctrl(
struct berval *bound_ndn,
ldap_back_proxy_authz_ctrl_free(
Operation *op,
LDAPControl ***pctrls );
+#endif
+
+extern int
+ldap_back_proxy_authz_ctrl(
+ Operation *op,
+ SlapReply *rs,
+ struct berval *bound_ndn,
+ int version,
+ slap_idassert_t *si,
+ LDAPControl *ctrl );
+
+extern int
+ldap_back_controls_add(
+ Operation *op,
+ SlapReply *rs,
+ ldapconn_t *lc,
+ LDAPControl ***pctrls );
+
+extern int
+ldap_back_controls_free( Operation *op, SlapReply *rs, LDAPControl ***pctrls );
extern void
ldap_back_quarantine(
int freetext = 0;
int do_retry = 1, dont_retry = 0;
LDAPControl **ctrls = NULL;
+ char **references = NULL;
+
/* FIXME: shouldn't this be null? */
const char *save_matched = rs->sr_matched;
}
ctrls = op->o_ctrls;
- rc = ldap_back_proxy_authz_ctrl( &lc->lc_bound_ndn,
- li->li_version, &li->li_idassert, op, rs, &ctrls );
+ rc = ldap_back_controls_add( op, rs, lc, &ctrls );
if ( rc != LDAP_SUCCESS ) {
goto finish;
}
e = ldap_first_entry( lc->lc_ld, res );
rc = ldap_build_entry( op, e, &ent, &bdn );
if ( rc == LDAP_SUCCESS ) {
+ ldap_get_entry_controls( lc->lc_ld, res, &rs->sr_ctrls );
rs->sr_entry = &ent;
rs->sr_attrs = op->ors_attrs;
rs->sr_operational_attrs = NULL;
rs->sr_flags = 0;
rs->sr_err = LDAP_SUCCESS;
rc = rs->sr_err = send_search_entry( op, rs );
+ if ( rs->sr_ctrls ) {
+ ldap_controls_free( rs->sr_ctrls );
+ rs->sr_ctrls = NULL;
+ }
+ rs->sr_entry = NULL;
if ( !BER_BVISNULL( &ent.e_name ) ) {
assert( ent.e_name.bv_val != bdn.bv_val );
op->o_tmpfree( ent.e_name.bv_val, op->o_tmpmemctx );
}
} else if ( rc == LDAP_RES_SEARCH_REFERENCE ) {
- char **references = NULL;
-
do_retry = 0;
rc = ldap_parse_reference( lc->lc_ld, res,
&references, &rs->sr_ctrls, 1 );
BER_BVZERO( &rs->sr_ref[ cnt ] );
/* ignore return value by now */
+ rs->sr_entry = NULL;
( void )send_search_reference( op, rs );
} else {
ber_memvfree( (void **)references );
op->o_tmpfree( rs->sr_ref, op->o_tmpmemctx );
rs->sr_ref = NULL;
+ references = NULL;
}
if ( rs->sr_ctrls ) {
}
} else {
- char **references = NULL, *err = NULL;
+ char *err = NULL;
rc = ldap_parse_result( lc->lc_ld, res, &rs->sr_err,
&match.bv_val, &err,
freetext = 1;
}
- if ( references && references[ 0 ] && references[ 0 ][ 0 ] ) {
- int cnt;
-
+ /* RFC 4511: referrals can only appear
+ * if result code is LDAP_REFERRAL */
+ if ( references
+ && references[ 0 ]
+ && references[ 0 ][ 0 ] )
+ {
if ( rs->sr_err != LDAP_REFERRAL ) {
- /* FIXME: error */
Debug( LDAP_DEBUG_ANY,
"%s ldap_back_search: "
- "got referrals with %d\n",
+ "got referrals with err=%d\n",
op->o_log_prefix,
rs->sr_err, 0 );
- rs->sr_err = LDAP_REFERRAL;
- }
- for ( cnt = 0; references[ cnt ]; cnt++ )
- /* NO OP */ ;
+ } else {
+ int cnt;
+
+ for ( cnt = 0; references[ cnt ]; cnt++ )
+ /* NO OP */ ;
- rs->sr_ref = op->o_tmpalloc( ( cnt + 1 ) * sizeof( struct berval ),
- op->o_tmpmemctx );
+ rs->sr_ref = op->o_tmpalloc( ( cnt + 1 ) * sizeof( struct berval ),
+ op->o_tmpmemctx );
- for ( cnt = 0; references[ cnt ]; cnt++ ) {
- /* duplicating ...*/
- ber_str2bv( references[ cnt ], 0, 1, &rs->sr_ref[ cnt ] );
+ for ( cnt = 0; references[ cnt ]; cnt++ ) {
+ /* duplicating ...*/
+ ber_str2bv( references[ cnt ], 0, 0, &rs->sr_ref[ cnt ] );
+ }
+ BER_BVZERO( &rs->sr_ref[ cnt ] );
}
- BER_BVZERO( &rs->sr_ref[ cnt ] );
+
+ } else if ( rs->sr_err == LDAP_REFERRAL ) {
+ Debug( LDAP_DEBUG_ANY,
+ "%s ldap_back_search: "
+ "got err=%d with null "
+ "or empty referrals\n",
+ op->o_log_prefix,
+ rs->sr_err, 0 );
+
+ rs->sr_err = LDAP_NO_SUCH_OBJECT;
}
if ( match.bv_val != NULL ) {
match.bv_len = strlen( match.bv_val );
}
- /* cleanup */
- if ( references ) {
- ber_memvfree( (void **)references );
- }
-
rc = 0;
break;
}
send_ldap_result( op, rs );
}
- (void)ldap_back_proxy_authz_ctrl_free( op, &ctrls );
+ (void)ldap_back_controls_free( op, rs, &ctrls );
if ( rs->sr_ctrls ) {
ldap_controls_free( rs->sr_ctrls );
}
if ( rs->sr_ref ) {
- ber_bvarray_free_x( rs->sr_ref, op->o_tmpmemctx );
+ op->o_tmpfree( rs->sr_ref, op->o_tmpmemctx );
rs->sr_ref = NULL;
}
+ if ( references ) {
+ ber_memvfree( (void **)references );
+ }
+
if ( attrs ) {
ch_free( attrs );
}
retry:
ctrls = op->o_ctrls;
- rc = ldap_back_proxy_authz_ctrl( &lc->lc_bound_ndn,
- li->li_version, &li->li_idassert, op, &rs, &ctrls );
+ rc = ldap_back_controls_add( op, &rs, lc, &ctrls );
if ( rc != LDAP_SUCCESS ) {
goto cleanup;
}
do_retry = 0;
if ( ldap_back_retry( &lc, op, &rs, LDAP_BACK_DONTSEND ) ) {
/* if the identity changed, there might be need to re-authz */
- (void)ldap_back_proxy_authz_ctrl_free( op, &ctrls );
+ (void)ldap_back_controls_free( op, &rs, &ctrls );
goto retry;
}
}
}
cleanup:
- (void)ldap_back_proxy_authz_ctrl_free( op, &ctrls );
+ (void)ldap_back_controls_free( op, &rs, &ctrls );
if ( result ) {
ldap_msgfree( result );
struct berval *res)
{
char *ptr, *sep, *end;
- struct berval bv;
assert( dn != NULL );
assert( !BER_BVISNULL( dn ) );
}
strcpy(ptr, LDIF);
#if IX_FSL != IX_DNL
- bv = *res;
- while ( ptr = ber_bvchr( &bv, IX_DNL ) ) {
- *ptr++ = IX_FSL;
- assert( ( ptr - bv.bv_val ) <= bv.bv_len );
- bv.bv_len -= ( ptr - bv.bv_val );
- bv.bv_val = ptr;
- ptr = ber_bvchr( &bv, IX_DNR );
- if ( !ptr )
- break;
- *ptr++ = IX_FSR;
- assert( ( ptr - bv.bv_val ) <= bv.bv_len );
- bv.bv_len -= ( ptr - bv.bv_val );
- bv.bv_val = ptr;
+ {
+ struct berval bv;
+ bv = *res;
+ while ( ptr = ber_bvchr( &bv, IX_DNL ) ) {
+ *ptr++ = IX_FSL;
+ assert( ( ptr - bv.bv_val ) <= bv.bv_len );
+ bv.bv_len -= ( ptr - bv.bv_val );
+ bv.bv_val = ptr;
+ ptr = ber_bvchr( &bv, IX_DNR );
+ if ( !ptr )
+ break;
+ *ptr++ = IX_FSR;
+ assert( ( ptr - bv.bv_val ) <= bv.bv_len );
+ bv.bv_len -= ( ptr - bv.bv_val );
+ bv.bv_val = ptr;
+ }
}
#endif
}
return entry;
}
+/*
+ * return number of bytes written, or -1 in case of error
+ * do not return numbers less than -1
+ */
static int spew_file(int fd, char * spew, int len) {
int writeres = 0;
while(len > 0) {
writeres = write(fd, spew, len);
if(writeres == -1) {
- Debug( LDAP_DEBUG_ANY, "could not spew write: %s\n",
- STRERROR( errno ), 0, 0 );
return -1;
}
else {
return writeres;
}
-static int spew_entry(Entry * e, struct berval * path) {
- int rs;
+static int
+spew_entry( Entry * e, struct berval * path, int dolock, int *save_errnop )
+{
+ int rs, save_errno = 0;
int openres;
- int spew_res;
+ int res, spew_res;
int entry_length;
char * entry_as_string;
+ char *tmpfname = NULL;
- openres = open(path->bv_val, O_WRONLY|O_CREAT|O_TRUNC, S_IREAD | S_IWRITE);
- if(openres == -1) {
- if(errno == ENOENT)
- rs = LDAP_NO_SUCH_OBJECT;
- else
- rs = LDAP_UNWILLING_TO_PERFORM;
- Debug( LDAP_DEBUG_ANY, "could not open \"%s\": %s\n",
- path->bv_val, STRERROR( errno ), 0 );
- }
- else {
+ tmpfname = ch_malloc( path->bv_len + STRLENOF( "XXXXXX" ) + 1 );
+ AC_MEMCPY( tmpfname, path->bv_val, path->bv_len );
+ AC_MEMCPY( &tmpfname[ path->bv_len ], "XXXXXX", STRLENOF( "XXXXXX" ) + 1 );
+
+ openres = mkstemp( tmpfname );
+ if ( openres == -1 ) {
+ save_errno = errno;
+ rs = LDAP_UNWILLING_TO_PERFORM;
+ Debug( LDAP_DEBUG_ANY, "could not create tmpfile \"%s\": %s\n",
+ tmpfname, STRERROR( save_errno ), 0 );
+
+ } else {
struct berval rdn;
int tmp;
rdn.bv_len = tmp;
}
+ spew_res = -2;
+ if ( dolock ) {
+ ldap_pvt_thread_mutex_lock(&entry2str_mutex);
+ }
+
entry_as_string = entry2str(e, &entry_length);
+ if ( entry_as_string != NULL ) {
+ spew_res = spew_file( openres,
+ entry_as_string, entry_length );
+ if ( spew_res == -1 ) {
+ save_errno = errno;
+ }
+ }
+
+ if ( dolock ) {
+ ldap_pvt_thread_mutex_unlock(&entry2str_mutex);
+ }
/* Restore full DN */
if ( rdn.bv_len != e->e_name.bv_len ) {
e->e_name.bv_len = rdn.bv_len;
}
- if(entry_as_string == NULL) {
- rs = LDAP_UNWILLING_TO_PERFORM;
- close(openres);
+ res = close( openres );
+ rs = LDAP_UNWILLING_TO_PERFORM;
+
+ if ( spew_res > -2 ) {
+ if ( res == -1 || spew_res == -1 ) {
+ if ( save_errno == 0 ) {
+ save_errno = errno;
+ }
+ Debug( LDAP_DEBUG_ANY, "write error to tmpfile \"%s\": %s\n",
+ tmpfname, STRERROR( save_errno ), 0 );
+
+ } else {
+ res = rename( tmpfname, path->bv_val );
+ if ( res == 0 ) {
+ rs = LDAP_SUCCESS;
+
+ } else {
+ save_errno = errno;
+ switch ( save_errno ) {
+ case ENOENT:
+ rs = LDAP_NO_SUCH_OBJECT;
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
}
- else {
- spew_res = spew_file(openres, entry_as_string, entry_length);
- close(openres);
- if(spew_res == -1)
- rs = LDAP_UNWILLING_TO_PERFORM;
- else
- rs = LDAP_SUCCESS;
+
+ if ( rs != LDAP_SUCCESS ) {
+ unlink( tmpfname );
}
}
+
+ ch_free( tmpfname );
+
+ if ( rs != LDAP_SUCCESS && save_errnop != NULL ) {
+ *save_errnop = save_errno;
+ }
+
return rs;
}
struct bvlist *next;
struct berval bv;
struct berval num;
- unsigned int inum;
+ int inum;
int off;
} bvlist;
enumCookie *ck
)
{
- struct ldif_info *ni = (struct ldif_info *) ck->op->o_bd->be_private;
+ struct ldif_info *li = (struct ldif_info *) ck->op->o_bd->be_private;
struct berval path;
struct berval pdn, pndn;
int rc;
dnParent( &ck->op->o_req_dn, &pdn );
dnParent( &ck->op->o_req_ndn, &pndn );
- dn2path( &ck->op->o_req_ndn, &ck->op->o_bd->be_nsuffix[0], &ni->li_base_path, &path);
+ dn2path( &ck->op->o_req_ndn, &ck->op->o_bd->be_nsuffix[0], &li->li_base_path, &path);
rc = r_enum_tree(ck, &path, &pdn, &pndn);
ch_free( path.bv_val );
return rc;
int
ldif_back_referrals( Operation *op, SlapReply *rs )
{
- struct ldif_info *ni = NULL;
+ struct ldif_info *li = NULL;
Entry *entry;
int rc = LDAP_SUCCESS;
return rc;
}
- ni = (struct ldif_info *)op->o_bd->be_private;
- ldap_pvt_thread_rdwr_rlock( &ni->li_rdwr );
- entry = (Entry *)get_entry( op, &ni->li_base_path );
+ li = (struct ldif_info *)op->o_bd->be_private;
+ ldap_pvt_thread_rdwr_rlock( &li->li_rdwr );
+ entry = get_entry( op, &li->li_base_path );
/* no object is found for them */
if ( entry == NULL ) {
op->o_req_dn = pndn;
op->o_req_ndn = pndn;
- entry = (Entry *)get_entry( op, &ni->li_base_path );
+ entry = get_entry( op, &li->li_base_path );
}
- ldap_pvt_thread_rdwr_runlock( &ni->li_rdwr );
+ ldap_pvt_thread_rdwr_runlock( &li->li_rdwr );
op->o_req_dn = odn;
op->o_req_ndn = ondn;
rs->sr_matched = NULL;
if ( entry != NULL ) {
Debug( LDAP_DEBUG_TRACE,
- "ldif_back_referrals: op=%ld target=\"%s\" matched=\"%s\"\n",
- (long) op->o_tag, op->o_req_dn.bv_val, entry->e_name.bv_val );
+ "ldif_back_referrals: tag=%lu target=\"%s\" matched=\"%s\"\n",
+ (unsigned long) op->o_tag, op->o_req_dn.bv_val, entry->e_name.bv_val );
if ( is_entry_referral( entry ) ) {
rc = LDAP_OTHER;
return rc;
}
- ldap_pvt_thread_rdwr_runlock( &ni->li_rdwr );
+ ldap_pvt_thread_rdwr_runlock( &li->li_rdwr );
if ( is_entry_referral( entry ) ) {
/* entry is a referral */
refs, &entry->e_name, &op->o_req_dn, LDAP_SCOPE_DEFAULT );
Debug( LDAP_DEBUG_TRACE,
- "ldif_back_referrals: op=%ld target=\"%s\" matched=\"%s\"\n",
- (long) op->o_tag, op->o_req_dn.bv_val, entry->e_name.bv_val );
+ "ldif_back_referrals: tag=%lu target=\"%s\" matched=\"%s\"\n",
+ (unsigned long) op->o_tag, op->o_req_dn.bv_val, entry->e_name.bv_val );
rs->sr_matched = entry->e_name.bv_val;
if ( rs->sr_ref != NULL ) {
static int
ldif_back_bind( Operation *op, SlapReply *rs )
{
- struct ldif_info *ni = NULL;
+ struct ldif_info *li = NULL;
Attribute * a = NULL;
AttributeDescription *password = slap_schema.si_ad_userPassword;
int return_val = 0;
Entry * entry = NULL;
- ni = (struct ldif_info *) op->o_bd->be_private;
- ldap_pvt_thread_rdwr_rlock(&ni->li_rdwr);
- entry = (Entry *) get_entry(op, &ni->li_base_path);
+ switch ( be_rootdn_bind( op, rs ) ) {
+ case SLAP_CB_CONTINUE:
+ break;
+
+ default:
+ /* in case of success, front end will send result;
+ * otherwise, be_rootdn_bind() did */
+ return rs->sr_err;
+ }
+
+ li = (struct ldif_info *) op->o_bd->be_private;
+ ldap_pvt_thread_rdwr_rlock(&li->li_rdwr);
+ entry = get_entry(op, &li->li_base_path);
/* no object is found for them */
if(entry == NULL) {
- if(be_isroot_pw(op)) {
- rs->sr_err = return_val = LDAP_SUCCESS;
- } else {
- rs->sr_err = return_val = LDAP_INVALID_CREDENTIALS;
- }
+ rs->sr_err = return_val = LDAP_INVALID_CREDENTIALS;
goto return_result;
}
goto return_result;
return_result:
- ldap_pvt_thread_rdwr_runlock(&ni->li_rdwr);
+ ldap_pvt_thread_rdwr_runlock(&li->li_rdwr);
if(return_val != 0)
send_ldap_result( op, rs );
if(entry != NULL)
static int ldif_back_search(Operation *op, SlapReply *rs)
{
- struct ldif_info *ni = (struct ldif_info *) op->o_bd->be_private;
+ struct ldif_info *li = (struct ldif_info *) op->o_bd->be_private;
enumCookie ck = { NULL, NULL, NULL, 0, 0 };
ck.op = op;
ck.rs = rs;
- ldap_pvt_thread_rdwr_rlock(&ni->li_rdwr);
+ ldap_pvt_thread_rdwr_rlock(&li->li_rdwr);
rs->sr_err = enum_tree( &ck );
- ldap_pvt_thread_rdwr_runlock(&ni->li_rdwr);
+ ldap_pvt_thread_rdwr_runlock(&li->li_rdwr);
send_ldap_result(op, rs);
return rs->sr_err;
}
static int ldif_back_add(Operation *op, SlapReply *rs) {
- struct ldif_info *ni = (struct ldif_info *) op->o_bd->be_private;
+ struct ldif_info *li = (struct ldif_info *) op->o_bd->be_private;
Entry * e = op->ora_e;
struct berval dn = e->e_nname;
struct berval leaf_path = BER_BVNULL;
&rs->sr_text, textbuf, sizeof( textbuf ), 1 );
if ( rs->sr_err != LDAP_SUCCESS ) goto send_res;
- ldap_pvt_thread_rdwr_wlock(&ni->li_rdwr);
+ ldap_pvt_thread_rdwr_wlock(&li->li_rdwr);
- dn2path(&dn, &op->o_bd->be_nsuffix[0], &ni->li_base_path, &leaf_path);
+ dn2path(&dn, &op->o_bd->be_nsuffix[0], &li->li_base_path, &leaf_path);
if(leaf_path.bv_val != NULL) {
struct berval base = BER_BVNULL;
if(rs->sr_err == LDAP_SUCCESS) {
statres = stat(leaf_path.bv_val, &stats);
if(statres == -1 && errno == ENOENT) {
- ldap_pvt_thread_mutex_lock(&entry2str_mutex);
- rs->sr_err = (int) spew_entry(e, &leaf_path);
- ldap_pvt_thread_mutex_unlock(&entry2str_mutex);
+ rs->sr_err = spew_entry(e, &leaf_path, 1, NULL);
}
else if ( statres == -1 ) {
rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
SLAP_FREE(leaf_path.bv_val);
}
- ldap_pvt_thread_rdwr_wunlock(&ni->li_rdwr);
+ ldap_pvt_thread_rdwr_wunlock(&li->li_rdwr);
send_res:
Debug( LDAP_DEBUG_TRACE,
rs->sr_text : "", 0);
send_ldap_result(op, rs);
slap_graduate_commit_csn( op );
- return 0;
+ return rs->sr_err;
}
static int ldif_back_modify(Operation *op, SlapReply *rs) {
- struct ldif_info *ni = (struct ldif_info *) op->o_bd->be_private;
+ struct ldif_info *li = (struct ldif_info *) op->o_bd->be_private;
Modifications * modlst = op->orm_modlist;
struct berval path = BER_BVNULL;
Entry * entry = NULL;
slap_mods_opattrs( op, &op->orm_modlist, 1 );
- ldap_pvt_thread_rdwr_wlock(&ni->li_rdwr);
- dn2path(&op->o_req_ndn, &op->o_bd->be_nsuffix[0], &ni->li_base_path,
+ ldap_pvt_thread_rdwr_wlock(&li->li_rdwr);
+ dn2path(&op->o_req_ndn, &op->o_bd->be_nsuffix[0], &li->li_base_path,
&path);
- entry = (Entry *) get_entry(op, &ni->li_base_path);
+ entry = get_entry(op, &li->li_base_path);
if(entry != NULL) {
rs->sr_err = apply_modify_to_entry(entry, modlst, op, rs);
if(rs->sr_err == LDAP_SUCCESS) {
int save_errno;
- ldap_pvt_thread_mutex_lock(&entry2str_mutex);
- spew_res = spew_entry(entry, &path);
- save_errno = errno;
- ldap_pvt_thread_mutex_unlock(&entry2str_mutex);
+ spew_res = spew_entry(entry, &path, 1, &save_errno);
if(spew_res == -1) {
Debug( LDAP_DEBUG_ANY,
"%s ldif_back_modify: could not output entry \"%s\": %s\n",
if(path.bv_val != NULL)
SLAP_FREE(path.bv_val);
rs->sr_text = NULL;
- ldap_pvt_thread_rdwr_wunlock(&ni->li_rdwr);
+ ldap_pvt_thread_rdwr_wunlock(&li->li_rdwr);
send_ldap_result(op, rs);
slap_graduate_commit_csn( op );
- return 0;
+ return rs->sr_err;
}
static int ldif_back_delete(Operation *op, SlapReply *rs) {
- struct ldif_info *ni = (struct ldif_info *) op->o_bd->be_private;
+ struct ldif_info *li = (struct ldif_info *) op->o_bd->be_private;
struct berval path = BER_BVNULL;
int res = 0;
slap_get_csn( op, &csn, 1 );
}
- ldap_pvt_thread_rdwr_wlock(&ni->li_rdwr);
- dn2path(&op->o_req_ndn, &op->o_bd->be_nsuffix[0], &ni->li_base_path, &path);
+ ldap_pvt_thread_rdwr_wlock(&li->li_rdwr);
+ dn2path(&op->o_req_ndn, &op->o_bd->be_nsuffix[0], &li->li_base_path, &path);
path.bv_val[path.bv_len - STRLENOF(LDIF)] = '\0';
res = rmdir(path.bv_val);
path.bv_val[path.bv_len - STRLENOF(LDIF)] = '.';
- if ( res && errno != ENOENT ) {
- rs->sr_err = LDAP_NOT_ALLOWED_ON_NONLEAF;
- } else {
- res = unlink(path.bv_val);
- }
+ rs->sr_err = LDAP_SUCCESS;
+ if ( res ) {
+ switch ( errno ) {
+ case ENOTEMPTY:
+ rs->sr_err = LDAP_NOT_ALLOWED_ON_NONLEAF;
+ break;
- if(res == -1) {
- if(errno == ENOENT)
+ case ENOENT:
rs->sr_err = LDAP_NO_SUCH_OBJECT;
- else
+ break;
+
+ default:
rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
+ break;
+ }
+
+ } else {
+ res = unlink(path.bv_val);
+ if ( res == -1 ) {
+ switch ( errno ) {
+ case ENOENT:
+ rs->sr_err = LDAP_NO_SUCH_OBJECT;
+ break;
+
+ default:
+ rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
+ break;
+ }
+ }
}
- else
- rs->sr_err = LDAP_SUCCESS;
SLAP_FREE(path.bv_val);
- ldap_pvt_thread_rdwr_wunlock(&ni->li_rdwr);
+ ldap_pvt_thread_rdwr_wunlock(&li->li_rdwr);
send_ldap_result(op, rs);
slap_graduate_commit_csn( op );
- return 0;
+ return rs->sr_err;
}
exists_res = open(newpath.bv_val, O_RDONLY);
if(exists_res == -1 && errno == ENOENT) {
ldap_pvt_thread_mutex_lock( &entry2str_mutex );
- res = spew_entry(entry, &newpath);
+ res = spew_entry(entry, &newpath, 0, NULL);
if(res != -1) {
/* if this fails we should log something bad */
res = unlink(path.bv_val);
static int
ldif_back_modrdn(Operation *op, SlapReply *rs)
{
- struct ldif_info *ni = (struct ldif_info *) op->o_bd->be_private;
+ struct ldif_info *li = (struct ldif_info *) op->o_bd->be_private;
struct berval new_dn = BER_BVNULL, new_ndn = BER_BVNULL;
struct berval p_dn;
Entry * entry = NULL;
slap_mods_opattrs( op, &op->orr_modlist, 1 );
- ldap_pvt_thread_rdwr_wlock( &ni->li_rdwr );
- entry = (Entry *) get_entry( op, &ni->li_base_path );
+ ldap_pvt_thread_rdwr_wlock( &li->li_rdwr );
+ entry = get_entry( op, &li->li_base_path );
/* build the mods to the entry */
if ( entry != NULL ) {
p_dn = *op->oq_modrdn.rs_newSup;
op->o_req_dn = *op->oq_modrdn.rs_newSup;
op->o_req_ndn = *op->oq_modrdn.rs_nnewSup;
- np = (Entry *)get_entry( op, &ni->li_base_path );
+ np = get_entry( op, &li->li_base_path );
op->o_req_dn = op_dn;
op->o_req_ndn = op_ndn;
if ( np == NULL ) {
rs->sr_err = move_entry( entry, &op->o_req_ndn,
&new_ndn,
&op->o_bd->be_nsuffix[0],
- &ni->li_base_path );
+ &li->li_base_path );
} else {
rs->sr_err = res;
}
entry_free( entry );
}
rs->sr_text = "";
- ldap_pvt_thread_rdwr_wunlock( &ni->li_rdwr );
+ ldap_pvt_thread_rdwr_wunlock( &li->li_rdwr );
send_ldap_result( op, rs );
slap_graduate_commit_csn( op );
- return 0;
+ return rs->sr_err;
}
/* return LDAP_SUCCESS IFF we can retrieve the specified entry.
int rw,
Entry **ent )
{
- struct ldif_info *ni = (struct ldif_info *) op->o_bd->be_private;
+ struct ldif_info *li = (struct ldif_info *) op->o_bd->be_private;
struct berval op_dn = op->o_req_dn, op_ndn = op->o_req_ndn;
assert( ndn != NULL );
assert( !BER_BVISNULL( ndn ) );
- ldap_pvt_thread_rdwr_rlock( &ni->li_rdwr );
+ ldap_pvt_thread_rdwr_rlock( &li->li_rdwr );
op->o_req_dn = *ndn;
op->o_req_ndn = *ndn;
- *ent = (Entry *) get_entry( op, &ni->li_base_path );
+ *ent = get_entry( op, &li->li_base_path );
op->o_req_dn = op_dn;
op->o_req_ndn = op_ndn;
- ldap_pvt_thread_rdwr_runlock( &ni->li_rdwr );
+ ldap_pvt_thread_rdwr_runlock( &li->li_rdwr );
if ( *ent && oc && !is_entry_objectclass_or_sub( *ent, oc ) ) {
entry_free( *ent );
return ( *ent == NULL ? 1 : 0 );
}
-static int ldif_tool_entry_open(BackendDB * be, int mode) {
- struct ldif_info *ni = (struct ldif_info *) be->be_private;
- ni->li_tool_current = 0;
+static int ldif_tool_entry_open(BackendDB *be, int mode) {
+ struct ldif_info *li = (struct ldif_info *) be->be_private;
+ li->li_tool_current = 0;
return 0;
}
static int ldif_tool_entry_close(BackendDB * be) {
- struct ldif_info *ni = (struct ldif_info *) be->be_private;
+ struct ldif_info *li = (struct ldif_info *) be->be_private;
- SLAP_FREE(ni->li_tool_cookie.entries);
+ SLAP_FREE(li->li_tool_cookie.entries);
return 0;
}
+static ID ldif_tool_entry_next(BackendDB *be)
+{
+ struct ldif_info *li = (struct ldif_info *) be->be_private;
+ if(li->li_tool_current >= li->li_tool_cookie.eind)
+ return NOID;
+ else
+ return ++li->li_tool_current;
+}
+
static ID
ldif_tool_entry_first(BackendDB *be)
{
- struct ldif_info *ni = (struct ldif_info *) be->be_private;
- ID id = 1; /* first entry in the array of entries shifted by one */
+ struct ldif_info *li = (struct ldif_info *) be->be_private;
- ni->li_tool_current = 1;
- if(ni->li_tool_cookie.entries == NULL) {
+ if(li->li_tool_cookie.entries == NULL) {
Operation op = {0};
op.o_bd = be;
op.o_req_dn = *be->be_suffix;
op.o_req_ndn = *be->be_nsuffix;
op.ors_scope = LDAP_SCOPE_SUBTREE;
- ni->li_tool_cookie.op = &op;
- (void)enum_tree( &ni->li_tool_cookie );
- ni->li_tool_cookie.op = NULL;
+ li->li_tool_cookie.op = &op;
+ (void)enum_tree( &li->li_tool_cookie );
+ li->li_tool_cookie.op = NULL;
}
- return id;
-}
-
-static ID ldif_tool_entry_next(BackendDB *be)
-{
- struct ldif_info *ni = (struct ldif_info *) be->be_private;
- ni->li_tool_current += 1;
- if(ni->li_tool_current > ni->li_tool_cookie.eind)
- return NOID;
- else
- return ni->li_tool_current;
+ return ldif_tool_entry_next( be );
}
static Entry * ldif_tool_entry_get(BackendDB * be, ID id) {
- struct ldif_info *ni = (struct ldif_info *) be->be_private;
+ struct ldif_info *li = (struct ldif_info *) be->be_private;
Entry * e;
- if(id > ni->li_tool_cookie.eind || id < 1)
+ if(id > li->li_tool_cookie.eind || id < 1)
return NULL;
else {
- e = ni->li_tool_cookie.entries[id - 1];
- ni->li_tool_cookie.entries[id - 1] = NULL;
+ e = li->li_tool_cookie.entries[id - 1];
+ li->li_tool_cookie.entries[id - 1] = NULL;
return e;
}
}
static ID ldif_tool_entry_put(BackendDB * be, Entry * e, struct berval *text) {
- struct ldif_info *ni = (struct ldif_info *) be->be_private;
+ struct ldif_info *li = (struct ldif_info *) be->be_private;
struct berval dn = e->e_nname;
struct berval leaf_path = BER_BVNULL;
struct stat stats;
int statres;
int res = LDAP_SUCCESS;
- dn2path(&dn, &be->be_nsuffix[0], &ni->li_base_path, &leaf_path);
+ dn2path(&dn, &be->be_nsuffix[0], &li->li_base_path, &leaf_path);
if(leaf_path.bv_val != NULL) {
struct berval base = BER_BVNULL;
if(res == LDAP_SUCCESS) {
statres = stat(leaf_path.bv_val, &stats);
if(statres == -1 && errno == ENOENT) {
- res = (int) spew_entry(e, &leaf_path);
+ res = spew_entry(e, &leaf_path, 0, NULL);
}
else /* it already exists */
res = LDAP_ALREADY_EXISTS;
}
static int
-ldif_back_db_init( BackendDB *be )
+ldif_back_db_init( BackendDB *be, ConfigReply *cr )
{
- struct ldif_info *ni;
+ struct ldif_info *li;
- ni = ch_calloc( 1, sizeof(struct ldif_info) );
- be->be_private = ni;
+ li = ch_calloc( 1, sizeof(struct ldif_info) );
+ be->be_private = li;
be->be_cf_ocs = ldifocs;
- ldap_pvt_thread_rdwr_init(&ni->li_rdwr);
+ ldap_pvt_thread_rdwr_init(&li->li_rdwr);
return 0;
}
static int
-ldif_back_db_destroy(
- Backend *be
- )
+ldif_back_db_destroy( Backend *be, ConfigReply *cr )
{
- struct ldif_info *ni = be->be_private;
+ struct ldif_info *li = be->be_private;
- ch_free(ni->li_base_path.bv_val);
- ldap_pvt_thread_rdwr_destroy(&ni->li_rdwr);
+ ch_free(li->li_base_path.bv_val);
+ ldap_pvt_thread_rdwr_destroy(&li->li_rdwr);
free( be->be_private );
return 0;
}
static int
-ldif_back_db_open(
- Backend *be
- )
+ldif_back_db_open( Backend *be, ConfigReply *cr)
{
- struct ldif_info *ni = (struct ldif_info *) be->be_private;
- if( BER_BVISEMPTY(&ni->li_base_path)) {/* missing base path */
+ struct ldif_info *li = (struct ldif_info *) be->be_private;
+ if( BER_BVISEMPTY(&li->li_base_path)) {/* missing base path */
Debug( LDAP_DEBUG_ANY, "missing base path for back-ldif\n", 0, 0, 0);
return 1;
}
bi->bi_tool_sync = 0;
bi->bi_tool_dn2id_get = 0;
- bi->bi_tool_id2entry_get = 0;
bi->bi_tool_entry_modify = 0;
bi->bi_cf_ocs = ldifocs;
retry:;
ctrls = op->o_ctrls;
- if ( ldap_back_proxy_authz_ctrl( &mc->mc_conns[ candidate ].msc_bound_ndn,
- mt->mt_version, &mt->mt_idassert, op, rs, &ctrls ) != LDAP_SUCCESS )
+ if ( meta_back_controls_add( op, rs, mc, candidate, &ctrls ) != LDAP_SUCCESS )
{
send_ldap_result( op, rs );
goto cleanup;
do_retry = 0;
if ( meta_back_retry( op, rs, &mc, candidate, LDAP_BACK_SENDERR ) ) {
/* if the identity changed, there might be need to re-authz */
- (void)ldap_back_proxy_authz_ctrl_free( op, &ctrls );
+ (void)ldap_back_controls_free( op, rs, &ctrls );
goto retry;
}
}
cleanup:;
- (void)ldap_back_proxy_authz_ctrl_free( op, &ctrls );
+ (void)ldap_back_controls_free( op, rs, &ctrls );
for ( --i; i >= 0; --i ) {
free( attrs[ i ]->mod_bvalues );
/* String rewrite library */
#include "rewrite.h"
+
LDAP_BEGIN_DECL
/*
#define META_BACK_PRINT_CONNTREE 0
#endif /* !META_BACK_PRINT_CONNTREE */
-struct slap_conn;
-struct slap_op;
-
/* from back-ldap.h before rwm removal */
struct ldapmap {
int drop_missing;
} metasingleconn_t;
typedef struct metaconn_t {
- struct slap_conn *mc_conn;
+ Connection *mc_conn;
#define lc_conn mc_conn
unsigned mc_refcnt;
#define META_BACK_TGT_CANCEL_DISCOVER(mt) META_BACK_TGT_ISMASK( (mt), LDAP_BACK_F_CANCEL_MASK2, LDAP_BACK_F_CANCEL_EXOP_DISCOVER )
#define META_BACK_TGT_QUARANTINE(mt) META_BACK_TGT_ISSET( (mt), LDAP_BACK_F_QUARANTINE )
+#ifdef SLAP_CONTROL_X_SESSION_TRACKING
+#define META_BACK_TGT_ST_REQUEST(mt) META_BACK_TGT_ISSET( (mt), LDAP_BACK_F_ST_REQUEST )
+#define META_BACK_TGT_ST_RESPONSE(mt) META_BACK_TGT_ISSET( (mt), LDAP_BACK_F_ST_RESPONSE )
+#endif /* SLAP_CONTROL_X_SESSION_TRACKING */
+
int mt_version;
time_t mt_network_timeout;
struct timeval mt_bind_timeout;
gotit = 0,
isroot = 0;
- SlapReply *candidates = meta_back_candidates_get( op );
+ SlapReply *candidates;
rs->sr_err = LDAP_SUCCESS;
op->o_log_prefix, op->o_req_dn.bv_val, 0 );
/* the test on the bind method should be superfluous */
- if ( op->orb_method == LDAP_AUTH_SIMPLE
- && be_isroot_dn( op->o_bd, &op->o_req_ndn ) )
- {
- if ( !be_isroot_pw( op ) ) {
- rs->sr_err = LDAP_INVALID_CREDENTIALS;
- rs->sr_text = NULL;
- send_ldap_result( op, rs );
- return rs->sr_err;
- }
-
+ switch ( be_rootdn_bind( op, rs ) ) {
+ case LDAP_SUCCESS:
if ( META_BACK_DEFER_ROOTDN_BIND( mi ) ) {
- rs->sr_err = LDAP_SUCCESS;
- rs->sr_text = NULL;
/* frontend will return success */
return rs->sr_err;
}
isroot = 1;
+ /* fallthru */
+
+ case SLAP_CB_CONTINUE:
+ break;
+
+ default:
+ /* be_rootdn_bind() sent result */
+ return rs->sr_err;
}
/* we need meta_back_getconn() not send result even on error,
return rs->sr_err;
}
+ candidates = meta_back_candidates_get( op );
+
/*
* Each target is scanned ...
*/
">>> %s meta_back_bind_op_result[%d]\n",
op->o_log_prefix, candidate, 0 );
+ /* make sure this is clean */
+ assert( rs->sr_ctrls == NULL );
+
if ( rs->sr_err == LDAP_SUCCESS ) {
time_t stoptime = (time_t)(-1),
timeout;
metasingleconn_t *msc = &mc->mc_conns[ candidate ];
int msgid;
dncookie dc;
+ struct berval save_o_dn;
+ int save_o_do_not_cache;
+ LDAPControl **ctrls = NULL;
if ( !BER_BVISNULL( &msc->msc_bound_ndn ) ) {
ch_free( msc->msc_bound_ndn.bv_val );
return rs->sr_err;
}
+ /* don't add proxyAuthz; set the bindDN */
+ save_o_dn = op->o_dn;
+ save_o_do_not_cache = op->o_do_not_cache;
+ op->o_do_not_cache = 1;
+ op->o_dn = op->o_req_dn;
+
+ ctrls = op->o_ctrls;
+ rs->sr_err = meta_back_controls_add( op, rs, mc, candidate, &ctrls );
+ op->o_dn = save_o_dn;
+ op->o_do_not_cache = save_o_do_not_cache;
+ if ( rs->sr_err != LDAP_SUCCESS ) {
+ goto return_results;
+ }
+
/* FIXME: this fixes the bind problem right now; we need
* to use the asynchronous version to get the "matched"
* and more in case of failure ... */
for (;;) {
rs->sr_err = ldap_sasl_bind( msc->msc_ld, mdn.bv_val,
LDAP_SASL_SIMPLE, &op->orb_cred,
- op->o_ctrls, NULL, &msgid );
+ ctrls, NULL, &msgid );
if ( rs->sr_err != LDAP_X_CONNECTING ) {
break;
}
ldap_pvt_thread_yield();
}
+
+ ldap_back_controls_free( op, rs, &ctrls );
+
meta_back_bind_op_result( op, rs, mc, candidate, msgid, LDAP_BACK_DONTSEND );
if ( rs->sr_err != LDAP_SUCCESS ) {
goto return_results;
i,
isroot = 0;
- SlapReply *candidates = meta_back_candidates_get( op );
+ SlapReply *candidates;
if ( be_isroot( op ) ) {
isroot = 1;
goto done;
}
+ candidates = meta_back_candidates_get( op );
+
for ( i = 0; i < mi->mi_ntargets; i++ ) {
metatarget_t *mt = mi->mi_targets[ i ];
metasingleconn_t *msc = &mc->mc_conns[ i ];
if ( rc != LDAP_SUCCESS ) {
rs->sr_err = rc;
}
- if ( refs != NULL ) {
- int i;
+
+ /* RFC 4511: referrals can only appear
+ * if result code is LDAP_REFERRAL */
+ if ( refs != NULL
+ && refs[ 0 ] != NULL
+ && refs[ 0 ][ 0 ] != '\0' )
+ {
+ if ( rs->sr_err != LDAP_REFERRAL ) {
+ Debug( LDAP_DEBUG_ANY,
+ "%s meta_back_op_result[%d]: "
+ "got referrals with err=%d\n",
+ op->o_log_prefix,
+ candidate, rs->sr_err );
+
+ } else {
+ int i;
- for ( i = 0; refs[ i ] != NULL; i++ )
- /* count */ ;
- rs->sr_ref = op->o_tmpalloc( sizeof( struct berval ) * ( i + 1 ),
- op->o_tmpmemctx );
- for ( i = 0; refs[ i ] != NULL; i++ ) {
- ber_str2bv( refs[ i ], 0, 0, &rs->sr_ref[ i ] );
+ for ( i = 0; refs[ i ] != NULL; i++ )
+ /* count */ ;
+ rs->sr_ref = op->o_tmpalloc( sizeof( struct berval ) * ( i + 1 ),
+ op->o_tmpmemctx );
+ for ( i = 0; refs[ i ] != NULL; i++ ) {
+ ber_str2bv( refs[ i ], 0, 0, &rs->sr_ref[ i ] );
+ }
+ BER_BVZERO( &rs->sr_ref[ i ] );
}
- BER_BVZERO( &rs->sr_ref[ i ] );
+
+ } else if ( rs->sr_err == LDAP_REFERRAL ) {
+ Debug( LDAP_DEBUG_ANY,
+ "%s meta_back_op_result[%d]: "
+ "got err=%d with null "
+ "or empty referrals\n",
+ op->o_log_prefix,
+ candidate, rs->sr_err );
+
+ rs->sr_err = LDAP_NO_SUCH_OBJECT;
}
+
if ( ctrls != NULL ) {
rs->sr_ctrls = ctrls;
}
ldap_memfree( text );
}
if ( rs->sr_ref ) {
- assert( refs != NULL );
- ber_memvfree( (void **)refs );
op->o_tmpfree( rs->sr_ref, op->o_tmpmemctx );
+ rs->sr_ref = NULL;
+ }
+ if ( refs ) {
+ ber_memvfree( (void **)refs );
}
if ( ctrls ) {
assert( rs->sr_ctrls != NULL );
mt->mt_idassert_authcID.bv_val,
mt->mt_idassert_passwd.bv_val,
authzID.bv_val );
+ if ( defaults == NULL ) {
+ rs->sr_err = LDAP_OTHER;
+ LDAP_BACK_CONN_ISBOUND_CLEAR( msc );
+ if ( sendok & LDAP_BACK_SENDERR ) {
+ send_ldap_result( op, rs );
+ }
+ goto done;
+ }
rs->sr_err = ldap_sasl_interactive_bind_s( msc->msc_ld, binddn->bv_val,
mt->mt_idassert_sasl_mech.bv_val, NULL, NULL,
return LDAP_BACK_CONN_ISBOUND( msc );
}
+
+/*
+ * Add controls;
+ *
+ * if any needs to be added, it is prepended to existing ones,
+ * in a newly allocated array. The companion function
+ * ldap_back_controls_free() must be used to restore the original
+ * status of op->o_ctrls.
+ */
+int
+meta_back_controls_add(
+ Operation *op,
+ SlapReply *rs,
+ metaconn_t *mc,
+ int candidate,
+ LDAPControl ***pctrls )
+{
+ metainfo_t *mi = (metainfo_t *)op->o_bd->be_private;
+ metatarget_t *mt = mi->mi_targets[ candidate ];
+ metasingleconn_t *msc = &mc->mc_conns[ candidate ];
+
+ LDAPControl **ctrls = NULL;
+ /* set to the maximum number of controls this backend can add */
+ LDAPControl c[ 2 ] = { 0 };
+ int i = 0, j = 0;
+
+ *pctrls = NULL;
+
+ rs->sr_err = LDAP_SUCCESS;
+
+ /* don't add controls if protocol is not LDAPv3 */
+ switch ( mt->mt_version ) {
+ case LDAP_VERSION3:
+ break;
+
+ case 0:
+ if ( op->o_protocol == 0 || op->o_protocol == LDAP_VERSION3 ) {
+ break;
+ }
+ /* fall thru */
+
+ default:
+ goto done;
+ }
+
+ /* proxyAuthz for identity assertion */
+ switch ( ldap_back_proxy_authz_ctrl( op, rs, &msc->msc_bound_ndn,
+ mt->mt_version, &mt->mt_idassert, &c[ j ] ) )
+ {
+ case SLAP_CB_CONTINUE:
+ break;
+
+ case LDAP_SUCCESS:
+ j++;
+ break;
+
+ default:
+ goto done;
+ }
+
+#ifdef SLAP_CONTROL_X_SESSION_TRACKING
+ /* session tracking */
+ if ( META_BACK_TGT_ST_REQUEST( mt ) ) {
+ switch ( slap_ctrl_session_tracking_request_add( op, rs, &c[ j ] ) ) {
+ case SLAP_CB_CONTINUE:
+ break;
+
+ case LDAP_SUCCESS:
+ j++;
+ break;
+
+ default:
+ goto done;
+ }
+ }
+#endif /* SLAP_CONTROL_X_SESSION_TRACKING */
+
+ if ( rs->sr_err == SLAP_CB_CONTINUE ) {
+ rs->sr_err = LDAP_SUCCESS;
+ }
+
+ if ( j == 0 ) {
+ goto done;
+ }
+
+ if ( op->o_ctrls ) {
+ for ( i = 0; op->o_ctrls[ i ]; i++ )
+ /* just count ctrls */ ;
+ }
+
+ ctrls = op->o_tmpalloc( sizeof( LDAPControl * ) * (i + j + 1) + j * sizeof( LDAPControl ),
+ op->o_tmpmemctx );
+ ctrls[ 0 ] = (LDAPControl *)&ctrls[ i + j + 1 ];
+ *ctrls[ 0 ] = c[ 0 ];
+ for ( i = 1; i < j; i++ ) {
+ ctrls[ i ] = &ctrls[ 0 ][ i ];
+ *ctrls[ i ] = c[ i ];
+ }
+
+ i = 0;
+ if ( op->o_ctrls ) {
+ for ( i = 0; op->o_ctrls[ i ]; i++ ) {
+ ctrls[ i + j ] = op->o_ctrls[ i ];
+ }
+ }
+ ctrls[ i + j ] = NULL;
+
+done:;
+ if ( ctrls == NULL ) {
+ ctrls = op->o_ctrls;
+ }
+
+ *pctrls = ctrls;
+
+ return rs->sr_err;
+}
+
retry:;
ctrls = op->o_ctrls;
- rc = ldap_back_proxy_authz_ctrl( &mc->mc_conns[ candidate ].msc_bound_ndn,
- mt->mt_version, &mt->mt_idassert, op, rs, &ctrls );
+ rc = meta_back_controls_add( op, rs, mc, candidate, &ctrls );
if ( rc != LDAP_SUCCESS ) {
send_ldap_result( op, rs );
goto cleanup;
do_retry = 0;
if ( meta_back_retry( op, rs, &mc, candidate, LDAP_BACK_SENDERR ) ) {
/* if the identity changed, there might be need to re-authz */
- (void)ldap_back_proxy_authz_ctrl_free( op, &ctrls );
+ (void)ldap_back_controls_free( op, rs, &ctrls );
goto retry;
}
}
cleanup:;
- (void)ldap_back_proxy_authz_ctrl_free( op, &ctrls );
+ (void)ldap_back_controls_free( op, rs, &ctrls );
if ( mdn.bv_val != op->o_req_dn.bv_val ) {
free( mdn.bv_val );
/* URI of server to query */
if ( strcasecmp( argv[ 0 ], "uri" ) == 0 ) {
int i = mi->mi_ntargets;
-#if 0
- int j;
-#endif /* uncomment if uri MUST be a branch of suffix */
LDAPURLDesc *ludp, *tmpludp;
struct berval dn;
int rc;
int c;
+ BackendDB *tmp_bd;
metatarget_t *mt;
/*
* uri MUST be a branch of suffix!
*/
-#if 0 /* too strict a constraint */
- if ( select_backend( &mt->mt_nsuffix, 0, 0 ) != be ) {
- Debug( LDAP_DEBUG_ANY,
- "%s: line %d: <naming context> of URI does not refer to current backend"
- " in \"uri <protocol>://<server>[:port]/<naming context>\" line\n",
- fname, lineno, 0 );
- return 1;
- }
-#else
- /*
- * uri MUST be a branch of a suffix!
- */
- if ( select_backend( &mt->mt_nsuffix, 0, 0 ) == NULL ) {
+ tmp_bd = select_backend( &mt->mt_nsuffix, 0 );
+ if ( tmp_bd == NULL || tmp_bd->be_private != be->be_private )
+ {
Debug( LDAP_DEBUG_ANY,
- "%s: line %d: <naming context> of URI does not resolve to a backend"
- " in \"uri <protocol>://<server>[:port]/<naming context>\" line\n",
+ "%s: line %d: <naming context> of URI does not resolve to this database.\n",
fname, lineno, 0 );
return 1;
}
-#endif
/* subtree-exclude */
} else if ( strcasecmp( argv[ 0 ], "subtree-exclude" ) == 0 ) {
} else {
mi->mi_targets[ mi->mi_ntargets - 1 ]->mt_flags |= LDAP_BACK_F_QUARANTINE;
}
+
+#ifdef SLAP_CONTROL_X_SESSION_TRACKING
+ /* session tracking request */
+ } else if ( strcasecmp( argv[ 0 ], "session-tracking-request" ) == 0 ) {
+ unsigned *flagsp = mi->mi_ntargets ?
+ &mi->mi_targets[ mi->mi_ntargets - 1 ]->mt_flags
+ : &mi->mi_flags;
+
+ if ( argc != 2 ) {
+ Debug( LDAP_DEBUG_ANY,
+ "%s: line %d: \"session-tracking-request {TRUE|false}\" needs 1 argument.\n",
+ fname, lineno, 0 );
+ return( 1 );
+ }
+
+ /* this is the default; we add it because the default might change... */
+ switch ( check_true_false( argv[ 1 ] ) ) {
+ case 1:
+ *flagsp |= LDAP_BACK_F_ST_REQUEST;
+ break;
+
+ case 0:
+ *flagsp &= ~LDAP_BACK_F_ST_REQUEST;
+ break;
+
+ default:
+ Debug( LDAP_DEBUG_ANY,
+ "%s: line %d: \"session-tracking-request {TRUE|false}\": unknown argument \"%s\".\n",
+ fname, lineno, argv[ 1 ] );
+ return( 1 );
+ }
+#endif /* SLAP_CONTROL_X_SESSION_TRACKING */
/* dn massaging */
} else if ( strcasecmp( argv[ 0 ], "suffixmassage" ) == 0 ) {
- BackendDB *tmp_be;
+ BackendDB *tmp_bd;
int i = mi->mi_ntargets - 1, rc;
struct berval dn, nvnc, pvnc, nrnc, prnc;
ber_str2bv( argv[ 1 ], 0, 0, &dn );
if ( dnPrettyNormal( NULL, &dn, &pvnc, &nvnc, NULL ) != LDAP_SUCCESS ) {
Debug( LDAP_DEBUG_ANY, "%s: line %d: "
- "suffix '%s' is invalid\n",
+ "suffix \"%s\" is invalid\n",
fname, lineno, argv[ 1 ] );
return 1;
}
- tmp_be = select_backend( &nvnc, 0, 0 );
- if ( tmp_be != NULL && tmp_be != be ) {
+ tmp_bd = select_backend( &nvnc, 0 );
+ if ( tmp_bd != NULL && tmp_bd->be_private != be->be_private ) {
Debug( LDAP_DEBUG_ANY,
- "%s: line %d: suffix already in use by another backend in"
- " \"suffixMassage <suffix> <massaged suffix>\"\n",
- fname, lineno, 0 );
+ "%s: line %d: <suffix> \"%s\" already in use by another database, in "
+ "\"suffixMassage <suffix> <massaged suffix>\"\n",
+ fname, lineno, pvnc.bv_val );
free( pvnc.bv_val );
free( nvnc.bv_val );
return 1;
ber_str2bv( argv[ 2 ], 0, 0, &dn );
if ( dnPrettyNormal( NULL, &dn, &prnc, &nrnc, NULL ) != LDAP_SUCCESS ) {
Debug( LDAP_DEBUG_ANY, "%s: line %d: "
- "massaged suffix '%s' is invalid\n",
+ "massaged suffix \"%s\" is invalid\n",
fname, lineno, argv[ 2 ] );
free( pvnc.bv_val );
free( nvnc.bv_val );
return 1;
}
-#if 0
- tmp_be = select_backend( &nrnc, 0, 0 );
- if ( tmp_be != NULL ) {
- Debug( LDAP_DEBUG_ANY,
- "%s: line %d: massaged suffix already in use by another backend in"
- " \"suffixMassage <suffix> <massaged suffix>\"\n",
- fname, lineno, 0 );
+ tmp_bd = select_backend( &nrnc, 0 );
+ if ( tmp_bd != NULL && tmp_bd->be_private == be->be_private ) {
+ Debug( LDAP_DEBUG_ANY,
+ "%s: line %d: warning: <massaged suffix> \"%s\" point to this database, in "
+ "\"suffixMassage <suffix> <massaged suffix>\"\n",
+ fname, lineno, prnc.bv_val );
free( pvnc.bv_val );
free( nvnc.bv_val );
- free( prnc.bv_val );
- free( nrnc.bv_val );
- return 1;
+ return 1;
}
-#endif
-
+
/*
* The suffix massaging is emulated by means of the
* rewrite capabilities
- * FIXME: no extra rewrite capabilities should be added
- * to the database
*/
rc = suffix_massage_config( mi->mi_targets[ i ]->mt_rwmap.rwm_rw,
&pvnc, &nvnc, &prnc, &nrnc );
retry:;
ctrls = op->o_ctrls;
- if ( ldap_back_proxy_authz_ctrl( &mc->mc_conns[ candidate ].msc_bound_ndn,
- mt->mt_version, &mt->mt_idassert, op, rs, &ctrls ) != LDAP_SUCCESS )
+ if ( meta_back_controls_add( op, rs, mc, candidate, &ctrls ) != LDAP_SUCCESS )
{
send_ldap_result( op, rs );
goto cleanup;
do_retry = 0;
if ( meta_back_retry( op, rs, &mc, candidate, LDAP_BACK_SENDERR ) ) {
/* if the identity changed, there might be need to re-authz */
- (void)ldap_back_proxy_authz_ctrl_free( op, &ctrls );
+ (void)ldap_back_controls_free( op, rs, &ctrls );
goto retry;
}
}
cleanup:;
- (void)ldap_back_proxy_authz_ctrl_free( op, &ctrls );
+ (void)ldap_back_controls_free( op, rs, &ctrls );
if ( mdn.bv_val != op->o_req_dn.bv_val ) {
free( mdn.bv_val );
#include <ac/socket.h>
#include "slap.h"
+#include "config.h"
#include "../back-ldap/back-ldap.h"
#include "back-meta.h"
int
meta_back_db_init(
- Backend *be )
+ Backend *be,
+ ConfigReply *cr)
{
metainfo_t *mi;
int i;
int
meta_back_db_open(
- Backend *be )
+ Backend *be,
+ ConfigReply *cr )
{
metainfo_t *mi = (metainfo_t *)be->be_private;
int
meta_back_db_destroy(
- Backend *be )
+ Backend *be,
+ ConfigReply *cr )
{
metainfo_t *mi;
fstr->bv_val = malloc( fstr->bv_len + 1 );
snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s=%s)",
- atmp.bv_val, vtmp.bv_val );
+ atmp.bv_val, vtmp.bv_len ? vtmp.bv_val : "" );
ber_memfree( vtmp.bv_val );
break;
fstr->bv_val = malloc( fstr->bv_len + 1 );
snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s>=%s)",
- atmp.bv_val, vtmp.bv_val );
+ atmp.bv_val, vtmp.bv_len ? vtmp.bv_val : "" );
ber_memfree( vtmp.bv_val );
break;
fstr->bv_val = malloc( fstr->bv_len + 1 );
snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s<=%s)",
- atmp.bv_val, vtmp.bv_val );
+ atmp.bv_val, vtmp.bv_len ? vtmp.bv_val : "" );
ber_memfree( vtmp.bv_val );
break;
fstr->bv_val = malloc( fstr->bv_len + 1 );
snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s~=%s)",
- atmp.bv_val, vtmp.bv_val );
+ atmp.bv_val, vtmp.bv_len ? vtmp.bv_val : "" );
ber_memfree( vtmp.bv_val );
break;
snprintf( &fstr->bv_val[len - 2], vtmp.bv_len + 3,
/* "(attr=" */ "%s*)",
- vtmp.bv_val );
+ vtmp.bv_len ? vtmp.bv_val : "" );
ber_memfree( vtmp.bv_val );
}
snprintf( &fstr->bv_val[len - 1], vtmp.bv_len + 3,
/* "(attr=[init]*[any*]" */ "%s*)",
- vtmp.bv_val );
+ vtmp.bv_len ? vtmp.bv_val : "" );
ber_memfree( vtmp.bv_val );
}
}
snprintf( &fstr->bv_val[len - 1], vtmp.bv_len + 3,
/* "(attr=[init*][any*]" */ "%s)",
- vtmp.bv_val );
+ vtmp.bv_len ? vtmp.bv_val : "" );
ber_memfree( vtmp.bv_val );
}
fstr->bv_val = ch_realloc( fstr->bv_val, fstr->bv_len + 1 );
snprintf( &fstr->bv_val[len-1], vtmp.bv_len + 2,
- /*"("*/ "%s)", vtmp.bv_val );
+ /*"("*/ "%s)", vtmp.bv_len ? vtmp.bv_val : "" );
ch_free( vtmp.bv_val );
}
f->f_mr_dnattrs ? ":dn" : "",
!BER_BVISEMPTY( &f->f_mr_rule_text ) ? ":" : "",
!BER_BVISEMPTY( &f->f_mr_rule_text ) ? f->f_mr_rule_text.bv_val : "",
- vtmp.bv_val );
+ vtmp.bv_len ? vtmp.bv_val : "" );
ber_memfree( vtmp.bv_val );
break;
retry:;
ctrls = op->o_ctrls;
- rc = ldap_back_proxy_authz_ctrl( &mc->mc_conns[ candidate ].msc_bound_ndn,
- mt->mt_version, &mt->mt_idassert, op, rs, &ctrls );
+ rc = meta_back_controls_add( op, rs, mc, candidate, &ctrls );
if ( rc != LDAP_SUCCESS ) {
send_ldap_result( op, rs );
goto cleanup;
do_retry = 0;
if ( meta_back_retry( op, rs, &mc, candidate, LDAP_BACK_SENDERR ) ) {
/* if the identity changed, there might be need to re-authz */
- (void)ldap_back_proxy_authz_ctrl_free( op, &ctrls );
+ (void)ldap_back_controls_free( op, rs, &ctrls );
goto retry;
}
}
cleanup:;
- (void)ldap_back_proxy_authz_ctrl_free( op, &ctrls );
+ (void)ldap_back_controls_free( op, rs, &ctrls );
if ( mdn.bv_val != op->o_req_dn.bv_val ) {
free( mdn.bv_val );
retry:;
ctrls = op->o_ctrls;
- if ( ldap_back_proxy_authz_ctrl( &mc->mc_conns[ candidate ].msc_bound_ndn,
- mt->mt_version, &mt->mt_idassert, op, rs, &ctrls ) != LDAP_SUCCESS )
+ if ( meta_back_controls_add( op, rs, mc, candidate, &ctrls ) != LDAP_SUCCESS )
{
send_ldap_result( op, rs );
goto cleanup;
do_retry = 0;
if ( meta_back_retry( op, rs, &mc, candidate, LDAP_BACK_SENDERR ) ) {
/* if the identity changed, there might be need to re-authz */
- (void)ldap_back_proxy_authz_ctrl_free( op, &ctrls );
+ (void)ldap_back_controls_free( op, rs, &ctrls );
goto retry;
}
}
cleanup:;
- (void)ldap_back_proxy_authz_ctrl_free( op, &ctrls );
+ (void)ldap_back_controls_free( op, rs, &ctrls );
if ( mdn.bv_val != op->o_req_dn.bv_val ) {
free( mdn.bv_val );
assert( msc->msc_ld != NULL );
- /* connect must be async */
-retry:;
+ /* connect must be async only the first time... */
ldap_set_option( msc->msc_ld, LDAP_OPT_CONNECT_ASYNC, LDAP_OPT_ON );
+retry:;
rc = ldap_sasl_bind( msc->msc_ld, binddn.bv_val, LDAP_SASL_SIMPLE, &cred,
NULL, NULL, &candidates[ candidate ].sr_msgid );
if ( *mcp == NULL ) {
retcode = META_SEARCH_ERR;
rs->sr_err = LDAP_UNAVAILABLE;
+ candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;
break;
}
/* fall thru */
retry:;
ctrls = op->o_ctrls;
- if ( ldap_back_proxy_authz_ctrl( &msc->msc_bound_ndn,
- mt->mt_version, &mt->mt_idassert, op, rs, &ctrls )
+ if ( meta_back_controls_add( op, rs, *mcp, candidate, &ctrls )
!= LDAP_SUCCESS )
{
candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;
if ( nretries && meta_back_retry( op, rs, mcp, candidate, LDAP_BACK_DONTSEND ) ) {
nretries = 0;
/* if the identity changed, there might be need to re-authz */
- (void)ldap_back_proxy_authz_ctrl_free( op, &ctrls );
+ (void)ldap_back_controls_free( op, rs, &ctrls );
goto retry;
}
if ( *mcp == NULL ) {
retcode = META_SEARCH_ERR;
+ candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;
break;
}
/* fall thru */
}
done:;
- (void)ldap_back_proxy_authz_ctrl_free( op, &ctrls );
+ (void)ldap_back_controls_free( op, rs, &ctrls );
if ( mapped_attrs ) {
free( mapped_attrs );
dncookie dc;
int is_ok = 0;
void *savepriv;
- SlapReply *candidates = meta_back_candidates_get( op );
+ SlapReply *candidates = NULL;
/*
* controls are set in ldap_back_dobind()
dc.conn = op->o_conn;
dc.rs = rs;
+ if ( candidates == NULL ) candidates = meta_back_candidates_get( op );
/*
* Inits searches
*/
int gotit = 0,
doabandon = 0,
alreadybound = ncandidates;
- time_t curr_time = 0;
/* check timeout */
if ( timeout && lastres_time > 0
candidates[ i ].sr_type = REP_RESULT;
}
+ candidates[ i ].sr_msgid = META_MSGID_IGNORE;
+
/* NOTE: ignores response controls
* (and intermediate response controls
* as well, except for those with search
NULL /* &candidates[ i ].sr_ctrls (unused) */ ,
0 );
if ( rs->sr_err != LDAP_SUCCESS ) {
- ldap_get_option( msc->msc_ld,
- LDAP_OPT_ERROR_NUMBER,
- &rs->sr_err );
- sres = slap_map_api2result( rs );
+ sres = slap_map_api2result( &candidates[ i ] );
candidates[ i ].sr_type = REP_RESULT;
ldap_msgfree( res );
res = NULL;
goto really_bad;
}
+ rs->sr_err = candidates[ i ].sr_err;
+
/* massage matchedDN if need be */
if ( candidates[ i ].sr_matched != NULL ) {
struct berval match, mmatch;
}
/* add references to array */
- if ( references ) {
- BerVarray sr_ref;
- int cnt;
+ /* RFC 4511: referrals can only appear
+ * if result code is LDAP_REFERRAL */
+ if ( references != NULL
+ && references[ 0 ] != NULL
+ && references[ 0 ][ 0 ] != '\0' )
+ {
+ if ( rs->sr_err != LDAP_REFERRAL ) {
+ Debug( LDAP_DEBUG_ANY,
+ "%s meta_back_search[%ld]: "
+ "got referrals with err=%d\n",
+ op->o_log_prefix,
+ i, rs->sr_err );
+
+ } else {
+ BerVarray sr_ref;
+ int cnt;
- for ( cnt = 0; references[ cnt ]; cnt++ )
- ;
+ for ( cnt = 0; references[ cnt ]; cnt++ )
+ ;
- sr_ref = ch_calloc( sizeof( struct berval ), cnt + 1 );
+ sr_ref = ch_calloc( sizeof( struct berval ), cnt + 1 );
- for ( cnt = 0; references[ cnt ]; cnt++ ) {
- ber_str2bv( references[ cnt ], 0, 1, &sr_ref[ cnt ] );
- }
- BER_BVZERO( &sr_ref[ cnt ] );
+ for ( cnt = 0; references[ cnt ]; cnt++ ) {
+ ber_str2bv( references[ cnt ], 0, 1, &sr_ref[ cnt ] );
+ }
+ BER_BVZERO( &sr_ref[ cnt ] );
- ( void )ldap_back_referral_result_rewrite( &dc, sr_ref );
+ ( void )ldap_back_referral_result_rewrite( &dc, sr_ref );
- /* cleanup */
- ber_memvfree( (void **)references );
-
- if ( rs->sr_v2ref == NULL ) {
- rs->sr_v2ref = sr_ref;
+ if ( rs->sr_v2ref == NULL ) {
+ rs->sr_v2ref = sr_ref;
- } else {
- for ( cnt = 0; !BER_BVISNULL( &sr_ref[ cnt ] ); cnt++ ) {
- ber_bvarray_add( &rs->sr_v2ref, &sr_ref[ cnt ] );
+ } else {
+ for ( cnt = 0; !BER_BVISNULL( &sr_ref[ cnt ] ); cnt++ ) {
+ ber_bvarray_add( &rs->sr_v2ref, &sr_ref[ cnt ] );
+ }
+ ber_memfree( sr_ref );
}
- ber_memfree( sr_ref );
}
+
+ } else if ( rs->sr_err == LDAP_REFERRAL ) {
+ Debug( LDAP_DEBUG_ANY,
+ "%s meta_back_search[%ld]: "
+ "got err=%d with null "
+ "or empty referrals\n",
+ op->o_log_prefix,
+ i, rs->sr_err );
+
+ rs->sr_err = LDAP_NO_SUCH_OBJECT;
}
+
+ /* cleanup */
+ ber_memvfree( (void **)references );
- rs->sr_err = candidates[ i ].sr_err;
sres = slap_map_api2result( rs );
if ( LogTest( LDAP_DEBUG_TRACE | LDAP_DEBUG_ANY ) ) {
* When no candidates are left,
* the outer cycle finishes
*/
- candidates[ i ].sr_msgid = META_MSGID_IGNORE;
assert( ncandidates > 0 );
--ncandidates;
/* check for abandon */
if ( op->o_abandon || LDAP_BACK_CONN_ABANDON( mc ) ) {
for ( i = 0; i < mi->mi_ntargets; i++ ) {
- if ( candidates[ i ].sr_msgid >= 0 ) {
- if ( META_IS_BINDING( &candidates[ i ] ) ) {
+ if ( candidates[ i ].sr_msgid >= 0
+ || candidates[ i ].sr_msgid == META_MSGID_CONNECTING )
+ {
+ if ( META_IS_BINDING( &candidates[ i ] )
+ || candidates[ i ].sr_msgid == META_MSGID_CONNECTING )
+ {
ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex );
- if ( LDAP_BACK_CONN_BINDING( &mc->mc_conns[ i ] ) ) {
+ if ( LDAP_BACK_CONN_BINDING( &mc->mc_conns[ i ] )
+ || candidates[ i ].sr_msgid == META_MSGID_CONNECTING )
+ {
/* if still binding, destroy */
#ifdef DEBUG_205
continue;
}
- if ( mc && META_IS_BINDING( &candidates[ i ] ) ) {
- ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex );
- if ( LDAP_BACK_CONN_BINDING( &mc->mc_conns[ i ] ) ) {
- assert( candidates[ i ].sr_msgid >= 0 );
- assert( mc->mc_conns[ i ].msc_ld != NULL );
+ if ( mc ) {
+ if ( META_IS_BINDING( &candidates[ i ] )
+ || candidates[ i ].sr_msgid == META_MSGID_CONNECTING )
+ {
+ ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex );
+ if ( LDAP_BACK_CONN_BINDING( &mc->mc_conns[ i ] )
+ || candidates[ i ].sr_msgid == META_MSGID_CONNECTING )
+ {
+ assert( candidates[ i ].sr_msgid >= 0
+ || candidates[ i ].sr_msgid == META_MSGID_CONNECTING );
+ assert( mc->mc_conns[ i ].msc_ld != NULL );
#ifdef DEBUG_205
- Debug( LDAP_DEBUG_ANY, "### %s meta_back_search(cleanup) "
- "ldap_unbind_ext[%ld] ld=%p\n",
- op->o_log_prefix, i, (void *)mc->mc_conns[i].msc_ld );
+ Debug( LDAP_DEBUG_ANY, "### %s meta_back_search(cleanup) "
+ "ldap_unbind_ext[%ld] ld=%p\n",
+ op->o_log_prefix, i, (void *)mc->mc_conns[i].msc_ld );
#endif /* DEBUG_205 */
- /* if still binding, destroy */
- meta_clear_one_candidate( op, mc, i );
+ /* if still binding, destroy */
+ meta_clear_one_candidate( op, mc, i );
+ }
+ ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
+ META_BINDING_CLEAR( &candidates[ i ] );
+
+ } else if ( candidates[ i ].sr_msgid >= 0 ) {
+ (void)meta_back_cancel( mc, op, rs,
+ candidates[ i ].sr_msgid, i,
+ LDAP_BACK_DONTSEND );
}
- ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
- META_BINDING_CLEAR( &candidates[ i ] );
}
if ( candidates[ i ].sr_matched ) {
{
metainfo_t *mi = ( metainfo_t * )op->o_bd->be_private;
struct berval a, mapped;
+ int check_duplicate_attrs = 0;
Entry ent = { 0 };
BerElement ber = *e->lm_ber;
Attribute *attr, **attrp;
( void )ber_scanf( &ber, "x" /* [W] */ );
continue;
}
+ if ( mapped.bv_val != a.bv_val ) {
+ /* will need to check for duplicate attrs */
+ check_duplicate_attrs++;
+ }
attr = attr_alloc( NULL );
if ( attr == NULL ) {
continue;
ldap_back_map( &mi->mi_targets[ target ]->mt_rwmap.rwm_oc,
bv, &mapped, BACKLDAP_REMAP );
if ( BER_BVISNULL( &mapped ) || mapped.bv_val[0] == '\0') {
+remove_oc:;
free( bv->bv_val );
BER_BVZERO( bv );
if ( --last < 0 ) {
bv--;
} else if ( mapped.bv_val != bv->bv_val ) {
- free( bv->bv_val );
- ber_dupbv( bv, &mapped );
+ int i;
+
+ for ( i = 0; !BER_BVISNULL( &attr->a_vals[ i ] ); i++ ) {
+ if ( &attr->a_vals[ i ] == bv ) {
+ continue;
+ }
+
+ if ( ber_bvstrcasecmp( &mapped, &attr->a_vals[ i ] ) == 0 ) {
+ break;
+ }
+ }
+
+ if ( !BER_BVISNULL( &attr->a_vals[ i ] ) ) {
+ goto remove_oc;
+ }
+
+ ber_bvreplace( bv, &mapped );
}
}
/*
attrp = &attr->a_next;
next_attr:;
}
+
+ /* only check if some mapping occurred */
+ if ( check_duplicate_attrs ) {
+ Attribute **ap;
+
+ for ( ap = &ent.e_attrs; *ap != NULL; ap = &(*ap)->a_next ) {
+ Attribute **tap;
+
+ for ( tap = &(*ap)->a_next; *tap != NULL; ) {
+ if ( (*tap)->a_desc == (*ap)->a_desc ) {
+ Entry e = { 0 };
+ Modification mod = { 0 };
+ const char *text = NULL;
+ char textbuf[ SLAP_TEXT_BUFLEN ];
+ Attribute *next = (*tap)->a_next;
+
+ BER_BVSTR( &e.e_name, "" );
+ BER_BVSTR( &e.e_nname, "" );
+ e.e_attrs = *ap;
+ mod.sm_op = LDAP_MOD_ADD;
+ mod.sm_desc = (*ap)->a_desc;
+ mod.sm_type = mod.sm_desc->ad_cname;
+ mod.sm_values = (*tap)->a_vals;
+ mod.sm_nvalues = (*tap)->a_nvals;
+
+ (void)modify_add_values( &e, &mod,
+ /* permissive */ 1,
+ &text, textbuf, sizeof( textbuf ) );
+
+ /* should not insert new attrs! */
+ assert( e.e_attrs == *ap );
+
+ attr_free( *tap );
+ *tap = next;
+
+ } else {
+ tap = &(*tap)->a_next;
+ }
+ }
+ }
+ }
+
+ ldap_get_entry_controls( mc->mc_conns[target].msc_ld,
+ e, &rs->sr_ctrls );
rs->sr_entry = &ent;
rs->sr_attrs = op->ors_attrs;
+ rs->sr_operational_attrs = NULL;
rs->sr_flags = 0;
rs->sr_err = LDAP_SUCCESS;
rc = send_search_entry( op, rs );
}
rs->sr_entry = NULL;
rs->sr_attrs = NULL;
-
+ if ( rs->sr_ctrls != NULL ) {
+ ldap_controls_free( rs->sr_ctrls );
+ rs->sr_ctrls = NULL;
+ }
if ( !BER_BVISNULL( &ent.e_name ) ) {
free( ent.e_name.bv_val );
BER_BVZERO( &ent.e_name );
struct monitor_callback_t *mp_cb; /* callback sequence */
} monitor_entry_t;
+struct entry_limbo_t; /* in init.c */
+
typedef struct monitor_info_t {
/*
AttributeDescription *mi_ad_readOnly;
AttributeDescription *mi_ad_restrictedOperation;
- void *mi_entry_limbo;
+ struct entry_limbo_t *mi_entry_limbo;
} monitor_info_t;
/*
monitor_subsys_t * (*get_subsys_by_dn)( struct berval *ndn, int sub );
int (*register_subsys)( monitor_subsys_t *ms );
+ int (*register_backend)( BackendInfo *bi );
+ int (*register_database)( BackendDB *be );
+ int (*register_overlay_info)( slap_overinst *on );
+ int (*register_overlay)( BackendDB *be );
int (*register_entry)( Entry *e, monitor_callback_t *cb,
monitor_subsys_t *ms, unsigned long flags );
int (*register_entry_parent)( Entry *e, monitor_callback_t *cb,
{
Debug(LDAP_DEBUG_ARGS, "==> monitor_back_bind: dn: %s\n",
op->o_req_dn.bv_val, 0, 0 );
-
- if ( op->oq_bind.rb_method == LDAP_AUTH_SIMPLE
- && be_isroot_pw( op ) )
- {
- ber_dupbv( &op->oq_bind.rb_edn, be_root_dn( op->o_bd ) );
+
+ if ( be_isroot_pw( op ) ) {
return LDAP_SUCCESS;
}
#include "back-monitor.h"
int
-monitor_back_compare( struct slap_op *op, struct slap_rep *rs)
+monitor_back_compare( Operation *op, SlapReply *rs )
{
monitor_info_t *mi = ( monitor_info_t * ) op->o_bd->be_private;
Entry *e, *matched = NULL;
return 0;
}
+int
+monitor_back_register_database(
+ BackendDB *be )
+{
+ monitor_info_t *mi;
+ Entry *e_database, **ep;
+ int i, rc;
+ monitor_entry_t *mp;
+ monitor_subsys_t *ms_backend,
+ *ms_database,
+ *ms_overlay;
+ struct berval bv;
+ char buf[ BACKMONITOR_BUFSIZE ];
+
+ assert( be_monitor != NULL );
+
+ if ( !monitor_subsys_is_opened() ) {
+ return monitor_back_register_database_limbo( be );
+ }
+
+ mi = ( monitor_info_t * )be_monitor->be_private;
+
+ ms_backend = monitor_back_get_subsys( SLAPD_MONITOR_BACKEND_NAME );
+ if ( ms_backend == NULL ) {
+ Debug( LDAP_DEBUG_ANY,
+ "monitor_back_register_database: "
+ "unable to get "
+ "\"" SLAPD_MONITOR_BACKEND_NAME "\" "
+ "subsystem\n",
+ 0, 0, 0 );
+ return -1;
+ }
+
+ ms_database = monitor_back_get_subsys( SLAPD_MONITOR_DATABASE_NAME );
+ if ( ms_database == NULL ) {
+ Debug( LDAP_DEBUG_ANY,
+ "monitor_back_register_database: "
+ "unable to get "
+ "\"" SLAPD_MONITOR_DATABASE_NAME "\" "
+ "subsystem\n",
+ 0, 0, 0 );
+ return -1;
+ }
+
+ ms_overlay = monitor_back_get_subsys( SLAPD_MONITOR_OVERLAY_NAME );
+ if ( ms_overlay == NULL ) {
+ Debug( LDAP_DEBUG_ANY,
+ "monitor_back_register_database: "
+ "unable to get "
+ "\"" SLAPD_MONITOR_OVERLAY_NAME "\" "
+ "subsystem\n",
+ 0, 0, 0 );
+ return -1;
+ }
+
+ if ( monitor_cache_get( mi, &ms_database->mss_ndn, &e_database ) ) {
+ Debug( LDAP_DEBUG_ANY,
+ "monitor_subsys_database_init: "
+ "unable to get entry \"%s\"\n",
+ ms_database->mss_ndn.bv_val, 0, 0 );
+ return( -1 );
+ }
+
+ mp = ( monitor_entry_t * )e_database->e_private;
+ for ( i = -1, ep = &mp->mp_children; *ep; i++ ) {
+ Attribute *a;
+
+ a = attr_find( (*ep)->e_attrs, slap_schema.si_ad_namingContexts );
+ if ( a ) {
+ int j, k;
+
+ for ( j = 0; !BER_BVISNULL( &a->a_nvals[ j ] ); j++ ) {
+ for ( k = 0; !BER_BVISNULL( &be->be_nsuffix[ k ] ); k++ ) {
+ if ( dn_match( &a->a_nvals[ j ], &be->be_nsuffix[ k ] ) ) {
+ rc = 0;
+ goto done;
+ }
+ }
+ }
+ }
+
+ mp = ( monitor_entry_t * )(*ep)->e_private;
+
+ assert( mp != NULL );
+ ep = &mp->mp_next;
+ }
+
+ bv.bv_val = buf;
+ bv.bv_len = snprintf( buf, sizeof( buf ), "cn=Database %d", i );
+ if ( bv.bv_len >= sizeof( buf ) ) {
+ rc = -1;
+ goto done;
+ }
+
+ rc = monitor_subsys_database_init_one( mi, be,
+ ms_database, ms_backend, ms_overlay, &bv, e_database, &ep );
+ if ( rc != 0 ) {
+ goto done;
+ }
+
+done:;
+ monitor_cache_release( mi, e_database );
+
+ return rc;
+}
+
int
monitor_subsys_database_init(
BackendDB *be,
monitor_back_get_subsys_by_dn,
monitor_back_register_subsys,
+ monitor_back_register_backend,
+ monitor_back_register_database,
+ monitor_back_register_overlay_info,
+ monitor_back_register_overlay,
monitor_back_register_entry,
monitor_back_register_entry_parent,
monitor_back_register_entry_attrs,
}, { NULL }
};
+int
+monitor_subsys_is_opened( void )
+{
+ return monitor_subsys_opened;
+}
+
int
monitor_back_register_subsys(
monitor_subsys_t *ms )
/* if a subsystem is registered __AFTER__ subsystem
* initialization (depending on the sequence the databases
* are listed in slapd.conf), init it */
- if ( monitor_subsys_opened ) {
+ if ( monitor_subsys_is_opened() ) {
/* FIXME: this should only be possible
* if be_monitor is already initialized */
LIMBO_ENTRY,
LIMBO_ENTRY_PARENT,
LIMBO_ATTRS,
- LIMBO_CB
+ LIMBO_CB,
+ LIMBO_BACKEND,
+ LIMBO_DATABASE,
+ LIMBO_OVERLAY_INFO,
+ LIMBO_OVERLAY,
+
+ LIMBO_LAST
};
typedef struct entry_limbo_t {
int el_type;
+ BackendInfo *el_bi;
+ BackendDB *el_be;
+ slap_overinst *el_on;
Entry *el_e;
Attribute *el_a;
struct berval el_ndn;
return be_monitor != NULL;
}
+int
+monitor_back_register_backend(
+ BackendInfo *bi )
+{
+ return -1;
+}
+
+int
+monitor_back_register_overlay_info(
+ slap_overinst *on )
+{
+ return -1;
+}
+
+int
+monitor_back_register_overlay(
+ BackendDB *be )
+{
+ return -1;
+}
+
+int
+monitor_back_register_backend_limbo(
+ BackendInfo *bi )
+{
+ return -1;
+}
+
+int
+monitor_back_register_database_limbo(
+ BackendDB *be )
+{
+ entry_limbo_t **elpp, el = { 0 };
+ monitor_info_t *mi;
+
+ if ( be_monitor == NULL ) {
+ Debug( LDAP_DEBUG_ANY,
+ "monitor_back_register_database_limbo: "
+ "monitor database not configured.\n",
+ 0, 0, 0 );
+ return -1;
+ }
+
+ mi = ( monitor_info_t * )be_monitor->be_private;
+
+
+ el.el_type = LIMBO_DATABASE;
+
+ el.el_be = be;
+
+ for ( elpp = &mi->mi_entry_limbo;
+ *elpp;
+ elpp = &(*elpp)->el_next )
+ /* go to last */;
+
+ *elpp = (entry_limbo_t *)ch_malloc( sizeof( entry_limbo_t ) );
+
+ el.el_next = NULL;
+ **elpp = el;
+
+ return 0;
+}
+
+int
+monitor_back_register_overlay_info_limbo(
+ slap_overinst *on )
+{
+ return -1;
+}
+
+int
+monitor_back_register_overlay_limbo(
+ BackendDB *be )
+{
+ return -1;
+}
+
int
monitor_back_register_entry(
Entry *e,
assert( e != NULL );
assert( e->e_private == NULL );
- if ( monitor_subsys_opened ) {
+ if ( monitor_subsys_is_opened() ) {
Entry *e_parent = NULL,
*e_new = NULL,
**ep = NULL;
el.el_mss = mss;
el.el_flags = flags;
- for ( elpp = (entry_limbo_t **)&mi->mi_entry_limbo;
+ for ( elpp = &mi->mi_entry_limbo;
*elpp;
elpp = &(*elpp)->el_next )
/* go to last */;
return -1;
}
- if ( monitor_subsys_opened ) {
+ if ( monitor_subsys_is_opened() ) {
Entry *e_parent = NULL,
*e_new = NULL,
**ep = NULL;
el.el_mss = mss;
el.el_flags = flags;
- for ( elpp = (entry_limbo_t **)&mi->mi_entry_limbo;
+ for ( elpp = &mi->mi_entry_limbo;
*elpp;
elpp = &(*elpp)->el_next )
/* go to last */;
return -1;
}
- op = (Operation *) &opbuf;
thrctx = ldap_pvt_thread_pool_context();
- connection_fake_init( &conn, op, thrctx );
+ connection_fake_init( &conn, &opbuf, thrctx );
+ op = &opbuf.ob_op;
op->o_tag = LDAP_REQ_SEARCH;
return -1;
}
- if ( monitor_subsys_opened ) {
+ if ( monitor_subsys_is_opened() ) {
Entry *e = NULL;
Attribute **atp = NULL;
monitor_entry_t *mp = NULL;
el.el_a = attrs_dup( a );
el.el_cb = cb;
- for ( elpp = (entry_limbo_t **)&mi->mi_entry_limbo;
+ for ( elpp = &mi->mi_entry_limbo;
*elpp;
elpp = &(*elpp)->el_next )
/* go to last */;
assert( mi != NULL );
- if ( monitor_subsys_opened ) {
+ if ( monitor_subsys_is_opened() ) {
Entry *e = NULL;
monitor_entry_t *mp = NULL;
monitor_callback_t *cb = NULL;
} else {
entry_limbo_t **elpp;
- for ( elpp = (entry_limbo_t **)&mi->mi_entry_limbo;
+ for ( elpp = &mi->mi_entry_limbo;
*elpp;
elpp = &(*elpp)->el_next )
{
for ( cb = elp->el_cb; cb; cb = next ) {
/* FIXME: call callbacks? */
next = cb->mc_next;
+ if ( cb->mc_dispose ) {
+ cb->mc_dispose( &cb->mc_private );
+ }
ch_free( cb );
}
assert( elp->el_e != NULL );
return -1;
}
- if ( monitor_subsys_opened ) {
+ if ( monitor_subsys_is_opened() ) {
Entry *e = NULL;
monitor_entry_t *mp = NULL;
} else {
entry_limbo_t **elpp;
- for ( elpp = (entry_limbo_t **)&mi->mi_entry_limbo;
+ for ( elpp = &mi->mi_entry_limbo;
*elpp;
elpp = &(*elpp)->el_next )
{
for ( cb = elp->el_cb; cb; cb = next ) {
/* FIXME: call callbacks? */
next = cb->mc_next;
+ if ( cb->mc_dispose ) {
+ cb->mc_dispose( &cb->mc_private );
+ }
ch_free( cb );
}
assert( elp->el_e != NULL );
return -1;
}
- if ( monitor_subsys_opened ) {
+ if ( monitor_subsys_is_opened() ) {
Entry *e = NULL;
monitor_entry_t *mp = NULL;
int freeit = 0;
ber_memfree( ndn.bv_val );
}
- if ( e ) {
- monitor_cache_release( mi, e );
- }
+ monitor_cache_release( mi, e );
} else {
entry_limbo_t **elpp;
- for ( elpp = (entry_limbo_t **)&mi->mi_entry_limbo;
+ for ( elpp = &mi->mi_entry_limbo;
*elpp;
elpp = &(*elpp)->el_next )
{
for ( cb = elp->el_cb; cb; cb = next ) {
/* FIXME: call callbacks? */
next = cb->mc_next;
+ if ( cb->mc_dispose ) {
+ cb->mc_dispose( &cb->mc_private );
+ }
ch_free( cb );
}
assert( elp->el_e == NULL );
bi->bi_tool_entry_reindex = 0;
bi->bi_tool_sync = 0;
bi->bi_tool_dn2id_get = 0;
- bi->bi_tool_id2entry_get = 0;
bi->bi_tool_entry_modify = 0;
bi->bi_connection_init = 0;
int
monitor_back_db_init(
- BackendDB *be )
+ BackendDB *be,
+ ConfigReply *c)
{
int rc;
struct berval dn = BER_BVC( SLAPD_MONITOR_DN ),
monitor_subsys_t *ms;
/*
- * register subsys
+ * database monitor can be defined once only
*/
- for ( ms = known_monitor_subsys; ms->mss_name != NULL; ms++ ) {
- if ( monitor_back_register_subsys( ms ) ) {
- return -1;
+ if ( be_monitor != NULL ) {
+ if (c) {
+ snprintf(c->msg, sizeof(c->msg),"only one monitor database allowed");
}
+ return( -1 );
}
+ be_monitor = be;
/*
- * database monitor can be defined once only
+ * register subsys
*/
- if ( be_monitor != NULL ) {
- Debug( LDAP_DEBUG_ANY,
- "only one monitor database is allowed\n", 0, 0, 0 );
- return( -1 );
+ for ( ms = known_monitor_subsys; ms->mss_name != NULL; ms++ ) {
+ if ( monitor_back_register_subsys( ms ) ) {
+ return -1;
+ }
}
- be_monitor = be;
/* indicate system schema supported */
SLAP_BFLAGS(be) |= SLAP_BFLAG_MONITOR;
be->be_private = &monitor_info;
- be2 = select_backend( &ndn, 0, 0 );
+ be2 = select_backend( &ndn, 0 );
if ( be2 != be ) {
char *type = be2->bd_info->bi_type;
type = oi->oi_orig->bi_type;
}
- Debug( LDAP_DEBUG_ANY,
- "\"monitor\" database serving namingContext \"%s\" "
- "is hidden by \"%s\" database serving namingContext \"%s\".\n",
- pdn.bv_val, type, be2->be_nsuffix[ 0 ].bv_val );
+ if (c) {
+ snprintf(c->msg, sizeof(c->msg),
+ "\"monitor\" database serving namingContext \"%s\" "
+ "is hidden by \"%s\" database serving namingContext \"%s\".\n",
+ pdn.bv_val, type, be2->be_nsuffix[ 0 ].bv_val );
+ }
return -1;
}
return 0;
}
+static void
+monitor_back_destroy_limbo_entry(
+ entry_limbo_t *el,
+ int dispose )
+{
+ if ( el->el_e ) {
+ entry_free( el->el_e );
+ }
+ if ( el->el_a ) {
+ attrs_free( el->el_a );
+ }
+ if ( !BER_BVISNULL( &el->el_ndn ) ) {
+ ber_memfree( el->el_ndn.bv_val );
+ }
+ if ( !BER_BVISNULL( &el->el_nbase ) ) {
+ ber_memfree( el->el_nbase.bv_val );
+ }
+ if ( !BER_BVISNULL( &el->el_filter ) ) {
+ ber_memfree( el->el_filter.bv_val );
+ }
+
+ /* NOTE: callbacks are not copied; so only free them
+ * if disposing of */
+ if ( el->el_cb && dispose != 0 ) {
+ monitor_callback_t *next;
+
+ for ( ; el->el_cb; el->el_cb = next ) {
+ next = el->el_cb->mc_next;
+ if ( el->el_cb->mc_dispose ) {
+ el->el_cb->mc_dispose( &el->el_cb->mc_private );
+ }
+ ch_free( el->el_cb );
+ }
+ }
+
+ ch_free( el );
+}
+
int
monitor_back_db_open(
- BackendDB *be )
+ BackendDB *be,
+ ConfigReply *cr)
{
monitor_info_t *mi = (monitor_info_t *)be->be_private;
struct monitor_subsys_t **ms;
" attributes, which must be explicitly requested."),
BER_BVNULL };
+ int retcode = 0;
+
assert( be_monitor != NULL );
if ( be != be_monitor ) {
be_monitor = be;
monitor_subsys_opened = 1;
if ( mi->mi_entry_limbo ) {
- entry_limbo_t *el = (entry_limbo_t *)mi->mi_entry_limbo;
+ entry_limbo_t *el = mi->mi_entry_limbo;
for ( ; el; ) {
entry_limbo_t *tmp;
&el->el_filter );
break;
+ case LIMBO_BACKEND:
+ rc = monitor_back_register_backend( el->el_bi );
+ break;
+
+ case LIMBO_DATABASE:
+ rc = monitor_back_register_database( el->el_be );
+ break;
+
+ case LIMBO_OVERLAY_INFO:
+ rc = monitor_back_register_overlay_info( el->el_on );
+ break;
+
+ case LIMBO_OVERLAY:
+ rc = monitor_back_register_overlay( el->el_be );
+ break;
+
default:
assert( 0 );
}
- if ( el->el_e ) {
- entry_free( el->el_e );
- }
- if ( el->el_a ) {
- attrs_free( el->el_a );
- }
- if ( !BER_BVISNULL( &el->el_ndn ) ) {
- ber_memfree( el->el_ndn.bv_val );
- }
- if ( !BER_BVISNULL( &el->el_nbase ) ) {
- ber_memfree( el->el_nbase.bv_val );
- }
- if ( !BER_BVISNULL( &el->el_filter ) ) {
- ber_memfree( el->el_filter.bv_val );
- }
- if ( el->el_cb && rc != 0 ) {
- if ( el->el_cb->mc_dispose ) {
- el->el_cb->mc_dispose( &el->el_cb->mc_private );
- }
- ch_free( el->el_cb );
- }
-
tmp = el;
el = el->el_next;
- ch_free( tmp );
+ monitor_back_destroy_limbo_entry( tmp, rc );
+
+ if ( rc != 0 ) {
+ /* try all, but report error at end */
+ retcode = 1;
+ }
}
mi->mi_entry_limbo = NULL;
}
- return( 0 );
+ return retcode;
}
int
int
monitor_back_db_destroy(
- BackendDB *be )
+ BackendDB *be,
+ ConfigReply *cr)
{
monitor_info_t *mi = ( monitor_info_t * )be->be_private;
ch_free( monitor_subsys );
}
+
+ if ( mi->mi_entry_limbo ) {
+ entry_limbo_t *el = mi->mi_entry_limbo;
+
+ for ( ; el; ) {
+ entry_limbo_t *tmp = el;
+ el = el->el_next;
+ monitor_back_destroy_limbo_entry( tmp, 1 );
+ }
+ }
ldap_pvt_thread_mutex_destroy( &monitor_info.mi_cache_mutex );
int rc = LDAP_OTHER;
int newlevel = ldap_syslog;
Attribute *save_attrs;
- Modifications *modlist = op->oq_modify.rs_modlist;
+ Modifications *modlist = op->orm_modlist;
Modifications *ml;
ldap_pvt_thread_mutex_lock( &monitor_log_mutex );
return rs->sr_err;
}
- if ( !acl_check_modlist( op, e, op->oq_modify.rs_modlist )) {
+ if ( !acl_check_modlist( op, e, op->orm_modlist )) {
rc = LDAP_INSUFFICIENT_ACCESS;
} else {
} monitor_op[] = {
{ BER_BVC( "cn=Bind" ), BER_BVNULL },
{ BER_BVC( "cn=Unbind" ), BER_BVNULL },
+ { BER_BVC( "cn=Search" ), BER_BVNULL },
+ { BER_BVC( "cn=Compare" ), BER_BVNULL },
+ { BER_BVC( "cn=Modify" ), BER_BVNULL },
+ { BER_BVC( "cn=Modrdn" ), BER_BVNULL },
{ BER_BVC( "cn=Add" ), BER_BVNULL },
{ BER_BVC( "cn=Delete" ), BER_BVNULL },
- { BER_BVC( "cn=Modrdn" ), BER_BVNULL },
- { BER_BVC( "cn=Modify" ), BER_BVNULL },
- { BER_BVC( "cn=Compare" ), BER_BVNULL },
- { BER_BVC( "cn=Search" ), BER_BVNULL },
{ BER_BVC( "cn=Abandon" ), BER_BVNULL },
{ BER_BVC( "cn=Extended" ), BER_BVNULL },
{ BER_BVNULL, BER_BVNULL }
* init
*/
extern int
+monitor_subsys_is_opened LDAP_P((
+ void ));
+extern int
monitor_back_register_subsys LDAP_P((
monitor_subsys_t *ms ));
+extern int
+monitor_back_register_backend LDAP_P((
+ BackendInfo *bi ));
+extern int
+monitor_back_register_database LDAP_P((
+ BackendDB *be ));
+extern int
+monitor_back_register_overlay_info LDAP_P((
+ slap_overinst *on ));
+extern int
+monitor_back_register_overlay LDAP_P((
+ BackendDB *be ));
+extern int
+monitor_back_register_backend_limbo LDAP_P((
+ BackendInfo *bi ));
+extern int
+monitor_back_register_database_limbo LDAP_P((
+ BackendDB *be ));
+extern int
+monitor_back_register_overlay_info_limbo LDAP_P((
+ slap_overinst *on ));
+extern int
+monitor_back_register_overlay_limbo LDAP_P((
+ BackendDB *be ));
extern monitor_subsys_t *
monitor_back_get_subsys LDAP_P((
const char *name ));
Entry *e, **ep, *e_time;
monitor_entry_t *mp;
- struct berval bv;
+ struct berval bv, value;
assert( be != NULL );
if ( e == NULL ) {
Debug( LDAP_DEBUG_ANY,
"monitor_subsys_time_init: "
- "unable to create entry \"cn=Start,%s\"\n",
- ms->mss_ndn.bv_val, 0, 0 );
+ "unable to create entry \"%s,%s\"\n",
+ bv.bv_val, ms->mss_ndn.bv_val, 0 );
return( -1 );
}
attr_merge_normalize_one( e, mi->mi_ad_monitorTimestamp,
if ( monitor_cache_add( mi, e ) ) {
Debug( LDAP_DEBUG_ANY,
"monitor_subsys_time_init: "
- "unable to add entry \"cn=Start,%s\"\n",
- ms->mss_ndn.bv_val, 0, 0 );
+ "unable to add entry \"%s,%s\"\n",
+ bv.bv_val, ms->mss_ndn.bv_val, 0 );
return( -1 );
}
if ( e == NULL ) {
Debug( LDAP_DEBUG_ANY,
"monitor_subsys_time_init: "
- "unable to create entry \"cn=Current,%s\"\n",
- ms->mss_ndn.bv_val, 0, 0 );
+ "unable to create entry \"%s,%s\"\n",
+ bv.bv_val, ms->mss_ndn.bv_val, 0 );
return( -1 );
}
attr_merge_normalize_one( e, mi->mi_ad_monitorTimestamp,
if ( monitor_cache_add( mi, e ) ) {
Debug( LDAP_DEBUG_ANY,
"monitor_subsys_time_init: "
- "unable to add entry \"cn=Current,%s\"\n",
- ms->mss_ndn.bv_val, 0, 0 );
+ "unable to add entry \"%s,%s\"\n",
+ bv.bv_val, ms->mss_ndn.bv_val, 0 );
+ return( -1 );
+ }
+
+ *ep = e;
+ ep = &mp->mp_next;
+
+ /*
+ * Uptime
+ */
+ BER_BVSTR( &bv, "cn=Uptime" );
+ e = monitor_entry_stub( &ms->mss_dn, &ms->mss_ndn, &bv,
+ mi->mi_oc_monitoredObject, mi, NULL, NULL );
+ if ( e == NULL ) {
+ Debug( LDAP_DEBUG_ANY,
+ "monitor_subsys_time_init: "
+ "unable to create entry \"%s,%s\"\n",
+ bv.bv_val, ms->mss_ndn.bv_val, 0 );
+ return( -1 );
+ }
+ BER_BVSTR( &value, "0" );
+ attr_merge_normalize_one( e, mi->mi_ad_monitoredInfo,
+ &value, NULL );
+
+ mp = monitor_entrypriv_create();
+ if ( mp == NULL ) {
+ return -1;
+ }
+ e->e_private = ( void * )mp;
+ mp->mp_info = ms;
+ mp->mp_flags = ms->mss_flags \
+ | MONITOR_F_SUB | MONITOR_F_PERSISTENT;
+
+ if ( monitor_cache_add( mi, e ) ) {
+ Debug( LDAP_DEBUG_ANY,
+ "monitor_subsys_time_init: "
+ "unable to add entry \"%s,%s\"\n",
+ bv.bv_val, ms->mss_ndn.bv_val, 0 );
return( -1 );
}
Entry *e )
{
monitor_info_t *mi = ( monitor_info_t * )op->o_bd->be_private;
- static struct berval bv_current = BER_BVC( "cn=current" );
+ static struct berval bv_current = BER_BVC( "cn=current" ),
+ bv_uptime = BER_BVC( "cn=uptime" );
struct berval rdn;
assert( mi != NULL );
assert( len == a->a_vals[ 0 ].bv_len );
AC_MEMCPY( a->a_vals[ 0 ].bv_val, tmbuf, len );
+ /* FIXME: touch modifyTimestamp? */
+
+ } else if ( dn_match( &rdn, &bv_uptime ) ) {
+ Attribute *a;
+ double diff;
+ char buf[ BACKMONITOR_BUFSIZE ];
+ struct berval bv;
+
+ a = attr_find( e->e_attrs, mi->mi_ad_monitoredInfo );
+ if ( a == NULL ) {
+ return rs->sr_err = LDAP_OTHER;
+ }
+
+ diff = difftime( slap_get_time(), starttime );
+ bv.bv_len = snprintf( buf, sizeof( buf ), "%lu",
+ (unsigned long) diff );
+ bv.bv_val = buf;
+
+ ber_bvreplace( &a->a_vals[ 0 ], &bv );
+ if ( a->a_nvals != a->a_vals ) {
+ ber_bvreplace( &a->a_nvals[ 0 ], &bv );
+ }
+
/* FIXME: touch modifyTimestamp? */
}
#include <ac/string.h>
#include "slap.h"
+#include "config.h"
struct null_info {
int ni_bind_allowed;
}
+/* for overlays */
+int null_back_entry_get(
+ Operation *op,
+ struct berval *ndn,
+ ObjectClass *oc,
+ AttributeDescription *at,
+ int rw,
+ Entry **ent )
+{
+ *ent = NULL;
+ return 1;
+}
+
+
/* Slap tools */
static int
}
static int
-null_back_db_init( BackendDB *be )
+null_back_db_init( BackendDB *be, ConfigReply *cr )
{
struct null_info *ni = ch_calloc( 1, sizeof(struct null_info) );
ni->ni_bind_allowed = 0;
}
static int
-null_back_db_destroy( Backend *be )
+null_back_db_destroy( Backend *be, ConfigReply *cr )
{
free( be->be_private );
return 0;
bi->bi_connection_init = 0;
bi->bi_connection_destroy = 0;
+ bi->bi_entry_get_rw = null_back_entry_get;
+
bi->bi_tool_entry_open = null_tool_entry_open;
bi->bi_tool_entry_close = null_tool_entry_close;
bi->bi_tool_entry_first = null_tool_entry_next;
#
# database perl
# suffix "o=AnyOrg,c=US"
-# perlModulePath /path/to/this/file
+# perlModulePath /directory/containing/this/module
# perlModule SampleLDAP
+#
+# See the slapd-perl(5) manual page for details.
package SampleLDAP;
-
+use strict;
+use warnings;
use POSIX;
-sub new
-{
- my $class = shift;
+$SampleLDAP::VERSION = '1.01';
+
+sub new {
+ my $class = shift;
- my $this = {};
- bless $this, $class;
- print STDERR "Here in new\n";
- print STDERR "Posix Var " . BUFSIZ . " and " . FILENAME_MAX . "\n";
- return $this;
+ my $this = {};
+ bless $this, $class;
+ print {*STDERR} "Here in new\n";
+ print {*STDERR} 'Posix Var ' . BUFSIZ . ' and ' . FILENAME_MAX . "\n";
+ return $this;
}
-sub init
-{
- return 0;
+sub init {
+ return 0;
}
-sub search
-{
- my $this = shift;
- my($base, $scope, $deref, $sizeLim, $timeLim, $filterStr, $attrOnly, @attrs ) = @_;
- print STDERR "====$filterStr====\n";
- $filterStr =~ s/\(|\)//g;
- $filterStr =~ s/=/: /;
+sub search {
+ my $this = shift;
+ my ( $base, $scope, $deref, $sizeLim, $timeLim, $filterStr, $attrOnly,
+ @attrs )
+ = @_;
+ print {*STDERR}, "====$filterStr====\n";
+ $filterStr =~ s/\(|\)//gm;
+ $filterStr =~ s/=/: /m;
- my @match_dn = ();
- foreach my $dn ( keys %$this ) {
- if ( $this->{ $dn } =~ /$filterStr/im ) {
- push @match_dn, $dn;
- last if ( scalar @match_dn == $sizeLim );
+ my @match_dn = ();
+ for my $dn ( keys %{$this} ) {
+ if ( $this->{$dn} =~ /$filterStr/imx ) {
+ push @match_dn, $dn;
+ last if ( scalar @match_dn == $sizeLim );
- }
- }
+ }
+ }
- my @match_entries = ();
-
- foreach my $dn ( @match_dn ) {
- push @match_entries, $this->{ $dn };
- }
+ my @match_entries = ();
- return ( 0 , @match_entries );
+ for my $dn (@match_dn) {
+ push @match_entries, $this->{$dn};
+ }
+
+ return ( 0, @match_entries );
}
-sub compare
-{
- my $this = shift;
- my ( $dn, $avaStr ) = @_;
- my $rc = 5; # LDAP_COMPARE_FALSE
+sub compare {
+ my $this = shift;
+ my ( $dn, $avaStr ) = @_;
+ my $rc = 5; # LDAP_COMPARE_FALSE
- $avaStr =~ s/=/: /;
+ $avaStr =~ s/=/: /m;
- if ( $this->{ $dn } =~ /$avaStr/im ) {
- $rc = 6; # LDAP_COMPARE_TRUE
- }
+ if ( $this->{$dn} =~ /$avaStr/im ) {
+ $rc = 6; # LDAP_COMPARE_TRUE
+ }
- return $rc;
+ return $rc;
}
-sub modify
-{
- my $this = shift;
+sub modify {
+ my $this = shift;
- my ( $dn, @list ) = @_;
+ my ( $dn, @list ) = @_;
- while ( @list > 0 ) {
- my $action = shift @list;
- my $key = shift @list;
- my $value = shift @list;
+ while ( @list > 0 ) {
+ my $action = shift @list;
+ my $key = shift @list;
+ my $value = shift @list;
- if( $action eq "ADD" ) {
- $this->{ $dn } .= "$key: $value\n";
+ if ( $action eq 'ADD' ) {
+ $this->{$dn} .= "$key: $value\n";
- }
- elsif( $action eq "DELETE" ) {
- $this->{ $dn } =~ s/^$key:\s*$value\n//mi ;
+ }
+ elsif ( $action eq 'DELETE' ) {
+ $this->{$dn} =~ s/^$key:\s*$value\n//im;
- }
- elsif( $action eq "REPLACE" ) {
- $this->{ $dn } =~ s/$key: .*$/$key: $value/im ;
- }
- }
+ }
+ elsif ( $action eq 'REPLACE' ) {
+ $this->{$dn} =~ s/$key: .*$/$key: $value/im;
+ }
+ }
- return 0;
+ return 0;
}
-sub add
-{
- my $this = shift;
-
- my ( $entryStr ) = @_;
+sub add {
+ my $this = shift;
- my ( $dn ) = ( $entryStr =~ /dn:\s(.*)$/m );
+ my ($entryStr) = @_;
- #
- # This needs to be here until a normalized dn is
- # passed to this routine.
- #
- $dn = uc( $dn );
- $dn =~ s/\s*//g;
+ my ($dn) = ( $entryStr =~ /dn:\s(.*)$/m );
+ #
+ # This needs to be here until a normalized dn is
+ # passed to this routine.
+ #
+ $dn = uc $dn;
+ $dn =~ s/\s*//gm;
- $this->{$dn} = $entryStr;
+ $this->{$dn} = $entryStr;
- return 0;
+ return 0;
}
-sub modrdn
-{
- my $this = shift;
+sub modrdn {
+ my $this = shift;
- my ( $dn, $newdn, $delFlag ) = @_;
+ my ( $dn, $newdn, $delFlag ) = @_;
- $this->{ $newdn } = $this->{ $dn };
+ $this->{$newdn} = $this->{$dn};
- if( $delFlag ) {
- delete $this->{ $dn };
- }
- return 0;
+ if ($delFlag) {
+ delete $this->{$dn};
+ }
+ return 0;
}
-sub delete
-{
- my $this = shift;
+sub delete {
+ my $this = shift;
+
+ my ($dn) = @_;
- my ( $dn ) = @_;
-
- print STDERR "XXXXXX $dn XXXXXXX\n";
- delete $this->{$dn};
+ print {*STDERR} "XXXXXX $dn XXXXXXX\n";
+ delete $this->{$dn};
+ return 0;
}
-sub config
-{
- my $this = shift;
+sub config {
+ my $this = shift;
- my ( @args ) = @_;
- local $, = " - ";
- print STDERR @args;
- print STDERR "\n";
- return 0;
+ my (@args) = @_;
+ local $, = ' - ';
+ print {*STDERR} @args;
+ print {*STDERR} "\n";
+ return 0;
}
1;
PerlBackend *perl_back = (PerlBackend *) op->o_bd->be_private;
+ /* allow rootdn as a means to auth without the need to actually
+ * contact the proxied DSA */
+ switch ( be_rootdn_bind( op, rs ) ) {
+ case SLAP_CB_CONTINUE:
+ break;
+
+ default:
+ return rs->sr_err;
+ }
+
#if defined(HAVE_WIN32_ASPERL) || defined(USE_ITHREADS)
PERL_SET_CONTEXT( PERL_INTERPRETER );
#endif
*/
#include "perl_back.h"
-
+#include "../config.h"
/**********************************************************
*
* Close
int
perl_back_db_destroy(
- BackendDB *be
+ BackendDB *be,
+ ConfigReply *cr
)
{
free( be->be_private );
*/
#include "perl_back.h"
+#include "../config.h"
static void perl_back_xs_init LDAP_P((PERL_BACK_XS_INIT_PARAMS));
EXT void boot_DynaLoader LDAP_P((PERL_BACK_BOOT_DYNALOADER_PARAMS));
int
perl_back_db_init(
- BackendDB *be
+ BackendDB *be,
+ ConfigReply *cr
)
{
be->be_private = (PerlBackend *) ch_malloc( sizeof(PerlBackend) );
int
perl_back_db_open(
- BackendDB *be
+ BackendDB *be,
+ ConfigReply *cr
)
{
int count;
## top-level directory of the distribution or, alternatively, at
## <http://www.OpenLDAP.org/license.html>.
-SRCS = init.c config.c op.c
-OBJS = init.lo config.lo op.lo
+SRCS = init.c op.c
+OBJS = init.lo op.lo
LDAP_INCDIR= ../../../include
LDAP_LIBDIR= ../../../libraries
+++ /dev/null
-/* config.c - relay backend configuration file routine */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 2004-2007 The OpenLDAP Foundation.
- * Portions Copyright 2004 Pierangelo Masarati.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted only as authorized by the OpenLDAP
- * Public License.
- *
- * A copy of this license is available in the file LICENSE in the
- * top-level directory of the distribution or, alternatively, at
- * <http://www.OpenLDAP.org/license.html>.
- */
-/* ACKNOWLEDGEMENTS:
- * This work was initially developed by Pierangelo Masaratifor inclusion
- * in OpenLDAP Software.
- */
-
-#include "portable.h"
-
-#include <stdio.h>
-
-#include "slap.h"
-#include "back-relay.h"
-
-int
-relay_back_db_config(
- BackendDB *be,
- const char *fname,
- int lineno,
- int argc,
- char **argv )
-{
- relay_back_info *ri = (struct relay_back_info *)be->be_private;
-
- if ( ri == NULL ) {
- Log2( LDAP_DEBUG_ANY, LDAP_LEVEL_ERR,
- "%s: line %d: relay backend info is null.\n",
- fname, lineno );
- return 1;
- }
-
- /* real naming context */
- if ( strcasecmp( argv[ 0 ], "relay" ) == 0 ) {
- struct berval dn, ndn, pdn;
- int rc;
- BackendDB *bd;
-
- switch ( argc ) {
- case 3:
- if ( strcmp( argv[ 2 ], "massage" ) != 0 ) {
- Log3( LDAP_DEBUG_ANY, LDAP_LEVEL_ERR,
- "%s: line %d: "
- "unknown arg[#2]=\"%s\" "
- "in \"relay <dn> [massage]\" line\n",
- fname, lineno, argv[ 2 ] );
- return 1;
- }
-
- if ( be->be_nsuffix == NULL ) {
- Log2( LDAP_DEBUG_ANY, LDAP_LEVEL_ERR,
- "%s: line %d: "
- "\"relay\" directive "
- "must appear after \"suffix\".\n",
- fname, lineno );
- return 1;
- }
-
- if ( !BER_BVISNULL( &be->be_nsuffix[ 1 ] ) ) {
- Log2( LDAP_DEBUG_ANY, LDAP_LEVEL_ERR,
- "%s: line %d: "
- "relayng of multiple suffix "
- "database not supported.\n",
- fname, lineno );
- return 1;
- }
- /* fallthru */
-
- case 2:
- break;
-
- case 1:
- Log2( LDAP_DEBUG_ANY, LDAP_LEVEL_ERR,
- "%s: line %d: missing relay suffix "
- "in \"relay <dn> [massage]\" line.\n",
- fname, lineno );
- return 1;
-
- default:
- Log2( LDAP_DEBUG_ANY, LDAP_LEVEL_ERR,
- "%s: line %d: extra cruft "
- "in \"relay <dn> [massage]\" line.\n",
- fname, lineno );
- return 1;
- }
-
- if ( !BER_BVISNULL( &ri->ri_realsuffix ) ) {
- Log2( LDAP_DEBUG_ANY, LDAP_LEVEL_ERR,
- "%s: line %d: "
- "relay dn already specified.\n",
- fname, lineno );
- return 1;
- }
-
- /* The man page says that the "relay" directive
- * automatically instantiates slapo-rwm; I don't
- * like this very much any more, I'd prefer to
- * have automatic instantiation only when "massage"
- * is specified, so one has better control on
- * where the overlay gets instantiated, but this
- * would break compatibility. One can still control
- * where the overlay is instantiated by moving
- * around the "relay" directive, although this could
- * make slapd.conf a bit confusing. */
- if ( overlay_config( be, "rwm", -1, NULL ) ) {
- Log2( LDAP_DEBUG_ANY, LDAP_LEVEL_ERR,
- "%s: line %d: unable to install "
- "rwm overlay "
- "in \"relay <dn> [massage]\" line\n",
- fname, lineno );
- return 1;
- }
-
- dn.bv_val = argv[ 1 ];
- dn.bv_len = strlen( argv[ 1 ] );
- rc = dnPrettyNormal( NULL, &dn, &pdn, &ndn, NULL );
- if ( rc != LDAP_SUCCESS ) {
- Log3( LDAP_DEBUG_ANY, LDAP_LEVEL_ERR,
- "%s: line %d: "
- "relay dn \"%s\" is invalid "
- "in \"relay <dn> [massage]\" line\n",
- fname, lineno, argv[ 1 ] );
- return 1;
- }
-
- bd = select_backend( &ndn, 0, 1 );
- if ( bd == NULL ) {
- Log3( LDAP_DEBUG_ANY, LDAP_LEVEL_ERR,
- "%s: line %d: "
- "cannot find database "
- "of relay dn \"%s\" "
- "in \"relay <dn> [massage]\" line\n",
- fname, lineno, argv[ 1 ] );
- rc = 1;
- goto relay_done;
-
- } else if ( bd->be_private == be->be_private ) {
- Log3( LDAP_DEBUG_ANY, LDAP_LEVEL_ERR,
- "%s: line %d: "
- "relay dn \"%s\" would call self "
- "in \"relay <dn> [massage]\" line\n",
- fname, lineno, pdn.bv_val );
- rc = 1;
- goto relay_done;
- }
-
- ri->ri_realsuffix = ndn;
-
- if ( argc == 3 ) {
- char *cargv[ 4 ];
-
- cargv[ 0 ] = "rwm-suffixmassage";
- cargv[ 1 ] = be->be_suffix[0].bv_val;
- cargv[ 2 ] = pdn.bv_val;
- cargv[ 3 ] = NULL;
-
- rc = be->be_config( be, fname, lineno, 3, cargv );
- }
-
-relay_done:;
- ch_free( pdn.bv_val );
-
- return rc;
- }
-
- /* anything else */
- return SLAP_CONF_UNKNOWN;
-}
-
#include <ac/string.h>
#include "slap.h"
+#include "config.h"
#include "back-relay.h"
+static ConfigDriver relay_back_cf;
+
+static ConfigTable relaycfg[] = {
+ { "relay", "relay", 2, 2, 0,
+ ARG_MAGIC|ARG_DN,
+ relay_back_cf, "( OLcfgDbAt:5.1 "
+ "NAME 'olcRelay' "
+ "DESC 'Relay DN' "
+ "SYNTAX OMsDN "
+ "SINGLE-VALUE )",
+ NULL, NULL },
+ { NULL }
+};
+
+static ConfigOCs relayocs[] = {
+ { "( OLcfgDbOc:5.1 "
+ "NAME 'olcRelayConfig' "
+ "DESC 'Relay backend configuration' "
+ "SUP olcDatabaseConfig "
+ "MAY ( olcRelay "
+ ") )",
+ Cft_Database, relaycfg},
+ { NULL, 0, NULL }
+};
+
+static int
+relay_back_cf( ConfigArgs *c )
+{
+ relay_back_info *ri = ( relay_back_info * )c->be->be_private;
+ int rc = 0;
+
+ if ( c->op == SLAP_CONFIG_EMIT ) {
+ if ( ri != NULL && !BER_BVISNULL( &ri->ri_realsuffix ) ) {
+ value_add_one( &c->rvalue_vals, &ri->ri_realsuffix );
+ return 0;
+ }
+ return 1;
+
+ } else if ( c->op == LDAP_MOD_DELETE ) {
+ if ( !BER_BVISNULL( &ri->ri_realsuffix ) ) {
+ ch_free( ri->ri_realsuffix.bv_val );
+ BER_BVZERO( &ri->ri_realsuffix );
+ ri->ri_bd = NULL;
+ return 0;
+ }
+ return 1;
+
+ } else {
+ BackendDB *bd;
+
+ assert( ri != NULL );
+ assert( BER_BVISNULL( &ri->ri_realsuffix ) );
+
+ if ( c->be->be_nsuffix == NULL ) {
+ snprintf( c->cr_msg, sizeof( c->cr_msg),
+ "\"relay\" directive "
+ "must appear after \"suffix\"" );
+ Log2( LDAP_DEBUG_ANY, LDAP_LEVEL_ERR,
+ "%s: %s.\n", c->log, c->cr_msg );
+ rc = 1;
+ goto relay_done;
+ }
+
+ if ( !BER_BVISNULL( &c->be->be_nsuffix[ 1 ] ) ) {
+ snprintf( c->cr_msg, sizeof( c->cr_msg),
+ "relaying of multiple suffix "
+ "database not supported" );
+ Log2( LDAP_DEBUG_ANY, LDAP_LEVEL_ERR,
+ "%s: %s.\n", c->log, c->cr_msg );
+ rc = 1;
+ goto relay_done;
+ }
+
+ bd = select_backend( &c->value_ndn, 1 );
+ if ( bd == NULL ) {
+ snprintf( c->cr_msg, sizeof( c->cr_msg),
+ "cannot find database "
+ "of relay dn \"%s\" "
+ "in \"olcRelay <dn>\"\n",
+ c->value_dn.bv_val );
+ Log2( LDAP_DEBUG_ANY, LDAP_LEVEL_ERR,
+ "%s: %s.\n", c->log, c->cr_msg );
+ rc = 1;
+ goto relay_done;
+
+ } else if ( bd->be_private == c->be->be_private ) {
+ snprintf( c->cr_msg, sizeof( c->cr_msg),
+ "relay dn \"%s\" would call self "
+ "in \"relay <dn>\" line\n",
+ c->value_dn.bv_val );
+ Log2( LDAP_DEBUG_ANY, LDAP_LEVEL_ERR,
+ "%s: %s.\n", c->log, c->cr_msg );
+ rc = 1;
+ goto relay_done;
+ }
+
+ ri->ri_realsuffix = c->value_ndn;
+ BER_BVZERO( &c->value_ndn );
+
+relay_done:;
+ ch_free( c->value_dn.bv_val );
+ ch_free( c->value_ndn.bv_val );
+ }
+
+ return rc;
+}
+
int
relay_back_initialize( BackendInfo *bi )
{
bi->bi_destroy = 0;
bi->bi_db_init = relay_back_db_init;
- bi->bi_db_config = relay_back_db_config;
+ bi->bi_db_config = config_generic_wrapper;
bi->bi_db_open = relay_back_db_open;
#if 0
- bi->bi_db_close =relay_back_db_close;
+ bi->bi_db_close = relay_back_db_close;
#endif
bi->bi_db_destroy = relay_back_db_destroy;
bi->bi_connection_init = relay_back_connection_init;
bi->bi_connection_destroy = relay_back_connection_destroy;
- return 0;
+ bi->bi_cf_ocs = relayocs;
+
+ return config_register_schema( relaycfg, relayocs );
}
int
-relay_back_db_init( Backend *be )
+relay_back_db_init( Backend *be, ConfigReply *cr)
{
relay_back_info *ri;
BER_BVZERO( &ri->ri_realsuffix );
ri->ri_massage = 0;
+ be->be_cf_ocs = be->bd_info->bi_cf_ocs;
+
be->be_private = (void *)ri;
return 0;
}
int
-relay_back_db_open( Backend *be )
+relay_back_db_open( Backend *be, ConfigReply *cr )
{
relay_back_info *ri = (relay_back_info *)be->be_private;
assert( ri != NULL );
if ( !BER_BVISNULL( &ri->ri_realsuffix ) ) {
- ri->ri_bd = select_backend( &ri->ri_realsuffix, 0, 1 );
+ ri->ri_bd = select_backend( &ri->ri_realsuffix, 1 );
/* must be there: it was during config! */
assert( ri->ri_bd != NULL );
}
int
-relay_back_db_close( Backend *be )
+relay_back_db_close( Backend *be, ConfigReply *cr )
{
return 0;
}
int
-relay_back_db_destroy( Backend *be )
+relay_back_db_destroy( Backend *be, ConfigReply *cr)
{
relay_back_info *ri = (relay_back_info *)be->be_private;
#include "back-relay.h"
static int
-relay_back_swap_bd( struct slap_op *op, struct slap_rep *rs )
+relay_back_swap_bd( Operation *op, SlapReply *rs )
{
slap_callback *cb = op->o_callback;
BackendDB *be = op->o_bd;
}
static void
-relay_back_add_cb( slap_callback *cb, struct slap_op *op )
+relay_back_add_cb( slap_callback *cb, Operation *op )
{
cb->sc_next = op->o_callback;
cb->sc_response = relay_back_swap_bd;
* any valid error send as error result
*/
static BackendDB *
-relay_back_select_backend( struct slap_op *op, struct slap_rep *rs, int err )
+relay_back_select_backend( Operation *op, SlapReply *rs, int err, int dosend )
{
relay_back_info *ri = (relay_back_info *)op->o_bd->be_private;
BackendDB *bd = ri->ri_bd;
- if ( bd == NULL ) {
- bd = select_backend( &op->o_req_ndn, 0, 1 );
+ if ( bd == NULL && !BER_BVISNULL( &op->o_req_ndn ) ) {
+ bd = select_backend( &op->o_req_ndn, 1 );
if ( bd == op->o_bd ) {
- if ( err > LDAP_SUCCESS ) {
+ if ( err > LDAP_SUCCESS && dosend ) {
send_ldap_error( op, rs,
LDAP_UNWILLING_TO_PERFORM,
"back-relay would call self" );
if ( bd == NULL && err > -1 ) {
if ( default_referral ) {
- rs->sr_ref = referral_rewrite( default_referral,
- NULL, &op->o_req_dn, LDAP_SCOPE_DEFAULT );
- if ( !rs->sr_ref ) {
- rs->sr_ref = default_referral;
- }
-
rs->sr_err = LDAP_REFERRAL;
- send_ldap_result( op, rs );
-
- if ( rs->sr_ref != default_referral ) {
- ber_bvarray_free( rs->sr_ref );
+ if ( dosend ) {
+ rs->sr_ref = referral_rewrite(
+ default_referral,
+ NULL, &op->o_req_dn,
+ LDAP_SCOPE_DEFAULT );
+ if ( !rs->sr_ref ) {
+ rs->sr_ref = default_referral;
+ }
+
+ send_ldap_result( op, rs );
+
+ if ( rs->sr_ref != default_referral ) {
+ ber_bvarray_free( rs->sr_ref );
+ }
}
} else {
* LDAP_NO_SUCH_OBJECT for other operations.
* noSuchObject cannot be returned by bind */
rs->sr_err = err;
- send_ldap_result( op, rs );
+ if ( dosend ) {
+ send_ldap_result( op, rs );
+ }
}
}
}
int
-relay_back_op_bind( struct slap_op *op, struct slap_rep *rs )
+relay_back_op_bind( Operation *op, SlapReply *rs )
{
BackendDB *bd;
int rc = 1;
- bd = relay_back_select_backend( op, rs, LDAP_INVALID_CREDENTIALS );
+ /* allow rootdn as a means to auth without the need to actually
+ * contact the proxied DSA */
+ switch ( be_rootdn_bind( op, rs ) ) {
+ case SLAP_CB_CONTINUE:
+ break;
+
+ default:
+ return rs->sr_err;
+ }
+
+ bd = relay_back_select_backend( op, rs, LDAP_INVALID_CREDENTIALS, 1 );
if ( bd == NULL ) {
return rc;
}
relay_back_add_cb( &cb, op );
op->o_bd = bd;
- rc = ( bd->be_bind )( op, rs );
+ rc = bd->be_bind( op, rs );
op->o_bd = be;
if ( op->o_callback == &cb ) {
}
int
-relay_back_op_unbind( struct slap_op *op, struct slap_rep *rs )
+relay_back_op_unbind( Operation *op, SlapReply *rs )
{
- relay_back_info *ri = (relay_back_info *)op->o_bd->be_private;
BackendDB *bd;
int rc = 1;
- bd = ri->ri_bd;
+ bd = relay_back_select_backend( op, rs, LDAP_SUCCESS, 0 );
if ( bd == NULL ) {
- bd = select_backend( &op->o_req_ndn, 0, 1 );
+ return 1;
}
if ( bd && bd->be_unbind ) {
relay_back_add_cb( &cb, op );
op->o_bd = bd;
- rc = ( bd->be_unbind )( op, rs );
+ rc = bd->be_unbind( op, rs );
op->o_bd = be;
if ( op->o_callback == &cb ) {
}
int
-relay_back_op_search( struct slap_op *op, struct slap_rep *rs )
+relay_back_op_search( Operation *op, SlapReply *rs )
{
BackendDB *bd;
int rc = 1;
- bd = relay_back_select_backend( op, rs, LDAP_NO_SUCH_OBJECT );
+ bd = relay_back_select_backend( op, rs, LDAP_NO_SUCH_OBJECT, 1 );
if ( bd == NULL ) {
return 1;
}
relay_back_add_cb( &cb, op );
op->o_bd = bd;
- rc = ( bd->be_search )( op, rs );
+ rc = bd->be_search( op, rs );
op->o_bd = be;
if ( op->o_callback == &cb ) {
}
int
-relay_back_op_compare( struct slap_op *op, struct slap_rep *rs )
+relay_back_op_compare( Operation *op, SlapReply *rs )
{
BackendDB *bd;
int rc = 1;
- bd = relay_back_select_backend( op, rs, LDAP_NO_SUCH_OBJECT );
+ bd = relay_back_select_backend( op, rs, LDAP_NO_SUCH_OBJECT, 1 );
if ( bd == NULL ) {
return 1;
}
relay_back_add_cb( &cb, op );
op->o_bd = bd;
- rc = ( bd->be_compare )( op, rs );
+ rc = bd->be_compare( op, rs );
op->o_bd = be;
if ( op->o_callback == &cb ) {
}
int
-relay_back_op_modify( struct slap_op *op, struct slap_rep *rs )
+relay_back_op_modify( Operation *op, SlapReply *rs )
{
BackendDB *bd;
int rc = 1;
- bd = relay_back_select_backend( op, rs, LDAP_NO_SUCH_OBJECT );
+ bd = relay_back_select_backend( op, rs, LDAP_NO_SUCH_OBJECT, 1 );
if ( bd == NULL ) {
return 1;
}
relay_back_add_cb( &cb, op );
op->o_bd = bd;
- rc = ( bd->be_modify )( op, rs );
+ rc = bd->be_modify( op, rs );
op->o_bd = be;
if ( op->o_callback == &cb ) {
}
int
-relay_back_op_modrdn( struct slap_op *op, struct slap_rep *rs )
+relay_back_op_modrdn( Operation *op, SlapReply *rs )
{
BackendDB *bd;
int rc = 1;
- bd = relay_back_select_backend( op, rs, LDAP_NO_SUCH_OBJECT );
+ bd = relay_back_select_backend( op, rs, LDAP_NO_SUCH_OBJECT, 1 );
if ( bd == NULL ) {
return 1;
}
relay_back_add_cb( &cb, op );
op->o_bd = bd;
- rc = ( bd->be_modrdn )( op, rs );
+ rc = bd->be_modrdn( op, rs );
op->o_bd = be;
if ( op->o_callback == &cb ) {
}
int
-relay_back_op_add( struct slap_op *op, struct slap_rep *rs )
+relay_back_op_add( Operation *op, SlapReply *rs )
{
BackendDB *bd;
int rc = 1;
- bd = relay_back_select_backend( op, rs, LDAP_NO_SUCH_OBJECT );
+ bd = relay_back_select_backend( op, rs, LDAP_NO_SUCH_OBJECT, 1 );
if ( bd == NULL ) {
return 1;
}
relay_back_add_cb( &cb, op );
op->o_bd = bd;
- rc = ( bd->be_add )( op, rs );
+ rc = bd->be_add( op, rs );
op->o_bd = be;
if ( op->o_callback == &cb ) {
}
int
-relay_back_op_delete( struct slap_op *op, struct slap_rep *rs )
+relay_back_op_delete( Operation *op, SlapReply *rs )
{
BackendDB *bd;
int rc = 1;
- bd = relay_back_select_backend( op, rs, LDAP_NO_SUCH_OBJECT );
+ bd = relay_back_select_backend( op, rs, LDAP_NO_SUCH_OBJECT, 1 );
if ( bd == NULL ) {
return 1;
}
relay_back_add_cb( &cb, op );
op->o_bd = bd;
- rc = ( bd->be_delete )( op, rs );
+ rc = bd->be_delete( op, rs );
op->o_bd = be;
if ( op->o_callback == &cb ) {
}
int
-relay_back_op_abandon( struct slap_op *op, struct slap_rep *rs )
+relay_back_op_abandon( Operation *op, SlapReply *rs )
{
BackendDB *bd;
int rc = 1;
- bd = relay_back_select_backend( op, rs, -1 );
+ bd = relay_back_select_backend( op, rs, LDAP_SUCCESS, 0 );
if ( bd == NULL ) {
return 1;
}
relay_back_add_cb( &cb, op );
op->o_bd = bd;
- rc = ( bd->be_abandon )( op, rs );
+ rc = bd->be_abandon( op, rs );
op->o_bd = be;
if ( op->o_callback == &cb ) {
}
int
-relay_back_op_cancel( struct slap_op *op, struct slap_rep *rs )
+relay_back_op_cancel( Operation *op, SlapReply *rs )
{
BackendDB *bd;
int rc = 1;
- bd = relay_back_select_backend( op, rs, LDAP_NO_SUCH_OBJECT );
+ bd = relay_back_select_backend( op, rs, LDAP_CANNOT_CANCEL, 0 );
if ( bd == NULL ) {
return 1;
}
relay_back_add_cb( &cb, op );
op->o_bd = bd;
- rc = ( bd->be_cancel )( op, rs );
+ rc = bd->be_cancel( op, rs );
op->o_bd = be;
if ( op->o_callback == &cb ) {
}
int
-relay_back_op_extended( struct slap_op *op, struct slap_rep *rs )
+relay_back_op_extended( Operation *op, SlapReply *rs )
{
BackendDB *bd;
int rc = 1;
- bd = relay_back_select_backend( op, rs, LDAP_NO_SUCH_OBJECT );
+ bd = relay_back_select_backend( op, rs, LDAP_NO_SUCH_OBJECT, 0 );
if ( bd == NULL ) {
return 1;
}
relay_back_add_cb( &cb, op );
op->o_bd = bd;
- rc = ( bd->be_extended )( op, rs );
+ rc = bd->be_extended( op, rs );
op->o_bd = be;
if ( op->o_callback == &cb ) {
}
int
-relay_back_entry_release_rw( struct slap_op *op, Entry *e, int rw )
+relay_back_entry_release_rw( Operation *op, Entry *e, int rw )
{
relay_back_info *ri = (relay_back_info *)op->o_bd->be_private;
BackendDB *bd;
bd = ri->ri_bd;
if ( bd == NULL) {
- bd = select_backend( &op->o_req_ndn, 0, 1 );
+ bd = select_backend( &op->o_req_ndn, 1 );
if ( bd == NULL ) {
return 1;
}
BackendDB *be = op->o_bd;
op->o_bd = bd;
- rc = ( bd->be_release )( op, e, rw );
+ rc = bd->be_release( op, e, rw );
op->o_bd = be;
}
}
int
-relay_back_entry_get_rw( struct slap_op *op, struct berval *ndn,
+relay_back_entry_get_rw( Operation *op, struct berval *ndn,
ObjectClass *oc, AttributeDescription *at, int rw, Entry **e )
{
relay_back_info *ri = (relay_back_info *)op->o_bd->be_private;
bd = ri->ri_bd;
if ( bd == NULL) {
- bd = select_backend( &op->o_req_ndn, 0, 1 );
+ bd = select_backend( &op->o_req_ndn, 1 );
if ( bd == NULL ) {
return 1;
}
BackendDB *be = op->o_bd;
op->o_bd = bd;
- rc = ( bd->be_fetch )( op, ndn, oc, at, rw, e );
+ rc = bd->be_fetch( op, ndn, oc, at, rw, e );
op->o_bd = be;
}
* naming context... mmmh.
*/
int
-relay_back_chk_referrals( struct slap_op *op, struct slap_rep *rs )
+relay_back_chk_referrals( Operation *op, SlapReply *rs )
{
BackendDB *bd;
int rc = 0;
- bd = relay_back_select_backend( op, rs, LDAP_SUCCESS );
+ bd = relay_back_select_backend( op, rs, LDAP_SUCCESS, 1 );
/* FIXME: this test only works if there are no overlays, so
* it is nearly useless; if made stricter, no nested back-relays
* can be instantiated... too bad. */
relay_back_add_cb( &cb, op );
op->o_bd = bd;
- rc = ( bd->be_chk_referrals )( op, rs );
+ rc = bd->be_chk_referrals( op, rs );
op->o_bd = be;
if ( op->o_callback == &cb ) {
}
int
-relay_back_operational( struct slap_op *op, struct slap_rep *rs )
+relay_back_operational( Operation *op, SlapReply *rs )
{
- relay_back_info *ri = (relay_back_info *)op->o_bd->be_private;
BackendDB *bd;
int rc = 1;
- bd = ri->ri_bd;
- if ( bd == NULL) {
- bd = select_backend( &op->o_req_ndn, 0, 1 );
- if ( bd == NULL ) {
- return 1;
- }
+ bd = relay_back_select_backend( op, rs, LDAP_SUCCESS, 0 );
+ /* FIXME: this test only works if there are no overlays, so
+ * it is nearly useless; if made stricter, no nested back-relays
+ * can be instantiated... too bad. */
+ if ( bd == NULL || bd == op->o_bd ) {
+ return 0;
}
if ( bd->be_operational ) {
relay_back_add_cb( &cb, op );
op->o_bd = bd;
- rc = ( bd->be_operational )( op, rs );
+ rc = bd->be_operational( op, rs );
op->o_bd = be;
if ( op->o_callback == &cb ) {
}
int
-relay_back_has_subordinates( struct slap_op *op, Entry *e, int *hasSubs )
+relay_back_has_subordinates( Operation *op, Entry *e, int *hasSubs )
{
- relay_back_info *ri = (relay_back_info *)op->o_bd->be_private;
+ SlapReply rs = { 0 };
BackendDB *bd;
int rc = 1;
- bd = ri->ri_bd;
- if ( bd == NULL) {
- bd = select_backend( &op->o_req_ndn, 0, 1 );
- if ( bd == NULL ) {
- return 1;
- }
+ bd = relay_back_select_backend( op, &rs, LDAP_SUCCESS, 0 );
+ /* FIXME: this test only works if there are no overlays, so
+ * it is nearly useless; if made stricter, no nested back-relays
+ * can be instantiated... too bad. */
+ if ( bd == NULL || bd == op->o_bd ) {
+ return 0;
}
if ( bd->be_has_subordinates ) {
BackendDB *be = op->o_bd;
op->o_bd = bd;
- rc = ( bd->be_has_subordinates )( op, e, hasSubs );
+ rc = bd->be_has_subordinates( op, e, hasSubs );
op->o_bd = be;
}
}
int
-relay_back_connection_init( BackendDB *bd, struct slap_conn *c )
+relay_back_connection_init( BackendDB *bd, Connection *c )
{
relay_back_info *ri = (relay_back_info *)bd->be_private;
}
if ( bd->be_connection_init ) {
- return ( bd->be_connection_init )( bd, c );
+ return bd->be_connection_init( bd, c );
}
return 0;
}
int
-relay_back_connection_destroy( BackendDB *bd, struct slap_conn *c )
+relay_back_connection_destroy( BackendDB *bd, Connection *c )
{
relay_back_info *ri = (relay_back_info *)bd->be_private;
bd = ri->ri_bd;
- if ( bd == NULL) {
+ if ( bd == NULL ) {
return 0;
}
if ( bd->be_connection_destroy ) {
- return ( bd->be_connection_destroy )( bd, c );
+ return bd->be_connection_destroy( bd, c );
}
return 0;
extern BI_init relay_back_initialize;
extern BI_db_init relay_back_db_init;
-extern BI_db_config relay_back_db_config;
extern BI_db_open relay_back_db_open;
extern BI_db_close relay_back_db_close;
extern BI_db_destroy relay_back_db_destroy;
FILE *rfp, *wfp;
int rc;
+ /* allow rootdn as a means to auth without the need to actually
+ * contact the proxied DSA */
+ switch ( be_rootdn_bind( op, rs ) ) {
+ case SLAP_CB_CONTINUE:
+ break;
+
+ default:
+ return rs->sr_err;
+ }
+
if ( si->si_bind == NULL ) {
send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
"bind not implemented" );
#include "slap.h"
+#include "config.h"
+
#include "shell.h"
int
int
shell_back_db_init(
- Backend *be
+ Backend *be,
+ ConfigReply *cr
)
{
struct shellinfo *si;
int
shell_back_db_destroy(
- Backend *be
+ Backend *be,
+ ConfigReply *cr
)
{
free( be->be_private );
Modification *mod;
struct shellinfo *si = (struct shellinfo *) op->o_bd->be_private;
AttributeDescription *entry = slap_schema.si_ad_entry;
- Modifications *ml = op->oq_modify.rs_modlist;
+ Modifications *ml = op->orm_modlist;
Entry e;
FILE *rfp, *wfp;
int i;
char **si_delete; /* cmd + args to exec for delete */
};
-struct slap_backend_db;
-struct slap_conn;
-struct slap_op;
-
extern pid_t forkandexec LDAP_P((
char **args,
FILE **rfp,
extern void print_suffixes LDAP_P((
FILE *fp,
- struct slap_backend_db *bd));
+ BackendDB *bd));
extern int read_and_send_results LDAP_P((
- struct slap_op *op,
- struct slap_rep *rs,
+ Operation *op,
+ SlapReply *rs,
FILE *fp));
LDAP_END_DECL
}
if ( !BER_BVISNULL( &bsi.bsi_base_id.eid_ndn ) ) {
- (void)backsql_free_entryID( op, &bsi.bsi_base_id, 0 );
+ (void)backsql_free_entryID( &bsi.bsi_base_id, 0, op->o_tmpmemctx );
}
if ( !BER_BVISNULL( &p.e_nname ) ) {
SWORD ncols;
BerVarray col_names;
UDWORD *col_prec;
+ SQLSMALLINT *col_type;
char **cols;
SQLINTEGER *value_len;
} BACKSQL_ROW_NTS;
struct backsql_api *ba_next;
} backsql_api;
-/*
- * Entry ID structure
- */
-typedef struct backsql_entryID {
- /* #define BACKSQL_ARBITRARY_KEY to allow a non-numeric key.
- * It is required by some special applications that use
- * strings as keys for the main table.
- * In this case, #define BACKSQL_MAX_KEY_LEN consistently
- * with the key size definition */
-#ifdef BACKSQL_ARBITRARY_KEY
- struct berval eid_id;
- struct berval eid_keyval;
-#define BACKSQL_MAX_KEY_LEN 64
-#else /* ! BACKSQL_ARBITRARY_KEY */
- /* The original numeric key is maintained as default. */
- unsigned long eid_id;
- unsigned long eid_keyval;
-#endif /* ! BACKSQL_ARBITRARY_KEY */
-
- unsigned long eid_oc_id;
- struct berval eid_dn;
- struct berval eid_ndn;
- struct backsql_entryID *eid_next;
-} backsql_entryID;
-
#ifdef BACKSQL_ARBITRARY_KEY
#define BACKSQL_ENTRYID_INIT { BER_BVNULL, BER_BVNULL, 0, BER_BVNULL, BER_BVNULL, NULL }
#else /* ! BACKSQL_ARBITRARY_KEY */
typedef struct backsql_at_map_rec {
/* Description of corresponding LDAP attribute type */
AttributeDescription *bam_ad;
+ AttributeDescription *bam_true_ad;
/* ObjectClass if bam_ad is objectClass */
ObjectClass *bam_oc;
#define BB_NULL { BER_BVNULL, 0 }
+/*
+ * Entry ID structure
+ */
+typedef struct backsql_entryID {
+ /* #define BACKSQL_ARBITRARY_KEY to allow a non-numeric key.
+ * It is required by some special applications that use
+ * strings as keys for the main table.
+ * In this case, #define BACKSQL_MAX_KEY_LEN consistently
+ * with the key size definition */
+#ifdef BACKSQL_ARBITRARY_KEY
+ struct berval eid_id;
+ struct berval eid_keyval;
+#define BACKSQL_MAX_KEY_LEN 64
+#else /* ! BACKSQL_ARBITRARY_KEY */
+ /* The original numeric key is maintained as default. */
+ unsigned long eid_id;
+ unsigned long eid_keyval;
+#endif /* ! BACKSQL_ARBITRARY_KEY */
+
+ unsigned long eid_oc_id;
+ backsql_oc_map_rec *eid_oc;
+ struct berval eid_dn;
+ struct berval eid_ndn;
+ struct backsql_entryID *eid_next;
+} backsql_entryID;
+
/* the function must collect the entry associated to nbase */
#define BACKSQL_ISF_GET_ID 0x1U
#define BACKSQL_ISF_GET_ENTRY ( 0x2U | BACKSQL_ISF_GET_ID )
-#define BACKSQL_ISF_MATCHED 0x4U
+#define BACKSQL_ISF_GET_OC ( 0x4U | BACKSQL_ISF_GET_ID )
+#define BACKSQL_ISF_MATCHED 0x8U
#define BACKSQL_IS_GET_ID(f) \
( ( (f) & BACKSQL_ISF_GET_ID ) == BACKSQL_ISF_GET_ID )
#define BACKSQL_IS_GET_ENTRY(f) \
( ( (f) & BACKSQL_ISF_GET_ENTRY ) == BACKSQL_ISF_GET_ENTRY )
+#define BACKSQL_IS_GET_OC(f) \
+ ( ( (f) & BACKSQL_ISF_GET_OC ) == BACKSQL_ISF_GET_OC )
#define BACKSQL_IS_MATCHED(f) \
( ( (f) & BACKSQL_ISF_MATCHED ) == BACKSQL_ISF_MATCHED )
typedef struct backsql_srch_info {
*/
struct berval sql_subtree_cond;
struct berval sql_children_cond;
- char *sql_oc_query,
- *sql_at_query;
- char *sql_insentry_stmt,
- *sql_delentry_stmt,
- *sql_renentry_stmt,
- *sql_delobjclasses_stmt;
+ struct berval sql_dn_match_cond;
+ char *sql_oc_query;
+ char *sql_at_query;
+ char *sql_insentry_stmt;
+ char *sql_delentry_stmt;
+ char *sql_renentry_stmt;
+ char *sql_delobjclasses_stmt;
char *sql_id_query;
char *sql_has_children_query;
+ char *sql_list_children_query;
MatchingRule *sql_caseIgnoreMatch;
MatchingRule *sql_telephoneNumberMatch;
#define BACKSQL_BASEOBJECT_OC 0
Avlnode *sql_db_conns;
+ SQLHDBC sql_dbh;
+ ldap_pvt_thread_mutex_t sql_dbconn_mutex;
Avlnode *sql_oc_by_oc;
Avlnode *sql_oc_by_id;
- ldap_pvt_thread_mutex_t sql_dbconn_mutex;
ldap_pvt_thread_mutex_t sql_schema_mutex;
SQLHENV sql_db_env;
#define BACKSQL_SANITIZE_ERROR( rc ) \
( BACKSQL_LEGAL_ERROR( (rc) ) ? (rc) : LDAP_OTHER )
+#define BACKSQL_IS_BINARY(ct) \
+ ( (ct) == SQL_BINARY \
+ || (ct) == SQL_VARBINARY \
+ || (ct) == SQL_LONGVARBINARY)
+
#endif /* __BACKSQL_H__ */
Debug( LDAP_DEBUG_TRACE, "==>backsql_bind()\n", 0, 0, 0 );
- if ( be_isroot_pw( op ) ) {
- ber_dupbv( &op->oq_bind.rb_edn, be_root_dn( op->o_bd ) );
- Debug( LDAP_DEBUG_TRACE, "<==backsql_bind() root bind\n",
- 0, 0, 0 );
- return LDAP_SUCCESS;
- }
-
- ber_dupbv( &op->oq_bind.rb_edn, &op->o_req_ndn );
-
- if ( op->oq_bind.rb_method != LDAP_AUTH_SIMPLE ) {
- rs->sr_err = LDAP_STRONG_AUTH_NOT_SUPPORTED;
- rs->sr_text = "authentication method not supported";
- send_ldap_result( op, rs );
+ switch ( be_rootdn_bind( op, rs ) ) {
+ case SLAP_CB_CONTINUE:
+ break;
+
+ default:
+ /* in case of success, front end will send result;
+ * otherwise, be_rootdn_bind() did */
+ Debug( LDAP_DEBUG_TRACE, "<==backsql_bind(%d)\n",
+ rs->sr_err, 0, 0 );
return rs->sr_err;
}
- /*
- * method = LDAP_AUTH_SIMPLE
- */
rs->sr_err = backsql_get_db_conn( op, &dbh );
- if ( !dbh ) {
+ if ( rs->sr_err != LDAP_SUCCESS ) {
Debug( LDAP_DEBUG_TRACE, "backsql_bind(): "
"could not get connection handle - exiting\n",
0, 0, 0 );
error_return:;
if ( !BER_BVISNULL( &bsi.bsi_base_id.eid_ndn ) ) {
- (void)backsql_free_entryID( op, &bsi.bsi_base_id, 0 );
+ (void)backsql_free_entryID( &bsi.bsi_base_id, 0, op->o_tmpmemctx );
}
if ( !BER_BVISNULL( &e.e_nname ) ) {
Debug( LDAP_DEBUG_TRACE, "==>backsql_compare()\n", 0, 0, 0 );
rs->sr_err = backsql_get_db_conn( op, &dbh );
- if ( !dbh ) {
+ if ( rs->sr_err != LDAP_SUCCESS ) {
Debug( LDAP_DEBUG_TRACE, "backsql_compare(): "
"could not get connection handle - exiting\n",
0, 0, 0 );
}
if ( !BER_BVISNULL( &bsi.bsi_base_id.eid_ndn ) ) {
- (void)backsql_free_entryID( op, &bsi.bsi_base_id, 0 );
+ (void)backsql_free_entryID( &bsi.bsi_base_id, 0, op->o_tmpmemctx );
}
if ( !BER_BVISNULL( &e.e_nname ) ) {
}
ber_str2bv( argv[ 1 ], 0, 1, &bi->sql_children_cond );
Debug( LDAP_DEBUG_TRACE, "<==backsql_db_config(): "
- "subtree_cond=%s\n", bi->sql_children_cond.bv_val, 0, 0 );
+ "children_cond=%s\n", bi->sql_children_cond.bv_val, 0, 0 );
+
+ } else if ( !strcasecmp( argv[ 0 ], "dn_match_cond" ) ) {
+ if ( argc < 2 ) {
+ Debug( LDAP_DEBUG_TRACE,
+ "<==backsql_db_config (%s line %d): "
+ "missing SQL condition "
+ "in \"dn_match_cond\" directive\n",
+ fname, lineno, 0 );
+ return 1;
+ }
+ ber_str2bv( argv[ 1 ], 0, 1, &bi->sql_dn_match_cond );
+ Debug( LDAP_DEBUG_TRACE, "<==backsql_db_config(): "
+ "children_cond=%s\n", bi->sql_dn_match_cond.bv_val, 0, 0 );
} else if ( !strcasecmp( argv[ 0 ], "oc_query" ) ) {
if ( argc < 2 ) {
Operation *op,
SlapReply *rs,
SQLHDBC dbh,
- backsql_entryID *e_id,
- backsql_oc_map_rec *oc )
+ backsql_entryID *eid )
{
backsql_delete_attr_t bda;
int rc;
bda.op = op;
bda.rs = rs;
bda.dbh = dbh;
- bda.e_id = e_id;
+ bda.e_id = eid;
- rc = avl_apply( oc->bom_attrs, backsql_delete_attr_f, &bda,
+ rc = avl_apply( eid->eid_oc->bom_attrs, backsql_delete_attr_f, &bda,
BACKSQL_AVL_STOP, AVL_INORDER );
if ( rc == BACKSQL_AVL_STOP ) {
return rs->sr_err;
return LDAP_SUCCESS;
}
-int
-backsql_delete( Operation *op, SlapReply *rs )
+static int
+backsql_delete_int(
+ Operation *op,
+ SlapReply *rs,
+ SQLHDBC dbh,
+ SQLHSTMT *sthp,
+ backsql_entryID *eid,
+ Entry **ep )
{
backsql_info *bi = (backsql_info*)op->o_bd->be_private;
- SQLHDBC dbh = SQL_NULL_HDBC;
SQLHSTMT sth = SQL_NULL_HSTMT;
RETCODE rc;
int prc = LDAP_SUCCESS;
- backsql_oc_map_rec *oc = NULL;
- backsql_srch_info bsi = { 0 };
- backsql_entryID e_id = { 0 };
- Entry d = { 0 }, p = { 0 }, *e = NULL;
- struct berval pdn = BER_BVNULL;
- int manageDSAit = get_manageDSAit( op );
/* first parameter no */
SQLUSMALLINT pno = 0;
- Debug( LDAP_DEBUG_TRACE, "==>backsql_delete(): deleting entry \"%s\"\n",
- op->o_req_ndn.bv_val, 0, 0 );
-
- rs->sr_err = backsql_get_db_conn( op, &dbh );
- if ( rs->sr_err != LDAP_SUCCESS ) {
- Debug( LDAP_DEBUG_TRACE, " backsql_delete(): "
- "could not get connection handle - exiting\n",
- 0, 0, 0 );
- rs->sr_text = ( rs->sr_err == LDAP_OTHER )
- ? "SQL-backend error" : NULL;
- e = NULL;
- goto done;
- }
-
- /*
- * Get the entry
- */
- bsi.bsi_e = &d;
- rs->sr_err = backsql_init_search( &bsi, &op->o_req_ndn,
- LDAP_SCOPE_BASE,
- (time_t)(-1), NULL, dbh, op, rs, slap_anlist_no_attrs,
- ( BACKSQL_ISF_MATCHED | BACKSQL_ISF_GET_ENTRY ) );
- switch ( rs->sr_err ) {
- case LDAP_SUCCESS:
- break;
-
- case LDAP_REFERRAL:
- if ( manageDSAit && !BER_BVISNULL( &bsi.bsi_e->e_nname ) &&
- dn_match( &op->o_req_ndn, &bsi.bsi_e->e_nname ) )
- {
- rs->sr_err = LDAP_SUCCESS;
- rs->sr_text = NULL;
- rs->sr_matched = NULL;
- if ( rs->sr_ref ) {
- ber_bvarray_free( rs->sr_ref );
- rs->sr_ref = NULL;
- }
- break;
- }
- e = &d;
- /* fallthru */
-
- default:
- Debug( LDAP_DEBUG_TRACE, "backsql_delete(): "
- "could not retrieve deleteDN ID - no such entry\n",
- 0, 0, 0 );
- if ( !BER_BVISNULL( &d.e_nname ) ) {
- /* FIXME: should always be true! */
- e = &d;
-
- } else {
- e = NULL;
- }
- goto done;
- }
-
- if ( get_assert( op ) &&
- ( test_filter( op, &d, get_assertion( op ) )
- != LDAP_COMPARE_TRUE ) )
- {
- rs->sr_err = LDAP_ASSERTION_FAILED;
- e = &d;
- goto done;
- }
-
- if ( !access_allowed( op, &d, slap_schema.si_ad_entry,
- NULL, ACL_WDEL, NULL ) )
- {
- Debug( LDAP_DEBUG_TRACE, " backsql_delete(): "
- "no write access to entry\n",
- 0, 0, 0 );
- rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
- e = &d;
- goto done;
- }
-
- rs->sr_err = backsql_has_children( op, dbh, &op->o_req_ndn );
- switch ( rs->sr_err ) {
- case LDAP_COMPARE_FALSE:
- rs->sr_err = LDAP_SUCCESS;
- break;
-
- case LDAP_COMPARE_TRUE:
- if ( get_treeDelete( op ) ) {
- /* not supported yet */ ;
- }
- Debug( LDAP_DEBUG_TRACE, " backsql_delete(): "
- "entry \"%s\" has children\n",
- op->o_req_dn.bv_val, 0, 0 );
- rs->sr_err = LDAP_NOT_ALLOWED_ON_NONLEAF;
- rs->sr_text = "subordinate objects must be deleted first";
- /* fallthru */
-
- default:
- e = &d;
- goto done;
- }
-
- oc = backsql_id2oc( bi, bsi.bsi_base_id.eid_oc_id );
- if ( oc == NULL ) {
- Debug( LDAP_DEBUG_TRACE, " backsql_delete(): "
- "cannot determine objectclass of entry -- aborting\n",
- 0, 0, 0 );
- rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
- rs->sr_text = "operation not permitted within namingContext";
- e = NULL;
- goto done;
- }
-
- if ( oc->bom_delete_proc == NULL ) {
- Debug( LDAP_DEBUG_TRACE, " backsql_delete(): "
- "delete procedure is not defined "
- "for this objectclass - aborting\n", 0, 0, 0 );
- rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
- rs->sr_text = "operation not permitted within namingContext";
- e = NULL;
- goto done;
- }
-
- /*
- * Get the parent
- */
- e_id = bsi.bsi_base_id;
- if ( !be_issuffix( op->o_bd, &op->o_req_ndn ) ) {
- dnParent( &op->o_req_ndn, &pdn );
- bsi.bsi_e = &p;
- rs->sr_err = backsql_init_search( &bsi, &pdn,
- LDAP_SCOPE_BASE,
- (time_t)(-1), NULL, dbh, op, rs,
- slap_anlist_no_attrs,
- BACKSQL_ISF_GET_ENTRY );
- if ( rs->sr_err != LDAP_SUCCESS ) {
- Debug( LDAP_DEBUG_TRACE, "backsql_delete(): "
- "could not retrieve deleteDN ID "
- "- no such entry\n",
- 0, 0, 0 );
- e = &p;
- goto done;
- }
-
- (void)backsql_free_entryID( op, &bsi.bsi_base_id, 0 );
-
- /* check parent for "children" acl */
- if ( !access_allowed( op, &p, slap_schema.si_ad_children,
- NULL, ACL_WDEL, NULL ) )
- {
- Debug( LDAP_DEBUG_TRACE, " backsql_delete(): "
- "no write access to parent\n",
- 0, 0, 0 );
- rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
- e = &p;
- goto done;
-
- }
- }
+ sth = *sthp;
/* avl_apply ... */
- rs->sr_err = backsql_delete_all_attrs( op, rs, dbh, &e_id, oc );
+ rs->sr_err = backsql_delete_all_attrs( op, rs, dbh, eid );
if ( rs->sr_err != LDAP_SUCCESS ) {
- e = &d;
goto done;
}
- rc = backsql_Prepare( dbh, &sth, oc->bom_delete_proc, 0 );
+ rc = backsql_Prepare( dbh, &sth, eid->eid_oc->bom_delete_proc, 0 );
if ( rc != SQL_SUCCESS ) {
Debug( LDAP_DEBUG_TRACE,
" backsql_delete(): "
rs->sr_err = LDAP_OTHER;
rs->sr_text = "SQL-backend error";
- e = NULL;
+ *ep = NULL;
goto done;
}
- if ( BACKSQL_IS_DEL( oc->bom_expect_return ) ) {
+ if ( BACKSQL_IS_DEL( eid->eid_oc->bom_expect_return ) ) {
pno = 1;
rc = backsql_BindParamInt( sth, 1, SQL_PARAM_OUTPUT, &prc );
if ( rc != SQL_SUCCESS ) {
Debug( LDAP_DEBUG_TRACE,
" backsql_delete(): "
"error binding output parameter for objectClass %s\n",
- oc->bom_oc->soc_cname.bv_val, 0, 0 );
+ eid->eid_oc->bom_oc->soc_cname.bv_val, 0, 0 );
backsql_PrintErrors( bi->sql_db_env, dbh,
sth, rc );
SQLFreeStmt( sth, SQL_DROP );
rs->sr_text = "SQL-backend error";
rs->sr_err = LDAP_OTHER;
- e = NULL;
+ *ep = NULL;
goto done;
}
}
- rc = backsql_BindParamID( sth, pno + 1, SQL_PARAM_INPUT, &e_id.eid_keyval );
+ rc = backsql_BindParamID( sth, pno + 1, SQL_PARAM_INPUT, &eid->eid_keyval );
if ( rc != SQL_SUCCESS ) {
Debug( LDAP_DEBUG_TRACE,
" backsql_delete(): "
"error binding keyval parameter for objectClass %s\n",
- oc->bom_oc->soc_cname.bv_val, 0, 0 );
+ eid->eid_oc->bom_oc->soc_cname.bv_val, 0, 0 );
backsql_PrintErrors( bi->sql_db_env, dbh,
sth, rc );
SQLFreeStmt( sth, SQL_DROP );
rs->sr_text = "SQL-backend error";
rs->sr_err = LDAP_OTHER;
- e = NULL;
+ *ep = NULL;
goto done;
}
rs->sr_err = LDAP_OTHER;
}
SQLFreeStmt( sth, SQL_DROP );
- e = &d;
goto done;
}
SQLFreeStmt( sth, SQL_DROP );
rs->sr_err = LDAP_OTHER;
rs->sr_text = "SQL-backend error";
- e = NULL;
+ *ep = NULL;
goto done;
}
- rc = backsql_BindParamID( sth, 1, SQL_PARAM_INPUT, &e_id.eid_id );
+ rc = backsql_BindParamID( sth, 1, SQL_PARAM_INPUT, &eid->eid_id );
if ( rc != SQL_SUCCESS ) {
Debug( LDAP_DEBUG_TRACE,
" backsql_delete(): "
"error binding auxiliary objectClasses "
"entry ID parameter for objectClass %s\n",
- oc->bom_oc->soc_cname.bv_val, 0, 0 );
+ eid->eid_oc->bom_oc->soc_cname.bv_val, 0, 0 );
backsql_PrintErrors( bi->sql_db_env, dbh,
sth, rc );
SQLFreeStmt( sth, SQL_DROP );
rs->sr_text = "SQL-backend error";
rs->sr_err = LDAP_OTHER;
- e = NULL;
+ *ep = NULL;
goto done;
}
SQLFreeStmt( sth, SQL_DROP );
rs->sr_err = LDAP_OTHER;
rs->sr_text = "SQL-backend error";
- e = NULL;
+ *ep = NULL;
goto done;
}
SQLFreeStmt( sth, SQL_DROP );
rs->sr_err = LDAP_OTHER;
rs->sr_text = "SQL-backend error";
- e = NULL;
+ *ep = NULL;
goto done;
}
- rc = backsql_BindParamID( sth, 1, SQL_PARAM_INPUT, &e_id.eid_id );
+ rc = backsql_BindParamID( sth, 1, SQL_PARAM_INPUT, &eid->eid_id );
if ( rc != SQL_SUCCESS ) {
Debug( LDAP_DEBUG_TRACE,
" backsql_delete(): "
"error binding entry ID parameter "
"for objectClass %s\n",
- oc->bom_oc->soc_cname.bv_val, 0, 0 );
+ eid->eid_oc->bom_oc->soc_cname.bv_val, 0, 0 );
backsql_PrintErrors( bi->sql_db_env, dbh,
sth, rc );
SQLFreeStmt( sth, SQL_DROP );
rs->sr_text = "SQL-backend error";
rs->sr_err = LDAP_OTHER;
- e = NULL;
+ *ep = NULL;
goto done;
}
SQLFreeStmt( sth, SQL_DROP );
rs->sr_err = LDAP_OTHER;
rs->sr_text = "SQL-backend error";
- e = NULL;
+ *ep = NULL;
goto done;
}
SQLFreeStmt( sth, SQL_DROP );
rs->sr_err = LDAP_SUCCESS;
+ *ep = NULL;
+
+done:;
+ *sthp = sth;
+
+ return rs->sr_err;
+}
+
+typedef struct backsql_tree_delete_t {
+ Operation *btd_op;
+ int btd_rc;
+ backsql_entryID *btd_eid;
+} backsql_tree_delete_t;
+
+static int
+backsql_tree_delete_search_cb( Operation *op, SlapReply *rs )
+{
+ if ( rs->sr_type == REP_SEARCH ) {
+ backsql_info *bi = (backsql_info*)op->o_bd->be_private;
+ backsql_tree_delete_t *btd;
+ backsql_entryID *eid;
+
+ btd = (backsql_tree_delete_t *)op->o_callback->sc_private;
+
+ if ( !access_allowed( btd->btd_op, rs->sr_entry,
+ slap_schema.si_ad_entry, NULL, ACL_WDEL, NULL )
+ || !access_allowed( btd->btd_op, rs->sr_entry,
+ slap_schema.si_ad_children, NULL, ACL_WDEL, NULL ) )
+ {
+ btd->btd_rc = LDAP_INSUFFICIENT_ACCESS;
+ return rs->sr_err = LDAP_UNAVAILABLE;
+ }
+
+ assert( rs->sr_entry != NULL );
+ assert( rs->sr_entry->e_private != NULL );
+
+ eid = (backsql_entryID *)rs->sr_entry->e_private;
+ assert( eid->eid_oc != NULL );
+ if ( eid->eid_oc == NULL || eid->eid_oc->bom_delete_proc == NULL ) {
+ btd->btd_rc = LDAP_UNWILLING_TO_PERFORM;
+ return rs->sr_err = LDAP_UNAVAILABLE;
+ }
+
+ eid = backsql_entryID_dup( eid, op->o_tmpmemctx );
+ eid->eid_next = btd->btd_eid;
+ btd->btd_eid = eid;
+ }
+
+ return 0;
+}
+
+static int
+backsql_tree_delete(
+ Operation *op,
+ SlapReply *rs,
+ SQLHDBC dbh,
+ SQLHSTMT *sthp )
+{
+ Operation op2 = *op;
+ slap_callback sc = { 0 };
+ SlapReply rs2 = { 0 };
+ Filter f = { 0 };
+ backsql_tree_delete_t btd = { 0 };
+
+ int rc;
+
+ /*
+ * - perform an internal subtree search as the rootdn
+ * - for each entry
+ * - check access
+ * - check objectClass and delete method(s)
+ * - for each entry
+ * - delete
+ * - if successful, commit
+ */
+
+ op2.o_tag = LDAP_REQ_SEARCH;
+ op2.o_protocol = LDAP_VERSION3;
+
+ btd.btd_op = op;
+ sc.sc_private = &btd;
+ sc.sc_response = backsql_tree_delete_search_cb;
+ op2.o_callback = ≻
+
+ op2.o_dn = op->o_bd->be_rootdn;
+ op2.o_ndn = op->o_bd->be_rootndn;
+
+ op2.o_managedsait = SLAP_CONTROL_CRITICAL;
+
+ op2.ors_scope = LDAP_SCOPE_SUBTREE;
+ op2.ors_deref = LDAP_DEREF_NEVER;
+ op2.ors_slimit = SLAP_NO_LIMIT;
+ op2.ors_tlimit = SLAP_NO_LIMIT;
+ op2.ors_filter = &f;
+ f.f_choice = LDAP_FILTER_PRESENT;
+ f.f_desc = slap_schema.si_ad_objectClass;
+ BER_BVSTR( &op2.ors_filterstr, "(objectClass=*)" );
+ op2.ors_attrs = slap_anlist_all_attributes;
+ op2.ors_attrsonly = 0;
+
+ rc = op->o_bd->be_search( &op2, &rs2 );
+ if ( rc != LDAP_SUCCESS ) {
+ rc = rs->sr_err = btd.btd_rc;
+ rs->sr_text = "subtree delete not possible";
+ send_ldap_result( op, rs );
+ goto clean;
+ }
+
+ for ( ; btd.btd_eid != NULL;
+ btd.btd_eid = backsql_free_entryID( btd.btd_eid,
+ 1, op->o_tmpmemctx ) )
+ {
+ Entry *e = (void *)0xbad;
+ rc = backsql_delete_int( op, rs, dbh, sthp, btd.btd_eid, &e );
+ if ( rc != LDAP_SUCCESS ) {
+ break;
+ }
+ }
+
+clean:;
+ for ( ; btd.btd_eid != NULL;
+ btd.btd_eid = backsql_free_entryID( btd.btd_eid,
+ 1, op->o_tmpmemctx ) )
+ ;
+
+ return rc;
+}
+
+int
+backsql_delete( Operation *op, SlapReply *rs )
+{
+ backsql_info *bi = (backsql_info*)op->o_bd->be_private;
+ SQLHDBC dbh = SQL_NULL_HDBC;
+ SQLHSTMT sth = SQL_NULL_HSTMT;
+ backsql_oc_map_rec *oc = NULL;
+ backsql_srch_info bsi = { 0 };
+ backsql_entryID e_id = { 0 };
+ Entry d = { 0 }, p = { 0 }, *e = NULL;
+ struct berval pdn = BER_BVNULL;
+ int manageDSAit = get_manageDSAit( op );
+
+ Debug( LDAP_DEBUG_TRACE, "==>backsql_delete(): deleting entry \"%s\"\n",
+ op->o_req_ndn.bv_val, 0, 0 );
+
+ rs->sr_err = backsql_get_db_conn( op, &dbh );
+ if ( rs->sr_err != LDAP_SUCCESS ) {
+ Debug( LDAP_DEBUG_TRACE, " backsql_delete(): "
+ "could not get connection handle - exiting\n",
+ 0, 0, 0 );
+ rs->sr_text = ( rs->sr_err == LDAP_OTHER )
+ ? "SQL-backend error" : NULL;
+ e = NULL;
+ goto done;
+ }
+
+ /*
+ * Get the entry
+ */
+ bsi.bsi_e = &d;
+ rs->sr_err = backsql_init_search( &bsi, &op->o_req_ndn,
+ LDAP_SCOPE_BASE,
+ (time_t)(-1), NULL, dbh, op, rs, slap_anlist_no_attrs,
+ ( BACKSQL_ISF_MATCHED | BACKSQL_ISF_GET_ENTRY | BACKSQL_ISF_GET_OC ) );
+ switch ( rs->sr_err ) {
+ case LDAP_SUCCESS:
+ break;
+
+ case LDAP_REFERRAL:
+ if ( manageDSAit && !BER_BVISNULL( &bsi.bsi_e->e_nname ) &&
+ dn_match( &op->o_req_ndn, &bsi.bsi_e->e_nname ) )
+ {
+ rs->sr_err = LDAP_SUCCESS;
+ rs->sr_text = NULL;
+ rs->sr_matched = NULL;
+ if ( rs->sr_ref ) {
+ ber_bvarray_free( rs->sr_ref );
+ rs->sr_ref = NULL;
+ }
+ break;
+ }
+ e = &d;
+ /* fallthru */
+
+ default:
+ Debug( LDAP_DEBUG_TRACE, "backsql_delete(): "
+ "could not retrieve deleteDN ID - no such entry\n",
+ 0, 0, 0 );
+ if ( !BER_BVISNULL( &d.e_nname ) ) {
+ /* FIXME: should always be true! */
+ e = &d;
+
+ } else {
+ e = NULL;
+ }
+ goto done;
+ }
+
+ if ( get_assert( op ) &&
+ ( test_filter( op, &d, get_assertion( op ) )
+ != LDAP_COMPARE_TRUE ) )
+ {
+ rs->sr_err = LDAP_ASSERTION_FAILED;
+ e = &d;
+ goto done;
+ }
+
+ if ( !access_allowed( op, &d, slap_schema.si_ad_entry,
+ NULL, ACL_WDEL, NULL ) )
+ {
+ Debug( LDAP_DEBUG_TRACE, " backsql_delete(): "
+ "no write access to entry\n",
+ 0, 0, 0 );
+ rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
+ e = &d;
+ goto done;
+ }
+
+ rs->sr_err = backsql_has_children( op, dbh, &op->o_req_ndn );
+ switch ( rs->sr_err ) {
+ case LDAP_COMPARE_FALSE:
+ rs->sr_err = LDAP_SUCCESS;
+ break;
+
+ case LDAP_COMPARE_TRUE:
+#ifdef SLAP_CONTROL_X_TREE_DELETE
+ if ( get_treeDelete( op ) ) {
+ rs->sr_err = LDAP_SUCCESS;
+ break;
+ }
+#endif /* SLAP_CONTROL_X_TREE_DELETE */
+
+ Debug( LDAP_DEBUG_TRACE, " backsql_delete(): "
+ "entry \"%s\" has children\n",
+ op->o_req_dn.bv_val, 0, 0 );
+ rs->sr_err = LDAP_NOT_ALLOWED_ON_NONLEAF;
+ rs->sr_text = "subordinate objects must be deleted first";
+ /* fallthru */
+
+ default:
+ e = &d;
+ goto done;
+ }
+
+ assert( bsi.bsi_base_id.eid_oc != NULL );
+ oc = bsi.bsi_base_id.eid_oc;
+ if ( oc->bom_delete_proc == NULL ) {
+ Debug( LDAP_DEBUG_TRACE, " backsql_delete(): "
+ "delete procedure is not defined "
+ "for this objectclass - aborting\n", 0, 0, 0 );
+ rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
+ rs->sr_text = "operation not permitted within namingContext";
+ e = NULL;
+ goto done;
+ }
+
+ /*
+ * Get the parent
+ */
+ e_id = bsi.bsi_base_id;
+ memset( &bsi.bsi_base_id, 0, sizeof( bsi.bsi_base_id ) );
+ if ( !be_issuffix( op->o_bd, &op->o_req_ndn ) ) {
+ dnParent( &op->o_req_ndn, &pdn );
+ bsi.bsi_e = &p;
+ rs->sr_err = backsql_init_search( &bsi, &pdn,
+ LDAP_SCOPE_BASE,
+ (time_t)(-1), NULL, dbh, op, rs,
+ slap_anlist_no_attrs,
+ BACKSQL_ISF_GET_ENTRY );
+ if ( rs->sr_err != LDAP_SUCCESS ) {
+ Debug( LDAP_DEBUG_TRACE, "backsql_delete(): "
+ "could not retrieve deleteDN ID "
+ "- no such entry\n",
+ 0, 0, 0 );
+ e = &p;
+ goto done;
+ }
+
+ (void)backsql_free_entryID( &bsi.bsi_base_id, 0, op->o_tmpmemctx );
+
+ /* check parent for "children" acl */
+ if ( !access_allowed( op, &p, slap_schema.si_ad_children,
+ NULL, ACL_WDEL, NULL ) )
+ {
+ Debug( LDAP_DEBUG_TRACE, " backsql_delete(): "
+ "no write access to parent\n",
+ 0, 0, 0 );
+ rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
+ e = &p;
+ goto done;
+
+ }
+ }
+
+ e = &d;
+#ifdef SLAP_CONTROL_X_TREE_DELETE
+ if ( get_treeDelete( op ) ) {
+ backsql_tree_delete( op, rs, dbh, &sth );
+ if ( rs->sr_err == LDAP_OTHER || rs->sr_err == LDAP_SUCCESS )
+ {
+ e = NULL;
+ }
+
+ } else
+#endif /* SLAP_CONTROL_X_TREE_DELETE */
+ {
+ backsql_delete_int( op, rs, dbh, &sth, &e_id, &e );
+ }
/*
* Commit only if all operations succeed
Debug( LDAP_DEBUG_TRACE, "<==backsql_delete()\n", 0, 0, 0 );
if ( !BER_BVISNULL( &e_id.eid_ndn ) ) {
- (void)backsql_free_entryID( op, &e_id, 0 );
+ (void)backsql_free_entryID( &e_id, 0, op->o_tmpmemctx );
}
if ( !BER_BVISNULL( &d.e_nname ) ) {
#endif /* BACKSQL_ARBITRARY_KEY */
backsql_entryID *
-backsql_free_entryID( Operation *op, backsql_entryID *id, int freeit )
+backsql_entryID_dup( backsql_entryID *src, void *ctx )
+{
+ backsql_entryID *dst;
+
+ if ( src == NULL ) return NULL;
+
+ dst = slap_sl_calloc( 1, sizeof( backsql_entryID ), ctx );
+ ber_dupbv_x( &dst->eid_ndn, &src->eid_ndn, ctx );
+ if ( src->eid_dn.bv_val == src->eid_ndn.bv_val ) {
+ dst->eid_dn = dst->eid_ndn;
+ } else {
+ ber_dupbv_x( &dst->eid_dn, &src->eid_dn, ctx );
+ }
+
+#ifdef BACKSQL_ARBITRARY_KEY
+ ber_dupbv_x( &dst->eid_id, &src->eid_id, ctx );
+ ber_dupbv_x( &dst->eid_keyval, &src->eid_keyval, ctx );
+#else /* ! BACKSQL_ARBITRARY_KEY */
+ dst->eid_id = src->eid_id;
+ dst->eid_keyval = src->eid_keyval;
+#endif /* ! BACKSQL_ARBITRARY_KEY */
+
+ dst->eid_oc = src->eid_oc;
+ dst->eid_oc_id = src->eid_oc_id;
+
+ return dst;
+}
+
+backsql_entryID *
+backsql_free_entryID( backsql_entryID *id, int freeit, void *ctx )
{
backsql_entryID *next;
if ( !BER_BVISNULL( &id->eid_dn )
&& id->eid_dn.bv_val != id->eid_ndn.bv_val )
{
- op->o_tmpfree( id->eid_dn.bv_val, op->o_tmpmemctx );
+ slap_sl_free( id->eid_dn.bv_val, ctx );
BER_BVZERO( &id->eid_dn );
}
- op->o_tmpfree( id->eid_ndn.bv_val, op->o_tmpmemctx );
+ slap_sl_free( id->eid_ndn.bv_val, ctx );
BER_BVZERO( &id->eid_ndn );
}
#ifdef BACKSQL_ARBITRARY_KEY
if ( !BER_BVISNULL( &id->eid_id ) ) {
- op->o_tmpfree( id->eid_id.bv_val, op->o_tmpmemctx );
+ slap_sl_free( id->eid_id.bv_val, ctx );
BER_BVZERO( &id->eid_id );
}
if ( !BER_BVISNULL( &id->eid_keyval ) ) {
- op->o_tmpfree( id->eid_keyval.bv_val, op->o_tmpmemctx );
+ slap_sl_free( id->eid_keyval.bv_val, ctx );
BER_BVZERO( &id->eid_keyval );
}
#endif /* BACKSQL_ARBITRARY_KEY */
if ( freeit ) {
- op->o_tmpfree( id, op->o_tmpmemctx );
+ slap_sl_free( id, ctx );
}
return next;
ldap_err2string( res ) );
/* cleanup... */
- (void)backsql_free_entryID( op, id, 0 );
+ (void)backsql_free_entryID( id, 0, op->o_tmpmemctx );
}
if ( dn.bv_val != row.cols[ 3 ] ) {
#endif /* ! BACKSQL_ARBITRARY_KEY */
#ifdef BACKSQL_PRETTY_VALIDATE
- validate = at->bam_ad->ad_type->sat_syntax->ssyn_validate;
- pretty = at->bam_ad->ad_type->sat_syntax->ssyn_pretty;
+ validate = at->bam_true_ad->ad_type->sat_syntax->ssyn_validate;
+ pretty = at->bam_true_ad->ad_type->sat_syntax->ssyn_pretty;
if ( validate == NULL && pretty == NULL ) {
return 1;
#endif /* BACKSQL_PRETTY_VALIDATE */
#ifdef BACKSQL_COUNTQUERY
- if ( at->bam_ad->ad_type->sat_equality ) {
- normfunc = at->bam_ad->ad_type->sat_equality->smr_normalize;
+ if ( at->bam_true_ad->ad_type->sat_equality ) {
+ normfunc = at->bam_true_ad->ad_type->sat_equality->smr_normalize;
}
/* Count how many rows will be returned. This avoids memory
return 1;
}
- attr = attr_find( bsi->bsi_e->e_attrs, at->bam_ad );
+ attr = attr_find( bsi->bsi_e->e_attrs, at->bam_true_ad );
if ( attr != NULL ) {
BerVarray tmp;
append = 1;
/* Make space for the array of values */
- attr = attr_alloc( at->bam_ad );
+ attr = attr_alloc( at->bam_true_ad );
attr->a_vals = ch_calloc( count + 1, sizeof( struct berval ) );
if ( attr->a_vals == NULL ) {
Debug( LDAP_DEBUG_TRACE, "Out of memory!\n", 0,0,0 );
}
#endif /* BACKSQL_TRACE */
- /*
- * FIXME: what if a binary
- * is fetched?
+ /* ITS#3386, ITS#3113 - 20070308
+ * If a binary is fetched?
+ * must use the actual size read
+ * from the database.
*/
- ber_str2bv( row.cols[ i ], 0, 0, &bv );
+ if ( BACKSQL_IS_BINARY( row.col_type[ i ] ) ) {
+#ifdef BACKSQL_TRACE
+ Debug( LDAP_DEBUG_ANY,
+ "==>backsql_get_attr_vals(\"%s\"): "
+ "column name %s: data is binary; "
+ "using database size %ld\n",
+ bsi->bsi_e->e_name.bv_val,
+ ad->ad_cname.bv_val,
+ row.value_len[ i ] );
+#endif /* BACKSQL_TRACE */
+ bv.bv_val = row.cols[ i ];
+ bv.bv_len = row.value_len[ i ];
+
+ } else {
+ ber_str2bv( row.cols[ i ], 0, 0, &bv );
+ }
#ifdef BACKSQL_PRETTY_VALIDATE
if ( pretty ) {
struct berval pbv;
- retval = pretty( at->bam_ad->ad_type->sat_syntax,
+ retval = pretty( at->bam_true_ad->ad_type->sat_syntax,
&bv, &pbv, bsi->bsi_op->o_tmpmemctx );
bv = pbv;
} else {
- retval = validate( at->bam_ad->ad_type->sat_syntax,
+ retval = validate( at->bam_true_ad->ad_type->sat_syntax,
&bv );
}
#ifndef BACKSQL_COUNTQUERY
(void)backsql_entry_addattr( bsi->bsi_e,
- at->bam_ad, &bv,
+ at->bam_true_ad, &bv,
bsi->bsi_op->o_tmpmemctx );
#else /* BACKSQL_COUNTQUERY */
struct berval nbv;
retval = (*normfunc)( SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
- at->bam_ad->ad_type->sat_syntax,
- at->bam_ad->ad_type->sat_equality,
+ at->bam_true_ad->ad_type->sat_syntax,
+ at->bam_true_ad->ad_type->sat_equality,
&bv, &nbv,
bsi->bsi_op->o_tmpmemctx );
bsi->bsi_e->e_attrs = NULL;
bsi->bsi_e->e_private = NULL;
- bsi->bsi_oc = backsql_id2oc( bsi->bsi_op->o_bd->be_private,
+ if ( eid->eid_oc == NULL ) {
+ eid->eid_oc = backsql_id2oc( bsi->bsi_op->o_bd->be_private,
eid->eid_oc_id );
+ }
+ bsi->bsi_oc = eid->eid_oc;
bsi->bsi_c_eid = eid;
#ifndef BACKSQL_ARBITRARY_KEY
|| an_find( bsi->bsi_attrs, &AllOper )
|| an_find( bsi->bsi_attrs, &slap_schema.si_ad_structuralObjectClass->ad_cname ) )
{
+ ObjectClass *soc = NULL;
+
if ( BACKSQL_CHECK_SCHEMA( bi ) ) {
Attribute *a;
const char *text = NULL;
char textbuf[ 1024 ];
size_t textlen = sizeof( textbuf );
- ObjectClass *soc = NULL;
struct berval bv[ 2 ],
*nvals;
int rc = LDAP_SUCCESS;
}
if ( !bvmatch( &soc->soc_cname, &bsi->bsi_oc->bom_oc->soc_cname ) ) {
+ if ( !is_object_subclass( bsi->bsi_oc->bom_oc, soc ) ) {
+ Debug( LDAP_DEBUG_TRACE, "backsql_id2entry(%s): "
+ "computed structuralObjectClass %s "
+ "does not match objectClass %s associated "
+ "to entry\n",
+ bsi->bsi_e->e_name.bv_val, soc->soc_cname.bv_val,
+ bsi->bsi_oc->bom_oc->soc_cname.bv_val );
+ backsql_entry_clean( op, bsi->bsi_e );
+ return rc;
+ }
+
Debug( LDAP_DEBUG_TRACE, "backsql_id2entry(%s): "
"computed structuralObjectClass %s "
- "does not match objectClass %s associated "
+ "is subclass of objectClass %s associated "
"to entry\n",
bsi->bsi_e->e_name.bv_val, soc->soc_cname.bv_val,
bsi->bsi_oc->bom_oc->soc_cname.bv_val );
- backsql_entry_clean( op, bsi->bsi_e );
- return rc;
}
+
+ } else {
+ soc = bsi->bsi_oc->bom_oc;
}
rc = attr_merge_normalize_one( bsi->bsi_e,
slap_schema.si_ad_structuralObjectClass,
- &bsi->bsi_oc->bom_oc->soc_cname,
+ &soc->soc_cname,
bsi->bsi_op->o_tmpmemctx );
if ( rc != LDAP_SUCCESS ) {
backsql_entry_clean( op, bsi->bsi_e );
#include "ac/string.h"
#include "slap.h"
+#include "config.h"
#include "proto-sql.h"
int
LDAP_CONTROL_ASSERT,
LDAP_CONTROL_MANAGEDSAIT,
LDAP_CONTROL_NOOP,
-#if 0 /* SLAP_CONTROL_X_TREE_DELETE */
+#ifdef SLAP_CONTROL_X_TREE_DELETE
SLAP_CONTROL_X_TREE_DELETE,
#endif /* SLAP_CONTROL_X_TREE_DELETE */
+ LDAP_CONTROL_PAGEDRESULTS,
NULL
};
bi->bi_entry_release_rw = backsql_entry_release;
bi->bi_connection_init = 0;
- bi->bi_connection_destroy = backsql_connection_destroy;
Debug( LDAP_DEBUG_TRACE,"<==sql_back_initialize()\n", 0, 0, 0 );
return 0;
int
backsql_db_init(
- BackendDB *bd )
+ BackendDB *bd,
+ ConfigReply *cr )
{
backsql_info *bi;
int rc = 0;
int
backsql_db_destroy(
- BackendDB *bd )
+ BackendDB *bd,
+ ConfigReply *cr )
{
backsql_info *bi = (backsql_info*)bd->be_private;
Debug( LDAP_DEBUG_TRACE, "==>backsql_db_destroy()\n", 0, 0, 0 );
- ldap_pvt_thread_mutex_lock( &bi->sql_dbconn_mutex );
backsql_free_db_env( bi );
- ldap_pvt_thread_mutex_unlock( &bi->sql_dbconn_mutex );
ldap_pvt_thread_mutex_destroy( &bi->sql_dbconn_mutex );
- ldap_pvt_thread_mutex_lock( &bi->sql_schema_mutex );
backsql_destroy_schema_map( bi );
- ldap_pvt_thread_mutex_unlock( &bi->sql_schema_mutex );
ldap_pvt_thread_mutex_destroy( &bi->sql_schema_mutex );
if ( bi->sql_dbname ) {
if ( !BER_BVISNULL( &bi->sql_children_cond ) ) {
ch_free( bi->sql_children_cond.bv_val );
}
+ if ( !BER_BVISNULL( &bi->sql_dn_match_cond ) ) {
+ ch_free( bi->sql_dn_match_cond.bv_val );
+ }
if ( !BER_BVISNULL( &bi->sql_subtree_cond ) ) {
ch_free( bi->sql_subtree_cond.bv_val );
}
int
backsql_db_open(
- BackendDB *bd )
+ BackendDB *bd,
+ ConfigReply *cr )
{
backsql_info *bi = (backsql_info*)bd->be_private;
- SQLHDBC dbh = SQL_NULL_HDBC;
struct berbuf bb = BB_NULL;
- OperationBuffer opbuf;
- Operation* op = (Operation *) &opbuf;
-
+ Connection conn = { 0 };
+ OperationBuffer opbuf;
+ Operation* op;
+ SQLHDBC dbh = SQL_NULL_HDBC;
+ void *thrctx = ldap_pvt_thread_pool_context();
+
Debug( LDAP_DEBUG_TRACE, "==>backsql_db_open(): "
"testing RDBMS connection\n", 0, 0, 0 );
if ( bi->sql_dbname == NULL ) {
};
struct berbuf bb = BB_NULL;
+ Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
+ "subtree search SQL condition not specified "
+ "(use \"subtree_cond\" directive in slapd.conf); "
+ "preparing default\n",
+ 0, 0, 0);
+
if ( backsql_prepare_pattern( bi->sql_concat_func, values,
&concat ) ) {
Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
- "unable to prepare CONCAT pattern", 0, 0, 0 );
+ "unable to prepare CONCAT pattern for subtree search",
+ 0, 0, 0 );
return 1;
}
- Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
- "subtree search SQL condition not specified "
- "(use \"subtree_cond\" directive in slapd.conf)\n",
- 0, 0, 0);
-
if ( bi->sql_upper_func.bv_val ) {
/*
bi->sql_subtree_cond = bb.bb_val;
Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
- "setting \"%s\" as default\n",
+ "setting \"%s\" as default \"subtree_cond\"\n",
bi->sql_subtree_cond.bv_val, 0, 0 );
}
if ( bi->sql_children_cond.bv_val == NULL ) {
+ /*
+ * Prepare concat function for children search condition
+ */
+ struct berval concat;
+ struct berval values[] = {
+ BER_BVC( "'%,'" ),
+ BER_BVC( "?" ),
+ BER_BVNULL
+ };
struct berbuf bb = BB_NULL;
+ Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
+ "children search SQL condition not specified "
+ "(use \"children_cond\" directive in slapd.conf); "
+ "preparing default\n",
+ 0, 0, 0);
+
+ if ( backsql_prepare_pattern( bi->sql_concat_func, values,
+ &concat ) ) {
+ Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
+ "unable to prepare CONCAT pattern for children search", 0, 0, 0 );
+ return 1;
+ }
+
if ( bi->sql_upper_func.bv_val ) {
/*
* UPPER(ldap_entries.dn) LIKE UPPER(CONCAT('%,',?))
*/
- backsql_strfcat_x( &bb, NULL, "blbl",
+ backsql_strfcat_x( &bb, NULL, "blbbb",
+ &bi->sql_upper_func,
+ (ber_len_t)STRLENOF( "(ldap_entries.dn) LIKE " ),
+ "(ldap_entries.dn) LIKE ",
+ &bi->sql_upper_func_open,
+ &concat,
+ &bi->sql_upper_func_close );
+
+ } else {
+
+ /*
+ * ldap_entries.dn LIKE CONCAT('%,',?)
+ */
+
+ backsql_strfcat_x( &bb, NULL, "lb",
+ (ber_len_t)STRLENOF( "ldap_entries.dn LIKE " ),
+ "ldap_entries.dn LIKE ",
+ &concat );
+ }
+
+ ch_free( concat.bv_val );
+
+ bi->sql_children_cond = bb.bb_val;
+
+ Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
+ "setting \"%s\" as default \"children_cond\"\n",
+ bi->sql_children_cond.bv_val, 0, 0 );
+ }
+
+ if ( bi->sql_dn_match_cond.bv_val == NULL ) {
+ /*
+ * Prepare concat function for dn match search condition
+ */
+ struct berbuf bb = BB_NULL;
+
+ Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
+ "DN match search SQL condition not specified "
+ "(use \"dn_match_cond\" directive in slapd.conf); "
+ "preparing default\n",
+ 0, 0, 0);
+
+ if ( bi->sql_upper_func.bv_val ) {
+
+ /*
+ * UPPER(ldap_entries.dn)=?
+ */
+
+ backsql_strfcat_x( &bb, NULL, "blbcb",
&bi->sql_upper_func,
(ber_len_t)STRLENOF( "(ldap_entries.dn)=" ),
"(ldap_entries.dn)=",
- &bi->sql_upper_func,
- (ber_len_t)STRLENOF( "(?)" ), "(?)" );
+ &bi->sql_upper_func_open,
+ '?',
+ &bi->sql_upper_func_close );
} else {
/*
- * ldap_entries.dn LIKE CONCAT('%,',?)
+ * ldap_entries.dn=?
*/
backsql_strfcat_x( &bb, NULL, "l",
(ber_len_t)STRLENOF( "ldap_entries.dn=?" ),
- "ldap_entries.dn=?");
+ "ldap_entries.dn=?" );
}
- bi->sql_children_cond = bb.bb_val;
+ bi->sql_dn_match_cond = bb.bb_val;
Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
- "setting \"%s\" as default\n",
- bi->sql_children_cond.bv_val, 0, 0 );
+ "setting \"%s\" as default \"dn_match_cond\"\n",
+ bi->sql_dn_match_cond.bv_val, 0, 0 );
}
if ( bi->sql_oc_query == NULL ) {
}
/* This should just be to force schema loading */
- op->o_hdr = (Opheader *)&op[ 1 ];
- op->o_connid = (unsigned long)(-1);
+ connection_fake_init( &conn, &opbuf, thrctx );
+ op = &opbuf.ob_op;
op->o_bd = bd;
if ( backsql_get_db_conn( op, &dbh ) != LDAP_SUCCESS ) {
Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
"connection failed, exiting\n", 0, 0, 0 );
return 1;
}
-
- if ( backsql_free_db_conn( op ) != SQL_SUCCESS ) {
+ if ( backsql_load_schema_map( bi, dbh ) != LDAP_SUCCESS ) {
+ Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
+ "schema mapping failed, exiting\n", 0, 0, 0 );
+ return 1;
+ }
+ if ( backsql_free_db_conn( op, dbh ) != SQL_SUCCESS ) {
Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
"connection free failed\n", 0, 0, 0 );
}
}
/*
- * Prepare children ID selection query
+ * Prepare children count query
*/
BER_BVZERO( &bb.bb_val );
bb.bb_len = 0;
"FROM ldap_entries,ldap_entries ",
&bi->sql_aliasing, "subordinates "
"WHERE subordinates.parent=ldap_entries.id AND ",
- &bi->sql_children_cond );
+ &bi->sql_dn_match_cond );
bi->sql_has_children_query = bb.bb_val.bv_val;
/*
int
backsql_db_close(
- BackendDB *bd )
+ BackendDB *bd,
+ ConfigReply *cr )
{
backsql_info *bi = (backsql_info*)bd->be_private;
return 0;
}
-int
-backsql_connection_destroy( Backend *bd, Connection *c )
-{
- OperationBuffer opbuf;
- Operation* op = (Operation *) &opbuf;
-
- op->o_hdr = (Opheader *)&op[ 1 ];
- op->o_connid = c->c_connid;
- op->o_bd = bd;
-
- Debug( LDAP_DEBUG_TRACE, "==>backsql_connection_destroy()\n", 0, 0, 0 );
- backsql_free_db_conn( op );
- Debug( LDAP_DEBUG_TRACE, "<==backsql_connection_destroy()\n", 0, 0, 0 );
-
- return 0;
-}
-
#if SLAPD_SQL == SLAPD_MOD_DYNAMIC
/* conditionally define the init_module() function */
LDAP_SCOPE_BASE,
(time_t)(-1), NULL, dbh, op, rs,
slap_anlist_all_attributes,
- ( BACKSQL_ISF_MATCHED | BACKSQL_ISF_GET_ENTRY ) );
+ ( BACKSQL_ISF_MATCHED | BACKSQL_ISF_GET_ENTRY | BACKSQL_ISF_GET_OC ) );
switch ( rs->sr_err ) {
case LDAP_SUCCESS:
break;
slap_mods_opattrs( op, &op->orm_modlist, 1 );
- oc = backsql_id2oc( bi, bsi.bsi_base_id.eid_oc_id );
- assert( oc != NULL );
+ assert( bsi.bsi_base_id.eid_oc != NULL );
+ oc = bsi.bsi_base_id.eid_oc;
- if ( !acl_check_modlist( op, &m, op->oq_modify.rs_modlist ) ) {
+ if ( !acl_check_modlist( op, &m, op->orm_modlist ) ) {
rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
e = &m;
goto done;
}
rs->sr_err = backsql_modify_internal( op, rs, dbh, oc,
- &bsi.bsi_base_id, op->oq_modify.rs_modlist );
+ &bsi.bsi_base_id, op->orm_modlist );
if ( rs->sr_err != LDAP_SUCCESS ) {
e = &m;
goto do_transact;
slap_graduate_commit_csn( op );
if ( !BER_BVISNULL( &bsi.bsi_base_id.eid_ndn ) ) {
- (void)backsql_free_entryID( op, &bsi.bsi_base_id, 0 );
+ (void)backsql_free_entryID( &bsi.bsi_base_id, 0, op->o_tmpmemctx );
}
if ( !BER_BVISNULL( &m.e_nname ) ) {
LDAP_SCOPE_BASE,
(time_t)(-1), NULL, dbh, op, rs,
slap_anlist_all_attributes,
- ( BACKSQL_ISF_MATCHED | BACKSQL_ISF_GET_ENTRY ) );
+ ( BACKSQL_ISF_MATCHED | BACKSQL_ISF_GET_ENTRY | BACKSQL_ISF_GET_OC ) );
switch ( rs->sr_err ) {
case LDAP_SUCCESS:
break;
*/
bsi.bsi_e = &p;
e_id = bsi.bsi_base_id;
+ memset( &bsi.bsi_base_id, 0, sizeof( bsi.bsi_base_id ) );
rs->sr_err = backsql_init_search( &bsi, &pndn,
LDAP_SCOPE_BASE,
(time_t)(-1), NULL, dbh, op, rs,
}
if ( newSuperior ) {
- (void)backsql_free_entryID( op, &bsi.bsi_base_id, 0 );
+ (void)backsql_free_entryID( &bsi.bsi_base_id, 0, op->o_tmpmemctx );
/*
* namingContext "" is not supported
new_npdn = &pndn;
}
+ memset( &bsi.bsi_base_id, 0, sizeof( bsi.bsi_base_id ) );
+
if ( newSuperior && dn_match( &pndn, new_npdn ) ) {
Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): "
"newSuperior is equal to old parent - ignored\n",
slap_mods_opattrs( op, &op->orr_modlist, 1 );
- oc = backsql_id2oc( bi, e_id.eid_oc_id );
+ assert( e_id.eid_oc != NULL );
+ oc = e_id.eid_oc;
rs->sr_err = backsql_modify_internal( op, rs, dbh, oc, &e_id, op->orr_modlist );
slap_graduate_commit_csn( op );
if ( rs->sr_err != LDAP_SUCCESS ) {
char textbuf[ SLAP_TEXT_BUFLEN ] = { '\0' };
backsql_entry_clean( op, &r );
- (void)backsql_free_entryID( op, &e_id, 0 );
+ (void)backsql_free_entryID( &e_id, 0, op->o_tmpmemctx );
bsi.bsi_e = &r;
rs->sr_err = backsql_init_search( &bsi, &new_ndn,
}
if ( !BER_BVISNULL( &e_id.eid_ndn ) ) {
- (void)backsql_free_entryID( op, &e_id, 0 );
+ (void)backsql_free_entryID( &e_id, 0, op->o_tmpmemctx );
}
if ( !BER_BVISNULL( &n_id.eid_ndn ) ) {
- (void)backsql_free_entryID( op, &n_id, 0 );
+ (void)backsql_free_entryID( &n_id, 0, op->o_tmpmemctx );
}
if ( !BER_BVISNULL( &r.e_nname ) ) {
*ap = backsql_operational_entryUUID( bi, &bsi.bsi_base_id );
- (void)backsql_free_entryID( op, &bsi.bsi_base_id, 0 );
+ (void)backsql_free_entryID( &bsi.bsi_base_id, 0, op->o_tmpmemctx );
if ( bsi.bsi_attrs != NULL ) {
op->o_tmpfree( bsi.bsi_attrs, op->o_tmpmemctx );
#endif /* BACKSQL_ARBITRARY_KEY */
/* stores in *id the ID in table ldap_entries corresponding to DN, if any */
-int backsql_dn2id( Operation *op, SlapReply *rs, SQLHDBC dbh,
+extern int
+backsql_dn2id( Operation *op, SlapReply *rs, SQLHDBC dbh,
struct berval *ndn, backsql_entryID *id,
int matched, int muck );
/* stores in *nchildren the count of children for an entry */
-int backsql_count_children( Operation *op, SQLHDBC dbh,
+extern int
+backsql_count_children( Operation *op, SQLHDBC dbh,
struct berval *dn, unsigned long *nchildren );
/* returns LDAP_COMPARE_TRUE/LDAP_COMPARE_FALSE if the entry corresponding
* to DN has/has not children */
-int backsql_has_children( Operation *op, SQLHDBC dbh, struct berval *dn );
+extern int
+backsql_has_children( Operation *op, SQLHDBC dbh, struct berval *dn );
-/* frees *id and returns next in list */
-backsql_entryID *backsql_free_entryID( Operation *op, backsql_entryID *id,
- int freeit );
+/* free *id and return next in list */
+extern backsql_entryID *
+backsql_free_entryID( backsql_entryID *id, int freeit, void *ctx );
-/* turns an ID into an entry */
-int backsql_id2entry( backsql_srch_info *bsi, backsql_entryID *id );
+/* turn an ID into an entry */
+extern int
+backsql_id2entry( backsql_srch_info *bsi, backsql_entryID *id );
+
+/* duplicate an entryID */
+extern backsql_entryID *
+backsql_entryID_dup( backsql_entryID *eid, void *ctx );
/*
* operational.c
int backsql_free_db_env( backsql_info *si );
-int backsql_get_db_conn( Operation *op, SQLHDBC *dbh );
+int backsql_get_db_conn( Operation *op, SQLHDBC *dbh );
-int backsql_free_db_conn( Operation *op );
+int backsql_free_db_conn( Operation *op, SQLHDBC dbh );
/*
* util.c
pers_id int NOT NULL
);
-
+drop table if exists certs;
+CREATE TABLE certs (
+ id int NOT NULL ,
+ cert LONGBLOB NOT NULL,
+ pers_id int NOT NULL
+);
ALTER TABLE authors_docs ADD
CONSTRAINT PK_authors_docs PRIMARY KEY
id
);
+ALTER TABLE certs ADD
+ CONSTRAINT PK_certs PRIMARY KEY
+ (
+ id
+ );
+
drop table if exists referrals;
CREATE TABLE referrals (
id int NOT NULL,
insert into authors_docs (pers_id,doc_id) values (2,1);
insert into referrals (id,name,url) values (1,'Referral','ldap://localhost:9012/');
+
+insert into certs (id,cert,pers_id) values (1,UNHEX('3082036b308202d4a003020102020102300d06092a864886f70d01010405003077310b3009060355040613025553311330110603550408130a43616c69666f726e6961311f301d060355040a13164f70656e4c444150204578616d706c652c204c74642e311330110603550403130a4578616d706c65204341311d301b06092a864886f70d010901160e6361406578616d706c652e636f6d301e170d3033313031373136333331395a170d3034313031363136333331395a307e310b3009060355040613025553311330110603550408130a43616c69666f726e6961311f301d060355040a13164f70656e4c444150204578616d706c652c204c74642e311830160603550403130f557273756c612048616d7073746572311f301d06092a864886f70d01090116107568616d406578616d706c652e636f6d30819f300d06092a864886f70d010101050003818d0030818902818100eec60a7910b57d2e687158ca55eea738d36f10413dfecf31435e1aeeb9713b8e2da7dd2dde6bc6cec03b4987eaa7b037b9eb50e11c71e58088cc282883122cd8329c6f24f6045e6be9d21b9190c8292998267a5f7905292de936262747ab4b76a88a63872c41629a69d32e894d44c896a8d06fab0a1bc7de343c6c1458478f290203010001a381ff3081fc30090603551d1304023000302c06096086480186f842010d041f161d4f70656e53534c2047656e657261746564204365727469666963617465301d0603551d0e04160414a323de136c19ae0c479450e882dfb10ad147f45e3081a10603551d2304819930819680144b6f211a3624d290f943b053472d7de1c0e69823a17ba4793077310b3009060355040613025553311330110603550408130a43616c69666f726e6961311f301d060355040a13164f70656e4c444150204578616d706c652c204c74642e311330110603550403130a4578616d706c65204341311d301b06092a864886f70d010901160e6361406578616d706c652e636f6d820100300d06092a864886f70d010104050003818100881470045bdce95660d6e6af59e6a844aec4b9f5eaea88d4eb7a5a47080afa64750f81a3e47d00fd39c69a17a1c66d29d36f06edc537107f8c592239c2d4da55fb3f1d488e7b2387ad2a551cbd1ceb070ae9e020a9467275cb28798abb4cbfff98ddb3f1e7689b067072392511bb08125b5bec2bc207b7b6b275c47248f29acd'),3);
+
insert into ldap_attr_mappings (id,oc_map_id,name,sel_expr,from_tbls,join_where,add_proc,delete_proc,param_order,expect_return)
values (14,4,'ref','referrals.url','referrals',NULL,NULL,NULL,3,0);
+insert into ldap_attr_mappings (id,oc_map_id,name,sel_expr,from_tbls,join_where,add_proc,delete_proc,param_order,expect_return)
+values (15,1,'userCertificate','certs.cert','persons,certs',
+ 'certs.pers_id=persons.id',NULL,NULL,3,0);
+
-- entries mapping: each entry must appear in this table, with a unique DN rooted at the database naming context
-- id a unique number > 0 identifying the entry
-- dn the DN of the entry, in "pretty" form
insert into ldap_entry_objclasses (entry_id,oc_name)
values (1,'dcObject');
+insert into ldap_entry_objclasses (entry_id,oc_name)
+values (4,'pkiUser');
+
insert into ldap_entry_objclasses (entry_id,oc_name)
values (7,'extensibleObject');
pers_id int not null
);
+drop table certs;
+drop sequence certs_id_seq;
+CREATE TABLE certs (
+ id int not null primary key,
+ cert bytea not null,
+ pers_id int not null
+);
+
drop table referrals;
drop sequence referrals_id_seq;
create table referrals (
insert into authors_docs (pers_id,doc_id) values (2,1);
insert into referrals (id,name,url) values (1,'Referral','ldap://localhost:9012/');
+
+insert into certs (id,cert,pers_id) values (1,decode('MIIDazCCAtSgAwIBAgIBAjANBgkqhkiG9w0BAQQFADB3MQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEfMB0GA1UEChMWT3BlbkxEQVAgRXhhbXBsZSwgTHRkLjETMBEGA1UEAxMKRXhhbXBsZSBDQTEdMBsGCSqGSIb3DQEJARYOY2FAZXhhbXBsZS5jb20wHhcNMDMxMDE3MTYzMzE5WhcNMDQxMDE2MTYzMzE5WjB+MQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEfMB0GA1UEChMWT3BlbkxEQVAgRXhhbXBsZSwgTHRkLjEYMBYGA1UEAxMPVXJzdWxhIEhhbXBzdGVyMR8wHQYJKoZIhvcNAQkBFhB1aGFtQGV4YW1wbGUuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDuxgp5ELV9LmhxWMpV7qc4028QQT3+zzFDXhruuXE7ji2n3S3ea8bOwDtJh+qnsDe561DhHHHlgIjMKCiDEizYMpxvJPYEXmvp0huRkMgpKZgmel95BSkt6TYmJ0erS3aoimOHLEFimmnTLolNRMiWqNBvqwobx940PGwUWEePKQIDAQABo4H/MIH8MAkGA1UdEwQCMAAwLAYJYIZIAYb4QgENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0GA1UdDgQWBBSjI94TbBmuDEeUUOiC37EK0Uf0XjCBoQYDVR0jBIGZMIGWgBRLbyEaNiTSkPlDsFNHLX3hwOaYI6F7pHkwdzELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExHzAdBgNVBAoTFk9wZW5MREFQIEV4YW1wbGUsIEx0ZC4xEzARBgNVBAMTCkV4YW1wbGUgQ0ExHTAbBgkqhkiG9w0BCQEWDmNhQGV4YW1wbGUuY29tggEAMA0GCSqGSIb3DQEBBAUAA4GBAIgUcARb3OlWYNbmr1nmqESuxLn16uqI1Ot6WkcICvpkdQ+Bo+R9AP05xpoXocZtKdNvBu3FNxB/jFkiOcLU2lX7Px1Ijnsjh60qVRy9HOsHCungIKlGcnXLKHmKu0y//5jds/HnaJsGcHI5JRG7CBJbW+wrwge3trJ1xHJI8prN','base64'),3);
+
insert into ldap_attr_mappings (id,oc_map_id,name,sel_expr,from_tbls,join_where,add_proc,delete_proc,param_order,expect_return) values (14,4,'ref','referrals.url','referrals',NULL,'UPDATE referrals SET url=? WHERE id=?','SELECT 1 FROM referrals WHERE url=? and id=? and 1=0',3,0);
+insert into ldap_attr_mappings (id,oc_map_id,name,sel_expr,from_tbls,join_where,add_proc,delete_proc,param_order,expect_return) values (15,1,'userCertificate','certs.cert','persons,certs','certs.pers_id=persons.id',NULL,NULL,3,0);
+
-- entries mapping: each entry must appear in this table, with a unique DN rooted at the database naming context
-- id a unique number > 0 identifying the entry
-- dn the DN of the entry, in "pretty" form
-- oc_name the name of the objectClass; it MUST match the name of an objectClass that is loaded in slapd's schema
insert into ldap_entry_objclasses (entry_id,oc_name) values (1,'dcObject');
+insert into ldap_entry_objclasses (entry_id,oc_name) values (4,'pkiUser');
+
insert into ldap_entry_objclasses (entry_id,oc_name) values (7,'extensibleObject');
-- procedures
const backsql_at_map_rec *m1 = v_m1,
*m2 = v_m2;
+ if ( slap_ad_is_binary( m1->bam_ad ) || slap_ad_is_binary( m2->bam_ad ) ) {
+#ifdef BACKSQL_USE_PTR_CMP
+ return SLAP_PTRCMP( m1->bam_ad->ad_type, m2->bam_ad->ad_type );
+#else /* ! BACKSQL_USE_PTR_CMP */
+ return ber_bvcmp( &m1->bam_ad->ad_type->sat_cname, &m2->bam_ad->ad_type->sat_cname );
+#endif /* ! BACKSQL_USE_PTR_CMP */
+ }
+
#ifdef BACKSQL_USE_PTR_CMP
return SLAP_PTRCMP( m1->bam_ad, m2->bam_ad );
#else /* ! BACKSQL_USE_PTR_CMP */
backsql_at_map_rec *m1 = v_m1,
*m2 = v_m2;
- assert( m1->bam_ad == m2->bam_ad );
+ if ( slap_ad_is_binary( m1->bam_ad ) || slap_ad_is_binary( m2->bam_ad ) ) {
+#ifdef BACKSQL_USE_PTR_CMP
+ assert( m1->bam_ad->ad_type == m2->bam_ad->ad_type );
+#else /* ! BACKSQL_USE_PTR_CMP */
+ assert( ber_bvcmp( &m1->bam_ad->ad_type->sat_cname, &m2->bam_ad->ad_type->sat_cname ) == 0 );
+#endif /* ! BACKSQL_USE_PTR_CMP */
+
+ } else {
+#ifdef BACKSQL_USE_PTR_CMP
+ assert( m1->bam_ad == m2->bam_ad );
+#else /* ! BACKSQL_USE_PTR_CMP */
+ assert( ber_bvcmp( &m1->bam_ad->ad_cname, &m2->bam_ad->ad_cname ) == 0 );
+#endif /* ! BACKSQL_USE_PTR_CMP */
+ }
/* duplicate definitions of attributeTypes are appended;
* this allows to define multiple rules for the same
* attributeType. Use with care! */
for ( ; m1->bam_next ; m1 = m1->bam_next );
+
m1->bam_next = m2;
m2->bam_next = NULL;
at_map = (backsql_at_map_rec *)ch_calloc(1,
sizeof( backsql_at_map_rec ) );
at_map->bam_ad = slap_schema.si_ad_objectClass;
+ at_map->bam_true_ad = slap_schema.si_ad_objectClass;
ber_str2bv( "ldap_entry_objclasses.oc_name", 0, 1,
&at_map->bam_sel_expr );
ber_str2bv( "ldap_entry_objclasses,ldap_entries", 0, 1,
at_map = (backsql_at_map_rec *)ch_calloc( 1,
sizeof( backsql_at_map_rec ) );
at_map->bam_ad = ad;
+ at_map->bam_true_ad = ad;
+ if ( slap_syntax_is_binary( ad->ad_type->sat_syntax )
+ && !slap_ad_is_binary( ad ) )
+ {
+ char buf[ BUFSIZ ];
+ struct berval bv;
+ const char *text = NULL;
+
+ bv.bv_val = buf;
+ bv.bv_len = snprintf( buf, sizeof( buf ), "%s;binary",
+ ad->ad_cname.bv_val );
+ at_map->bam_true_ad = NULL;
+ bas->bas_rc = slap_bv2ad( &bv, &at_map->bam_true_ad, &text );
+ if ( bas->bas_rc != LDAP_SUCCESS ) {
+ Debug( LDAP_DEBUG_TRACE, "backsql_oc_get_attr_mapping(): "
+ "unable to fetch attribute \"%s\": %s (%d)\n",
+ buf, text, rc );
+ return BACKSQL_AVL_STOP;
+ }
+ }
ber_str2bv( at_row.cols[ 1 ], 0, 1, &at_map->bam_sel_expr );
if ( at_row.value_len[ 8 ] < 0 ) {
backsql_at_map_rec *
backsql_ad2at( backsql_oc_map_rec* objclass, AttributeDescription *ad )
{
- backsql_at_map_rec tmp, *res;
+ backsql_at_map_rec tmp = { 0 }, *res;
#ifdef BACKSQL_TRACE
Debug( LDAP_DEBUG_TRACE, "==>backsql_ad2at(): "
static int backsql_process_filter_attr( backsql_srch_info *bsi, Filter *f,
backsql_at_map_rec *at );
+/* For LDAP_CONTROL_PAGEDRESULTS, a 32 bit cookie is available to keep track of
+ the state of paged results. The ldap_entries.id and oc_map_id values of the
+ last entry returned are used as the cookie, so 6 bits are used for the OC id
+ and the other 26 for ldap_entries ID number. If your max(oc_map_id) is more
+ than 63, you will need to steal more bits from ldap_entries ID number and
+ put them into the OC ID part of the cookie. */
+#define SQL_TO_PAGECOOKIE(id, oc) (((id) << 6 ) | ((oc) & 0x3F))
+#define PAGECOOKIE_TO_SQL_ID(pc) ((pc) >> 6)
+#define PAGECOOKIE_TO_SQL_OC(pc) ((pc) & 0x3F)
+
+static int parse_paged_cookie( Operation *op, SlapReply *rs );
+
+static void send_paged_response(
+ Operation *op,
+ SlapReply *rs,
+ ID *lastid );
+
static int
backsql_attrlist_add( backsql_srch_info *bsi, AttributeDescription *ad )
{
return 1;
}
+ /* strip ';binary' */
+ if ( slap_ad_is_binary( ad ) ) {
+ ad = ad->ad_type->sat_ad;
+ }
+
for ( ; !BER_BVISNULL( &bsi->bsi_attrs[ n_attrs ].an_name ); n_attrs++ ) {
an = &bsi->bsi_attrs[ n_attrs ];
rs->sr_err = rc;
}
}
+
+ if ( gotit && BACKSQL_IS_GET_OC( flags ) ) {
+ bsi->bsi_base_id.eid_oc = backsql_id2oc( bi,
+ bsi->bsi_base_id.eid_oc_id );
+ if ( bsi->bsi_base_id.eid_oc == NULL ) {
+ /* error? */
+ backsql_free_entryID( &bsi->bsi_base_id, 1,
+ op->o_tmpmemctx );
+ rc = rs->sr_err = LDAP_OTHER;
+ }
+ }
}
bsi->bsi_status = rc;
(ber_len_t)STRLENOF( "9=9"), "9=9");
} else if ( !BER_BVISNULL( &bi->sql_subtree_cond ) ) {
+ /* This should always be true... */
backsql_strfcat_x( &bsi->bsi_join_where,
bsi->bsi_op->o_tmpmemctx,
"b",
assert( 0 );
}
+ /* If paged results are in effect, ignore low ldap_entries.id numbers */
+ if ( get_pagedresults(bsi->bsi_op) > SLAP_CONTROL_IGNORED ) {
+ unsigned long lowid = 0;
+
+ /* Pick up the previous ldap_entries.id if the previous page ended in this objectClass */
+ if ( bsi->bsi_oc->bom_id == PAGECOOKIE_TO_SQL_OC( ((PagedResultsState *)bsi->bsi_op->o_pagedresults_state)->ps_cookie ) )
+ {
+ lowid = PAGECOOKIE_TO_SQL_ID( ((PagedResultsState *)bsi->bsi_op->o_pagedresults_state)->ps_cookie );
+ }
+
+ if ( lowid ) {
+ char lowidstring[48];
+ int lowidlen;
+
+ lowidlen = snprintf( lowidstring, sizeof( lowidstring ),
+ " AND ldap_entries.id>%lu", lowid );
+ backsql_strfcat_x( &bsi->bsi_join_where,
+ bsi->bsi_op->o_tmpmemctx,
+ "l",
+ (ber_len_t)lowidlen,
+ lowidstring );
+ }
+ }
+
rc = backsql_process_filter( bsi, bsi->bsi_filter );
if ( rc > 0 ) {
struct berbuf bb = BB_NULL;
return BACKSQL_AVL_STOP;
}
+ /* If paged results have already completed this objectClass, skip it */
+ if ( get_pagedresults(op) > SLAP_CONTROL_IGNORED ) {
+ if ( oc->bom_id < PAGECOOKIE_TO_SQL_OC( ((PagedResultsState *)op->o_pagedresults_state)->ps_cookie ) )
+ {
+ return BACKSQL_AVL_CONTINUE;
+ }
+ }
+
if ( bsi->bsi_n_candidates == -1 ) {
Debug( LDAP_DEBUG_TRACE, "backsql_oc_get_candidates(): "
"unchecked limit has been overcome\n", 0, 0, 0 );
goto cleanup;
}
#endif /* ! BACKSQL_ARBITRARY_KEY */
+ c_id->eid_oc = bsi->bsi_oc;
c_id->eid_oc_id = bsi->bsi_oc->bom_id;
c_id->eid_dn = pdn;
backsql_srch_info bsi = { 0 };
backsql_entryID *eid = NULL;
struct berval nbase = BER_BVNULL;
+ unsigned long lastid = 0;
Debug( LDAP_DEBUG_TRACE, "==>backsql_search(): "
"base=\"%s\", filter=\"%s\", scope=%d,",
( op->ors_limit->lms_s_unchecked == -1 ? -2 :
( op->ors_limit->lms_s_unchecked ) ) );
+ /* If paged results are in effect, check the paging cookie */
+ if ( get_pagedresults( op ) > SLAP_CONTROL_IGNORED ) {
+ rs->sr_err = parse_paged_cookie( op, rs );
+ if ( rs->sr_err != LDAP_SUCCESS ) {
+ send_ldap_result( op, rs );
+ goto done;
+ }
+ }
+
switch ( bsi.bsi_scope ) {
case LDAP_SCOPE_BASE:
case BACKSQL_SCOPE_BASE_LIKE:
/*
* for each objectclass we try to construct query which gets IDs
* of entries matching LDAP query filter and scope (or at least
- * candidates), and get the IDs
+ * candidates), and get the IDs. Do this in ID order for paging.
*/
- avl_apply( bi->sql_oc_by_oc, backsql_oc_get_candidates,
+ avl_apply( bi->sql_oc_by_id, backsql_oc_get_candidates,
&bsi, BACKSQL_AVL_STOP, AVL_INORDER );
/* check for abandon */
* and then send to client; don't free entry_id if baseObject...
*/
for ( eid = bsi.bsi_id_list;
- eid != NULL;
- eid = backsql_free_entryID( op,
- eid, eid == &bsi.bsi_base_id ? 0 : 1 ) )
+ eid != NULL;
+ eid = backsql_free_entryID(
+ eid, eid == &bsi.bsi_base_id ? 0 : 1, op->o_tmpmemctx ) )
{
int rc;
Attribute *a_hasSubordinate = NULL,
case LDAP_SCOPE_SUBTREE:
/* FIXME: this should never fail... */
if ( !dnIsSuffix( &eid->eid_ndn, &op->o_req_ndn ) ) {
- assert( 0 );
goto next_entry2;
}
break;
rs->sr_ref = NULL;
rs->sr_matched = NULL;
rs->sr_entry = NULL;
+ if ( rs->sr_err == LDAP_REFERRAL ) {
+ rs->sr_err = LDAP_SUCCESS;
+ }
goto next_entry;
}
if ( test_filter( op, e, op->ors_filter ) == LDAP_COMPARE_TRUE )
{
+ /* If paged results are in effect, see if the page limit was exceeded */
+ if ( get_pagedresults(op) > SLAP_CONTROL_IGNORED ) {
+ if ( rs->sr_nentries >= ((PagedResultsState *)op->o_pagedresults_state)->ps_size )
+ {
+ e = NULL;
+ send_paged_response( op, rs, &lastid );
+ goto done;
+ }
+ lastid = SQL_TO_PAGECOOKIE( eid->eid_id, eid->eid_oc_id );
+ }
rs->sr_attrs = op->ors_attrs;
rs->sr_operational_attrs = NULL;
rs->sr_entry = e;
+ e->e_private = (void *)eid;
rs->sr_flags = ( e == &user_entry ) ? REP_ENTRY_MODIFIABLE : 0;
/* FIXME: need the whole entry (ITS#3480) */
rs->sr_err = send_search_entry( op, rs );
+ e->e_private = NULL;
rs->sr_entry = NULL;
rs->sr_attrs = NULL;
rs->sr_operational_attrs = NULL;
send_results:;
if ( rs->sr_err != SLAPD_ABANDON ) {
- send_ldap_result( op, rs );
+ if ( get_pagedresults(op) > SLAP_CONTROL_IGNORED ) {
+ send_paged_response( op, rs, NULL );
+ } else {
+ send_ldap_result( op, rs );
+ }
}
/* cleanup in case of abandon */
for ( ; eid != NULL;
- eid = backsql_free_entryID( op,
- eid, eid == &bsi.bsi_base_id ? 0 : 1 ) )
+ eid = backsql_free_entryID(
+ eid, eid == &bsi.bsi_base_id ? 0 : 1, op->o_tmpmemctx ) )
;
backsql_entry_clean( op, &base_entry );
slap_callback cb = { 0 };
op2.o_tag = LDAP_REQ_ADD;
- op2.o_bd = select_backend( &op->o_bd->be_nsuffix[0], 0, 0 );
+ op2.o_bd = select_backend( &op->o_bd->be_nsuffix[0], 0 );
op2.ora_e = e;
op2.o_callback = &cb;
#endif /* BACKSQL_SYNCPROV */
done:;
- (void)backsql_free_entryID( op, &bsi.bsi_base_id, 0 );
+ (void)backsql_free_entryID( &bsi.bsi_base_id, 0, op->o_tmpmemctx );
if ( bsi.bsi_attrs != NULL ) {
op->o_tmpfree( bsi.bsi_attrs, op->o_tmpmemctx );
*ent = NULL;
rc = backsql_get_db_conn( op, &dbh );
- if ( !dbh ) {
- return LDAP_OTHER;
+ if ( rc != LDAP_SUCCESS ) {
+ return rc;
}
if ( at ) {
BACKSQL_ISF_GET_ENTRY );
if ( !BER_BVISNULL( &bsi.bsi_base_id.eid_ndn ) ) {
- (void)backsql_free_entryID( op, &bsi.bsi_base_id, 0 );
+ (void)backsql_free_entryID( &bsi.bsi_base_id, 0, op->o_tmpmemctx );
}
if ( rc == LDAP_SUCCESS ) {
{
backsql_entry_clean( op, e );
- ch_free( e );
+ entry_free( e );
return 0;
}
+
+
+/* This function is copied verbatim from back-bdb/search.c */
+static int
+parse_paged_cookie( Operation *op, SlapReply *rs )
+{
+ LDAPControl **c;
+ int rc = LDAP_SUCCESS;
+ ber_tag_t tag;
+ ber_int_t size;
+ BerElement *ber;
+ struct berval cookie = BER_BVNULL;
+ PagedResultsState *ps = op->o_pagedresults_state;
+
+ /* this function must be invoked only if the pagedResults
+ * control has been detected, parsed and partially checked
+ * by the frontend */
+ assert( get_pagedresults( op ) > SLAP_CONTROL_IGNORED );
+
+ /* look for the appropriate ctrl structure */
+ for ( c = op->o_ctrls; c[0] != NULL; c++ ) {
+ if ( strcmp( c[0]->ldctl_oid, LDAP_CONTROL_PAGEDRESULTS ) == 0 )
+ {
+ break;
+ }
+ }
+
+ if ( c[0] == NULL ) {
+ rs->sr_text = "missing pagedResults control";
+ return LDAP_PROTOCOL_ERROR;
+ }
+
+ /* Tested by frontend */
+ assert( c[0]->ldctl_value.bv_len > 0 );
+
+ /* Parse the control value
+ * realSearchControlValue ::= SEQUENCE {
+ * size INTEGER (0..maxInt),
+ * -- requested page size from client
+ * -- result set size estimate from server
+ * cookie OCTET STRING
+ * }
+ */
+ ber = ber_init( &c[0]->ldctl_value );
+ if ( ber == NULL ) {
+ rs->sr_text = "internal error";
+ return LDAP_OTHER;
+ }
+
+ tag = ber_scanf( ber, "{im}", &size, &cookie );
+
+ /* Tested by frontend */
+ assert( tag != LBER_ERROR );
+ assert( size >= 0 );
+
+ /* cookie decoding/checks deferred to backend... */
+ if ( cookie.bv_len ) {
+ PagedResultsCookie reqcookie;
+ if( cookie.bv_len != sizeof( reqcookie ) ) {
+ /* bad cookie */
+ rs->sr_text = "paged results cookie is invalid";
+ rc = LDAP_PROTOCOL_ERROR;
+ goto done;
+ }
+
+ AC_MEMCPY( &reqcookie, cookie.bv_val, sizeof( reqcookie ));
+
+ if ( reqcookie > ps->ps_cookie ) {
+ /* bad cookie */
+ rs->sr_text = "paged results cookie is invalid";
+ rc = LDAP_PROTOCOL_ERROR;
+ goto done;
+
+ } else if ( reqcookie < ps->ps_cookie ) {
+ rs->sr_text = "paged results cookie is invalid or old";
+ rc = LDAP_UNWILLING_TO_PERFORM;
+ goto done;
+ }
+
+ } else {
+ /* Initial request. Initialize state. */
+#if 0
+ if ( op->o_conn->c_pagedresults_state.ps_cookie != 0 ) {
+ /* There's another pagedResults control on the
+ * same connection; reject new pagedResults controls
+ * (allowed by RFC2696) */
+ rs->sr_text = "paged results cookie unavailable; try later";
+ rc = LDAP_UNWILLING_TO_PERFORM;
+ goto done;
+ }
+#endif
+ ps->ps_cookie = 0;
+ ps->ps_count = 0;
+ }
+
+done:;
+ (void)ber_free( ber, 1 );
+
+ return rc;
+}
+
+/* This function is copied nearly verbatim from back-bdb/search.c */
+static void
+send_paged_response(
+ Operation *op,
+ SlapReply *rs,
+ unsigned long *lastid )
+{
+ LDAPControl ctrl, *ctrls[2];
+ BerElementBuffer berbuf;
+ BerElement *ber = (BerElement *)&berbuf;
+ PagedResultsCookie respcookie;
+ struct berval cookie;
+
+ Debug(LDAP_DEBUG_ARGS,
+ "send_paged_response: lastid=0x%08lx nentries=%d\n",
+ lastid ? *lastid : 0, rs->sr_nentries, NULL );
+
+ BER_BVZERO( &ctrl.ldctl_value );
+ ctrls[0] = &ctrl;
+ ctrls[1] = NULL;
+
+ ber_init2( ber, NULL, LBER_USE_DER );
+
+ if ( lastid ) {
+ respcookie = ( PagedResultsCookie )(*lastid);
+ cookie.bv_len = sizeof( respcookie );
+ cookie.bv_val = (char *)&respcookie;
+
+ } else {
+ respcookie = ( PagedResultsCookie )0;
+ BER_BVSTR( &cookie, "" );
+ }
+
+ op->o_conn->c_pagedresults_state.ps_cookie = respcookie;
+ op->o_conn->c_pagedresults_state.ps_count =
+ ((PagedResultsState *)op->o_pagedresults_state)->ps_count +
+ rs->sr_nentries;
+
+ /* return size of 0 -- no estimate */
+ ber_printf( ber, "{iO}", 0, &cookie );
+
+ if ( ber_flatten2( ber, &ctrls[0]->ldctl_value, 0 ) == -1 ) {
+ goto done;
+ }
+
+ ctrls[0]->ldctl_oid = LDAP_CONTROL_PAGEDRESULTS;
+ ctrls[0]->ldctl_iscritical = 0;
+
+ rs->sr_ctrls = ctrls;
+ rs->sr_err = LDAP_SUCCESS;
+ send_ldap_result( op, rs );
+ rs->sr_ctrls = NULL;
+
+done:
+ (void) ber_free_buf( ber );
+}
#define MAX_ATTR_LEN 16384
-typedef struct backsql_db_conn {
- unsigned long ldap_cid;
- SQLHDBC dbh;
-} backsql_db_conn;
-
void
backsql_PrintErrors( SQLHENV henv, SQLHDBC hdbc, SQLHSTMT sth, int rc )
{
backsql_BindRowAsStrings_x( SQLHSTMT sth, BACKSQL_ROW_NTS *row, void *ctx )
{
RETCODE rc;
- SQLCHAR colname[ 64 ];
- SQLSMALLINT name_len, col_type, col_scale, col_null;
- UDWORD col_prec;
- int i;
if ( row == NULL ) {
return SQL_ERROR;
backsql_PrintErrors( SQL_NULL_HENV, SQL_NULL_HDBC, sth, rc );
} else {
+ SQLCHAR colname[ 64 ];
+ SQLSMALLINT name_len, col_type, col_scale, col_null;
+ UDWORD col_prec;
+ int i;
+
#ifdef BACKSQL_TRACE
Debug( LDAP_DEBUG_TRACE, "backsql_BindRowAsStrings: "
"ncols=%d\n", (int)row->ncols, 0, 0 );
row->col_names = (BerVarray)ber_memcalloc_x( row->ncols + 1,
sizeof( struct berval ), ctx );
- if ( !row->col_names ) goto nomem3;
- row->cols = (char **)ber_memcalloc_x( row->ncols + 1,
- sizeof( char * ), ctx );
- if ( !row->cols ) goto nomem2;
+ if ( row->col_names == NULL ) {
+ goto nomem;
+ }
+
row->col_prec = (UDWORD *)ber_memcalloc_x( row->ncols,
sizeof( UDWORD ), ctx );
- if ( !row->col_prec ) goto nomem1;
+ if ( row->col_prec == NULL ) {
+ goto nomem;
+ }
+
+ row->col_type = (SQLSMALLINT *)ber_memcalloc_x( row->ncols,
+ sizeof( SQLSMALLINT ), ctx );
+ if ( row->col_type == NULL ) {
+ goto nomem;
+ }
+
+ row->cols = (char **)ber_memcalloc_x( row->ncols + 1,
+ sizeof( char * ), ctx );
+ if ( row->cols == NULL ) {
+ goto nomem;
+ }
+
row->value_len = (SQLINTEGER *)ber_memcalloc_x( row->ncols,
sizeof( SQLINTEGER ), ctx );
- if ( !row->value_len ) {
+ if ( row->value_len == NULL ) {
+ goto nomem;
+ }
+
+ if ( 0 ) {
+nomem:
+ ber_memfree_x( row->col_names, ctx );
+ row->col_names = NULL;
ber_memfree_x( row->col_prec, ctx );
row->col_prec = NULL;
-nomem1: ber_memfree_x( row->cols, ctx );
+ ber_memfree_x( row->col_type, ctx );
+ row->col_type = NULL;
+ ber_memfree_x( row->cols, ctx );
row->cols = NULL;
-nomem2: ber_memfree_x( row->col_names, ctx );
- row->col_names = NULL;
-nomem3: Debug( LDAP_DEBUG_ANY, "backsql_BindRowAsStrings: "
+ ber_memfree_x( row->value_len, ctx );
+ row->value_len = NULL;
+
+ Debug( LDAP_DEBUG_ANY, "backsql_BindRowAsStrings: "
"out of memory\n", 0, 0, 0 );
+
return LDAP_NO_MEMORY;
}
- for ( i = 1; i <= row->ncols; i++ ) {
- rc = SQLDescribeCol( sth, (SQLSMALLINT)i, &colname[ 0 ],
+
+ for ( i = 0; i < row->ncols; i++ ) {
+ SQLSMALLINT TargetType;
+
+ rc = SQLDescribeCol( sth, (SQLSMALLINT)(i + 1), &colname[ 0 ],
(SQLUINTEGER)( sizeof( colname ) - 1 ),
&name_len, &col_type,
&col_prec, &col_scale, &col_null );
/* FIXME: test rc? */
ber_str2bv_x( (char *)colname, 0, 1,
- &row->col_names[ i - 1 ], ctx );
+ &row->col_names[ i ], ctx );
#ifdef BACKSQL_TRACE
Debug( LDAP_DEBUG_TRACE, "backsql_BindRowAsStrings: "
"col_name=%s, col_prec[%d]=%d\n",
- colname, (int)i, (int)col_prec );
+ colname, (int)(i + 1), (int)col_prec );
#endif /* BACKSQL_TRACE */
if ( col_type != SQL_CHAR && col_type != SQL_VARCHAR )
{
col_prec = MAX_ATTR_LEN;
}
- row->cols[ i - 1 ] = (char *)ber_memcalloc_x( col_prec + 1,
+ row->cols[ i ] = (char *)ber_memcalloc_x( col_prec + 1,
sizeof( char ), ctx );
- row->col_prec[ i - 1 ] = col_prec;
- rc = SQLBindCol( sth, (SQLUSMALLINT)i,
- SQL_C_CHAR,
- (SQLPOINTER)row->cols[ i - 1 ],
- col_prec + 1,
- &row->value_len[ i - 1 ] );
+ row->col_prec[ i ] = col_prec;
+ row->col_type[ i ] = col_type;
+
+ /*
+ * ITS#3386, ITS#3113 - 20070308
+ * Note: there are many differences between various DPMS and ODBC
+ * Systems; some support SQL_C_BLOB, SQL_C_BLOB_LOCATOR. YMMV:
+ * This has only been tested on Linux/MySQL/UnixODBC
+ * For BINARY-type Fields (BLOB, etc), read the data as BINARY
+ */
+ if ( BACKSQL_IS_BINARY( col_type ) ) {
+#ifdef BACKSQL_TRACE
+ Debug( LDAP_DEBUG_TRACE, "backsql_BindRowAsStrings: "
+ "col_name=%s, col_type[%d]=%d: reading binary data\n",
+ colname, (int)(i + 1), (int)col_type);
+#endif /* BACKSQL_TRACE */
+ TargetType = SQL_C_BINARY;
+
+ } else {
+ /* Otherwise read it as Character data */
+#ifdef BACKSQL_TRACE
+ Debug( LDAP_DEBUG_TRACE, "backsql_BindRowAsStrings: "
+ "col_name=%s, col_type[%d]=%d: reading character data\n",
+ colname, (int)(i + 1), (int)col_type);
+#endif /* BACKSQL_TRACE */
+ TargetType = SQL_C_CHAR;
+ }
+
+ rc = SQLBindCol( sth, (SQLUSMALLINT)(i + 1),
+ TargetType,
+ (SQLPOINTER)row->cols[ i ],
+ col_prec + 1,
+ &row->value_len[ i ] );
+
/* FIXME: test rc? */
}
- BER_BVZERO( &row->col_names[ i - 1 ] );
- row->cols[ i - 1 ] = NULL;
+ BER_BVZERO( &row->col_names[ i ] );
+ row->cols[ i ] = NULL;
}
#ifdef BACKSQL_TRACE
}
ber_bvarray_free_x( row->col_names, ctx );
- ber_memvfree_x( (void **)row->cols, ctx );
ber_memfree_x( row->col_prec, ctx );
+ ber_memfree_x( row->col_type, ctx );
+ ber_memvfree_x( (void **)row->cols, ctx );
ber_memfree_x( row->value_len, ctx );
return SQL_SUCCESS;
return backsql_FreeRow_x( row, NULL );
}
-static int
-backsql_cmp_connid( const void *v_c1, const void *v_c2 )
-{
- const backsql_db_conn *c1 = v_c1, *c2 = v_c2;
- if ( c1->ldap_cid > c2->ldap_cid ) {
- return 1;
- }
-
- if ( c1->ldap_cid < c2->ldap_cid ) {
- return -1;
- }
-
- return 0;
-}
-
static void
-backsql_close_db_conn( void *v_conn )
+backsql_close_db_handle( SQLHDBC dbh )
{
- backsql_db_conn *conn = (backsql_db_conn *)v_conn;
- unsigned long cid = conn->ldap_cid;
+ if ( dbh == SQL_NULL_HDBC ) {
+ return;
+ }
- Debug( LDAP_DEBUG_TRACE, "==>backsql_close_db_conn(%lu)\n",
- cid, 0, 0 );
+ Debug( LDAP_DEBUG_TRACE, "==>backsql_close_db_handle(%p)\n",
+ (void *)dbh, 0, 0 );
/*
* Default transact is SQL_ROLLBACK; commit is required only
*/
/* TimesTen */
- SQLTransact( SQL_NULL_HENV, conn->dbh, SQL_ROLLBACK );
- SQLDisconnect( conn->dbh );
- SQLFreeConnect( conn->dbh );
- ch_free( conn );
+ SQLTransact( SQL_NULL_HENV, dbh, SQL_ROLLBACK );
+ SQLDisconnect( dbh );
+ SQLFreeConnect( dbh );
- Debug( LDAP_DEBUG_TRACE, "<==backsql_close_db_conn(%lu)\n",
- cid, 0, 0 );
+ Debug( LDAP_DEBUG_TRACE, "<==backsql_close_db_handle(%p)\n",
+ (void *)dbh, 0, 0 );
}
int
backsql_conn_destroy(
backsql_info *bi )
{
- avl_free( bi->sql_db_conns, backsql_close_db_conn );
-
return 0;
}
}
static int
-backsql_open_db_conn( backsql_info *bi, unsigned long ldap_cid, backsql_db_conn **pdbc )
+backsql_open_db_handle(
+ backsql_info *bi,
+ SQLHDBC *dbhp )
{
/* TimesTen */
char DBMSName[ 32 ];
- backsql_db_conn *dbc;
int rc;
- assert( pdbc != NULL );
- *pdbc = NULL;
+ assert( dbhp != NULL );
+ *dbhp = SQL_NULL_HDBC;
- Debug( LDAP_DEBUG_TRACE, "==>backsql_open_db_conn(%lu)\n",
- ldap_cid, 0, 0 );
+ Debug( LDAP_DEBUG_TRACE, "==>backsql_open_db_handle()\n",
+ 0, 0, 0 );
- dbc = (backsql_db_conn *)ch_calloc( 1, sizeof( backsql_db_conn ) );
- dbc->ldap_cid = ldap_cid;
- rc = SQLAllocConnect( bi->sql_db_env, &dbc->dbh );
+ rc = SQLAllocConnect( bi->sql_db_env, dbhp );
if ( !BACKSQL_SUCCESS( rc ) ) {
- Debug( LDAP_DEBUG_TRACE, "backsql_open_db_conn(%lu): "
- "SQLAllocConnect() failed:\n", ldap_cid, 0, 0 );
+ Debug( LDAP_DEBUG_TRACE, "backsql_open_db_handle(): "
+ "SQLAllocConnect() failed:\n",
+ 0, 0, 0 );
backsql_PrintErrors( bi->sql_db_env, SQL_NULL_HDBC,
- SQL_NULL_HENV, rc );
+ SQL_NULL_HENV, rc );
return LDAP_UNAVAILABLE;
}
- rc = SQLConnect( dbc->dbh,
- (SQLCHAR*)bi->sql_dbname, SQL_NTS,
- (SQLCHAR*)bi->sql_dbuser, SQL_NTS,
- (SQLCHAR*)bi->sql_dbpasswd, SQL_NTS );
+ rc = SQLConnect( *dbhp,
+ (SQLCHAR*)bi->sql_dbname, SQL_NTS,
+ (SQLCHAR*)bi->sql_dbuser, SQL_NTS,
+ (SQLCHAR*)bi->sql_dbpasswd, SQL_NTS );
if ( rc != SQL_SUCCESS ) {
- Debug( LDAP_DEBUG_TRACE, "backsql_open_db_conn(%lu): "
+ Debug( LDAP_DEBUG_TRACE, "backsql_open_db_handle(): "
"SQLConnect() to database \"%s\" %s.\n",
- ldap_cid, bi->sql_dbname,
+ bi->sql_dbname,
rc == SQL_SUCCESS_WITH_INFO ?
- "succeeded with info" : "failed" );
- backsql_PrintErrors( bi->sql_db_env, dbc->dbh, SQL_NULL_HENV, rc );
+ "succeeded with info" : "failed",
+ 0 );
+ backsql_PrintErrors( bi->sql_db_env, *dbhp, SQL_NULL_HENV, rc );
if ( rc != SQL_SUCCESS_WITH_INFO ) {
+ SQLFreeConnect( *dbhp );
return LDAP_UNAVAILABLE;
}
}
* TimesTen : Turn off autocommit. We must explicitly
* commit any transactions.
*/
- SQLSetConnectOption( dbc->dbh, SQL_AUTOCOMMIT, SQL_AUTOCOMMIT_OFF );
+ SQLSetConnectOption( *dbhp, SQL_AUTOCOMMIT, SQL_AUTOCOMMIT_OFF );
/*
* See if this connection is to TimesTen. If it is,
/* Assume until proven otherwise */
bi->sql_flags &= ~BSQLF_USE_REVERSE_DN;
DBMSName[ 0 ] = '\0';
- rc = SQLGetInfo( dbc->dbh, SQL_DBMS_NAME, (PTR)&DBMSName,
+ rc = SQLGetInfo( *dbhp, SQL_DBMS_NAME, (PTR)&DBMSName,
sizeof( DBMSName ), NULL );
if ( rc == SQL_SUCCESS ) {
if ( strcmp( DBMSName, "TimesTen" ) == 0 ||
- strcmp( DBMSName, "Front-Tier" ) == 0 ) {
- Debug( LDAP_DEBUG_TRACE, "backsql_open_db_conn(%lu): "
- "TimesTen database!\n", ldap_cid, 0, 0 );
+ strcmp( DBMSName, "Front-Tier" ) == 0 )
+ {
+ Debug( LDAP_DEBUG_TRACE, "backsql_open_db_handle(): "
+ "TimesTen database!\n",
+ 0, 0, 0 );
bi->sql_flags |= BSQLF_USE_REVERSE_DN;
}
+
} else {
- Debug( LDAP_DEBUG_TRACE, "backsql_open_db_conn(%lu): "
- "SQLGetInfo() failed.\n", ldap_cid, 0, 0 );
- backsql_PrintErrors( bi->sql_db_env, dbc->dbh, SQL_NULL_HENV, rc );
- return rc;
+ Debug( LDAP_DEBUG_TRACE, "backsql_open_db_handle(): "
+ "SQLGetInfo() failed.\n",
+ 0, 0, 0 );
+ backsql_PrintErrors( bi->sql_db_env, *dbhp, SQL_NULL_HENV, rc );
+ SQLDisconnect( *dbhp );
+ SQLFreeConnect( *dbhp );
+ return LDAP_UNAVAILABLE;
}
/* end TimesTen */
- Debug( LDAP_DEBUG_TRACE, "backsql_open_db_conn(%lu): "
- "connected, adding to tree.\n", ldap_cid, 0, 0 );
- ldap_pvt_thread_mutex_lock( &bi->sql_dbconn_mutex );
- if ( avl_insert( &bi->sql_db_conns, dbc, backsql_cmp_connid, avl_dup_error ) ) {
- Debug( LDAP_DEBUG_TRACE, "backsql_open_db_conn(%lu): "
- "duplicate connection ID.\n", ldap_cid, 0, 0 );
- return LDAP_OTHER;
- }
- ldap_pvt_thread_mutex_unlock( &bi->sql_dbconn_mutex );
- Debug( LDAP_DEBUG_TRACE, "<==backsql_open_db_conn(%lu)\n", ldap_cid, 0, 0 );
-
- *pdbc = dbc;
+ Debug( LDAP_DEBUG_TRACE, "<==backsql_open_db_handle()\n",
+ 0, 0, 0 );
return LDAP_SUCCESS;
}
int
-backsql_free_db_conn( Operation *op )
+backsql_free_db_conn( Operation *op, SQLHDBC dbh )
{
- backsql_info *bi = (backsql_info *)op->o_bd->be_private;
- backsql_db_conn tmp = { 0 },
- *conn;
-
Debug( LDAP_DEBUG_TRACE, "==>backsql_free_db_conn()\n", 0, 0, 0 );
- tmp.ldap_cid = op->o_connid;
- ldap_pvt_thread_mutex_lock( &bi->sql_dbconn_mutex );
- conn = avl_delete( &bi->sql_db_conns, &tmp, backsql_cmp_connid );
- ldap_pvt_thread_mutex_unlock( &bi->sql_dbconn_mutex );
- /*
- * we have one thread per connection, as I understand -- so we can
- * get this out of critical section
- */
- if ( conn != NULL ) {
- Debug( LDAP_DEBUG_TRACE, "backsql_free_db_conn(): "
- "closing db connection %lu (%p)\n",
- op->o_connid, (void *)conn, 0 );
- backsql_close_db_conn( (void *)conn );
- }
+ (void)backsql_close_db_handle( dbh );
Debug( LDAP_DEBUG_TRACE, "<==backsql_free_db_conn()\n", 0, 0, 0 );
- return conn ? SQL_SUCCESS : SQL_ERROR;
+ return LDAP_SUCCESS;
+}
+
+static void *backsql_db_conn_dummy;
+
+static void
+backsql_db_conn_keyfree(
+ void *key,
+ void *data )
+{
+ backsql_close_db_handle( (SQLHDBC)data );
}
int
-backsql_get_db_conn( Operation *op, SQLHDBC *dbh )
+backsql_get_db_conn( Operation *op, SQLHDBC *dbhp )
{
- backsql_info *bi = (backsql_info *)op->o_bd->be_private;
- backsql_db_conn *dbc,
- tmp = { 0 };
- int rc = LDAP_SUCCESS;
+ backsql_info *bi = (backsql_info *)op->o_bd->be_private;
+ int rc = LDAP_SUCCESS;
+ SQLHDBC dbh = SQL_NULL_HDBC;
Debug( LDAP_DEBUG_TRACE, "==>backsql_get_db_conn()\n", 0, 0, 0 );
- assert( dbh != NULL );
- *dbh = SQL_NULL_HDBC;
+ assert( dbhp != NULL );
+ *dbhp = SQL_NULL_HDBC;
- tmp.ldap_cid = op->o_connid;
+ if ( op->o_threadctx ) {
+ void *data = NULL;
- /*
- * we have one thread per connection, as I understand --
- * so we do not need locking here
- */
- dbc = avl_find( bi->sql_db_conns, &tmp, backsql_cmp_connid );
- if ( !dbc ) {
- rc = backsql_open_db_conn( bi, op->o_connid, &dbc );
- if ( rc != LDAP_SUCCESS) {
- Debug( LDAP_DEBUG_TRACE, "backsql_get_db_conn(): "
- "could not get connection handle "
- "-- returning NULL\n", 0, 0, 0 );
- return rc;
- }
+ ldap_pvt_thread_pool_getkey( op->o_threadctx,
+ &backsql_db_conn_dummy, &data, NULL );
+ dbh = (SQLHDBC)data;
+
+ } else {
+ dbh = bi->sql_dbh;
}
- ldap_pvt_thread_mutex_lock( &bi->sql_schema_mutex );
- if ( !BACKSQL_SCHEMA_LOADED( bi ) ) {
- Debug( LDAP_DEBUG_TRACE, "backsql_get_db_conn(): "
- "first call -- reading schema map\n", 0, 0, 0 );
- rc = backsql_load_schema_map( bi, dbc->dbh );
+ if ( dbh == SQL_NULL_HDBC ) {
+ rc = backsql_open_db_handle( bi, &dbh );
if ( rc != LDAP_SUCCESS ) {
- ldap_pvt_thread_mutex_unlock( &bi->sql_schema_mutex );
- backsql_free_db_conn( op );
return rc;
}
+
+ if ( op->o_threadctx ) {
+ void *data = NULL;
+
+ data = (void *)dbh;
+ ldap_pvt_thread_pool_setkey( op->o_threadctx,
+ &backsql_db_conn_dummy, data,
+ backsql_db_conn_keyfree );
+
+ } else {
+ bi->sql_dbh = dbh;
+ }
}
- ldap_pvt_thread_mutex_unlock( &bi->sql_schema_mutex );
- *dbh = dbc->dbh;
+ *dbhp = dbh;
Debug( LDAP_DEBUG_TRACE, "<==backsql_get_db_conn()\n", 0, 0, 0 );
#include <sys/stat.h>
#include "slap.h"
+#include "config.h"
#include "lutil.h"
#include "lber_pvt.h"
}
/* startup a specific backend database */
-int backend_startup_one(Backend *be)
+int backend_startup_one(Backend *be, ConfigReply *cr)
{
int rc = 0;
/* set database controls */
(void)backend_set_controls( be );
+#if 0
+ if ( !BER_BVISEMPTY( &be->be_rootndn )
+ && select_backend( &be->be_rootndn, 0 ) == be
+ && BER_BVISNULL( &be->be_rootpw ) )
+ {
+ /* warning: if rootdn entry is created,
+ * it can take rootdn privileges;
+ * set empty rootpw to prevent */
+ }
+#endif
+
if ( be->bd_info->bi_db_open ) {
- rc = be->bd_info->bi_db_open( be );
+ rc = be->bd_info->bi_db_open( be, cr );
if ( rc == 0 ) {
(void)backend_set_controls( be );
int i;
int rc = 0;
BackendInfo *bi;
+ ConfigReply cr={0, ""};
if( ! ( nBackendDB > 0 ) ) {
/* no databases */
/* append global access controls */
acl_append( &be->be_acl, frontendDB->be_acl, -1 );
- return backend_startup_one( be );
+ return backend_startup_one( be, &cr );
}
/* open frontend, if required */
if ( frontendDB->bd_info->bi_db_open ) {
- rc = frontendDB->bd_info->bi_db_open( frontendDB );
+ rc = frontendDB->bd_info->bi_db_open( frontendDB, NULL );
if ( rc != 0 ) {
Debug( LDAP_DEBUG_ANY,
"backend_startup: bi_db_open(frontend) failed! (%d)\n",
/* append global access controls */
acl_append( &be->be_acl, frontendDB->be_acl, -1 );
- rc = backend_startup_one( be );
+ rc = backend_startup_one( be, &cr );
if ( rc ) return rc;
}
}
if ( be->bd_info->bi_db_close ) {
- be->bd_info->bi_db_close( be );
+ be->bd_info->bi_db_close( be, NULL );
}
if( be->bd_info->bi_close ) {
/* close each backend database */
LDAP_STAILQ_FOREACH( be, &backendDB, be_next ) {
if ( be->bd_info->bi_db_close ) {
- be->bd_info->bi_db_close( be );
+ be->bd_info->bi_db_close( be, NULL );
}
if(rc != 0) {
/* close frontend, if required */
if ( frontendDB->bd_info->bi_db_close ) {
- rc = frontendDB->bd_info->bi_db_close ( frontendDB );
+ rc = frontendDB->bd_info->bi_db_close ( frontendDB, NULL );
if ( rc != 0 ) {
Debug( LDAP_DEBUG_ANY,
"backend_startup: bi_db_close(frontend) failed! (%d)\n",
}
if ( bd->bd_info->bi_db_destroy ) {
- bd->bd_info->bi_db_destroy( bd );
+ bd->bd_info->bi_db_destroy( bd, NULL );
}
}
void backend_destroy_one( BackendDB *bd, int dynamic )
{
if ( dynamic ) {
- LDAP_STAILQ_REMOVE(&backendDB, bd, slap_backend_db, be_next );
+ LDAP_STAILQ_REMOVE(&backendDB, bd, BackendDB, be_next );
}
if ( bd->be_syncinfo ) {
}
acl_destroy( bd->be_acl, frontendDB->be_acl );
limits_destroy( bd->be_limits );
- if ( bd->be_replogfile ) {
- ch_free( bd->be_replogfile );
- }
- if ( bd->be_replica_argsfile ) {
- ch_free( bd->be_replica_argsfile );
- }
- if ( bd->be_replica_pidfile ) {
- ch_free( bd->be_replica_pidfile );
- }
- destroy_replica_info( bd );
if ( !BER_BVISNULL( &bd->be_update_ndn ) ) {
ch_free( bd->be_update_ndn.bv_val );
}
bd = frontendDB;
if ( bd ) {
if ( bd->bd_info->bi_db_destroy ) {
- bd->bd_info->bi_db_destroy( bd );
+ bd->bd_info->bi_db_destroy( bd, NULL );
}
ber_bvarray_free( bd->be_suffix );
ber_bvarray_free( bd->be_nsuffix );
free( bd->be_rootpw.bv_val );
}
acl_destroy( bd->be_acl, frontendDB->be_acl );
-
- if ( bd->be_replogfile != NULL ) {
- free( bd->be_replogfile );
- }
- if ( bd->be_replica_argsfile ) {
- ch_free( bd->be_replica_argsfile );
- }
- if ( bd->be_replica_pidfile ) {
- ch_free( bd->be_replica_pidfile );
- }
- assert( bd->be_replica == NULL );
}
return 0;
int idx
)
{
- LDAP_STAILQ_REMOVE(&backendDB, be, slap_backend_db, be_next);
+ LDAP_STAILQ_REMOVE(&backendDB, be, BackendDB, be_next);
backend_db_insert(be, idx);
}
backend_db_init(
const char *type,
BackendDB *b0,
- int idx )
+ int idx,
+ ConfigReply *cr)
{
BackendInfo *bi = backend_info(type);
BackendDB *be = b0;
be->be_max_deref_depth = SLAPD_DEFAULT_MAXDEREFDEPTH;
if ( bi->bi_db_init ) {
- rc = bi->bi_db_init( be );
+ rc = bi->bi_db_init( be, cr );
}
if ( rc != 0 ) {
fprintf( stderr, "database init failed (%s)\n", type );
/* If we created and linked this be, remove it and free it */
if ( !b0 ) {
- LDAP_STAILQ_REMOVE(&backendDB, be, slap_backend_db, be_next);
+ LDAP_STAILQ_REMOVE(&backendDB, be, BackendDB, be_next);
ch_free( be );
be = NULL;
nbackends--;
LDAP_STAILQ_FOREACH( be, &backendDB, be_next ) {
if ( be->bd_info->bi_db_close ) {
- be->bd_info->bi_db_close( be );
+ be->bd_info->bi_db_close( be, NULL );
}
}
if ( frontendDB->bd_info->bi_db_close ) {
- frontendDB->bd_info->bi_db_close( frontendDB );
+ frontendDB->bd_info->bi_db_close( frontendDB, NULL );
}
}
Backend *
select_backend(
struct berval * dn,
- int manageDSAit,
int noSubs )
{
int j;
ber_len_t len, dnlen = dn->bv_len;
- Backend *be, *b2 = NULL;
+ Backend *be;
LDAP_STAILQ_FOREACH( be, &backendDB, be_next ) {
if ( be->be_nsuffix == NULL || SLAP_DBHIDDEN( be )) {
if ( strcmp( be->be_nsuffix[j].bv_val,
&dn->bv_val[dnlen-len] ) == 0 )
{
- if( b2 == NULL ) {
- b2 = be;
-
- if( manageDSAit && len == dnlen &&
- !SLAP_GLUE_SUBORDINATE( be ) ) {
- continue;
- }
- } else {
- /* If any parts of the tree are glued, use the first
- * match regardless of manageDSAit. Otherwise use the
- * last match.
- */
- if( !( SLAP_DBFLAGS( be ) & ( SLAP_DBFLAG_GLUE_INSTANCE |
- SLAP_DBFLAG_GLUE_SUBORDINATE )))
- b2 = be;
- }
- return b2;
+ return be;
}
}
}
- return b2;
+ return be;
}
int
return 0;
}
+int
+be_issubordinate(
+ Backend *be,
+ struct berval *bvsubordinate )
+{
+ int i;
+
+ if ( be->be_nsuffix == NULL ) {
+ return 0;
+ }
+
+ for ( i = 0; !BER_BVISNULL( &be->be_nsuffix[i] ); i++ ) {
+ if ( dnIsSuffix( bvsubordinate, &be->be_nsuffix[i] ) ) {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
int
be_isroot_dn( Backend *be, struct berval *ndn )
{
int
be_isroot_pw( Operation *op )
{
- int result;
+ return be_rootdn_bind( op, NULL ) == LDAP_SUCCESS;
+}
- if ( ! be_isroot_dn( op->o_bd, &op->o_req_ndn ) ) {
- return 0;
+/*
+ * checks if binding as rootdn
+ *
+ * return value:
+ * SLAP_CB_CONTINUE if not the rootdn
+ * LDAP_SUCCESS if rootdn & rootpw
+ * LDAP_INVALID_CREDENTIALS if rootdn & !rootpw
+ *
+ * if rs != NULL
+ * if LDAP_SUCCESS, op->orb_edn is set
+ * if LDAP_INVALID_CREDENTIALS, response is sent to client
+ */
+int
+be_rootdn_bind( Operation *op, SlapReply *rs )
+{
+ int rc;
+
+ assert( op->o_tag == LDAP_REQ_BIND );
+ assert( op->orb_method == LDAP_AUTH_SIMPLE );
+
+ if ( !be_isroot_dn( op->o_bd, &op->o_req_ndn ) ) {
+ return SLAP_CB_CONTINUE;
+ }
+
+ if ( BER_BVISNULL( &op->o_bd->be_rootpw ) ) {
+ /* give the database a chance */
+ return SLAP_CB_CONTINUE;
}
if ( BER_BVISEMPTY( &op->o_bd->be_rootpw ) ) {
- return 0;
+ /* rootdn bind explicitly disallowed */
+ rc = LDAP_INVALID_CREDENTIALS;
+ if ( rs ) {
+ goto send_result;
+ }
+
+ return rc;
}
#ifdef SLAPD_SPASSWD
op->o_conn->c_sasl_authctx, NULL );
#endif
- result = lutil_passwd( &op->o_bd->be_rootpw, &op->orb_cred, NULL, NULL );
+ rc = lutil_passwd( &op->o_bd->be_rootpw, &op->orb_cred, NULL, NULL );
#ifdef SLAPD_SPASSWD
ldap_pvt_thread_pool_setkey( op->o_threadctx, slap_sasl_bind, NULL, NULL );
#endif
- return result == 0;
+ rc = ( rc == 0 ? LDAP_SUCCESS : LDAP_INVALID_CREDENTIALS );
+ if ( rs ) {
+send_result:;
+ rs->sr_err = rc;
+
+ Debug( LDAP_DEBUG_TRACE, "%s: rootdn=\"%s\" bind%s\n",
+ op->o_log_prefix, op->o_bd->be_rootdn.bv_val,
+ rc == LDAP_SUCCESS ? " succeeded" : " failed" );
+
+ if ( rc == LDAP_SUCCESS ) {
+ /* Set to the pretty rootdn */
+ ber_dupbv( &op->orb_edn, &op->o_bd->be_rootdn );
+
+ } else {
+ send_ldap_result( op, rs );
+ }
+ }
+
+ return rc;
}
int
GroupAssertion *g;
Backend *be = op->o_bd;
- op->o_bd = select_backend( gr_ndn, 0, 0 );
+ op->o_bd = select_backend( gr_ndn, 0 );
for ( g = op->o_groups; g; g = g->ga_next ) {
if ( g->ga_be != op->o_bd || g->ga_oc != group_oc ||
if ( target && dn_match( &target->e_nname, gr_ndn ) ) {
e = target;
rc = 0;
+
} else {
op->o_private = NULL;
rc = be_entry_get_rw( op, gr_ndn, group_oc, group_at, 0, &e );
e_priv = op->o_private;
op->o_private = o_priv;
}
+
if ( e ) {
a = attr_find( e->e_attrs, group_at );
if ( a ) {
- /* If the attribute is a subtype of labeledURI, treat this as
- * a dynamic group ala groupOfURLs
+ /* If the attribute is a subtype of labeledURI,
+ * treat this as a dynamic group ala groupOfURLs
*/
- if (is_at_subtype( group_at->ad_type,
+ if ( is_at_subtype( group_at->ad_type,
slap_schema.si_ad_labeledURI->ad_type ) )
{
int i;
LDAPURLDesc *ludp;
struct berval bv, nbase;
Filter *filter;
- Entry *user;
+ Entry *user = NULL;
void *user_priv = NULL;
Backend *b2 = op->o_bd;
if ( target && dn_match( &target->e_nname, op_ndn ) ) {
user = target;
- } else {
- op->o_bd = select_backend( op_ndn, 0, 0 );
- op->o_private = NULL;
- rc = be_entry_get_rw(op, op_ndn, NULL, NULL, 0, &user );
- user_priv = op->o_private;
- op->o_private = o_priv;
}
- if ( rc == 0 ) {
- rc = LDAP_COMPARE_FALSE;
- for ( i = 0; !BER_BVISNULL( &a->a_vals[i] ); i++ ) {
- if ( ldap_url_parse( a->a_vals[i].bv_val, &ludp ) !=
- LDAP_URL_SUCCESS )
- {
- continue;
+ rc = LDAP_COMPARE_FALSE;
+ for ( i = 0; !BER_BVISNULL( &a->a_vals[i] ); i++ ) {
+ if ( ldap_url_parse( a->a_vals[i].bv_val, &ludp ) !=
+ LDAP_URL_SUCCESS )
+ {
+ continue;
+ }
+
+ BER_BVZERO( &nbase );
+
+ /* host, attrs and extensions parts must be empty */
+ if ( ( ludp->lud_host && *ludp->lud_host )
+ || ludp->lud_attrs
+ || ludp->lud_exts )
+ {
+ goto loopit;
+ }
+
+ ber_str2bv( ludp->lud_dn, 0, 0, &bv );
+ if ( dnNormalize( 0, NULL, NULL, &bv, &nbase,
+ op->o_tmpmemctx ) != LDAP_SUCCESS )
+ {
+ goto loopit;
+ }
+
+ switch ( ludp->lud_scope ) {
+ case LDAP_SCOPE_BASE:
+ if ( !dn_match( &nbase, op_ndn ) ) {
+ goto loopit;
}
- BER_BVZERO( &nbase );
- /* host part must be empty */
- /* attrs and extensions parts must be empty */
- if ( ( ludp->lud_host && *ludp->lud_host ) ||
- ludp->lud_attrs || ludp->lud_exts )
- {
+ break;
+ case LDAP_SCOPE_ONELEVEL:
+ dnParent( op_ndn, &bv );
+ if ( !dn_match( &nbase, &bv ) ) {
goto loopit;
}
- ber_str2bv( ludp->lud_dn, 0, 0, &bv );
- if ( dnNormalize( 0, NULL, NULL, &bv, &nbase,
- op->o_tmpmemctx ) != LDAP_SUCCESS )
+ break;
+ case LDAP_SCOPE_SUBTREE:
+ if ( !dnIsSuffix( op_ndn, &nbase ) ) {
+ goto loopit;
+ }
+ break;
+ case LDAP_SCOPE_SUBORDINATE:
+ if ( dn_match( &nbase, op_ndn ) ||
+ !dnIsSuffix( op_ndn, &nbase ) )
{
goto loopit;
}
- switch ( ludp->lud_scope ) {
- case LDAP_SCOPE_BASE:
- if ( !dn_match( &nbase, op_ndn ) ) {
- goto loopit;
- }
- break;
- case LDAP_SCOPE_ONELEVEL:
- dnParent( op_ndn, &bv );
- if ( !dn_match( &nbase, &bv ) ) {
- goto loopit;
- }
- break;
- case LDAP_SCOPE_SUBTREE:
- if ( !dnIsSuffix( op_ndn, &nbase ) ) {
- goto loopit;
- }
- break;
- case LDAP_SCOPE_SUBORDINATE:
- if ( dn_match( &nbase, op_ndn ) ||
- !dnIsSuffix( op_ndn, &nbase ) )
- {
+ }
+
+ /* NOTE: this could be NULL
+ * if no filter is provided,
+ * or if filter parsing fails.
+ * In the latter case,
+ * we should give up. */
+ if ( ludp->lud_filter != NULL && ludp->lud_filter != '\0') {
+ filter = str2filter_x( op, ludp->lud_filter );
+ if ( filter == NULL ) {
+ /* give up... */
+ rc = LDAP_OTHER;
+ goto loopit;
+ }
+
+ /* only get user if required
+ * and not available yet */
+ if ( user == NULL ) {
+ int rc2;
+
+ op->o_bd = select_backend( op_ndn, 0 );
+ op->o_private = NULL;
+ rc2 = be_entry_get_rw( op, op_ndn, NULL, NULL, 0, &user );
+ user_priv = op->o_private;
+ op->o_private = o_priv;
+ if ( rc2 != 0 ) {
+ /* give up... */
+ rc = LDAP_OTHER;
goto loopit;
}
}
- filter = str2filter_x( op, ludp->lud_filter );
- if ( filter ) {
- if ( test_filter( NULL, user, filter ) ==
- LDAP_COMPARE_TRUE )
- {
- rc = 0;
- }
- filter_free_x( op, filter );
+
+ if ( test_filter( NULL, user, filter ) ==
+ LDAP_COMPARE_TRUE )
+ {
+ rc = 0;
}
+ filter_free_x( op, filter );
+ }
loopit:
- ldap_free_urldesc( ludp );
- if ( !BER_BVISNULL( &nbase ) ) {
- op->o_tmpfree( nbase.bv_val, op->o_tmpmemctx );
- }
- if ( rc == 0 ) break;
+ ldap_free_urldesc( ludp );
+ if ( !BER_BVISNULL( &nbase ) ) {
+ op->o_tmpfree( nbase.bv_val, op->o_tmpmemctx );
}
- if ( user != target ) {
- op->o_private = user_priv;
- be_entry_release_r( op, user );
- op->o_private = o_priv;
+ if ( rc != LDAP_COMPARE_FALSE ) {
+ break;
}
}
+
+ if ( user != NULL && user != target ) {
+ op->o_private = user_priv;
+ be_entry_release_r( op, user );
+ op->o_private = o_priv;
+ }
op->o_bd = b2;
+
} else {
rc = value_find_ex( group_at,
- SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH |
- SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH,
- a->a_nvals, op_ndn, op->o_tmpmemctx );
- if ( rc == LDAP_NO_SUCH_ATTRIBUTE )
+ SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH |
+ SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH,
+ a->a_nvals, op_ndn, op->o_tmpmemctx );
+ if ( rc == LDAP_NO_SUCH_ATTRIBUTE ) {
rc = LDAP_COMPARE_FALSE;
+ }
}
+
} else {
rc = LDAP_NO_SUCH_ATTRIBUTE;
}
+
if ( e != target ) {
op->o_private = e_priv;
be_entry_release_r( op, e );
op->o_private = o_priv;
}
+
} else {
rc = LDAP_NO_SUCH_OBJECT;
}
g->ga_next = op->o_groups;
op->o_groups = g;
}
+
done:
op->o_bd = be;
return rc;
AccessControlState acl_state = ACL_STATE_INIT;
Backend *be = op->o_bd;
- op->o_bd = select_backend( edn, 0, 0 );
+ op->o_bd = select_backend( edn, 0 );
if ( target && dn_match( &target->e_nname, edn ) ) {
e = target;
assert( edn != NULL );
assert( access > ACL_NONE );
- op->o_bd = select_backend( edn, 0, 0 );
+ op->o_bd = select_backend( edn, 0 );
if ( target && dn_match( &target->e_nname, edn ) ) {
e = target;
BackendDB *be_orig = op->o_bd;
/* Let the overlays have a chance at this */
- op->o_bd = select_backend( &op->o_req_ndn, 0, 0 );
+ op->o_bd = select_backend( &op->o_req_ndn, 0 );
if ( op->o_bd != NULL && !be_match( op->o_bd, frontendDB ) &&
( SLAP_OPATTRS( rs->sr_attr_flags ) || rs->sr_attrs ) &&
op->o_bd->be_operational != NULL )
#define SLAPD_TOOLS
#include "slap.h"
+#include "config.h"
typedef struct gluenode {
BackendDB *gn_be;
gi->gi_n[i].gn_be->bd_info );
/* Let backend.c take care of the rest of startup */
if ( !rc )
- rc = backend_startup_one( gi->gi_n[i].gn_be );
+ rc = backend_startup_one( gi->gi_n[i].gn_be, NULL );
if ( rc ) break;
}
if ( !rc && !bsame && on->on_info->oi_orig->bi_open )
static int
glue_db_init(
- BackendDB *be
+ BackendDB *be,
+ ConfigReply *cr
)
{
slap_overinst *on = (slap_overinst *)be->bd_info;
/*FIXME : need to add support */
oi->oi_bi.bi_tool_dn2id_get = 0;
- oi->oi_bi.bi_tool_id2entry_get = 0;
oi->oi_bi.bi_tool_entry_modify = 0;
SLAP_DBFLAGS( be ) |= SLAP_DBFLAG_GLUE_INSTANCE;
static int
glue_db_destroy (
- BackendDB *be
+ BackendDB *be,
+ ConfigReply *cr
)
{
slap_overinst *on = (slap_overinst *)be->bd_info;
static int
glue_db_close(
- BackendDB *be
+ BackendDB *be,
+ ConfigReply *cr
)
{
slap_overinst *on = (slap_overinst *)be->bd_info;
func = &oi->oi_orig->bi_db_open;
if ( func[which] ) {
be->bd_info = oi->oi_orig;
- rc = func[which]( be );
+ rc = func[which]( be, NULL );
}
for (; on && rc == 0; on=on->on_next) {
be->bd_info = &on->on_bi;
func = &on->on_bi.bi_db_open;
if (func[which]) {
- rc = func[which]( be );
+ rc = func[which]( be, NULL );
}
}
be->bd_info = bi_orig;
ca.bi = &on->on_bi;
ct = config_find_keyword( on->on_bi.bi_cf_ocs->co_table, &ca );
if ( ct ) {
+ ca.table = on->on_bi.bi_cf_ocs->co_type;
rc = config_add_vals( ct, &ca );
if ( rc != SLAP_CONF_UNKNOWN )
break;
static int
over_db_open(
- BackendDB *be
+ BackendDB *be,
+ ConfigReply *cr
)
{
return over_db_func( be, db_open );
static int
over_db_close(
- BackendDB *be
+ BackendDB *be,
+ ConfigReply *cr
)
{
slap_overinfo *oi = be->bd_info->bi_private;
for (; on && rc == 0; on=on->on_next) {
be->bd_info = &on->on_bi;
if ( be->bd_info->bi_db_close ) {
- rc = be->bd_info->bi_db_close( be );
+ rc = be->bd_info->bi_db_close( be, NULL );
}
}
if ( oi->oi_orig->bi_db_close ) {
be->bd_info = oi->oi_orig;
- rc = be->bd_info->bi_db_close( be );
+ rc = be->bd_info->bi_db_close( be, NULL );
}
be->bd_info = bi_orig;
static int
over_db_destroy(
- BackendDB *be
+ BackendDB *be,
+ ConfigReply *cr
)
{
slap_overinfo *oi = be->bd_info->bi_private;
if ( on->on_bi.bi_db_destroy ) {
BackendInfo *bi_orig = be->bd_info;
be->bd_info = (BackendInfo *)on;
- on->on_bi.bi_db_destroy( be );
+ on->on_bi.bi_db_destroy( be, NULL );
be->bd_info = bi_orig;
}
free( on );
if ( on2->on_bi.bi_db_init ) {
int rc;
be->bd_info = (BackendInfo *)on2;
- rc = on2->on_bi.bi_db_init( be );
+ rc = on2->on_bi.bi_db_init( be, NULL );
be->bd_info = (BackendInfo *)oi;
if ( rc ) {
*prev = on2->on_next;
static ConfigDriver config_security;
static ConfigDriver config_referral;
static ConfigDriver config_loglevel;
-static ConfigDriver config_replica;
static ConfigDriver config_updatedn;
static ConfigDriver config_updateref;
static ConfigDriver config_include;
+static ConfigDriver config_obsolete;
#ifdef HAVE_TLS
static ConfigDriver config_tls_option;
static ConfigDriver config_tls_config;
CFG_TLS_DH_FILE,
CFG_TLS_VERIFY,
CFG_TLS_CRLCHECK,
+ CFG_TLS_CRL_FILE,
CFG_CONCUR,
CFG_THREADS,
CFG_SALT,
CFG_DIT,
CFG_ATTR,
CFG_ATOPT,
- CFG_REPLICA_ARGSFILE,
- CFG_REPLICA_PIDFILE,
- CFG_REPLICATIONINTERVAL,
- CFG_REPLOG,
CFG_ROOTDSE,
CFG_LOGFILE,
CFG_PLUGIN,
* OLcfg{Bk|Db}{Oc|At}:1 -> back-bdb(/back-hdb)
* OLcfg{Bk|Db}{Oc|At}:2 -> back-ldif
* OLcfg{Bk|Db}{Oc|At}:3 -> back-ldap
+ * OLcfg{Bk|Db}{Oc|At}:4 -> back-monitor
+ * OLcfg{Bk|Db}{Oc|At}:5 -> back-relay
+ * OLcfg{Bk|Db}{Oc|At}:6 -> back-sql
*/
/*
* OLcfgOv{Oc|At}:7 -> distproc
* OLcfgOv{Oc|At}:8 -> dynlist
* OLcfgOv{Oc|At}:9 -> dds
- * OLcfgOv{Oc|At}:10 -> unique
- * OLcfgOv{Oc|At}:11 -> refint
- * OLcfgOv{Oc|At}:12 -> ppolicy
- * OLcfgOv{Oc|At}:13 -> constraint
- * OLcfgOv{Oc|At}:14 -> translucent
- * OLcfgOv{Oc|At}:15 -> auditlog
+ * OLcfgOv{Oc|At}:10 -> unique
+ * OLcfgOv{Oc|At}:11 -> refint
+ * OLcfgOv{Oc|At}:12 -> ppolicy
+ * OLcfgOv{Oc|At}:13 -> constraint
+ * OLcfgOv{Oc|At}:14 -> translucent
+ * OLcfgOv{Oc|At}:15 -> auditlog
+ * OLcfgOv{Oc|At}:16 -> rwm
+ * OLcfgOv{Oc|At}:17 -> dyngroup
+ * OLcfgOv{Oc|At}:18 -> memberof
+ * OLcfgOv{Oc|At}:19 -> collect
*/
/* alphabetical ordering */
"SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL },
{ "moduleload", "file", 2, 0, 0,
#ifdef SLAPD_MODULES
- ARG_MAGIC|CFG_MODLOAD, &config_generic,
+ ARG_MAGIC|CFG_MODLOAD|ARG_NO_DELETE, &config_generic,
#else
ARG_IGNORED, NULL,
#endif
&config_referral, "( OLcfgGlAt:41 NAME 'olcReferral' "
"SUP labeledURI SINGLE-VALUE )", NULL, NULL },
{ "replica", "host or uri", 2, 0, 0, ARG_DB|ARG_MAGIC,
- &config_replica, "( OLcfgDbAt:0.7 NAME 'olcReplica' "
+ &config_obsolete, "( OLcfgDbAt:0.7 NAME 'olcReplica' "
"EQUALITY caseIgnoreMatch "
"SUP labeledURI X-ORDERED 'VALUES' )", NULL, NULL },
- { "replica-argsfile", NULL, 0, 0, 0, ARG_MAY_DB|ARG_MAGIC|ARG_STRING|CFG_REPLICA_ARGSFILE,
- &config_generic, "( OLcfgGlAt:43 NAME 'olcReplicaArgsFile' "
+ { "replica-argsfile", NULL, 0, 0, 0, ARG_MAY_DB|ARG_MAGIC,
+ &config_obsolete, "( OLcfgGlAt:43 NAME 'olcReplicaArgsFile' "
"SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
- { "replica-pidfile", NULL, 0, 0, 0, ARG_MAY_DB|ARG_MAGIC|ARG_STRING|CFG_REPLICA_PIDFILE,
- &config_generic, "( OLcfgGlAt:44 NAME 'olcReplicaPidFile' "
+ { "replica-pidfile", NULL, 0, 0, 0, ARG_MAY_DB|ARG_MAGIC,
+ &config_obsolete, "( OLcfgGlAt:44 NAME 'olcReplicaPidFile' "
"SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
- { "replicationInterval", NULL, 0, 0, 0, ARG_MAY_DB|ARG_MAGIC|ARG_INT|CFG_REPLICATIONINTERVAL,
- &config_generic, "( OLcfgGlAt:45 NAME 'olcReplicationInterval' "
+ { "replicationInterval", NULL, 0, 0, 0, ARG_MAY_DB|ARG_MAGIC,
+ &config_obsolete, "( OLcfgGlAt:45 NAME 'olcReplicationInterval' "
"SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
- { "replogfile", "filename", 2, 2, 0, ARG_MAY_DB|ARG_MAGIC|ARG_STRING|CFG_REPLOG,
- &config_generic, "( OLcfgGlAt:46 NAME 'olcReplogFile' "
+ { "replogfile", "filename", 2, 2, 0, ARG_MAY_DB|ARG_MAGIC,
+ &config_obsolete, "( OLcfgGlAt:46 NAME 'olcReplogFile' "
"SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
{ "require", "features", 2, 0, 7, ARG_MAY_DB|ARG_MAGIC,
&config_requires, "( OLcfgGlAt:47 NAME 'olcRequires' "
#endif
"( OLcfgGlAt:73 NAME 'olcTLSCRLCheck' "
"SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
+ { "TLSCRLFile", NULL, 0, 0, 0,
+#if defined(HAVE_GNUTLS)
+ CFG_TLS_CRL_FILE|ARG_STRING|ARG_MAGIC, &config_tls_option,
+#else
+ ARG_IGNORED, NULL,
+#endif
+ "( OLcfgGlAt:82 NAME 'olcTLSCRLFile' "
+ "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
{ "TLSRandFile", NULL, 0, 0, 0,
#ifdef HAVE_TLS
CFG_TLS_RAND|ARG_STRING|ARG_MAGIC, &config_tls_option,
"olcIndexSubstrIfMaxLen $ olcIndexSubstrIfMinLen $ "
"olcIndexSubstrAnyLen $ olcIndexSubstrAnyStep $ olcLocalSSF $ "
"olcLogLevel $ "
- "olcPasswordCryptSaltFormat $ olcPasswordHash $ olcPidFile $ "
+ "olcPasswordCryptSaltFormat $ olcPidFile $ "
"olcPluginLogFile $ olcReadOnly $ olcReferral $ "
"olcReplogFile $ olcRequires $ olcRestrict $ olcReverseLookup $ "
"olcRootDSE $ "
"olcTLSCACertificatePath $ olcTLSCertificateFile $ "
"olcTLSCertificateKeyFile $ olcTLSCipherSuite $ olcTLSCRLCheck $ "
"olcTLSRandFile $ olcTLSVerifyClient $ olcTLSDHParamFile $ "
- "olcToolThreads $ "
+ "olcTLSCRLFile $ olcToolThreads $ "
"olcObjectIdentifier $ olcAttributeTypes $ olcObjectClasses $ "
"olcDitContentRules ) )", Cft_Global },
{ "( OLcfgGlOc:2 "
"NAME 'olcFrontendConfig' "
"DESC 'OpenLDAP frontend configuration' "
"AUXILIARY "
- "MAY olcDefaultSearchBase )",
+ "MAY ( olcDefaultSearchBase $ olcPasswordHash ) )",
Cft_Database, NULL, NULL },
#ifdef SLAPD_MODULES
{ "( OLcfgGlOc:8 "
if ( c->be->be_limits ) {
char buf[4096*3];
struct berval bv;
- int i;
for ( i=0; c->be->be_limits[i]; i++ ) {
bv.bv_len = snprintf( buf, sizeof( buf ), SLAP_X_ORDERED_FMT, i );
rc = (!i);
break;
}
- case CFG_REPLICA_ARGSFILE:
- if ( c->be->be_replica_argsfile )
- c->value_string = ch_strdup( c->be->be_replica_argsfile );
- break;
- case CFG_REPLICA_PIDFILE:
- if ( c->be->be_replica_pidfile )
- c->value_string = ch_strdup( c->be->be_replica_pidfile );
- break;
- case CFG_REPLICATIONINTERVAL:
- if ( c->be->be_replicationinterval > 0 ) {
- c->value_int = c->be->be_replicationinterval;
- } else {
- rc = 1;
- }
- break;
- case CFG_REPLOG:
- if ( c->be->be_replogfile )
- c->value_string = ch_strdup( c->be->be_replogfile );
- break;
case CFG_ROOTDSE: {
ConfigFile *cf = c->private;
if ( cf->c_dseFiles ) {
if ( sid_list ) {
ServerID *si;
struct berval bv;
- char *ptr;
for ( si = sid_list; si; si=si->si_next ) {
+ assert( si->si_num >= 0 && si->si_num <= SLAP_SYNC_SID_MAX );
if ( !BER_BVISEMPTY( &si->si_url )) {
bv.bv_len = si->si_url.bv_len + 6;
bv.bv_val = ch_malloc( bv.bv_len );
passwd_salt = NULL;
break;
- case CFG_REPLICA_ARGSFILE:
- ch_free( c->be->be_replica_argsfile );
- c->be->be_replica_argsfile = NULL;
- break;
-
- case CFG_REPLICA_PIDFILE:
- ch_free( c->be->be_replica_pidfile );
- c->be->be_replica_pidfile = NULL;
- break;
-
- case CFG_REPLICATIONINTERVAL:
- c->be->be_replicationinterval = 0;
- break;
-
- case CFG_REPLOG:
- ch_free( c->be->be_replogfile );
- c->be->be_replogfile = NULL;
- break;
-
case CFG_LOGFILE:
ch_free( logfileName );
logfileName = NULL;
break;
case CFG_SERVERID: {
- int i;
ServerID *si, **sip;
for ( i=0, si = sid_list, sip = &sid_list;
cfn->c_oc_head = cfn->c_oc_tail = NULL;
} else {
ObjectClass *oc, *prev = NULL;
- int i;
for ( i=0, oc=cfn->c_oc_head; i<c->valx; i++) {
prev = oc;
cfn->c_at_head = cfn->c_at_tail = NULL;
} else {
AttributeType *at, *prev = NULL;
- int i;
for ( i=0, at=cfn->c_at_head; i<c->valx; i++) {
prev = at;
switch(c->type) {
case CFG_BACKEND:
if(!(c->bi = backend_info(c->argv[1]))) {
- snprintf( c->msg, sizeof( c->msg ), "<%s> failed init", c->argv[0] );
+ snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> failed init", c->argv[0] );
Debug(LDAP_DEBUG_ANY, "%s: %s (%s)!\n",
- c->log, c->msg, c->argv[1] );
+ c->log, c->cr_msg, c->argv[1] );
return(1);
}
break;
} else if ( !strcasecmp( c->argv[1], "frontend" )) {
c->be = frontendDB;
} else {
- c->be = backend_db_init(c->argv[1], NULL, c->valx);
+ c->be = backend_db_init(c->argv[1], NULL, c->valx, &c->reply);
if ( !c->be ) {
- snprintf( c->msg, sizeof( c->msg ), "<%s> failed init", c->argv[0] );
- Debug(LDAP_DEBUG_ANY, "%s: %s (%s)!\n",
- c->log, c->msg, c->argv[1] );
+ if ( c->cr_msg[0] == 0 )
+ snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> failed init", c->argv[0] );
+ Debug(LDAP_DEBUG_ANY, "%s: %s (%s)\n", c->log, c->cr_msg, c->argv[1] );
return(1);
}
}
case CFG_THREADS:
if ( c->value_int < 2 ) {
- snprintf( c->msg, sizeof( c->msg ),
+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
"threads=%d smaller than minimum value 2",
c->value_int );
Debug(LDAP_DEBUG_ANY, "%s: %s.\n",
- c->log, c->msg, 0 );
+ c->log, c->cr_msg, 0 );
return 1;
} else if ( c->value_int > 2 * SLAP_MAX_WORKER_THREADS ) {
- snprintf( c->msg, sizeof( c->msg ),
+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
"warning, threads=%d larger than twice the default (2*%d=%d); YMMV",
c->value_int, SLAP_MAX_WORKER_THREADS, 2 * SLAP_MAX_WORKER_THREADS );
Debug(LDAP_DEBUG_ANY, "%s: %s.\n",
- c->log, c->msg, 0 );
+ c->log, c->cr_msg, 0 );
}
if ( slapMode & SLAP_SERVER_MODE )
ldap_pvt_thread_pool_maxthreads(&connection_pool, c->value_int);
case CFG_AZPOLICY:
ch_free(c->value_string);
if (slap_sasl_setpolicy( c->argv[1] )) {
- snprintf( c->msg, sizeof( c->msg ), "<%s> unable to parse value", c->argv[0] );
+ snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> unable to parse value", c->argv[0] );
Debug(LDAP_DEBUG_ANY, "%s: %s \"%s\"\n",
- c->log, c->msg, c->argv[1] );
+ c->log, c->cr_msg, c->argv[1] );
return(1);
}
break;
{
char *txt = slap_sasl_secprops( c->argv[1] );
if ( txt ) {
- snprintf( c->msg, sizeof(c->msg), "<%s> %s",
+ snprintf( c->cr_msg, sizeof(c->cr_msg), "<%s> %s",
c->argv[0], txt );
- Debug(LDAP_DEBUG_ANY, "%s: %s\n", c->log, c->msg, 0 );
+ Debug(LDAP_DEBUG_ANY, "%s: %s\n", c->log, c->cr_msg, 0 );
return(1);
}
break;
}
break;
- case CFG_REPLICA_ARGSFILE:
- if(SLAP_MONITOR(c->be)) {
- Debug(LDAP_DEBUG_ANY, "%s: "
- "\"replica-argsfile\" should not be used "
- "inside monitor database\n",
- c->log, 0, 0);
- /* FIXME: should this be an error? */
- return(0);
- }
-
- if ( c->be->be_replica_argsfile != NULL ) {
- /* FIXME: error? */
- Debug(LDAP_DEBUG_ANY, "%s: "
- "\"replica-argsfile\" already provided; "
- "replacing \"%s\" with \"%s\".\n",
- c->log, c->be->be_replica_argsfile, c->value_string );
- ch_free( c->be->be_replica_argsfile );
- }
-
- c->be->be_replica_argsfile = c->value_string;
- break;
-
- case CFG_REPLICA_PIDFILE:
- if(SLAP_MONITOR(c->be)) {
- Debug(LDAP_DEBUG_ANY, "%s: "
- "\"replica-pidfile\" should not be used "
- "inside monitor database\n",
- c->log, 0, 0);
- /* FIXME: should this be an error? */
- return(0);
- }
-
- if ( c->be->be_replica_pidfile != NULL ) {
- /* FIXME: error? */
- Debug(LDAP_DEBUG_ANY, "%s: "
- "\"replica-pidfile\" already provided; "
- "replacing \"%s\" with \"%s\".\n",
- c->log, c->be->be_replica_pidfile, c->value_string );
- ch_free( c->be->be_replica_pidfile );
- }
-
- c->be->be_replica_pidfile = c->value_string;
- break;
-
- case CFG_REPLICATIONINTERVAL:
- if(SLAP_MONITOR(c->be)) {
- Debug(LDAP_DEBUG_ANY, "%s: "
- "\"replicationinterval\" should not be used "
- "inside monitor database\n",
- c->log, 0, 0);
- /* FIXME: should this be an error? */
- return(0);
- }
-
- c->be->be_replicationinterval = c->value_int;
- break;
-
- case CFG_REPLOG:
- if(SLAP_MONITOR(c->be)) {
- Debug(LDAP_DEBUG_ANY, "%s: "
- "\"replogfile\" should not be used "
- "inside monitor database\n",
- c->log, 0, 0);
- /* FIXME: should this be an error? */
- return(0);
- }
-
- if ( c->be->be_replogfile != NULL ) {
- /* FIXME: error? */
- Debug(LDAP_DEBUG_ANY, "%s: "
- "\"replogfile\" already provided; "
- "replacing \"%s\" with \"%s\".\n",
- c->log, c->be->be_replogfile, c->value_string );
- ch_free( c->be->be_replogfile );
- }
-
- c->be->be_replogfile = c->value_string;
- break;
-
case CFG_ROOTDSE:
if(root_dse_read_file(c->argv[1])) {
- snprintf( c->msg, sizeof( c->msg ), "<%s> could not read file", c->argv[0] );
+ snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> could not read file", c->argv[0] );
Debug(LDAP_DEBUG_ANY, "%s: %s %s\n",
- c->log, c->msg, c->argv[1] );
+ c->log, c->cr_msg, c->argv[1] );
return(1);
}
{
{
ServerID *si, **sip;
LDAPURLDesc *lud;
- int num = atoi( c->argv[1] );
- if ( num < 0 || num > SLAP_SYNC_SID_MAX ) {
- snprintf( c->msg, sizeof( c->msg ),
+ int num;
+ if ( lutil_atoi( &num, c->argv[1] ) ||
+ num < 0 || num > SLAP_SYNC_SID_MAX )
+ {
+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
"<%s> illegal server ID", c->argv[0] );
Debug(LDAP_DEBUG_ANY, "%s: %s %s\n",
- c->log, c->msg, c->argv[1] );
+ c->log, c->cr_msg, c->argv[1] );
return 1;
}
/* only one value allowed if no URL is given */
int len;
if ( sid_list && BER_BVISEMPTY( &sid_list->si_url )) {
- snprintf( c->msg, sizeof( c->msg ),
+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
"<%s> only one server ID allowed now", c->argv[0] );
Debug(LDAP_DEBUG_ANY, "%s: %s %s\n",
- c->log, c->msg, c->argv[1] );
+ c->log, c->cr_msg, c->argv[1] );
return 1;
}
if ( ldap_url_parse( c->argv[2], &lud )) {
- snprintf( c->msg, sizeof( c->msg ),
+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
"<%s> invalid URL", c->argv[0] );
Debug(LDAP_DEBUG_ANY, "%s: %s %s\n",
- c->log, c->msg, c->argv[2] );
+ c->log, c->cr_msg, c->argv[2] );
return 1;
}
len = strlen( c->argv[2] );
strcpy( si->si_url.bv_val, c->argv[2] );
} else {
if ( sid_list ) {
- snprintf( c->msg, sizeof( c->msg ),
+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
"<%s> unqualified server ID not allowed now", c->argv[0] );
Debug(LDAP_DEBUG_ANY, "%s: %s %s\n",
- c->log, c->msg, c->argv[1] );
+ c->log, c->cr_msg, c->argv[1] );
return 1;
}
si = ch_malloc( sizeof(ServerID) );
+ BER_BVZERO( &si->si_url );
slap_serverID = num;
+ Debug( LDAP_DEBUG_CONFIG,
+ "%s: SID=%d\n",
+ c->log, slap_serverID, 0 );
}
si->si_next = NULL;
si->si_num = num;
ldap_free_urldesc( lu2 );
if ( isMe ) {
slap_serverID = si->si_num;
+ Debug( LDAP_DEBUG_CONFIG,
+ "%s: SID=%d (listener=%s)\n",
+ c->log, slap_serverID,
+ l[i]->sl_url.bv_val );
break;
}
}
case CFG_LASTMOD:
if(SLAP_NOLASTMODCMD(c->be)) {
- snprintf( c->msg, sizeof( c->msg ), "<%s> not available for %s database",
+ snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> not available for %s database",
c->argv[0], c->be->bd_info->bi_type );
Debug(LDAP_DEBUG_ANY, "%s: %s\n",
- c->log, c->msg, 0 );
+ c->log, c->cr_msg, 0 );
return(1);
}
if(c->value_int)
case CFG_MIRRORMODE:
if(!SLAP_SHADOW(c->be)) {
- snprintf( c->msg, sizeof( c->msg ), "<%s> database is not a shadow",
+ snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> database is not a shadow",
c->argv[0] );
Debug(LDAP_DEBUG_ANY, "%s: %s\n",
- c->log, c->msg, 0 );
+ c->log, c->cr_msg, 0 );
return(1);
}
if(c->value_int)
case CFG_SSTR_IF_MAX:
if (c->value_int < index_substr_if_minlen) {
- snprintf( c->msg, sizeof( c->msg ), "<%s> invalid value", c->argv[0] );
+ snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> invalid value", c->argv[0] );
Debug(LDAP_DEBUG_ANY, "%s: %s (%d)\n",
- c->log, c->msg, c->value_int );
+ c->log, c->cr_msg, c->value_int );
return(1);
}
index_substr_if_maxlen = c->value_int;
case CFG_SSTR_IF_MIN:
if (c->value_int > index_substr_if_maxlen) {
- snprintf( c->msg, sizeof( c->msg ), "<%s> invalid value", c->argv[0] );
+ snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> invalid value", c->argv[0] );
Debug(LDAP_DEBUG_ANY, "%s: %s (%d)\n",
- c->log, c->msg, c->value_int );
+ c->log, c->cr_msg, c->value_int );
return(1);
}
index_substr_if_minlen = c->value_int;
modcur = c->private;
/* This should never fail */
if ( module_path( modcur->mp_path.bv_val )) {
- snprintf( c->msg, sizeof( c->msg ), "<%s> module path no longer valid",
+ snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> module path no longer valid",
c->argv[0] );
Debug(LDAP_DEBUG_ANY, "%s: %s (%s)\n",
- c->log, c->msg, modcur->mp_path.bv_val );
+ c->log, c->cr_msg, modcur->mp_path.bv_val );
return(1);
}
}
}
for(i = 1; i < c->argc; i++) {
if(!lutil_passwd_scheme(c->argv[i])) {
- snprintf( c->msg, sizeof( c->msg ), "<%s> scheme not available", c->argv[0] );
+ snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> scheme not available", c->argv[0] );
Debug(LDAP_DEBUG_ANY, "%s: %s (%s)\n",
- c->log, c->msg, c->argv[i]);
+ c->log, c->cr_msg, c->argv[i]);
} else {
ldap_charray_add(&default_passwd_hash, c->argv[i]);
}
if(!default_passwd_hash) {
- snprintf( c->msg, sizeof( c->msg ), "<%s> no valid hashes found", c->argv[0] );
+ snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> no valid hashes found", c->argv[0] );
Debug(LDAP_DEBUG_ANY, "%s: %s\n",
- c->log, c->msg, 0 );
+ c->log, c->cr_msg, 0 );
return(1);
}
}
if(!strncasecmp(c->argv[i], "size", 4)) {
rc = limits_parse_one(c->argv[i], lim);
if ( rc ) {
- snprintf( c->msg, sizeof( c->msg ), "<%s> unable to parse value", c->argv[0] );
+ snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> unable to parse value", c->argv[0] );
Debug(LDAP_DEBUG_ANY, "%s: %s \"%s\"\n",
- c->log, c->msg, c->argv[i]);
+ c->log, c->cr_msg, c->argv[i]);
return(1);
}
} else {
lim->lms_s_soft = -1;
} else {
if ( lutil_atoix( &lim->lms_s_soft, c->argv[i], 0 ) != 0 ) {
- snprintf( c->msg, sizeof( c->msg ), "<%s> unable to parse limit", c->argv[0]);
+ snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> unable to parse limit", c->argv[0]);
Debug(LDAP_DEBUG_ANY, "%s: %s \"%s\"\n",
- c->log, c->msg, c->argv[i]);
+ c->log, c->cr_msg, c->argv[i]);
return(1);
}
}
if(!strncasecmp(c->argv[i], "time", 4)) {
rc = limits_parse_one(c->argv[i], lim);
if ( rc ) {
- snprintf( c->msg, sizeof( c->msg ), "<%s> unable to parse value", c->argv[0] );
+ snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> unable to parse value", c->argv[0] );
Debug(LDAP_DEBUG_ANY, "%s: %s \"%s\"\n",
- c->log, c->msg, c->argv[i]);
+ c->log, c->cr_msg, c->argv[i]);
return(1);
}
} else {
lim->lms_t_soft = -1;
} else {
if ( lutil_atoix( &lim->lms_t_soft, c->argv[i], 0 ) != 0 ) {
- snprintf( c->msg, sizeof( c->msg ), "<%s> unable to parse limit", c->argv[0]);
+ snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> unable to parse limit", c->argv[0]);
Debug(LDAP_DEBUG_ANY, "%s: %s \"%s\"\n",
- c->log, c->msg, c->argv[i]);
+ c->log, c->cr_msg, c->argv[i]);
return(1);
}
}
#ifdef SLAPD_MONITOR_DN
if(!strcasecmp(c->argv[1], SLAPD_MONITOR_DN)) {
- snprintf( c->msg, sizeof( c->msg ), "<%s> DN is reserved for monitoring slapd",
+ snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> DN is reserved for monitoring slapd",
c->argv[0] );
Debug(LDAP_DEBUG_ANY, "%s: %s (%s)\n",
- c->log, c->msg, SLAPD_MONITOR_DN);
+ c->log, c->cr_msg, SLAPD_MONITOR_DN);
return(1);
}
#endif
if (SLAP_DBHIDDEN( c->be ))
tbe = NULL;
else
- tbe = select_backend(&ndn, 0, 0);
+ tbe = select_backend(&ndn, 0);
if(tbe == c->be) {
Debug( LDAP_DEBUG_ANY, "%s: suffix already served by this backend!.\n",
c->log, 0, 0);
type = oi->oi_orig->bi_type;
}
- snprintf( c->msg, sizeof( c->msg ), "<%s> namingContext \"%s\" "
+ snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> namingContext \"%s\" "
"already served by a preceding %s database",
c->argv[0], pdn.bv_val, type );
Debug(LDAP_DEBUG_ANY, "%s: %s serving namingContext \"%s\"\n",
- c->log, c->msg, tbe->be_suffix[0].bv_val);
+ c->log, c->cr_msg, tbe->be_suffix[0].bv_val);
free(pdn.bv_val);
free(ndn.bv_val);
return(1);
return 0;
}
- tbe = select_backend(&c->be->be_rootndn, 0, 0);
+ tbe = select_backend(&c->be->be_rootndn, 0);
if(tbe != c->be) {
- snprintf( c->msg, sizeof( c->msg ), "<%s> can only be set when rootdn is under suffix",
+ snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> can only be set when rootdn is under suffix",
c->argv[0] );
Debug(LDAP_DEBUG_ANY, "%s: %s\n",
- c->log, c->msg, 0);
+ c->log, c->cr_msg, 0);
return(1);
}
if ( !BER_BVISNULL( &c->be->be_rootpw ))
}
i = verbs_to_mask( c->argc, c->argv, restrictable_ops, &restrictops );
if ( i ) {
- snprintf( c->msg, sizeof( c->msg ), "<%s> unknown operation", c->argv[0] );
+ snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> unknown operation", c->argv[0] );
Debug(LDAP_DEBUG_ANY, "%s: %s %s\n",
- c->log, c->msg, c->argv[i]);
+ c->log, c->cr_msg, c->argv[i]);
return(1);
}
if ( restrictops & SLAP_RESTRICT_OP_EXTENDED )
}
i = verbs_to_mask(c->argc, c->argv, allowable_ops, &allows);
if ( i ) {
- snprintf( c->msg, sizeof( c->msg ), "<%s> unknown feature", c->argv[0] );
+ snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> unknown feature", c->argv[0] );
Debug(LDAP_DEBUG_ANY, "%s: %s %s\n",
- c->log, c->msg, c->argv[i]);
+ c->log, c->cr_msg, c->argv[i]);
return(1);
}
global_allows |= allows;
}
i = verbs_to_mask(c->argc, c->argv, disallowable_ops, &disallows);
if ( i ) {
- snprintf( c->msg, sizeof( c->msg ), "<%s> unknown feature", c->argv[0] );
+ snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> unknown feature", c->argv[0] );
Debug(LDAP_DEBUG_ANY, "%s: %s %s\n",
- c->log, c->msg, c->argv[i]);
+ c->log, c->cr_msg, c->argv[i]);
return(1);
}
global_disallows |= disallows;
i = verbs_to_mask(argc, argv, requires_ops, &requires);
if ( i ) {
if (strcasecmp( c->argv[ i ], "none" ) == 0 ) {
- snprintf( c->msg, sizeof( c->msg ), "<%s> \"none\" (#%d) must be listed first", c->argv[0], i - 1 );
+ snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> \"none\" (#%d) must be listed first", c->argv[0], i - 1 );
Debug(LDAP_DEBUG_ANY, "%s: %s\n",
- c->log, c->msg, 0);
+ c->log, c->cr_msg, 0);
} else {
- snprintf( c->msg, sizeof( c->msg ), "<%s> unknown feature #%d", c->argv[0], i - 1 );
+ snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> unknown feature #%d", c->argv[0], i - 1 );
Debug(LDAP_DEBUG_ANY, "%s: %s \"%s\"\n",
- c->log, c->msg, c->argv[i]);
+ c->log, c->cr_msg, c->argv[i]);
}
return(1);
}
slap_loglevel_get( struct berval *s, int *l )
{
int rc;
- unsigned long i;
- slap_mask_t m;
+ slap_mask_t m, i;
if ( loglevel_ops == NULL ) {
loglevel_init();
m |= loglevel_ops[ i ].mask;
}
- m = ~m;
-
- for ( i = 1; i <= ( 1 << ( sizeof( int ) * 8 - 1 ) ) && !( m & i ); i <<= 1 )
+ for ( i = 1; m & i; i <<= 1 )
;
- if ( !( m & i ) ) {
+ if ( i == 0 ) {
return -1;
}
return 0;
}
- config_syslog = 0;
-
for( i=1; i < c->argc; i++ ) {
int level;
if ( isdigit((unsigned char)c->argv[i][0]) || c->argv[i][0] == '-' ) {
if( lutil_atoi( &level, c->argv[i] ) != 0 ) {
- snprintf( c->msg, sizeof( c->msg ), "<%s> unable to parse level", c->argv[0] );
+ snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> unable to parse level", c->argv[0] );
Debug( LDAP_DEBUG_ANY, "%s: %s \"%s\"\n",
- c->log, c->msg, c->argv[i]);
+ c->log, c->cr_msg, c->argv[i]);
return( 1 );
}
} else {
if ( str2loglevel( c->argv[i], &level ) ) {
- snprintf( c->msg, sizeof( c->msg ), "<%s> unknown level", c->argv[0] );
+ snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> unknown level", c->argv[0] );
Debug( LDAP_DEBUG_ANY, "%s: %s \"%s\"\n",
- c->log, c->msg, c->argv[i]);
+ c->log, c->cr_msg, c->argv[i]);
return( 1 );
}
}
- config_syslog |= level;
+ /* Explicitly setting a zero clears all the levels */
+ if ( level )
+ config_syslog |= level;
+ else
+ config_syslog = 0;
}
if ( slapMode & SLAP_SERVER_MODE ) {
ldap_syslog = config_syslog;
return 0;
}
if(validate_global_referral(c->argv[1])) {
- snprintf( c->msg, sizeof( c->msg ), "<%s> invalid URL", c->argv[0] );
+ snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> invalid URL", c->argv[0] );
Debug(LDAP_DEBUG_ANY, "%s: %s (%s)\n",
- c->log, c->msg, c->argv[1]);
+ c->log, c->cr_msg, c->argv[1]);
return(1);
}
}
}
if ( !tgt ) {
- snprintf( c->msg, sizeof( c->msg ), "<%s> unknown factor", c->argv[0] );
+ snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> unknown factor", c->argv[0] );
Debug(LDAP_DEBUG_ANY, "%s: %s %s\n",
- c->log, c->msg, c->argv[i]);
+ c->log, c->cr_msg, c->argv[i]);
return(1);
}
if ( lutil_atou( tgt, src ) != 0 ) {
- snprintf( c->msg, sizeof( c->msg ), "<%s> unable to parse factor", c->argv[0] );
+ snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> unable to parse factor", c->argv[0] );
Debug(LDAP_DEBUG_ANY, "%s: %s \"%s\"\n",
- c->log, c->msg, c->argv[i]);
+ c->log, c->cr_msg, c->argv[i]);
return(1);
}
}
return ptr;
}
-static void
-replica_unparse( struct slap_replica_info *ri, int i, struct berval *bv )
-{
- int len;
- char *ptr;
- struct berval bc = BER_BVNULL;
- char numbuf[32];
-
- assert( !BER_BVISNULL( &ri->ri_bindconf.sb_uri ) );
-
- BER_BVZERO( bv );
-
- len = snprintf(numbuf, sizeof( numbuf ), SLAP_X_ORDERED_FMT, i );
- if ( len >= sizeof( numbuf ) ) {
- /* FIXME: how can indicate error? */
- return;
- }
-
- if ( ri->ri_nsuffix ) {
- for (i=0; !BER_BVISNULL( &ri->ri_nsuffix[i] ); i++) {
- len += ri->ri_nsuffix[i].bv_len + STRLENOF(" suffix=\"\"");
- }
- }
- if ( ri->ri_attrs ) {
- len += STRLENOF(" attrs");
- if ( ri->ri_exclude ) len++;
- for (i=0; !BER_BVISNULL( &ri->ri_attrs[i].an_name ); i++) {
- len += 1 + ri->ri_attrs[i].an_name.bv_len;
- }
- }
- bindconf_unparse( &ri->ri_bindconf, &bc );
- len += bc.bv_len;
-
- bv->bv_val = ch_malloc(len + 1);
- bv->bv_len = len;
-
- ptr = lutil_strcopy( bv->bv_val, numbuf );
-
- /* start with URI from bindconf */
- assert( !BER_BVISNULL( &bc ) );
- if ( bc.bv_val ) {
- strcpy( ptr, bc.bv_val );
- ch_free( bc.bv_val );
- }
-
- if ( ri->ri_nsuffix ) {
- for (i=0; !BER_BVISNULL( &ri->ri_nsuffix[i] ); i++) {
- ptr = lutil_strcopy( ptr, " suffix=\"" );
- ptr = lutil_strcopy( ptr, ri->ri_nsuffix[i].bv_val );
- *ptr++ = '"';
- }
- }
- if ( ri->ri_attrs ) {
- ptr = lutil_strcopy( ptr, " attrs" );
- if ( ri->ri_exclude ) *ptr++ = '!';
- *ptr++ = '=';
- ptr = anlist_unparse( ri->ri_attrs, ptr, 0 );
- }
-}
-
-static int
-config_replica(ConfigArgs *c) {
- int i, nr = -1;
- char *replicahost = NULL, *replicauri = NULL;
- LDAPURLDesc *ludp;
-
- if (c->op == SLAP_CONFIG_EMIT) {
- if (c->be->be_replica) {
- struct berval bv;
- for (i=0;c->be->be_replica[i]; i++) {
- replica_unparse( c->be->be_replica[i], i, &bv );
- ber_bvarray_add( &c->rvalue_vals, &bv );
- }
- return 0;
- }
- return 1;
- } else if ( c->op == LDAP_MOD_DELETE ) {
- /* FIXME: there is no replica_free function */
- if ( c->valx < 0 ) {
- } else {
- }
- }
- if(SLAP_MONITOR(c->be)) {
- Debug(LDAP_DEBUG_ANY, "%s: "
- "\"replica\" should not be used inside monitor database\n",
- c->log, 0, 0);
- return(0); /* FIXME: should this be an error? */
- }
-
- for(i = 1; i < c->argc; i++) {
- if(!strncasecmp(c->argv[i], "host=", STRLENOF("host="))) {
- ber_len_t len;
-
- if ( replicauri ) {
- snprintf( c->msg, sizeof( c->msg ), "<%s> replica host/URI already specified", c->argv[0] );
- Debug(LDAP_DEBUG_ANY, "%s: %s \"%s\"\n", c->log, c->msg, replicauri );
- return(1);
- }
-
- replicahost = c->argv[i] + STRLENOF("host=");
- len = strlen( replicahost ) + STRLENOF("ldap://");
- replicauri = ch_malloc( len + 1 );
- snprintf( replicauri, len + 1, "ldap://%s", replicahost );
- replicahost = replicauri + STRLENOF( "ldap://");
- nr = add_replica_info(c->be, replicauri, replicahost);
- break;
- } else if(!strncasecmp(c->argv[i], "uri=", STRLENOF("uri="))) {
- ber_len_t len;
-
- if ( replicauri ) {
- snprintf( c->msg, sizeof( c->msg ), "<%s> replica host/URI already specified", c->argv[0] );
- Debug(LDAP_DEBUG_ANY, "%s: %s \"%s\"\n", c->log, c->msg, replicauri );
- return(1);
- }
-
- if(ldap_url_parse(c->argv[i] + STRLENOF("uri="), &ludp) != LDAP_SUCCESS) {
- snprintf( c->msg, sizeof( c->msg ), "<%s> invalid uri", c->argv[0] );
- Debug(LDAP_DEBUG_ANY, "%s: %s\n", c->log, c->msg, 0 );
- return(1);
- }
- if(!ludp->lud_host) {
- ldap_free_urldesc(ludp);
- snprintf( c->msg, sizeof( c->msg ), "<%s> invalid uri - missing hostname",
- c->argv[0] );
- Debug(LDAP_DEBUG_ANY, "%s: %s\n", c->log, c->msg, 0 );
- return(1);
- }
-
- len = strlen(ludp->lud_scheme) + strlen(ludp->lud_host) +
- STRLENOF("://") + 1;
- if (ludp->lud_port != LDAP_PORT) {
- if (ludp->lud_port < 1 || ludp->lud_port > 65535) {
- ldap_free_urldesc(ludp);
- snprintf( c->msg, sizeof( c->msg ), "<%s> invalid port",
- c->argv[0] );
- Debug(LDAP_DEBUG_ANY, "%s: %s\n", c->log, c->msg, 0 );
- return(1);
- }
- len += STRLENOF(":65535");
- }
- replicauri = ch_malloc( len );
- replicahost = lutil_strcopy( replicauri, ludp->lud_scheme );
- replicahost = lutil_strcopy( replicahost, "://" );
- if (ludp->lud_port == LDAP_PORT) {
- strcpy( replicahost, ludp->lud_host );
- } else {
- sprintf( replicahost, "%s:%d",ludp->lud_host,ludp->lud_port );
- }
- ldap_free_urldesc(ludp);
- nr = add_replica_info(c->be, replicauri, replicahost);
- break;
- }
- }
- if(i == c->argc) {
- snprintf( c->msg, sizeof( c->msg ), "<%s> missing host or uri", c->argv[0] );
- Debug(LDAP_DEBUG_ANY, "%s: %s\n", c->log, c->msg, 0 );
- return(1);
- } else if(nr == -1) {
- snprintf( c->msg, sizeof( c->msg ), "<%s> unable to add replica", c->argv[0] );
- Debug(LDAP_DEBUG_ANY, "%s: %s \"%s\"\n", c->log, c->msg,
- replicauri ? replicauri : "" );
- return(1);
- } else {
- for(i = 1; i < c->argc; i++) {
- if(!strncasecmp(c->argv[i], "uri=", STRLENOF("uri="))) {
- /* dealt with separately; don't let it get to bindconf */
- ;
-
- } else if(!strncasecmp(c->argv[i], "host=", STRLENOF("host="))) {
- /* dealt with separately; don't let it get to bindconf */
- ;
-
- } else if(!strncasecmp(c->argv[i], "suffix=", STRLENOF( "suffix="))) {
- switch(add_replica_suffix(c->be, nr, c->argv[i] + STRLENOF("suffix="))) {
- case 1:
- Debug( LDAP_DEBUG_ANY, "%s: "
- "suffix \"%s\" in \"replica\" line is not valid for backend.\n",
- c->log, c->argv[i] + STRLENOF("suffix="), 0);
- return 1;
- break;
- case 2:
- Debug( LDAP_DEBUG_ANY, "%s: "
- "unable to normalize suffix in \"replica\" line.\n",
- c->log, 0, 0);
- return 1;
- break;
- }
-
- } else if (!strncasecmp(c->argv[i], "attr", STRLENOF("attr"))
- || !strncasecmp(c->argv[i], "attrs", STRLENOF("attrs")))
- {
- int exclude = 0;
- char *arg = c->argv[i] + STRLENOF("attr");
- if (arg[0] == 's') {
- arg++;
- } else {
- Debug( LDAP_DEBUG_ANY,
- "%s: \"attr\" "
- "is deprecated (and undocumented); "
- "use \"attrs\" instead.\n",
- c->log, 0, 0 );
- }
- if(arg[0] == '!') {
- arg++;
- exclude = 1;
- }
- if(arg[0] != '=') {
- continue;
- }
- if(add_replica_attrs(c->be, nr, arg + 1, exclude)) {
- snprintf( c->msg, sizeof( c->msg ), "<%s> unknown attribute", c->argv[0] );
- Debug(LDAP_DEBUG_ANY, "%s: %s \"%s\"\n",
- c->log, c->msg, arg + 1);
- return(1);
- }
- } else if ( bindconf_parse( c->argv[i],
- &c->be->be_replica[nr]->ri_bindconf ) ) {
- return(1);
- }
- }
- }
- return(0);
-}
-
static int
config_updatedn(ConfigArgs *c) {
if (c->op == SLAP_CONFIG_EMIT) {
return 0;
}
if(SLAP_SHADOW(c->be)) {
- snprintf( c->msg, sizeof( c->msg ), "<%s> database already shadowed", c->argv[0] );
+ snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> database already shadowed", c->argv[0] );
Debug(LDAP_DEBUG_ANY, "%s: %s\n",
- c->log, c->msg, 0);
+ c->log, c->cr_msg, 0);
return(1);
}
return 0;
}
if(!SLAP_SHADOW(c->be) && !c->be->be_syncinfo) {
- snprintf( c->msg, sizeof( c->msg ), "<%s> must appear after syncrepl or updatedn",
+ snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> must appear after syncrepl or updatedn",
c->argv[0] );
Debug(LDAP_DEBUG_ANY, "%s: %s\n",
- c->log, c->msg, 0);
+ c->log, c->cr_msg, 0);
return(1);
}
if(validate_global_referral(c->argv[1])) {
- snprintf( c->msg, sizeof( c->msg ), "<%s> invalid URL", c->argv[0] );
+ snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> invalid URL", c->argv[0] );
Debug(LDAP_DEBUG_ANY, "%s: %s (%s)\n",
- c->log, c->msg, c->argv[1]);
+ c->log, c->cr_msg, c->argv[1]);
return(1);
}
ber_str2bv(c->argv[1], 0, 0, &val);
return(0);
}
+static int
+config_obsolete(ConfigArgs *c) {
+ if (c->op == SLAP_CONFIG_EMIT)
+ return 1;
+
+ snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> keyword is obsolete (ignored)",
+ c->argv[0] );
+ Debug(LDAP_DEBUG_ANY, "%s: %s\n", c->log, c->cr_msg, 0);
+ return(0);
+}
+
static int
config_include(ConfigArgs *c) {
int savelineno = c->lineno;
case CFG_TLS_CA_PATH: flag = LDAP_OPT_X_TLS_CACERTDIR; break;
case CFG_TLS_CA_FILE: flag = LDAP_OPT_X_TLS_CACERTFILE; break;
case CFG_TLS_DH_FILE: flag = LDAP_OPT_X_TLS_DHFILE; break;
+#ifdef HAVE_GNUTLS
+ case CFG_TLS_CRL_FILE: flag = LDAP_OPT_X_TLS_CRLFILE; break;
+#endif
default: Debug(LDAP_DEBUG_ANY, "%s: "
"unknown tls_option <0x%x>\n",
c->log, c->type, 0);
rs->sr_err = config_add_internal( sc->cfb, rs->sr_entry, sc->ca, NULL, NULL, NULL );
if ( rs->sr_err != LDAP_SUCCESS ) {
Debug( LDAP_DEBUG_ANY, "config error processing %s: %s\n",
- rs->sr_entry->e_name.bv_val, sc->ca->msg, 0 );
+ rs->sr_entry->e_name.bv_val, sc->ca->cr_msg, 0 );
}
}
return rs->sr_err;
if ( !cfb->cb_db.bd_info )
return 0; /* FIXME: eventually this will be a fatal error */
- if ( backend_db_init( "ldif", &cfb->cb_db, -1 ) == NULL )
+ if ( backend_db_init( "ldif", &cfb->cb_db, -1, NULL ) == NULL )
return 1;
cfb->cb_db.be_suffix = be->be_suffix;
argv[1] = (char *)dir;
argv[2] = NULL;
c.argv = argv;
+ c.reply.err = 0;
+ c.reply.msg[0] = 0;
+ c.table = Cft_Database;
ct = config_find_keyword( c.be->be_cf_ocs->co_table, &c );
if ( !ct )
if ( config_add_vals( ct, &c ))
return 1;
- if ( backend_startup_one( &cfb->cb_db ))
+ if ( backend_startup_one( &cfb->cb_db, &c.reply ))
return 1;
if ( readit ) {
void *thrctx = ldap_pvt_thread_pool_context();
int prev_DN_strict;
- op = (Operation *) &opbuf;
- connection_fake_init( &conn, op, thrctx );
+ connection_fake_init( &conn, &opbuf, thrctx );
+ op = &opbuf.ob_op;
filter.f_desc = slap_schema.si_ad_objectClass;
int rc;
/* Setup the config backend */
- be = backend_db_init( "config", NULL, 0 );
+ be = backend_db_init( "config", NULL, 0, NULL );
if ( !be )
return 1;
static int
config_back_bind( Operation *op, SlapReply *rs )
{
- if ( op->orb_method == LDAP_AUTH_SIMPLE && be_isroot_pw( op )) {
+ if ( be_isroot_pw( op ) ) {
ber_dupbv( &op->orb_edn, be_root_dn( op->o_bd ));
/* frontend sends result */
return LDAP_SUCCESS;
}
static ConfigTable *
-config_find_table( ConfigOCs **colst, int nocs, AttributeDescription *ad )
+config_find_table( ConfigOCs **colst, int nocs, AttributeDescription *ad,
+ ConfigArgs *ca )
{
int i, j;
for (j=0; j<nocs; j++) {
for (i=0; colst[j]->co_table[i].name; i++)
- if ( colst[j]->co_table[i].ad == ad )
+ if ( colst[j]->co_table[i].ad == ad ) {
+ ca->table = colst[j]->co_type;
return &colst[j]->co_table[i];
+ }
}
return NULL;
}
if ( a && ( ad->ad_type->sat_flags & SLAP_AT_ORDERED_VAL )) {
rc = ordered_value_sort( a, 1 );
if ( rc ) {
- snprintf(ca->msg, sizeof( ca->msg ), "ordered_value_sort failed on attr %s\n",
+ snprintf(ca->cr_msg, sizeof( ca->cr_msg ), "ordered_value_sort failed on attr %s\n",
ad->ad_cname.bv_val );
return rc;
}
{
CfEntryInfo *ce;
int index = -1, gotindex = 0, nsibs, rc = 0;
- int renumber = 0, tailindex = 0, isfrontend = 0;
+ int renumber = 0, tailindex = 0, isfrontend = 0, isconfig = 0;
char *ptr1, *ptr2 = NULL;
struct berval rdn;
/* See if the rdn has an index already */
dnRdn( &e->e_name, &rdn );
- if ( ce_type == Cft_Database && !strncmp( rdn.bv_val + rdn.bv_len -
- STRLENOF("frontend"), "frontend", STRLENOF("frontend") ))
- isfrontend = 1;
+ if ( ce_type == Cft_Database ) {
+ if ( !strncmp( rdn.bv_val + rdn.bv_len - STRLENOF("frontend"),
+ "frontend", STRLENOF("frontend") ))
+ isfrontend = 1;
+ else if ( !strncmp( rdn.bv_val + rdn.bv_len - STRLENOF("config"),
+ "config", STRLENOF("config") ))
+ isconfig = 1;
+ }
ptr1 = ber_bvchr( &e->e_name, '{' );
if ( ptr1 && ptr1 - e->e_name.bv_val < rdn.bv_len ) {
char *next;
if ( index != -1 || !isfrontend )
return LDAP_NAMING_VIOLATION;
}
+ if ( isconfig && index != 0 ){
+ return LDAP_NAMING_VIOLATION;
+ }
}
/* count related kids */
renumber = 1;
}
}
+ /* config DB is always "0" */
+ if ( isconfig && index == -1 ) {
+ index = 0;
+ }
if ( !isfrontend && index == -1 ) {
index = nsibs;
}
return rc;
}
+static int
+count_oc( ObjectClass *oc, ConfigOCs ***copp, int *nocs )
+{
+ ConfigOCs co, *cop;
+ ObjectClass **sups;
+
+ co.co_name = &oc->soc_cname;
+ cop = avl_find( CfOcTree, &co, CfOc_cmp );
+ if ( cop ) {
+ int i;
+
+ /* check for duplicates */
+ for ( i = 0; i < *nocs; i++ ) {
+ if ( *copp && (*copp)[i] == cop ) {
+ break;
+ }
+ }
+
+ if ( i == *nocs ) {
+ ConfigOCs **tmp = ch_realloc( *copp, (*nocs + 1)*sizeof( ConfigOCs * ) );
+ if ( tmp == NULL ) {
+ return -1;
+ }
+ *copp = tmp;
+ (*copp)[*nocs] = cop;
+ (*nocs)++;
+ }
+ }
+
+ for ( sups = oc->soc_sups; sups && *sups; sups++ ) {
+ if ( count_oc( *sups, copp, nocs ) ) {
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
static ConfigOCs **
count_ocs( Attribute *oc_at, int *nocs )
{
- int i, j, n;
- ConfigOCs co, *coptr, **colst;
+ int i;
+ ConfigOCs **colst = NULL;
- /* count the objectclasses */
- for ( i=0; oc_at->a_nvals[i].bv_val; i++ );
- n = i;
- colst = (ConfigOCs **)ch_malloc( n * sizeof(ConfigOCs *));
+ *nocs = 0;
- for ( i=0, j=0; i<n; i++) {
- co.co_name = &oc_at->a_nvals[i];
- coptr = avl_find( CfOcTree, &co, CfOc_cmp );
-
- /* ignore non-config objectclasses. probably should be
- * an error, general data doesn't belong here.
- */
- if ( !coptr ) continue;
+ for ( i = 0; !BER_BVISNULL( &oc_at->a_nvals[i] ); i++ )
+ /* count attrs */ ;
- /* Ignore the root objectclass, it has no implementation.
- */
- if ( coptr->co_type == Cft_Abstract ) continue;
- colst[j++] = coptr;
+ for ( ; i--; ) {
+ ObjectClass *oc = oc_bvfind( &oc_at->a_nvals[i] );
+
+ assert( oc != NULL );
+ if ( count_oc( oc, &colst, nocs ) ) {
+ ch_free( colst );
+ return NULL;
+ }
}
- *nocs = j;
+
return colst;
}
static int
cfAddDatabase( CfEntryInfo *p, Entry *e, struct config_args_s *ca )
{
- if ( p->ce_type != Cft_Global )
+ if ( p->ce_type != Cft_Global ) {
return LDAP_CONSTRAINT_VIOLATION;
+ }
ca->be = frontendDB; /* just to get past check_vals */
return LDAP_SUCCESS;
}
static int
cfAddBackend( CfEntryInfo *p, Entry *e, struct config_args_s *ca )
{
- if ( p->ce_type != Cft_Global )
+ if ( p->ce_type != Cft_Global ) {
return LDAP_CONSTRAINT_VIOLATION;
+ }
return LDAP_SUCCESS;
}
static int
cfAddModule( CfEntryInfo *p, Entry *e, struct config_args_s *ca )
{
- if ( p->ce_type != Cft_Global )
+ if ( p->ce_type != Cft_Global ) {
return LDAP_CONSTRAINT_VIOLATION;
+ }
return LDAP_SUCCESS;
}
static int
cfAddOverlay( CfEntryInfo *p, Entry *e, struct config_args_s *ca )
{
- if ( p->ce_type != Cft_Database )
+ if ( p->ce_type != Cft_Database ) {
return LDAP_CONSTRAINT_VIOLATION;
+ }
ca->be = p->ce_be;
return LDAP_SUCCESS;
}
struct berval bv = BER_BVC("olcDitContentRules");
ad = NULL;
slap_bv2ad( &bv, &ad, &text );
- ct = config_find_table( colst, nocs, ad );
+ ct = config_find_table( colst, nocs, ad, ca );
config_del_vals( ct, ca );
}
if ( cfn->c_oc_head ) {
struct berval bv = BER_BVC("olcObjectClasses");
ad = NULL;
slap_bv2ad( &bv, &ad, &text );
- ct = config_find_table( colst, nocs, ad );
+ ct = config_find_table( colst, nocs, ad, ca );
config_del_vals( ct, ca );
}
if ( cfn->c_at_head ) {
struct berval bv = BER_BVC("olcAttributeTypes");
ad = NULL;
slap_bv2ad( &bv, &ad, &text );
- ct = config_find_table( colst, nocs, ad );
+ ct = config_find_table( colst, nocs, ad, ca );
config_del_vals( ct, ca );
}
if ( cfn->c_om_head ) {
struct berval bv = BER_BVC("olcObjectIdentifier");
ad = NULL;
slap_bv2ad( &bv, &ad, &text );
- ct = config_find_table( colst, nocs, ad );
+ ct = config_find_table( colst, nocs, ad, ca );
config_del_vals( ct, ca );
}
cfo = p->ce_private;
ch_free( cfn );
}
+static int
+config_add_oc( ConfigOCs **cop, CfEntryInfo *last, Entry *e, ConfigArgs *ca )
+{
+ int rc = LDAP_CONSTRAINT_VIOLATION;
+ ObjectClass **ocp;
+
+ if ( (*cop)->co_ldadd ) {
+ rc = (*cop)->co_ldadd( last, e, ca );
+ if ( rc != LDAP_CONSTRAINT_VIOLATION ) {
+ return rc;
+ }
+ }
+
+ for ( ocp = (*cop)->co_oc->soc_sups; ocp && *ocp; ocp++ ) {
+ ConfigOCs co = { 0 };
+
+ co.co_name = &(*ocp)->soc_cname;
+ *cop = avl_find( CfOcTree, &co, CfOc_cmp );
+ if ( *cop == NULL ) {
+ return rc;
+ }
+
+ rc = config_add_oc( cop, last, e, ca );
+ if ( rc != LDAP_CONSTRAINT_VIOLATION ) {
+ return rc;
+ }
+ }
+
+ return rc;
+}
+
/* Parse an LDAP entry into config directives */
static int
config_add_internal( CfBackInfo *cfb, Entry *e, ConfigArgs *ca, SlapReply *rs,
int *renum, Operation *op )
{
- CfEntryInfo *ce, *last;
- ConfigOCs **colst;
- Attribute *a, *oc_at;
- int i, ibase = -1, nocs, rc = 0;
- struct berval pdn;
- ConfigTable *ct;
- char *ptr;
+ CfEntryInfo *ce, *last = NULL;
+ ConfigOCs co, *coptr, **colst;
+ Attribute *a, *oc_at, *soc_at;
+ int i, ibase = -1, nocs, rc = 0;
+ struct berval pdn;
+ ConfigTable *ct;
+ char *ptr, *log_prefix = op ? op->o_log_prefix : "";
memset( ca, 0, sizeof(ConfigArgs));
*/
ce = config_find_base( cfb->cb_root, &e->e_nname, &last );
if ( ce ) {
- if (( op && op->o_managedsait ) ||
+ if ( ( op && op->o_managedsait ) ||
( ce->ce_type != Cft_Database && ce->ce_type != Cft_Overlay &&
- ce->ce_type != Cft_Module ))
- return LDAP_ALREADY_EXISTS;
+ ce->ce_type != Cft_Module ) )
+ {
+ Debug( LDAP_DEBUG_TRACE, "%s: config_add_internal: "
+ "DN=\"%s\" already exists\n",
+ log_prefix, e->e_name.bv_val, 0 );
+ return LDAP_ALREADY_EXISTS;
+ }
}
dnParent( &e->e_nname, &pdn );
/* If last is NULL, the new entry is the root/suffix entry,
* otherwise last should be the parent.
*/
- if ( last && !dn_match( &last->ce_entry->e_nname, &pdn )) {
- if ( rs )
+ if ( last && !dn_match( &last->ce_entry->e_nname, &pdn ) ) {
+ if ( rs ) {
rs->sr_matched = last->ce_entry->e_name.bv_val;
+ }
+ Debug( LDAP_DEBUG_TRACE, "%s: config_add_internal: "
+ "DN=\"%s\" not child of DN=\"%s\"\n",
+ log_prefix, e->e_name.bv_val,
+ last->ce_entry->e_name.bv_val );
return LDAP_NO_SUCH_OBJECT;
}
if ( op ) {
/* No parent, must be root. This will never happen... */
- if ( !last && !be_isroot( op ) && !be_shadow_update( op ))
+ if ( !last && !be_isroot( op ) && !be_shadow_update( op ) ) {
return LDAP_NO_SUCH_OBJECT;
+ }
+
if ( last && !access_allowed( op, last->ce_entry,
- slap_schema.si_ad_children, NULL, ACL_WADD, NULL ))
+ slap_schema.si_ad_children, NULL, ACL_WADD, NULL ) )
+ {
+ Debug( LDAP_DEBUG_TRACE, "%s: config_add_internal: "
+ "DN=\"%s\" no write access to \"children\" of parent\n",
+ log_prefix, e->e_name.bv_val, 0 );
return LDAP_INSUFFICIENT_ACCESS;
+ }
}
oc_at = attr_find( e->e_attrs, slap_schema.si_ad_objectClass );
- if ( !oc_at ) return LDAP_OBJECT_CLASS_VIOLATION;
+ if ( !oc_at ) {
+ Debug( LDAP_DEBUG_TRACE, "%s: config_add_internal: "
+ "DN=\"%s\" no objectClass\n",
+ log_prefix, e->e_name.bv_val, 0 );
+ return LDAP_OBJECT_CLASS_VIOLATION;
+ }
+
+ soc_at = attr_find( e->e_attrs, slap_schema.si_ad_structuralObjectClass );
+ if ( !soc_at ) {
+ ObjectClass *soc = NULL;
+ char textbuf[ SLAP_TEXT_BUFLEN ];
+ const char *text = textbuf;
+
+ /* FIXME: check result */
+ rc = structural_class( oc_at->a_nvals, &soc, NULL,
+ &text, textbuf, sizeof(textbuf), NULL );
+ if ( rc != LDAP_SUCCESS ) {
+ Debug( LDAP_DEBUG_TRACE, "%s: config_add_internal: "
+ "DN=\"%s\" no structural objectClass (%s)\n",
+ log_prefix, e->e_name.bv_val, text );
+ return rc;
+ }
+ attr_merge_one( e, slap_schema.si_ad_structuralObjectClass, &soc->soc_cname, NULL );
+ soc_at = attr_find( e->e_attrs, slap_schema.si_ad_structuralObjectClass );
+ if ( soc_at == NULL ) {
+ Debug( LDAP_DEBUG_TRACE, "%s: config_add_internal: "
+ "DN=\"%s\" no structural objectClass; "
+ "unable to merge computed class %s\n",
+ log_prefix, e->e_name.bv_val,
+ soc->soc_cname.bv_val );
+ return LDAP_OBJECT_CLASS_VIOLATION;
+ }
+
+ Debug( LDAP_DEBUG_TRACE, "%s: config_add_internal: "
+ "DN=\"%s\" no structural objectClass; "
+ "computed objectClass %s merged\n",
+ log_prefix, e->e_name.bv_val,
+ soc->soc_cname.bv_val );
+ }
/* Fake the coordinates based on whether we're part of an
* LDAP Add or if reading the config dir
}
ca->ca_op = op;
- colst = count_ocs( oc_at, &nocs );
+ co.co_name = &soc_at->a_nvals[0];
+ coptr = avl_find( CfOcTree, &co, CfOc_cmp );
+ if ( coptr == NULL ) {
+ Debug( LDAP_DEBUG_TRACE, "%s: config_add_internal: "
+ "DN=\"%s\" no structural objectClass in configuration table\n",
+ log_prefix, e->e_name.bv_val, 0 );
+ return LDAP_OBJECT_CLASS_VIOLATION;
+ }
/* Only the root can be Cft_Global, everything else must
* have a parent. Only limited nesting arrangements are allowed.
*/
rc = LDAP_CONSTRAINT_VIOLATION;
- if ( colst[0]->co_type == Cft_Global && !last ) {
+ if ( coptr->co_type == Cft_Global && !last ) {
cfn = cfb->cb_config;
ca->private = cfn;
ca->be = frontendDB; /* just to get past check_vals */
* any necessary arg setup
*/
if ( last ) {
- for ( i=0; i<nocs; i++ ) {
- if ( colst[i]->co_ldadd &&
- ( rc = colst[i]->co_ldadd( last, e, ca ))
- != LDAP_CONSTRAINT_VIOLATION ) {
- break;
- }
+ rc = config_add_oc( &coptr, last, e, ca );
+ if ( rc == LDAP_CONSTRAINT_VIOLATION ) {
+ Debug( LDAP_DEBUG_TRACE, "%s: config_add_internal: "
+ "DN=\"%s\" no structural objectClass add function\n",
+ log_prefix, e->e_name.bv_val, 0 );
+ return LDAP_OBJECT_CLASS_VIOLATION;
}
}
+ colst = count_ocs( oc_at, &nocs );
+
/* Add the entry but don't parse it, we already have its contents */
if ( rc == LDAP_COMPARE_TRUE ) {
rc = LDAP_SUCCESS;
* but only the other types support auto-renumbering of siblings.
*/
{
- rc = check_name_index( last, colst[0]->co_type, e, rs, renum,
+ rc = check_name_index( last, coptr->co_type, e, rs, renum,
&ibase );
if ( rc ) {
goto done_noop;
}
- if ( renum && *renum && colst[0]->co_type != Cft_Database &&
- colst[0]->co_type != Cft_Overlay ) {
- snprintf( ca->msg, sizeof( ca->msg ),
+ if ( renum && *renum && coptr->co_type != Cft_Database &&
+ coptr->co_type != Cft_Overlay )
+ {
+ snprintf( ca->cr_msg, sizeof( ca->cr_msg ),
"operation requires sibling renumbering" );
rc = LDAP_UNWILLING_TO_PERFORM;
goto done_noop;
/* Make sure we process attrs in the required order */
sort_attrs( e, colst, nocs );
- for ( a=e->e_attrs; a; a=a->a_next ) {
+ for ( a = e->e_attrs; a; a = a->a_next ) {
if ( a == oc_at ) continue;
- ct = config_find_table( colst, nocs, a->a_desc );
+ ct = config_find_table( colst, nocs, a->a_desc, ca );
if ( !ct ) continue; /* user data? */
rc = check_vals( ct, ca, a, 1 );
if ( rc ) goto done_noop;
/* Basic syntax checks are OK. Do the actual settings. */
for ( a=e->e_attrs; a; a=a->a_next ) {
if ( a == oc_at ) continue;
- ct = config_find_table( colst, nocs, a->a_desc );
+ ct = config_find_table( colst, nocs, a->a_desc, ca );
if ( !ct ) continue; /* user data? */
for (i=0; a->a_vals[i].bv_val; i++) {
char *iptr = NULL;
/* Newly added databases and overlays need to be started up */
if ( CONFIG_ONLINE_ADD( ca )) {
if ( colst[0]->co_type == Cft_Database ) {
- rc = backend_startup_one( ca->be );
+ rc = backend_startup_one( ca->be, &ca->reply );
} else if ( colst[0]->co_type == Cft_Overlay ) {
if ( ca->bi->bi_db_open ) {
BackendInfo *bi_orig = ca->be->bd_info;
ca->be->bd_info = ca->bi;
- rc = ca->bi->bi_db_open( ca->be );
+ rc = ca->bi->bi_db_open( ca->be, &ca->reply );
ca->be->bd_info = bi_orig;
}
}
if ( rc ) {
- snprintf( ca->msg, sizeof( ca->msg ), "<%s> failed startup", ca->argv[0] );
+ if (ca->cr_msg[0] == '\0')
+ snprintf( ca->cr_msg, sizeof( ca->cr_msg ), "<%s> failed startup", ca->argv[0] );
+
Debug(LDAP_DEBUG_ANY, "%s: %s (%s)!\n",
- ca->log, ca->msg, ca->argv[1] );
+ ca->log, ca->cr_msg, ca->argv[1] );
rc = LDAP_OTHER;
goto done;
}
*/
rs->sr_err = config_add_internal( cfb, op->ora_e, &ca, rs, &renumber, op );
if ( rs->sr_err != LDAP_SUCCESS ) {
- rs->sr_text = ca.msg;
+ rs->sr_text = ca.cr_msg;
goto out2;
}
strcpy( ca->log, "back-config" );
for (ml = op->orm_modlist; ml; ml=ml->sml_next) {
- ct = config_find_table( colst, nocs, ml->sml_desc );
+ ct = config_find_table( colst, nocs, ml->sml_desc, ca );
switch (ml->sml_op) {
case LDAP_MOD_DELETE:
case LDAP_MOD_REPLACE: {
int *idx = NULL;
if ( ct && ( ct->arg_type & ARG_NO_DELETE )) {
rc = LDAP_OTHER;
- snprintf(ca->msg, sizeof(ca->msg), "cannot delete %s",
+ snprintf(ca->cr_msg, sizeof(ca->cr_msg), "cannot delete %s",
ml->sml_desc->ad_cname.bv_val );
goto out_noop;
}
}
rc = modify_delete_vindex(e, &ml->sml_mod,
get_permissiveModify(op),
- &rs->sr_text, ca->msg, sizeof(ca->msg), idx );
+ &rs->sr_text, ca->cr_msg, sizeof(ca->cr_msg), idx );
if ( ml->sml_op == LDAP_MOD_REPLACE ) {
ml->sml_values = vals;
ml->sml_nvalues = nvals;
j = strtol( val, &next, 0 );
if ( next == val || next[ 0 ] != '}' || j < navals ) {
rc = LDAP_OTHER;
- snprintf(ca->msg, sizeof(ca->msg), "cannot insert %s",
+ snprintf(ca->cr_msg, sizeof(ca->cr_msg), "cannot insert %s",
ml->sml_desc->ad_cname.bv_val );
goto out_noop;
}
}
rc = modify_add_values(e, &ml->sml_mod,
get_permissiveModify(op),
- &rs->sr_text, ca->msg, sizeof(ca->msg) );
+ &rs->sr_text, ca->cr_msg, sizeof(ca->cr_msg) );
/* If value already exists, show success here
* and ignore this operation down below.
if ( rc == LDAP_SUCCESS) {
/* check that the entry still obeys the schema */
rc = entry_schema_check(op, e, NULL, 0, 0,
- &rs->sr_text, ca->msg, sizeof(ca->msg) );
+ &rs->sr_text, ca->cr_msg, sizeof(ca->cr_msg) );
if ( rc ) goto out_noop;
}
/* Basic syntax checks are OK. Do the actual settings. */
for ( ml = op->orm_modlist; ml; ml = ml->sml_next ) {
- ct = config_find_table( colst, nocs, ml->sml_desc );
+ ct = config_find_table( colst, nocs, ml->sml_desc, ca );
if ( !ct ) continue;
s = attr_find( save_attrs, ml->sml_desc );
for ( s = save_attrs; s; s = s->a_next ) {
if ( s->a_flags & SLAP_ATTR_IXDEL ) {
s->a_flags &= ~(SLAP_ATTR_IXDEL|SLAP_ATTR_IXADD);
- ct = config_find_table( colst, nocs, s->a_desc );
+ ct = config_find_table( colst, nocs, s->a_desc, ca );
a = attr_find( e->e_attrs, s->a_desc );
if ( a ) {
/* clear the flag so the add check below will skip it */
}
for ( a = e->e_attrs; a; a = a->a_next ) {
if ( a->a_flags & SLAP_ATTR_IXADD ) {
- ct = config_find_table( colst, nocs, a->a_desc );
+ ct = config_find_table( colst, nocs, a->a_desc, ca );
ca->valx = -1;
ca->line = NULL;
config_del_vals( ct, ca );
*/
rs->sr_err = config_modify_internal( ce, op, rs, &ca );
if ( rs->sr_err ) {
- rs->sr_text = ca.msg;
+ rs->sr_text = ca.cr_msg;
} else if ( cfb->cb_use_ldif ) {
BackendDB *be = op->o_bd;
slap_callback sc = { NULL, slap_null_cb, NULL, NULL }, *scp;
attr_merge_normalize_one(e, ad, &val, NULL );
oc = main->co_oc;
+ c->table = main->co_type;
if ( oc->soc_required )
config_build_attrs( e, oc->soc_required, ad, main->co_table, c );
if ( extra ) {
oc = extra->co_oc;
+ c->table = extra->co_type;
if ( oc->soc_required )
config_build_attrs( e, oc->soc_required, ad, extra->co_table, c );
}
oc_at = attr_find( e->e_attrs, slap_schema.si_ad_objectClass );
- rc = structural_class(oc_at->a_vals, &oc, NULL, &text, c->msg,
- sizeof(c->msg), op ? op->o_tmpmemctx : NULL );
+ rc = structural_class(oc_at->a_vals, &oc, NULL, &text, c->cr_msg,
+ sizeof(c->cr_msg), op ? op->o_tmpmemctx : NULL );
attr_merge_normalize_one(e, slap_schema.si_ad_structuralObjectClass, &oc->soc_cname, NULL );
if ( op && !op->o_noop ) {
op->ora_e = e;
struct berval bv;
for (; cf; cf=cf->c_sibs, c->depth++) {
+ if ( !cf->c_at_head && !cf->c_cr_head && !cf->c_oc_head &&
+ !cf->c_om_head ) continue;
c->value_dn.bv_val = c->log;
+ LUTIL_SLASHPATH( cf->c_file.bv_val );
bv.bv_val = strrchr(cf->c_file.bv_val, LDAP_DIRSEP[0]);
if ( !bv.bv_val ) {
bv = cf->c_file;
};
static int
-config_back_db_open( BackendDB *be )
+config_back_db_open( BackendDB *be, ConfigReply *cr )
{
CfBackInfo *cfb = be->be_private;
struct berval rdn;
}
thrctx = ldap_pvt_thread_pool_context();
- op = (Operation *) &opbuf;
- connection_fake_init( &conn, op, thrctx );
+ connection_fake_init( &conn, &opbuf, thrctx );
+ op = &opbuf.ob_op;
op->o_tag = LDAP_REQ_ADD;
op->o_callback = &cb;
}
static int
-config_back_db_close( BackendDB *be )
+config_back_db_close( BackendDB *be, ConfigReply *cr )
{
CfBackInfo *cfb = be->be_private;
}
static int
-config_back_db_destroy( BackendDB *be )
+config_back_db_destroy( BackendDB *be, ConfigReply *cr )
{
CfBackInfo *cfb = be->be_private;
}
static int
-config_back_db_init( BackendDB *be )
+config_back_db_init( BackendDB *be, ConfigReply* cr )
{
struct berval dn;
CfBackInfo *cfb;
return NULL;
}
+static int entry_put_got_frontend=0;
+static int entry_put_got_config=0;
static ID
config_tool_entry_put( BackendDB *be, Entry *e, struct berval *text )
{
CfBackInfo *cfb = be->be_private;
BackendInfo *bi = cfb->cb_db.bd_info;
+ int rc;
+ struct berval rdn, vals[ 2 ];
ConfigArgs ca;
+ OperationBuffer opbuf;
+ Entry *ce;
+ Connection conn = {0};
+ Operation *op = NULL;
+ void *thrctx;
+
+ /* Create entry for frontend database if it does not exist already */
+ if ( !entry_put_got_frontend ) {
+ if ( !strncmp( e->e_nname.bv_val, "olcDatabase",
+ STRLENOF( "olcDatabase" ))) {
+ if ( strncmp( e->e_nname.bv_val +
+ STRLENOF( "olcDatabase" ), "={-1}frontend",
+ STRLENOF( "={-1}frontend" )) &&
+ strncmp( e->e_nname.bv_val +
+ STRLENOF( "olcDatabase" ), "=frontend",
+ STRLENOF( "=frontend" ))) {
+ vals[1].bv_len = 0;
+ vals[1].bv_val = NULL;
+ memset( &ca, 0, sizeof(ConfigArgs));
+ ca.be = frontendDB;
+ ca.bi = frontendDB->bd_info;
+ ca.be->be_cf_ocs = &CFOC_FRONTEND;
+ rdn.bv_val = ca.log;
+ rdn.bv_len = snprintf(rdn.bv_val, sizeof( ca.log ),
+ "%s=" SLAP_X_ORDERED_FMT "%s",
+ cfAd_database->ad_cname.bv_val, -1,
+ ca.bi->bi_type);
+ ce = config_build_entry( NULL, NULL, cfb->cb_root, &ca, &rdn,
+ &CFOC_DATABASE, ca.be->be_cf_ocs );
+ thrctx = ldap_pvt_thread_pool_context();
+ connection_fake_init2( &conn, &opbuf, thrctx,0 );
+ op = &opbuf.ob_op;
+ op->o_bd = &cfb->cb_db;
+ op->o_tag = LDAP_REQ_ADD;
+ op->ora_e = ce;
+ op->o_dn = be->be_rootdn;
+ op->o_ndn = be->be_rootndn;
+ rc = slap_add_opattrs(op, NULL, NULL, 0, 0);
+ if ( rc != LDAP_SUCCESS ) {
+ text->bv_val = "autocreation of \"olcDatabase={-1}frontend\" failed";
+ text->bv_len = STRLENOF("autocreation of \"olcDatabase={-1}frontend\" failed");
+ return NOID;
+ }
+ if ( ce && bi && bi->bi_tool_entry_put &&
+ bi->bi_tool_entry_put( &cfb->cb_db, ce, text ) != NOID ) {
+ entry_put_got_frontend++;
+ } else {
+ text->bv_val = "autocreation of \"olcDatabase={-1}frontend\" failed";
+ text->bv_len = STRLENOF("autocreation of \"olcDatabase={-1}frontend\" failed");
+ return NOID;
+ }
+ } else {
+ entry_put_got_frontend++;
+ }
+ }
+ }
+ /* Create entry for config database if it does not exist already */
+ if ( !entry_put_got_config ) {
+ if ( !strncmp( e->e_nname.bv_val, "olcDatabase",
+ STRLENOF( "olcDatabase" ))) {
+ if ( strncmp( e->e_nname.bv_val +
+ STRLENOF( "olcDatabase" ), "={0}config",
+ STRLENOF( "={0}config" )) &&
+ strncmp( e->e_nname.bv_val +
+ STRLENOF( "olcDatabase" ), "=config",
+ STRLENOF( "=config" )) ) {
+ vals[1].bv_len = 0;
+ vals[1].bv_val = NULL;
+ memset( &ca, 0, sizeof(ConfigArgs));
+ ca.be = LDAP_STAILQ_FIRST( &backendDB );
+ ca.bi = ca.be->bd_info;
+ rdn.bv_val = ca.log;
+ rdn.bv_len = snprintf(rdn.bv_val, sizeof( ca.log ),
+ "%s=" SLAP_X_ORDERED_FMT "%s",
+ cfAd_database->ad_cname.bv_val, 0,
+ ca.bi->bi_type);
+ ce = config_build_entry( NULL, NULL, cfb->cb_root, &ca, &rdn, &CFOC_DATABASE,
+ ca.be->be_cf_ocs );
+ if ( ! op ) {
+ thrctx = ldap_pvt_thread_pool_context();
+ connection_fake_init2( &conn, &opbuf, thrctx,0 );
+ op = &opbuf.ob_op;
+ op->o_bd = &cfb->cb_db;
+ op->o_tag = LDAP_REQ_ADD;
+ op->o_dn = be->be_rootdn;
+ op->o_ndn = be->be_rootndn;
+ }
+ op->ora_e = ce;
+ rc = slap_add_opattrs(op, NULL, NULL, 0, 0);
+ if ( rc != LDAP_SUCCESS ) {
+ text->bv_val = "autocreation of \"olcDatabase={0}config\" failed";
+ text->bv_len = STRLENOF("autocreation of \"olcDatabase={0}config\" failed");
+ return NOID;
+ }
+ if (ce && bi && bi->bi_tool_entry_put &&
+ bi->bi_tool_entry_put( &cfb->cb_db, ce, text ) != NOID ) {
+ entry_put_got_config++;
+ } else {
+ text->bv_val = "autocreation of \"olcDatabase={0}config\" failed";
+ text->bv_len = STRLENOF("autocreation of \"olcDatabase={0}config\" failed");
+ return NOID;
+ }
+ } else {
+ entry_put_got_config++;
+ }
+ }
+ }
if ( bi && bi->bi_tool_entry_put &&
config_add_internal( cfb, e, &ca, NULL, NULL, NULL ) == 0 )
return bi->bi_tool_entry_put( &cfb->cb_db, e, text );
ber_tag_t tag;
Backend *be = NULL;
- Debug( LDAP_DEBUG_TRACE, "do_bind\n", 0, 0, 0 );
+ Debug( LDAP_DEBUG_TRACE, "%s do_bind\n",
+ op->o_log_prefix, 0, 0 );
/*
- * Force to connection to "anonymous" until bind succeeds.
+ * Force the connection to "anonymous" until bind succeeds.
*/
ldap_pvt_thread_mutex_lock( &op->o_conn->c_mutex );
if ( op->o_conn->c_sasl_bind_in_progress ) {
tag = ber_scanf( ber, "{imt" /*}*/, &version, &dn, &method );
if ( tag == LBER_ERROR ) {
- Debug( LDAP_DEBUG_ANY, "bind: ber_scanf failed\n", 0, 0, 0 );
+ Debug( LDAP_DEBUG_ANY, "%s do_bind: ber_scanf failed\n",
+ op->o_log_prefix, 0, 0 );
send_ldap_discon( op, rs, LDAP_PROTOCOL_ERROR, "decoding error" );
rs->sr_err = SLAPD_DISCONNECT;
goto cleanup;
}
if ( tag == LBER_ERROR ) {
+ Debug( LDAP_DEBUG_ANY, "%s do_bind: ber_scanf failed\n",
+ op->o_log_prefix, 0, 0 );
send_ldap_discon( op, rs, LDAP_PROTOCOL_ERROR, "decoding error" );
rs->sr_err = SLAPD_DISCONNECT;
goto cleanup;
}
if( get_ctrls( op, rs, 1 ) != LDAP_SUCCESS ) {
- Debug( LDAP_DEBUG_ANY, "do_bind: get_ctrls failed\n", 0, 0, 0 );
+ Debug( LDAP_DEBUG_ANY, "%s do_bind: get_ctrls failed\n",
+ op->o_log_prefix, 0, 0 );
goto cleanup;
}
rs->sr_err = dnPrettyNormal( NULL, &dn, &op->o_req_dn, &op->o_req_ndn,
op->o_tmpmemctx );
if ( rs->sr_err != LDAP_SUCCESS ) {
- Debug( LDAP_DEBUG_ANY, "bind: invalid dn (%s)\n",
- dn.bv_val, 0, 0 );
+ Debug( LDAP_DEBUG_ANY, "%s do_bind: invalid dn (%s)\n",
+ op->o_log_prefix, dn.bv_val, 0 );
send_ldap_error( op, rs, LDAP_INVALID_DN_SYNTAX, "invalid DN" );
goto cleanup;
}
+ Statslog( LDAP_DEBUG_STATS, "%s BIND dn=\"%s\" method=%ld\n",
+ op->o_log_prefix, op->o_req_dn.bv_val,
+ (unsigned long) op->orb_method, 0, 0 );
+
if( op->orb_method == LDAP_AUTH_SASL ) {
- Debug( LDAP_DEBUG_TRACE, "do_sasl_bind: dn (%s) mech %s\n",
+ Debug( LDAP_DEBUG_TRACE, "do_bind: dn (%s) SASL mech %s\n",
op->o_req_dn.bv_val, mech.bv_val, NULL );
} else {
(unsigned long) op->orb_method );
}
- Statslog( LDAP_DEBUG_STATS, "%s BIND dn=\"%s\" method=%ld\n",
- op->o_log_prefix, op->o_req_dn.bv_val,
- (unsigned long) op->orb_method, 0, 0 );
-
if ( version < LDAP_VERSION_MIN || version > LDAP_VERSION_MAX ) {
- Debug( LDAP_DEBUG_ANY, "do_bind: unknown version=%ld\n",
- (unsigned long) version, 0, 0 );
+ Debug( LDAP_DEBUG_ANY, "%s do_bind: unknown version=%ld\n",
+ op->o_log_prefix, (unsigned long) version, 0 );
send_ldap_error( op, rs, LDAP_PROTOCOL_ERROR,
"requested protocol version not supported" );
goto cleanup;
op->o_conn->c_protocol = version;
ldap_pvt_thread_mutex_unlock( &op->o_conn->c_mutex );
- op->orb_tmp_mech = mech;
+ op->orb_mech = mech;
op->o_bd = frontendDB;
rs->sr_err = frontendDB->be_bind( op, rs );
goto cleanup;
}
- if( BER_BVISNULL( &op->orb_tmp_mech ) || BER_BVISEMPTY( &op->orb_tmp_mech ) ) {
+ if( BER_BVISNULL( &op->orb_mech ) || BER_BVISEMPTY( &op->orb_mech ) ) {
Debug( LDAP_DEBUG_ANY,
"do_bind: no sasl mechanism provided\n",
0, 0, 0 );
}
/* check restrictions */
- if( backend_check_restrictions( op, rs, &op->orb_tmp_mech ) != LDAP_SUCCESS ) {
+ if( backend_check_restrictions( op, rs, &op->orb_mech ) != LDAP_SUCCESS ) {
send_ldap_result( op, rs );
goto cleanup;
}
ldap_pvt_thread_mutex_lock( &op->o_conn->c_mutex );
if ( op->o_conn->c_sasl_bind_in_progress ) {
- if( !bvmatch( &op->o_conn->c_sasl_bind_mech, &op->orb_tmp_mech ) ) {
+ if( !bvmatch( &op->o_conn->c_sasl_bind_mech, &op->orb_mech ) ) {
/* mechanism changed between bind steps */
slap_sasl_reset(op->o_conn);
}
} else {
- ber_dupbv(&op->o_conn->c_sasl_bind_mech, &op->orb_tmp_mech);
+ ber_dupbv(&op->o_conn->c_sasl_bind_mech, &op->orb_mech);
}
/* Set the bindop for the benefit of in-directory SASL lookups */
}
if ( op->orb_method == LDAP_AUTH_SIMPLE ) {
- BER_BVSTR( &op->orb_tmp_mech, "SIMPLE" );
+ BER_BVSTR( &op->orb_mech, "SIMPLE" );
/* accept "anonymous" binds */
if ( BER_BVISEMPTY( &op->orb_cred ) || BER_BVISEMPTY( &op->o_req_ndn ) ) {
rs->sr_err = LDAP_SUCCESS;
rs->sr_text = "anonymous bind disallowed";
} else {
- backend_check_restrictions( op, rs, &op->orb_tmp_mech );
+ backend_check_restrictions( op, rs, &op->orb_mech );
}
/*
* if we don't hold it.
*/
- if ( (op->o_bd = select_backend( &op->o_req_ndn, 0, 0 )) == NULL ) {
+ if ( (op->o_bd = select_backend( &op->o_req_ndn, 0 )) == NULL ) {
/* don't return referral for bind requests */
/* noSuchObject is not allowed to be returned by bind */
rs->sr_err = LDAP_INVALID_CREDENTIALS;
Statslog( LDAP_DEBUG_STATS,
"%s BIND dn=\"%s\" mech=%s ssf=0\n",
op->o_log_prefix,
- op->o_conn->c_dn.bv_val, op->orb_tmp_mech.bv_val, 0, 0 );
+ op->o_conn->c_dn.bv_val, op->orb_mech.bv_val, 0, 0 );
Debug( LDAP_DEBUG_TRACE,
"do_bind: v%d bind: \"%s\" to \"%s\"\n",
(void) ber_free( ber, 1 );
+ Statslog( LDAP_DEBUG_STATS, "%s CANCEL msg=%d\n",
+ op->o_log_prefix, opid, 0, 0, 0 );
+
if ( opid < 0 ) {
rs->sr_text = "message ID invalid";
return LDAP_PROTOCOL_ERROR;
}
- Statslog( LDAP_DEBUG_STATS, "%s CANCEL msg=%d\n",
- op->o_log_prefix, opid, 0, 0, 0 );
-
ldap_pvt_thread_mutex_lock( &op->o_conn->c_mutex );
LDAP_STAILQ_FOREACH( o, &op->o_conn->c_pending_ops, o_next ) {
if ( o->o_msgid == opid ) {
- LDAP_STAILQ_REMOVE( &op->o_conn->c_pending_ops, o, slap_op, o_next );
+ LDAP_STAILQ_REMOVE( &op->o_conn->c_pending_ops, o, Operation, o_next );
LDAP_STAILQ_NEXT(o, o_next) = NULL;
op->o_conn->c_n_ops_pending--;
slap_op_free( o );
struct berval dn = BER_BVNULL;
struct berval desc = BER_BVNULL;
struct berval value = BER_BVNULL;
-#ifdef LDAP_COMP_MATCH
- AttributeAssertion ava = { NULL, BER_BVNULL, NULL };
-#else
- AttributeAssertion ava = { NULL, BER_BVNULL };
-#endif
+ AttributeAssertion ava = { 0 };
- ava.aa_desc = NULL;
-
- Debug( LDAP_DEBUG_TRACE, "do_compare\n", 0, 0, 0 );
+ Debug( LDAP_DEBUG_TRACE, "%s do_compare\n",
+ op->o_log_prefix, 0, 0 );
/*
* Parse the compare request. It looks like this:
*
*/
if ( ber_scanf( op->o_ber, "{m" /*}*/, &dn ) == LBER_ERROR ) {
- Debug( LDAP_DEBUG_ANY, "ber_scanf failed\n", 0, 0, 0 );
+ Debug( LDAP_DEBUG_ANY, "%s do_compare: ber_scanf failed\n",
+ op->o_log_prefix, 0, 0 );
send_ldap_discon( op, rs, LDAP_PROTOCOL_ERROR, "decoding error" );
return SLAPD_DISCONNECT;
}
if ( ber_scanf( op->o_ber, "{mm}", &desc, &value ) == LBER_ERROR ) {
- Debug( LDAP_DEBUG_ANY, "do_compare: get ava failed\n", 0, 0, 0 );
+ Debug( LDAP_DEBUG_ANY, "%s do_compare: get ava failed\n",
+ op->o_log_prefix, 0, 0 );
send_ldap_discon( op, rs, LDAP_PROTOCOL_ERROR, "decoding error" );
return SLAPD_DISCONNECT;
}
if ( ber_scanf( op->o_ber, /*{*/ "}" ) == LBER_ERROR ) {
- Debug( LDAP_DEBUG_ANY, "ber_scanf failed\n", 0, 0, 0 );
+ Debug( LDAP_DEBUG_ANY, "%s do_compare: ber_scanf failed\n",
+ op->o_log_prefix, 0, 0 );
send_ldap_discon( op, rs, LDAP_PROTOCOL_ERROR, "decoding error" );
return SLAPD_DISCONNECT;
}
if( get_ctrls( op, rs, 1 ) != LDAP_SUCCESS ) {
- Debug( LDAP_DEBUG_ANY, "do_compare: get_ctrls failed\n", 0, 0, 0 );
+ Debug( LDAP_DEBUG_ANY, "%s do_compare: get_ctrls failed\n",
+ op->o_log_prefix, 0, 0 );
goto cleanup;
}
rs->sr_err = dnPrettyNormal( NULL, &dn, &op->o_req_dn, &op->o_req_ndn,
op->o_tmpmemctx );
if( rs->sr_err != LDAP_SUCCESS ) {
- Debug( LDAP_DEBUG_ANY,
- "do_compare: invalid dn (%s)\n", dn.bv_val, 0, 0 );
+ Debug( LDAP_DEBUG_ANY, "%s do_compare: invalid dn (%s)\n",
+ op->o_log_prefix, dn.bv_val, 0 );
send_ldap_error( op, rs, LDAP_INVALID_DN_SYNTAX, "invalid DN" );
goto cleanup;
}
+ Statslog( LDAP_DEBUG_STATS,
+ "%s CMP dn=\"%s\" attr=\"%s\"\n",
+ op->o_log_prefix, op->o_req_dn.bv_val,
+ desc.bv_val, 0, 0 );
+
rs->sr_err = slap_bv2ad( &desc, &ava.aa_desc, &rs->sr_text );
if( rs->sr_err != LDAP_SUCCESS ) {
rs->sr_err = slap_bv2undef_ad( &desc, &ava.aa_desc,
op->orc_ava = &ava;
+ Debug( LDAP_DEBUG_ARGS,
+ "do_compare: dn (%s) attr (%s) value (%s)\n",
+ op->o_req_dn.bv_val,
+ ava.aa_desc->ad_cname.bv_val, ava.aa_value.bv_val );
+
op->o_bd = frontendDB;
rs->sr_err = frontendDB->be_compare( op, rs );
fe_op_compare( Operation *op, SlapReply *rs )
{
Entry *entry = NULL;
- int manageDSAit;
- AttributeAssertion ava = *op->orc_ava;
+ AttributeAssertion *ava = op->orc_ava;
BackendDB *bd = op->o_bd;
if( strcasecmp( op->o_req_ndn.bv_val, LDAP_ROOT_DSE ) == 0 ) {
- Debug( LDAP_DEBUG_ARGS,
- "do_compare: dn (%s) attr (%s) value (%s)\n",
- op->o_req_dn.bv_val,
- ava.aa_desc->ad_cname.bv_val, ava.aa_value.bv_val );
-
- Statslog( LDAP_DEBUG_STATS,
- "%s CMP dn=\"%s\" attr=\"%s\"\n",
- op->o_log_prefix, op->o_req_dn.bv_val,
- ava.aa_desc->ad_cname.bv_val, 0, 0 );
-
if( backend_check_restrictions( op, rs, NULL ) != LDAP_SUCCESS ) {
send_ldap_result( op, rs );
goto cleanup;
}
} else if ( bvmatch( &op->o_req_ndn, &frontendDB->be_schemandn ) ) {
- Debug( LDAP_DEBUG_ARGS, "do_compare: dn (%s) attr (%s) value (%s)\n",
- op->o_req_dn.bv_val,
- ava.aa_desc->ad_cname.bv_val, ava.aa_value.bv_val );
-
- Statslog( LDAP_DEBUG_STATS,
- "%s CMP dn=\"%s\" attr=\"%s\"\n",
- op->o_log_prefix, op->o_req_dn.bv_val,
- ava.aa_desc->ad_cname.bv_val, 0, 0 );
-
if( backend_check_restrictions( op, rs, NULL ) != LDAP_SUCCESS ) {
send_ldap_result( op, rs );
rs->sr_err = 0;
}
if( entry ) {
- rs->sr_err = compare_entry( op, entry, &ava );
+ rs->sr_err = compare_entry( op, entry, ava );
entry_free( entry );
send_ldap_result( op, rs );
goto cleanup;
}
- manageDSAit = get_manageDSAit( op );
-
/*
* We could be serving multiple database backends. Select the
* appropriate one, or send a referral to our "referral server"
* if we don't hold it.
*/
- op->o_bd = select_backend( &op->o_req_ndn, manageDSAit, 0 );
+ op->o_bd = select_backend( &op->o_req_ndn, 0 );
if ( op->o_bd == NULL ) {
rs->sr_ref = referral_rewrite( default_referral,
NULL, &op->o_req_dn, LDAP_SCOPE_DEFAULT );
goto cleanup;
}
- Debug( LDAP_DEBUG_ARGS, "do_compare: dn (%s) attr (%s) value (%s)\n",
- op->o_req_dn.bv_val,
- ava.aa_desc->ad_cname.bv_val, ava.aa_value.bv_val );
-
- Statslog( LDAP_DEBUG_STATS, "%s CMP dn=\"%s\" attr=\"%s\"\n",
- op->o_log_prefix, op->o_req_dn.bv_val,
- ava.aa_desc->ad_cname.bv_val, 0, 0 );
-
- op->orc_ava = &ava;
-
if ( SLAP_SHADOW(op->o_bd) && get_dontUseCopy(op) ) {
/* don't use shadow copy */
send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
"copy not used" );
- } else if ( ava.aa_desc == slap_schema.si_ad_entryDN ) {
+ } else if ( ava->aa_desc == slap_schema.si_ad_entryDN ) {
send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
"entryDN compare not supported" );
- } else if ( ava.aa_desc == slap_schema.si_ad_subschemaSubentry ) {
+ } else if ( ava->aa_desc == slap_schema.si_ad_subschemaSubentry ) {
send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
"subschemaSubentry compare not supported" );
#ifndef SLAP_COMPARE_IN_FRONTEND
- } else if ( ava.aa_desc == slap_schema.si_ad_hasSubordinates
+ } else if ( ava->aa_desc == slap_schema.si_ad_hasSubordinates
&& op->o_bd->be_has_subordinates )
{
int rc, hasSubordinates = LDAP_SUCCESS;
rc = be_entry_get_rw( op, &op->o_req_ndn, NULL, NULL, 0, &entry );
if ( rc == 0 && entry ) {
if ( ! access_allowed( op, entry,
- ava.aa_desc, &ava.aa_value, ACL_COMPARE, NULL ) )
+ ava->aa_desc, &ava->aa_value, ACL_COMPARE, NULL ) )
{
rc = rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
if ( rc == 0 ) {
int asserted;
- asserted = bvmatch( &ava.aa_value, &slap_true_bv )
+ asserted = bvmatch( &ava->aa_value, &slap_true_bv )
? LDAP_COMPARE_TRUE : LDAP_COMPARE_FALSE;
if ( hasSubordinates == asserted ) {
rs->sr_err = LDAP_COMPARE_TRUE;
int rc = LDAP_OTHER;
rs->sr_err = backend_attribute( op, NULL, &op->o_req_ndn,
- ava.aa_desc, &vals, ACL_COMPARE );
+ ava->aa_desc, &vals, ACL_COMPARE );
switch ( rs->sr_err ) {
default:
/* return error only if "disclose"
if ( value_find_ex( op->oq_compare.rs_ava->aa_desc,
SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH |
SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH,
- vals, &ava.aa_value, op->o_tmpmemctx ) == 0 )
+ vals, &ava->aa_value, op->o_tmpmemctx ) == 0 )
{
rs->sr_err = LDAP_COMPARE_TRUE;
break;
#define S_ISREG(m) (((m) & _S_IFMT) == _S_IFREG)
#endif
-#if HAVE_UNISTD_H
+#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include "lutil_ldap.h"
#include "config.h"
-#ifdef HAVE_TLS
-#include <openssl/ssl.h>
-#endif
-
#define ARGS_STEP 512
/*
c->argv[1] = "";
}
if(Conf->min_args && (c->argc < Conf->min_args)) {
- snprintf( c->msg, sizeof( c->msg ), "<%s> missing <%s> argument",
+ snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> missing <%s> argument",
c->argv[0], Conf->what );
- Debug(LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, "%s: keyword %s\n", c->log, c->msg, 0 );
+ Debug(LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, "%s: keyword %s\n", c->log, c->cr_msg, 0 );
return(ARG_BAD_CONF);
}
if(Conf->max_args && (c->argc > Conf->max_args)) {
char *ignored = " ignored";
- snprintf( c->msg, sizeof( c->msg ), "<%s> extra cruft after <%s>",
+ snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> extra cruft after <%s>",
c->argv[0], Conf->what );
ignored = "";
Debug(LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, "%s: %s%s.\n",
- c->log, c->msg, ignored );
+ c->log, c->cr_msg, ignored );
return(ARG_BAD_CONF);
}
if((arg_syn & ARG_DB) && !c->be) {
- snprintf( c->msg, sizeof( c->msg ), "<%s> only allowed within database declaration",
+ snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> only allowed within database declaration",
c->argv[0] );
Debug(LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, "%s: keyword %s\n",
- c->log, c->msg, 0);
+ c->log, c->cr_msg, 0);
return(ARG_BAD_CONF);
}
if((arg_syn & ARG_PRE_BI) && c->bi) {
- snprintf( c->msg, sizeof( c->msg ), "<%s> must occur before any backend %sdeclaration",
+ snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> must occur before any backend %sdeclaration",
c->argv[0], (arg_syn & ARG_PRE_DB) ? "or database " : "" );
Debug(LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, "%s: keyword %s\n",
- c->log, c->msg, 0 );
+ c->log, c->cr_msg, 0 );
return(ARG_BAD_CONF);
}
if((arg_syn & ARG_PRE_DB) && c->be && c->be != frontendDB) {
- snprintf( c->msg, sizeof( c->msg ), "<%s> must occur before any database declaration",
+ snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> must occur before any database declaration",
c->argv[0] );
Debug(LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, "%s: keyword %s\n",
- c->log, c->msg, 0);
+ c->log, c->cr_msg, 0);
return(ARG_BAD_CONF);
}
if((arg_syn & ARG_PAREN) && *c->argv[1] != '(' /*')'*/) {
- snprintf( c->msg, sizeof( c->msg ), "<%s> old format not supported", c->argv[0] );
+ snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> old format not supported", c->argv[0] );
Debug(LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, "%s: %s\n",
- c->log, c->msg, 0);
+ c->log, c->cr_msg, 0);
return(ARG_BAD_CONF);
}
if(arg_type && !Conf->arg_item && !(arg_syn & ARG_OFFSET)) {
- snprintf( c->msg, sizeof( c->msg ), "<%s> invalid config_table, arg_item is NULL",
+ snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> invalid config_table, arg_item is NULL",
c->argv[0] );
Debug(LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, "%s: %s\n",
- c->log, c->msg, 0);
+ c->log, c->cr_msg, 0);
return(ARG_BAD_CONF);
}
c->type = arg_user;
ber_str2bv( c->argv[1], 0, 0, &bv );
rc = dnPrettyNormal( NULL, &bv, &c->value_dn, &c->value_ndn, NULL );
if ( rc != LDAP_SUCCESS ) {
- snprintf( c->msg, sizeof( c->msg ), "<%s> invalid DN %d (%s)",
+ snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> invalid DN %d (%s)",
c->argv[0], rc, ldap_err2string( rc ));
- Debug(LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, "%s: %s\n" , c->log, c->msg, 0);
+ Debug(LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, "%s: %s\n" , c->log, c->cr_msg, 0);
return(ARG_BAD_CONF);
}
if ( check_only ) {
switch(arg_type) {
case ARG_INT:
if ( lutil_atoix( &iarg, c->argv[1], 0 ) != 0 ) {
- snprintf( c->msg, sizeof( c->msg ),
+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
"<%s> unable to parse \"%s\" as int",
c->argv[0], c->argv[1] );
Debug(LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, "%s: %s\n",
- c->log, c->msg, 0);
+ c->log, c->cr_msg, 0);
return(ARG_BAD_CONF);
}
break;
case ARG_LONG:
if ( lutil_atolx( &larg, c->argv[1], 0 ) != 0 ) {
- snprintf( c->msg, sizeof( c->msg ),
+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
"<%s> unable to parse \"%s\" as long",
c->argv[0], c->argv[1] );
Debug(LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, "%s: %s\n",
- c->log, c->msg, 0);
+ c->log, c->cr_msg, 0);
return(ARG_BAD_CONF);
}
break;
case ARG_BER_LEN_T: {
unsigned long l;
if ( lutil_atoulx( &l, c->argv[1], 0 ) != 0 ) {
- snprintf( c->msg, sizeof( c->msg ),
+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
"<%s> unable to parse \"%s\" as ber_len_t",
c->argv[0], c->argv[1] );
Debug(LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, "%s: %s\n",
- c->log, c->msg, 0);
+ c->log, c->cr_msg, 0);
return(ARG_BAD_CONF);
}
barg = (ber_len_t)l;
{
iarg = 0;
} else {
- snprintf( c->msg, sizeof( c->msg ), "<%s> invalid value",
+ snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> invalid value",
c->argv[0] );
Debug(LDAP_DEBUG_ANY|LDAP_DEBUG_NONE, "%s: %s\n",
- c->log, c->msg, 0 );
+ c->log, c->cr_msg, 0 );
return(ARG_BAD_CONF);
}
break;
j = (arg_type & ARG_NONZERO) ? 1 : 0;
if(iarg < j && larg < j && barg < j ) {
larg = larg ? larg : (barg ? barg : iarg);
- snprintf( c->msg, sizeof( c->msg ), "<%s> invalid value",
+ snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> invalid value",
c->argv[0] );
Debug(LDAP_DEBUG_ANY|LDAP_DEBUG_NONE, "%s: %s\n",
- c->log, c->msg, 0 );
+ c->log, c->cr_msg, 0 );
return(ARG_BAD_CONF);
}
switch(arg_type) {
arg_type = Conf->arg_type;
if(arg_type & ARG_MAGIC) {
if(!c->be) c->be = frontendDB;
- c->msg[0] = '\0';
+ c->cr_msg[0] = '\0';
rc = (*((ConfigDriver*)Conf->arg_item))(c);
#if 0
if(c->be == frontendDB) c->be = NULL;
#endif
if(rc) {
- if ( !c->msg[0] ) {
- snprintf( c->msg, sizeof( c->msg ), "<%s> handler exited with %d",
+ if ( !c->cr_msg[0] ) {
+ snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> handler exited with %d",
c->argv[0], rc );
Debug(LDAP_DEBUG_CONFIG, "%s: %s!\n",
- c->log, c->msg, 0 );
+ c->log, c->cr_msg, 0 );
}
return(ARG_BAD_CONF);
}
return(0);
}
if(arg_type & ARG_OFFSET) {
- if (c->be && (!overlay_is_over(c->be) ||
- ((slap_overinfo *)c->be->bd_info)->oi_orig == c->bi))
+ if (c->be && c->table == Cft_Database)
ptr = c->be->be_private;
else if (c->bi)
ptr = c->bi->bi_private;
else {
- snprintf( c->msg, sizeof( c->msg ), "<%s> offset is missing base pointer",
+ snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> offset is missing base pointer",
c->argv[0] );
Debug(LDAP_DEBUG_CONFIG, "%s: %s!\n",
- c->log, c->msg, 0);
+ c->log, c->cr_msg, 0);
return(ARG_BAD_CONF);
}
ptr = (void *)((char *)ptr + (long)Conf->arg_item);
if ( rc ) return rc;
} else {
if ( cf->arg_type & ARG_OFFSET ) {
- if (c->be && (!overlay_is_over(c->be) ||
- ((slap_overinfo *)c->be->bd_info)->oi_orig == c->bi))
+ if (c->be && c->table == Cft_Database)
ptr = c->be->be_private;
else if ( c->bi )
ptr = c->bi->bi_private;
ct = config_find_keyword( cft, c );
if ( ct ) {
+ c->table = Cft_Global;
rc = config_add_vals( ct, c );
if ( !rc ) continue;
if ( c->bi->bi_cf_ocs ) {
ct = config_find_keyword( c->bi->bi_cf_ocs->co_table, c );
if ( ct ) {
+ c->table = c->bi->bi_cf_ocs->co_type;
rc = config_add_vals( ct, c );
}
}
if ( c->be->be_cf_ocs ) {
ct = config_find_keyword( c->be->be_cf_ocs->co_table, c );
if ( ct ) {
+ c->table = c->be->be_cf_ocs->co_type;
rc = config_add_vals( ct, c );
}
}
{ BER_BVC("saslmech="), offsetof(slap_bindconf, sb_saslmech), 'b', 0, NULL },
{ BER_BVC("secprops="), offsetof(slap_bindconf, sb_secprops), 's', 0, NULL },
{ BER_BVC("realm="), offsetof(slap_bindconf, sb_realm), 'b', 0, NULL },
- { BER_BVC("authcID="), offsetof(slap_bindconf, sb_authcId), 'b', 0, (slap_verbmasks *)authzNormalize },
+ { BER_BVC("authcID="), offsetof(slap_bindconf, sb_authcId), 'b', 1, NULL },
{ BER_BVC("authzID="), offsetof(slap_bindconf, sb_authzId), 'b', 1, (slap_verbmasks *)authzNormalize },
#ifdef HAVE_TLS
{ BER_BVC("starttls="), offsetof(slap_bindconf, sb_tls), 'i', 0, tlskey },
BER_BVZERO( &bc->sb_authzId );
}
#ifdef HAVE_TLS
-#if 0
- if ( bc->sb_tls_ctx ) {
- SSL_CTX_free( bc->sb_tls_ctx );
- bc->sb_tls_ctx = NULL;
- }
-#endif
if ( bc->sb_tls_cert ) {
ch_free( bc->sb_tls_cert );
bc->sb_tls_cert = NULL;
int opt = 0;
if ( bc->sb_tls_ctx ) {
- SSL_CTX_free( bc->sb_tls_ctx );
+ ldap_pvt_tls_ctx_free( bc->sb_tls_ctx );
bc->sb_tls_ctx = NULL;
}
rc = ldap_set_option( ld, LDAP_OPT_X_TLS_NEWCTX, &opt );
sb->sb_authcId.bv_val,
sb->sb_cred.bv_val,
sb->sb_authzId.bv_val );
+ if ( defaults == NULL ) {
+ rc = LDAP_OTHER;
+ goto done;
+ }
rc = ldap_sasl_interactive_bind_s( ld,
sb->sb_binddn.bv_val,
rc = SLAP_CONF_UNKNOWN;
ct = config_find_keyword( be->be_cf_ocs->co_table, &c );
- if ( ct )
+ if ( ct ) {
+ c.table = be->be_cf_ocs->co_type;
rc = config_add_vals( ct, &c );
+ }
return rc;
}
#ifndef CONFIG_H
#define CONFIG_H
+#include<ac/string.h>
+
typedef struct ConfigTable {
char *name;
char *what;
typedef int (ConfigDriver)(struct config_args_s *c);
+typedef struct config_reply_s {
+ int err;
+ char msg[SLAP_TEXT_BUFLEN];
+} ConfigReply;
+
typedef struct config_args_s {
int argc;
char **argv;
const char *fname;
int lineno;
char log[MAXPATHLEN + STRLENOF(": line 18446744073709551615") + 1];
- char msg[SLAP_TEXT_BUFLEN];
+#define cr_msg reply.msg
+ ConfigReply reply;
int depth;
int valx; /* multi-valued value index */
/* parsed first val for simple cases */
Entry *ca_entry; /* entry being modified */
void *private; /* anything */
ConfigDriver *cleanup;
+ ConfigType table; /* which config table did we come from */
} ConfigArgs;
/* If lineno is zero, we have an actual LDAP Add request from a client.
ldap_pvt_thread_mutex_unlock( &c->c_mutex );
}
-long connection_init(
+Connection * connection_init(
ber_socket_t s,
Listener *listener,
const char* dnsname,
const char* peername,
int flags,
slap_ssf_t ssf,
- struct berval *authid )
+ struct berval *authid
+ LDAP_PF_LOCAL_SENDMSG_ARG(struct berval *peerbv))
{
unsigned long id;
Connection *c;
assert( peername != NULL );
#ifndef HAVE_TLS
- assert( flags != CONN_IS_TLS );
+ assert( !( flags & CONN_IS_TLS ));
#endif
if( s == AC_SOCKET_INVALID ) {
Debug( LDAP_DEBUG_ANY,
"connection_init: init of socket %ld invalid.\n", (long)s, 0, 0 );
- return -1;
+ return NULL;
}
assert( s >= 0 );
Debug( LDAP_DEBUG_ANY,
"connection_init(%d): connection table full "
"(%d/%d)\n", s, i, dtblsize);
- return -1;
+ return NULL;
}
}
#endif
c->c_listener = listener;
- if ( flags == CONN_IS_CLIENT ) {
+ if ( flags & CONN_IS_CLIENT ) {
+ c->c_connid = 0;
c->c_conn_state = SLAP_C_CLIENT;
c->c_struct_state = SLAP_C_USED;
c->c_close_reason = "?"; /* should never be needed */
ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_SET_FD, &s );
ldap_pvt_thread_mutex_unlock( &c->c_mutex );
- return 0;
+ return c;
}
ber_str2bv( dnsname, 0, 1, &c->c_peer_domain );
#ifdef LDAP_CONNECTIONLESS
c->c_is_udp = 0;
- if( flags == CONN_IS_UDP ) {
+ if( flags & CONN_IS_UDP ) {
c->c_is_udp = 1;
#ifdef LDAP_DEBUG
ber_sockbuf_add_io( c->c_sb, &ber_sockbuf_io_debug,
ber_sockbuf_add_io( c->c_sb, &ber_sockbuf_io_readahead,
LBER_SBIOD_LEVEL_PROVIDER, NULL );
} else
+#endif /* LDAP_CONNECTIONLESS */
+#ifdef LDAP_PF_LOCAL
+ if ( flags & CONN_IS_IPC ) {
+#ifdef LDAP_DEBUG
+ ber_sockbuf_add_io( c->c_sb, &ber_sockbuf_io_debug,
+ LBER_SBIOD_LEVEL_PROVIDER, (void*)"ipc_" );
#endif
+ ber_sockbuf_add_io( c->c_sb, &ber_sockbuf_io_fd,
+ LBER_SBIOD_LEVEL_PROVIDER, (void *)&s );
+#ifdef LDAP_PF_LOCAL_SENDMSG
+ if ( !BER_BVISEMPTY( peerbv ))
+ ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_UNGET_BUF, peerbv );
+#endif
+ } else
+#endif /* LDAP_PF_LOCAL */
{
#ifdef LDAP_DEBUG
ber_sockbuf_add_io( c->c_sb, &ber_sockbuf_io_debug,
c->c_tls_ssf = 0;
#ifdef HAVE_TLS
- if ( flags == CONN_IS_TLS ) {
+ if ( flags & CONN_IS_TLS ) {
c->c_is_tls = 1;
c->c_needs_tls_accept = 1;
} else {
backend_connection_init(c);
- return id;
+ return c;
}
void connection2anonymous( Connection *c )
static BI_op_func *opfun[] = {
do_bind,
do_unbind,
+ do_search,
+ do_compare,
+ do_modify,
+ do_modrdn,
do_add,
do_delete,
- do_modrdn,
- do_modify,
- do_compare,
- do_search,
do_abandon,
do_extended,
NULL
ber_set_option( op->o_ber, LBER_OPT_BER_MEMCTX, &memctx_null );
- LDAP_STAILQ_REMOVE( &conn->c_ops, op, slap_op, o_next);
+ LDAP_STAILQ_REMOVE( &conn->c_ops, op, Operation, o_next);
LDAP_STAILQ_NEXT(op, o_next) = NULL;
slap_op_free( op );
conn->c_n_ops_executing--;
ldap_pvt_thread_start_t *func,
void *arg )
{
- int rc;
Connection *c;
- rc = connection_init( s, (Listener *)&dummy_list, "", "",
- CONN_IS_CLIENT, 0, NULL );
- if ( rc < 0 ) return -1;
+ c = connection_init( s, (Listener *)&dummy_list, "", "",
+ CONN_IS_CLIENT, 0, NULL
+ LDAP_PF_LOCAL_SENDMSG_ARG(NULL));
+ if ( !c ) return -1;
- c = connection_get( s );
c->c_clientfunc = func;
c->c_clientarg = arg;
slapd_add_internal( s, 0 );
slapd_set_read( s, 1 );
- connection_return( c );
return 0;
}
}
#ifdef DATA_READY_LOOP
while( !rc && ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_DATA_READY, NULL ));
-#elif CONNECTION_INPUT_LOOP
+#elif defined CONNECTION_INPUT_LOOP
while(!rc);
#else
while(0);
/* log authorization identity */
Statslog( LDAP_DEBUG_STATS,
- "%s BIND dn=\"%s\" mech=%s ssf=%d\n",
+ "%s BIND dn=\"%s\" mech=%s sasl_ssf=%d ssf=%d\n",
op->o_log_prefix,
BER_BVISNULL( &op->o_conn->c_dn ) ? "<empty>" : op->o_conn->c_dn.bv_val,
- op->o_conn->c_authmech.bv_val, op->orb_ssf, 0 );
+ op->o_conn->c_authmech.bv_val,
+ op->orb_ssf, op->o_conn->c_ssf );
Debug( LDAP_DEBUG_TRACE,
- "do_bind: SASL/%s bind: dn=\"%s\" ssf=%d\n",
+ "do_bind: SASL/%s bind: dn=\"%s\" sasl_ssf=%d\n",
op->o_conn->c_authmech.bv_val,
BER_BVISNULL( &op->o_conn->c_dn ) ? "<empty>" : op->o_conn->c_dn.bv_val,
op->orb_ssf );
void
connection_fake_init(
Connection *conn,
- Operation *op,
+ OperationBuffer *opbuf,
void *ctx )
{
- connection_fake_init2( conn, op, ctx, 1 );
+ connection_fake_init2( conn, opbuf, ctx, 1 );
}
void
connection_fake_init2(
Connection *conn,
- Operation *op,
+ OperationBuffer *opbuf,
void *ctx,
int newmem )
{
+ Operation *op = (Operation *) opbuf;
+
conn->c_connid = -1;
conn->c_send_ldap_result = slap_send_ldap_result;
conn->c_send_search_entry = slap_send_search_entry;
conn->c_peer_domain = slap_empty_bv;
conn->c_peer_name = slap_empty_bv;
- memset(op, 0, OPERATION_BUFFER_SIZE);
- op->o_hdr = (Opheader *)(op+1);
- op->o_controls = (void **)(op->o_hdr+1);
+ memset( opbuf, 0, sizeof( *opbuf ));
+ op->o_hdr = &opbuf->ob_hdr;
+ op->o_controls = opbuf->ob_controls;
+
/* set memory context */
op->o_tmpmemctx = slap_sl_mem_create(SLAP_SLAB_SIZE, SLAP_SLAB_STACK, ctx,
newmem );
#ifdef LDAP_SLAPI
if ( slapi_plugins_used ) {
- conn_fake_extblock *eb = NULL;
+ conn_fake_extblock *eb;
+ void *ebx = NULL;
/* Use thread keys to make sure these eventually get cleaned up */
- if ( ldap_pvt_thread_pool_getkey( ctx, connection_fake_init, &eb,
+ if ( ldap_pvt_thread_pool_getkey( ctx, connection_fake_init, &ebx,
NULL )) {
eb = ch_malloc( sizeof( *eb ));
slapi_int_create_object_extensions( SLAPI_X_EXT_CONNECTION, conn );
ldap_pvt_thread_pool_setkey( ctx, connection_fake_init, eb,
connection_fake_destroy );
} else {
+ eb = ebx;
conn->c_extensions = eb->eb_conn;
op->o_hdr->oh_extensions = eb->eb_op;
}
#include <ac/socket.h>
#include "slap.h"
+#include "ldif.h"
+#include "lutil.h"
#include "../../libraries/liblber/lber-int.h"
static SLAP_CTRL_PARSE_FN parseProxyAuthz;
static SLAP_CTRL_PARSE_FN parseRelax;
static SLAP_CTRL_PARSE_FN parseSearchOptions;
-#ifdef SLAP_SORTEDRESULTS
+#ifdef SLAP_CONTROL_X_SORTEDRESULTS
static SLAP_CTRL_PARSE_FN parseSortedResults;
#endif
static SLAP_CTRL_PARSE_FN parseSubentries;
static SLAP_CTRL_PARSE_FN parseTreeDelete;
#endif
static SLAP_CTRL_PARSE_FN parseValuesReturnFilter;
+#ifdef SLAP_CONTROL_X_SESSION_TRACKING
+static SLAP_CTRL_PARSE_FN parseSessionTracking;
+#endif
#undef sc_mask /* avoid conflict with Irix 6.5 <sys/signal.h> */
NULL
};
+#ifdef SLAP_CONTROL_X_SESSION_TRACKING
+static char *session_tracking_extops[] = {
+ LDAP_EXOP_MODIFY_PASSWD,
+ LDAP_EXOP_WHO_AM_I,
+ LDAP_EXOP_REFRESH,
+ NULL
+};
+#endif
+
static struct slap_control control_defs[] = {
{ LDAP_CONTROL_ASSERT,
(int)offsetof(struct slap_control_ids, sc_assert),
SLAP_CTRL_SEARCH,
NULL, NULL,
parsePagedResults, LDAP_SLIST_ENTRY_INITIALIZER(next) },
-#ifdef SLAP_SORTEDRESULTS
+#ifdef SLAP_CONTROL_X_SORTEDRESULTS
{ LDAP_CONTROL_SORTREQUEST,
(int)offsetof(struct slap_control_ids, sc_sortedResults),
SLAP_CTRL_GLOBAL|SLAP_CTRL_SEARCH|SLAP_CTRL_HIDE,
SLAP_CTRL_GLOBAL|SLAP_CTRL_ACCESS,
proxy_authz_extops, NULL,
parseProxyAuthz, LDAP_SLIST_ENTRY_INITIALIZER(next) },
+#ifdef SLAP_CONTROL_X_SESSION_TRACKING
+ { LDAP_CONTROL_X_SESSION_TRACKING,
+ (int)offsetof(struct slap_control_ids, sc_sessionTracking),
+ SLAP_CTRL_GLOBAL|SLAP_CTRL_ACCESS|SLAP_CTRL_BIND|SLAP_CTRL_HIDE,
+ session_tracking_extops, NULL,
+ parseSessionTracking, LDAP_SLIST_ENTRY_INITIALIZER(next) },
+#endif
{ NULL, 0, 0, NULL, 0, NULL, LDAP_SLIST_ENTRY_INITIALIZER(next) }
};
return LDAP_PROTOCOL_ERROR;
}
- if ( ctrl->ldctl_value.bv_len ) {
- rs->sr_text = "dontUseCopy control value not empty";
+ if ( !BER_BVISNULL( &ctrl->ldctl_value )) {
+ rs->sr_text = "dontUseCopy control value not absent";
return LDAP_PROTOCOL_ERROR;
}
return LDAP_PROTOCOL_ERROR;
}
- if ( ctrl->ldctl_value.bv_len ) {
- rs->sr_text = "relax control value not empty";
+ if ( !BER_BVISNULL( &ctrl->ldctl_value )) {
+ rs->sr_text = "relax control value not absent";
return LDAP_PROTOCOL_ERROR;
}
return LDAP_PROTOCOL_ERROR;
}
- if ( ctrl->ldctl_value.bv_len ) {
- rs->sr_text = "manageDSAit control value not empty";
+ if ( !BER_BVISNULL( &ctrl->ldctl_value )) {
+ rs->sr_text = "manageDSAit control value not absent";
return LDAP_PROTOCOL_ERROR;
}
return LDAP_PROTOCOL_ERROR;
}
+ if ( BER_BVISNULL( &ctrl->ldctl_value )) {
+ rs->sr_text = "proxy authorization control value absent";
+ return LDAP_PROTOCOL_ERROR;
+ }
+
if ( !( global_allows & SLAP_ALLOW_PROXY_AUTHZ_ANON )
&& BER_BVISEMPTY( &op->o_ndn ) )
{
ctrl->ldctl_value.bv_len ? ctrl->ldctl_value.bv_val : "anonymous",
0 );
- if ( ctrl->ldctl_value.bv_len == 0 ) {
+ if ( BER_BVISEMPTY( &ctrl->ldctl_value )) {
Debug( LDAP_DEBUG_TRACE,
"parseProxyAuthz: conn=%lu anonymous\n",
op->o_connid, 0, 0 );
return LDAP_PROTOCOL_ERROR;
}
- if ( ctrl->ldctl_value.bv_len ) {
+ if ( !BER_BVISNULL( &ctrl->ldctl_value ) ) {
rs->sr_text = "noop control value not empty";
return LDAP_PROTOCOL_ERROR;
}
return LDAP_PROTOCOL_ERROR;
}
+ if ( BER_BVISNULL( &ctrl->ldctl_value ) ) {
+ rs->sr_text = "paged results control value is absent";
+ return LDAP_PROTOCOL_ERROR;
+ }
+
if ( BER_BVISEMPTY( &ctrl->ldctl_value ) ) {
- rs->sr_text = "paged results control value is empty (or absent)";
+ rs->sr_text = "paged results control value is empty";
return LDAP_PROTOCOL_ERROR;
}
return rc;
}
-#ifdef SLAP_SORTEDRESULTS
+#ifdef SLAP_CONTROL_X_SORTEDRESULTS
static int parseSortedResults (
Operation *op,
SlapReply *rs,
return LDAP_PROTOCOL_ERROR;
}
+ if ( BER_BVISNULL( &ctrl->ldctl_value ) ) {
+ rs->sr_text = "sorted results control value is absent";
+ return LDAP_PROTOCOL_ERROR;
+ }
+
if ( BER_BVISEMPTY( &ctrl->ldctl_value ) ) {
- rs->sr_text = "sorted results control value is empty (or absent)";
+ rs->sr_text = "sorted results control value is empty";
return LDAP_PROTOCOL_ERROR;
}
return LDAP_PROTOCOL_ERROR;
}
- if ( ctrl->ldctl_value.bv_len == 0 ) {
- rs->sr_text = "assert control value is empty (or absent)";
+ if ( BER_BVISNULL( &ctrl->ldctl_value )) {
+ rs->sr_text = "assert control value is absent";
+ return LDAP_PROTOCOL_ERROR;
+ }
+
+ if ( BER_BVISEMPTY( &ctrl->ldctl_value )) {
+ rs->sr_text = "assert control value is empty";
return LDAP_PROTOCOL_ERROR;
}
return LDAP_PROTOCOL_ERROR;
}
- if ( ctrl->ldctl_value.bv_len == 0 ) {
- rs->sr_text = "preread control value is empty (or absent)";
+ if ( BER_BVISNULL( &ctrl->ldctl_value )) {
+ rs->sr_text = "preread control value is absent";
+ return LDAP_PROTOCOL_ERROR;
+ }
+
+ if ( BER_BVISEMPTY( &ctrl->ldctl_value )) {
+ rs->sr_text = "preread control value is empty";
return LDAP_PROTOCOL_ERROR;
}
return LDAP_PROTOCOL_ERROR;
}
- if ( ctrl->ldctl_value.bv_len == 0 ) {
- rs->sr_text = "postread control value is empty (or absent)";
+ if ( BER_BVISNULL( &ctrl->ldctl_value )) {
+ rs->sr_text = "postread control value is absent";
+ return LDAP_PROTOCOL_ERROR;
+ }
+
+ if ( BER_BVISEMPTY( &ctrl->ldctl_value )) {
+ rs->sr_text = "postread control value is empty";
return LDAP_PROTOCOL_ERROR;
}
return LDAP_PROTOCOL_ERROR;
}
- if ( ctrl->ldctl_value.bv_len == 0 ) {
- rs->sr_text = "valuesReturnFilter control value is empty (or absent)";
+ if ( BER_BVISNULL( &ctrl->ldctl_value )) {
+ rs->sr_text = "valuesReturnFilter control value is absent";
+ return LDAP_PROTOCOL_ERROR;
+ }
+
+ if ( BER_BVISEMPTY( &ctrl->ldctl_value )) {
+ rs->sr_text = "valuesReturnFilter control value is empty";
return LDAP_PROTOCOL_ERROR;
}
return LDAP_PROTOCOL_ERROR;
}
- if ( ctrl->ldctl_value.bv_len ) {
- rs->sr_text = "permissiveModify control value not empty";
+ if ( BER_BVISNULL( &ctrl->ldctl_value )) {
+ rs->sr_text = "permissiveModify control value not absent";
return LDAP_PROTOCOL_ERROR;
}
return LDAP_PROTOCOL_ERROR;
}
- if ( ctrl->ldctl_value.bv_len ) {
+ if ( BER_BVISNULL( &ctrl->ldctl_value )) {
rs->sr_text = "domainScope control value not empty";
return LDAP_PROTOCOL_ERROR;
}
return LDAP_PROTOCOL_ERROR;
}
- if ( ctrl->ldctl_value.bv_len ) {
- rs->sr_text = "treeDelete control value not empty";
+ if ( !BER_BVISNULL( &ctrl->ldctl_value )) {
+ rs->sr_text = "treeDelete control value not absent";
return LDAP_PROTOCOL_ERROR;
}
ber_int_t search_flags;
ber_tag_t tag;
- if ( ctrl->ldctl_value.bv_len == 0 ) {
- rs->sr_text = "searchOptions control value is empty (or absent)";
+ if ( BER_BVISNULL( &ctrl->ldctl_value )) {
+ rs->sr_text = "searchOptions control value is absent";
+ return LDAP_PROTOCOL_ERROR;
+ }
+
+ if ( BER_BVISEMPTY( &ctrl->ldctl_value )) {
+ rs->sr_text = "searchOptions control value is empty";
return LDAP_PROTOCOL_ERROR;
}
return LDAP_SUCCESS;
}
+#ifdef SLAP_CONTROL_X_SESSION_TRACKING
+struct berval session_tracking_formats[] = {
+ BER_BVC( LDAP_CONTROL_X_SESSION_TRACKING_RADIUS_ACCT_SESSION_ID ),
+ BER_BVC( "RADIUS-Acct-Session-Id" ),
+ BER_BVC( LDAP_CONTROL_X_SESSION_TRACKING_RADIUS_ACCT_MULTI_SESSION_ID ),
+ BER_BVC( "RADIUS-Acct-Multi-Session-Id" ),
+ BER_BVC( LDAP_CONTROL_X_SESSION_TRACKING_USERNAME ),
+ BER_BVC( "USERNAME" ),
+
+ BER_BVNULL
+};
+
+static int parseSessionTracking(
+ Operation *op,
+ SlapReply *rs,
+ LDAPControl *ctrl )
+{
+ BerElement *ber;
+ ber_tag_t tag;
+ ber_len_t len;
+ int i, rc;
+
+ struct berval sessionSourceIp = BER_BVNULL,
+ sessionSourceName = BER_BVNULL,
+ formatOID = BER_BVNULL,
+ sessionTrackingIdentifier = BER_BVNULL;
+
+ size_t st_len, st_pos;
+
+ if ( ctrl->ldctl_iscritical ) {
+ rs->sr_text = "sessionTracking criticality is TRUE";
+ return LDAP_PROTOCOL_ERROR;
+ }
+
+ if ( BER_BVISNULL( &ctrl->ldctl_value ) ) {
+ rs->sr_text = "sessionTracking control value is absent";
+ return LDAP_PROTOCOL_ERROR;
+ }
+
+ if ( BER_BVISEMPTY( &ctrl->ldctl_value ) ) {
+ rs->sr_text = "sessionTracking control value is empty";
+ return LDAP_PROTOCOL_ERROR;
+ }
+
+ ber = ber_init( &ctrl->ldctl_value );
+ if ( ber == NULL ) {
+ rs->sr_text = "internal error";
+ return LDAP_OTHER;
+ }
+
+ tag = ber_skip_tag( ber, &len );
+ if ( tag != LBER_SEQUENCE ) {
+ tag = LBER_ERROR;
+ goto error;
+ }
+
+ /* sessionSourceIp */
+ tag = ber_peek_tag( ber, &len );
+ if ( tag == LBER_DEFAULT ) {
+ tag = LBER_ERROR;
+ goto error;
+ }
+
+ if ( len == 0 ) {
+ tag = ber_skip_tag( ber, &len );
+
+ } else if ( len > 128 ) {
+ rs->sr_text = "sessionTracking.sessionSourceIp too long";
+ rs->sr_err = LDAP_PROTOCOL_ERROR;
+ goto error;
+
+ } else {
+ tag = ber_scanf( ber, "m", &sessionSourceIp );
+ }
+
+ if ( ldif_is_not_printable( sessionSourceIp.bv_val, sessionSourceIp.bv_len ) ) {
+ BER_BVZERO( &sessionSourceIp );
+ }
+
+ /* sessionSourceName */
+ tag = ber_peek_tag( ber, &len );
+ if ( tag == LBER_DEFAULT ) {
+ tag = LBER_ERROR;
+ goto error;
+ }
+
+ if ( len == 0 ) {
+ tag = ber_skip_tag( ber, &len );
+
+ } else if ( len > 65536 ) {
+ rs->sr_text = "sessionTracking.sessionSourceName too long";
+ rs->sr_err = LDAP_PROTOCOL_ERROR;
+ goto error;
+
+ } else {
+ tag = ber_scanf( ber, "m", &sessionSourceName );
+ }
+
+ if ( ldif_is_not_printable( sessionSourceName.bv_val, sessionSourceName.bv_len ) ) {
+ BER_BVZERO( &sessionSourceName );
+ }
+
+ /* formatOID */
+ tag = ber_peek_tag( ber, &len );
+ if ( tag == LBER_DEFAULT ) {
+ tag = LBER_ERROR;
+ goto error;
+ }
+
+ if ( len == 0 ) {
+ rs->sr_text = "sessionTracking.formatOID empty";
+ rs->sr_err = LDAP_PROTOCOL_ERROR;
+ goto error;
+
+ } else if ( len > 1024 ) {
+ rs->sr_text = "sessionTracking.formatOID too long";
+ rs->sr_err = LDAP_PROTOCOL_ERROR;
+ goto error;
+
+ } else {
+ tag = ber_scanf( ber, "m", &formatOID );
+ }
+
+ rc = numericoidValidate( NULL, &formatOID );
+ if ( rc != LDAP_SUCCESS ) {
+ rs->sr_text = "sessionTracking.formatOID invalid";
+ goto error;
+ }
+
+ for ( i = 0; !BER_BVISNULL( &session_tracking_formats[ i ] ); i += 2 )
+ {
+ if ( bvmatch( &formatOID, &session_tracking_formats[ i ] ) ) {
+ formatOID = session_tracking_formats[ i + 1 ];
+ break;
+ }
+ }
+
+ /* sessionTrackingIdentifier */
+ tag = ber_peek_tag( ber, &len );
+ if ( tag == LBER_DEFAULT ) {
+ tag = LBER_ERROR;
+ goto error;
+ }
+
+ if ( len == 0 ) {
+ tag = ber_skip_tag( ber, &len );
+
+ } else {
+ /* note: should not be more than 65536... */
+ tag = ber_scanf( ber, "m", &sessionTrackingIdentifier );
+ if ( ldif_is_not_printable( sessionTrackingIdentifier.bv_val, sessionTrackingIdentifier.bv_len ) ) {
+ /* we want the OID printed, at least */
+ BER_BVSTR( &sessionTrackingIdentifier, "" );
+ }
+ }
+
+ /* closure */
+ tag = ber_skip_tag( ber, &len );
+ if ( tag != LBER_DEFAULT || len != 0 ) {
+ tag = LBER_ERROR;
+ goto error;
+ }
+ tag = 0;
+
+ st_len = 0;
+ if ( !BER_BVISNULL( &sessionSourceIp ) ) {
+ st_len += STRLENOF( "IP=" ) + sessionSourceIp.bv_len;
+ }
+ if ( !BER_BVISNULL( &sessionSourceName ) ) {
+ if ( st_len ) st_len++;
+ st_len += STRLENOF( "NAME=" ) + sessionSourceName.bv_len;
+ }
+ if ( !BER_BVISNULL( &sessionTrackingIdentifier ) ) {
+ if ( st_len ) st_len++;
+ st_len += formatOID.bv_len + STRLENOF( "=" )
+ + sessionTrackingIdentifier.bv_len;
+ }
+
+ if ( st_len == 0 ) {
+ goto error;
+ }
+
+ st_len += STRLENOF( " []" );
+ st_pos = strlen( op->o_log_prefix );
+
+ if ( sizeof( op->o_log_prefix ) - st_pos > st_len ) {
+ char *ptr = &op->o_log_prefix[ st_pos ];
+
+ ptr = lutil_strcopy( ptr, " [" /*]*/ );
+
+ st_len = 0;
+ if ( !BER_BVISNULL( &sessionSourceIp ) ) {
+ ptr = lutil_strcopy( ptr, "IP=" );
+ ptr = lutil_strcopy( ptr, sessionSourceIp.bv_val );
+ st_len++;
+ }
+
+ if ( !BER_BVISNULL( &sessionSourceName ) ) {
+ if ( st_len ) *ptr++ = ' ';
+ ptr = lutil_strcopy( ptr, "NAME=" );
+ ptr = lutil_strcopy( ptr, sessionSourceName.bv_val );
+ st_len++;
+ }
+
+ if ( !BER_BVISNULL( &sessionTrackingIdentifier ) ) {
+ if ( st_len ) *ptr++ = ' ';
+ ptr = lutil_strcopy( ptr, formatOID.bv_val );
+ *ptr++ = '=';
+ ptr = lutil_strcopy( ptr, sessionTrackingIdentifier.bv_val );
+ }
+
+ *ptr++ = /*[*/ ']';
+ *ptr = '\0';
+ }
+
+error:;
+ (void)ber_free( ber, 1 );
+
+ if ( tag == LBER_ERROR ) {
+ rs->sr_text = "sessionTracking control decoding error";
+ return LDAP_PROTOCOL_ERROR;
+ }
+
+
+ return rs->sr_err;
+}
+
+int
+slap_ctrl_session_tracking_add(
+ Operation *op,
+ SlapReply *rs,
+ struct berval *ip,
+ struct berval *name,
+ struct berval *id,
+ LDAPControl *ctrl )
+{
+ BerElementBuffer berbuf;
+ BerElement *ber = (BerElement *)&berbuf;
+
+ static struct berval oid = BER_BVC( LDAP_CONTROL_X_SESSION_TRACKING_USERNAME );
+
+ assert( ctrl != NULL );
+
+ ber_init2( ber, NULL, LBER_USE_DER );
+
+ ber_printf( ber, "{OOOO}", ip, name, &oid, id );
+
+ if ( ber_flatten2( ber, &ctrl->ldctl_value, 0 ) == -1 ) {
+ rs->sr_err = LDAP_OTHER;
+ goto done;
+ }
+
+ ctrl->ldctl_oid = LDAP_CONTROL_X_SESSION_TRACKING;
+ ctrl->ldctl_iscritical = 0;
+
+ rs->sr_err = LDAP_SUCCESS;
+
+done:;
+ return rs->sr_err;
+}
+
+int
+slap_ctrl_session_tracking_request_add( Operation *op, SlapReply *rs, LDAPControl *ctrl )
+{
+ static struct berval bv_unknown = BER_BVC( SLAP_STRING_UNKNOWN );
+ struct berval ip = BER_BVNULL,
+ name = BER_BVNULL,
+ id = BER_BVNULL;
+
+ if ( !BER_BVISNULL( &op->o_conn->c_peer_name ) &&
+ memcmp( op->o_conn->c_peer_name.bv_val, "IP=", STRLENOF( "IP=" ) ) == 0 )
+ {
+ char *ptr;
+
+ ip.bv_val = op->o_conn->c_peer_name.bv_val + STRLENOF( "IP=" );
+ ip.bv_len = op->o_conn->c_peer_name.bv_len - STRLENOF( "IP=" );
+
+ ptr = ber_bvchr( &ip, ':' );
+ if ( ptr ) {
+ ip.bv_len = ptr - ip.bv_val;
+ }
+ }
+
+ if ( !BER_BVISNULL( &op->o_conn->c_peer_domain ) &&
+ !bvmatch( &op->o_conn->c_peer_domain, &bv_unknown ) )
+ {
+ name = op->o_conn->c_peer_domain;
+ }
+
+ if ( !BER_BVISNULL( &op->o_dn ) && !BER_BVISEMPTY( &op->o_dn ) ) {
+ id = op->o_dn;
+ }
+
+ return slap_ctrl_session_tracking_add( op, rs, &ip, &name, &id, ctrl );
+}
+#endif
};
static Avlnode *cr_index = NULL;
-static LDAP_STAILQ_HEAD(CRList, slap_content_rule) cr_list
+static LDAP_STAILQ_HEAD(CRList, ContentRule) cr_list
= LDAP_STAILQ_HEAD_INITIALIZER(cr_list);
static int
#endif /* ! epoll && ! /dev/poll */
#ifdef HAVE_TCPD
-# include <tcpd.h>
int allow_severity = LOG_INFO;
int deny_severity = LOG_NOTICE;
-
-# define SLAP_STRING_UNKNOWN STRING_UNKNOWN
-#else /* ! TCP Wrappers */
-# define SLAP_STRING_UNKNOWN "unknown"
-#endif /* ! TCP Wrappers */
+#endif /* TCP Wrappers */
#ifdef LDAP_PF_LOCAL
# include <sys/stat.h>
(int *)(ptr) <= &slap_daemon.sd_index[dtblsize]) ? 0 : 1 )
# define SLAP_EPOLL_EV_PTRFD(ptr) (SLAP_EPOLL_EV_LISTENER(ptr) ? \
- ((Listener *)ptr)->sl_sd : (int *)(ptr) - slap_daemon.sd_index)
+ ((Listener *)ptr)->sl_sd : \
+ (ber_socket_t) ((int *)(ptr) - slap_daemon.sd_index))
# define SLAP_SOCK_DEL(s) do { \
int fd, rc, index = SLAP_EPOLL_SOCK_IX((s)); \
#ifdef HAVE_SYSCONF
dtblsize = sysconf( _SC_OPEN_MAX );
-#elif HAVE_GETDTABLESIZE
+#elif defined(HAVE_GETDTABLESIZE)
dtblsize = getdtablesize();
#else /* ! HAVE_SYSCONF && ! HAVE_GETDTABLESIZE */
dtblsize = FD_SETSIZE;
Sockaddr from;
ber_socket_t s;
- socklen_t len = sizeof(from);
- long id;
+ ber_socklen_t len = sizeof(from);
+ Connection *c;
slap_ssf_t ssf = 0;
struct berval authid = BER_BVNULL;
#ifdef SLAPD_RLOOKUPS
char *peeraddr = NULL;
#ifdef LDAP_PF_LOCAL
char peername[MAXPATHLEN + sizeof("PATH=")];
+#ifdef LDAP_PF_LOCAL_SENDMSG
+ char peerbuf[8];
+ struct berval peerbv = BER_BVNULL;
+#endif
#elif defined(LDAP_PF_INET6)
char peername[sizeof("IP=[ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff]:65535")];
#else /* ! LDAP_PF_LOCAL && ! LDAP_PF_INET6 */
char peername[sizeof("IP=255.255.255.255:65336")];
#endif /* LDAP_PF_LOCAL */
+ int cflag;
Debug( LDAP_DEBUG_TRACE,
">>> slap_listener(%s)\n",
"daemon: listen=%ld, new connection on %ld\n",
(long) sl->sl_sd, (long) s, 0 );
+ cflag = 0;
switch ( from.sa_addr.sa_family ) {
# ifdef LDAP_PF_LOCAL
case AF_LOCAL:
+ cflag |= CONN_IS_IPC;
+
/* FIXME: apparently accept doesn't fill
* the sun_path sun_path member */
if ( from.sa_un_addr.sun_path[0] == '\0' ) {
uid_t uid;
gid_t gid;
- if( getpeereid( s, &uid, &gid ) == 0 ) {
+#ifdef LDAP_PF_LOCAL_SENDMSG
+ peerbv.bv_val = peerbuf;
+ peerbv.bv_len = sizeof( peerbuf );
+#endif
+ if( LUTIL_GETPEEREID( s, &uid, &gid, &peerbv ) == 0 ) {
authid.bv_val = ch_malloc(
STRLENOF( "gidNumber=4294967295+uidNumber=4294967295,"
"cn=peercred,cn=external,cn=auth" ) + 1 );
#endif /* HAVE_TCPD */
}
- id = connection_init(s, sl,
- dnsname != NULL ? dnsname : SLAP_STRING_UNKNOWN,
- peername,
#ifdef HAVE_TLS
- sl->sl_is_tls ? CONN_IS_TLS : 0,
-#else /* ! HAVE_TLS */
- 0,
-#endif /* ! HAVE_TLS */
- ssf,
- authid.bv_val ? &authid : NULL );
+ if ( sl->sl_is_tls ) cflag |= CONN_IS_TLS;
+#endif
+ c = connection_init(s, sl,
+ dnsname != NULL ? dnsname : SLAP_STRING_UNKNOWN,
+ peername, cflag, ssf,
+ authid.bv_val ? &authid : NULL
+ LDAP_PF_LOCAL_SENDMSG_ARG(&peerbv));
if( authid.bv_val ) ch_free(authid.bv_val);
- if( id < 0 ) {
+ if( !c ) {
Debug( LDAP_DEBUG_ANY,
"daemon: connection_init(%ld, %s, %s) failed.\n",
(long) s, peername, sl->sl_name.bv_val );
Statslog( LDAP_DEBUG_STATS,
"conn=%ld fd=%ld ACCEPT from %s (%s)\n",
- id, (long) s, peername, sl->sl_name.bv_val,
+ c->c_connid, (long) s, peername, sl->sl_name.bv_val,
0 );
return 0;
}
#endif /* HAVE_NT_SERVICE_MANAGER */
-#ifdef SLAP_SEM_LOAD_CONTROL
- /*
- * initialize count and lazyness of a semaphore
- */
- (void) ldap_lazy_sem_init(
- SLAP_MAX_WORKER_THREADS + 4 /* max workers + margin */,
- 4 /* lazyness */ );
-#endif /* SLAP_SEM_LOAD_CONTROL */
-
/* initialization complete. Here comes the loop. */
while ( !slapd_shutdown ) {
ldap_pvt_thread_mutex_unlock( &slapd_rq.rq_mutex );
if ( rtask && cat.tv_sec ) {
- time_t diff = difftime( cat.tv_sec, now );
- if ( diff == 0 ) diff = tdelta;
+ /* NOTE: diff __should__ always be >= 0,
+ * AFAI understand; however (ITS#4872),
+ * time_t might be unsigned in some systems,
+ * while difftime() returns a double */
+ double diff = difftime( cat.tv_sec, now );
+ if ( diff <= 0 ) {
+ diff = tdelta;
+ }
if ( tvp == NULL || diff < tv.tv_sec ) {
tv.tv_sec = diff;
tv.tv_usec = 0;
for ( l = 0; slap_listeners[l] != NULL; l++ ) {
Listener *lr = slap_listeners[l];
- long id;
+ Connection *c;
if ( !lr->sl_is_udp ) {
continue;
}
- id = connection_init( lr->sl_sd, lr, "", "",
- CONN_IS_UDP, (slap_ssf_t) 0, NULL );
+ c = connection_init( lr->sl_sd, lr, "", "",
+ CONN_IS_UDP, (slap_ssf_t) 0, NULL
+ LDAP_PF_LOCAL_SENDMSG_ARG(NULL));
- if ( id < 0 ) {
+ if ( !c ) {
Debug( LDAP_DEBUG_TRACE,
"connectionless_init: failed on %s (%d)\n",
lr->sl_url, lr->sl_sd, 0 );
* SIGBREAK is generated when a user logs out.
*/
-#if HAVE_NT_SERVICE_MANAGER && SIGBREAK
+#if defined(HAVE_NT_SERVICE_MANAGER) && defined(SIGBREAK)
if (is_NT_Service && sig == SIGBREAK) {
/* empty */;
} else
{
struct berval dn = BER_BVNULL;
- Debug( LDAP_DEBUG_TRACE, "do_delete\n", 0, 0, 0 );
-
+ Debug( LDAP_DEBUG_TRACE, "%s do_delete\n",
+ op->o_log_prefix, 0, 0 );
/*
* Parse the delete request. It looks like this:
*
*/
if ( ber_scanf( op->o_ber, "m", &dn ) == LBER_ERROR ) {
- Debug( LDAP_DEBUG_ANY, "ber_scanf failed\n", 0, 0, 0 );
+ Debug( LDAP_DEBUG_ANY, "%s do_delete: ber_scanf failed\n",
+ op->o_log_prefix, 0, 0 );
send_ldap_discon( op, rs, LDAP_PROTOCOL_ERROR, "decoding error" );
return SLAPD_DISCONNECT;
}
if( get_ctrls( op, rs, 1 ) != LDAP_SUCCESS ) {
- Debug( LDAP_DEBUG_ANY, "do_delete: get_ctrls failed\n", 0, 0, 0 );
+ Debug( LDAP_DEBUG_ANY, "%s do_delete: get_ctrls failed\n",
+ op->o_log_prefix, 0, 0 );
goto cleanup;
}
rs->sr_err = dnPrettyNormal( NULL, &dn, &op->o_req_dn, &op->o_req_ndn,
op->o_tmpmemctx );
if( rs->sr_err != LDAP_SUCCESS ) {
- Debug( LDAP_DEBUG_ANY,
- "do_delete: invalid dn (%s)\n", dn.bv_val, 0, 0 );
+ Debug( LDAP_DEBUG_ANY, "%s do_delete: invalid dn (%s)\n",
+ op->o_log_prefix, dn.bv_val, 0 );
send_ldap_error( op, rs, LDAP_INVALID_DN_SYNTAX, "invalid DN" );
goto cleanup;
}
+ Statslog( LDAP_DEBUG_STATS, "%s DEL dn=\"%s\"\n",
+ op->o_log_prefix, op->o_req_dn.bv_val, 0, 0, 0 );
+
if( op->o_req_ndn.bv_len == 0 ) {
- Debug( LDAP_DEBUG_ANY, "do_delete: root dse!\n", 0, 0, 0 );
+ Debug( LDAP_DEBUG_ANY, "%s do_delete: root dse!\n",
+ op->o_log_prefix, 0, 0 );
/* protocolError would likely be a more appropriate error */
send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
"cannot delete the root DSE" );
goto cleanup;
} else if ( bvmatch( &op->o_req_ndn, &frontendDB->be_schemandn ) ) {
- Debug( LDAP_DEBUG_ANY, "do_delete: subschema subentry!\n", 0, 0, 0 );
+ Debug( LDAP_DEBUG_ANY, "%s do_delete: subschema subentry!\n",
+ op->o_log_prefix, 0, 0 );
/* protocolError would likely be a more appropriate error */
send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
"cannot delete the root DSE" );
goto cleanup;
}
- Statslog( LDAP_DEBUG_STATS, "%s DEL dn=\"%s\"\n",
- op->o_log_prefix, op->o_req_dn.bv_val, 0, 0, 0 );
-
op->o_bd = frontendDB;
rs->sr_err = frontendDB->be_delete( op, rs );
fe_op_delete( Operation *op, SlapReply *rs )
{
struct berval pdn = BER_BVNULL;
- int manageDSAit;
BackendDB *op_be, *bd = op->o_bd;
- manageDSAit = get_manageDSAit( op );
-
/*
* We could be serving multiple database backends. Select the
* appropriate one, or send a referral to our "referral server"
* if we don't hold it.
*/
- op->o_bd = select_backend( &op->o_req_ndn, manageDSAit, 1 );
+ op->o_bd = select_backend( &op->o_req_ndn, 1 );
if ( op->o_bd == NULL ) {
op->o_bd = bd;
rs->sr_ref = referral_rewrite( default_referral,
/* If we've got a glued backend, check the real backend */
op_be = op->o_bd;
if ( SLAP_GLUE_INSTANCE( op->o_bd )) {
- op->o_bd = select_backend( &op->o_req_ndn, manageDSAit, 0 );
+ op->o_bd = select_backend( &op->o_req_ndn, 0 );
}
/* check restrictions */
struct berval org_dn = BER_BVNULL;
struct berval org_ndn = BER_BVNULL;
int org_managedsait;
- slap_callback cb = { NULL, slap_replog_cb, NULL, NULL };
op->o_bd = op_be;
-
- if ( !op->o_bd->be_update_ndn.bv_len || !repl_user ) {
- cb.sc_next = op->o_callback;
- op->o_callback = &cb;
- }
-
op->o_bd->be_delete( op, rs );
org_req_dn = op->o_req_dn;
* Note: the sorting can be slightly improved by sorting first
* by attribute type length, then by alphabetical order.
*
- * uses a linear search; should be fine since the number of AVAs in
+ * uses an insertion sort; should be fine since the number of AVAs in
* a RDN should be limited.
*/
-static void
-AVA_Sort( LDAPRDN rdn, int iAVA )
+static int
+AVA_Sort( LDAPRDN rdn, int nAVAs )
{
+ LDAPAVA *ava_i;
int i;
- LDAPAVA *ava_in = rdn[ iAVA ];
assert( rdn != NULL );
- assert( ava_in != NULL );
-
- for ( i = 0; i < iAVA; i++ ) {
- LDAPAVA *ava = rdn[ i ];
- int a, j;
- assert( ava != NULL );
+ for ( i = 1; i < nAVAs; i++ ) {
+ LDAPAVA *ava_j;
+ int j;
- a = strcmp( ava_in->la_attr.bv_val, ava->la_attr.bv_val );
+ ava_i = rdn[ i ];
+ for ( j = i-1; j >=0; j-- ) {
+ int a;
- if ( a > 0 ) {
- break;
- }
+ ava_j = rdn[ j ];
+ a = strcmp( ava_i->la_attr.bv_val, ava_j->la_attr.bv_val );
- while ( a == 0 ) {
- int v, d;
+ if ( a == 0 ) {
+ int d;
- d = ava_in->la_value.bv_len - ava->la_value.bv_len;
+ d = ava_i->la_value.bv_len - ava_j->la_value.bv_len;
- v = memcmp( ava_in->la_value.bv_val,
- ava->la_value.bv_val,
- d <= 0 ? ava_in->la_value.bv_len
- : ava->la_value.bv_len );
+ a = memcmp( ava_i->la_value.bv_val,
+ ava_j->la_value.bv_val,
+ d <= 0 ? ava_i->la_value.bv_len
+ : ava_j->la_value.bv_len );
- if ( v == 0 && d != 0 ) {
- v = d;
+ if ( a == 0 ) {
+ a = d;
+ }
}
+ /* Duplicates are not allowed */
+ if ( a == 0 )
+ return LDAP_INVALID_DN_SYNTAX;
- if ( v <= 0 ) {
- /*
- * got it!
- */
+ if ( a > 0 )
break;
- }
- if ( ++i == iAVA ) {
- /*
- * already sorted
- */
- return;
- }
-
- ava = rdn[ i ];
- a = strcmp( ava_in->la_attr.bv_val,
- ava->la_attr.bv_val );
- }
-
- /*
- * move ahead
- */
- for ( j = iAVA; j > i; j-- ) {
- rdn[ j ] = rdn[ j - 1 ];
+ rdn[ j+1 ] = rdn[ j ];
}
- rdn[ i ] = ava_in;
-
- return;
+ rdn[ j+1 ] = ava_i;
}
+ return LDAP_SUCCESS;
}
static int
LDAPRDN_rewrite( LDAPRDN rdn, unsigned flags, void *ctx )
{
- int rc;
- int iAVA;
+ int rc, iAVA, do_sort = 0;
+
for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) {
LDAPAVA *ava = rdn[ iAVA ];
AttributeDescription *ad;
slap_syntax_transform_func *transf = NULL;
MatchingRule *mr = NULL;
struct berval bv = BER_BVNULL;
- int do_sort = 0;
assert( ava != NULL );
ava->la_value = bv;
ava->la_flags |= LDAP_AVA_FREE_VALUE;
}
+ }
+ rc = LDAP_SUCCESS;
- if( do_sort ) AVA_Sort( rdn, iAVA );
+ if ( do_sort ) {
+ rc = AVA_Sort( rdn, iAVA );
}
- return LDAP_SUCCESS;
+
+ return rc;
}
/*
return -1;
}
-#ifdef HAVE_TLS
/*
* Convert an X.509 DN into a normalized LDAP DN
*/
return rc;
}
+#ifdef HAVE_TLS
/*
* Get the TLS session's peer's DN into a normalized LDAP DN
*/
return str2entry2( s, 1 );
}
+#define bvcasematch(bv1, bv2) (ber_bvstrcasecmp(bv1, bv2) == 0)
+
Entry *
str2entry2( char *s, int checkvals )
{
break;
}
i++;
+ if (i >= lines) {
+ Debug( LDAP_DEBUG_TRACE,
+ "<= str2entry ran past end of entry\n", 0, 0, 0 );
+ goto fail;
+ }
rc = ldif_parse_line2( s, type+i, vals+i, &freev );
freeval[i] = freev;
continue;
}
- if ( type[i].bv_len == dn_bv.bv_len &&
- strcasecmp( type[i].bv_val, dn_bv.bv_val ) == 0 ) {
-
+ if ( bvcasematch( &type[i], &dn_bv ) ) {
if ( e->e_dn != NULL ) {
Debug( LDAP_DEBUG_ANY, "str2entry: "
"entry %ld has multiple DNs \"%s\" and \"%s\"\n",
goto fail;
}
-#define bvcasematch(bv1, bv2) ( ((bv1)->bv_len == (bv2)->bv_len) && (strncasecmp((bv1)->bv_val, (bv2)->bv_val, (bv1)->bv_len) == 0) )
-
/* Make sure all attributes with multiple values are contiguous */
if ( checkvals ) {
int j, k;
goto fail;
}
}
+
+ /* require ';binary' when appropriate (ITS#5071) */
+ if ( slap_syntax_is_binary( ad->ad_type->sat_syntax ) && !slap_ad_is_binary( ad ) ) {
+ Debug( LDAP_DEBUG_ANY,
+ "str2entry: attributeType %s #%d: "
+ "needs ';binary' transfer as per syntax %s\n",
+ ad->ad_cname.bv_val, 0,
+ ad->ad_type->sat_syntax->ssyn_oid );
+ goto fail;
+ }
}
if (( ad_prev && ad != ad_prev ) || ( i == lines )) {
if ( i == lines ) break;
}
+ if ( BER_BVISNULL( &vals[i] ) ) {
+ Debug( LDAP_DEBUG_ANY,
+ "str2entry: attributeType %s #%d: "
+ "no value\n",
+ ad->ad_cname.bv_val, attr_cnt, 0 );
+ goto fail;
+ }
+
if( slapMode & SLAP_TOOL_MODE ) {
struct berval pval;
slap_syntax_validate_func *validate =
ber_tag_t tag;
ber_len_t len;
- Debug( LDAP_DEBUG_TRACE, "do_extended\n", 0, 0, 0 );
+ Debug( LDAP_DEBUG_TRACE, "%s do_extended\n",
+ op->o_log_prefix, 0, 0 );
if( op->o_protocol < LDAP_VERSION3 ) {
- Debug( LDAP_DEBUG_ANY,
- "do_extended: protocol version (%d) too low\n",
- op->o_protocol, 0 ,0 );
+ Debug( LDAP_DEBUG_ANY, "%s do_extended: protocol version (%d) too low\n",
+ op->o_log_prefix, op->o_protocol, 0 );
send_ldap_discon( op, rs, LDAP_PROTOCOL_ERROR, "requires LDAPv3" );
rs->sr_err = SLAPD_DISCONNECT;
goto done;
}
if ( ber_scanf( op->o_ber, "{m" /*}*/, &op->ore_reqoid ) == LBER_ERROR ) {
- Debug( LDAP_DEBUG_ANY, "do_extended: ber_scanf failed\n", 0, 0 ,0 );
+ Debug( LDAP_DEBUG_ANY, "%s do_extended: ber_scanf failed\n",
+ op->o_log_prefix, 0, 0 );
send_ldap_discon( op, rs, LDAP_PROTOCOL_ERROR, "decoding error" );
rs->sr_err = SLAPD_DISCONNECT;
goto done;
if( ber_peek_tag( op->o_ber, &len ) == LDAP_TAG_EXOP_REQ_VALUE ) {
if( ber_scanf( op->o_ber, "m", &reqdata ) == LBER_ERROR ) {
- Debug( LDAP_DEBUG_ANY, "do_extended: ber_scanf failed\n", 0, 0 ,0 );
+ Debug( LDAP_DEBUG_ANY, "%s do_extended: ber_scanf failed\n",
+ op->o_log_prefix, 0, 0 );
send_ldap_discon( op, rs, LDAP_PROTOCOL_ERROR, "decoding error" );
rs->sr_err = SLAPD_DISCONNECT;
goto done;
}
if( get_ctrls( op, rs, 1 ) != LDAP_SUCCESS ) {
- Debug( LDAP_DEBUG_ANY, "do_extended: get_ctrls failed\n", 0, 0 ,0 );
+ Debug( LDAP_DEBUG_ANY, "%s do_extended: get_ctrls failed\n",
+ op->o_log_prefix, 0, 0 );
return rs->sr_err;
}
+ Statslog( LDAP_DEBUG_STATS, "%s EXT oid=%s\n",
+ op->o_log_prefix, op->ore_reqoid.bv_val, 0, 0, 0 );
+
/* check for controls inappropriate for all extended operations */
if( get_manageDSAit( op ) == SLAP_CONTROL_CRITICAL ) {
- Statslog( LDAP_DEBUG_STATS, "%s EXT oid=%s\n",
- op->o_log_prefix, op->ore_reqoid.bv_val, 0, 0, 0 );
send_ldap_error( op, rs,
LDAP_UNAVAILABLE_CRITICAL_EXTENSION,
"manageDSAit control inappropriate" );
ext = find_extop(supp_ext_list, &op->ore_reqoid );
if ( ext == NULL ) {
- Statslog( LDAP_DEBUG_STATS, "%s EXT oid=%s\n",
- op->o_log_prefix, op->ore_reqoid.bv_val, 0, 0, 0 );
- Debug( LDAP_DEBUG_ANY, "do_extended: unsupported operation \"%s\"\n",
- op->ore_reqoid.bv_val, 0 ,0 );
+ Debug( LDAP_DEBUG_ANY, "%s do_extended: unsupported operation \"%s\"\n",
+ op->o_log_prefix, op->ore_reqoid.bv_val, 0 );
send_ldap_error( op, rs, LDAP_PROTOCOL_ERROR,
"unsupported extended operation" );
goto done;
len = fstr->bv_len;
filter_escape_value_x( &f->f_sub_initial, &tmp, op->o_tmpmemctx );
- tmplen = tmp.bv_len ? tmp.bv_len : STRLENOF( "(null)" );
+ tmplen = tmp.bv_len;
fstr->bv_len += tmplen;
fstr->bv_val = op->o_tmprealloc( fstr->bv_val,
fstr->bv_len + 1, op->o_tmpmemctx );
- snprintf( &fstr->bv_val[len-2],
+ snprintf( &fstr->bv_val[len - 2],
tmplen + STRLENOF( /*(*/ "*)" ) + 1,
/* "(attr=" */ "%s*)",
- tmp.bv_len ? tmp.bv_val : "(null)");
+ tmp.bv_len ? tmp.bv_val : "");
ber_memfree_x( tmp.bv_val, op->o_tmpmemctx );
}
len = fstr->bv_len;
filter_escape_value_x( &f->f_sub_any[i],
&tmp, op->o_tmpmemctx );
- tmplen = tmp.bv_len ? tmp.bv_len : STRLENOF( "(null)" );
+ tmplen = tmp.bv_len;
fstr->bv_len += tmplen + STRLENOF( /*(*/ ")" );
fstr->bv_val = op->o_tmprealloc( fstr->bv_val,
fstr->bv_len + 1, op->o_tmpmemctx );
- snprintf( &fstr->bv_val[len-1],
+ snprintf( &fstr->bv_val[len - 1],
tmplen + STRLENOF( /*(*/ "*)" ) + 1,
/* "(attr=[init]*[any*]" */ "%s*)",
- tmp.bv_len ? tmp.bv_val : "(null)");
+ tmp.bv_len ? tmp.bv_val : "");
ber_memfree_x( tmp.bv_val, op->o_tmpmemctx );
}
}
len = fstr->bv_len;
filter_escape_value_x( &f->f_sub_final, &tmp, op->o_tmpmemctx );
- tmplen = tmp.bv_len ? tmp.bv_len : STRLENOF( "(null)" );
+ tmplen = tmp.bv_len;
fstr->bv_len += tmplen;
fstr->bv_val = op->o_tmprealloc( fstr->bv_val,
fstr->bv_len + 1, op->o_tmpmemctx );
- snprintf( &fstr->bv_val[len-1],
+ snprintf( &fstr->bv_val[len - 1],
tmplen + STRLENOF( /*(*/ ")" ) + 1,
/* "(attr=[init*][any*]" */ "%s)",
- tmp.bv_len ? tmp.bv_val : "(null)");
+ tmp.bv_len ? tmp.bv_val : "");
ber_memfree_x( tmp.bv_val, op->o_tmpmemctx );
}
if ( ava->aa_desc == slap_schema.si_ad_entryDN ) {
MatchingRule *mr;
- int rc, match;
+ int match;
const char *text;
if( type != LDAP_FILTER_EQUALITY &&
} else
#endif
{
- ret = value_match( &match, a->a_desc, mr, use,
+ ret = ordered_value_match( &match, a->a_desc, mr, use,
bv, &ava->aa_value, &text );
}
slap_counters_t slap_counters;
-ldap_pvt_thread_mutex_t replog_mutex;
-
static const char* slap_name = NULL;
int slapMode = SLAP_UNDEFINED_MODE;
slapMode = mode;
+ slap_op_init();
+
#ifdef SLAPD_MODULES
if ( module_init() != 0 ) {
slap_debug |= LDAP_DEBUG_NONE;
ldap_pvt_thread_pool_init( &connection_pool,
connection_pool_max, 0);
- ldap_pvt_thread_mutex_init( &replog_mutex );
ldap_pvt_thread_mutex_init( &slap_counters.sc_sent_mutex );
ldap_pvt_thread_mutex_init( &slap_counters.sc_ops_mutex );
}
+ slap_op_destroy();
+
ldap_pvt_thread_destroy();
- /* should destory the above mutex */
+ /* should destroy the above mutex */
return rc;
}
}
int
-slap_parse_csn_sid( struct berval *csn )
+slap_parse_csn_sid( struct berval *csnp )
{
char *p, *q;
+ struct berval csn = *csnp;
int i;
- p = memchr( csn->bv_val, '#', csn->bv_len );
- if ( p )
- p = strchr( p+1, '#' );
+ p = ber_bvchr( &csn, '#' );
if ( !p )
return -1;
p++;
- i = strtoul( p, &q, 10 );
- if ( p == q || i > SLAP_SYNC_SID_MAX )
+ csn.bv_len -= p - csn.bv_val;
+ csn.bv_val = p;
+
+ p = ber_bvchr( &csn, '#' );
+ if ( !p )
+ return -1;
+ p++;
+ csn.bv_len -= p - csn.bv_val;
+ csn.bv_val = p;
+
+ q = ber_bvchr( &csn, '#' );
+ if ( !q )
+ return -1;
+
+ csn.bv_len = q - p;
+
+ i = (int)strtoul( p, &q, 16 );
+ if ( p == q || q != p + csn.bv_len || i > SLAP_SYNC_SID_MAX ) {
i = -1;
+ }
+
return i;
}
slap_parse_csn_sids( BerVarray csns, int numcsns, void *memctx )
{
int i, *ret;
- char *p, *q;
ret = slap_sl_malloc( numcsns * sizeof(int), memctx );
for ( i=0; i<numcsns; i++ ) {
{
char *csn_ptr;
char *csn_str;
- int csn_str_len;
char *rid_ptr;
char *cval;
char *next, *end;
if ( !strncmp( next, "rid=", STRLENOF("rid=") )) {
rid_ptr = next;
cookie->rid = strtoul( &rid_ptr[ STRLENOF( "rid=" ) ], &next, 10 );
- if ( next == rid_ptr || next > end || *next != ',' ) {
+ if ( next == rid_ptr ||
+ next > end ||
+ ( *next && *next != ',' ) )
+ {
return -1;
}
if ( *next == ',' ) {
if ( !strncmp( next, "sid=", STRLENOF("sid=") )) {
rid_ptr = next;
cookie->sid = strtoul( &rid_ptr[ STRLENOF( "sid=" ) ], &next, 16 );
- if ( next == rid_ptr || next > end || *next != ',' ) {
+ if ( next == rid_ptr ||
+ next > end ||
+ ( *next && *next != ',' ) )
+ {
return -1;
}
if ( *next == ',' ) {
ad.bv_val = strchr( oc.bv_val, '/' );
if ( ad.bv_val != NULL ) {
const char *text = NULL;
- int rc;
oc.bv_len = ad.bv_val - oc.bv_val;
if ( group_ad == NULL ) {
const char *text = NULL;
- int rc;
rc = slap_str2ad( SLAPD_GROUP_ATTR, &group_ad, &text );
"\t-g group\tGroup (id or name) to run as\n"
#endif
"\t-h URLs\t\tList of URLs to serve\n"
-#ifdef LOG_LOCAL4
+#ifdef SLAP_DEFAULT_SYSLOG_USER
"\t-l facility\tSyslog facility (default: LOCAL4)\n"
#endif
"\t-n serverName\tService name\n"
#if defined(HAVE_CHROOT)
char *sandbox = NULL;
#endif
-#ifdef LOG_LOCAL4
+#ifdef SLAP_DEFAULT_SYSLOG_USER
int syslogUser = SLAP_DEFAULT_SYSLOG_USER;
#endif
#ifdef HAVE_NT_SERVICE_MANAGER
{
- int *i;
+ int *ip;
char *newConfigFile;
char *newConfigDir;
char *newUrls;
regService = serverName;
}
- i = (int*)lutil_getRegParam( regService, "DebugLevel" );
- if ( i != NULL ) {
- slap_debug = *i;
+ ip = (int*)lutil_getRegParam( regService, "DebugLevel" );
+ if ( ip != NULL ) {
+ slap_debug = *ip;
Debug( LDAP_DEBUG_ANY,
"new debug level from registry is: %d\n", slap_debug, 0, 0 );
}
while ( (i = getopt( argc, argv,
"c:d:f:F:h:n:o:s:tT:V"
-#if LDAP_PF_INET6
+#ifdef LDAP_PF_INET6
"46"
#endif
#ifdef HAVE_CHROOT
case 'o': {
char *val = strchr( optarg, '=' );
struct berval opt;
- int i;
opt.bv_val = optarg;
if ( version > 1 ) goto stop;
}
+#if defined(LDAP_DEBUG) && defined(LDAP_SYSLOG)
{
char *logName;
#ifdef HAVE_EBCDIC
#ifdef LOG_LOCAL4
openlog( logName, OPENLOG_OPTIONS, syslogUser );
-#elif LOG_DEBUG
+#elif defined LOG_DEBUG
openlog( logName, OPENLOG_OPTIONS );
#endif
#ifdef HAVE_EBCDIC
free( logName );
#endif
}
+#endif /* LDAP_DEBUG && LDAP_SYSLOG */
Debug( LDAP_DEBUG_ANY, "%s", Versionstr, 0, 0 );
extops_init();
lutil_passwd_init();
- slap_op_init();
#ifdef HAVE_TLS
rc = ldap_create( &slap_tls_ld );
module_kill();
#endif
- slap_op_destroy();
-
extops_kill();
supported_feature_destroy();
#ifdef HAVE_TLS
if ( slap_tls_ld ) {
- SSL_CTX_free( slap_tls_ctx );
+ ldap_pvt_tls_ctx_free( slap_tls_ctx );
ldap_unbind_ext( slap_tls_ld, NULL, NULL );
}
ldap_pvt_tls_destroy();
SlapReply *rs )
{
struct berval dn = BER_BVNULL;
- char *last;
- ber_tag_t tag;
- ber_len_t len;
char textbuf[ SLAP_TEXT_BUFLEN ];
size_t textlen = sizeof( textbuf );
+#ifdef LDAP_DEBUG
+ Modifications *tmp;
+#endif
- Debug( LDAP_DEBUG_TRACE, "do_modify\n", 0, 0, 0 );
-
+ Debug( LDAP_DEBUG_TRACE, "%s do_modify\n",
+ op->o_log_prefix, 0, 0 );
/*
* Parse the modify request. It looks like this:
*
*/
if ( ber_scanf( op->o_ber, "{m" /*}*/, &dn ) == LBER_ERROR ) {
- Debug( LDAP_DEBUG_ANY, "do_modify: ber_scanf failed\n", 0, 0, 0 );
-
+ Debug( LDAP_DEBUG_ANY, "%s do_modify: ber_scanf failed\n",
+ op->o_log_prefix, 0, 0 );
send_ldap_discon( op, rs, LDAP_PROTOCOL_ERROR, "decoding error" );
return SLAPD_DISCONNECT;
}
- Debug( LDAP_DEBUG_ARGS, "do_modify: dn (%s)\n", dn.bv_val, 0, 0 );
+ Debug( LDAP_DEBUG_ARGS, "%s do_modify: dn (%s)\n",
+ op->o_log_prefix, dn.bv_val, 0 );
rs->sr_err = slap_parse_modlist( op, rs, op->o_ber, &op->oq_modify );
if ( rs->sr_err != LDAP_SUCCESS ) {
- Debug( LDAP_DEBUG_ANY, "do_modify: slap_parse_modlist failed err=%d msg=%s\n",
- rs->sr_err, rs->sr_text, 0 );
+ Debug( LDAP_DEBUG_ANY, "%s do_modify: slap_parse_modlist failed err=%d msg=%s\n",
+ op->o_log_prefix, rs->sr_err, rs->sr_text );
goto cleanup;
}
if( get_ctrls( op, rs, 1 ) != LDAP_SUCCESS ) {
- Debug( LDAP_DEBUG_ANY, "do_modify: get_ctrls failed\n", 0, 0, 0 );
+ Debug( LDAP_DEBUG_ANY, "%s do_modify: get_ctrls failed\n",
+ op->o_log_prefix, 0, 0 );
goto cleanup;
}
rs->sr_err = dnPrettyNormal( NULL, &dn, &op->o_req_dn, &op->o_req_ndn,
op->o_tmpmemctx );
if( rs->sr_err != LDAP_SUCCESS ) {
- Debug( LDAP_DEBUG_ANY,
- "do_modify: invalid dn (%s)\n", dn.bv_val, 0, 0 );
+ Debug( LDAP_DEBUG_ANY, "%s do_modify: invalid dn (%s)\n",
+ op->o_log_prefix, dn.bv_val, 0 );
send_ldap_error( op, rs, LDAP_INVALID_DN_SYNTAX, "invalid DN" );
goto cleanup;
}
- rs->sr_err = slap_mods_check( op, op->orm_modlist,
- &rs->sr_text, textbuf, textlen, NULL );
+ op->orm_no_opattrs = 0;
- if ( rs->sr_err != LDAP_SUCCESS ) {
- send_ldap_result( op, rs );
- goto cleanup;
- }
-
- op->o_bd = frontendDB;
- rs->sr_err = frontendDB->be_modify( op, rs );
-
-#ifdef LDAP_X_TXN
- if( rs->sr_err == LDAP_X_TXN_SPECIFY_OKAY ) {
- /* skip cleanup */
- return rs->sr_err;
- }
-#endif
-
-cleanup:
- op->o_tmpfree( op->o_req_dn.bv_val, op->o_tmpmemctx );
- op->o_tmpfree( op->o_req_ndn.bv_val, op->o_tmpmemctx );
- if ( op->orm_modlist != NULL ) slap_mods_free( op->orm_modlist, 1 );
-
- return rs->sr_err;
-}
-
-int
-fe_op_modify( Operation *op, SlapReply *rs )
-{
#ifdef LDAP_DEBUG
- Modifications *tmp;
-#endif
- int manageDSAit;
- BackendDB *op_be, *bd = op->o_bd;
- char textbuf[ SLAP_TEXT_BUFLEN ];
- size_t textlen = sizeof( textbuf );
-
- if ( BER_BVISEMPTY( &op->o_req_ndn ) ) {
- Debug( LDAP_DEBUG_ANY, "do_modify: root dse!\n", 0, 0, 0 );
-
- send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
- "modify upon the root DSE not supported" );
- goto cleanup;
-
- } else if ( bvmatch( &op->o_req_ndn, &frontendDB->be_schemandn ) ) {
- Debug( LDAP_DEBUG_ANY, "do_modify: subschema subentry!\n", 0, 0, 0 );
-
- send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
- "modification of subschema subentry not supported" );
- goto cleanup;
- }
-
-#ifdef LDAP_DEBUG
- Debug( LDAP_DEBUG_ARGS, "modifications:\n", 0, 0, 0 );
+ Debug( LDAP_DEBUG_ARGS, "%s modifications:\n",
+ op->o_log_prefix, 0, 0 );
for ( tmp = op->orm_modlist; tmp != NULL; tmp = tmp->sml_next ) {
Debug( LDAP_DEBUG_ARGS, "\t%s: %s\n",
}
#endif /* LDAP_DEBUG */
- manageDSAit = get_manageDSAit( op );
+ rs->sr_err = slap_mods_check( op, op->orm_modlist,
+ &rs->sr_text, textbuf, textlen, NULL );
+
+ if ( rs->sr_err != LDAP_SUCCESS ) {
+ send_ldap_result( op, rs );
+ goto cleanup;
+ }
+
+ op->o_bd = frontendDB;
+ rs->sr_err = frontendDB->be_modify( op, rs );
+
+#ifdef LDAP_X_TXN
+ if( rs->sr_err == LDAP_X_TXN_SPECIFY_OKAY ) {
+ /* skip cleanup */
+ return rs->sr_err;
+ }
+#endif
+
+cleanup:
+ op->o_tmpfree( op->o_req_dn.bv_val, op->o_tmpmemctx );
+ op->o_tmpfree( op->o_req_ndn.bv_val, op->o_tmpmemctx );
+ if ( op->orm_modlist != NULL ) slap_mods_free( op->orm_modlist, 1 );
+
+ return rs->sr_err;
+}
+
+int
+fe_op_modify( Operation *op, SlapReply *rs )
+{
+ BackendDB *op_be, *bd = op->o_bd;
+ char textbuf[ SLAP_TEXT_BUFLEN ];
+ size_t textlen = sizeof( textbuf );
+
+ if ( BER_BVISEMPTY( &op->o_req_ndn ) ) {
+ Debug( LDAP_DEBUG_ANY, "%s do_modify: root dse!\n",
+ op->o_log_prefix, 0, 0 );
+ send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
+ "modify upon the root DSE not supported" );
+ goto cleanup;
+
+ } else if ( bvmatch( &op->o_req_ndn, &frontendDB->be_schemandn ) ) {
+ Debug( LDAP_DEBUG_ANY, "%s do_modify: subschema subentry!\n",
+ op->o_log_prefix, 0, 0 );
+ send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
+ "modification of subschema subentry not supported" );
+ goto cleanup;
+ }
/*
* We could be serving multiple database backends. Select the
* appropriate one, or send a referral to our "referral server"
* if we don't hold it.
*/
- op->o_bd = select_backend( &op->o_req_ndn, manageDSAit, 1 );
+ op->o_bd = select_backend( &op->o_req_ndn, 1 );
if ( op->o_bd == NULL ) {
op->o_bd = bd;
rs->sr_ref = referral_rewrite( default_referral,
/* If we've got a glued backend, check the real backend */
op_be = op->o_bd;
if ( SLAP_GLUE_INSTANCE( op->o_bd )) {
- op->o_bd = select_backend( &op->o_req_ndn, manageDSAit, 0 );
+ op->o_bd = select_backend( &op->o_req_ndn, 0 );
}
/* check restrictions */
*/
if ( !SLAP_SINGLE_SHADOW(op->o_bd) || repl_user ) {
int update = !BER_BVISEMPTY( &op->o_bd->be_update_ndn );
- slap_callback cb = { NULL, slap_replog_cb, NULL, NULL };
op->o_bd = op_be;
goto cleanup;
}
}
-
- if ( !repl_user ) {
- /* but multimaster slapd logs only the ones
- * not from a replicator user */
- cb.sc_next = op->o_callback;
- op->o_callback = &cb;
- }
op->o_bd->be_modify( op, rs );
} else { /* send a referral */
MatchingRule *mr = ad->ad_type->sat_equality;
int istack[sizeof(int)*16];
- int i,j,k,l,ir,jstack, rc, match, *ix, itmp;
+ int i, j, k, l, ir, jstack, match, *ix, itmp;
struct berval a, *cv;
/* If PRESERVE_ORDER is defined only the index array is sorted; the
timestamp.bv_val = timebuf;
for ( modtail = modsp; *modtail; modtail = &(*modtail)->sml_next ) {
if ( (*modtail)->sml_op != LDAP_MOD_ADD &&
+ (*modtail)->sml_op != SLAP_MOD_SOFTADD &&
(*modtail)->sml_op != LDAP_MOD_REPLACE )
{
continue;
ber_tag_t tag;
ber_len_t len;
char *last;
- Modifications **modtail = &ms->rs_modlist;
+ Modifications **modtail = &ms->rs_mods.rs_modlist;
- ms->rs_modlist = NULL;
+ ms->rs_mods.rs_modlist = NULL;
ms->rs_increment = 0;
rs->sr_err = LDAP_SUCCESS;
switch( mop ) {
case LDAP_MOD_ADD:
if ( mod->sml_values == NULL ) {
- Debug( LDAP_DEBUG_ANY, "slap_parse_modlist: "
- "modify/add operation (%ld) requires values\n",
- (long) mop, 0, 0 );
-
rs->sr_text = "modify/add operation requires values";
rs->sr_err = LDAP_PROTOCOL_ERROR;
goto done;
if( op->o_protocol >= LDAP_VERSION3 ) {
ms->rs_increment++;
if ( mod->sml_values == NULL ) {
- Debug( LDAP_DEBUG_ANY, "slap_parse_modlist: "
- "modify/increment operation (%ld) requires value\n",
- (long) mop, 0, 0 );
-
rs->sr_text = "modify/increment operation requires value";
rs->sr_err = LDAP_PROTOCOL_ERROR;
goto done;
}
if ( !BER_BVISNULL( &mod->sml_values[ 1 ] ) ) {
- Debug( LDAP_DEBUG_ANY, "slap_parse_modlist: modify/increment "
- "operation (%ld) requires single value\n",
- (long) mop, 0, 0 );
-
rs->sr_text = "modify/increment operation requires single value";
rs->sr_err = LDAP_PROTOCOL_ERROR;
goto done;
/* fall thru */
default:
- Debug( LDAP_DEBUG_ANY, "slap_parse_modlist: "
- "unrecognized modify operation (%ld)\n",
- (long) mop, 0, 0 );
-
rs->sr_text = "unrecognized modify operation";
rs->sr_err = LDAP_PROTOCOL_ERROR;
goto done;
done:
if ( rs->sr_err != LDAP_SUCCESS ) {
- slap_mods_free( ms->rs_modlist, 1 );
- ms->rs_modlist = NULL;
+ slap_mods_free( ms->rs_mods.rs_modlist, 1 );
+ ms->rs_mods.rs_modlist = NULL;
ms->rs_increment = 0;
}
ber_len_t length;
- Debug( LDAP_DEBUG_TRACE, "do_modrdn\n", 0, 0, 0 );
-
-
+ Debug( LDAP_DEBUG_TRACE, "%s do_modrdn\n",
+ op->o_log_prefix, 0, 0 );
/*
* Parse the modrdn request. It looks like this:
*
if ( ber_scanf( op->o_ber, "{mmb", &dn, &newrdn, &deloldrdn )
== LBER_ERROR )
{
- Debug( LDAP_DEBUG_ANY, "ber_scanf failed\n", 0, 0, 0 );
-
+ Debug( LDAP_DEBUG_ANY, "%s do_modrdn: ber_scanf failed\n",
+ op->o_log_prefix, 0, 0 );
send_ldap_discon( op, rs, LDAP_PROTOCOL_ERROR, "decoding error" );
return SLAPD_DISCONNECT;
}
if ( ber_peek_tag( op->o_ber, &length ) == LDAP_TAG_NEWSUPERIOR ) {
if ( op->o_protocol < LDAP_VERSION3 ) {
- /* Conection record indicates v2 but field
+ /* Connection record indicates v2 but field
* newSuperior is present: report error.
*/
Debug( LDAP_DEBUG_ANY,
- "modrdn(v2): invalid field newSuperior!\n",
- 0, 0, 0 );
+ "%s do_modrdn: newSuperior requires LDAPv3\n",
+ op->o_log_prefix, 0, 0 );
send_ldap_discon( op, rs,
LDAP_PROTOCOL_ERROR, "newSuperior requires LDAPv3" );
if ( ber_scanf( op->o_ber, "m", &newSuperior )
== LBER_ERROR ) {
- Debug( LDAP_DEBUG_ANY, "ber_scanf(\"m\") failed\n",
- 0, 0, 0 );
+ Debug( LDAP_DEBUG_ANY, "%s do_modrdn: ber_scanf(\"m\") failed\n",
+ op->o_log_prefix, 0, 0 );
send_ldap_discon( op, rs,
LDAP_PROTOCOL_ERROR, "decoding error" );
newSuperior.bv_len ? newSuperior.bv_val : "" );
if ( ber_scanf( op->o_ber, /*{*/ "}") == LBER_ERROR ) {
- Debug( LDAP_DEBUG_ANY, "do_modrdn: ber_scanf failed\n", 0, 0, 0 );
-
+ Debug( LDAP_DEBUG_ANY, "%s do_modrdn: ber_scanf failed\n",
+ op->o_log_prefix, 0, 0 );
send_ldap_discon( op, rs,
LDAP_PROTOCOL_ERROR, "decoding error" );
rs->sr_err = SLAPD_DISCONNECT;
}
if( get_ctrls( op, rs, 1 ) != LDAP_SUCCESS ) {
- Debug( LDAP_DEBUG_ANY, "do_modrdn: get_ctrls failed\n", 0, 0, 0 );
-
+ Debug( LDAP_DEBUG_ANY, "%s do_modrdn: get_ctrls failed\n",
+ op->o_log_prefix, 0, 0 );
/* get_ctrls has sent results. Now clean up. */
goto cleanup;
}
rs->sr_err = dnPrettyNormal( NULL, &dn, &op->o_req_dn, &op->o_req_ndn, op->o_tmpmemctx );
if( rs->sr_err != LDAP_SUCCESS ) {
- Debug( LDAP_DEBUG_ANY,
- "do_modrdn: invalid dn (%s)\n", dn.bv_val, 0, 0 );
+ Debug( LDAP_DEBUG_ANY, "%s do_modrdn: invalid dn (%s)\n",
+ op->o_log_prefix, dn.bv_val, 0 );
send_ldap_error( op, rs, LDAP_INVALID_DN_SYNTAX, "invalid DN" );
goto cleanup;
}
rs->sr_err = dnPrettyNormal( NULL, &newrdn, &op->orr_newrdn, &op->orr_nnewrdn, op->o_tmpmemctx );
if( rs->sr_err != LDAP_SUCCESS ) {
- Debug( LDAP_DEBUG_ANY,
- "do_modrdn: invalid newrdn (%s)\n", newrdn.bv_val, 0, 0 );
+ Debug( LDAP_DEBUG_ANY, "%s do_modrdn: invalid newrdn (%s)\n",
+ op->o_log_prefix, newrdn.bv_val, 0 );
send_ldap_error( op, rs, LDAP_INVALID_DN_SYNTAX, "invalid new RDN" );
goto cleanup;
}
if( rdn_validate( &op->orr_newrdn ) != LDAP_SUCCESS ) {
- Debug( LDAP_DEBUG_ANY, "do_modrdn: invalid rdn (%s)\n",
- op->orr_newrdn.bv_val, 0, 0 );
-
+ Debug( LDAP_DEBUG_ANY, "%s do_modrdn: invalid rdn (%s)\n",
+ op->o_log_prefix, op->orr_newrdn.bv_val, 0 );
send_ldap_error( op, rs, LDAP_INVALID_DN_SYNTAX, "invalid new RDN" );
goto cleanup;
}
&nnewSuperior, op->o_tmpmemctx );
if( rs->sr_err != LDAP_SUCCESS ) {
Debug( LDAP_DEBUG_ANY,
- "do_modrdn: invalid newSuperior (%s)\n",
- newSuperior.bv_val, 0, 0 );
+ "%s do_modrdn: invalid newSuperior (%s)\n",
+ op->o_log_prefix, newSuperior.bv_val, 0 );
send_ldap_error( op, rs, LDAP_INVALID_DN_SYNTAX, "invalid newSuperior" );
goto cleanup;
}
}
+ Statslog( LDAP_DEBUG_STATS, "%s MODRDN dn=\"%s\"\n",
+ op->o_log_prefix, op->o_req_dn.bv_val, 0, 0, 0 );
+
op->orr_deleteoldrdn = deloldrdn;
op->orr_modlist = NULL;
fe_op_modrdn( Operation *op, SlapReply *rs )
{
Backend *newSuperior_be = NULL;
- int manageDSAit;
struct berval pdn = BER_BVNULL;
BackendDB *op_be, *bd = op->o_bd;
if( op->o_req_ndn.bv_len == 0 ) {
- Debug( LDAP_DEBUG_ANY, "do_modrdn: root dse!\n", 0, 0, 0 );
-
+ Debug( LDAP_DEBUG_ANY, "%s do_modrdn: root dse!\n",
+ op->o_log_prefix, 0, 0 );
send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
"cannot rename the root DSE" );
goto cleanup;
} else if ( bvmatch( &op->o_req_ndn, &frontendDB->be_schemandn ) ) {
- Debug( LDAP_DEBUG_ANY, "do_modrdn: subschema subentry: %s (%ld)\n",
- frontendDB->be_schemandn.bv_val, (long)frontendDB->be_schemandn.bv_len, 0 );
+ Debug( LDAP_DEBUG_ANY, "%s do_modrdn: subschema subentry: %s (%ld)\n",
+ op->o_log_prefix, frontendDB->be_schemandn.bv_val, (long)frontendDB->be_schemandn.bv_len );
send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
"cannot rename subschema subentry" );
goto cleanup;
}
- Statslog( LDAP_DEBUG_STATS, "%s MODRDN dn=\"%s\"\n",
- op->o_log_prefix, op->o_req_dn.bv_val, 0, 0, 0 );
-
- manageDSAit = get_manageDSAit( op );
-
/*
* We could be serving multiple database backends. Select the
* appropriate one, or send a referral to our "referral server"
* if we don't hold it.
*/
- op->o_bd = select_backend( &op->o_req_ndn, manageDSAit, 1 );
+ op->o_bd = select_backend( &op->o_req_ndn, 1 );
if ( op->o_bd == NULL ) {
op->o_bd = bd;
rs->sr_ref = referral_rewrite( default_referral,
/* If we've got a glued backend, check the real backend */
op_be = op->o_bd;
if ( SLAP_GLUE_INSTANCE( op->o_bd )) {
- op->o_bd = select_backend( &op->o_req_ndn, manageDSAit, 0 );
+ op->o_bd = select_backend( &op->o_req_ndn, 0 );
}
/* check restrictions */
* the same backend, otherwise we return an error.
*/
if( op->orr_newSup ) {
- newSuperior_be = select_backend( op->orr_nnewSup, 0, 0 );
+ newSuperior_be = select_backend( op->orr_nnewSup, 0 );
if ( newSuperior_be != op->o_bd ) {
/* newSuperior is in different backend */
int repl_user = be_isupdate( op );
if ( !SLAP_SINGLE_SHADOW(op->o_bd) || repl_user )
{
- slap_callback cb = { NULL, slap_replog_cb, NULL, NULL };
-
op->o_bd = op_be;
-
- if ( !op->o_bd->be_update_ndn.bv_len || !repl_user )
- {
- cb.sc_next = op->o_callback;
- op->o_callback = &cb;
- }
op->o_bd->be_modrdn( op, rs );
if ( op->o_bd->be_delete ) {
}
}
op->o_managedsait = org_managedsait;
- op->o_dn = org_dn;
+ op->o_dn = org_dn;
op->o_ndn = org_ndn;
op->o_req_dn = org_req_dn;
op->o_req_ndn = org_req_ndn;
if ( ldap_bv2rdn_x( &op->oq_modrdn.rs_newrdn, &new_rdn,
(char **)&rs->sr_text, LDAP_DN_FORMAT_LDAP, op->o_tmpmemctx ) ) {
Debug( LDAP_DEBUG_TRACE,
- "slap_modrdn2mods: can't figure out "
- "type(s)/value(s) of newrdn\n", 0, 0, 0 );
+ "%s slap_modrdn2mods: can't figure out "
+ "type(s)/value(s) of newrdn\n",
+ op->o_log_prefix, 0, 0 );
rs->sr_err = LDAP_INVALID_DN_SYNTAX;
rs->sr_text = "unknown type(s) used in RDN";
goto done;
if ( ldap_bv2rdn_x( &op->o_req_dn, &old_rdn,
(char **)&rs->sr_text, LDAP_DN_FORMAT_LDAP, op->o_tmpmemctx ) ) {
Debug( LDAP_DEBUG_TRACE,
- "slap_modrdn2mods: can't figure out "
- "type(s)/value(s) of oldrdn\n", 0, 0, 0 );
+ "%s slap_modrdn2mods: can't figure out "
+ "type(s)/value(s) of oldrdn\n",
+ op->o_log_prefix, 0, 0 );
rs->sr_err = LDAP_OTHER;
rs->sr_text = "cannot parse RDN from old DN";
goto done;
if ( rs->sr_err != LDAP_SUCCESS ) {
Debug( LDAP_DEBUG_TRACE,
- "slap_modrdn2mods: %s: %s (new)\n",
+ "%s slap_modrdn2mods: %s: %s (new)\n",
+ op->o_log_prefix,
rs->sr_text,
- new_rdn[ a_cnt ]->la_attr.bv_val, 0 );
+ new_rdn[ a_cnt ]->la_attr.bv_val );
goto done;
}
rs->sr_err = slap_bv2ad( &old_rdn[d_cnt]->la_attr, &desc, &rs->sr_text );
if ( rs->sr_err != LDAP_SUCCESS ) {
Debug( LDAP_DEBUG_TRACE,
- "slap_modrdn2mods: %s: %s (old)\n",
+ "%s slap_modrdn2mods: %s: %s (old)\n",
+ op->o_log_prefix,
rs->sr_text,
- old_rdn[d_cnt]->la_attr.bv_val,
- 0 );
+ old_rdn[d_cnt]->la_attr.bv_val );
goto done;
}
return -1;
}
- return 0;
+
+ return module_path( LDAP_MODULEDIR );
}
int module_kill (void)
};
static Avlnode *mr_index = NULL;
-static LDAP_SLIST_HEAD(MRList, slap_matching_rule) mr_list
+static LDAP_SLIST_HEAD(MRList, MatchingRule) mr_list
= LDAP_SLIST_HEAD_INITIALIZER(&mr_list);
-static LDAP_SLIST_HEAD(MRUList, slap_matching_rule_use) mru_list
+static LDAP_SLIST_HEAD(MRUList, MatchingRuleUse) mru_list
= LDAP_SLIST_HEAD_INITIALIZER(&mru_list);
static int
return 0;
}
+int
+mr_make_syntax_compat_with_mr(
+ Syntax *syn,
+ MatchingRule *mr )
+{
+ int n = 0;
+
+ assert( syn != NULL );
+ assert( mr != NULL );
+
+ if ( mr->smr_compat_syntaxes ) {
+ /* count esisting */
+ for ( n = 0;
+ mr->smr_compat_syntaxes[ n ];
+ n++ )
+ {
+ if ( mr->smr_compat_syntaxes[ n ] == syn ) {
+ /* already compatible; mmmmh... */
+ return 1;
+ }
+ }
+ }
+
+ mr->smr_compat_syntaxes = ch_realloc(
+ mr->smr_compat_syntaxes,
+ sizeof( Syntax * )*(n + 2) );
+ mr->smr_compat_syntaxes[ n ] = syn;
+ mr->smr_compat_syntaxes[ n + 1 ] = NULL;
+
+ return 0;
+}
+
+int
+mr_make_syntax_compat_with_mrs(
+ const char *syntax,
+ char *const *mrs )
+{
+ int r, rc = 0;
+ Syntax *syn;
+
+ assert( syntax != NULL );
+ assert( mrs != NULL );
+
+ syn = syn_find( syntax );
+ if ( syn == NULL ) {
+ return -1;
+ }
+
+ for ( r = 0; mrs[ r ] != NULL; r++ ) {
+ MatchingRule *mr = mr_find( mrs[ r ] );
+ if ( mr == NULL ) {
+ /* matchingRule not found -- ignore by now */
+ continue;
+ }
+
+ rc += mr_make_syntax_compat_with_mr( syn, mr );
+ }
+
+ return rc;
+}
+
int
mr_add(
LDAPMatchingRule *mr,
LDAP_SLIST_FOREACH( mr, &mr_list, smr_next ) {
AttributeType *at;
- MatchingRuleUse mru_storage, *mru = &mru_storage;
+ MatchingRuleUse mru_storage = { 0 },
+ *mru = &mru_storage;
char **applies_oids = NULL;
continue;
}
- memset( mru, 0, sizeof( MatchingRuleUse ) );
-
/*
* Note: we're using the same values of the corresponding
* MatchingRule structure; maybe we'd copy them ...
return( 0 );
}
-int mr_usable_with_at(
- MatchingRule *mr,
- AttributeType *at )
+int
+mr_usable_with_at(
+ MatchingRule *mr,
+ AttributeType *at )
{
- if( mr->smr_usage & SLAP_MR_EXT && (
+ if ( ( mr->smr_usage & SLAP_MR_EXT ) && (
mr->smr_syntax == at->sat_syntax ||
- mr == at->sat_equality || mr == at->sat_approx ) )
+ mr == at->sat_equality ||
+ mr == at->sat_approx ||
+ syn_is_sup( at->sat_syntax, mr->smr_syntax ) ) )
{
return 1;
}
sup->soc_oid, sub->soc_oid, sup == sub );
#endif
- if( sup == sub ) {
+ if ( sup == sub ) {
return 1;
}
- if( sub->soc_sups == NULL ) {
+ if ( sub->soc_sups == NULL ) {
return 0;
}
- for( i=0; sub->soc_sups[i] != NULL; i++ ) {
- if( is_object_subclass( sup, sub->soc_sups[i] ) ) {
+ for ( i = 0; sub->soc_sups[i] != NULL; i++ ) {
+ if ( is_object_subclass( sup, sub->soc_sups[i] ) ) {
return 1;
}
}
assert( !( e == NULL || oc == NULL ) );
assert( ( flags & SLAP_OCF_MASK ) != SLAP_OCF_MASK );
- if( e == NULL || oc == NULL ) {
+ if ( e == NULL || oc == NULL ) {
return 0;
}
- if( flags == SLAP_OCF_SET_FLAGS && ( e->e_ocflags & SLAP_OC__END ) )
+ if ( flags == SLAP_OCF_SET_FLAGS && ( e->e_ocflags & SLAP_OC__END ) )
{
/* flags are set, use them */
return (e->e_ocflags & oc->soc_flags & SLAP_OC__MASK) != 0;
* find objectClass attribute
*/
attr = attr_find( e->e_attrs, slap_schema.si_ad_objectClass );
- if( attr == NULL ) {
+ if ( attr == NULL ) {
/* no objectClass attribute */
Debug( LDAP_DEBUG_ANY, "is_entry_objectclass(\"%s\", \"%s\") "
"no objectClass attribute\n",
return 0;
}
- for( bv=attr->a_vals; bv->bv_val; bv++ ) {
+ for ( bv = attr->a_vals; bv->bv_val; bv++ ) {
ObjectClass *objectClass = oc_bvfind( bv );
if ( objectClass == NULL ) {
static Avlnode *oc_index = NULL;
static Avlnode *oc_cache = NULL;
-static LDAP_STAILQ_HEAD(OCList, slap_object_class) oc_list
+static LDAP_STAILQ_HEAD(OCList, ObjectClass) oc_list
= LDAP_STAILQ_HEAD_INITIALIZER(oc_list);
ObjectClass *oc_sys_tail;
return( NULL );
}
-static LDAP_STAILQ_HEAD(OCUList, slap_object_class) oc_undef_list
+static LDAP_STAILQ_HEAD(OCUList, ObjectClass) oc_undef_list
= LDAP_STAILQ_HEAD_INITIALIZER(oc_undef_list);
ObjectClass *
{
oc->soc_flags |= SLAP_OC_DELETED;
- LDAP_STAILQ_REMOVE(&oc_list,oc,slap_object_class,soc_next);
+ LDAP_STAILQ_REMOVE(&oc_list, oc, ObjectClass, soc_next);
oc_delete_names( oc );
}
#include "lutil.h"
#include "config.h"
-static LDAP_STAILQ_HEAD(OidMacroList, slap_oid_macro) om_list
+static LDAP_STAILQ_HEAD(OidMacroList, OidMacro) om_list
= LDAP_STAILQ_HEAD_INITIALIZER(om_list);
OidMacro *om_sys_tail;
oidv = oidm_find( c->argv[2] );
if( !oidv ) {
- snprintf( c->msg, sizeof( c->msg ),
+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
"%s: OID %s not recognized",
c->argv[0], c->argv[2] );
Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
- "%s %s\n", c->log, c->msg, 0 );
+ "%s %s\n", c->log, c->cr_msg, 0 );
return 1;
}
oid = oidm_find( c->argv[1] );
if( oid != NULL ) {
int rc;
- snprintf( c->msg, sizeof( c->msg ),
+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
"%s: \"%s\" previously defined \"%s\"",
c->argv[0], c->argv[1], oid );
Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
- "%s %s\n", c->log, c->msg, 0 );
+ "%s %s\n", c->log, c->cr_msg, 0 );
/* Allow duplicate if the definition is identical */
rc = strcmp( oid, oidv ) != 0;
SLAP_FREE( oid );
om = (OidMacro *) SLAP_CALLOC( sizeof(OidMacro), 1 );
if( om == NULL ) {
- snprintf( c->msg, sizeof( c->msg ),
+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
"%s: SLAP_CALLOC failed", c->argv[0] );
Debug( LDAP_DEBUG_ANY,
- "%s %s\n", c->log, c->msg, 0 );
+ "%s %s\n", c->log, c->cr_msg, 0 );
if ( oidv != c->argv[2] )
SLAP_FREE( oidv );
return 1;
#endif
static ldap_pvt_thread_mutex_t slap_op_mutex;
-static LDAP_STAILQ_HEAD(s_o, slap_op) slap_free_ops;
+static LDAP_STAILQ_HEAD(s_o, Operation) slap_free_ops;
static time_t last_time;
static int last_incr;
void
slap_op_free( Operation *op )
{
+ OperationBuffer *opbuf;
+
assert( LDAP_STAILQ_NEXT(op, o_next) == NULL );
if ( op->o_ber != NULL ) {
#endif /* defined( LDAP_SLAPI ) */
- memset( op, 0, sizeof(Operation) + sizeof(Opheader) + SLAP_MAX_CIDS * sizeof(void *) );
- op->o_hdr = (Opheader *)(op+1);
- op->o_controls = (void **)(op->o_hdr+1);
+ opbuf = (OperationBuffer *) op;
+ memset( opbuf, 0, sizeof(*opbuf) );
+ op->o_hdr = &opbuf->ob_hdr;
+ op->o_controls = opbuf->ob_controls;
ldap_pvt_thread_mutex_lock( &slap_op_mutex );
LDAP_STAILQ_INSERT_HEAD( &slap_free_ops, op, o_next );
ldap_pvt_thread_mutex_unlock( &slap_op_mutex );
if (!op) {
- op = (Operation *) ch_calloc( 1, sizeof(Operation)
- + sizeof(Opheader) + SLAP_MAX_CIDS * sizeof(void *) );
- op->o_hdr = (Opheader *)(op + 1);
- op->o_controls = (void **)(op->o_hdr+1);
+ op = (Operation *) ch_calloc( 1, sizeof(OperationBuffer) );
+ op->o_hdr = &((OperationBuffer *) op)->ob_hdr;
+ op->o_controls = ((OperationBuffer *) op)->ob_controls;
}
op->o_ber = ber;
dds.c \
dyngroup.c \
dynlist.c \
+ memberof.c \
pcache.c \
ppolicy.c \
refint.c \
translucent.c \
unique.c \
valsort.c
-OBJS = overlays.o \
- statover.o \
- @SLAPD_STATIC_OVERLAYS@
+OBJS = statover.o \
+ @SLAPD_STATIC_OVERLAYS@ \
+ overlays.o
# Add here the objs that are needed by overlays, but do not make it
# into SLAPD_STATIC_OVERLAYS...
dynlist.la : dynlist.lo
$(LTLINK_MOD) -module -o $@ dynlist.lo version.lo $(LINK_LIBS)
+memberof.la : memberof.lo
+ $(LTLINK_MOD) -module -o $@ memberof.lo version.lo $(LINK_LIBS)
+
pcache.la : pcache.lo
$(LTLINK_MOD) -module -o $@ pcache.lo version.lo $(LINK_LIBS)
#define LOG_SCHEMA_AT LOG_SCHEMA_ROOT ".1"
#define LOG_SCHEMA_OC LOG_SCHEMA_ROOT ".2"
+#define LOG_SCHEMA_SYN LOG_SCHEMA_ROOT ".3"
static AttributeDescription *ad_reqDN, *ad_reqStart, *ad_reqEnd, *ad_reqType,
*ad_reqSession, *ad_reqResult, *ad_reqAuthzID, *ad_reqControls,
*ad_reqId, *ad_reqMessage, *ad_reqVersion, *ad_reqDerefAliases,
*ad_reqReferral, *ad_reqOld, *ad_auditContext;
+static int
+logSchemaControlValidate(
+ Syntax *syntax,
+ struct berval *val );
+
+char *mrControl[] = {
+ "objectIdentifierFirstComponentMatch",
+ NULL
+};
+
+static struct {
+ char *oid;
+ slap_syntax_defs_rec syn;
+ char **mrs;
+} lsyntaxes[] = {
+ { LOG_SCHEMA_SYN ".1" ,
+ { "( " LOG_SCHEMA_SYN ".1 DESC 'Control' )",
+ SLAP_SYNTAX_HIDE,
+ NULL,
+ logSchemaControlValidate,
+ NULL },
+ mrControl },
+ { NULL }
+};
+
static struct {
char *at;
AttributeDescription **ad;
"SUP labeledURI )", &ad_reqReferral },
{ "( " LOG_SCHEMA_AT ".10 NAME 'reqControls' "
"DESC 'Request controls' "
- "SYNTAX OMsOctetString )", &ad_reqControls },
+ "EQUALITY objectIdentifierFirstComponentMatch "
+ "SYNTAX " LOG_SCHEMA_SYN ".1 "
+ "X-ORDERED 'VALUES' )", &ad_reqControls },
{ "( " LOG_SCHEMA_AT ".11 NAME 'reqRespControls' "
"DESC 'Response controls of request' "
- "SYNTAX OMsOctetString )", &ad_reqRespControls },
+ "EQUALITY objectIdentifierFirstComponentMatch "
+ "SYNTAX " LOG_SCHEMA_SYN ".1 "
+ "X-ORDERED 'VALUES' )", &ad_reqRespControls },
{ "( " LOG_SCHEMA_AT ".12 NAME 'reqId' "
"DESC 'ID of Request to Abandon' "
"EQUALITY integerMatch "
Connection conn = {0};
OperationBuffer opbuf;
- Operation *op = (Operation *) &opbuf;
+ Operation *op;
SlapReply rs = {REP_RESULT};
slap_callback cb = { NULL, log_old_lookup, NULL, NULL };
Filter f;
char csnbuf[LDAP_LUTIL_CSNSTR_BUFSIZE];
time_t old = slap_get_time();
- connection_fake_init( &conn, op, ctx );
+ connection_fake_init( &conn, &opbuf, ctx );
+ op = &opbuf.ob_op;
f.f_choice = LDAP_FILTER_LE;
f.f_ava = &ava;
value_add_one( &c->rvalue_vals, li->li_db->be_suffix );
value_add_one( &c->rvalue_nvals, li->li_db->be_nsuffix );
} else {
- snprintf( c->msg, sizeof( c->msg ),
+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
"accesslog: \"logdb <suffix>\" must be specified" );
Debug( LDAP_DEBUG_ANY, "%s: %s \"%s\"\n",
- c->log, c->msg, c->value_dn.bv_val );
+ c->log, c->cr_msg, c->value_dn.bv_val );
rc = 1;
break;
}
switch( c->type ) {
case LOG_DB:
if ( CONFIG_ONLINE_ADD( c )) {
- li->li_db = select_backend( &c->value_ndn, 0, 0 );
+ li->li_db = select_backend( &c->value_ndn, 0 );
if ( !li->li_db ) {
- snprintf( c->msg, sizeof( c->msg ),
+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
"<%s> no matching backend found for suffix",
c->argv[0] );
Debug( LDAP_DEBUG_ANY, "%s: %s \"%s\"\n",
- c->log, c->msg, c->value_dn.bv_val );
+ c->log, c->cr_msg, c->value_dn.bv_val );
rc = 1;
}
ch_free( c->value_ndn.bv_val );
case LOG_OLD:
li->li_oldf = str2filter( c->argv[1] );
if ( !li->li_oldf ) {
- sprintf( c->msg, "bad filter!" );
+ sprintf( c->cr_msg, "bad filter!" );
rc = 1;
}
break;
la->next = li->li_oldattrs;
li->li_oldattrs = la;
} else {
- snprintf( c->msg, sizeof( c->msg ), "%s <%s>: %s",
+ snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s <%s>: %s",
c->argv[0], c->argv[i], text );
Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
- "%s: %s\n", c->log, c->msg, 0 );
+ "%s: %s\n", c->log, c->cr_msg, 0 );
rc = ARG_BAD_CONF;
break;
}
return rc;
}
-static Entry *accesslog_entry( Operation *op, int logop,
+static int
+logSchemaControlValidate(
+ Syntax *syntax,
+ struct berval *valp )
+{
+ struct berval val, bv;
+ int i;
+ int rc = LDAP_SUCCESS;
+
+ assert( valp != NULL );
+
+ val = *valp;
+
+ /* check minimal size */
+ if ( val.bv_len < STRLENOF( "{*}" ) ) {
+ return LDAP_INVALID_SYNTAX;
+ }
+
+ val.bv_len--;
+
+ /* check SEQUENCE boundaries */
+ if ( val.bv_val[ 0 ] != '{' /*}*/ ||
+ val.bv_val[ val.bv_len ] != /*{*/ '}' )
+ {
+ return LDAP_INVALID_SYNTAX;
+ }
+
+ /* extract and check OID */
+ for ( i = 1; i < val.bv_len; i++ ) {
+ if ( !ASCII_SPACE( val.bv_val[ i ] ) ) {
+ break;
+ }
+ }
+
+ bv.bv_val = &val.bv_val[ i ];
+
+ for ( i++; i < val.bv_len; i++ ) {
+ if ( ASCII_SPACE( val.bv_val[ i ] ) )
+ {
+ break;
+ }
+ }
+
+ bv.bv_len = &val.bv_val[ i ] - bv.bv_val;
+
+ rc = numericoidValidate( NULL, &bv );
+ if ( rc != LDAP_SUCCESS ) {
+ return rc;
+ }
+
+ if ( i == val.bv_len ) {
+ return LDAP_SUCCESS;
+ }
+
+ if ( val.bv_val[ i ] != ' ' ) {
+ return LDAP_INVALID_SYNTAX;
+ }
+
+ for ( i++; i < val.bv_len; i++ ) {
+ if ( !ASCII_SPACE( val.bv_val[ i ] ) ) {
+ break;
+ }
+ }
+
+ if ( i == val.bv_len ) {
+ return LDAP_SUCCESS;
+ }
+
+ /* extract and check criticality */
+ if ( strncasecmp( &val.bv_val[ i ], "criticality ", STRLENOF( "criticality " ) ) == 0 )
+ {
+ i += STRLENOF( "criticality " );
+ for ( ; i < val.bv_len; i++ ) {
+ if ( !ASCII_SPACE( val.bv_val[ i ] ) ) {
+ break;
+ }
+ }
+
+ if ( i == val.bv_len ) {
+ return LDAP_INVALID_SYNTAX;
+ }
+
+ bv.bv_val = &val.bv_val[ i ];
+
+ for ( ; i < val.bv_len; i++ ) {
+ if ( ASCII_SPACE( val.bv_val[ i ] ) ) {
+ break;
+ }
+ }
+
+ bv.bv_len = &val.bv_val[ i ] - bv.bv_val;
+
+ if ( !bvmatch( &bv, &slap_true_bv ) && !bvmatch( &bv, &slap_false_bv ) )
+ {
+ return LDAP_INVALID_SYNTAX;
+ }
+
+ if ( i == val.bv_len ) {
+ return LDAP_SUCCESS;
+ }
+
+ if ( val.bv_val[ i ] != ' ' ) {
+ return LDAP_INVALID_SYNTAX;
+ }
+
+ for ( i++; i < val.bv_len; i++ ) {
+ if ( !ASCII_SPACE( val.bv_val[ i ] ) ) {
+ break;
+ }
+ }
+
+ if ( i == val.bv_len ) {
+ return LDAP_SUCCESS;
+ }
+ }
+
+ /* extract and check controlValue */
+ if ( strncasecmp( &val.bv_val[ i ], "controlValue ", STRLENOF( "controlValue " ) ) == 0 )
+ {
+ i += STRLENOF( "controlValue " );
+ for ( ; i < val.bv_len; i++ ) {
+ if ( !ASCII_SPACE( val.bv_val[ i ] ) ) {
+ break;
+ }
+ }
+
+ if ( i == val.bv_len ) {
+ return LDAP_INVALID_SYNTAX;
+ }
+
+ if ( val.bv_val[ i ] != '"' ) {
+ return LDAP_INVALID_SYNTAX;
+ }
+
+ for ( ; i < val.bv_len; i++ ) {
+ if ( val.bv_val[ i ] == '"' ) {
+ break;
+ }
+
+ if ( !ASCII_HEX( val.bv_val[ i ] ) ) {
+ return LDAP_INVALID_SYNTAX;
+ }
+ }
+
+ if ( val.bv_val[ i ] != '"' ) {
+ return LDAP_INVALID_SYNTAX;
+ }
+
+ for ( ; i < val.bv_len; i++ ) {
+ if ( !ASCII_SPACE( val.bv_val[ i ] ) ) {
+ break;
+ }
+ }
+
+ if ( i == val.bv_len ) {
+ return LDAP_SUCCESS;
+ }
+ }
+
+ return LDAP_INVALID_SYNTAX;
+}
+
+static int
+accesslog_ctrls(
+ LDAPControl **ctrls,
+ BerVarray *valsp,
+ BerVarray *nvalsp,
+ void *memctx )
+{
+ long i, rc = 0;
+
+ assert( valsp != NULL );
+ assert( ctrls != NULL );
+
+ *valsp = NULL;
+ *nvalsp = NULL;
+
+ for ( i = 0; ctrls[ i ] != NULL; i++ ) {
+ struct berval idx,
+ oid,
+ noid,
+ bv;
+ char *ptr,
+ buf[ 32 ];
+
+ if ( ctrls[ i ]->ldctl_oid == NULL ) {
+ return LDAP_PROTOCOL_ERROR;
+ }
+
+ idx.bv_len = snprintf( buf, sizeof( buf ), "{%ld}", i );
+ idx.bv_val = buf;
+
+ ber_str2bv( ctrls[ i ]->ldctl_oid, 0, 0, &oid );
+ noid.bv_len = idx.bv_len + oid.bv_len;
+ ptr = noid.bv_val = ber_memalloc_x( noid.bv_len + 1, memctx );
+ ptr = lutil_strcopy( ptr, idx.bv_val );
+ ptr = lutil_strcopy( ptr, oid.bv_val );
+
+ bv.bv_len = idx.bv_len + STRLENOF( "{}" ) + oid.bv_len;
+
+ if ( ctrls[ i ]->ldctl_iscritical ) {
+ bv.bv_len += STRLENOF( " criticality TRUE" );
+ }
+
+ if ( !BER_BVISNULL( &ctrls[ i ]->ldctl_value ) ) {
+ bv.bv_len += STRLENOF( " controlValue \"\"" )
+ + 2 * ctrls[ i ]->ldctl_value.bv_len;
+ }
+
+ ptr = bv.bv_val = ber_memalloc_x( bv.bv_len + 1, memctx );
+ if ( ptr == NULL ) {
+ ber_bvarray_free( *valsp );
+ *valsp = NULL;
+ ber_bvarray_free( *nvalsp );
+ *nvalsp = NULL;
+ return LDAP_OTHER;
+ }
+
+ ptr = lutil_strcopy( ptr, idx.bv_val );
+
+ *ptr++ = '{' /*}*/ ;
+ ptr = lutil_strcopy( ptr, oid.bv_val );
+
+ if ( ctrls[ i ]->ldctl_iscritical ) {
+ ptr = lutil_strcopy( ptr, " criticality TRUE" );
+ }
+
+ if ( !BER_BVISNULL( &ctrls[ i ]->ldctl_value ) ) {
+ int j;
+
+ ptr = lutil_strcopy( ptr, " controlValue \"" );
+ for ( j = 0; j < ctrls[ i ]->ldctl_value.bv_len; j++ )
+ {
+ unsigned char o;
+
+ o = ( ( ctrls[ i ]->ldctl_value.bv_val[ j ] >> 4 ) & 0xF );
+ if ( o < 10 ) {
+ *ptr++ = '0' + o;
+
+ } else {
+ *ptr++ = 'A' + o;
+ }
+
+ o = ( ctrls[ i ]->ldctl_value.bv_val[ j ] & 0xF );
+ if ( o < 10 ) {
+ *ptr++ = '0' + o;
+
+ } else {
+ *ptr++ = 'A' + o;
+ }
+ }
+
+ *ptr++ = '"';
+ }
+
+ *ptr++ = '}';
+ *ptr = '\0';
+
+ ber_bvarray_add_x( valsp, &bv, memctx );
+ ber_bvarray_add_x( nvalsp, &noid, memctx );
+ }
+
+ return rc;
+
+}
+
+static Entry *accesslog_entry( Operation *op, SlapReply *rs, int logop,
Operation *op2 ) {
slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
log_info *li = on->on_bi.bi_private;
rdn.bv_len = sprintf( rdn.bv_val, "%lu", op->o_connid );
attr_merge_one( e, ad_reqSession, &rdn, NULL );
- if ( BER_BVISNULL( &op->o_dn ))
+ if ( BER_BVISNULL( &op->o_dn ) ) {
attr_merge_one( e, ad_reqAuthzID, (struct berval *)&slap_empty_bv,
(struct berval *)&slap_empty_bv );
- else
+ } else {
attr_merge_one( e, ad_reqAuthzID, &op->o_dn, &op->o_ndn );
+ }
/* FIXME: need to add reqControls and reqRespControls */
+ if ( op->o_ctrls ) {
+ BerVarray vals = NULL,
+ nvals = NULL;
+
+ if ( accesslog_ctrls( op->o_ctrls, &vals, &nvals,
+ op->o_tmpmemctx ) == LDAP_SUCCESS && vals )
+ {
+ attr_merge( e, ad_reqControls, vals, nvals );
+ ber_bvarray_free_x( vals, op->o_tmpmemctx );
+ ber_bvarray_free_x( nvals, op->o_tmpmemctx );
+ }
+ }
+
+ if ( rs->sr_ctrls ) {
+ BerVarray vals = NULL,
+ nvals = NULL;
+
+ if ( accesslog_ctrls( rs->sr_ctrls, &vals, &nvals,
+ op->o_tmpmemctx ) == LDAP_SUCCESS && vals )
+ {
+ attr_merge( e, ad_reqRespControls, vals, nvals );
+ ber_bvarray_free_x( vals, op->o_tmpmemctx );
+ ber_bvarray_free_x( nvals, op->o_tmpmemctx );
+ }
+
+ }
return e;
}
if ( li->li_success && rs->sr_err != LDAP_SUCCESS )
goto done;
- e = accesslog_entry( op, logop, &op2 );
+ e = accesslog_entry( op, rs, logop, &op2 );
attr_merge_one( e, ad_reqDN, &op->o_req_dn, &op->o_req_ndn );
if ( op->orb_method == LDAP_AUTH_SIMPLE ) {
attr_merge_one( e, ad_reqMethod, &simple, NULL );
} else {
- bv.bv_len = STRLENOF("SASL()") + op->orb_tmp_mech.bv_len;
+ bv.bv_len = STRLENOF("SASL()") + op->orb_mech.bv_len;
bv.bv_val = op->o_tmpalloc( bv.bv_len + 1, op->o_tmpmemctx );
ptr = lutil_strcopy( bv.bv_val, "SASL(" );
- ptr = lutil_strcopy( ptr, op->orb_tmp_mech.bv_val );
+ ptr = lutil_strcopy( ptr, op->orb_mech.bv_val );
*ptr++ = ')';
*ptr = '\0';
attr_merge_one( e, ad_reqMethod, &bv, NULL );
if ( !( li->li_ops & LOG_OP_UNBIND ))
return SLAP_CB_CONTINUE;
- e = accesslog_entry( op, LOG_EN_UNBIND, &op2 );
+ e = accesslog_entry( op, rs, LOG_EN_UNBIND, &op2 );
op2.o_hdr = op->o_hdr;
op2.o_tag = LDAP_REQ_ADD;
op2.o_bd = li->li_db;
if ( !op->o_time || !( li->li_ops & LOG_OP_ABANDON ))
return SLAP_CB_CONTINUE;
- e = accesslog_entry( op, LOG_EN_ABANDON, &op2 );
+ e = accesslog_entry( op, rs, LOG_EN_ABANDON, &op2 );
bv.bv_val = buf;
bv.bv_len = sprintf( buf, "%d", op->orn_msgid );
attr_merge_one( e, ad_reqId, &bv, NULL );
static int
accesslog_db_init(
- BackendDB *be
+ BackendDB *be,
+ ConfigReply *cr
)
{
slap_overinst *on = (slap_overinst *)be->bd_info;
static int
accesslog_db_destroy(
- BackendDB *be
+ BackendDB *be,
+ ConfigReply *cr
)
{
slap_overinst *on = (slap_overinst *)be->bd_info;
Connection conn = {0};
OperationBuffer opbuf;
- Operation *op = (Operation *) &opbuf;
+ Operation *op;
Entry *e;
int rc;
- connection_fake_init( &conn, op, ctx );
+ connection_fake_init( &conn, &opbuf, ctx );
+ op = &opbuf.ob_op;
op->o_bd = li->li_db;
op->o_dn = li->li_db->be_rootdn;
op->o_ndn = li->li_db->be_rootndn;
a = attr_find( e_ctx->e_attrs, slap_schema.si_ad_contextCSN );
if ( a ) {
- attr_merge( e, slap_schema.si_ad_entryCSN, a->a_vals, NULL );
- attr_merge( e, a->a_desc, a->a_vals, NULL );
+ /* FIXME: contextCSN could have multiple values!
+ * should select the one with the server's SID */
+ attr_merge_one( e, slap_schema.si_ad_entryCSN,
+ &a->a_vals[0], &a->a_nvals[0] );
+ attr_merge( e, a->a_desc, a->a_vals, a->a_nvals );
}
be_entry_release_rw( op, e_ctx, 0 );
}
static int
accesslog_db_open(
- BackendDB *be
+ BackendDB *be,
+ ConfigReply *cr
)
{
slap_overinst *on = (slap_overinst *)be->bd_info;
if ( !BER_BVISEMPTY( &li->li_db_suffix )) {
- li->li_db = select_backend( &li->li_db_suffix, 0, 0 );
+ li->li_db = select_backend( &li->li_db_suffix, 0 );
ch_free( li->li_db_suffix.bv_val );
BER_BVZERO( &li->li_db_suffix );
}
if ( rc ) return rc;
/* log schema integration */
+ for ( i=0; lsyntaxes[i].oid; i++ ) {
+ int code;
+
+ code = register_syntax( &lsyntaxes[ i ].syn );
+ if ( code != 0 ) {
+ Debug( LDAP_DEBUG_ANY,
+ "accesslog_init: register_syntax failed\n",
+ 0, 0, 0 );
+ return code;
+ }
+
+ if ( lsyntaxes[i].mrs != NULL ) {
+ code = mr_make_syntax_compat_with_mrs(
+ lsyntaxes[i].oid, lsyntaxes[i].mrs );
+ if ( code < 0 ) {
+ Debug( LDAP_DEBUG_ANY,
+ "accesslog_init: "
+ "mr_make_syntax_compat_with_mrs "
+ "failed\n",
+ 0, 0, 0 );
+ return code;
+ }
+ }
+ }
+
for ( i=0; lattrs[i].at; i++ ) {
int code;
code = register_at( lattrs[i].at, lattrs[i].ad, 0 );
if ( code ) {
Debug( LDAP_DEBUG_ANY,
- "accesslog_init: register_at failed\n", 0, 0, 0 );
+ "accesslog_init: register_at failed\n",
+ 0, 0, 0 );
return -1;
}
}
+
for ( i=0; locs[i].ot; i++ ) {
int code;
code = register_oc( locs[i].ot, locs[i].oc, 0 );
if ( code ) {
Debug( LDAP_DEBUG_ANY,
- "accesslog_init: register_oc failed\n", 0, 0, 0 );
+ "accesslog_init: register_oc failed\n",
+ 0, 0, 0 );
return -1;
}
}
static int
auditlog_db_init(
- BackendDB *be
+ BackendDB *be,
+ ConfigReply *cr
)
{
slap_overinst *on = (slap_overinst *)be->bd_info;
static int
auditlog_db_close(
- BackendDB *be
+ BackendDB *be,
+ ConfigReply *cr
)
{
slap_overinst *on = (slap_overinst *)be->bd_info;
static int
auditlog_db_destroy(
- BackendDB *be
+ BackendDB *be,
+ ConfigReply *cr
)
{
slap_overinst *on = (slap_overinst *)be->bd_info;
#include <ac/socket.h>
#include "slap.h"
-
+#include "config.h"
/* This is a cheap hack to implement a collective attribute.
*
AttributeDescription *ci_ad;
} collect_info;
+static int
+collect_cf( ConfigArgs *c )
+{
+ slap_overinst *on = (slap_overinst *)c->bi;
+ int rc = 1;
+
+ switch( c->op ) {
+ case SLAP_CONFIG_EMIT:
+ {
+ collect_info *ci;
+ for ( ci = on->on_bi.bi_private; ci; ci = ci->ci_next ) {
+ struct berval bv;
+
+ bv.bv_len = ci->ci_dn.bv_len + 3 +
+ ci->ci_ad->ad_cname.bv_len;
+ bv.bv_val = ch_malloc( bv.bv_len + 1 );
+ sprintf( bv.bv_val, "\"%s\" %s", ci->ci_dn.bv_val,
+ ci->ci_ad->ad_cname.bv_val );
+ ber_bvarray_add( &c->rvalue_vals, &bv );
+ rc = 0;
+ }
+ }
+ break;
+ case LDAP_MOD_DELETE:
+ if ( c->valx == -1 ) {
+ /* Delete entire attribute */
+ collect_info *ci;
+ while (( ci = on->on_bi.bi_private )) {
+ on->on_bi.bi_private = ci->ci_next;
+ ch_free( ci->ci_dn.bv_val );
+ ch_free( ci );
+ }
+ } else {
+ /* Delete just one value */
+ collect_info **cip, *ci;
+ int i;
+ cip = (collect_info **)&on->on_bi.bi_private;
+ for ( i=0; i <= c->valx; i++, cip = &ci->ci_next ) ci = *cip;
+ *cip = ci->ci_next;
+ ch_free( ci->ci_dn.bv_val );
+ ch_free( ci );
+ }
+ rc = 0;
+ break;
+ case SLAP_CONFIG_ADD:
+ case LDAP_MOD_ADD:
+ {
+ collect_info *ci;
+ struct berval bv, dn;
+ const char *text;
+ AttributeDescription *ad = NULL;
+
+ ber_str2bv( c->argv[1], 0, 0, &bv );
+ if ( dnNormalize( 0, NULL, NULL, &bv, &dn, NULL ) ) {
+ snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s invalid DN: \"%s\"",
+ c->argv[0], c->argv[1] );
+ Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
+ "%s: %s\n", c->log, c->cr_msg, 0 );
+ return ARG_BAD_CONF;
+ }
+ if ( slap_str2ad( c->argv[2], &ad, &text ) ) {
+ snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s attribute description unknown: \"%s\"",
+ c->argv[0], c->argv[2] );
+ Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
+ "%s: %s\n", c->log, c->cr_msg, 0 );
+ return ARG_BAD_CONF;
+ }
+
+ /* The on->on_bi.bi_private pointer can be used for
+ * anything this instance of the overlay needs.
+ */
+ ci = ch_malloc( sizeof( collect_info ));
+ ci->ci_ad = ad;
+ ci->ci_dn = dn;
+ ci->ci_next = on->on_bi.bi_private;
+ on->on_bi.bi_private = ci;
+ rc = 0;
+ }
+ }
+ return rc;
+}
+
+static ConfigTable collectcfg[] = {
+ { "collectinfo", "dn> <attribute", 3, 3, 0,
+ ARG_MAGIC, collect_cf,
+ "( OLcfgOvAt:19.1 NAME 'olcCollectInfo' "
+ "DESC 'DN of entry and attribute to distribute' "
+ "SYNTAX OMsDirectoryString )", NULL, NULL },
+ { NULL, NULL, 0, 0, 0, ARG_IGNORED }
+};
+
+static ConfigOCs collectocs[] = {
+ { "( OLcfgOvOc:19.1 "
+ "NAME 'olcCollectConfig' "
+ "DESC 'Collective Attribute configuration' "
+ "SUP olcOverlayConfig "
+ "MAY olcCollectInfo )",
+ Cft_Overlay, collectcfg },
+ { NULL, 0, NULL }
+};
+
+static int
+collect_destroy(
+ BackendDB *be,
+ ConfigReply *cr
+)
+{
+ slap_overinst *on = (slap_overinst *)be->bd_info;
+ collect_info *ci;
+
+ while (( ci = on->on_bi.bi_private )) {
+ on->on_bi.bi_private = ci->ci_next;
+ ch_free( ci->ci_dn.bv_val );
+ ch_free( ci );
+ }
+ return 0;
+}
+
static int
collect_response( Operation *op, SlapReply *rs )
{
* a search entry
*/
if ( ci && rs->sr_type == REP_SEARCH ) {
- Entry *new = NULL;
int rc;
op->o_bd->bd_info = (BackendInfo *)on->on_info;
BerVarray vals = NULL;
/* Is our configured entry an ancestor of this one? */
- rc = rs->sr_entry->e_nname.bv_len - ci->ci_dn.bv_len;
- if ( rc < 1 || strcmp( rs->sr_entry->e_nname.bv_val + rc,
- ci->ci_dn.bv_val )) continue;
+ if ( !dnIsSuffix( &rs->sr_entry->e_nname, &ci->ci_dn ))
+ continue;
/* Extract the values of the desired attribute from
* the ancestor entry
* don't modify it directly. Make a copy and
* work with that instead.
*/
- if ( !new ) {
- new = entry_dup( rs->sr_entry );
+ if ( !( rs->sr_flags & REP_ENTRY_MODIFIABLE )) {
+ rs->sr_entry = entry_dup( rs->sr_entry );
+ rs->sr_flags |= REP_ENTRY_MODIFIABLE |
+ REP_ENTRY_MUSTBEFREED;
}
- attr_merge( new, ci->ci_ad, vals, NULL );
+ attr_merge( rs->sr_entry, ci->ci_ad, vals, NULL );
ber_bvarray_free_x( vals, op->o_tmpmemctx );
}
}
-
- if ( new ) {
- rs->sr_entry = new;
- rs->sr_flags |= REP_ENTRY_MUSTBEFREED;
- }
}
/* Default is to just fall through to the normal processing */
return SLAP_CB_CONTINUE;
}
-static int collect_config(
- BackendDB *be,
- const char *fname,
- int lineno,
- int argc,
- char **argv
-)
-{
- slap_overinst *on = (slap_overinst *) be->bd_info;
- AttributeDescription *ad = NULL;
-
- /* The config syntax is "collectinfo <dn> <attribute-description>"
- * and only one directive may be specified per overlay instance.
- */
-
- if ( strcasecmp( argv[0], "collectinfo" ) == 0 ) {
- collect_info *ci;
- struct berval bv, dn;
- const char *text;
- if ( argc != 3 ) {
- Debug( LDAP_DEBUG_ANY,
- "%s: line %d: argument missing in \"collectinfo <dn> <attribute-description>\" line.\n",
- fname, lineno, 0 );
- return( 1 );
- }
- ber_str2bv( argv[1], 0, 0, &bv );
- if ( dnNormalize( 0, NULL, NULL, &bv, &dn, NULL ) ) {
- Debug( LDAP_DEBUG_ANY,
- "%s: line %d: invalid DN in \"collectinfo\" line: %s.\n",
- fname, lineno, text );
- return( 1 );
- }
- if ( slap_str2ad( argv[2], &ad, &text ) ) {
- Debug( LDAP_DEBUG_ANY,
- "%s: line %d: attribute description unknown in \"collectinfo\" line: %s.\n",
- fname, lineno, text );
- return( 1 );
- }
-
- /* The on->on_bi.bi_private pointer can be used for
- * anything this instance of the overlay needs.
- */
- ci = ch_malloc( sizeof( collect_info ));
- ci->ci_ad = ad;
- ci->ci_dn = dn;
- ci->ci_next = on->on_bi.bi_private;
- on->on_bi.bi_private = ci;
- return 0;
- }
- return SLAP_CONF_UNKNOWN;
-}
-
static slap_overinst collect;
int collect_initialize() {
+ int code;
+
collect.on_bi.bi_type = "collect";
- collect.on_bi.bi_db_config = collect_config;
+ collect.on_bi.bi_db_destroy = collect_destroy;
collect.on_response = collect_response;
+ collect.on_bi.bi_cf_ocs = collectocs;
+ code = config_register_schema( collectcfg, collectocs );
+ if ( code ) return code;
+
return overlay_register( &collect );
}
switch (c->type) {
case CONSTRAINT_ATTRIBUTE:
if ( slap_str2ad( c->argv[1], &ap.ap, &text ) ) {
- snprintf( c->msg, sizeof( c->msg ),
+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
"%s <%s>: %s\n", c->argv[0], c->argv[1], text );
Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
- "%s: %s\n", c->log, c->msg, 0 );
+ "%s: %s\n", c->log, c->cr_msg, 0 );
return( ARG_BAD_CONF );
}
regerror( err, ap.re, errmsg, sizeof(errmsg) );
ch_free(ap.re);
- snprintf( c->msg, sizeof( c->msg ),
+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
"%s %s: Illegal regular expression \"%s\": Error %s",
c->argv[0], c->argv[1], c->argv[3], errmsg);
Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
- "%s: %s\n", c->log, c->msg, 0 );
+ "%s: %s\n", c->log, c->cr_msg, 0 );
ap.re = NULL;
return( ARG_BAD_CONF );
}
ap.re_str = ch_strdup( c->argv[3] );
} else {
- snprintf( c->msg, sizeof( c->msg ),
+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
"%s %s: Unknown constraint type: %s",
c->argv[0], c->argv[1], c->argv[2] );
Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
- "%s: %s\n", c->log, c->msg, 0 );
+ "%s: %s\n", c->log, c->cr_msg, 0 );
return ( ARG_BAD_CONF );
}
}
static char *
-print_message( const char *fmt, AttributeDescription *a )
+print_message( const char *errtext, AttributeDescription *a )
{
char *ret;
int sz;
- sz = strlen(fmt) + a->ad_cname.bv_len + 1;
+ sz = strlen(errtext) + sizeof(" on ") + a->ad_cname.bv_len;
ret = ch_malloc(sz);
- snprintf( ret, sz, fmt, a->ad_cname.bv_val );
+ snprintf( ret, sz, "%s on %s", errtext, a->ad_cname.bv_val );
return ret;
}
constraint *c = on->on_bi.bi_private, *cp;
BerVarray b = NULL;
int i;
- const char *rsv = "add breaks regular expression constraint on %s";
+ const char *rsv = "add breaks regular expression constraint";
char *msg;
if ((a = op->ora_e->e_attrs) == NULL) {
Modifications *m;
BerVarray b = NULL;
int i;
- const char *rsv = "modify breaks regular expression constraint on %s";
+ const char *rsv = "modify breaks regular expression constraint";
char *msg;
if ((m = op->orm_modlist) == NULL) {
static int
constraint_close(
- BackendDB *be
- )
+ BackendDB *be,
+ ConfigReply *cr )
{
slap_overinst *on = (slap_overinst *) be->bd_info;
constraint *ap, *a2;
Connection conn = { 0 };
OperationBuffer opbuf;
Operation *op;
- slap_callback sc = { 0 }, sc2 = { 0 };
+ slap_callback sc = { 0 };
dds_cb_t dc = { 0 };
dds_expire_t *de = NULL, **dep;
SlapReply rs = { REP_RESULT };
int ndeletes, ntotdeletes;
- op = (Operation *)&opbuf;
- connection_fake_init( &conn, op, ctx );
+ connection_fake_init( &conn, &opbuf, ctx );
+ op = &opbuf.ob_op;
op->o_tag = LDAP_REQ_SEARCH;
memset( &op->oq_search, 0, sizeof( op->oq_search ) );
- op->o_bd = select_backend( &di->di_nsuffix[ 0 ], 0, 0 );
+ op->o_bd = select_backend( &di->di_nsuffix[ 0 ], 0 );
op->o_req_dn = op->o_bd->be_suffix[ 0 ];
op->o_req_ndn = op->o_bd->be_nsuffix[ 0 ];
op->o_tag = LDAP_REQ_DELETE;
op->o_callback = ≻
- sc.sc_response = slap_replog_cb;
+ sc.sc_response = slap_null_cb;
sc.sc_private = NULL;
- sc.sc_next = &sc2;
- sc2.sc_response = slap_null_cb;
for ( ntotdeletes = 0, ndeletes = 1; dc.dc_ndnlist != NULL && ndeletes > 0; ) {
ndeletes = 0;
tag = ber_peek_tag( ber, &len );
- if ( len != 0 ) {
+ if ( tag != LBER_DEFAULT || len != 0 ) {
decoding_error:;
Log1( LDAP_DEBUG_TRACE, LDAP_LEVEL_ERR,
"slap_parse_refresh: decoding error, len=%ld\n",
SlapReply rs2 = { REP_RESULT };
Operation op2 = *op;
slap_callback sc = { 0 };
- slap_callback sc2 = { 0 };
Modifications ttlmod = { { 0 } };
struct berval ttlvalues[ 2 ];
char ttlbuf[] = "31557600";
op2.o_bd = &db;
db.bd_info = (BackendInfo *)on->on_info;
op2.o_callback = ≻
- sc.sc_response = slap_replog_cb;
- sc.sc_next = &sc2;
- sc2.sc_response = slap_null_cb;
+ sc.sc_response = slap_null_cb;
op2.o_relax = SLAP_CONTROL_CRITICAL;
op2.orm_modlist = &ttlmod;
case DDS_MAXTTL:
if ( lutil_parse_time( c->argv[ 1 ], &t ) != 0 ) {
- snprintf( c->msg, sizeof( c->msg),
+ snprintf( c->cr_msg, sizeof( c->cr_msg),
"DDS unable to parse dds-max-ttl \"%s\"",
c->argv[ 1 ] );
Log2( LDAP_DEBUG_ANY, LDAP_LEVEL_ERR,
- "%s: %s.\n", c->log, c->msg );
+ "%s: %s.\n", c->log, c->cr_msg );
return 1;
}
if ( t < DDS_RF2589_DEFAULT_TTL || t > DDS_RF2589_MAX_TTL ) {
- snprintf( c->msg, sizeof( c->msg ),
+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
"DDS invalid dds-max-ttl=%ld; must be between %d and %d",
t, DDS_RF2589_DEFAULT_TTL, DDS_RF2589_MAX_TTL );
Log2( LDAP_DEBUG_ANY, LDAP_LEVEL_ERR,
- "%s: %s.\n", c->log, c->msg );
+ "%s: %s.\n", c->log, c->cr_msg );
return 1;
}
case DDS_MINTTL:
if ( lutil_parse_time( c->argv[ 1 ], &t ) != 0 ) {
- snprintf( c->msg, sizeof( c->msg),
+ snprintf( c->cr_msg, sizeof( c->cr_msg),
"DDS unable to parse dds-min-ttl \"%s\"",
c->argv[ 1 ] );
Log2( LDAP_DEBUG_ANY, LDAP_LEVEL_ERR,
- "%s: %s.\n", c->log, c->msg );
+ "%s: %s.\n", c->log, c->cr_msg );
return 1;
}
if ( t < 0 || t > DDS_RF2589_MAX_TTL ) {
- snprintf( c->msg, sizeof( c->msg ),
+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
"DDS invalid dds-min-ttl=%ld",
t );
Log2( LDAP_DEBUG_ANY, LDAP_LEVEL_ERR,
- "%s: %s.\n", c->log, c->msg );
+ "%s: %s.\n", c->log, c->cr_msg );
return 1;
}
case DDS_DEFAULTTTL:
if ( lutil_parse_time( c->argv[ 1 ], &t ) != 0 ) {
- snprintf( c->msg, sizeof( c->msg),
+ snprintf( c->cr_msg, sizeof( c->cr_msg),
"DDS unable to parse dds-default-ttl \"%s\"",
c->argv[ 1 ] );
Log2( LDAP_DEBUG_ANY, LDAP_LEVEL_ERR,
- "%s: %s.\n", c->log, c->msg );
+ "%s: %s.\n", c->log, c->cr_msg );
return 1;
}
if ( t < 0 || t > DDS_RF2589_MAX_TTL ) {
- snprintf( c->msg, sizeof( c->msg ),
+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
"DDS invalid dds-default-ttl=%ld",
t );
Log2( LDAP_DEBUG_ANY, LDAP_LEVEL_ERR,
- "%s: %s.\n", c->log, c->msg );
+ "%s: %s.\n", c->log, c->cr_msg );
return 1;
}
case DDS_INTERVAL:
if ( lutil_parse_time( c->argv[ 1 ], &t ) != 0 ) {
- snprintf( c->msg, sizeof( c->msg),
+ snprintf( c->cr_msg, sizeof( c->cr_msg),
"DDS unable to parse dds-interval \"%s\"",
c->argv[ 1 ] );
Log2( LDAP_DEBUG_ANY, LDAP_LEVEL_ERR,
- "%s: %s.\n", c->log, c->msg );
+ "%s: %s.\n", c->log, c->cr_msg );
return 1;
}
if ( t <= 0 ) {
- snprintf( c->msg, sizeof( c->msg ),
+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
"DDS invalid dds-interval=%ld",
t );
Log2( LDAP_DEBUG_ANY, LDAP_LEVEL_ERR,
- "%s: %s.\n", c->log, c->msg );
+ "%s: %s.\n", c->log, c->cr_msg );
return 1;
}
case DDS_TOLERANCE:
if ( lutil_parse_time( c->argv[ 1 ], &t ) != 0 ) {
- snprintf( c->msg, sizeof( c->msg),
+ snprintf( c->cr_msg, sizeof( c->cr_msg),
"DDS unable to parse dds-tolerance \"%s\"",
c->argv[ 1 ] );
Log2( LDAP_DEBUG_ANY, LDAP_LEVEL_ERR,
- "%s: %s.\n", c->log, c->msg );
+ "%s: %s.\n", c->log, c->cr_msg );
return 1;
}
if ( t < 0 || t > DDS_RF2589_MAX_TTL ) {
- snprintf( c->msg, sizeof( c->msg ),
+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
"DDS invalid dds-tolerance=%ld",
t );
Log2( LDAP_DEBUG_ANY, LDAP_LEVEL_ERR,
- "%s: %s.\n", c->log, c->msg );
+ "%s: %s.\n", c->log, c->cr_msg );
return 1;
}
case DDS_MAXDYNAMICOBJS:
if ( c->value_int < 0 ) {
- snprintf( c->msg, sizeof( c->msg ),
+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
"DDS invalid dds-max-dynamicObjects=%d", c->value_int );
Log2( LDAP_DEBUG_ANY, LDAP_LEVEL_ERR,
- "%s: %s.\n", c->log, c->msg );
+ "%s: %s.\n", c->log, c->cr_msg );
return 1;
}
di->di_max_dynamicObjects = c->value_int;
static int
dds_db_init(
- BackendDB *be )
+ BackendDB *be,
+ ConfigReply *cr)
{
slap_overinst *on = (slap_overinst *)be->bd_info;
dds_info_t *di;
slap_callback sc = { 0 };
SlapReply rs = { REP_RESULT };
- op = (Operation *)&opbuf;
- connection_fake_init( &conn, op, ctx );
+ connection_fake_init( &conn, &opbuf, ctx );
+ op = &opbuf.ob_op;
op->o_tag = LDAP_REQ_SEARCH;
memset( &op->oq_search, 0, sizeof( op->oq_search ) );
static int
dds_db_open(
- BackendDB *be )
+ BackendDB *be,
+ ConfigReply *cr )
{
slap_overinst *on = (slap_overinst *)be->bd_info;
dds_info_t *di = on->on_bi.bi_private;
static int
dds_db_close(
- BackendDB *be )
+ BackendDB *be,
+ ConfigReply *cr )
{
slap_overinst *on = (slap_overinst *)be->bd_info;
dds_info_t *di = on->on_bi.bi_private;
static int
dds_db_destroy(
- BackendDB *be )
+ BackendDB *be,
+ ConfigReply *cr )
{
slap_overinst *on = (slap_overinst *)be->bd_info;
dds_info_t *di = on->on_bi.bi_private;
op->o_log_prefix, op->o_req_ndn.bv_val );
op->o_req_dn = op->o_req_ndn;
- op->o_bd = select_backend( &op->o_req_ndn, 0, 0 );
+ op->o_bd = select_backend( &op->o_req_ndn, 0 );
if ( !SLAP_DYNAMIC( op->o_bd ) ) {
send_ldap_error( op, rs, LDAP_UNAVAILABLE_CRITICAL_EXTENSION,
"backend does not support dynamic directory services" );
#include <ac/string.h>
#include <ac/socket.h>
+#include "lutil.h"
#include "slap.h"
+#include "config.h"
/* This overlay extends the Compare operation to detect members of a
* dynamic group. It has no effect on any other operations. It must
AttributeDescription *ap_uri;
} adpair;
+static int dgroup_cf( ConfigArgs *c )
+{
+ slap_overinst *on = (slap_overinst *)c->bi;
+ int rc = 1;
+
+ switch( c->op ) {
+ case SLAP_CONFIG_EMIT:
+ {
+ adpair *ap;
+ for ( ap = on->on_bi.bi_private; ap; ap = ap->ap_next ) {
+ struct berval bv;
+ char *ptr;
+ bv.bv_len = ap->ap_mem->ad_cname.bv_len + 1 +
+ ap->ap_uri->ad_cname.bv_len;
+ bv.bv_val = ch_malloc( bv.bv_len + 1 );
+ ptr = lutil_strcopy( bv.bv_val, ap->ap_mem->ad_cname.bv_val );
+ *ptr++ = ' ';
+ strcpy( ptr, ap->ap_uri->ad_cname.bv_val );
+ ber_bvarray_add( &c->rvalue_vals, &bv );
+ rc = 0;
+ }
+ }
+ break;
+ case LDAP_MOD_DELETE:
+ if ( c->valx == -1 ) {
+ adpair *ap;
+ while (( ap = on->on_bi.bi_private )) {
+ on->on_bi.bi_private = ap->ap_next;
+ ch_free( ap );
+ }
+ } else {
+ adpair **app, *ap;
+ int i;
+ app = (adpair **)&on->on_bi.bi_private;
+ for (i=0; i<=c->valx; i++, app = &ap->ap_next) {
+ ap = *app;
+ }
+ *app = ap->ap_next;
+ ch_free( ap );
+ }
+ rc = 0;
+ break;
+ case SLAP_CONFIG_ADD:
+ case LDAP_MOD_ADD:
+ {
+ adpair ap = { NULL, NULL, NULL }, *a2;
+ const char *text;
+ if ( slap_str2ad( c->argv[1], &ap.ap_mem, &text ) ) {
+ snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s attribute description unknown: \"%s\"",
+ c->argv[0], c->argv[1] );
+ Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
+ "%s: %s\n", c->log, c->cr_msg, 0 );
+ return ARG_BAD_CONF;
+ }
+ if ( slap_str2ad( c->argv[2], &ap.ap_uri, &text ) ) {
+ snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s attribute description unknown: \"%s\"",
+ c->argv[0], c->argv[2] );
+ Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
+ "%s: %s\n", c->log, c->cr_msg, 0 );
+ return ARG_BAD_CONF;
+ }
+ /* The on->on_bi.bi_private pointer can be used for
+ * anything this instance of the overlay needs.
+ */
+ a2 = ch_malloc( sizeof(adpair) );
+ a2->ap_next = on->on_bi.bi_private;
+ a2->ap_mem = ap.ap_mem;
+ a2->ap_uri = ap.ap_uri;
+ on->on_bi.bi_private = a2;
+ rc = 0;
+ }
+ }
+ return rc;
+}
+
+static ConfigTable dgroupcfg[] = {
+ { "attrpair", "member-attribute> <URL-attribute", 3, 3, 0,
+ ARG_MAGIC, dgroup_cf,
+ "( OLcfgOvAt:17.1 NAME 'olcDGAttrPair' "
+ "DESC 'Member and MemberURL attribute pair' "
+ "SYNTAX OMsDirectoryString )", NULL, NULL },
+ { NULL, NULL, 0, 0, 0, ARG_IGNORED }
+};
+
+static ConfigOCs dgroupocs[] = {
+ { "( OLcfgOvOc:17.1 "
+ "NAME 'olcDGConfig' "
+ "DESC 'Dynamic Group configuration' "
+ "SUP olcOverlayConfig "
+ "MAY olcDGAttrPair )",
+ Cft_Overlay, dgroupcfg },
+ { NULL, 0, NULL }
+};
+
static int
dyngroup_response( Operation *op, SlapReply *rs )
{
return SLAP_CB_CONTINUE;
}
-static int dyngroup_config(
- BackendDB *be,
- const char *fname,
- int lineno,
- int argc,
- char **argv
-)
-{
- slap_overinst *on = (slap_overinst *) be->bd_info;
- adpair ap = { NULL, NULL, NULL }, *a2;
-
- if ( strcasecmp( argv[0], "attrpair" ) == 0 ) {
- const char *text;
- if ( argc != 3 ) {
- Debug( LDAP_DEBUG_ANY, "%s: line %d: "
- "attribute description missing in "
- "\"attrpair <member-attribute> <URL-attribute>\" line.\n",
- fname, lineno, 0 );
- return( 1 );
- }
- if ( slap_str2ad( argv[1], &ap.ap_mem, &text ) ) {
- Debug( LDAP_DEBUG_ANY, "%s: line %d: "
- "attribute description unknown \"attrpair\" line: %s.\n",
- fname, lineno, text );
- return( 1 );
- }
- if ( slap_str2ad( argv[2], &ap.ap_uri, &text ) ) {
- Debug( LDAP_DEBUG_ANY, "%s: line %d: "
- "attribute description unknown \"attrpair\" line: %s.\n",
- fname, lineno, text );
- return( 1 );
- }
- /* The on->on_bi.bi_private pointer can be used for
- * anything this instance of the overlay needs.
- */
-
- a2 = ch_malloc( sizeof(adpair) );
- a2->ap_next = on->on_bi.bi_private;
- a2->ap_mem = ap.ap_mem;
- a2->ap_uri = ap.ap_uri;
- on->on_bi.bi_private = a2;
- } else {
- return SLAP_CONF_UNKNOWN;
- }
- return 0;
-}
-
static int
dyngroup_close(
- BackendDB *be
+ BackendDB *be,
+ ConfigReply *cr
)
{
slap_overinst *on = (slap_overinst *) be->bd_info;
*/
int dyngroup_initialize() {
+ int code;
+
dyngroup.on_bi.bi_type = "dyngroup";
- dyngroup.on_bi.bi_db_config = dyngroup_config;
dyngroup.on_bi.bi_db_close = dyngroup_close;
dyngroup.on_response = dyngroup_response;
+ dyngroup.on_bi.bi_cf_ocs = dgroupocs;
+ code = config_register_schema( dgroupcfg, dgroupocs );
+ if ( code ) return code;
+
return overlay_register( &dyngroup );
}
static AttributeName *slap_anlist_no_attrs = anlist_no_attrs;
#endif
+static AttributeDescription *ad_dgIdentity;
+
typedef struct dynlist_info_t {
ObjectClass *dli_oc;
AttributeDescription *dli_ad;
} dynlist_info_t;
static dynlist_info_t *
-dynlist_is_dynlist( Operation *op, SlapReply *rs )
+dynlist_is_dynlist_next( Operation *op, SlapReply *rs, dynlist_info_t *old_dli )
{
slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
- dynlist_info_t *dli = (dynlist_info_t *)on->on_bi.bi_private;
+ dynlist_info_t *dli;
Attribute *a;
+ if ( old_dli == NULL ) {
+ dli = (dynlist_info_t *)on->on_bi.bi_private;
+
+ } else {
+ dli = old_dli->dli_next;
+ }
+
a = attrs_find( rs->sr_entry->e_attrs, slap_schema.si_ad_objectClass );
if ( a == NULL ) {
/* FIXME: objectClass must be present; for non-storage
}
static int
-dynlist_send_entry( Operation *op, SlapReply *rs, dynlist_info_t *dli )
+dynlist_prepare_entry( Operation *op, SlapReply *rs, dynlist_info_t *dli )
{
- Attribute *a;
+ Attribute *a, *id = NULL;
slap_callback cb;
Operation o = *op;
SlapReply r = { REP_SEARCH };
return SLAP_CB_CONTINUE;
}
- e = entry_dup( rs->sr_entry );
+ if ( !( rs->sr_flags & REP_ENTRY_MODIFIABLE ) ) {
+ e = entry_dup( rs->sr_entry );
+ } else {
+ e = rs->sr_entry;
+ }
e_flags = rs->sr_flags | ( REP_ENTRY_MODIFIABLE | REP_ENTRY_MUSTBEFREED );
+ if ( ad_dgIdentity && ( id = attrs_find( e->e_attrs, ad_dgIdentity ))) {
+ o.o_dn = id->a_vals[0];
+ o.o_ndn = id->a_nvals[0];
+ o.o_groups = NULL;
+ }
+
dlc.dlc_e = e;
dlc.dlc_dli = dli;
cb.sc_private = &dlc;
if ( lud->lud_host != NULL ) {
/* FIXME: host not allowed; reject as illegal? */
- Debug( LDAP_DEBUG_ANY, "dynlist_send_entry(\"%s\"): "
+ Debug( LDAP_DEBUG_ANY, "dynlist_prepare_entry(\"%s\"): "
"illegal URI \"%s\"\n",
e->e_name.bv_val, url->bv_val, 0 );
goto cleanup;
goto cleanup;
}
- o.o_bd = select_backend( &o.o_req_ndn, 0, 1 );
+ o.o_bd = select_backend( &o.o_req_ndn, 1 );
if ( o.o_bd && o.o_bd->be_search ) {
#ifdef SLAP_OPATTRS
r.sr_attr_flags = slap_attr_flags( o.ors_attrs );
}
cleanup:;
+ if ( id ) {
+ slap_op_groups_free( &o );
+ }
if ( o.ors_filter ) {
filter_free_x( &o, o.ors_filter );
}
if ( !BER_BVISNULL( &o.o_req_ndn ) ) {
op->o_tmpfree( o.o_req_ndn.bv_val, op->o_tmpmemctx );
}
- assert( o.ors_filterstr.bv_val != lud->lud_filter );
+ assert( BER_BVISNULL( &o.ors_filterstr )
+ || o.ors_filterstr.bv_val != lud->lud_filter );
op->o_tmpfree( o.ors_filterstr.bv_val, op->o_tmpmemctx );
ldap_free_urldesc( lud );
}
{
slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
dynlist_info_t *dli = (dynlist_info_t *)on->on_bi.bi_private;
+ Operation o = *op;
+ Entry *e;
for ( ; dli != NULL; dli = dli->dli_next ) {
if ( op->oq_compare.rs_ava->aa_desc == dli->dli_member_ad ) {
* interested in. We'll use slapd's existing dyngroup
* evaluator to get the answer we want.
*/
- int cache = op->o_do_not_cache;
-
- op->o_do_not_cache = 1;
- rs->sr_err = backend_group( op, NULL, &op->o_req_ndn,
- &op->oq_compare.rs_ava->aa_value, dli->dli_oc, dli->dli_ad );
- op->o_do_not_cache = cache;
+ struct berval *id = NULL;
+
+ o.o_do_not_cache = 1;
+
+ if ( ad_dgIdentity && backend_attribute( &o, NULL, &o.o_req_ndn,
+ ad_dgIdentity, &id, ACL_READ ) == LDAP_SUCCESS ) {
+ o.o_dn = *id;
+ o.o_ndn = *id;
+ o.o_groups = NULL; /* authz changed, invalidate cached groups */
+ }
+ rs->sr_err = backend_group( &o, NULL, &o.o_req_ndn,
+ &o.oq_compare.rs_ava->aa_value, dli->dli_oc, dli->dli_ad );
switch ( rs->sr_err ) {
case LDAP_SUCCESS:
rs->sr_err = LDAP_COMPARE_TRUE;
break;
}
+ if ( id ) ber_bvarray_free_x( id, o.o_tmpmemctx );
+
return SLAP_CB_CONTINUE;
}
}
+ if ( overlay_entry_get_ov( &o, &o.o_req_ndn, NULL, NULL, 0, &e, on ) !=
+ LDAP_SUCCESS || e == NULL ) {
+ return SLAP_CB_CONTINUE;
+ }
+ if ( ad_dgIdentity ) {
+ Attribute *id = attrs_find( e->e_attrs, ad_dgIdentity );
+ if ( id ) {
+ o.o_dn = id->a_vals[0];
+ o.o_ndn = id->a_nvals[0];
+ o.o_groups = NULL;
+ }
+ }
dli = (dynlist_info_t *)on->on_bi.bi_private;
for ( ; dli != NULL && rs->sr_err != LDAP_COMPARE_TRUE; dli = dli->dli_next ) {
Attribute *a;
slap_callback cb;
- Operation o = *op;
SlapReply r = { REP_SEARCH };
AttributeName an[2];
int rc;
dynlist_sc_t dlc = { 0 };
- Entry *e;
-
- int cache = op->o_do_not_cache;
- struct berval op_dn = op->o_dn,
- op_ndn = op->o_ndn;
- BackendDB *op_bd = op->o_bd;
-
- /* fetch the entry as rootdn (a hack to see if it exists
- * and if it has the right objectClass) */
- op->o_do_not_cache = 1;
- op->o_dn = op->o_bd->be_rootdn;
- op->o_ndn = op->o_bd->be_rootndn;
- op->o_bd = select_backend( &op->o_req_ndn, 0, 0 );
-
- r.sr_err = be_entry_get_rw( op, &op->o_req_ndn,
- dli->dli_oc, NULL, 0, &e );
- if ( e != NULL ) {
- be_entry_release_r( op, e );
- }
- op->o_do_not_cache = cache;
- op->o_dn = op_dn;
- op->o_ndn = op_ndn;
- op->o_bd = op_bd;
- if ( r.sr_err != LDAP_SUCCESS ) {
+
+ if ( !is_entry_objectclass_or_sub( e, dli->dli_oc ))
continue;
- }
/* if the entry has the right objectClass, generate
* the dynamic list and compare */
o.ors_tlimit = SLAP_NO_LIMIT;
o.ors_slimit = SLAP_NO_LIMIT;
- o.o_bd = select_backend( &o.o_req_ndn, 0, 1 );
+ o.o_bd = select_backend( &o.o_req_ndn, 1 );
if ( !o.o_bd || !o.o_bd->be_search ) {
return SLAP_CB_CONTINUE;
}
rc = o.o_bd->be_search( &o, &r );
filter_free_x( &o, o.ors_filter );
+ if ( o.o_dn.bv_val != op->o_dn.bv_val ) {
+ slap_op_groups_free( &o );
+ }
+
if ( rc != 0 ) {
return rc;
}
case LDAP_REQ_SEARCH:
if ( rs->sr_type == REP_SEARCH && !get_manageDSAit( op ) )
{
- dli = dynlist_is_dynlist( op, rs );
- if ( dli != NULL ) {
- return dynlist_send_entry( op, rs, dli );
+ int rc = LDAP_OTHER;
+
+ for ( dli = dynlist_is_dynlist_next( op, rs, NULL );
+ dli;
+ dli = dynlist_is_dynlist_next( op, rs, dli ) )
+ {
+ rc = dynlist_prepare_entry( op, rs, dli );
+ }
+
+ if ( rc != LDAP_OTHER ) {
+ return rc;
}
}
break;
for ( dlip = (dynlist_info_t **)&on->on_bi.bi_private;
*dlip; dlip = &(*dlip)->dli_next )
{
- /* The check on objectClass may be relaxed */
-#if 0
- if ( (*dlip)->dli_oc == oc ) {
- Debug( LDAP_DEBUG_ANY, "%s: line %d: "
- "\"dynlist-attrset <oc> <URL-ad> [<member-ad>]\": "
- "objectClass \"%s\" already mapped.\n",
- fname, lineno, oc->soc_cname.bv_val );
- return 1;
- }
-#endif
-
- if ( (*dlip)->dli_ad == ad ) {
+ /* The same URL attribute / member attribute pair
+ * cannot be repeated */
+ if ( (*dlip)->dli_ad == ad && (*dlip)->dli_member_ad == member_ad ) {
Debug( LDAP_DEBUG_ANY, "%s: line %d: "
"\"dynlist-attrset <oc> <URL-ad> [<member-ad>]\": "
"URL attributeDescription \"%s\" already mapped.\n",
fname, lineno, ad->ad_cname.bv_val );
+#if 0
+ /* make it a warning... */
return 1;
- }
-
- if ( member_ad != NULL && (*dlip)->dli_member_ad == member_ad ) {
- Debug( LDAP_DEBUG_ANY, "%s: line %d: "
- "\"dynlist-attrset <oc> <URL-ad> [<member-ad>]\": "
- "member attributeDescription \"%s\" already mapped.\n",
- fname, lineno, member_ad->ad_cname.bv_val );
- return 1;
+#endif
}
}
return 1;
}
-
for ( dlip = (dynlist_info_t **)&on->on_bi.bi_private;
*dlip; dlip = &(*dlip)->dli_next )
{
-#if 0
- /* The check on objectClass may be relaxed */
- if ( (*dlip)->dli_oc == oc ) {
- Debug( LDAP_DEBUG_ANY, "%s: line %d: "
- "\"dynlist-attrpair <member-ad> <URL-ad>\": "
- "objectClass \"%s\" already mapped.\n",
- fname, lineno, oc->soc_cname.bv_val );
- return 1;
- }
-#endif
-
- if ( (*dlip)->dli_ad == ad ) {
+ /* The same URL attribute / member attribute pair
+ * cannot be repeated */
+ if ( (*dlip)->dli_ad == ad && (*dlip)->dli_member_ad == member_ad ) {
Debug( LDAP_DEBUG_ANY, "%s: line %d: "
"\"dynlist-attrpair <member-ad> <URL-ad>\": "
"URL attributeDescription \"%s\" already mapped.\n",
fname, lineno, ad->ad_cname.bv_val );
+#if 0
+ /* make it a warning... */
return 1;
- }
-
- if ( member_ad != NULL && (*dlip)->dli_member_ad == member_ad ) {
- Debug( LDAP_DEBUG_ANY, "%s: line %d: "
- "\"dynlist-attrpair <member-ad> <URL-ad>\": "
- "member attributeDescription \"%s\" already mapped.\n",
- fname, lineno, member_ad->ad_cname.bv_val );
- return 1;
+#endif
}
}
case DL_ATTRSET:
for ( i = 0; dli; i++, dli = dli->dli_next ) {
struct berval bv;
- char *ptr = c->msg;
+ char *ptr = c->cr_msg;
assert( dli->dli_oc != NULL );
assert( dli->dli_ad != NULL );
- ptr += snprintf( c->msg, sizeof( c->msg ),
+ ptr += snprintf( c->cr_msg, sizeof( c->cr_msg ),
SLAP_X_ORDERED_FMT "%s %s", i,
dli->dli_oc->soc_cname.bv_val,
dli->dli_ad->ad_cname.bv_val );
ptr = lutil_strcopy( ptr, dli->dli_member_ad->ad_cname.bv_val );
}
- bv.bv_val = c->msg;
+ bv.bv_val = c->cr_msg;
bv.bv_len = ptr - bv.bv_val;
value_add_one( &c->rvalue_vals, &bv );
}
break;
}
- return 1; /* FIXME */
+ return rc;
}
switch( c->type ) {
oc = oc_find( c->argv[ 1 ] );
if ( oc == NULL ) {
- snprintf( c->msg, sizeof( c->msg ),
+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
"\"dynlist-attrset <oc> <URL-ad> [<member-ad>]\": "
"unable to find ObjectClass \"%s\"",
c->argv[ 1 ] );
Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
- c->log, c->msg, 0 );
+ c->log, c->cr_msg, 0 );
return 1;
}
rc = slap_str2ad( c->argv[ 2 ], &ad, &text );
if ( rc != LDAP_SUCCESS ) {
- snprintf( c->msg, sizeof( c->msg ),
+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
"\"dynlist-attrset <oc> <URL-ad> [<member-ad>]\": "
"unable to find AttributeDescription \"%s\"",
c->argv[ 2 ] );
Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
- c->log, c->msg, 0 );
+ c->log, c->cr_msg, 0 );
return 1;
}
if ( !is_at_subtype( ad->ad_type, slap_schema.si_ad_labeledURI->ad_type ) ) {
- snprintf( c->msg, sizeof( c->msg ),
+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
"\"dynlist-attrset <oc> <URL-ad> [<member-ad>]\": "
"AttributeDescription \"%s\" "
"must be a subtype of \"labeledURI\"",
c->argv[ 2 ] );
Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
- c->log, c->msg, 0 );
+ c->log, c->cr_msg, 0 );
return 1;
}
if ( c->argc == 4 ) {
rc = slap_str2ad( c->argv[ 3 ], &member_ad, &text );
if ( rc != LDAP_SUCCESS ) {
- snprintf( c->msg, sizeof( c->msg ),
+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
"\"dynlist-attrset <oc> <URL-ad> [<member-ad>]\": "
"unable to find AttributeDescription \"%s\"\n",
c->argv[ 3 ] );
Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
- c->log, c->msg, 0 );
+ c->log, c->cr_msg, 0 );
return 1;
}
}
for ( dlip = (dynlist_info_t **)&on->on_bi.bi_private;
*dlip; dlip = &(*dlip)->dli_next )
{
- /* The check on objectClass may be relaxed */
-#if 0
- if ( (*dlip)->dli_oc == oc ) {
- snprintf( c->msg, sizeof( c->msg ),
- "\"dynlist-attrset <oc> <URL-ad> [<member-ad>]\": "
- "objectClass \"%s\" already mapped.\n",
- oc->soc_cname.bv_val );
- Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
- c->log, c->msg, 0 );
- return 1;
- }
-#endif
-
- if ( (*dlip)->dli_ad == ad ) {
- snprintf( c->msg, sizeof( c->msg ),
+ /* The same URL attribute / member attribute pair
+ * cannot be repeated */
+ if ( (*dlip)->dli_ad == ad && (*dlip)->dli_member_ad == member_ad ) {
+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
"\"dynlist-attrset <oc> <URL-ad> [<member-ad>]\": "
"URL attributeDescription \"%s\" already mapped.\n",
ad->ad_cname.bv_val );
Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
- c->log, c->msg, 0 );
- return 1;
- }
-
- if ( member_ad != NULL && (*dlip)->dli_member_ad == member_ad ) {
- snprintf( c->msg, sizeof( c->msg ),
- "\"dynlist-attrset <oc> <URL-ad> [<member-ad>]\": "
- "member attributeDescription \"%s\" already mapped.\n",
- member_ad->ad_cname.bv_val );
- Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
- c->log, c->msg, 0 );
+ c->log, c->cr_msg, 0 );
+#if 0
+ /* make it a warning... */
return 1;
+#endif
}
}
i < c->valx; i++ )
{
if ( *dlip == NULL ) {
- snprintf( c->msg, sizeof( c->msg ),
+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
"\"dynlist-attrset <oc> <URL-ad> [<member-ad>]\": "
"invalid index {%d}\n",
c->valx );
Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
- c->log, c->msg, 0 );
+ c->log, c->cr_msg, 0 );
return 1;
}
dlip = &(*dlip)->dli_next;
} break;
case DL_ATTRPAIR_COMPAT:
- snprintf( c->msg, sizeof( c->msg ),
+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
"warning: \"attrpair\" only supported for limited "
"backward compatibility with overlay \"dyngroup\"" );
- Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
/* fallthru */
case DL_ATTRPAIR: {
oc = oc_find( "groupOfURLs" );
if ( oc == NULL ) {
- snprintf( c->msg, sizeof( c->msg ),
+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
"\"dynlist-attrpair <member-ad> <URL-ad>\": "
"unable to find default ObjectClass \"groupOfURLs\"" );
Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
- c->log, c->msg, 0 );
+ c->log, c->cr_msg, 0 );
return 1;
}
rc = slap_str2ad( c->argv[ 1 ], &member_ad, &text );
if ( rc != LDAP_SUCCESS ) {
- snprintf( c->msg, sizeof( c->msg ),
+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
"\"dynlist-attrpair <member-ad> <URL-ad>\": "
"unable to find AttributeDescription \"%s\"",
c->argv[ 1 ] );
Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
- c->log, c->msg, 0 );
+ c->log, c->cr_msg, 0 );
return 1;
}
rc = slap_str2ad( c->argv[ 2 ], &ad, &text );
if ( rc != LDAP_SUCCESS ) {
- snprintf( c->msg, sizeof( c->msg ),
+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
"\"dynlist-attrpair <member-ad> <URL-ad>\": "
"unable to find AttributeDescription \"%s\"\n",
c->argv[ 2 ] );
Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
- c->log, c->msg, 0 );
+ c->log, c->cr_msg, 0 );
return 1;
}
if ( !is_at_subtype( ad->ad_type, slap_schema.si_ad_labeledURI->ad_type ) ) {
- snprintf( c->msg, sizeof( c->msg ),
+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
"\"dynlist-attrset <oc> <URL-ad> [<member-ad>]\": "
"AttributeDescription \"%s\" "
"must be a subtype of \"labeledURI\"",
c->argv[ 2 ] );
Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
- c->log, c->msg, 0 );
+ c->log, c->cr_msg, 0 );
return 1;
}
for ( dlip = (dynlist_info_t **)&on->on_bi.bi_private;
*dlip; dlip = &(*dlip)->dli_next )
{
- /* The check on objectClass may be relaxed */
-#if 0
- if ( (*dlip)->dli_oc == oc ) {
- snprintf( c->msg, sizeof( c->msg ),
- "\"dynlist-attrpair <member-ad> <URL-ad>\": "
- "objectClass \"%s\" already mapped.\n",
- oc->soc_cname.bv_val );
- Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
- c->log, c->msg, 0 );
- return 1;
- }
-#endif
-
- if ( (*dlip)->dli_ad == ad ) {
- snprintf( c->msg, sizeof( c->msg ),
+ /* The same URL attribute / member attribute pair
+ * cannot be repeated */
+ if ( (*dlip)->dli_ad == ad && (*dlip)->dli_member_ad == member_ad ) {
+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
"\"dynlist-attrpair <member-ad> <URL-ad>\": "
"URL attributeDescription \"%s\" already mapped.\n",
ad->ad_cname.bv_val );
Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
- c->log, c->msg, 0 );
- return 1;
- }
-
- if ( member_ad != NULL && (*dlip)->dli_member_ad == member_ad ) {
- snprintf( c->msg, sizeof( c->msg ),
- "\"dynlist-attrpair <member-ad> <URL-ad>\": "
- "member attributeDescription \"%s\" already mapped.\n",
- member_ad->ad_cname.bv_val );
- Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
- c->log, c->msg, 0 );
+ c->log, c->cr_msg, 0 );
+#if 0
+ /* make it a warning... */
return 1;
+#endif
}
}
static int
dynlist_db_open(
- BackendDB *be )
+ BackendDB *be,
+ ConfigReply *cr )
{
slap_overinst *on = (slap_overinst *) be->bd_info;
dynlist_info_t *dli = (dynlist_info_t *)on->on_bi.bi_private;
ObjectClass *oc = NULL;
AttributeDescription *ad = NULL;
+ const char *text;
+ int rc;
if ( dli == NULL ) {
dli = ch_calloc( 1, sizeof( dynlist_info_t ) );
}
for ( ; dli; dli = dli->dli_next ) {
- const char *text;
- int rc;
-
if ( dli->dli_oc == NULL ) {
if ( oc == NULL ) {
oc = oc_find( "groupOfURLs" );
if ( oc == NULL ) {
- Debug( LDAP_DEBUG_ANY, "dynlist_db_open: "
- "unable to fetch objectClass \"groupOfURLs\".\n",
- 0, 0, 0 );
+ sprintf( cr->msg, "unable to fetch objectClass \"groupOfURLs\"" );
+ Debug( LDAP_DEBUG_ANY, "dynlist_db_open: %s.\n", cr->msg, 0, 0 );
return 1;
}
}
if ( ad == NULL ) {
rc = slap_str2ad( "memberURL", &ad, &text );
if ( rc != LDAP_SUCCESS ) {
- Debug( LDAP_DEBUG_ANY, "dynlist_db_open: "
- "unable to fetch attributeDescription \"memberURL\": %d (%s).\n",
- rc, text, 0 );
+ sprintf( cr->msg, "unable to fetch attributeDescription \"memberURL\": %d (%s)",
+ rc, text );
+ Debug( LDAP_DEBUG_ANY, "dynlist_db_open: %s.\n", cr->msg, 0, 0 );
return 1;
}
}
}
}
+ rc = slap_str2ad( "dgIdentity", &ad_dgIdentity, &text );
+ if ( rc != LDAP_SUCCESS ) {
+ sprintf( cr->msg, "unable to fetch attributeDescription \"dgIdentity\": %d (%s)",
+ rc, text );
+ Debug( LDAP_DEBUG_ANY, "dynlist_db_open: %s\n", cr->msg, 0, 0 );
+ /* Just a warning */
+ }
+
return 0;
}
static int
dynlist_db_destroy(
- BackendDB *be )
+ BackendDB *be,
+ ConfigReply *cr )
{
slap_overinst *on = (slap_overinst *) be->bd_info;
--- /dev/null
+/* memberof.c - back-reference for group membership */
+/* $OpenLDAP$ */
+/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
+ *
+ * Copyright 2005-2007 Pierangelo Masarati <ando@sys-net.it>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted only as authorized by the OpenLDAP
+ * Public License.
+ *
+ * A copy of this license is available in the file LICENSE in the
+ * top-level directory of the distribution or, alternatively, at
+ * <http://www.OpenLDAP.org/license.html>.
+ */
+/* ACKNOWLEDGMENTS:
+ * This work was initially developed by Pierangelo Masarati for inclusion
+ * in OpenLDAP Software, sponsored by SysNet s.r.l.
+ */
+
+#include "portable.h"
+
+#ifdef SLAPD_OVER_MEMBEROF
+
+#include <stdio.h>
+
+#include "ac/string.h"
+#include "ac/socket.h"
+
+#include "slap.h"
+#include "config.h"
+#include "lutil.h"
+
+/*
+ * Glossary:
+ *
+ * GROUP a group object (an entry with GROUP_OC
+ * objectClass)
+ * MEMBER a member object (an entry whose DN is
+ * listed as MEMBER_AT value of a GROUP)
+ * GROUP_OC the objectClass of the group object
+ * (default: groupOfNames)
+ * MEMBER_AT the membership attribute, DN-valued;
+ * note: nameAndOptionalUID is tolerated
+ * as soon as the optionalUID is absent
+ * (default: member)
+ * MEMBER_OF reverse membership attribute
+ * (default: memberOf)
+ *
+ * - add:
+ * - if the entry that is being added is a GROUP,
+ * the MEMBER_AT defined as values of the add operation
+ * get the MEMBER_OF value directly from the request.
+ *
+ * if configured to do so, the MEMBER objects do not exist,
+ * and no relax control is issued, either:
+ * - fail
+ * - drop non-existing members
+ * (by default: don't muck with values)
+ *
+ * - if (configured to do so,) the referenced GROUP exists,
+ * the relax control is set and the user has
+ * "manage" privileges, allow to add MEMBER_OF values to
+ * generic entries.
+ *
+ * - modify:
+ * - if the entry being modified is a GROUP_OC and the
+ * MEMBER_AT attribute is modified, the MEMBER_OF value
+ * of the (existing) MEMBER_AT entries that are affected
+ * is modified according to the request:
+ * - if a MEMBER is removed from the group,
+ * delete the corresponding MEMBER_OF
+ * - if a MEMBER is added to a group,
+ * add the corresponding MEMBER_OF
+ *
+ * We need to determine, from the database, if it is
+ * a GROUP_OC, and we need to check, from the
+ * modification list, if the MEMBER_AT attribute is being
+ * affected, and what MEMBER_AT values are affected.
+ *
+ * if configured to do so, the entries corresponding to
+ * the MEMBER_AT values do not exist, and no relax control
+ * is issued, either:
+ * - fail
+ * - drop non-existing members
+ * (by default: don't muck with values)
+ *
+ * - if configured to do so, the referenced GROUP exists,
+ * (the relax control is set) and the user has
+ * "manage" privileges, allow to add MEMBER_OF values to
+ * generic entries; the change is NOT automatically reflected
+ * in the MEMBER attribute of the GROUP referenced
+ * by the value of MEMBER_OF; a separate modification,
+ * with or without relax control, needs to be performed.
+ *
+ * - modrdn:
+ * - if the entry being renamed is a GROUP, the MEMBER_OF
+ * value of the (existing) MEMBER objects is modified
+ * accordingly based on the newDN of the GROUP.
+ *
+ * We need to determine, from the database, if it is
+ * a GROUP; the list of MEMBER objects is obtained from
+ * the database.
+ *
+ * Non-existing MEMBER objects are ignored, since the
+ * MEMBER_AT is not being addressed by the operation.
+ *
+ * - if the entry being renamed has the MEMBER_OF attribute,
+ * the corresponding MEMBER value must be modified in the
+ * respective group entries.
+ *
+ *
+ * - delete:
+ * - if the entry being deleted is a GROUP, the (existing)
+ * MEMBER objects are modified accordingly; a copy of the
+ * values of the MEMBER_AT is saved and, if the delete
+ * succeeds, the MEMBER_OF value of the (existing) MEMBER
+ * objects is deleted.
+ *
+ * We need to determine, from the database, if it is
+ * a GROUP.
+ *
+ * Non-existing MEMBER objects are ignored, since the entry
+ * is being deleted.
+ *
+ * - if the entry being deleted has the MEMBER_OF attribute,
+ * the corresponding value of the MEMBER_AT must be deleted
+ * from the respective GROUP entries.
+ */
+
+#define SLAPD_MEMBEROF_ATTR "memberOf"
+
+static slap_overinst memberof;
+
+typedef struct memberof_t {
+ struct berval mo_dn;
+ struct berval mo_ndn;
+
+ ObjectClass *mo_oc_group;
+ AttributeDescription *mo_ad_member;
+ AttributeDescription *mo_ad_memberof;
+
+ struct berval mo_groupFilterstr;
+ AttributeAssertion mo_groupAVA;
+ Filter mo_groupFilter;
+
+ struct berval mo_memberFilterstr;
+ Filter mo_memberFilter;
+
+ unsigned mo_flags;
+#define MEMBEROF_NONE 0x00U
+#define MEMBEROF_FDANGLING_DROP 0x01U
+#define MEMBEROF_FDANGLING_ERROR 0x02U
+#define MEMBEROF_FDANGLING_MASK (MEMBEROF_FDANGLING_DROP|MEMBEROF_FDANGLING_ERROR)
+#define MEMBEROF_FREFINT 0x04U
+#define MEMBEROF_FREVERSE 0x08U
+
+#define MEMBEROF_CHK(mo,f) \
+ (((mo)->mo_flags & (f)) == (f))
+#define MEMBEROF_DANGLING_CHECK(mo) \
+ ((mo)->mo_flags & MEMBEROF_FDANGLING_MASK)
+#define MEMBEROF_DANGLING_DROP(mo) \
+ MEMBEROF_CHK((mo),MEMBEROF_FDANGLING_DROP)
+#define MEMBEROF_DANGLING_ERROR(mo) \
+ MEMBEROF_CHK((mo),MEMBEROF_FDANGLING_ERROR)
+#define MEMBEROF_REFINT(mo) \
+ MEMBEROF_CHK((mo),MEMBEROF_FREFINT)
+#define MEMBEROF_REVERSE(mo) \
+ MEMBEROF_CHK((mo),MEMBEROF_FREVERSE)
+} memberof_t;
+
+typedef enum memberof_is_t {
+ MEMBEROF_IS_NONE = 0x00,
+ MEMBEROF_IS_GROUP = 0x01,
+ MEMBEROF_IS_MEMBER = 0x02,
+ MEMBEROF_IS_BOTH = (MEMBEROF_IS_GROUP|MEMBEROF_IS_MEMBER)
+} memberof_is_t;
+
+/*
+ * failover storage for member attribute values of groups being deleted
+ * handles [no]thread cases.
+ */
+static BerVarray saved_member_vals;
+static BerVarray saved_memberof_vals;
+
+static void
+memberof_saved_member_free( void *key, void *data )
+{
+ ber_bvarray_free( (BerVarray)data );
+}
+
+static BerVarray
+memberof_saved_member_get( Operation *op, void *keyp )
+{
+ BerVarray vals;
+ BerVarray *key = (BerVarray *)keyp;
+
+ assert( op );
+
+ if ( op->o_threadctx == NULL ) {
+ vals = *key;
+ *key = NULL;
+
+ } else {
+ ldap_pvt_thread_pool_getkey( op->o_threadctx,
+ key, (void **)&vals, NULL );
+ ldap_pvt_thread_pool_setkey( op->o_threadctx,
+ key, NULL, NULL );
+ }
+
+ return vals;
+}
+
+static void
+memberof_saved_member_set( Operation *op, void *keyp, BerVarray vals )
+{
+ BerVarray saved_vals = NULL;
+ BerVarray *key = (BerVarray*)keyp;
+
+ assert( op );
+
+ if ( vals ) {
+ ber_bvarray_dup_x( &saved_vals, vals, NULL );
+ }
+
+ if ( op->o_threadctx == NULL ) {
+ if ( *key ) {
+ ber_bvarray_free( *key );
+ }
+ *key = saved_vals;
+
+ } else {
+ ldap_pvt_thread_pool_setkey( op->o_threadctx, key,
+ saved_vals, memberof_saved_member_free );
+ }
+}
+
+typedef struct memberof_cookie_t {
+ AttributeDescription *ad;
+ void *key;
+ int foundit;
+} memberof_cookie_t;
+
+static int
+memberof_isGroupOrMember_cb( Operation *op, SlapReply *rs )
+{
+ if ( rs->sr_type == REP_SEARCH ) {
+ memberof_cookie_t *mc;
+
+ mc = (memberof_cookie_t *)op->o_callback->sc_private;
+ mc->foundit = 1;
+ }
+
+ return 0;
+}
+
+/*
+ * callback for internal search that saves the member attribute values
+ * of groups being deleted.
+ */
+static int
+memberof_saveMember_cb( Operation *op, SlapReply *rs )
+{
+ if ( rs->sr_type == REP_SEARCH ) {
+ memberof_cookie_t *mc;
+ Attribute *a;
+
+ mc = (memberof_cookie_t *)op->o_callback->sc_private;
+ mc->foundit = 1;
+
+ assert( rs->sr_entry );
+ assert( rs->sr_entry->e_attrs );
+
+ a = attr_find( rs->sr_entry->e_attrs, mc->ad );
+
+ assert( a != NULL );
+
+ memberof_saved_member_set( op, mc->key, a->a_nvals );
+
+ if ( attr_find( a->a_next, mc->ad ) != NULL ) {
+ Debug( LDAP_DEBUG_ANY,
+ "%s: memberof_saveMember_cb(\"%s\"): "
+ "more than one occurrence of \"%s\" "
+ "attribute.\n",
+ op->o_log_prefix,
+ rs->sr_entry->e_name.bv_val,
+ mc->ad->ad_cname.bv_val );
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * the delete hook performs an internal search that saves the member
+ * attribute values of groups being deleted.
+ */
+static int
+memberof_isGroupOrMember( Operation *op, memberof_is_t *iswhatp )
+{
+ slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
+ memberof_t *mo = (memberof_t *)on->on_bi.bi_private;
+
+ Operation op2 = *op;
+ SlapReply rs2 = { REP_RESULT };
+ slap_callback cb = { 0 };
+ memberof_cookie_t mc;
+ AttributeName an[ 2 ];
+
+ memberof_is_t iswhat = MEMBEROF_IS_NONE;
+
+ assert( iswhatp != NULL );
+ assert( *iswhatp != MEMBEROF_IS_NONE );
+
+ cb.sc_private = &mc;
+ if ( op->o_tag == LDAP_REQ_DELETE ) {
+ cb.sc_response = memberof_saveMember_cb;
+
+ } else {
+ cb.sc_response = memberof_isGroupOrMember_cb;
+ }
+
+ op2.o_tag = LDAP_REQ_SEARCH;
+ op2.o_callback = &cb;
+ op2.o_dn = op->o_bd->be_rootdn;
+ op2.o_ndn = op->o_bd->be_rootndn;
+
+ op2.ors_scope = LDAP_SCOPE_BASE;
+ op2.ors_deref = LDAP_DEREF_NEVER;
+ BER_BVZERO( &an[ 1 ].an_name );
+ op2.ors_attrs = an;
+ op2.ors_attrsonly = 0;
+ op2.ors_limit = NULL;
+ op2.ors_slimit = 1;
+ op2.ors_tlimit = SLAP_NO_LIMIT;
+
+ if ( *iswhatp & MEMBEROF_IS_GROUP ) {
+ mc.ad = mo->mo_ad_member;
+ mc.key = &saved_member_vals;
+ mc.foundit = 0;
+ an[ 0 ].an_desc = mo->mo_ad_member;
+ an[ 0 ].an_name = an[ 0 ].an_desc->ad_cname;
+ op2.ors_filterstr = mo->mo_groupFilterstr;
+ op2.ors_filter = &mo->mo_groupFilter;
+
+ op2.o_bd->bd_info = (BackendInfo *)on->on_info;
+ (void)op->o_bd->be_search( &op2, &rs2 );
+ op2.o_bd->bd_info = (BackendInfo *)on;
+
+ if ( mc.foundit ) {
+ iswhat |= MEMBEROF_IS_GROUP;
+
+ } else {
+ memberof_saved_member_set( op, mc.key, NULL );
+ }
+ }
+
+ if ( *iswhatp & MEMBEROF_IS_MEMBER ) {
+ mc.ad = mo->mo_ad_memberof;
+ mc.key = &saved_memberof_vals;
+ mc.foundit = 0;
+ an[ 0 ].an_desc = mo->mo_ad_memberof;
+ an[ 0 ].an_name = an[ 0 ].an_desc->ad_cname;
+ op2.ors_filterstr = mo->mo_memberFilterstr;
+ op2.ors_filter = &mo->mo_memberFilter;
+
+ op2.o_bd->bd_info = (BackendInfo *)on->on_info;
+ (void)op->o_bd->be_search( &op2, &rs2 );
+ op2.o_bd->bd_info = (BackendInfo *)on;
+
+ if ( mc.foundit ) {
+ iswhat |= MEMBEROF_IS_MEMBER;
+
+ } else {
+ memberof_saved_member_set( op, mc.key, NULL );
+ }
+ }
+
+ *iswhatp = iswhat;
+
+ return LDAP_SUCCESS;
+}
+
+/*
+ * response callback that adds memberof values when a group is modified.
+ */
+static int
+memberof_value_modify(
+ Operation *op,
+ SlapReply *rs,
+ struct berval *ndn,
+ AttributeDescription *ad,
+ struct berval *old_dn,
+ struct berval *old_ndn,
+ struct berval *new_dn,
+ struct berval *new_ndn )
+{
+ slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
+ memberof_t *mo = (memberof_t *)on->on_bi.bi_private;
+
+ Operation op2 = *op;
+ SlapReply rs2 = { REP_RESULT };
+ slap_callback cb = { NULL, slap_null_cb, NULL, NULL };
+ Modifications mod[ 2 ] = { { { 0 } } }, *ml;
+ struct berval values[ 4 ], nvalues[ 4 ];
+
+ op2.o_tag = LDAP_REQ_MODIFY;
+
+ op2.o_req_dn = *ndn;
+ op2.o_req_ndn = *ndn;
+
+ op2.o_bd->bd_info = (BackendInfo *)on->on_info;
+
+ op2.o_callback = &cb;
+ op2.o_dn = op->o_bd->be_rootdn;
+ op2.o_ndn = op->o_bd->be_rootndn;
+
+ ml = &mod[ 0 ];
+ ml->sml_values = &values[ 0 ];
+ ml->sml_values[ 0 ] = mo->mo_dn;
+ BER_BVZERO( &ml->sml_values[ 1 ] );
+ ml->sml_nvalues = &nvalues[ 0 ];
+ ml->sml_nvalues[ 0 ] = mo->mo_ndn;
+ BER_BVZERO( &ml->sml_nvalues[ 1 ] );
+ ml->sml_desc = slap_schema.si_ad_modifiersName;
+ ml->sml_type = ml->sml_desc->ad_cname;
+ ml->sml_op = LDAP_MOD_REPLACE;
+ ml->sml_flags = SLAP_MOD_INTERNAL;
+ ml->sml_next = NULL;
+ op2.orm_modlist = ml;
+
+ ml = &mod[ 1 ];
+ ml->sml_values = &values[ 2 ];
+ BER_BVZERO( &ml->sml_values[ 1 ] );
+ ml->sml_nvalues = &nvalues[ 2 ];
+ BER_BVZERO( &ml->sml_nvalues[ 1 ] );
+ ml->sml_desc = ad;
+ ml->sml_type = ml->sml_desc->ad_cname;
+ ml->sml_flags = SLAP_MOD_INTERNAL;
+ ml->sml_next = NULL;
+ op2.orm_modlist->sml_next = ml;
+
+ if ( new_ndn != NULL ) {
+ assert( !BER_BVISNULL( new_dn ) );
+ assert( !BER_BVISNULL( new_ndn ) );
+
+ ml->sml_op = LDAP_MOD_ADD;
+
+ ml->sml_values[ 0 ] = *new_dn;
+ ml->sml_nvalues[ 0 ] = *new_ndn;
+
+ (void)op->o_bd->be_modify( &op2, &rs2 );
+
+ assert( op2.orm_modlist == &mod[ 0 ] );
+ assert( op2.orm_modlist->sml_next == &mod[ 1 ] );
+ ml = op2.orm_modlist->sml_next->sml_next;
+ if ( ml != NULL ) {
+ slap_mods_free( ml, 1 );
+ }
+ }
+
+ if ( old_ndn != NULL ) {
+ assert( !BER_BVISNULL( old_dn ) );
+ assert( !BER_BVISNULL( old_ndn ) );
+
+ ml->sml_op = LDAP_MOD_DELETE;
+
+ ml->sml_values[ 0 ] = *old_dn;
+ ml->sml_nvalues[ 0 ] = *old_ndn;
+
+ (void)op->o_bd->be_modify( &op2, &rs2 );
+
+ assert( op2.orm_modlist == &mod[ 0 ] );
+ assert( op2.orm_modlist->sml_next == &mod[ 1 ] );
+ ml = op2.orm_modlist->sml_next->sml_next;
+ if ( ml != NULL ) {
+ slap_mods_free( ml, 1 );
+ }
+ }
+
+ /* FIXME: if old_group_ndn doesn't exist, both delete __and__
+ * add will fail; better split in two operations, although
+ * not optimal in terms of performance. At least it would
+ * move towards self-repairing capabilities. */
+
+ op2.o_bd->bd_info = (BackendInfo *)on;
+
+ return rs2.sr_err;
+}
+
+static int
+memberof_op_add( Operation *op, SlapReply *rs )
+{
+ slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
+ memberof_t *mo = (memberof_t *)on->on_bi.bi_private;
+
+ Attribute **ap, **map = NULL;
+ int rc = SLAP_CB_CONTINUE;
+ int i;
+ struct berval save_dn, save_ndn;
+
+ if ( op->ora_e->e_attrs == NULL ) {
+ /* FIXME: global overlay; need to deal with */
+ Debug( LDAP_DEBUG_ANY, "%s: memberof_op_add(\"%s\"): "
+ "consistency checks not implemented when overlay "
+ "is instantiated as global.\n",
+ op->o_log_prefix, op->o_req_dn.bv_val, 0 );
+ return SLAP_CB_CONTINUE;
+ }
+
+ if ( MEMBEROF_REVERSE( mo ) ) {
+ for ( ap = &op->ora_e->e_attrs; *ap; ap = &(*ap)->a_next ) {
+ Attribute *a = *ap;
+
+ if ( a->a_desc == mo->mo_ad_memberof ) {
+ map = ap;
+ break;
+ }
+ }
+ }
+
+ save_dn = op->o_dn;
+ save_ndn = op->o_ndn;
+
+ if ( MEMBEROF_DANGLING_CHECK( mo )
+ && !get_relax( op )
+ && is_entry_objectclass( op->ora_e, mo->mo_oc_group, 0 ) )
+ {
+ op->o_dn = op->o_bd->be_rootdn;
+ op->o_dn = op->o_bd->be_rootndn;
+ op->o_bd->bd_info = (BackendInfo *)on->on_info;
+
+ for ( ap = &op->ora_e->e_attrs; *ap; ) {
+ Attribute *a = *ap;
+
+ if ( !is_ad_subtype( a->a_desc, mo->mo_ad_member ) ) {
+ ap = &a->a_next;
+ continue;
+ }
+
+ assert( a->a_nvals != NULL );
+
+ for ( i = 0; !BER_BVISNULL( &a->a_nvals[ i ] ); i++ ) {
+ Entry *e;
+
+ /* FIXME: entry_get_rw does not pass
+ * thru overlays yet; when it does, we
+ * might need to make a copy of the DN */
+
+ rc = be_entry_get_rw( op, &a->a_nvals[ i ],
+ NULL, NULL, 0, &e );
+ if ( rc == LDAP_SUCCESS ) {
+ be_entry_release_r( op, e );
+ continue;
+ }
+
+ if ( MEMBEROF_DANGLING_ERROR( mo ) ) {
+ rc = rs->sr_err = LDAP_CONSTRAINT_VIOLATION;
+ rs->sr_text = "adding non-existing object "
+ "as group member";
+ send_ldap_result( op, rs );
+ goto done;
+ }
+
+ if ( MEMBEROF_DANGLING_DROP( mo ) ) {
+ int j;
+
+ Debug( LDAP_DEBUG_ANY, "%s: memberof_op_add(\"%s\"): "
+ "member=\"%s\" does not exist (stripping...)\n",
+ op->o_log_prefix, op->ora_e->e_name.bv_val,
+ a->a_vals[ i ].bv_val );
+
+ for ( j = i + 1; !BER_BVISNULL( &a->a_nvals[ j ] ); j++ );
+ ber_memfree( a->a_vals[ i ].bv_val );
+ BER_BVZERO( &a->a_vals[ i ] );
+ if ( a->a_nvals != a->a_vals ) {
+ ber_memfree( a->a_nvals[ i ].bv_val );
+ BER_BVZERO( &a->a_nvals[ i ] );
+ }
+ if ( j - i == 1 ) {
+ break;
+ }
+
+ AC_MEMCPY( &a->a_vals[ i ], &a->a_vals[ i + 1 ],
+ sizeof( struct berval ) * ( j - i ) );
+ if ( a->a_nvals != a->a_vals ) {
+ AC_MEMCPY( &a->a_nvals[ i ], &a->a_nvals[ i + 1 ],
+ sizeof( struct berval ) * ( j - i ) );
+ }
+ i--;
+ }
+ }
+
+ /* If all values have been removed,
+ * remove the attribute itself. */
+ if ( BER_BVISNULL( &a->a_nvals[ 0 ] ) ) {
+ *ap = a->a_next;
+ attr_free( a );
+
+ } else {
+ ap = &a->a_next;
+ }
+ }
+ op->o_dn = save_dn;
+ op->o_ndn = save_ndn;
+ op->o_bd->bd_info = (BackendInfo *)on;
+ }
+
+ if ( map != NULL ) {
+ Attribute *a = *map;
+ AccessControlState acl_state = ACL_STATE_INIT;
+
+ for ( i = 0; !BER_BVISNULL( &a->a_nvals[ i ] ); i++ ) {
+ Entry *e;
+
+ op->o_bd->bd_info = (BackendInfo *)on->on_info;
+ /* access is checked with the original identity */
+ rc = access_allowed( op, op->ora_e, mo->mo_ad_memberof,
+ &a->a_nvals[ i ], ACL_WADD,
+ &acl_state );
+ if ( rc == 0 ) {
+ rc = rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
+ rs->sr_text = NULL;
+ send_ldap_result( op, rs );
+ goto done;
+ }
+ rc = be_entry_get_rw( op, &a->a_nvals[ i ],
+ NULL, NULL, 0, &e );
+ op->o_bd->bd_info = (BackendInfo *)on;
+ if ( rc != LDAP_SUCCESS ) {
+ if ( get_relax( op ) ) {
+ continue;
+ }
+
+ if ( MEMBEROF_DANGLING_ERROR( mo ) ) {
+ rc = rs->sr_err = LDAP_CONSTRAINT_VIOLATION;
+ rs->sr_text = "adding non-existing object "
+ "as memberof";
+ send_ldap_result( op, rs );
+ goto done;
+ }
+
+ if ( MEMBEROF_DANGLING_DROP( mo ) ) {
+ int j;
+
+ Debug( LDAP_DEBUG_ANY, "%s: memberof_op_add(\"%s\"): "
+ "memberof=\"%s\" does not exist (stripping...)\n",
+ op->o_log_prefix, op->ora_e->e_name.bv_val,
+ a->a_nvals[ i ].bv_val );
+
+ for ( j = i + 1; !BER_BVISNULL( &a->a_nvals[ j ] ); j++ );
+ ber_memfree( a->a_vals[ i ].bv_val );
+ BER_BVZERO( &a->a_vals[ i ] );
+ if ( a->a_nvals != a->a_vals ) {
+ ber_memfree( a->a_nvals[ i ].bv_val );
+ BER_BVZERO( &a->a_nvals[ i ] );
+ }
+ if ( j - i == 1 ) {
+ break;
+ }
+
+ AC_MEMCPY( &a->a_vals[ i ], &a->a_vals[ i + 1 ],
+ sizeof( struct berval ) * ( j - i ) );
+ if ( a->a_nvals != a->a_vals ) {
+ AC_MEMCPY( &a->a_nvals[ i ], &a->a_nvals[ i + 1 ],
+ sizeof( struct berval ) * ( j - i ) );
+ }
+ i--;
+ }
+
+ continue;
+ }
+
+ /* access is checked with the original identity */
+ op->o_bd->bd_info = (BackendInfo *)on->on_info;
+ rc = access_allowed( op, e, mo->mo_ad_member,
+ &op->o_req_ndn, ACL_WADD, NULL );
+ be_entry_release_r( op, e );
+ op->o_bd->bd_info = (BackendInfo *)on;
+
+ if ( !rc ) {
+ rc = rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
+ rs->sr_text = "insufficient access to object referenced by memberof";
+ send_ldap_result( op, rs );
+ goto done;
+ }
+ }
+
+ if ( BER_BVISNULL( &a->a_nvals[ 0 ] ) ) {
+ *map = a->a_next;
+ attr_free( a );
+ }
+ }
+
+ rc = SLAP_CB_CONTINUE;
+
+done:;
+ op->o_dn = save_dn;
+ op->o_ndn = save_ndn;
+ op->o_bd->bd_info = (BackendInfo *)on;
+
+ return rc;
+}
+
+static int
+memberof_op_delete( Operation *op, SlapReply *rs )
+{
+ slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
+ memberof_t *mo = (memberof_t *)on->on_bi.bi_private;
+
+ memberof_is_t iswhat = MEMBEROF_IS_GROUP;
+
+ if ( MEMBEROF_REFINT( mo ) ) {
+ iswhat = MEMBEROF_IS_BOTH;
+ }
+
+ memberof_isGroupOrMember( op, &iswhat );
+
+ return SLAP_CB_CONTINUE;
+}
+
+static int
+memberof_op_modify( Operation *op, SlapReply *rs )
+{
+ slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
+ memberof_t *mo = (memberof_t *)on->on_bi.bi_private;
+
+ Modifications **mlp, **mmlp = NULL;
+ int rc = SLAP_CB_CONTINUE;
+ struct berval save_dn, save_ndn;
+ memberof_is_t iswhat = MEMBEROF_IS_GROUP;
+
+ if ( MEMBEROF_REVERSE( mo ) ) {
+ for ( mlp = &op->orm_modlist; *mlp; mlp = &(*mlp)->sml_next ) {
+ Modifications *ml = *mlp;
+
+ if ( ml->sml_desc == mo->mo_ad_memberof ) {
+ mmlp = mlp;
+ break;
+ }
+ }
+ }
+
+ save_dn = op->o_dn;
+ save_ndn = op->o_ndn;
+
+ if ( MEMBEROF_DANGLING_CHECK( mo )
+ && !get_relax( op )
+ && memberof_isGroupOrMember( op, &iswhat ) == LDAP_SUCCESS
+ && ( iswhat & MEMBEROF_IS_GROUP ) )
+ {
+ op->o_dn = op->o_bd->be_rootdn;
+ op->o_dn = op->o_bd->be_rootndn;
+ op->o_bd->bd_info = (BackendInfo *)on->on_info;
+
+ assert( op->orm_modlist != NULL );
+
+ for ( mlp = &op->orm_modlist; *mlp; ) {
+ Modifications *ml = *mlp;
+ int i;
+
+ if ( !is_ad_subtype( ml->sml_desc, mo->mo_ad_member ) ) {
+ mlp = &ml->sml_next;
+ continue;
+ }
+
+ switch ( ml->sml_op ) {
+ case LDAP_MOD_DELETE:
+ /* we don't care about cancellations: if the value
+ * exists, fine; if it doesn't, we let the underlying
+ * database fail as appropriate; */
+ mlp = &ml->sml_next;
+ break;
+
+ case LDAP_MOD_REPLACE:
+ case LDAP_MOD_ADD:
+ /* NOTE: right now, the attributeType we use
+ * for member must have a normalized value */
+ assert( ml->sml_nvalues );
+
+ for ( i = 0; !BER_BVISNULL( &ml->sml_nvalues[ i ] ); i++ ) {
+ int rc;
+ Entry *e;
+
+ if ( be_entry_get_rw( op, &ml->sml_nvalues[ i ],
+ NULL, NULL, 0, &e ) == LDAP_SUCCESS )
+ {
+ be_entry_release_r( op, e );
+ continue;
+ }
+
+ if ( MEMBEROF_DANGLING_ERROR( mo ) ) {
+ rc = rs->sr_err = LDAP_CONSTRAINT_VIOLATION;
+ rs->sr_text = "adding non-existing object "
+ "as group member";
+ send_ldap_result( op, rs );
+ goto done;
+ }
+
+ if ( MEMBEROF_DANGLING_DROP( mo ) ) {
+ int j;
+
+ Debug( LDAP_DEBUG_ANY, "%s: memberof_op_modify(\"%s\"): "
+ "member=\"%s\" does not exist (stripping...)\n",
+ op->o_log_prefix, op->o_req_dn.bv_val,
+ ml->sml_nvalues[ i ].bv_val );
+
+ for ( j = i + 1; !BER_BVISNULL( &ml->sml_nvalues[ j ] ); j++ );
+ ber_memfree( ml->sml_values[ i ].bv_val );
+ BER_BVZERO( &ml->sml_values[ i ] );
+ ber_memfree( ml->sml_nvalues[ i ].bv_val );
+ BER_BVZERO( &ml->sml_nvalues[ i ] );
+ if ( j - i == 1 ) {
+ break;
+ }
+
+ AC_MEMCPY( &ml->sml_values[ i ], &ml->sml_values[ i + 1 ],
+ sizeof( struct berval ) * ( j - i ) );
+ AC_MEMCPY( &ml->sml_nvalues[ i ], &ml->sml_nvalues[ i + 1 ],
+ sizeof( struct berval ) * ( j - i ) );
+ i--;
+ }
+ }
+
+ if ( BER_BVISNULL( &ml->sml_nvalues[ 0 ] ) ) {
+ *mlp = ml->sml_next;
+ slap_mod_free( &ml->sml_mod, 0 );
+ free( ml );
+
+ } else {
+ mlp = &ml->sml_next;
+ }
+
+ break;
+
+ default:
+ assert( 0 );
+ }
+ }
+ }
+
+ if ( mmlp != NULL ) {
+ Modifications *ml = *mmlp;
+ int i;
+ Entry *target;
+
+ op->o_bd->bd_info = (BackendInfo *)on->on_info;
+ rc = be_entry_get_rw( op, &op->o_req_ndn,
+ NULL, NULL, 0, &target );
+ op->o_bd->bd_info = (BackendInfo *)on;
+ if ( rc != LDAP_SUCCESS ) {
+ rc = rs->sr_err = LDAP_NO_SUCH_OBJECT;
+ send_ldap_result( op, rs );
+ goto done;
+ }
+
+ switch ( ml->sml_op ) {
+ case LDAP_MOD_DELETE:
+ if ( ml->sml_nvalues != NULL ) {
+ AccessControlState acl_state = ACL_STATE_INIT;
+
+ for ( i = 0; !BER_BVISNULL( &ml->sml_nvalues[ i ] ); i++ ) {
+ Entry *e;
+
+ op->o_bd->bd_info = (BackendInfo *)on->on_info;
+ /* access is checked with the original identity */
+ rc = access_allowed( op, target,
+ mo->mo_ad_memberof,
+ &ml->sml_nvalues[ i ],
+ ACL_WDEL,
+ &acl_state );
+ if ( rc == 0 ) {
+ rc = rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
+ rs->sr_text = NULL;
+ send_ldap_result( op, rs );
+ goto done2;
+ }
+
+ rc = be_entry_get_rw( op, &ml->sml_nvalues[ i ],
+ NULL, NULL, 0, &e );
+ op->o_bd->bd_info = (BackendInfo *)on;
+ if ( rc != LDAP_SUCCESS ) {
+ if ( get_relax( op ) ) {
+ continue;
+ }
+
+ if ( MEMBEROF_DANGLING_ERROR( mo ) ) {
+ rc = rs->sr_err = LDAP_CONSTRAINT_VIOLATION;
+ rs->sr_text = "deleting non-existing object "
+ "as memberof";
+ send_ldap_result( op, rs );
+ goto done2;
+ }
+
+ if ( MEMBEROF_DANGLING_DROP( mo ) ) {
+ int j;
+
+ Debug( LDAP_DEBUG_ANY, "%s: memberof_op_modify(\"%s\"): "
+ "memberof=\"%s\" does not exist (stripping...)\n",
+ op->o_log_prefix, op->o_req_ndn.bv_val,
+ ml->sml_nvalues[ i ].bv_val );
+
+ for ( j = i + 1; !BER_BVISNULL( &ml->sml_nvalues[ j ] ); j++ );
+ ber_memfree( ml->sml_values[ i ].bv_val );
+ BER_BVZERO( &ml->sml_values[ i ] );
+ if ( ml->sml_nvalues != ml->sml_values ) {
+ ber_memfree( ml->sml_nvalues[ i ].bv_val );
+ BER_BVZERO( &ml->sml_nvalues[ i ] );
+ }
+ if ( j - i == 1 ) {
+ break;
+ }
+
+ AC_MEMCPY( &ml->sml_values[ i ], &ml->sml_values[ i + 1 ],
+ sizeof( struct berval ) * ( j - i ) );
+ if ( ml->sml_nvalues != ml->sml_values ) {
+ AC_MEMCPY( &ml->sml_nvalues[ i ], &ml->sml_nvalues[ i + 1 ],
+ sizeof( struct berval ) * ( j - i ) );
+ }
+ i--;
+ }
+
+ continue;
+ }
+
+ /* access is checked with the original identity */
+ op->o_bd->bd_info = (BackendInfo *)on->on_info;
+ rc = access_allowed( op, e, mo->mo_ad_member,
+ &op->o_req_ndn,
+ ACL_WDEL, NULL );
+ be_entry_release_r( op, e );
+ op->o_bd->bd_info = (BackendInfo *)on;
+
+ if ( !rc ) {
+ rc = rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
+ rs->sr_text = "insufficient access to object referenced by memberof";
+ send_ldap_result( op, rs );
+ goto done;
+ }
+ }
+
+ if ( BER_BVISNULL( &ml->sml_nvalues[ 0 ] ) ) {
+ *mmlp = ml->sml_next;
+ slap_mod_free( &ml->sml_mod, 0 );
+ free( ml );
+ }
+
+ break;
+ }
+ /* fall thru */
+
+ case LDAP_MOD_REPLACE:
+
+ op->o_bd->bd_info = (BackendInfo *)on->on_info;
+ /* access is checked with the original identity */
+ rc = access_allowed( op, target,
+ mo->mo_ad_memberof,
+ NULL,
+ ACL_WDEL, NULL );
+ op->o_bd->bd_info = (BackendInfo *)on;
+ if ( rc == 0 ) {
+ rc = rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
+ rs->sr_text = NULL;
+ send_ldap_result( op, rs );
+ goto done2;
+ }
+
+ if ( ml->sml_op == LDAP_MOD_DELETE ) {
+ break;
+ }
+ /* fall thru */
+
+ case LDAP_MOD_ADD: {
+ AccessControlState acl_state = ACL_STATE_INIT;
+
+ for ( i = 0; !BER_BVISNULL( &ml->sml_nvalues[ i ] ); i++ ) {
+ Entry *e;
+
+ op->o_bd->bd_info = (BackendInfo *)on->on_info;
+ /* access is checked with the original identity */
+ rc = access_allowed( op, target,
+ mo->mo_ad_memberof,
+ &ml->sml_nvalues[ i ],
+ ACL_WADD,
+ &acl_state );
+ if ( rc == 0 ) {
+ rc = rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
+ rs->sr_text = NULL;
+ send_ldap_result( op, rs );
+ goto done2;
+ }
+
+ rc = be_entry_get_rw( op, &ml->sml_nvalues[ i ],
+ NULL, NULL, 0, &e );
+ op->o_bd->bd_info = (BackendInfo *)on;
+ if ( rc != LDAP_SUCCESS ) {
+ if ( MEMBEROF_DANGLING_ERROR( mo ) ) {
+ rc = rs->sr_err = LDAP_CONSTRAINT_VIOLATION;
+ rs->sr_text = "adding non-existing object "
+ "as memberof";
+ send_ldap_result( op, rs );
+ goto done2;
+ }
+
+ if ( MEMBEROF_DANGLING_DROP( mo ) ) {
+ int j;
+
+ Debug( LDAP_DEBUG_ANY, "%s: memberof_op_modify(\"%s\"): "
+ "memberof=\"%s\" does not exist (stripping...)\n",
+ op->o_log_prefix, op->o_req_ndn.bv_val,
+ ml->sml_nvalues[ i ].bv_val );
+
+ for ( j = i + 1; !BER_BVISNULL( &ml->sml_nvalues[ j ] ); j++ );
+ ber_memfree( ml->sml_values[ i ].bv_val );
+ BER_BVZERO( &ml->sml_values[ i ] );
+ if ( ml->sml_nvalues != ml->sml_values ) {
+ ber_memfree( ml->sml_nvalues[ i ].bv_val );
+ BER_BVZERO( &ml->sml_nvalues[ i ] );
+ }
+ if ( j - i == 1 ) {
+ break;
+ }
+
+ AC_MEMCPY( &ml->sml_values[ i ], &ml->sml_values[ i + 1 ],
+ sizeof( struct berval ) * ( j - i ) );
+ if ( ml->sml_nvalues != ml->sml_values ) {
+ AC_MEMCPY( &ml->sml_nvalues[ i ], &ml->sml_nvalues[ i + 1 ],
+ sizeof( struct berval ) * ( j - i ) );
+ }
+ i--;
+ }
+
+ continue;
+ }
+
+ /* access is checked with the original identity */
+ op->o_bd->bd_info = (BackendInfo *)on->on_info;
+ rc = access_allowed( op, e, mo->mo_ad_member,
+ &op->o_req_ndn,
+ ACL_WDEL, NULL );
+ be_entry_release_r( op, e );
+ op->o_bd->bd_info = (BackendInfo *)on;
+
+ if ( !rc ) {
+ rc = rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
+ rs->sr_text = "insufficient access to object referenced by memberof";
+ send_ldap_result( op, rs );
+ goto done;
+ }
+ }
+
+ if ( BER_BVISNULL( &ml->sml_nvalues[ 0 ] ) ) {
+ *mmlp = ml->sml_next;
+ slap_mod_free( &ml->sml_mod, 0 );
+ free( ml );
+ }
+
+ } break;
+
+ default:
+ assert( 0 );
+ }
+
+done2:;
+ op->o_bd->bd_info = (BackendInfo *)on->on_info;
+ be_entry_release_r( op, target );
+ op->o_bd->bd_info = (BackendInfo *)on;
+ }
+
+ rc = SLAP_CB_CONTINUE;
+
+done:;
+ op->o_dn = save_dn;
+ op->o_ndn = save_ndn;
+ op->o_bd->bd_info = (BackendInfo *)on;
+
+ return rc;
+}
+
+/*
+ * response callback that adds memberof values when a group is added.
+ */
+static int
+memberof_res_add( Operation *op, SlapReply *rs )
+{
+ slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
+ memberof_t *mo = (memberof_t *)on->on_bi.bi_private;
+
+ int i;
+
+ if ( MEMBEROF_REVERSE( mo ) ) {
+ Attribute *ma;
+
+ ma = attr_find( op->ora_e->e_attrs, mo->mo_ad_memberof );
+ if ( ma != NULL ) {
+ Operation op2 = *op;
+ SlapReply rs2 = { 0 };
+
+ /* relax is required to allow to add
+ * a non-existing member */
+ op2.o_relax = SLAP_CONTROL_CRITICAL;
+
+ for ( i = 0; !BER_BVISNULL( &ma->a_nvals[ i ] ); i++ ) {
+
+ /* the modification is attempted
+ * with the original identity */
+ (void)memberof_value_modify( &op2, &rs2,
+ &ma->a_nvals[ i ], mo->mo_ad_member,
+ NULL, NULL, &op->o_req_dn, &op->o_req_ndn );
+ }
+ }
+ }
+
+ if ( is_entry_objectclass( op->ora_e, mo->mo_oc_group, 0 ) ) {
+ Attribute *a;
+
+ for ( a = attrs_find( op->ora_e->e_attrs, mo->mo_ad_member );
+ a != NULL;
+ a = attrs_find( a->a_next, mo->mo_ad_member ) )
+ {
+ for ( i = 0; !BER_BVISNULL( &a->a_nvals[ i ] ); i++ ) {
+ (void)memberof_value_modify( op, rs,
+ &a->a_nvals[ i ],
+ mo->mo_ad_memberof,
+ NULL, NULL,
+ &op->o_req_dn,
+ &op->o_req_ndn );
+ }
+ }
+ }
+
+ return SLAP_CB_CONTINUE;
+}
+
+/*
+ * response callback that deletes memberof values when a group is deleted.
+ */
+static int
+memberof_res_delete( Operation *op, SlapReply *rs )
+{
+ slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
+ memberof_t *mo = (memberof_t *)on->on_bi.bi_private;
+
+ BerVarray vals;
+ int i;
+
+ vals = memberof_saved_member_get( op, &saved_member_vals );
+ if ( vals != NULL ) {
+ for ( i = 0; !BER_BVISNULL( &vals[ i ] ); i++ ) {
+ (void)memberof_value_modify( op, rs,
+ &vals[ i ], mo->mo_ad_memberof,
+ &op->o_req_dn, &op->o_req_ndn,
+ NULL, NULL );
+ }
+
+ ber_bvarray_free( vals );
+ }
+
+ if ( MEMBEROF_REFINT( mo ) ) {
+ vals = memberof_saved_member_get( op, &saved_memberof_vals );
+ if ( vals != NULL ) {
+ for ( i = 0; !BER_BVISNULL( &vals[ i ] ); i++ ) {
+ (void)memberof_value_modify( op, rs,
+ &vals[ i ], mo->mo_ad_member,
+ &op->o_req_dn, &op->o_req_ndn,
+ NULL, NULL );
+ }
+
+ ber_bvarray_free( vals );
+ }
+ }
+
+ return SLAP_CB_CONTINUE;
+}
+
+/*
+ * response callback that adds/deletes memberof values when a group
+ * is modified.
+ */
+static int
+memberof_res_modify( Operation *op, SlapReply *rs )
+{
+ slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
+ memberof_t *mo = (memberof_t *)on->on_bi.bi_private;
+
+ int i, rc;
+ Modifications *ml, *mml = NULL;
+ BerVarray vals;
+ memberof_is_t iswhat = MEMBEROF_IS_GROUP;
+
+ if ( MEMBEROF_REVERSE( mo ) ) {
+ for ( ml = op->orm_modlist; ml; ml = ml->sml_next ) {
+ if ( ml->sml_desc == mo->mo_ad_memberof ) {
+ mml = ml;
+ break;
+ }
+ }
+ }
+
+ if ( mml != NULL ) {
+ BerVarray vals = mml->sml_nvalues;
+
+ switch ( mml->sml_op ) {
+ case LDAP_MOD_DELETE:
+ if ( vals != NULL ) {
+ for ( i = 0; !BER_BVISNULL( &vals[ i ] ); i++ ) {
+ memberof_value_modify( op, rs,
+ &vals[ i ], mo->mo_ad_member,
+ &op->o_req_dn, &op->o_req_ndn,
+ NULL, NULL );
+ }
+ break;
+ }
+ /* fall thru */
+
+ case LDAP_MOD_REPLACE:
+ /* delete all ... */
+ op->o_bd->bd_info = (BackendInfo *)on->on_info;
+ rc = backend_attribute( op, NULL, &op->o_req_ndn,
+ mo->mo_ad_memberof, &vals, ACL_READ );
+ op->o_bd->bd_info = (BackendInfo *)on;
+ if ( rc == LDAP_SUCCESS ) {
+ for ( i = 0; !BER_BVISNULL( &vals[ i ] ); i++ ) {
+ (void)memberof_value_modify( op, rs,
+ &vals[ i ], mo->mo_ad_member,
+ &op->o_req_dn, &op->o_req_ndn,
+ NULL, NULL );
+ }
+ ber_bvarray_free_x( vals, op->o_tmpmemctx );
+ }
+
+ if ( ml->sml_op == LDAP_MOD_DELETE ) {
+ break;
+ }
+ /* fall thru */
+
+ case LDAP_MOD_ADD:
+ assert( vals != NULL );
+
+ for ( i = 0; !BER_BVISNULL( &vals[ i ] ); i++ ) {
+ memberof_value_modify( op, rs,
+ &vals[ i ], mo->mo_ad_member,
+ NULL, NULL,
+ &op->o_req_dn, &op->o_req_ndn );
+ }
+ break;
+
+ default:
+ assert( 0 );
+ }
+ }
+
+ if ( memberof_isGroupOrMember( op, &iswhat ) == LDAP_SUCCESS
+ && ( iswhat & MEMBEROF_IS_GROUP ) )
+ {
+ for ( ml = op->orm_modlist; ml; ml = ml->sml_next ) {
+ if ( ml->sml_desc != mo->mo_ad_member ) {
+ continue;
+ }
+
+ switch ( ml->sml_op ) {
+ case LDAP_MOD_DELETE:
+ vals = ml->sml_nvalues;
+ if ( vals != NULL ) {
+ for ( i = 0; !BER_BVISNULL( &vals[ i ] ); i++ ) {
+ memberof_value_modify( op, rs,
+ &vals[ i ], mo->mo_ad_memberof,
+ &op->o_req_dn, &op->o_req_ndn,
+ NULL, NULL );
+ }
+ break;
+ }
+ /* fall thru */
+
+ case LDAP_MOD_REPLACE:
+ /* delete all ... */
+ op->o_bd->bd_info = (BackendInfo *)on->on_info;
+ rc = backend_attribute( op, NULL, &op->o_req_ndn,
+ mo->mo_ad_member, &vals, ACL_READ );
+ op->o_bd->bd_info = (BackendInfo *)on;
+ if ( rc == LDAP_SUCCESS ) {
+ for ( i = 0; !BER_BVISNULL( &vals[ i ] ); i++ ) {
+ (void)memberof_value_modify( op, rs,
+ &vals[ i ], mo->mo_ad_memberof,
+ &op->o_req_dn, &op->o_req_ndn,
+ NULL, NULL );
+ }
+ ber_bvarray_free_x( vals, op->o_tmpmemctx );
+ }
+
+ if ( ml->sml_op == LDAP_MOD_DELETE ) {
+ break;
+ }
+ /* fall thru */
+
+ case LDAP_MOD_ADD:
+ assert( ml->sml_nvalues != NULL );
+ vals = ml->sml_nvalues;
+ for ( i = 0; !BER_BVISNULL( &vals[ i ] ); i++ ) {
+ memberof_value_modify( op, rs,
+ &vals[ i ], mo->mo_ad_memberof,
+ NULL, NULL,
+ &op->o_req_dn, &op->o_req_ndn );
+ }
+ break;
+
+ default:
+ assert( 0 );
+ }
+ }
+ }
+
+ return SLAP_CB_CONTINUE;
+}
+
+/*
+ * response callback that adds/deletes member values when a group member
+ * is modified.
+ */
+static int
+memberof_res_rename( Operation *op, SlapReply *rs )
+{
+ slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
+ memberof_t *mo = (memberof_t *)on->on_bi.bi_private;
+
+ struct berval newPDN, newDN = BER_BVNULL, newPNDN, newNDN;
+ int i, rc;
+ BerVarray vals;
+
+ struct berval save_dn, save_ndn;
+ memberof_is_t iswhat = MEMBEROF_IS_GROUP;
+
+ if ( MEMBEROF_REFINT( mo ) ) {
+ iswhat |= MEMBEROF_IS_MEMBER;
+ }
+
+ if ( op->orr_nnewSup ) {
+ newPNDN = *op->orr_nnewSup;
+
+ } else {
+ dnParent( &op->o_req_ndn, &newPNDN );
+ }
+
+ build_new_dn( &newNDN, &newPNDN, &op->orr_nnewrdn, op->o_tmpmemctx );
+
+ save_dn = op->o_req_dn;
+ save_ndn = op->o_req_ndn;
+
+ op->o_req_dn = newNDN;
+ op->o_req_ndn = newNDN;
+ rc = memberof_isGroupOrMember( op, &iswhat );
+ op->o_req_dn = save_dn;
+ op->o_req_ndn = save_ndn;
+
+ if ( rc != LDAP_SUCCESS || iswhat == MEMBEROF_IS_NONE ) {
+ goto done;
+ }
+
+ if ( op->orr_newSup ) {
+ newPDN = *op->orr_newSup;
+
+ } else {
+ dnParent( &op->o_req_dn, &newPDN );
+ }
+
+ build_new_dn( &newDN, &newPDN, &op->orr_newrdn, op->o_tmpmemctx );
+
+ if ( iswhat & MEMBEROF_IS_GROUP ) {
+ op->o_bd->bd_info = (BackendInfo *)on->on_info;
+ rc = backend_attribute( op, NULL, &newNDN,
+ mo->mo_ad_member, &vals, ACL_READ );
+ op->o_bd->bd_info = (BackendInfo *)on;
+
+ if ( rc == LDAP_SUCCESS ) {
+ for ( i = 0; !BER_BVISNULL( &vals[ i ] ); i++ ) {
+ (void)memberof_value_modify( op, rs,
+ &vals[ i ], mo->mo_ad_memberof,
+ &op->o_req_dn, &op->o_req_ndn,
+ &newDN, &newNDN );
+ }
+ ber_bvarray_free_x( vals, op->o_tmpmemctx );
+ }
+ }
+
+ if ( MEMBEROF_REFINT( mo ) && ( iswhat & MEMBEROF_IS_MEMBER ) ) {
+ op->o_bd->bd_info = (BackendInfo *)on->on_info;
+ rc = backend_attribute( op, NULL, &newNDN,
+ mo->mo_ad_memberof, &vals, ACL_READ );
+ op->o_bd->bd_info = (BackendInfo *)on;
+
+ if ( rc == LDAP_SUCCESS ) {
+ for ( i = 0; !BER_BVISNULL( &vals[ i ] ); i++ ) {
+ (void)memberof_value_modify( op, rs,
+ &vals[ i ], mo->mo_ad_member,
+ &op->o_req_dn, &op->o_req_ndn,
+ &newDN, &newNDN );
+ }
+ ber_bvarray_free_x( vals, op->o_tmpmemctx );
+ }
+ }
+
+done:;
+ if ( !BER_BVISNULL( &newDN ) ) {
+ op->o_tmpfree( newDN.bv_val, op->o_tmpmemctx );
+ }
+ op->o_tmpfree( newNDN.bv_val, op->o_tmpmemctx );
+
+ return SLAP_CB_CONTINUE;
+}
+
+static int
+memberof_response( Operation *op, SlapReply *rs )
+{
+ if ( rs->sr_err != LDAP_SUCCESS ) {
+ return SLAP_CB_CONTINUE;
+ }
+
+ switch ( op->o_tag ) {
+ case LDAP_REQ_ADD:
+ return memberof_res_add( op, rs );
+
+ case LDAP_REQ_DELETE:
+ return memberof_res_delete( op, rs );
+
+ case LDAP_REQ_MODIFY:
+ return memberof_res_modify( op, rs );
+
+ case LDAP_REQ_MODDN:
+ return memberof_res_rename( op, rs );
+
+ default:
+ return SLAP_CB_CONTINUE;
+ }
+}
+
+static int
+memberof_db_init(
+ BackendDB *be,
+ ConfigReply *cr )
+{
+ slap_overinst *on = (slap_overinst *)be->bd_info;
+ memberof_t *mo;
+
+ int rc;
+ const char *text = NULL;
+
+ mo = (memberof_t *)ch_calloc( 1, sizeof( memberof_t ) );
+
+ rc = slap_str2ad( SLAPD_MEMBEROF_ATTR, &mo->mo_ad_memberof, &text );
+ if ( rc != LDAP_SUCCESS ) {
+ Debug( LDAP_DEBUG_ANY,
+ "memberof_db_init: "
+ "unable to find attribute=\"%s\": %s (%d)\n",
+ SLAPD_MEMBEROF_ATTR, text, rc );
+ return rc;
+ }
+
+ rc = slap_str2ad( SLAPD_GROUP_ATTR, &mo->mo_ad_member, &text );
+ if ( rc != LDAP_SUCCESS ) {
+ Debug( LDAP_DEBUG_ANY,
+ "memberof_db_init: "
+ "unable to find attribute=\"%s\": %s (%d)\n",
+ SLAPD_GROUP_ATTR, text, rc );
+ return rc;
+ }
+
+ mo->mo_oc_group = oc_find( SLAPD_GROUP_CLASS );
+ if ( mo->mo_oc_group == NULL ) {
+ Debug( LDAP_DEBUG_ANY,
+ "memberof_db_init: "
+ "unable to find objectClass=\"%s\"\n",
+ SLAPD_GROUP_CLASS, 0, 0 );
+ return 1;
+ }
+
+ on->on_bi.bi_private = (void *)mo;
+
+ return 0;
+}
+
+enum {
+ MO_DN = 1,
+ MO_DANGLING,
+ MO_REFINT,
+#if 0
+ MO_REVERSE,
+#endif
+ MO_GROUP_OC,
+ MO_MEMBER_AD,
+ MO_MEMBER_OF_AD
+};
+
+static ConfigDriver mo_cf_gen;
+
+#define OID "1.3.6.1.4.1.7136.2.666.4"
+#define OIDAT OID ".1.1"
+#define OIDCFGAT OID ".1.2"
+#define OIDOC OID ".2.1"
+#define OIDCFGOC OID ".2.2"
+
+
+static ConfigTable mo_cfg[] = {
+ { "memberof-dn", "modifiersName",
+ 2, 2, 0, ARG_MAGIC|ARG_DN|MO_DN, mo_cf_gen,
+ "( OLcfgOvAt:18.0 NAME 'olcMemberOfDN' "
+ "DESC 'DN to be used as modifiersName' "
+ "SYNTAX OMsDN SINGLE-VALUE )",
+ NULL, NULL },
+
+ { "memberof-dangling", "ignore|drop|error",
+ 2, 2, 0, ARG_MAGIC|MO_DANGLING, mo_cf_gen,
+ "( OLcfgOvAt:18.1 NAME 'olcMemberOfDangling' "
+ "DESC 'Behavior with respect to dangling members, "
+ "constrained to ignore, drop, error' "
+ "SYNTAX OMsDirectoryString SINGLE-VALUE )",
+ NULL, NULL },
+
+ { "memberof-refint", "true|FALSE",
+ 2, 2, 0, ARG_MAGIC|ARG_ON_OFF|MO_REFINT, mo_cf_gen,
+ "( OLcfgOvAt:18.2 NAME 'olcMemberOfRefInt' "
+ "DESC 'Take care of referential integrity' "
+ "SYNTAX OMsBoolean SINGLE-VALUE )",
+ NULL, NULL },
+
+ { "memberof-group-oc", "objectClass",
+ 2, 2, 0, ARG_MAGIC|MO_GROUP_OC, mo_cf_gen,
+ "( OLcfgOvAt:18.3 NAME 'olcMemberOfGroupOC' "
+ "DESC 'Group objectClass' "
+ "SYNTAX OMsDirectoryString SINGLE-VALUE )",
+ NULL, NULL },
+
+ { "memberof-member-ad", "member attribute",
+ 2, 2, 0, ARG_MAGIC|MO_MEMBER_AD, mo_cf_gen,
+ "( OLcfgOvAt:18.4 NAME 'olcMemberOfMemberAD' "
+ "DESC 'member attribute' "
+ "SYNTAX OMsDirectoryString SINGLE-VALUE )",
+ NULL, NULL },
+
+ { "memberof-memberof-ad", "memberOf attribute",
+ 2, 2, 0, ARG_MAGIC|MO_MEMBER_OF_AD, mo_cf_gen,
+ "( OLcfgOvAt:18.5 NAME 'olcMemberOfMemberOfAD' "
+ "DESC 'memberOf attribute' "
+ "SYNTAX OMsDirectoryString SINGLE-VALUE )",
+ NULL, NULL },
+
+#if 0
+ { "memberof-reverse", "true|FALSE",
+ 2, 2, 0, ARG_MAGIC|ARG_ON_OFF|MO_REVERSE, mo_cf_gen,
+ "( OLcfgOvAt:18.6 NAME 'olcMemberOfReverse' "
+ "DESC 'Take care of referential integrity "
+ "also when directly modifying memberOf' "
+ "SYNTAX OMsBoolean SINGLE-VALUE )",
+ NULL, NULL },
+#endif
+
+ { NULL, NULL, 0, 0, 0, ARG_IGNORED }
+};
+
+static ConfigOCs mo_ocs[] = {
+ { "( OLcfgOvOc:18.1 "
+ "NAME 'olcMemberOf' "
+ "DESC 'Member-of configuration' "
+ "SUP olcOverlayConfig "
+ "MAY ( "
+ "olcMemberOfDN "
+ "$ olcMemberOfDangling "
+ "$ olcMemberOfRefInt "
+ "$ olcMemberOfGroupOC "
+ "$ olcMemberOfMemberAD "
+ "$ olcMemberOfMemberOfAD "
+#if 0
+ "$ olcMemberOfReverse "
+#endif
+ ") "
+ ")",
+ Cft_Overlay, mo_cfg, NULL, NULL },
+ { NULL, 0, NULL }
+};
+
+static slap_verbmasks dangling_mode[] = {
+ { BER_BVC( "ignore" ), MEMBEROF_NONE },
+ { BER_BVC( "drop" ), MEMBEROF_FDANGLING_DROP },
+ { BER_BVC( "error" ), MEMBEROF_FDANGLING_ERROR },
+ { BER_BVNULL, 0 }
+};
+
+static int
+memberof_make_group_filter( memberof_t *mo )
+{
+ char *ptr;
+
+ if ( !BER_BVISNULL( &mo->mo_groupFilterstr ) ) {
+ ch_free( mo->mo_groupFilterstr.bv_val );
+ }
+
+ mo->mo_groupFilter.f_choice = LDAP_FILTER_EQUALITY;
+ mo->mo_groupFilter.f_ava = &mo->mo_groupAVA;
+
+ mo->mo_groupFilter.f_av_desc = slap_schema.si_ad_objectClass;
+ mo->mo_groupFilter.f_av_value = mo->mo_oc_group->soc_cname;
+
+ mo->mo_groupFilterstr.bv_len = STRLENOF( "(=)" )
+ + slap_schema.si_ad_objectClass->ad_cname.bv_len
+ + mo->mo_oc_group->soc_cname.bv_len;
+ ptr = mo->mo_groupFilterstr.bv_val = ch_malloc( mo->mo_groupFilterstr.bv_len + 1 );
+ *ptr++ = '(';
+ ptr = lutil_strcopy( ptr, slap_schema.si_ad_objectClass->ad_cname.bv_val );
+ *ptr++ = '=';
+ ptr = lutil_strcopy( ptr, mo->mo_oc_group->soc_cname.bv_val );
+ *ptr++ = ')';
+ *ptr = '\0';
+
+ return 0;
+}
+
+static int
+memberof_make_member_filter( memberof_t *mo )
+{
+ char *ptr;
+
+ if ( !BER_BVISNULL( &mo->mo_memberFilterstr ) ) {
+ ch_free( mo->mo_memberFilterstr.bv_val );
+ }
+
+ mo->mo_memberFilter.f_choice = LDAP_FILTER_PRESENT;
+ mo->mo_memberFilter.f_desc = mo->mo_ad_memberof;
+
+ mo->mo_memberFilterstr.bv_len = STRLENOF( "(=*)" )
+ + mo->mo_ad_memberof->ad_cname.bv_len;
+ ptr = mo->mo_memberFilterstr.bv_val = ch_malloc( mo->mo_memberFilterstr.bv_len + 1 );
+ *ptr++ = '(';
+ ptr = lutil_strcopy( ptr, mo->mo_ad_memberof->ad_cname.bv_val );
+ ptr = lutil_strcopy( ptr, "=*)" );
+
+ return 0;
+}
+
+static int
+mo_cf_gen( ConfigArgs *c )
+{
+ slap_overinst *on = (slap_overinst *)c->bi;
+ memberof_t *mo = (memberof_t *)on->on_bi.bi_private;
+
+ int i, rc = 0;
+
+ if ( c->op == SLAP_CONFIG_EMIT ) {
+ struct berval bv = BER_BVNULL;
+
+ switch( c->type ) {
+ case MO_DN:
+ value_add_one( &c->rvalue_vals, &mo->mo_dn );
+ value_add_one( &c->rvalue_nvals, &mo->mo_ndn );
+ break;
+
+ case MO_DANGLING:
+ enum_to_verb( dangling_mode, (mo->mo_flags & MEMBEROF_FDANGLING_MASK), &bv );
+ if ( BER_BVISNULL( &bv ) ) {
+ /* there's something wrong... */
+ assert( 0 );
+ rc = 1;
+
+ } else {
+ value_add_one( &c->rvalue_vals, &bv );
+ }
+ break;
+
+ case MO_REFINT:
+ c->value_int = MEMBEROF_REFINT( mo );
+ break;
+
+#if 0
+ case MO_REVERSE:
+ c->value_int = MEMBEROF_REVERSE( mo );
+ break;
+#endif
+
+ case MO_GROUP_OC:
+ assert( mo->mo_oc_group != NULL );
+ value_add_one( &c->rvalue_vals, &mo->mo_oc_group->soc_cname );
+ break;
+
+ case MO_MEMBER_AD:
+ assert( mo->mo_ad_member != NULL );
+ value_add_one( &c->rvalue_vals, &mo->mo_ad_member->ad_cname );
+ break;
+
+ case MO_MEMBER_OF_AD:
+ assert( mo->mo_ad_memberof != NULL );
+ value_add_one( &c->rvalue_vals, &mo->mo_ad_memberof->ad_cname );
+ break;
+
+ default:
+ assert( 0 );
+ return 1;
+ }
+
+ return rc;
+
+ } else if ( c->op == LDAP_MOD_DELETE ) {
+ return 1; /* FIXME */
+
+ } else {
+ switch( c->type ) {
+ case MO_DN:
+ if ( !BER_BVISNULL( &mo->mo_dn ) ) {
+ ber_memfree( mo->mo_dn.bv_val );
+ ber_memfree( mo->mo_ndn.bv_val );
+ }
+ mo->mo_dn = c->value_dn;
+ mo->mo_ndn = c->value_ndn;
+ break;
+
+ case MO_DANGLING:
+ i = verb_to_mask( c->argv[ 1 ], dangling_mode );
+ if ( BER_BVISNULL( &dangling_mode[ i ].word ) ) {
+ return 1;
+ }
+
+ mo->mo_flags &= ~MEMBEROF_FDANGLING_MASK;
+ mo->mo_flags |= dangling_mode[ i ].mask;
+ break;
+
+ case MO_REFINT:
+ if ( c->value_int ) {
+ mo->mo_flags |= MEMBEROF_FREFINT;
+
+ } else {
+ mo->mo_flags &= ~MEMBEROF_FREFINT;
+ }
+ break;
+
+#if 0
+ case MO_REVERSE:
+ if ( c->value_int ) {
+ mo->mo_flags |= MEMBEROF_FREVERSE;
+
+ } else {
+ mo->mo_flags &= ~MEMBEROF_FREVERSE;
+ }
+ break;
+#endif
+
+ case MO_GROUP_OC: {
+ ObjectClass *oc = NULL;
+
+ oc = oc_find( c->argv[ 1 ] );
+ if ( oc == NULL ) {
+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
+ "unable to find group objectClass=\"%s\"",
+ c->argv[ 1 ] );
+ Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n",
+ c->log, c->cr_msg, 0 );
+ return 1;
+ }
+
+ mo->mo_oc_group = oc;
+ memberof_make_group_filter( mo );
+ } break;
+
+ case MO_MEMBER_AD: {
+ AttributeDescription *ad = NULL;
+ const char *text = NULL;
+
+
+ rc = slap_str2ad( c->argv[ 1 ], &ad, &text );
+ if ( rc != LDAP_SUCCESS ) {
+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
+ "unable to find member attribute=\"%s\": %s (%d)",
+ c->argv[ 1 ], text, rc );
+ Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n",
+ c->log, c->cr_msg, 0 );
+ return 1;
+ }
+
+ if ( !is_at_syntax( ad->ad_type, SLAPD_DN_SYNTAX ) /* e.g. "member" */
+ && !is_at_syntax( ad->ad_type, SLAPD_NAMEUID_SYNTAX ) ) /* e.g. "uniqueMember" */
+ {
+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
+ "member attribute=\"%s\" must either "
+ "have DN (%s) or nameUID (%s) syntax",
+ c->argv[ 1 ], SLAPD_DN_SYNTAX, SLAPD_NAMEUID_SYNTAX );
+ Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n",
+ c->log, c->cr_msg, 0 );
+ return 1;
+ }
+
+ mo->mo_ad_member = ad;
+ } break;
+
+ case MO_MEMBER_OF_AD: {
+ AttributeDescription *ad = NULL;
+ const char *text = NULL;
+
+
+ rc = slap_str2ad( c->argv[ 1 ], &ad, &text );
+ if ( rc != LDAP_SUCCESS ) {
+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
+ "unable to find memberof attribute=\"%s\": %s (%d)",
+ c->argv[ 1 ], text, rc );
+ Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n",
+ c->log, c->cr_msg, 0 );
+ return 1;
+ }
+
+ if ( !is_at_syntax( ad->ad_type, SLAPD_DN_SYNTAX ) /* e.g. "member" */
+ && !is_at_syntax( ad->ad_type, SLAPD_NAMEUID_SYNTAX ) ) /* e.g. "uniqueMember" */
+ {
+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
+ "memberof attribute=\"%s\" must either "
+ "have DN (%s) or nameUID (%s) syntax",
+ c->argv[ 1 ], SLAPD_DN_SYNTAX, SLAPD_NAMEUID_SYNTAX );
+ Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n",
+ c->log, c->cr_msg, 0 );
+ return 1;
+ }
+
+ mo->mo_ad_memberof = ad;
+ memberof_make_member_filter( mo );
+ } break;
+
+ default:
+ assert( 0 );
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+static int
+memberof_db_open(
+ BackendDB *be,
+ ConfigReply *cr )
+{
+ slap_overinst *on = (slap_overinst *)be->bd_info;
+ memberof_t *mo = (memberof_t *)on->on_bi.bi_private;
+
+ if ( BER_BVISNULL( &mo->mo_dn ) ) {
+ ber_dupbv( &mo->mo_dn, &be->be_rootdn );
+ ber_dupbv( &mo->mo_ndn, &be->be_rootndn );
+ }
+
+ if ( BER_BVISNULL( &mo->mo_groupFilterstr ) ) {
+ memberof_make_group_filter( mo );
+ }
+
+ if ( BER_BVISNULL( &mo->mo_memberFilterstr ) ) {
+ memberof_make_member_filter( mo );
+ }
+
+ return 0;
+}
+
+static int
+memberof_db_destroy(
+ BackendDB *be,
+ ConfigReply *cr )
+{
+ slap_overinst *on = (slap_overinst *)be->bd_info;
+ memberof_t *mo = (memberof_t *)on->on_bi.bi_private;
+
+ if ( mo ) {
+ if ( !BER_BVISNULL( &mo->mo_dn ) ) {
+ ber_memfree( mo->mo_dn.bv_val );
+ ber_memfree( mo->mo_ndn.bv_val );
+ }
+
+ if ( !BER_BVISNULL( &mo->mo_groupFilterstr ) ) {
+ ber_memfree( mo->mo_groupFilterstr.bv_val );
+ }
+
+ if ( !BER_BVISNULL( &mo->mo_memberFilterstr ) ) {
+ ber_memfree( mo->mo_memberFilterstr.bv_val );
+ }
+
+ ber_memfree( mo );
+ }
+
+ return 0;
+}
+
+/* unused */
+static AttributeDescription *ad_memberOf;
+
+static struct {
+ char *desc;
+ AttributeDescription **adp;
+} as[] = {
+ { "( 1.2.840.113556.1.2.102 "
+ "NAME 'memberOf' "
+ "DESC 'Group that the entry belongs to' "
+ "SYNTAX '1.3.6.1.4.1.1466.115.121.1.12' "
+ "EQUALITY distinguishedNameMatch " /* added */
+ "USAGE dSAOperation " /* added; questioned */
+ /* "NO-USER-MODIFICATION " */ /* add? */
+ "X-ORIGIN 'iPlanet Delegated Administrator' )",
+ &ad_memberOf },
+ { NULL }
+};
+
+#if SLAPD_OVER_MEMBEROF == SLAPD_MOD_DYNAMIC
+static
+#endif /* SLAPD_OVER_MEMBEROF == SLAPD_MOD_DYNAMIC */
+int
+memberof_initialize( void )
+{
+ int code, i;
+
+ for ( i = 0; as[ i ].desc != NULL; i++ ) {
+ code = register_at( as[ i ].desc, as[ i ].adp, 0 );
+ if ( code ) {
+ Debug( LDAP_DEBUG_ANY,
+ "memberof_initialize: register_at #%d failed\n",
+ i, 0, 0 );
+ return code;
+ }
+ }
+
+ memberof.on_bi.bi_type = "memberof";
+
+ memberof.on_bi.bi_db_init = memberof_db_init;
+ memberof.on_bi.bi_db_open = memberof_db_open;
+ memberof.on_bi.bi_db_destroy = memberof_db_destroy;
+
+ memberof.on_bi.bi_op_add = memberof_op_add;
+ memberof.on_bi.bi_op_delete = memberof_op_delete;
+ memberof.on_bi.bi_op_modify = memberof_op_modify;
+
+ memberof.on_response = memberof_response;
+
+ memberof.on_bi.bi_cf_ocs = mo_ocs;
+
+ code = config_register_schema( mo_cfg, mo_ocs );
+ if ( code ) return code;
+
+ return overlay_register( &memberof );
+}
+
+#if SLAPD_OVER_MEMBEROF == SLAPD_MOD_DYNAMIC
+int
+init_module( int argc, char *argv[] )
+{
+ return memberof_initialize();
+}
+#endif /* SLAPD_OVER_MEMBEROF == SLAPD_MOD_DYNAMIC */
+
+#endif /* SLAPD_OVER_MEMBEROF */
#include "config.h"
+#ifdef LDAP_DEVEL
+/*
+ * Control that allows to access the private DB
+ * instead of the public one
+ */
+#define PCACHE_CONTROL_PRIVDB "1.3.6.1.4.1.4203.666.11.9.5.1"
+
+/*
+ * Extended Operation that allows to remove a query from the cache
+ */
+#define PCACHE_EXOP_QUERY_DELETE "1.3.6.1.4.1.4203.666.11.9.6.1"
+#endif
+
/* query cache structs */
/* query */
Qbase *qbase;
int scope;
struct berval q_uuid; /* query identifier */
- struct query_template_s *qtemp; /* template of the query */
+ struct query_template_s *qtemp; /* template of the query */
time_t expiry_time; /* time till the query is considered valid */
struct cached_query_s *next; /* next query in the template */
struct cached_query_s *prev; /* previous query in the template */
struct cached_query_s *lru_down; /* next query in the LRU list */
} CachedQuery;
+/*
+ * URL representation:
+ *
+ * ldap:///<base>??<scope>?<filter>?x-uuid=<uid>,x-template=<template>,x-attrset=<attrset>,x-expiry=<expiry>
+ *
+ * <base> ::= CachedQuery.qbase->base
+ * <scope> ::= CachedQuery.scope
+ * <filter> ::= filter2bv(CachedQuery.filter)
+ * <uuid> ::= CachedQuery.q_uuid
+ * <attrset> ::= CachedQuery.qtemp->attr_set_index
+ * <expiry> ::= CachedQuery.expiry_time
+ *
+ * quick hack: parse URI, call add_query() and then fix
+ * CachedQuery.expiry_time and CachedQuery.q_uuid
+ */
+
/*
* Represents a set of projected attributes.
*/
BackendDB db; /* underlying database */
unsigned long num_cached_queries; /* total number of cached queries */
unsigned long max_queries; /* upper bound on # of cached queries */
+ int save_queries; /* save cached queries across restarts */
int numattrsets; /* number of attribute sets */
int cur_entries; /* current number of entries cached */
int max_entries; /* max number of entries cached */
static int pcache_debug;
-static AttributeDescription *ad_queryid;
-static char *queryid_schema = "( 1.3.6.1.4.1.4203.666.1.12 NAME 'queryid' "
- "DESC 'list of queries the entry belongs to' "
- "EQUALITY octetStringMatch "
- "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40{64} "
- "NO-USER-MODIFICATION USAGE directoryOperation )";
+#ifdef PCACHE_CONTROL_PRIVDB
+static int privDB_cid;
+#endif /* PCACHE_CONTROL_PRIVDB */
+
+static AttributeDescription *ad_queryId, *ad_cachedQueryURL;
+static struct {
+ char *desc;
+ AttributeDescription **adp;
+} as[] = {
+ { "( 1.3.6.1.4.1.4203.666.11.9.1.1 "
+ "NAME 'queryId' "
+ "DESC 'ID of query the entry belongs to, formatted as a UUID' "
+ "EQUALITY octetStringMatch "
+ "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40{64} "
+ "NO-USER-MODIFICATION "
+ "USAGE directoryOperation )",
+ &ad_queryId },
+ { "( 1.3.6.1.4.1.4203.666.11.9.1.2 "
+ "NAME 'cachedQueryURL' "
+ "DESC 'URI describing a cached query' "
+ "EQUALITY caseExactMatch "
+ "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 "
+ "NO-USER-MODIFICATION "
+ "USAGE directoryOperation )",
+ &ad_cachedQueryURL },
+ { NULL }
+};
+
+static int
+filter2template(
+ Operation *op,
+ Filter *f,
+ struct berval *fstr,
+ AttributeName** filter_attrs,
+ int* filter_cnt,
+ int* filter_got_oc );
+
+static CachedQuery *
+add_query(
+ Operation *op,
+ query_manager* qm,
+ Query* query,
+ QueryTemplate *templ,
+ int positive);
+
+static int
+remove_query_data(
+ Operation *op,
+ SlapReply *rs,
+ struct berval *query_uuid );
+
+/*
+ * Turn a cached query into its URL representation
+ */
+static int
+query2url( Operation *op, CachedQuery *q, struct berval *urlbv )
+{
+ struct berval bv_scope,
+ bv_filter;
+ char attrset_buf[ 32 ],
+ expiry_buf[ 32 ],
+ *ptr;
+ ber_len_t attrset_len,
+ expiry_len;
+
+ ldap_pvt_scope2bv( q->scope, &bv_scope );
+ filter2bv_x( op, q->filter, &bv_filter );
+ attrset_len = snprintf( attrset_buf, sizeof( attrset_buf ),
+ "%lu", (unsigned long)q->qtemp->attr_set_index );
+ expiry_len = snprintf( expiry_buf, sizeof( expiry_buf ),
+ "%lu", (unsigned long)q->expiry_time );
+
+ urlbv->bv_len = STRLENOF( "ldap:///" )
+ + q->qbase->base.bv_len
+ + STRLENOF( "??" )
+ + bv_scope.bv_len
+ + STRLENOF( "?" )
+ + bv_filter.bv_len
+ + STRLENOF( "?x-uuid=" )
+ + q->q_uuid.bv_len
+ + STRLENOF( ",x-attrset=" )
+ + attrset_len
+ + STRLENOF( ",x-expiry=" )
+ + expiry_len;
+ ptr = urlbv->bv_val = ber_memalloc_x( urlbv->bv_len + 1, op->o_tmpmemctx );
+ ptr = lutil_strcopy( ptr, "ldap:///" );
+ ptr = lutil_strcopy( ptr, q->qbase->base.bv_val );
+ ptr = lutil_strcopy( ptr, "??" );
+ ptr = lutil_strcopy( ptr, bv_scope.bv_val );
+ ptr = lutil_strcopy( ptr, "?" );
+ ptr = lutil_strcopy( ptr, bv_filter.bv_val );
+ ptr = lutil_strcopy( ptr, "?x-uuid=" );
+ ptr = lutil_strcopy( ptr, q->q_uuid.bv_val );
+ ptr = lutil_strcopy( ptr, ",x-attrset=" );
+ ptr = lutil_strcopy( ptr, attrset_buf );
+ ptr = lutil_strcopy( ptr, ",x-expiry=" );
+ ptr = lutil_strcopy( ptr, expiry_buf );
+
+ ber_memfree_x( bv_filter.bv_val, op->o_tmpmemctx );
+
+ return 0;
+}
+
+/*
+ * Turn an URL representing a formerly cached query into a cached query,
+ * and try to cache it
+ */
+static int
+url2query(
+ char *url,
+ Operation *op,
+ query_manager *qm )
+{
+ Query query = { 0 };
+ QueryTemplate *qt;
+ CachedQuery *cq;
+ LDAPURLDesc *lud = NULL;
+ struct berval base,
+ tempstr = BER_BVNULL,
+ uuid;
+ int attrset;
+ time_t expiry_time;
+ int i,
+ got_uuid = 0,
+ got_attrset = 0,
+ got_expiry = 0,
+ rc = 0;
+
+ rc = ldap_url_parse( url, &lud );
+ if ( rc != LDAP_URL_SUCCESS ) {
+ return -1;
+ }
+
+ /* non-allowed fields */
+ if ( lud->lud_host != NULL ) {
+ rc = 1;
+ goto error;
+ }
+
+ if ( lud->lud_attrs != NULL ) {
+ rc = 1;
+ goto error;
+ }
+
+ /* be pedantic */
+ if ( strcmp( lud->lud_scheme, "ldap" ) != 0 ) {
+ rc = 1;
+ goto error;
+ }
+
+ /* required fields */
+ if ( lud->lud_dn == NULL || lud->lud_dn[ 0 ] == '\0' ) {
+ rc = 1;
+ goto error;
+ }
+
+ switch ( lud->lud_scope ) {
+ case LDAP_SCOPE_BASE:
+ case LDAP_SCOPE_ONELEVEL:
+ case LDAP_SCOPE_SUBTREE:
+ case LDAP_SCOPE_SUBORDINATE:
+ break;
+
+ default:
+ rc = 1;
+ goto error;
+ }
+
+ if ( lud->lud_filter == NULL || lud->lud_filter[ 0 ] == '\0' ) {
+ rc = 1;
+ goto error;
+ }
+
+ if ( lud->lud_exts == NULL ) {
+ rc = 1;
+ goto error;
+ }
+
+ for ( i = 0; lud->lud_exts[ i ] != NULL; i++ ) {
+ if ( strncmp( lud->lud_exts[ i ], "x-uuid=", STRLENOF( "x-uuid=" ) ) == 0 ) {
+ struct berval tmpUUID;
+ Syntax *syn_UUID = slap_schema.si_ad_entryUUID->ad_type->sat_syntax;
+
+ ber_str2bv( &lud->lud_exts[ i ][ STRLENOF( "x-uuid=" ) ], 0, 0, &tmpUUID );
+ rc = syn_UUID->ssyn_pretty( syn_UUID, &tmpUUID, &uuid, NULL );
+ if ( rc != LDAP_SUCCESS ) {
+ goto error;
+ }
+ got_uuid = 1;
+
+ } else if ( strncmp( lud->lud_exts[ i ], "x-attrset=", STRLENOF( "x-attrset=" ) ) == 0 ) {
+ rc = lutil_atoi( &attrset, &lud->lud_exts[ i ][ STRLENOF( "x-attrset=" ) ] );
+ if ( rc ) {
+ goto error;
+ }
+ got_attrset = 1;
+
+ } else if ( strncmp( lud->lud_exts[ i ], "x-expiry=", STRLENOF( "x-expiry=" ) ) == 0 ) {
+ unsigned long l;
+
+ rc = lutil_atoul( &l, &lud->lud_exts[ i ][ STRLENOF( "x-expiry=" ) ] );
+ if ( rc ) {
+ goto error;
+ }
+ expiry_time = (time_t)l;
+ got_expiry = 1;
+
+ } else {
+ rc = -1;
+ goto error;
+ }
+ }
+
+ if ( !got_uuid ) {
+ rc = 1;
+ goto error;
+ }
+
+ if ( !got_attrset ) {
+ rc = 1;
+ goto error;
+ }
+
+ if ( !got_expiry ) {
+ rc = 1;
+ goto error;
+ }
+
+ /* ignore expired queries */
+ if ( expiry_time <= slap_get_time()) {
+ Operation op2 = *op;
+ SlapReply rs2 = { 0 };
+
+ memset( &op2.oq_search, 0, sizeof( op2.oq_search ) );
+
+ (void)remove_query_data( &op2, &rs2, &uuid );
+
+ rc = 0;
+
+ } else {
+ ber_str2bv( lud->lud_dn, 0, 0, &base );
+ rc = dnNormalize( 0, NULL, NULL, &base, &query.base, NULL );
+ if ( rc != LDAP_SUCCESS ) {
+ goto error;
+ }
+ query.scope = lud->lud_scope;
+ query.filter = str2filter( lud->lud_filter );
+
+ tempstr.bv_val = ch_malloc( strlen( lud->lud_filter ) + 1 );
+ tempstr.bv_len = 0;
+ if ( filter2template( op, query.filter, &tempstr, NULL, NULL, NULL ) ) {
+ ch_free( tempstr.bv_val );
+ rc = -1;
+ goto error;
+ }
+
+ /* check for query containment */
+ qt = qm->attr_sets[attrset].templates;
+ for ( ; qt; qt = qt->qtnext ) {
+ /* find if template i can potentially answer tempstr */
+ if ( bvmatch( &qt->querystr, &tempstr ) ) {
+ break;
+ }
+ }
+
+ if ( qt == NULL ) {
+ rc = 1;
+ goto error;
+ }
+
+ cq = add_query( op, qm, &query, qt, 1 );
+ if ( cq != NULL ) {
+ cq->expiry_time = expiry_time;
+ cq->q_uuid = uuid;
+
+ /* it's now into cq->filter */
+ BER_BVZERO( &uuid );
+ query.filter = NULL;
+
+ } else {
+ rc = 1;
+ }
+ }
+
+error:;
+ if ( query.filter != NULL ) filter_free( query.filter );
+ if ( !BER_BVISNULL( &tempstr ) ) ch_free( tempstr.bv_val );
+ if ( !BER_BVISNULL( &query.base ) ) ch_free( query.base.bv_val );
+ if ( !BER_BVISNULL( &uuid ) ) ch_free( uuid.bv_val );
+ if ( lud != NULL ) ldap_free_urldesc( lud );
+
+ return rc;
+}
/* Return 1 for an added entry, else 0 */
static int
attr = e->e_attrs;
e->e_attrs = NULL;
- /* add queryid attribute */
- attr_merge_one( e, ad_queryid, query_uuid, NULL );
+ /* add queryId attribute */
+ attr_merge_one( e, ad_queryId, query_uuid, NULL );
/* append the attribute list from the fetched entry */
e->e_attrs->a_next = attr;
/* Add query to query cache */
-static CachedQuery * add_query(
+static CachedQuery *
+add_query(
Operation *op,
query_manager* qm,
Query* query,
qbase = avl_find( templ->qbase, &qb, pcache_dn_cmp );
if ( !qbase ) {
qbase = ch_calloc( 1, sizeof(Qbase) + qb.base.bv_len + 1 );
- qbase->base.bv_len =qb.base.bv_len;
+ qbase->base.bv_len = qb.base.bv_len;
qbase->base.bv_val = (char *)(qbase+1);
memcpy( qbase->base.bv_val, qb.base.bv_val, qb.base.bv_len );
qbase->base.bv_val[qbase->base.bv_len] = '\0';
}
/* remove bottom query of LRU list from the query cache */
-static void cache_replacement(query_manager* qm, struct berval *result)
+/*
+ * NOTE: slight change in functionality.
+ *
+ * - if result->bv_val is NULL, the query at the bottom of the LRU
+ * is removed
+ * - otherwise, the query whose UUID is *result is removed
+ * - if not found, result->bv_val is zeroed
+ */
+static void
+cache_replacement(query_manager* qm, struct berval *result)
{
CachedQuery* bottom;
QueryTemplate *temp;
ldap_pvt_thread_mutex_lock(&qm->lru_mutex);
- bottom = qm->lru_bottom;
+ if ( BER_BVISNULL( result ) ) {
+ bottom = qm->lru_bottom;
+
+ if (!bottom) {
+ Debug ( pcache_debug,
+ "Cache replacement invoked without "
+ "any query in LRU list\n", 0, 0, 0 );
+ ldap_pvt_thread_mutex_unlock(&qm->lru_mutex);
+ return;
+ }
- result->bv_val = NULL;
- result->bv_len = 0;
+ } else {
+ for ( bottom = qm->lru_bottom;
+ bottom != NULL;
+ bottom = bottom->lru_up )
+ {
+ if ( bvmatch( result, &bottom->q_uuid ) ) {
+ break;
+ }
+ }
- if (!bottom) {
- Debug ( pcache_debug,
- "Cache replacement invoked without "
- "any query in LRU list\n", 0, 0, 0 );
- ldap_pvt_thread_mutex_unlock(&qm->lru_mutex);
- return;
+ if ( !bottom ) {
+ Debug ( pcache_debug,
+ "Could not find query with uuid=\"%s\""
+ "in LRU list\n", result->bv_val, 0, 0 );
+ ldap_pvt_thread_mutex_unlock(&qm->lru_mutex);
+ BER_BVZERO( result );
+ return;
+ }
}
temp = bottom->qtemp;
if ( rs->sr_type != REP_SEARCH ) return 0;
- for (attr = rs->sr_entry->e_attrs; attr!= NULL; attr = attr->a_next) {
- if (attr->a_desc == ad_queryid) {
- for (count=0; attr->a_vals[count].bv_val; count++)
- ;
- break;
- }
- }
- if ( count == 0 ) return 0;
+ attr = attr_find( rs->sr_entry->e_attrs, ad_queryId );
+ if ( attr == NULL ) return 0;
+
+ for ( count = 0; !BER_BVISNULL( &attr->a_vals[count] ); count++ )
+ ;
+ assert( count > 0 );
qi = op->o_tmpalloc( sizeof( struct query_info ), op->o_tmpmemctx );
qi->next = op->o_callback->sc_private;
op->o_callback->sc_private = qi;
}
static int
-remove_query_data (
+remove_query_data(
Operation *op,
SlapReply *rs,
- struct berval* query_uuid)
+ struct berval *query_uuid )
{
struct query_info *qi, *qnext;
- char filter_str[64];
+ char filter_str[ LDAP_LUTIL_UUIDSTR_BUFSIZE + STRLENOF( "(queryId=)" ) ];
#ifdef LDAP_COMP_MATCH
AttributeAssertion ava = { NULL, BER_BVNULL, NULL };
#else
sreply.sr_entry = NULL;
sreply.sr_nentries = 0;
op->ors_filterstr.bv_len = snprintf(filter_str, sizeof(filter_str),
- "(%s=%s)", ad_queryid->ad_cname.bv_val, query_uuid->bv_val);
+ "(%s=%s)", ad_queryId->ad_cname.bv_val, query_uuid->bv_val);
filter.f_ava = &ava;
- filter.f_av_desc = ad_queryid;
+ filter.f_av_desc = ad_queryId;
filter.f_av_value = *query_uuid;
op->o_tag = LDAP_REQ_SEARCH;
op->o_req_dn = qi->xdn;
op->o_req_ndn = qi->xdn;
- if ( qi->del) {
+ if ( qi->del ) {
Debug( pcache_debug, "DELETING ENTRY TEMPLATE=%s\n",
query_uuid->bv_val, 0, 0 );
if (op->o_bd->be_delete(op, &sreply) == LDAP_SUCCESS) {
deleted++;
}
+
} else {
Modifications mod;
struct berval vals[2];
vals[1].bv_len = 0;
mod.sml_op = LDAP_MOD_DELETE;
mod.sml_flags = 0;
- mod.sml_desc = ad_queryid;
- mod.sml_type = ad_queryid->ad_cname;
+ mod.sml_desc = ad_queryId;
+ mod.sml_type = ad_queryId->ad_cname;
mod.sml_values = vals;
mod.sml_nvalues = NULL;
mod.sml_next = NULL;
return -1;
}
- *filter_attrs = (AttributeName *)op->o_tmprealloc(*filter_attrs,
+ if ( filter_attrs != NULL ) {
+ *filter_attrs = (AttributeName *)op->o_tmprealloc(*filter_attrs,
(*filter_cnt + 2)*sizeof(AttributeName), op->o_tmpmemctx);
- (*filter_attrs)[*filter_cnt].an_desc = ad;
- (*filter_attrs)[*filter_cnt].an_name = ad->ad_cname;
- (*filter_attrs)[*filter_cnt].an_oc = NULL;
- (*filter_attrs)[*filter_cnt].an_oc_exclude = 0;
- BER_BVZERO( &(*filter_attrs)[*filter_cnt+1].an_name );
- (*filter_cnt)++;
- if ( ad == slap_schema.si_ad_objectClass )
- *filter_got_oc = 1;
+ (*filter_attrs)[*filter_cnt].an_desc = ad;
+ (*filter_attrs)[*filter_cnt].an_name = ad->ad_cname;
+ (*filter_attrs)[*filter_cnt].an_oc = NULL;
+ (*filter_attrs)[*filter_cnt].an_oc_exclude = 0;
+ BER_BVZERO( &(*filter_attrs)[*filter_cnt+1].an_name );
+ (*filter_cnt)++;
+ if ( ad == slap_schema.si_ad_objectClass )
+ *filter_got_oc = 1;
+ }
+
return 0;
}
Entry *head, *tail;
};
-static int
-cache_entries(
+static void
+remove_query_and_data(
Operation *op,
SlapReply *rs,
- struct berval *query_uuid)
+ cache_manager *cm,
+ struct berval *uuid )
{
- struct search_info *si = op->o_callback->sc_private;
- slap_overinst *on = si->on;
- cache_manager *cm = on->on_bi.bi_private;
query_manager* qm = cm->qm;
- int return_val = 0;
- Entry *e;
- struct berval crp_uuid;
- char uuidbuf[ LDAP_LUTIL_UUIDSTR_BUFSIZE ];
- Operation op_tmp = *op;
- query_uuid->bv_len = lutil_uuidstr(uuidbuf, sizeof(uuidbuf));
- ber_str2bv(uuidbuf, query_uuid->bv_len, 1, query_uuid);
+ qm->crfunc( qm, uuid );
+ if ( !BER_BVISNULL( uuid ) ) {
+ int return_val;
- op_tmp.o_bd = &cm->db;
- op_tmp.o_dn = cm->db.be_rootdn;
- op_tmp.o_ndn = cm->db.be_rootndn;
+ Debug( pcache_debug,
+ "Removing query UUID %s\n",
+ uuid->bv_val, 0, 0 );
+ return_val = remove_query_data( op, rs, uuid );
+ Debug( pcache_debug,
+ "QUERY REMOVED, SIZE=%d\n",
+ return_val, 0, 0);
+ ldap_pvt_thread_mutex_lock( &cm->cache_mutex );
+ cm->cur_entries -= return_val;
+ cm->num_cached_queries--;
+ Debug( pcache_debug,
+ "STORED QUERIES = %lu\n",
+ cm->num_cached_queries, 0, 0 );
+ ldap_pvt_thread_mutex_unlock( &cm->cache_mutex );
+ Debug( pcache_debug,
+ "QUERY REMOVED, CACHE ="
+ "%d entries\n",
+ cm->cur_entries, 0, 0 );
+ }
+}
- Debug( pcache_debug, "UUID for query being added = %s\n",
- uuidbuf, 0, 0 );
+/*
+ * Callback used to fetch queryId values based on entryUUID;
+ * used by pcache_remove_entries_from_cache()
+ */
+static int
+fetch_queryId_cb( Operation *op, SlapReply *rs )
+{
+ int rc = 0;
- for ( e=si->head; e; e=si->head ) {
- si->head = e->e_private;
- e->e_private = NULL;
- while ( cm->cur_entries > (cm->max_entries) ) {
- qm->crfunc(qm, &crp_uuid);
- if (crp_uuid.bv_val) {
- Debug( pcache_debug,
- "Removing query UUID %s\n",
- crp_uuid.bv_val, 0, 0 );
- return_val = remove_query_data(&op_tmp, rs, &crp_uuid);
- Debug( pcache_debug,
- "QUERY REMOVED, SIZE=%d\n",
- return_val, 0, 0);
- ldap_pvt_thread_mutex_lock(
- &cm->cache_mutex );
- cm->cur_entries -= return_val;
- cm->num_cached_queries--;
- Debug( pcache_debug,
- "STORED QUERIES = %lu\n",
- cm->num_cached_queries, 0, 0 );
- ldap_pvt_thread_mutex_unlock(
- &cm->cache_mutex );
- Debug( pcache_debug,
- "QUERY REMOVED, CACHE ="
- "%d entries\n",
- cm->cur_entries, 0, 0 );
- }
+ /* only care about searchEntry responses */
+ if ( rs->sr_type != REP_SEARCH ) {
+ return 0;
+ }
+
+ /* allow only one response per entryUUID */
+ if ( op->o_callback->sc_private != NULL ) {
+ rc = 1;
+
+ } else {
+ Attribute *a;
+
+ /* copy all queryId values into callback's private data */
+ a = attr_find( rs->sr_entry->e_attrs, ad_queryId );
+ if ( a != NULL ) {
+ BerVarray vals = NULL;
+
+ ber_bvarray_dup_x( &vals, a->a_nvals, op->o_tmpmemctx );
+ op->o_callback->sc_private = (void *)vals;
}
+ }
- return_val = merge_entry(&op_tmp, e, query_uuid);
- ldap_pvt_thread_mutex_lock(&cm->cache_mutex);
- cm->cur_entries += return_val;
- Debug( pcache_debug,
- "ENTRY ADDED/MERGED, CACHED ENTRIES=%d\n",
- cm->cur_entries, 0, 0 );
- return_val = 0;
- ldap_pvt_thread_mutex_unlock(&cm->cache_mutex);
+ /* clear entry if required */
+ if ( rs->sr_flags & REP_ENTRY_MUSTBEFREED ) {
+ entry_free( rs->sr_entry );
+ rs->sr_entry = NULL;
+ rs->sr_flags ^= REP_ENTRY_MUSTBEFREED;
}
- return return_val;
+ return rc;
}
-static int
-pcache_response(
+/*
+ * Call that allows to remove a set of entries from the cache,
+ * by forcing the removal of all the related queries.
+ */
+int
+pcache_remove_entries_from_cache(
Operation *op,
- SlapReply *rs )
+ cache_manager *cm,
+ BerVarray entryUUIDs )
{
- struct search_info *si = op->o_callback->sc_private;
- slap_overinst *on = si->on;
- cache_manager *cm = on->on_bi.bi_private;
- query_manager* qm = cm->qm;
+ Connection conn = { 0 };
+ OperationBuffer opbuf;
+ Operation op2;
+ slap_callback sc = { 0 };
+ SlapReply rs = { REP_RESULT };
+ Filter f = { 0 };
+ char filtbuf[ LDAP_LUTIL_UUIDSTR_BUFSIZE + STRLENOF( "(entryUUID=)" ) ];
+#ifdef LDAP_COMP_MATCH
+ AttributeAssertion ava = { NULL, BER_BVNULL, NULL };
+#else
+ AttributeAssertion ava = { NULL, BER_BVNULL };
+#endif
+ AttributeName attrs[ 2 ] = { 0 };
+ int s, rc;
- if ( si->save_attrs != NULL ) {
- rs->sr_attrs = si->save_attrs;
- op->ors_attrs = si->save_attrs;
- si->save_attrs = NULL;
+ if ( op == NULL ) {
+ void *thrctx = ldap_pvt_thread_pool_context();
+
+ connection_fake_init( &conn, &opbuf, thrctx );
+ op = &opbuf.ob_op;
+
+ } else {
+ op2 = *op;
+ op = &op2;
}
- if ( rs->sr_type == REP_SEARCH ) {
- Entry *e;
- /* If we haven't exceeded the limit for this query,
- * build a chain of answers to store. If we hit the
- * limit, empty the chain and ignore the rest.
- */
- if ( !si->over ) {
- if ( si->count < si->max ) {
- si->count++;
- e = entry_dup( rs->sr_entry );
- if ( !si->head ) si->head = e;
- if ( si->tail ) si->tail->e_private = e;
- si->tail = e;
- } else {
- si->over = 1;
- si->count = 0;
- for (;si->head; si->head=e) {
- e = si->head->e_private;
- si->head->e_private = NULL;
- entry_free(si->head);
- }
- si->tail = NULL;
- }
- }
+ memset( &op->oq_search, 0, sizeof( op->oq_search ) );
+ op->ors_scope = LDAP_SCOPE_SUBTREE;
+ op->ors_deref = LDAP_DEREF_NEVER;
+ f.f_choice = LDAP_FILTER_EQUALITY;
+ f.f_ava = &ava;
+ ava.aa_desc = slap_schema.si_ad_entryUUID;
+ op->ors_filter = &f;
+ op->ors_slimit = 1;
+ op->ors_tlimit = SLAP_NO_LIMIT;
+ attrs[ 0 ].an_desc = ad_queryId;
+ attrs[ 0 ].an_name = ad_queryId->ad_cname;
+ op->ors_attrs = attrs;
+ op->ors_attrsonly = 0;
- } else if ( rs->sr_type == REP_RESULT ) {
- if ( si->count ||
- ( si->qtemp->negttl && !si->count && !si->over &&
- rs->sr_err == LDAP_SUCCESS )) {
- CachedQuery *qc = qm->addfunc(op, qm, &si->query, si->qtemp,
- si->count);
+ op->o_req_dn = cm->db.be_suffix[ 0 ];
+ op->o_req_ndn = cm->db.be_nsuffix[ 0 ];
- if ( qc != NULL ) {
- if ( si->count )
+ op->o_tag = LDAP_REQ_SEARCH;
+ op->o_protocol = LDAP_VERSION3;
+ op->o_managedsait = SLAP_CONTROL_CRITICAL;
+ op->o_bd = &cm->db;
+ op->o_dn = op->o_bd->be_rootdn;
+ op->o_ndn = op->o_bd->be_rootndn;
+ sc.sc_response = fetch_queryId_cb;
+ op->o_callback = ≻
+
+ for ( s = 0; !BER_BVISNULL( &entryUUIDs[ s ] ); s++ ) {
+ BerVarray vals = NULL;
+
+ op->ors_filterstr.bv_len = snprintf( filtbuf, sizeof( filtbuf ),
+ "(entryUUID=%s)", entryUUIDs[ s ].bv_val );
+ op->ors_filterstr.bv_val = filtbuf;
+ ava.aa_value = entryUUIDs[ s ];
+
+ rc = op->o_bd->be_search( op, &rs );
+ if ( rc != LDAP_SUCCESS ) {
+ continue;
+ }
+
+ vals = (BerVarray)op->o_callback->sc_private;
+ if ( vals != NULL ) {
+ int i;
+
+ for ( i = 0; !BER_BVISNULL( &vals[ i ] ); i++ ) {
+ struct berval val = vals[ i ];
+
+ remove_query_and_data( op, &rs, cm, &val );
+
+ if ( !BER_BVISNULL( &val ) && val.bv_val != vals[ i ].bv_val ) {
+ ch_free( val.bv_val );
+ }
+ }
+
+ ber_bvarray_free_x( vals, op->o_tmpmemctx );
+ op->o_callback->sc_private = NULL;
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * Call that allows to remove a query from the cache.
+ */
+int
+pcache_remove_query_from_cache(
+ Operation *op,
+ cache_manager *cm,
+ struct berval *queryid )
+{
+ Operation op2 = *op;
+ SlapReply rs2 = { 0 };
+
+ op2.o_bd = &cm->db;
+
+ /* remove the selected query */
+ remove_query_and_data( &op2, &rs2, cm, queryid );
+
+ return LDAP_SUCCESS;
+}
+
+/*
+ * Call that allows to remove a set of queries related to an entry
+ * from the cache; if queryid is not null, the entry must belong to
+ * the query indicated by queryid.
+ */
+int
+pcache_remove_entry_queries_from_cache(
+ Operation *op,
+ cache_manager *cm,
+ struct berval *ndn,
+ struct berval *queryid )
+{
+ Connection conn = { 0 };
+ OperationBuffer opbuf;
+ Operation op2;
+ slap_callback sc = { 0 };
+ SlapReply rs = { REP_RESULT };
+ Filter f = { 0 };
+ char filter_str[ LDAP_LUTIL_UUIDSTR_BUFSIZE + STRLENOF( "(queryId=)" ) ];
+#ifdef LDAP_COMP_MATCH
+ AttributeAssertion ava = { NULL, BER_BVNULL, NULL };
+#else
+ AttributeAssertion ava = { NULL, BER_BVNULL };
+#endif
+ AttributeName attrs[ 2 ] = { 0 };
+ int rc;
+
+ BerVarray vals = NULL;
+
+ if ( op == NULL ) {
+ void *thrctx = ldap_pvt_thread_pool_context();
+
+ connection_fake_init( &conn, &opbuf, thrctx );
+ op = &opbuf.ob_op;
+
+ } else {
+ op2 = *op;
+ op = &op2;
+ }
+
+ memset( &op->oq_search, 0, sizeof( op->oq_search ) );
+ op->ors_scope = LDAP_SCOPE_BASE;
+ op->ors_deref = LDAP_DEREF_NEVER;
+ if ( queryid == NULL || BER_BVISNULL( queryid ) ) {
+ BER_BVSTR( &op->ors_filterstr, "(objectClass=*)" );
+ f.f_choice = LDAP_FILTER_PRESENT;
+ f.f_desc = slap_schema.si_ad_objectClass;
+
+ } else {
+ op->ors_filterstr.bv_len = snprintf( filter_str,
+ sizeof( filter_str ), "(%s=%s)",
+ ad_queryId->ad_cname.bv_val, queryid->bv_val );
+ f.f_choice = LDAP_FILTER_EQUALITY;
+ f.f_ava = &ava;
+ f.f_av_desc = ad_queryId;
+ f.f_av_value = *queryid;
+ }
+ op->ors_filter = &f;
+ op->ors_slimit = 1;
+ op->ors_tlimit = SLAP_NO_LIMIT;
+ attrs[ 0 ].an_desc = ad_queryId;
+ attrs[ 0 ].an_name = ad_queryId->ad_cname;
+ op->ors_attrs = attrs;
+ op->ors_attrsonly = 0;
+
+ op->o_req_dn = *ndn;
+ op->o_req_ndn = *ndn;
+
+ op->o_tag = LDAP_REQ_SEARCH;
+ op->o_protocol = LDAP_VERSION3;
+ op->o_managedsait = SLAP_CONTROL_CRITICAL;
+ op->o_bd = &cm->db;
+ op->o_dn = op->o_bd->be_rootdn;
+ op->o_ndn = op->o_bd->be_rootndn;
+ sc.sc_response = fetch_queryId_cb;
+ op->o_callback = ≻
+
+ rc = op->o_bd->be_search( op, &rs );
+ if ( rc != LDAP_SUCCESS ) {
+ return rc;
+ }
+
+ vals = (BerVarray)op->o_callback->sc_private;
+ if ( vals != NULL ) {
+ int i;
+
+ for ( i = 0; !BER_BVISNULL( &vals[ i ] ); i++ ) {
+ struct berval val = vals[ i ];
+
+ remove_query_and_data( op, &rs, cm, &val );
+
+ if ( !BER_BVISNULL( &val ) && val.bv_val != vals[ i ].bv_val ) {
+ ch_free( val.bv_val );
+ }
+ }
+
+ ber_bvarray_free_x( vals, op->o_tmpmemctx );
+ }
+
+ return LDAP_SUCCESS;
+}
+
+static int
+cache_entries(
+ Operation *op,
+ SlapReply *rs,
+ struct berval *query_uuid )
+{
+ struct search_info *si = op->o_callback->sc_private;
+ slap_overinst *on = si->on;
+ cache_manager *cm = on->on_bi.bi_private;
+ int return_val = 0;
+ Entry *e;
+ struct berval crp_uuid;
+ char uuidbuf[ LDAP_LUTIL_UUIDSTR_BUFSIZE ];
+ Operation op_tmp = *op;
+
+ query_uuid->bv_len = lutil_uuidstr(uuidbuf, sizeof(uuidbuf));
+ ber_str2bv(uuidbuf, query_uuid->bv_len, 1, query_uuid);
+
+ op_tmp.o_bd = &cm->db;
+ op_tmp.o_dn = cm->db.be_rootdn;
+ op_tmp.o_ndn = cm->db.be_rootndn;
+
+ Debug( pcache_debug, "UUID for query being added = %s\n",
+ uuidbuf, 0, 0 );
+
+ for ( e=si->head; e; e=si->head ) {
+ si->head = e->e_private;
+ e->e_private = NULL;
+ while ( cm->cur_entries > (cm->max_entries) ) {
+ BER_BVZERO( &crp_uuid );
+ remove_query_and_data( &op_tmp, rs, cm, &crp_uuid );
+ }
+
+ return_val = merge_entry(&op_tmp, e, query_uuid);
+ ldap_pvt_thread_mutex_lock(&cm->cache_mutex);
+ cm->cur_entries += return_val;
+ Debug( pcache_debug,
+ "ENTRY ADDED/MERGED, CACHED ENTRIES=%d\n",
+ cm->cur_entries, 0, 0 );
+ return_val = 0;
+ ldap_pvt_thread_mutex_unlock(&cm->cache_mutex);
+ }
+
+ return return_val;
+}
+
+static int
+pcache_op_cleanup( Operation *op, SlapReply *rs ) {
+ slap_callback *cb = op->o_callback;
+ struct search_info *si = cb->sc_private;
+ if ( rs->sr_type == REP_RESULT || op->o_abandon ||
+ rs->sr_err == SLAPD_ABANDON ) {
+ if ( si->save_attrs != NULL ) {
+ rs->sr_attrs = si->save_attrs;
+ op->ors_attrs = si->save_attrs;
+ }
+ op->o_callback = op->o_callback->sc_next;
+ op->o_tmpfree( cb, op->o_tmpmemctx );
+ }
+ return SLAP_CB_CONTINUE;
+}
+
+static int
+pcache_response(
+ Operation *op,
+ SlapReply *rs )
+{
+ struct search_info *si = op->o_callback->sc_private;
+ slap_overinst *on = si->on;
+ cache_manager *cm = on->on_bi.bi_private;
+ query_manager* qm = cm->qm;
+
+ if ( si->save_attrs != NULL ) {
+ rs->sr_attrs = si->save_attrs;
+ op->ors_attrs = si->save_attrs;
+ }
+
+ if ( rs->sr_type == REP_SEARCH ) {
+ Entry *e;
+ /* If we haven't exceeded the limit for this query,
+ * build a chain of answers to store. If we hit the
+ * limit, empty the chain and ignore the rest.
+ */
+ if ( !si->over ) {
+ if ( si->count < si->max ) {
+ si->count++;
+ e = entry_dup( rs->sr_entry );
+ if ( !si->head ) si->head = e;
+ if ( si->tail ) si->tail->e_private = e;
+ si->tail = e;
+ } else {
+ si->over = 1;
+ si->count = 0;
+ for (;si->head; si->head=e) {
+ e = si->head->e_private;
+ si->head->e_private = NULL;
+ entry_free(si->head);
+ }
+ si->tail = NULL;
+ }
+ }
+
+ } else if ( rs->sr_type == REP_RESULT ) {
+ if ( si->count ||
+ ( si->qtemp->negttl && !si->count && !si->over &&
+ rs->sr_err == LDAP_SUCCESS )) {
+ CachedQuery *qc = qm->addfunc(op, qm, &si->query, si->qtemp,
+ si->count);
+
+ if ( qc != NULL ) {
+ if ( si->count )
cache_entries( op, rs, &qc->q_uuid );
ldap_pvt_thread_mutex_lock(&cm->cache_mutex);
cm->num_cached_queries++;
} else {
filter_free( si->query.filter );
}
-
- /* free self */
- op->o_callback->sc_cleanup = slap_freeself_cb;
}
return SLAP_CB_CONTINUE;
}
-static void
+static int
add_filter_attrs(
Operation *op,
AttributeName** new_attrs,
count++;
}
- *new_attrs = (AttributeName*)ch_malloc((count+1)*
- sizeof(AttributeName));
+ *new_attrs = (AttributeName*)ch_calloc( count + 1,
+ sizeof(AttributeName) );
for (i=0; i<attrs->count; i++) {
(*new_attrs)[i].an_name = attrs->attrs[i].an_name;
(*new_attrs)[i].an_desc = attrs->attrs[i].an_desc;
j = i;
for ( i=0; i<fattr_cnt; i++ ) {
- if ( an_find(*new_attrs, &filter_attrs[i].an_name ))
+ if ( an_find(*new_attrs, &filter_attrs[i].an_name ) ) {
continue;
+ }
if ( is_at_operational(filter_attrs[i].an_desc->ad_type) ) {
- if (allop)
+ if ( allop ) {
continue;
- } else if (alluser)
+ }
+ } else if ( alluser ) {
continue;
+ }
(*new_attrs)[j].an_name = filter_attrs[i].an_name;
(*new_attrs)[j].an_desc = filter_attrs[i].an_desc;
(*new_attrs)[j].an_oc = NULL;
j++;
}
BER_BVZERO( &(*new_attrs)[j].an_name );
+
+ return count;
}
/* NOTE: this is a quick workaround to let pcache minimally interact
return rs->sr_err;
}
+#ifdef PCACHE_CONTROL_PRIVDB
+static int
+pcache_op_privdb(
+ Operation *op,
+ SlapReply *rs )
+{
+ slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
+ cache_manager *cm = on->on_bi.bi_private;
+ slap_callback *save_cb;
+ slap_op_t type;
+
+ /* skip if control is unset */
+ if ( op->o_ctrlflag[ privDB_cid ] != SLAP_CONTROL_CRITICAL ) {
+ return SLAP_CB_CONTINUE;
+ }
+
+ /* FIXME: might be a little bit exaggerated... */
+ if ( !be_isroot( op ) ) {
+ save_cb = op->o_callback;
+ op->o_callback = NULL;
+ send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
+ "pcachePrivDB: operation not allowed" );
+ op->o_callback = save_cb;
+
+ return rs->sr_err;
+ }
+
+ /* map tag to operation */
+ type = slap_req2op( op->o_tag );
+ if ( type != SLAP_OP_LAST ) {
+ BI_op_func **func;
+ int rc;
+
+ /* execute, if possible */
+ func = &cm->db.be_bind;
+ if ( func[ type ] != NULL ) {
+ Operation op2 = *op;
+
+ op2.o_bd = &cm->db;
+
+ rc = func[ type ]( &op2, rs );
+ if ( type == SLAP_OP_BIND && rc == LDAP_SUCCESS ) {
+ op->o_conn->c_authz_cookie = cm->db.be_private;
+ }
+ }
+ }
+
+ /* otherwise fall back to error */
+ save_cb = op->o_callback;
+ op->o_callback = NULL;
+ send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
+ "operation not supported with pcachePrivDB control" );
+ op->o_callback = save_cb;
+
+ return rs->sr_err;
+}
+#endif /* PCACHE_CONTROL_PRIVDB */
+
static int
pcache_op_search(
Operation *op,
AttributeName *filter_attrs = NULL;
Query query;
- QueryTemplate *qtemp = NULL;
+ QueryTemplate *qtemp = NULL;
int attr_set = -1;
CachedQuery *answerable = NULL;
int fattr_cnt=0;
int fattr_got_oc = 0;
- struct berval tempstr;
+ struct berval tempstr;
+
+#ifdef PCACHE_CONTROL_PRIVDB
+ if ( op->o_ctrlflag[ privDB_cid ] == SLAP_CONTROL_CRITICAL ) {
+ return pcache_op_privdb( op, rs );
+ }
+#endif /* PCACHE_CONTROL_PRIVDB */
tempstr.bv_val = op->o_tmpalloc( op->ors_filterstr.bv_len+1, op->o_tmpmemctx );
tempstr.bv_len = 0;
query.filter = filter_dup(op->ors_filter, NULL);
ldap_pvt_thread_rdwr_wlock(&qtemp->t_rwlock);
if ( !qtemp->t_attrs.count ) {
- add_filter_attrs(op, &qtemp->t_attrs.attrs,
+ qtemp->t_attrs.count = add_filter_attrs(op,
+ &qtemp->t_attrs.attrs,
&qm->attr_sets[attr_set],
filter_attrs, fattr_cnt, fattr_got_oc);
}
ldap_pvt_thread_rdwr_wunlock(&qtemp->t_rwlock);
- cb = op->o_tmpalloc( sizeof(*cb) + sizeof(*si), op->o_tmpmemctx);
+ cb = op->o_tmpalloc( sizeof(*cb) + sizeof(*si), op->o_tmpmemctx );
cb->sc_response = pcache_response;
- cb->sc_cleanup = NULL;
+ cb->sc_cleanup = pcache_op_cleanup;
cb->sc_private = (cb+1);
si = cb->sc_private;
si->on = on;
for ( ; attrs[count].an_name.bv_val; count++ );
}
- for (i=0; i<num; i++) {
+ /* recognize a single "*" or a "1.1" */
+ if ( count == 0 ) {
+ count = 1;
+ attrs = slap_anlist_all_user_attributes;
+
+ } else if ( count == 1 && strcmp( attrs[0].an_name.bv_val, LDAP_NO_ATTRS ) == 0 ) {
+ count = 0;
+ attrs = NULL;
+ }
+
+ for ( i = 0; i < num; i++ ) {
AttributeName *a2;
int found = 1;
- if ( count > qm->attr_sets[i].count )
+ if ( count > qm->attr_sets[i].count ) {
continue;
+ }
+
if ( !count ) {
- if ( !qm->attr_sets[i].count )
+ if ( !qm->attr_sets[i].count ) {
break;
+ }
continue;
}
+
for ( a2 = attrs; a2->an_name.bv_val; a2++ ) {
- if ( !an_find( qm->attr_sets[i].attrs, &a2->an_name )) {
+ if ( !an_find( qm->attr_sets[i].attrs, &a2->an_name ) ) {
found = 0;
break;
}
}
- if ( found )
+
+ if ( found ) {
break;
+ }
}
- if ( i == num )
+
+ if ( i == num ) {
i = -1;
+ }
+
return i;
}
int return_val, pause = 1;
QueryTemplate* templ;
- op = (Operation *) &opbuf;
- connection_fake_init( &conn, op, ctx );
+ connection_fake_init( &conn, &opbuf, ctx );
+ op = &opbuf.ob_op;
op->o_bd = &cm->db;
op->o_dn = cm->db.be_rootdn;
"( OLcfgOvAt:2.5 NAME 'olcProxyCacheQueries' "
"DESC 'Maximum number of queries to cache' "
"SYNTAX OMsInteger )", NULL, NULL },
+ { "proxySaveQueries", "TRUE|FALSE",
+ 2, 2, 0, ARG_ON_OFF|ARG_OFFSET, (void *)offsetof(cache_manager, save_queries),
+ "( OLcfgOvAt:2.6 NAME 'olcProxySaveQueries' "
+ "DESC 'Save cached queries for hot restart' "
+ "SYNTAX OMsBoolean )", NULL, NULL },
{ NULL, NULL, 0, 0, 0, ARG_IGNORED }
};
"DESC 'ProxyCache configuration' "
"SUP olcOverlayConfig "
"MUST ( olcProxyCache $ olcProxyAttrset $ olcProxyTemplate ) "
- "MAY ( olcProxyResponseCB $ olcProxyCacheQueries ) )", Cft_Overlay, pccfg, NULL, pc_cfadd },
+ "MAY ( olcProxyResponseCB $ olcProxyCacheQueries $ olcProxySaveQueries ) )",
+ Cft_Overlay, pccfg, NULL, pc_cfadd },
{ "( OLcfgOvOc:2.2 "
"NAME 'olcPcacheDatabase' "
"DESC 'Cache database configuration' "
struct berval bv;
/* FIXME: should not hardcode "olcDatabase" here */
- bv.bv_len = sprintf( ca->msg, "olcDatabase=%s", cm->db.bd_info->bi_type );
- bv.bv_val = ca->msg;
+ bv.bv_len = sprintf( ca->cr_msg, "olcDatabase=%s", cm->db.bd_info->bi_type );
+ bv.bv_val = ca->cr_msg;
ca->be = &cm->db;
/* We can only create this entry if the database is table-driven
struct berval bv;
switch( c->type ) {
case PC_MAIN:
- bv.bv_len = snprintf( c->msg, sizeof( c->msg ), "%s %d %d %d %ld",
+ bv.bv_len = snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s %d %d %d %ld",
cm->db.bd_info->bi_type, cm->max_entries, cm->numattrsets,
cm->num_entries_limit, cm->cc_period );
- bv.bv_val = c->msg;
+ bv.bv_val = c->cr_msg;
value_add_one( &c->rvalue_vals, &bv );
break;
case PC_ATTR:
for (i=0; i<cm->numattrsets; i++) {
if ( !qm->attr_sets[i].count ) continue;
- bv.bv_len = snprintf( c->msg, sizeof( c->msg ), "%d", i );
+ bv.bv_len = snprintf( c->cr_msg, sizeof( c->cr_msg ), "%d", i );
/* count the attr length */
for ( attr_name = qm->attr_sets[i].attrs;
bv.bv_len += attr_name->an_name.bv_len + 1;
bv.bv_val = ch_malloc( bv.bv_len+1 );
- ptr = lutil_strcopy( bv.bv_val, c->msg );
+ ptr = lutil_strcopy( bv.bv_val, c->cr_msg );
for ( attr_name = qm->attr_sets[i].attrs;
attr_name->an_name.bv_val; attr_name++ ) {
*ptr++ = ' ';
case PC_TEMP:
for (temp=qm->templates; temp; temp=temp->qmnext) {
if ( temp->negttl ) {
- bv.bv_len = snprintf( c->msg, sizeof( c->msg ),
+ bv.bv_len = snprintf( c->cr_msg, sizeof( c->cr_msg ),
" %d %ld %ld",
temp->attr_set_index,
temp->ttl,
temp->negttl );
} else {
- bv.bv_len = snprintf( c->msg, sizeof( c->msg ), " %d %ld",
+ bv.bv_len = snprintf( c->cr_msg, sizeof( c->cr_msg ), " %d %ld",
temp->attr_set_index,
temp->ttl );
}
*ptr++ = '"';
ptr = lutil_strcopy( ptr, temp->querystr.bv_val );
*ptr++ = '"';
- strcpy( ptr, c->msg );
+ strcpy( ptr, c->cr_msg );
ber_bvarray_add( &c->rvalue_vals, &bv );
}
if ( !c->rvalue_vals )
switch( c->type ) {
case PC_MAIN:
if ( cm->numattrsets > 0 ) {
- snprintf( c->msg, sizeof( c->msg ), "\"proxycache\" directive already provided" );
- Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", c->log, c->msg, 0 );
+ snprintf( c->cr_msg, sizeof( c->cr_msg ), "\"proxycache\" directive already provided" );
+ Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", c->log, c->cr_msg, 0 );
return( 1 );
}
if ( lutil_atoi( &cm->numattrsets, c->argv[3] ) != 0 ) {
- snprintf( c->msg, sizeof( c->msg ), "unable to parse num attrsets=\"%s\" (arg #3)",
+ snprintf( c->cr_msg, sizeof( c->cr_msg ), "unable to parse num attrsets=\"%s\" (arg #3)",
c->argv[3] );
- Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", c->log, c->msg, 0 );
+ Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", c->log, c->cr_msg, 0 );
return( 1 );
}
if ( cm->numattrsets <= 0 ) {
- snprintf( c->msg, sizeof( c->msg ), "numattrsets (arg #3) must be positive" );
- Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", c->log, c->msg, 0 );
+ snprintf( c->cr_msg, sizeof( c->cr_msg ), "numattrsets (arg #3) must be positive" );
+ Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", c->log, c->cr_msg, 0 );
return( 1 );
}
if ( cm->numattrsets > MAX_ATTR_SETS ) {
- snprintf( c->msg, sizeof( c->msg ), "numattrsets (arg #3) must be <= %d", MAX_ATTR_SETS );
- Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", c->log, c->msg, 0 );
+ snprintf( c->cr_msg, sizeof( c->cr_msg ), "numattrsets (arg #3) must be <= %d", MAX_ATTR_SETS );
+ Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", c->log, c->cr_msg, 0 );
return( 1 );
}
- if ( !backend_db_init( c->argv[1], &cm->db, -1 )) {
- snprintf( c->msg, sizeof( c->msg ), "unknown backend type (arg #1)" );
- Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", c->log, c->msg, 0 );
+ if ( !backend_db_init( c->argv[1], &cm->db, -1, NULL )) {
+ snprintf( c->cr_msg, sizeof( c->cr_msg ), "unknown backend type (arg #1)" );
+ Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", c->log, c->cr_msg, 0 );
return( 1 );
}
if ( lutil_atoi( &cm->max_entries, c->argv[2] ) != 0 ) {
- snprintf( c->msg, sizeof( c->msg ), "unable to parse max entries=\"%s\" (arg #2)",
+ snprintf( c->cr_msg, sizeof( c->cr_msg ), "unable to parse max entries=\"%s\" (arg #2)",
c->argv[2] );
- Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", c->log, c->msg, 0 );
+ Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", c->log, c->cr_msg, 0 );
return( 1 );
}
if ( cm->max_entries <= 0 ) {
- snprintf( c->msg, sizeof( c->msg ), "max entries (arg #2) must be positive.\n" );
- Debug( LDAP_DEBUG_CONFIG, "%s: %s\n", c->log, c->msg, 0 );
+ snprintf( c->cr_msg, sizeof( c->cr_msg ), "max entries (arg #2) must be positive.\n" );
+ Debug( LDAP_DEBUG_CONFIG, "%s: %s\n", c->log, c->cr_msg, 0 );
return( 1 );
}
if ( lutil_atoi( &cm->num_entries_limit, c->argv[4] ) != 0 ) {
- snprintf( c->msg, sizeof( c->msg ), "unable to parse entry limit=\"%s\" (arg #4)",
+ snprintf( c->cr_msg, sizeof( c->cr_msg ), "unable to parse entry limit=\"%s\" (arg #4)",
c->argv[4] );
- Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", c->log, c->msg, 0 );
+ Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", c->log, c->cr_msg, 0 );
return( 1 );
}
if ( cm->num_entries_limit <= 0 ) {
- snprintf( c->msg, sizeof( c->msg ), "entry limit (arg #4) must be positive" );
- Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", c->log, c->msg, 0 );
+ snprintf( c->cr_msg, sizeof( c->cr_msg ), "entry limit (arg #4) must be positive" );
+ Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", c->log, c->cr_msg, 0 );
return( 1 );
}
if ( cm->num_entries_limit > cm->max_entries ) {
- snprintf( c->msg, sizeof( c->msg ), "entry limit (arg #4) must be less than max entries %d (arg #2)", cm->max_entries );
- Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", c->log, c->msg, 0 );
+ snprintf( c->cr_msg, sizeof( c->cr_msg ), "entry limit (arg #4) must be less than max entries %d (arg #2)", cm->max_entries );
+ Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", c->log, c->cr_msg, 0 );
return( 1 );
}
if ( lutil_parse_time( c->argv[5], &t ) != 0 ) {
- snprintf( c->msg, sizeof( c->msg ), "unable to parse period=\"%s\" (arg #5)",
+ snprintf( c->cr_msg, sizeof( c->cr_msg ), "unable to parse period=\"%s\" (arg #5)",
c->argv[5] );
- Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", c->log, c->msg, 0 );
+ Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", c->log, c->cr_msg, 0 );
return( 1 );
}
cm->cc_period = (time_t)t;
break;
case PC_ATTR:
if ( cm->numattrsets == 0 ) {
- snprintf( c->msg, sizeof( c->msg ), "\"proxycache\" directive not provided yet" );
- Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", c->log, c->msg, 0 );
+ snprintf( c->cr_msg, sizeof( c->cr_msg ), "\"proxycache\" directive not provided yet" );
+ Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", c->log, c->cr_msg, 0 );
return( 1 );
}
if ( lutil_atoi( &num, c->argv[1] ) != 0 ) {
- snprintf( c->msg, sizeof( c->msg ), "unable to parse attrset #=\"%s\"",
+ snprintf( c->cr_msg, sizeof( c->cr_msg ), "unable to parse attrset #=\"%s\"",
c->argv[1] );
- Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", c->log, c->msg, 0 );
+ Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", c->log, c->cr_msg, 0 );
return( 1 );
}
if ( num < 0 || num >= cm->numattrsets ) {
- snprintf( c->msg, sizeof( c->msg ), "attrset index %d out of bounds (must be %s%d)",
+ snprintf( c->cr_msg, sizeof( c->cr_msg ), "attrset index %d out of bounds (must be %s%d)",
num, cm->numattrsets > 1 ? "0->" : "", cm->numattrsets - 1 );
- Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", c->log, c->msg, 0 );
+ Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", c->log, c->cr_msg, 0 );
return 1;
}
qm->attr_sets[num].flags |= PC_CONFIGURED;
- if ( c->argc > 2 && strcmp( c->argv[2], "*" ) ) {
+ if ( c->argc == 2 ) {
+ /* assume "1.1" */
+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
+ "need an explicit attr in attrlist; use \"*\" to indicate all attrs" );
+ Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", c->log, c->cr_msg, 0 );
+ return 1;
+
+ } else if ( c->argc == 3 ) {
+ if ( strcmp( c->argv[2], LDAP_ALL_USER_ATTRIBUTES ) == 0 ) {
+ qm->attr_sets[num].count = 1;
+ qm->attr_sets[num].attrs = (AttributeName*)ch_calloc( 2,
+ sizeof( AttributeName ) );
+ BER_BVSTR( &qm->attr_sets[num].attrs[0].an_name, LDAP_ALL_USER_ATTRIBUTES );
+ break;
+
+ } else if ( strcmp( c->argv[2], LDAP_ALL_OPERATIONAL_ATTRIBUTES ) == 0 ) {
+ qm->attr_sets[num].count = 1;
+ qm->attr_sets[num].attrs = (AttributeName*)ch_calloc( 2,
+ sizeof( AttributeName ) );
+ BER_BVSTR( &qm->attr_sets[num].attrs[0].an_name, LDAP_ALL_OPERATIONAL_ATTRIBUTES );
+ break;
+
+ } else if ( strcmp( c->argv[2], LDAP_NO_ATTRS ) == 0 ) {
+ break;
+ }
+ /* else: fallthru */
+
+ } else if ( c->argc == 4 ) {
+ if ( ( strcmp( c->argv[2], LDAP_ALL_USER_ATTRIBUTES ) == 0 && strcmp( c->argv[3], LDAP_ALL_OPERATIONAL_ATTRIBUTES ) == 0 )
+ || ( strcmp( c->argv[2], LDAP_ALL_OPERATIONAL_ATTRIBUTES ) == 0 && strcmp( c->argv[3], LDAP_ALL_USER_ATTRIBUTES ) == 0 ) )
+ {
+ qm->attr_sets[num].count = 2;
+ qm->attr_sets[num].attrs = (AttributeName*)ch_calloc( 3,
+ sizeof( AttributeName ) );
+ BER_BVSTR( &qm->attr_sets[num].attrs[0].an_name, LDAP_ALL_USER_ATTRIBUTES );
+ BER_BVSTR( &qm->attr_sets[num].attrs[1].an_name, LDAP_ALL_OPERATIONAL_ATTRIBUTES );
+ break;
+ }
+ /* else: fallthru */
+ }
+
+ if ( c->argc > 2 ) {
+ int all_user = 0, all_op = 0;
+
qm->attr_sets[num].count = c->argc - 2;
- qm->attr_sets[num].attrs = (AttributeName*)ch_malloc(
- (c->argc-1) * sizeof( AttributeName ));
+ qm->attr_sets[num].attrs = (AttributeName*)ch_calloc( c->argc - 1,
+ sizeof( AttributeName ) );
attr_name = qm->attr_sets[num].attrs;
for ( i = 2; i < c->argc; i++ ) {
attr_name->an_desc = NULL;
- if ( slap_str2ad( c->argv[i],
- &attr_name->an_desc, &text ) )
- {
- strcpy( c->msg, text );
- Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", c->log, c->msg, 0 );
+ if ( strcmp( c->argv[i], LDAP_NO_ATTRS ) == 0 ) {
+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
+ "invalid attr #%d \"%s\" in attrlist",
+ i - 2, c->argv[i] );
+ Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", c->log, c->cr_msg, 0 );
ch_free( qm->attr_sets[num].attrs );
qm->attr_sets[num].attrs = NULL;
qm->attr_sets[num].count = 0;
return 1;
}
- attr_name->an_name = attr_name->an_desc->ad_cname;
+ if ( strcmp( c->argv[i], LDAP_ALL_USER_ATTRIBUTES ) == 0 ) {
+ all_user = 1;
+ BER_BVSTR( &attr_name->an_name, LDAP_ALL_USER_ATTRIBUTES );
+ } else if ( strcmp( c->argv[i], LDAP_ALL_OPERATIONAL_ATTRIBUTES ) == 0 ) {
+ all_op = 1;
+ BER_BVSTR( &attr_name->an_name, LDAP_ALL_OPERATIONAL_ATTRIBUTES );
+ } else {
+ if ( slap_str2ad( c->argv[i], &attr_name->an_desc, &text ) ) {
+ strcpy( c->cr_msg, text );
+ Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", c->log, c->cr_msg, 0 );
+ ch_free( qm->attr_sets[num].attrs );
+ qm->attr_sets[num].attrs = NULL;
+ qm->attr_sets[num].count = 0;
+ return 1;
+ }
+ attr_name->an_name = attr_name->an_desc->ad_cname;
+ }
attr_name->an_oc = NULL;
attr_name->an_oc_exclude = 0;
if ( attr_name->an_desc == slap_schema.si_ad_objectClass )
attr_name++;
BER_BVZERO( &attr_name->an_name );
}
+
+ /* warn if list contains both "*" and "+" */
+ if ( i > 4 && all_user && all_op ) {
+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
+ "warning: attribute list contains \"*\" and \"+\"" );
+ Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", c->log, c->cr_msg, 0 );
+ }
}
break;
case PC_TEMP:
if ( cm->numattrsets == 0 ) {
- snprintf( c->msg, sizeof( c->msg ), "\"proxycache\" directive not provided yet" );
- Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", c->log, c->msg, 0 );
+ snprintf( c->cr_msg, sizeof( c->cr_msg ), "\"proxycache\" directive not provided yet" );
+ Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", c->log, c->cr_msg, 0 );
return( 1 );
}
if ( lutil_atoi( &i, c->argv[2] ) != 0 ) {
- snprintf( c->msg, sizeof( c->msg ), "unable to parse template #=\"%s\"",
+ snprintf( c->cr_msg, sizeof( c->cr_msg ), "unable to parse template #=\"%s\"",
c->argv[2] );
- Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", c->log, c->msg, 0 );
+ Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", c->log, c->cr_msg, 0 );
return( 1 );
}
if ( i < 0 || i >= cm->numattrsets ||
!(qm->attr_sets[i].flags & PC_CONFIGURED )) {
- snprintf( c->msg, sizeof( c->msg ), "template index %d invalid (%s%d)",
+ snprintf( c->cr_msg, sizeof( c->cr_msg ), "template index %d invalid (%s%d)",
i, cm->numattrsets > 1 ? "0->" : "", cm->numattrsets - 1 );
- Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", c->log, c->msg, 0 );
+ Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", c->log, c->cr_msg, 0 );
return 1;
}
temp = ch_calloc( 1, sizeof( QueryTemplate ));
ldap_pvt_thread_rdwr_init( &temp->t_rwlock );
temp->query = temp->query_last = NULL;
if ( lutil_parse_time( c->argv[3], &t ) != 0 ) {
- snprintf( c->msg, sizeof( c->msg ), "unable to parse template ttl=\"%s\"",
+ snprintf( c->cr_msg, sizeof( c->cr_msg ), "unable to parse template ttl=\"%s\"",
c->argv[3] );
- Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", c->log, c->msg, 0 );
+ Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", c->log, c->cr_msg, 0 );
return( 1 );
}
temp->ttl = (time_t)t;
if ( c->argc == 5 ) {
if ( lutil_parse_time( c->argv[4], &t ) != 0 ) {
- snprintf( c->msg, sizeof( c->msg ),
+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
"unable to parse template negttl=\"%s\"",
c->argv[4] );
- Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", c->log, c->msg, 0 );
+ Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", c->log, c->cr_msg, 0 );
return( 1 );
}
temp->negttl = (time_t)t;
cm->response_cb = PCACHE_RESPONSE_CB_TAIL;
} else {
- snprintf( c->msg, sizeof( c->msg ), "unknown specifier" );
- Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", c->log, c->msg, 0 );
+ snprintf( c->cr_msg, sizeof( c->cr_msg ), "unknown specifier" );
+ Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", c->log, c->cr_msg, 0 );
return 1;
}
break;
case PC_QUERIES:
if ( c->value_int <= 0 ) {
- snprintf( c->msg, sizeof( c->msg ), "max queries must be positive" );
- Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", c->log, c->msg, 0 );
+ snprintf( c->cr_msg, sizeof( c->cr_msg ), "max queries must be positive" );
+ Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", c->log, c->cr_msg, 0 );
return( 1 );
}
cm->max_queries = c->value_int;
static int
pcache_db_init(
- BackendDB *be )
+ BackendDB *be,
+ ConfigReply *cr)
{
slap_overinst *on = (slap_overinst *)be->bd_info;
cache_manager *cm;
cm->max_entries = 0;
cm->cur_entries = 0;
cm->max_queries = 10000;
+ cm->save_queries = 0;
cm->response_cb = PCACHE_RESPONSE_CB_TAIL;
cm->cc_period = 1000;
cm->cc_paused = 0;
return 0;
}
+static int
+pcache_cachedquery_open_cb( Operation *op, SlapReply *rs )
+{
+ assert( op->o_tag == LDAP_REQ_SEARCH );
+
+ if ( rs->sr_type == REP_SEARCH ) {
+ Attribute *a;
+
+ a = attr_find( rs->sr_entry->e_attrs, ad_cachedQueryURL );
+ if ( a != NULL ) {
+ BerVarray *valsp;
+
+ assert( a->a_nvals != NULL );
+
+ valsp = op->o_callback->sc_private;
+ assert( *valsp == NULL );
+
+ ber_bvarray_dup_x( valsp, a->a_nvals, op->o_tmpmemctx );
+ }
+ }
+
+ return 0;
+}
+
+static int
+pcache_cachedquery_count_cb( Operation *op, SlapReply *rs )
+{
+ assert( op->o_tag == LDAP_REQ_SEARCH );
+
+ if ( rs->sr_type == REP_SEARCH ) {
+ int *countp = (int *)op->o_callback->sc_private;
+
+ (*countp)++;
+ }
+
+ return 0;
+}
+
static int
pcache_db_open(
- BackendDB *be )
+ BackendDB *be,
+ ConfigReply *cr )
{
slap_overinst *on = (slap_overinst *)be->bd_info;
cache_manager *cm = on->on_bi.bi_private;
SLAP_DBFLAGS( &cm->db ) &= ~SLAP_DBFLAG_MONITORING;
}
- rc = backend_startup_one( &cm->db );
+ rc = backend_startup_one( &cm->db, NULL );
/* There is no runqueue in TOOL mode */
if ( slapMode & SLAP_SERVER_MODE ) {
cm->db.be_suffix[0].bv_val, 0 );
return 1;
}
+
+ if ( cm->save_queries ) {
+ void *thrctx = ldap_pvt_thread_pool_context();
+ Connection conn = { 0 };
+ OperationBuffer opbuf;
+ Operation *op;
+ slap_callback cb = { 0 };
+ SlapReply rs = { 0 };
+ BerVarray vals = NULL;
+ Filter f = { 0 }, f2 = { 0 };
+#ifdef LDAP_COMP_MATCH
+ AttributeAssertion ava = { NULL, BER_BVNULL, NULL };
+#else
+ AttributeAssertion ava = { NULL, BER_BVNULL };
+#endif
+ AttributeName attrs[ 2 ] = { 0 };
+
+ connection_fake_init( &conn, &opbuf, thrctx );
+ op = &opbuf.ob_op;
+
+ op->o_bd = &cm->db;
+
+ op->o_tag = LDAP_REQ_SEARCH;
+ op->o_protocol = LDAP_VERSION3;
+ cb.sc_response = pcache_cachedquery_open_cb;
+ cb.sc_private = &vals;
+ op->o_callback = &cb;
+ op->o_time = slap_get_time();
+ op->o_do_not_cache = 1;
+ op->o_managedsait = SLAP_CONTROL_CRITICAL;
+
+ op->o_dn = cm->db.be_rootdn;
+ op->o_ndn = cm->db.be_rootndn;
+ op->o_req_dn = cm->db.be_suffix[ 0 ];
+ op->o_req_ndn = cm->db.be_nsuffix[ 0 ];
+
+ op->ors_scope = LDAP_SCOPE_BASE;
+ op->ors_deref = LDAP_DEREF_NEVER;
+ op->ors_slimit = 1;
+ op->ors_tlimit = SLAP_NO_LIMIT;
+ ber_str2bv( "(cachedQueryURL=*)", 0, 0, &op->ors_filterstr );
+ f.f_choice = LDAP_FILTER_PRESENT;
+ f.f_desc = ad_cachedQueryURL;
+ op->ors_filter = &f;
+ attrs[ 0 ].an_desc = ad_cachedQueryURL;
+ attrs[ 0 ].an_name = ad_cachedQueryURL->ad_cname;
+ op->ors_attrs = attrs;
+ op->ors_attrsonly = 0;
+
+ rc = op->o_bd->be_search( op, &rs );
+ if ( rc == LDAP_SUCCESS && vals != NULL ) {
+ int i;
+
+ for ( i = 0; !BER_BVISNULL( &vals[ i ] ); i++ ) {
+ if ( url2query( vals[ i ].bv_val, op, qm ) == 0 ) {
+ cm->num_cached_queries++;
+ }
+ }
+
+ ber_bvarray_free_x( vals, op->o_tmpmemctx );
+ }
+
+ /* count cached entries */
+ f.f_choice = LDAP_FILTER_NOT;
+ f.f_not = &f2;
+ f2.f_choice = LDAP_FILTER_EQUALITY;
+ f2.f_ava = &ava;
+ f2.f_av_desc = slap_schema.si_ad_objectClass;
+ BER_BVSTR( &f2.f_av_value, "glue" );
+ ber_str2bv( "(!(objectClass=glue))", 0, 0, &op->ors_filterstr );
+
+ op->ors_slimit = SLAP_NO_LIMIT;
+ op->ors_scope = LDAP_SCOPE_SUBTREE;
+ op->ors_attrs = slap_anlist_no_attrs;
+
+ op->o_callback->sc_response = pcache_cachedquery_count_cb;
+ rs.sr_nentries = 0;
+ op->o_callback->sc_private = &rs.sr_nentries;
+
+ rc = op->o_bd->be_search( op, &rs );
+
+ cm->cur_entries = rs.sr_nentries;
+
+ /* ignore errors */
+ rc = 0;
+ }
}
return rc;
static int
pcache_db_close(
- BackendDB *be
+ BackendDB *be,
+ ConfigReply *cr
)
{
slap_overinst *on = (slap_overinst *)be->bd_info;
QueryTemplate *tm;
int i, rc = 0;
+ if ( cm->save_queries ) {
+ CachedQuery *qc;
+ BerVarray vals = NULL;
+
+ void *thrctx;
+ Connection conn = { 0 };
+ OperationBuffer opbuf;
+ Operation *op;
+ slap_callback cb = { 0 };
+
+ SlapReply rs = { REP_RESULT };
+ Modifications mod = { 0 };
+
+ thrctx = ldap_pvt_thread_pool_context();
+
+ connection_fake_init( &conn, &opbuf, thrctx );
+ op = &opbuf.ob_op;
+
+ if ( qm->templates != NULL ) {
+ for ( tm = qm->templates; tm != NULL; tm = tm->qmnext ) {
+ for ( qc = tm->query; qc; qc = qc->next ) {
+ struct berval bv;
+
+ if ( query2url( op, qc, &bv ) == 0 ) {
+ ber_bvarray_add_x( &vals, &bv, op->o_tmpmemctx );
+ }
+ }
+ }
+ }
+
+ op->o_bd = &cm->db;
+ op->o_dn = cm->db.be_rootdn;
+ op->o_ndn = cm->db.be_rootndn;
+
+ op->o_tag = LDAP_REQ_MODIFY;
+ op->o_protocol = LDAP_VERSION3;
+ cb.sc_response = slap_null_cb;
+ op->o_callback = &cb;
+ op->o_time = slap_get_time();
+ op->o_do_not_cache = 1;
+ op->o_managedsait = SLAP_CONTROL_CRITICAL;
+
+ op->o_req_dn = op->o_bd->be_suffix[0];
+ op->o_req_ndn = op->o_bd->be_nsuffix[0];
+
+ mod.sml_op = LDAP_MOD_REPLACE;
+ mod.sml_flags = 0;
+ mod.sml_desc = ad_cachedQueryURL;
+ mod.sml_type = ad_cachedQueryURL->ad_cname;
+ mod.sml_values = vals;
+ mod.sml_nvalues = NULL;
+ mod.sml_next = NULL;
+ Debug( pcache_debug,
+ "%sSETTING CACHED QUERY URLS\n",
+ vals == NULL ? "RE" : "", 0, 0 );
+
+ op->orm_modlist = &mod;
+
+ op->o_bd->be_modify( op, &rs );
+
+ ber_bvarray_free_x( vals, op->o_tmpmemctx );
+ }
+
/* cleanup stuff inherited from the original database... */
cm->db.be_limits = NULL;
cm->db.be_acl = NULL;
+ /* stop the thread ... */
+ if ( cm->cc_arg ) {
+ ldap_pvt_thread_mutex_lock( &slapd_rq.rq_mutex );
+ if ( ldap_pvt_runqueue_isrunning( &slapd_rq, cm->cc_arg ) ) {
+ ldap_pvt_runqueue_stoptask( &slapd_rq, cm->cc_arg );
+ }
+ ldap_pvt_runqueue_remove( &slapd_rq, cm->cc_arg );
+ ldap_pvt_thread_mutex_unlock( &slapd_rq.rq_mutex );
+ }
+
if ( cm->db.bd_info->bi_db_close ) {
- rc = cm->db.bd_info->bi_db_close( &cm->db );
+ rc = cm->db.bd_info->bi_db_close( &cm->db, NULL );
}
while ( (tm = qm->templates) != NULL ) {
CachedQuery *qc, *qn;
static int
pcache_db_destroy(
- BackendDB *be
+ BackendDB *be,
+ ConfigReply *cr
)
{
slap_overinst *on = (slap_overinst *)be->bd_info;
return 0;
}
+#ifdef PCACHE_CONTROL_PRIVDB
+/*
+ Control ::= SEQUENCE {
+ controlType LDAPOID,
+ criticality BOOLEAN DEFAULT FALSE,
+ controlValue OCTET STRING OPTIONAL }
+
+ controlType ::= 1.3.6.1.4.1.4203.666.11.9.5.1
+
+ * criticality must be TRUE; controlValue must be absent.
+ */
+static int
+parse_privdb_ctrl(
+ Operation *op,
+ SlapReply *rs,
+ LDAPControl *ctrl )
+{
+ if ( op->o_ctrlflag[ privDB_cid ] != SLAP_CONTROL_NONE ) {
+ rs->sr_text = "privateDB control specified multiple times";
+ return LDAP_PROTOCOL_ERROR;
+ }
+
+ if ( !BER_BVISNULL( &ctrl->ldctl_value ) ) {
+ rs->sr_text = "privateDB control value not absent";
+ return LDAP_PROTOCOL_ERROR;
+ }
+
+ if ( !ctrl->ldctl_iscritical ) {
+ rs->sr_text = "privateDB control criticality required";
+ return LDAP_PROTOCOL_ERROR;
+ }
+
+ op->o_ctrlflag[ privDB_cid ] = SLAP_CONTROL_CRITICAL;
+
+ return LDAP_SUCCESS;
+}
+
+static char *extops[] = {
+ LDAP_EXOP_MODIFY_PASSWD,
+ NULL
+};
+#endif /* PCACHE_CONTROL_PRIVDB */
+
+#ifdef PCACHE_EXOP_QUERY_DELETE
+static struct berval pcache_exop_QUERY_DELETE = BER_BVC( PCACHE_EXOP_QUERY_DELETE );
+
+#define LDAP_TAG_EXOP_QUERY_DELETE_BASE ((LBER_CLASS_CONTEXT|LBER_CONSTRUCTED) + 0)
+#define LDAP_TAG_EXOP_QUERY_DELETE_DN ((LBER_CLASS_CONTEXT|LBER_CONSTRUCTED) + 1)
+#define LDAP_TAG_EXOP_QUERY_DELETE_UUID ((LBER_CLASS_CONTEXT|LBER_CONSTRUCTED) + 2)
+
+/*
+ ExtendedRequest ::= [APPLICATION 23] SEQUENCE {
+ requestName [0] LDAPOID,
+ requestValue [1] OCTET STRING OPTIONAL }
+
+ requestName ::= 1.3.6.1.4.1.4203.666.11.9.6.1
+
+ requestValue ::= SEQUENCE { CHOICE {
+ baseDN [0] LDAPDN
+ entryDN [1] LDAPDN },
+ queryID [2] OCTET STRING (SIZE(16))
+ -- constrained to UUID }
+
+ * Either baseDN or entryDN must be present, to allow database selection.
+ *
+ * 1. if baseDN and queryID are present, then the query corresponding
+ * to queryID is deleted;
+ * 2. if baseDN is present and queryID is absent, then all queries
+ * are deleted;
+ * 3. if entryDN is present and queryID is absent, then all queries
+ * corresponding to the queryID values present in entryDN are deleted;
+ * 4. if entryDN and queryID are present, then all queries
+ * corresponding to the queryID values present in entryDN are deleted,
+ * but only if the value of queryID is contained in the entry;
+ *
+ * Currently, only 1, 3 and 4 are implemented. 2 can be obtained by either
+ * recursively deleting the database (ldapdelete -r) with PRIVDB control,
+ * or by removing the database files.
+
+ ExtendedResponse ::= [APPLICATION 24] SEQUENCE {
+ COMPONENTS OF LDAPResult,
+ responseName [10] LDAPOID OPTIONAL,
+ responseValue [11] OCTET STRING OPTIONAL }
+
+ * responseName and responseValue must be absent.
+ */
+
+/*
+ * - on success, *tagp is either LDAP_TAG_EXOP_QUERY_DELETE_BASE
+ * or LDAP_TAG_EXOP_QUERY_DELETE_DN.
+ * - if ndn != NULL, it is set to the normalized DN in the request
+ * corresponding to either the baseDN or the entryDN, according
+ * to *tagp; memory is malloc'ed on the Operation's slab, and must
+ * be freed by the caller.
+ * - if uuid != NULL, it is set to point to the normalized UUID;
+ * memory is malloc'ed on the Operation's slab, and must
+ * be freed by the caller.
+ */
+static int
+pcache_parse_query_delete(
+ struct berval *in,
+ ber_tag_t *tagp,
+ struct berval *ndn,
+ struct berval *uuid,
+ const char **text,
+ void *ctx )
+{
+ int rc = LDAP_SUCCESS;
+ ber_tag_t tag;
+ ber_len_t len = -1;
+ BerElementBuffer berbuf;
+ BerElement *ber = (BerElement *)&berbuf;
+ struct berval reqdata = BER_BVNULL;
+
+ *text = NULL;
+
+ if ( ndn ) {
+ BER_BVZERO( ndn );
+ }
+
+ if ( uuid ) {
+ BER_BVZERO( uuid );
+ }
+
+ if ( in == NULL || in->bv_len == 0 ) {
+ *text = "empty request data field in queryDelete exop";
+ return LDAP_PROTOCOL_ERROR;
+ }
+
+ ber_dupbv_x( &reqdata, in, ctx );
+
+ /* ber_init2 uses reqdata directly, doesn't allocate new buffers */
+ ber_init2( ber, &reqdata, 0 );
+
+ tag = ber_scanf( ber, "{" /*}*/ );
+
+ if ( tag == LBER_ERROR ) {
+ Debug( LDAP_DEBUG_TRACE,
+ "pcache_parse_query_delete: decoding error.\n",
+ 0, 0, 0 );
+ goto decoding_error;
+ }
+
+ tag = ber_peek_tag( ber, &len );
+ if ( tag == LDAP_TAG_EXOP_QUERY_DELETE_BASE
+ || tag == LDAP_TAG_EXOP_QUERY_DELETE_DN )
+ {
+ *tagp = tag;
+
+ if ( ndn != NULL ) {
+ struct berval dn;
+
+ tag = ber_scanf( ber, "m", &dn );
+ if ( tag == LBER_ERROR ) {
+ Debug( LDAP_DEBUG_TRACE,
+ "pcache_parse_query_delete: DN parse failed.\n",
+ 0, 0, 0 );
+ goto decoding_error;
+ }
+
+ rc = dnNormalize( 0, NULL, NULL, &dn, ndn, ctx );
+ if ( rc != LDAP_SUCCESS ) {
+ *text = "invalid DN in queryDelete exop request data";
+ goto done;
+ }
+
+ } else {
+ tag = ber_scanf( ber, "x" /* "m" */ );
+ if ( tag == LBER_DEFAULT ) {
+ goto decoding_error;
+ }
+ }
+
+ tag = ber_peek_tag( ber, &len );
+ }
+
+ if ( tag == LDAP_TAG_EXOP_QUERY_DELETE_UUID ) {
+ if ( uuid != NULL ) {
+ struct berval bv;
+ char uuidbuf[ LDAP_LUTIL_UUIDSTR_BUFSIZE ];
+
+ tag = ber_scanf( ber, "m", &bv );
+ if ( tag == LBER_ERROR ) {
+ Debug( LDAP_DEBUG_TRACE,
+ "pcache_parse_query_delete: UUID parse failed.\n",
+ 0, 0, 0 );
+ goto decoding_error;
+ }
+
+ if ( bv.bv_len != 16 ) {
+ Debug( LDAP_DEBUG_TRACE,
+ "pcache_parse_query_delete: invalid UUID length %lu.\n",
+ (unsigned long)bv.bv_len, 0, 0 );
+ goto decoding_error;
+ }
+
+ rc = lutil_uuidstr_from_normalized(
+ bv.bv_val, bv.bv_len,
+ uuidbuf, sizeof( uuidbuf ) );
+ if ( rc == -1 ) {
+ goto decoding_error;
+ }
+ ber_str2bv( uuidbuf, rc, 1, uuid );
+ rc = LDAP_SUCCESS;
+
+ } else {
+ tag = ber_skip_tag( ber, &len );
+ if ( tag == LBER_DEFAULT ) {
+ goto decoding_error;
+ }
+
+ if ( len != 16 ) {
+ Debug( LDAP_DEBUG_TRACE,
+ "pcache_parse_query_delete: invalid UUID length %lu.\n",
+ (unsigned long)len, 0, 0 );
+ goto decoding_error;
+ }
+ }
+
+ tag = ber_peek_tag( ber, &len );
+ }
+
+ if ( tag != LBER_DEFAULT || len != 0 ) {
+decoding_error:;
+ Debug( LDAP_DEBUG_TRACE,
+ "pcache_parse_query_delete: decoding error\n",
+ 0, 0, 0 );
+ rc = LDAP_PROTOCOL_ERROR;
+ *text = "queryDelete data decoding error";
+
+done:;
+ if ( ndn && !BER_BVISNULL( ndn ) ) {
+ slap_sl_free( ndn->bv_val, ctx );
+ BER_BVZERO( ndn );
+ }
+
+ if ( uuid && !BER_BVISNULL( uuid ) ) {
+ slap_sl_free( uuid->bv_val, ctx );
+ BER_BVZERO( uuid );
+ }
+ }
+
+ if ( !BER_BVISNULL( &reqdata ) ) {
+ ber_memfree_x( reqdata.bv_val, ctx );
+ }
+
+ return rc;
+}
+
+static int
+pcache_exop_query_delete(
+ Operation *op,
+ SlapReply *rs )
+{
+ BackendDB *bd = op->o_bd;
+
+ struct berval uuid = BER_BVNULL,
+ *uuidp = NULL;
+ char buf[ SLAP_TEXT_BUFLEN ] = { '\0' };
+ int len = 0;
+ ber_tag_t tag = LBER_DEFAULT;
+
+ if ( LogTest( LDAP_DEBUG_STATS ) ) {
+ uuidp = &uuid;
+ }
+
+ rs->sr_err = pcache_parse_query_delete( op->ore_reqdata,
+ &tag, &op->o_req_ndn, uuidp,
+ &rs->sr_text, op->o_tmpmemctx );
+ if ( rs->sr_err != LDAP_SUCCESS ) {
+ return rs->sr_err;
+ }
+
+ if ( LogTest( LDAP_DEBUG_STATS ) ) {
+ assert( !BER_BVISNULL( &op->o_req_ndn ) );
+ len = snprintf( buf, sizeof( buf ), " dn=\"%s\"", op->o_req_ndn.bv_val );
+
+ if ( !BER_BVISNULL( &uuid ) ) {
+ snprintf( &buf[ len ], sizeof( buf ) - len, " queryId=\"%s\"", uuid.bv_val );
+ }
+
+ Debug( LDAP_DEBUG_STATS, "%s QUERY DELETE%s\n",
+ op->o_log_prefix, buf, 0 );
+ }
+ op->o_req_dn = op->o_req_ndn;
+
+ op->o_bd = select_backend( &op->o_req_ndn, 0 );
+ rs->sr_err = backend_check_restrictions( op, rs,
+ (struct berval *)&pcache_exop_QUERY_DELETE );
+ if ( rs->sr_err != LDAP_SUCCESS ) {
+ goto done;
+ }
+
+ if ( op->o_bd->be_extended == NULL ) {
+ send_ldap_error( op, rs, LDAP_UNAVAILABLE_CRITICAL_EXTENSION,
+ "backend does not support extended operations" );
+ goto done;
+ }
+
+ op->o_bd->be_extended( op, rs );
+
+done:;
+ if ( !BER_BVISNULL( &op->o_req_ndn ) ) {
+ op->o_tmpfree( op->o_req_ndn.bv_val, op->o_tmpmemctx );
+ BER_BVZERO( &op->o_req_ndn );
+ BER_BVZERO( &op->o_req_dn );
+ }
+
+ if ( !BER_BVISNULL( &uuid ) ) {
+ op->o_tmpfree( uuid.bv_val, op->o_tmpmemctx );
+ }
+
+ op->o_bd = bd;
+
+ return rs->sr_err;
+}
+
+static int
+pcache_op_extended( Operation *op, SlapReply *rs )
+{
+ slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
+ cache_manager *cm = on->on_bi.bi_private;
+
+#ifdef PCACHE_CONTROL_PRIVDB
+ if ( op->o_ctrlflag[ privDB_cid ] == SLAP_CONTROL_CRITICAL ) {
+ return pcache_op_privdb( op, rs );
+ }
+#endif /* PCACHE_CONTROL_PRIVDB */
+
+ if ( bvmatch( &op->ore_reqoid, &pcache_exop_QUERY_DELETE ) ) {
+ struct berval uuid = BER_BVNULL;
+ ber_tag_t tag = LBER_DEFAULT;
+
+ rs->sr_err = pcache_parse_query_delete( op->ore_reqdata,
+ &tag, NULL, &uuid, &rs->sr_text, op->o_tmpmemctx );
+ assert( rs->sr_err == LDAP_SUCCESS );
+
+ if ( tag == LDAP_TAG_EXOP_QUERY_DELETE_DN ) {
+ /* remove all queries related to the selected entry */
+ rs->sr_err = pcache_remove_entry_queries_from_cache( op,
+ cm, &op->o_req_ndn, &uuid );
+
+ } else if ( tag == LDAP_TAG_EXOP_QUERY_DELETE_BASE ) {
+ if ( !BER_BVISNULL( &uuid ) ) {
+ /* remove the selected query */
+ rs->sr_err = pcache_remove_query_from_cache( op,
+ cm, &uuid );
+
+ } else {
+ /* TODO: remove all queries */
+ rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
+ rs->sr_text = "deletion of all queries not implemented";
+ }
+ }
+
+ op->o_tmpfree( uuid.bv_val, op->o_tmpmemctx );
+ }
+
+ return rs->sr_err;
+}
+#endif /* PCACHE_EXOP_QUERY_DELETE */
+
static slap_overinst pcache;
static char *obsolete_names[] = {
NULL
};
-int pcache_initialize()
+#if SLAPD_OVER_PROXYCACHE == SLAPD_MOD_DYNAMIC
+static
+#endif /* SLAPD_OVER_PROXYCACHE == SLAPD_MOD_DYNAMIC */
+int
+pcache_initialize()
{
- int code;
+ int i, code;
struct berval debugbv = BER_BVC("pcache");
- if (( code = slap_loglevel_get( &debugbv, &pcache_debug )))
+ code = slap_loglevel_get( &debugbv, &pcache_debug );
+ if ( code ) {
return code;
+ }
- code = register_at( queryid_schema, &ad_queryid, 0 );
- if ( code ) {
+#ifdef PCACHE_CONTROL_PRIVDB
+ code = register_supported_control( PCACHE_CONTROL_PRIVDB,
+ SLAP_CTRL_BIND|SLAP_CTRL_ACCESS|SLAP_CTRL_HIDE, extops,
+ parse_privdb_ctrl, &privDB_cid );
+ if ( code != LDAP_SUCCESS ) {
Debug( LDAP_DEBUG_ANY,
- "pcache_initialize: register_at failed\n", 0, 0, 0 );
+ "pcache_initialize: failed to register control %s (%d)\n",
+ PCACHE_CONTROL_PRIVDB, code, 0 );
return code;
}
+#endif /* PCACHE_CONTROL_PRIVDB */
+
+#ifdef PCACHE_EXOP_QUERY_DELETE
+ code = load_extop2( (struct berval *)&pcache_exop_QUERY_DELETE,
+ SLAP_EXOP_WRITES|SLAP_EXOP_HIDE, pcache_exop_query_delete,
+ 0 );
+ if ( code != LDAP_SUCCESS ) {
+ Debug( LDAP_DEBUG_ANY,
+ "pcache_initialize: unable to register queryDelete exop: %d.\n",
+ code, 0, 0 );
+ return code;
+ }
+#endif /* PCACHE_EXOP_QUERY_DELETE */
+
+ for ( i = 0; as[i].desc != NULL; i++ ) {
+ code = register_at( as[i].desc, as[i].adp, 0 );
+ if ( code ) {
+ Debug( LDAP_DEBUG_ANY,
+ "pcache_initialize: register_at #%d failed\n", i, 0, 0 );
+ return code;
+ }
+ }
pcache.on_bi.bi_type = "pcache";
pcache.on_bi.bi_obsolete_names = obsolete_names;
pcache.on_bi.bi_db_destroy = pcache_db_destroy;
pcache.on_bi.bi_op_search = pcache_op_search;
+#ifdef PCACHE_CONTROL_PRIVDB
+ pcache.on_bi.bi_op_bind = pcache_op_privdb;
+ pcache.on_bi.bi_op_compare = pcache_op_privdb;
+ pcache.on_bi.bi_op_modrdn = pcache_op_privdb;
+ pcache.on_bi.bi_op_modify = pcache_op_privdb;
+ pcache.on_bi.bi_op_add = pcache_op_privdb;
+ pcache.on_bi.bi_op_delete = pcache_op_privdb;
+#endif /* PCACHE_CONTROL_PRIVDB */
+#ifdef PCACHE_EXOP_QUERY_DELETE
+ pcache.on_bi.bi_extended = pcache_op_extended;
+#elif defined( PCACHE_CONTROL_PRIVDB )
+ pcache.on_bi.bi_extended = pcache_op_privdb;
+#endif
pcache.on_bi.bi_chk_controls = pcache_chk_controls;
#include <ldap.h>
#include "lutil.h"
#include "slap.h"
-#if SLAPD_MODULES
+#ifdef SLAPD_MODULES
#define LIBLTDL_DLL_IMPORT /* Win32: don't re-export libltdl's symbols */
#include <ltdl.h>
#endif
static pw_conn *pwcons;
static int ppolicy_cid;
+static int ov_count;
typedef struct pass_policy {
AttributeDescription *ad; /* attribute to which the policy applies */
#define PPOLICY_EXPIRE 0x80L /* primitive + 0 */
#define PPOLICY_GRACE 0x81L /* primitive + 1 */
+static const char ppolicy_ctrl_oid[] = LDAP_CONTROL_PASSWORDPOLICYRESPONSE;
+
static LDAPControl *
create_passcontrol( int exptime, int grace, LDAPPasswordPolicyError err )
{
if ( c == NULL ) {
return NULL;
}
- c->ldctl_oid = LDAP_CONTROL_PASSWORDPOLICYRESPONSE;
+ c->ldctl_oid = (char *)ppolicy_ctrl_oid;
c->ldctl_iscritical = 0;
BER_BVZERO( &c->ldctl_value );
rc = LDAP_SUCCESS;
if (pp->pwdCheckModule[0]) {
-#if SLAPD_MODULES
+#ifdef SLAPD_MODULES
lt_dlhandle mod;
const char *err;
assert( rs->sr_ctrls[0] != NULL );
for ( n = 0; rs->sr_ctrls[n]; n++ ) {
- if ( rs->sr_ctrls[n]->ldctl_oid == LDAP_CONTROL_PASSWORDPOLICYRESPONSE ) {
+ if ( rs->sr_ctrls[n]->ldctl_oid == ppolicy_ctrl_oid ) {
ch_free( rs->sr_ctrls[n]->ldctl_value.bv_val );
ch_free( rs->sr_ctrls[n] );
rs->sr_ctrls[n] = (LDAPControl *)(-1);
slap_callback *sc;
for ( sc = op->o_callback; sc; sc=sc->sc_next ) {
- if ( sc->sc_response == slap_replog_cb &&
+ if ( sc->sc_response == slap_null_cb &&
sc->sc_private ) {
req_pwdexop_s *qpw = sc->sc_private;
newpw = qpw->rs_new;
goto return_results;
}
- if (pp.pwdMinAge > 0) {
+ /* Check age, but only if pwdReset is not TRUE */
+ pa = attr_find( e->e_attrs, ad_pwdReset );
+ if ((!pa || !bvmatch( &pa->a_nvals[0], &slap_true_bv )) &&
+ pp.pwdMinAge > 0) {
time_t pwtime = (time_t)-1, now;
int age;
SlapReply *rs,
LDAPControl *ctrl )
{
- if ( ctrl->ldctl_value.bv_len ) {
- rs->sr_text = "passwordPolicyRequest control value not empty";
+ if ( !BER_BVISNULL( &ctrl->ldctl_value ) ) {
+ rs->sr_text = "passwordPolicyRequest control value not absent";
return LDAP_PROTOCOL_ERROR;
}
op->o_ctrlflag[ppolicy_cid] = ctrl->ldctl_iscritical
static int
ppolicy_db_init(
- BackendDB *be
+ BackendDB *be,
+ ConfigReply *cr
)
{
slap_overinst *on = (slap_overinst *) be->bd_info;
static int
ppolicy_db_open(
- BackendDB *be
+ BackendDB *be,
+ ConfigReply *cr
)
{
+ ov_count++;
return overlay_register_control( be, LDAP_CONTROL_PASSWORDPOLICYREQUEST );
}
static int
ppolicy_close(
- BackendDB *be
+ BackendDB *be,
+ ConfigReply *cr
)
{
slap_overinst *on = (slap_overinst *) be->bd_info;
pp_info *pi = on->on_bi.bi_private;
-
- free( pwcons );
+
+ /* Perhaps backover should provide bi_destroy hooks... */
+ ov_count--;
+ if ( ov_count <=0 && pwcons ) {
+ free( pwcons );
+ pwcons = NULL;
+ }
free( pi->def_policy.bv_val );
free( pi );
static BerValue refint_ndn = BER_BVC("cn=referential integrity overlay");
typedef struct refint_attrs_s {
- struct refint_attrs_s *next;
- AttributeDescription *attr;
+ struct refint_attrs_s *next;
+ AttributeDescription *attr;
+ BerVarray old_vals;
+ BerVarray old_nvals;
+ BerVarray new_vals;
+ BerVarray new_nvals;
} refint_attrs;
typedef struct dependents_s {
#define RUNQ_INTERVAL 36000 /* a long time */
+static MatchingRule *mr_dnSubtreeMatch;
+
enum {
REFINT_ATTRS = 1,
REFINT_NOTHING
ip->next = dd->attrs;
dd->attrs = ip;
} else {
- snprintf( c->msg, sizeof( c->msg ),
+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
"%s <%s>: %s", c->argv[0], c->argv[i], text );
Debug ( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
- "%s: %s\n", c->log, c->msg, 0 );
+ "%s: %s\n", c->log, c->cr_msg, 0 );
rc = ARG_BAD_CONF;
}
}
static int
refint_db_init(
- BackendDB *be
+ BackendDB *be,
+ ConfigReply *cr
)
{
slap_overinst *on = (slap_overinst *)be->bd_info;
static int
refint_db_destroy(
- BackendDB *be
+ BackendDB *be,
+ ConfigReply *cr
)
{
slap_overinst *on = (slap_overinst *)be->bd_info;
static int
refint_open(
- BackendDB *be
+ BackendDB *be,
+ ConfigReply *cr
)
{
slap_overinst *on = (slap_overinst *)be->bd_info;
static int
refint_close(
- BackendDB *be
+ BackendDB *be,
+ ConfigReply *cr
)
{
slap_overinst *on = (slap_overinst *) be->bd_info;
rq->attrs = ip;
ip->attrs = NULL;
for(ia = da; ia; ia = ia->next) {
- if ( (a = attr_find(rs->sr_entry->e_attrs, ia->attr) ) )
- for(i = 0, b = a->a_nvals; b[i].bv_val; i++)
- if(bvmatch(&rq->oldndn, &b[i])) {
- na = op->o_tmpalloc(sizeof( refint_attrs ), op->o_tmpmemctx );
- na->next = ip->attrs;
- ip->attrs = na;
- na->attr = ia->attr;
- /* If this is a delete and there's only one value, and
- * we have a nothing DN configured, allocate the attr again.
- */
- if(!b[1].bv_val && BER_BVISEMPTY( &rq->newdn ) &&
- dd->nothing.bv_val) {
- na = op->o_tmpalloc(sizeof( refint_attrs ), op->o_tmpmemctx );
- na->next = ip->attrs;
- ip->attrs = na;
- na->attr = ia->attr;
+ if ( (a = attr_find(rs->sr_entry->e_attrs, ia->attr) ) ) {
+ int first = -1, count = 0, deleted = 0;
+
+ na = NULL;
+
+ for(i = 0, b = a->a_nvals; b[i].bv_val; i++) {
+ count++;
+
+ if(dnIsSuffix(&b[i], &rq->oldndn)) {
+ /* first match? create structure */
+ if ( na == NULL ) {
+ na = op->o_tmpcalloc( 1,
+ sizeof( refint_attrs ),
+ op->o_tmpmemctx );
+ na->next = ip->attrs;
+ ip->attrs = na;
+ na->attr = ia->attr;
+
+ /* delete, or exact match? note it's first match */
+ if ( BER_BVISEMPTY( &rq->newdn ) &&
+ b[i].bv_len == rq->oldndn.bv_len )
+ {
+ first = i;
+ }
+ }
+
+ /* if it's a rename, or a subordinate match,
+ * save old and build new dn */
+ if ( !BER_BVISEMPTY( &rq->newdn ) &&
+ b[i].bv_len != rq->oldndn.bv_len )
+ {
+ struct berval newsub, newdn, olddn, oldndn;
+
+ /* if not first, save first as well */
+ if ( first != -1 ) {
+
+ ber_dupbv_x( &olddn, &a->a_vals[first], op->o_tmpmemctx );
+ ber_bvarray_add_x( &na->old_vals, &olddn, op->o_tmpmemctx );
+ ber_dupbv_x( &oldndn, &a->a_nvals[first], op->o_tmpmemctx );
+ ber_bvarray_add_x( &na->old_nvals, &oldndn, op->o_tmpmemctx );
+
+ newsub = a->a_vals[first];
+ newsub.bv_len -= rq->olddn.bv_len + 1;
+
+ build_new_dn( &newdn, &rq->newdn, &newsub, op->o_tmpmemctx );
+
+ ber_bvarray_add_x( &na->new_vals, &newdn, op->o_tmpmemctx );
+
+ newsub = a->a_nvals[first];
+ newsub.bv_len -= rq->oldndn.bv_len + 1;
+
+ build_new_dn( &newdn, &rq->newndn, &newsub, op->o_tmpmemctx );
+
+ ber_bvarray_add_x( &na->new_nvals, &newdn, op->o_tmpmemctx );
+
+ first = -1;
+ }
+
+ ber_dupbv_x( &olddn, &a->a_vals[i], op->o_tmpmemctx );
+ ber_bvarray_add_x( &na->old_vals, &olddn, op->o_tmpmemctx );
+ ber_dupbv_x( &oldndn, &a->a_nvals[i], op->o_tmpmemctx );
+ ber_bvarray_add_x( &na->old_nvals, &oldndn, op->o_tmpmemctx );
+
+ newsub = a->a_vals[i];
+ newsub.bv_len -= rq->olddn.bv_len + 1;
+
+ build_new_dn( &newdn, &rq->newdn, &newsub, op->o_tmpmemctx );
+
+ ber_bvarray_add_x( &na->new_vals, &newdn, op->o_tmpmemctx );
+
+ newsub = a->a_nvals[i];
+ newsub.bv_len -= rq->oldndn.bv_len + 1;
+
+ build_new_dn( &newdn, &rq->newndn, &newsub, op->o_tmpmemctx );
+
+ ber_bvarray_add_x( &na->new_nvals, &newdn, op->o_tmpmemctx );
+ }
+
+ /* count deteles */
+ if ( BER_BVISEMPTY( &rq->newdn ) ) {
+ deleted++;
+ }
+ }
+
+ /* If this is a delete and no value would be left, and
+ * we have a nothing DN configured, allocate the attr again.
+ */
+ if ( count == deleted && !BER_BVISNULL(&dd->nothing) )
+ {
+ na = op->o_tmpcalloc( 1,
+ sizeof( refint_attrs ),
+ op->o_tmpmemctx );
+ na->next = ip->attrs;
+ ip->attrs = na;
+ na->attr = ia->attr;
+ }
+
+ Debug( LDAP_DEBUG_TRACE, "refint_search_cb: %s: %s (#%d)\n",
+ a->a_desc->ad_cname.bv_val, rq->olddn.bv_val, count );
}
- Debug(LDAP_DEBUG_TRACE, "refint_search_cb: %s: %s\n",
- a->a_desc->ad_cname.bv_val, rq->olddn.bv_val, 0);
- break;
- }
+ }
}
+
return(0);
}
slap_callback cb = { NULL, NULL, NULL, NULL };
Filter ftop, *fptr;
refint_q *rq;
- dependent_data *dp;
+ dependent_data *dp, *dp_next;
refint_attrs *ra, *ip;
int rc;
- op = (Operation *) &opbuf;
- connection_fake_init( &conn, op, ctx );
+ connection_fake_init( &conn, &opbuf, ctx );
+ op = &opbuf.ob_op;
/*
** build a search filter for all configured attributes;
ftop.f_or = NULL;
op->ors_filter = &ftop;
for(ip = id->attrs; ip; ip = ip->next) {
- fptr = op->o_tmpalloc( sizeof(Filter) + sizeof(AttributeAssertion),
- op->o_tmpmemctx );
- fptr->f_choice = LDAP_FILTER_EQUALITY;
- fptr->f_ava = (AttributeAssertion *)(fptr+1);
- fptr->f_ava->aa_desc = ip->attr;
+ fptr = op->o_tmpcalloc( sizeof(Filter) + sizeof(MatchingRuleAssertion),
+ 1, op->o_tmpmemctx );
+ /* Use (attr:dnSubtreeMatch:=value) to catch subtree rename
+ * and subtree delete where supported */
+ fptr->f_choice = LDAP_FILTER_EXT;
+ fptr->f_mra = (MatchingRuleAssertion *)(fptr+1);
+ fptr->f_mr_rule = mr_dnSubtreeMatch;
+ fptr->f_mr_rule_text = mr_dnSubtreeMatch->smr_str;
+ fptr->f_mr_desc = ip->attr;
+ fptr->f_mr_dnattrs = 0;
fptr->f_next = ftop.f_or;
ftop.f_or = fptr;
}
break;
for (fptr = ftop.f_or; fptr; fptr=fptr->f_next )
- fptr->f_av_value = rq->oldndn;
+ fptr->f_mr_value = rq->oldndn;
filter2bv_x( op, op->ors_filter, &op->ors_filterstr );
**
*/
- for(dp = rq->attrs; dp; dp = dp->next) {
+ for(dp = rq->attrs; dp; dp = dp_next) {
Modifications *m, *first = NULL;
+ dp_next = dp->next;
+
op->orm_modlist = NULL;
op->o_req_dn = dp->dn;
op->o_req_ndn = dp->ndn;
- op->o_bd = select_backend(&dp->ndn, 0, 1);
+ op->o_bd = select_backend(&dp->ndn, 1);
if(!op->o_bd) {
Debug( LDAP_DEBUG_TRACE,
"refint_response: no backend for DN %s!\n",
}
rs.sr_type = REP_RESULT;
for (ra = dp->attrs; ra; ra = dp->attrs) {
+ size_t len;
+
dp->attrs = ra->next;
/* Set our ModifiersName */
if ( SLAP_LASTMOD( op->o_bd )) {
m->sml_nvalues[0] = refint_ndn;
}
if ( !BER_BVISEMPTY( &rq->newdn ) || ( ra->next &&
- ra->attr == ra->next->attr )) {
- m = op->o_tmpalloc( sizeof(Modifications) +
- 4*sizeof(BerValue), op->o_tmpmemctx );
+ ra->attr == ra->next->attr ))
+ {
+ len = sizeof(Modifications);
+
+ if ( ra->new_vals == NULL ) {
+ len += 4*sizeof(BerValue);
+ }
+
+ m = op->o_tmpalloc( len, op->o_tmpmemctx );
m->sml_next = op->orm_modlist;
if ( !first )
first = m;
m->sml_flags = 0;
m->sml_desc = ra->attr;
m->sml_type = ra->attr->ad_cname;
- m->sml_values = (BerVarray)(m+1);
- m->sml_nvalues = m->sml_values+2;
- BER_BVZERO( &m->sml_values[1] );
- BER_BVZERO( &m->sml_nvalues[1] );
- if ( BER_BVISEMPTY( &rq->newdn )) {
- op->o_tmpfree( ra, op->o_tmpmemctx );
- ra = dp->attrs;
- dp->attrs = ra->next;
- m->sml_values[0] = id->nothing;
- m->sml_nvalues[0] = id->nnothing;
+ if ( ra->new_vals == NULL ) {
+ m->sml_values = (BerVarray)(m+1);
+ m->sml_nvalues = m->sml_values+2;
+ BER_BVZERO( &m->sml_values[1] );
+ BER_BVZERO( &m->sml_nvalues[1] );
+ if ( BER_BVISEMPTY( &rq->newdn )) {
+ op->o_tmpfree( ra, op->o_tmpmemctx );
+ ra = dp->attrs;
+ dp->attrs = ra->next;
+ m->sml_values[0] = id->nothing;
+ m->sml_nvalues[0] = id->nnothing;
+ } else {
+ m->sml_values[0] = rq->newdn;
+ m->sml_nvalues[0] = rq->newndn;
+ }
} else {
- m->sml_values[0] = rq->newdn;
- m->sml_nvalues[0] = rq->newndn;
+ m->sml_values = ra->new_vals;
+ m->sml_nvalues = ra->new_nvals;
}
}
- m = op->o_tmpalloc( sizeof(Modifications) + 4*sizeof(BerValue),
- op->o_tmpmemctx );
+
+ len = sizeof(Modifications);
+ if ( ra->old_vals == NULL ) {
+ len += 4*sizeof(BerValue);
+ }
+
+ m = op->o_tmpalloc( len, op->o_tmpmemctx );
m->sml_next = op->orm_modlist;
op->orm_modlist = m;
if ( !first )
m->sml_flags = 0;
m->sml_desc = ra->attr;
m->sml_type = ra->attr->ad_cname;
- m->sml_values = (BerVarray)(m+1);
- m->sml_nvalues = m->sml_values+2;
- m->sml_values[0] = rq->olddn;
- m->sml_nvalues[0] = rq->oldndn;
- BER_BVZERO( &m->sml_values[1] );
- BER_BVZERO( &m->sml_nvalues[1] );
+ if ( ra->old_vals == NULL ) {
+ m->sml_values = (BerVarray)(m+1);
+ m->sml_nvalues = m->sml_values+2;
+ m->sml_values[0] = rq->olddn;
+ m->sml_nvalues[0] = rq->oldndn;
+ BER_BVZERO( &m->sml_values[1] );
+ BER_BVZERO( &m->sml_nvalues[1] );
+ } else {
+ m->sml_values = ra->old_vals;
+ m->sml_nvalues = ra->old_nvals;
+ }
op->o_tmpfree( ra, op->o_tmpmemctx );
}
while (( m = op->orm_modlist )) {
op->orm_modlist = m->sml_next;
+ if ( m->sml_values && m->sml_values != (BerVarray)(m+1) ) {
+ ber_bvarray_free_x( m->sml_values, op->o_tmpmemctx );
+ ber_bvarray_free_x( m->sml_nvalues, op->o_tmpmemctx );
+ }
op->o_tmpfree( m, op->o_tmpmemctx );
if ( m == first ) break;
}
ch_free( rq );
}
+ /* free filter */
+ for ( fptr = ftop.f_or; fptr; ) {
+ Filter *f_next = fptr->f_next;
+ op->o_tmpfree( fptr, op->o_tmpmemctx );
+ fptr = f_next;
+ }
+
/* wait until we get explicitly scheduled again */
ldap_pvt_thread_mutex_lock( &slapd_rq.rq_mutex );
ldap_pvt_runqueue_stoptask( &slapd_rq, id->qtask );
**
*/
- db = select_backend(&id->dn, 0, 1);
+ db = select_backend(&id->dn, 1);
if(db) {
if (!db->be_search || !db->be_modify) {
int refint_initialize() {
int rc;
+ mr_dnSubtreeMatch = mr_find( "dnSubtreeMatch" );
+ if ( mr_dnSubtreeMatch == NULL ) {
+ Debug( LDAP_DEBUG_ANY, "refint_initialize: "
+ "unable to find MatchingRule 'dnSubtreeMatch'.\n",
+ 0, 0, 0 );
+ return 1;
+ }
+
/* statically declared just after the #includes at top */
refint.on_bi.bi_type = "refint";
refint.on_bi.bi_db_init = refint_db_init;
#include <ac/socket.h>
#include "slap.h"
+#include "config.h"
#include "lutil.h"
#include "ldif.h"
{
retcode_cb_t *rdc = (retcode_cb_t *)op->o_callback->sc_private;
+ op->o_tag = rdc->rdc_tag;
if ( rs->sr_type == REP_SEARCH ) {
ber_tag_t o_tag = op->o_tag;
int rc;
- op->o_tag = rdc->rdc_tag;
if ( op->o_tag == LDAP_REQ_SEARCH ) {
rs->sr_attrs = rdc->rdc_attrs;
}
return rc;
}
- if ( rs->sr_err == LDAP_SUCCESS ) {
+ switch ( rs->sr_err ) {
+ case LDAP_SUCCESS:
+ case LDAP_NO_SUCH_OBJECT:
+ /* in case of noSuchObject, stop the internal search
+ * for in-directory error stuff */
if ( !op->o_abandon ) {
rdc->rdc_flags = SLAP_CB_CONTINUE;
}
case LDAP_REQ_BIND:
/* skip if rootdn */
+ /* FIXME: better give the db a chance? */
if ( be_isroot_pw( op ) ) {
- return SLAP_CB_CONTINUE;
+ return LDAP_SUCCESS;
}
return retcode_op_internal( op, rs );
}
static int
-retcode_db_init( BackendDB *be )
+retcode_db_init( BackendDB *be, ConfigReply *cr )
{
slap_overinst *on = (slap_overinst *)be->bd_info;
retcode_t *rd;
}
static int
-retcode_db_open( BackendDB *be )
+retcode_db_open( BackendDB *be, ConfigReply *cr)
{
slap_overinst *on = (slap_overinst *)be->bd_info;
retcode_t *rd = (retcode_t *)on->on_bi.bi_private;
}
static int
-retcode_db_destroy( BackendDB *be )
+retcode_db_destroy( BackendDB *be, ConfigReply *cr )
{
slap_overinst *on = (slap_overinst *)be->bd_info;
retcode_t *rd = (retcode_t *)on->on_bi.bi_private;
#include <ac/string.h>
#include "slap.h"
+#include "config.h"
+#include "lutil.h"
#include "rwm.h"
typedef struct rwm_op_state {
struct berval ro_ndn;
struct berval r_dn;
struct berval r_ndn;
+ AttributeName *mapped_attrs;
OpRequest o_request;
} rwm_op_state;
static int
-rwm_db_destroy( BackendDB *be );
+rwm_db_destroy( BackendDB *be, ConfigReply *cr );
typedef struct rwm_op_cb {
slap_callback cb;
op->o_req_dn = ros->ro_dn;
op->o_req_ndn = ros->ro_ndn;
- if ( !BER_BVISEMPTY( &ros->r_dn )) ch_free( ros->r_dn.bv_val );
- if ( !BER_BVISEMPTY( &ros->r_ndn )) ch_free( ros->r_ndn.bv_val );
+ if ( !BER_BVISNULL( &ros->r_dn )
+ && ros->r_dn.bv_val != ros->r_ndn.bv_val )
+ {
+ ch_free( ros->r_dn.bv_val );
+ BER_BVZERO( &ros->r_dn );
+ }
+
+ if ( !BER_BVISNULL( &ros->r_ndn ) ) {
+ ch_free( ros->r_ndn.bv_val );
+ BER_BVZERO( &ros->r_ndn );
+ }
switch( ros->r_tag ) {
case LDAP_REQ_COMPARE:
}
break;
case LDAP_REQ_SEARCH:
- ch_free( op->ors_attrs );
+ ch_free( ros->mapped_attrs );
filter_free_x( op, op->ors_filter );
ch_free( op->ors_filterstr.bv_val );
op->ors_attrs = ros->ors_attrs;
* Rewrite the dn if needed
*/
dc.rwmap = rwmap;
-#ifdef ENABLE_REWRITE
dc.conn = op->o_conn;
dc.rs = rs;
dc.ctx = (char *)cookie;
-#else /* ! ENABLE_REWRITE */
- dc.tofrom = ((int *)cookie)[0];
- dc.normalized = 0;
-#endif /* ! ENABLE_REWRITE */
/* NOTE: in those cases where only the ndn is available,
* and the caller sets op->o_req_dn = op->o_req_ndn,
if ( op->o_req_dn.bv_val != op->o_req_ndn.bv_val ) {
op->o_req_dn = dn;
- ros->r_dn = dn;
+ ros->r_dn = dn;
} else {
op->o_req_dn = ndn;
}
- ros->r_ndn = ndn;
op->o_req_ndn = ndn;
+ ros->r_ndn = ndn;
return LDAP_SUCCESS;
}
char *olddn = op->o_req_dn.bv_val;
int isupdate;
- rwm_op_cb *roc = rwm_callback_get( op, rs );
+ rwm_op_cb *roc = rwm_callback_get( op, rs );
-#ifdef ENABLE_REWRITE
rc = rwm_op_dn_massage( op, rs, "addDN", &roc->ros );
-#else /* ! ENABLE_REWRITE */
- rc = 1;
- rc = rwm_op_dn_massage( op, rs, &rc, &roc->ros );
-#endif /* ! ENABLE_REWRITE */
if ( rc != LDAP_SUCCESS ) {
op->o_bd->bd_info = (BackendInfo *)on->on_info;
send_ldap_error( op, rs, rc, "addDN massage error" );
* FIXME: rewrite could fail; in this case
* the operation should give up, right?
*/
-#ifdef ENABLE_REWRITE
rc = rwm_dnattr_rewrite( op, rs, "addAttrDN",
(*ap)->a_vals,
(*ap)->a_nvals ? &(*ap)->a_nvals : NULL );
-#else /* ! ENABLE_REWRITE */
- rc = 1;
- rc = rwm_dnattr_rewrite( op, rs, &rc, (*ap)->a_vals,
- (*ap)->a_nvals ? &(*ap)->a_nvals : NULL );
-#endif /* ! ENABLE_REWRITE */
if ( rc ) {
goto cleanup_attr;
}
} else if ( (*ap)->a_desc == slap_schema.si_ad_ref ) {
-#ifdef ENABLE_REWRITE
rc = rwm_referral_rewrite( op, rs, "referralAttrDN",
(*ap)->a_vals,
(*ap)->a_nvals ? &(*ap)->a_nvals : NULL );
-#else /* ! ENABLE_REWRITE */
- rc = 1;
- rc = rwm_referral_rewrite( op, rs, &rc, (*ap)->a_vals,
- (*ap)->a_nvals ? &(*ap)->a_nvals : NULL );
-#endif /* ! ENABLE_REWRITE */
if ( rc != LDAP_SUCCESS ) {
goto cleanup_attr;
}
return SLAP_CB_CONTINUE;
}
-#ifdef ENABLE_REWRITE
static int
rwm_conn_init( BackendDB *be, Connection *conn )
{
return SLAP_CB_CONTINUE;
}
-#endif /* ENABLE_REWRITE */
static int
rwm_op_bind( Operation *op, SlapReply *rs )
slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
int rc;
- rwm_op_cb *roc = rwm_callback_get( op, rs );
+ rwm_op_cb *roc = rwm_callback_get( op, rs );
-#ifdef ENABLE_REWRITE
rc = rwm_op_dn_massage( op, rs, "bindDN", &roc->ros );
-#else /* ! ENABLE_REWRITE */
- rc = 1;
- rc = rwm_op_dn_massage( op, rs, &rc, &roc->ros );
-#endif /* ! ENABLE_REWRITE */
if ( rc != LDAP_SUCCESS ) {
op->o_bd->bd_info = (BackendInfo *)on->on_info;
send_ldap_error( op, rs, rc, "bindDN massage error" );
struct ldaprwmap *rwmap =
(struct ldaprwmap *)on->on_bi.bi_private;
-#ifdef ENABLE_REWRITE
rewrite_session_delete( rwmap->rwm_rw, op->o_conn );
-#endif /* ENABLE_REWRITE */
return SLAP_CB_CONTINUE;
}
(struct ldaprwmap *)on->on_bi.bi_private;
int rc;
- struct berval mapped_vals[2] = { BER_BVNULL, BER_BVNULL };
+ struct berval mapped_vals[2] = { BER_BVNULL, BER_BVNULL };
- rwm_op_cb *roc = rwm_callback_get( op, rs );
+ rwm_op_cb *roc = rwm_callback_get( op, rs );
-#ifdef ENABLE_REWRITE
rc = rwm_op_dn_massage( op, rs, "compareDN", &roc->ros );
-#else /* ! ENABLE_REWRITE */
- rc = 1;
- rc = rwm_op_dn_massage( op, rs, &rc, &roc->ros );
-#endif /* ! ENABLE_REWRITE */
if ( rc != LDAP_SUCCESS ) {
op->o_bd->bd_info = (BackendInfo *)on->on_info;
send_ldap_error( op, rs, rc, "compareDN massage error" );
mapped_vals[0] = op->orc_ava->aa_value;
-#ifdef ENABLE_REWRITE
rc = rwm_dnattr_rewrite( op, rs, "compareAttrDN", NULL, mapped_valsp );
-#else /* ! ENABLE_REWRITE */
- rc = 1;
- rc = rwm_dnattr_rewrite( op, rs, &rc, NULL, mapped_valsp );
-#endif /* ! ENABLE_REWRITE */
if ( rc != LDAP_SUCCESS ) {
op->o_bd->bd_info = (BackendInfo *)on->on_info;
slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
int rc;
- rwm_op_cb *roc = rwm_callback_get( op, rs );
+ rwm_op_cb *roc = rwm_callback_get( op, rs );
-#ifdef ENABLE_REWRITE
rc = rwm_op_dn_massage( op, rs, "deleteDN", &roc->ros );
-#else /* ! ENABLE_REWRITE */
- rc = 1;
- rc = rwm_op_dn_massage( op, rs, &rc, &roc->ros );
-#endif /* ! ENABLE_REWRITE */
if ( rc != LDAP_SUCCESS ) {
op->o_bd->bd_info = (BackendInfo *)on->on_info;
send_ldap_error( op, rs, rc, "deleteDN massage error" );
Modifications **mlp;
int rc;
- rwm_op_cb *roc = rwm_callback_get( op, rs );
+ rwm_op_cb *roc = rwm_callback_get( op, rs );
-#ifdef ENABLE_REWRITE
rc = rwm_op_dn_massage( op, rs, "modifyDN", &roc->ros );
-#else /* ! ENABLE_REWRITE */
- rc = 1;
- rc = rwm_op_dn_massage( op, rs, &rc, &roc->ros );
-#endif /* ! ENABLE_REWRITE */
if ( rc != LDAP_SUCCESS ) {
op->o_bd->bd_info = (BackendInfo *)on->on_info;
send_ldap_error( op, rs, rc, "modifyDN massage error" );
}
isupdate = be_shadow_update( op );
- for ( mlp = &op->oq_modify.rs_modlist; *mlp; ) {
+ for ( mlp = &op->orm_modlist; *mlp; ) {
int is_oc = 0;
Modifications *ml;
struct ldapmapping *mapping = NULL;
if ( ml->sml_desc->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName
|| ( mapping != NULL && mapping->m_dst_ad->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName ) )
{
-#ifdef ENABLE_REWRITE
rc = rwm_dnattr_rewrite( op, rs, "modifyAttrDN",
ml->sml_values,
ml->sml_nvalues ? &ml->sml_nvalues : NULL );
-#else /* ! ENABLE_REWRITE */
- rc = 1;
- rc = rwm_dnattr_rewrite( op, rs, &rc,
- ml->sml_values,
- ml->sml_nvalues ? &ml->sml_nvalues : NULL );
-#endif /* ! ENABLE_REWRITE */
} else if ( ml->sml_desc == slap_schema.si_ad_ref ) {
-#ifdef ENABLE_REWRITE
rc = rwm_referral_rewrite( op, rs,
"referralAttrDN",
ml->sml_values,
ml->sml_nvalues ? &ml->sml_nvalues : NULL );
-#else /* ! ENABLE_REWRITE */
- rc = 1;
- rc = rwm_referral_rewrite( op, rs, &rc,
- ml->sml_values,
- ml->sml_nvalues ? &ml->sml_nvalues : NULL );
-#endif /* ! ENABLE_REWRITE */
if ( rc != LDAP_SUCCESS ) {
goto cleanup_mod;
}
int rc;
- rwm_op_cb *roc = rwm_callback_get( op, rs );
+ rwm_op_cb *roc = rwm_callback_get( op, rs );
if ( op->orr_newSup ) {
dncookie dc;
* Rewrite the new superior, if defined and required
*/
dc.rwmap = rwmap;
-#ifdef ENABLE_REWRITE
dc.conn = op->o_conn;
dc.rs = rs;
dc.ctx = "newSuperiorDN";
-#else /* ! ENABLE_REWRITE */
- dc.tofrom = 0;
- dc.normalized = 0;
-#endif /* ! ENABLE_REWRITE */
newSup = *op->orr_newSup;
nnewSup = *op->orr_nnewSup;
rc = rwm_dn_massage_pretty_normalize( &dc, op->orr_newSup, &newSup, &nnewSup );
/*
* Rewrite the dn, if needed
*/
-#ifdef ENABLE_REWRITE
rc = rwm_op_dn_massage( op, rs, "renameDN", &roc->ros );
-#else /* ! ENABLE_REWRITE */
- rc = 1;
- rc = rwm_op_dn_massage( op, rs, &rc, &roc->ros );
-#endif /* ! ENABLE_REWRITE */
if ( rc != LDAP_SUCCESS ) {
op->o_bd->bd_info = (BackendInfo *)on->on_info;
send_ldap_error( op, rs, rc, "renameDN massage error" );
rwm_op_state *ros = cb->sc_private;
rs->sr_attrs = ros->ors_attrs;
+
+ /* other overlays might have touched op->ors_attrs,
+ * so we restore the original version here, otherwise
+ * attribute-mapping might fail */
+ op->ors_attrs = ros->mapped_attrs;
return SLAP_CB_CONTINUE;
}
char *text = NULL;
- rwm_op_cb *roc = rwm_callback_get( op, rs );
+ rwm_op_cb *roc = rwm_callback_get( op, rs );
-#ifdef ENABLE_REWRITE
rc = rewrite_session_var_set( rwmap->rwm_rw, op->o_conn,
"searchFilter", op->ors_filterstr.bv_val );
if ( rc == LDAP_SUCCESS )
rc = rwm_op_dn_massage( op, rs, "searchDN", &roc->ros );
-#else /* ! ENABLE_REWRITE */
- rc = 1;
- rc = rwm_op_dn_massage( op, rs, &rc, &roc->ros );
-#endif /* ! ENABLE_REWRITE */
if ( rc != LDAP_SUCCESS ) {
text = "searchDN massage error";
goto error_return;
* Rewrite the dn if needed
*/
dc.rwmap = rwmap;
-#ifdef ENABLE_REWRITE
dc.conn = op->o_conn;
dc.rs = rs;
dc.ctx = "searchFilterAttrDN";
-#else /* ! ENABLE_REWRITE */
- dc.tofrom = 0;
- dc.normalized = 0;
-#endif /* ! ENABLE_REWRITE */
rc = rwm_filter_map_rewrite( op, &dc, op->ors_filter, &fstr );
if ( rc != LDAP_SUCCESS ) {
}
op->ors_attrs = an;
+ /* store the mapped Attributes for later usage, in
+ * the case that other overlays change op->ors_attrs */
+ roc->ros.mapped_attrs = an;
roc->cb.sc_response = rwm_swap_attrs;
op->o_callback = &roc->cb;
roc = rwm_callback_get( op, rs );
-#ifdef ENABLE_REWRITE
rc = rwm_op_dn_massage( op, rs, "extendedDN", &roc->ros );
-#else /* ! ENABLE_REWRITE */
- rc = 1;
- rc = rwm_op_dn_massage( op, rs, &rc, &roc->ros );
-#endif /* ! ENABLE_REWRITE */
if ( rc != LDAP_SUCCESS ) {
op->o_bd->bd_info = (BackendInfo *)on->on_info;
send_ldap_error( op, rs, rc, "extendedDN massage error" );
roc = rwm_callback_get( op, rs );
-#ifdef ENABLE_REWRITE
rc = rwm_op_dn_massage( op, rs, "extendedDN", &roc->ros );
-#else /* ! ENABLE_REWRITE */
- rc = 1;
- rc = rwm_op_dn_massage( op, rs, &rc, &roc->ros );
-#endif /* ! ENABLE_REWRITE */
if ( rc != LDAP_SUCCESS ) {
op->o_bd->bd_info = (BackendInfo *)on->on_info;
send_ldap_error( op, rs, rc, "extendedDN massage error" );
}
dc.rwmap = rwmap;
-#ifdef ENABLE_REWRITE
dc.conn = op->o_conn;
dc.rs = rs;
dc.ctx = "matchedDN";
-#else /* ! ENABLE_REWRITE */
- dc.tofrom = 0;
- dc.normalized = 0;
-#endif /* ! ENABLE_REWRITE */
ber_str2bv( rs->sr_matched, 0, 0, &dn );
mdn = dn;
rc = rwm_dn_massage_pretty( &dc, &dn, &mdn );
int rc;
Attribute **ap;
int isupdate;
+ int check_duplicate_attrs = 0;
/*
* Rewrite the dn attrs, if needed
*/
dc.rwmap = rwmap;
-#ifdef ENABLE_REWRITE
dc.conn = op->o_conn;
dc.rs = NULL;
-#else /* ! ENABLE_REWRITE */
- dc.tofrom = 0;
- dc.normalized = 0;
-#endif /* ! ENABLE_REWRITE */
/* FIXME: the entries are in the remote mapping form;
* so we need to select those attributes we are willing
for ( ap = a_first; *ap; ) {
struct ldapmapping *mapping = NULL;
int drop_missing;
- int last;
+ int last = -1;
Attribute *a;
if ( SLAP_OPATTRS( rs->sr_attr_flags ) && is_at_operational( (*ap)->a_desc->ad_type ) )
{
goto cleanup_attr;
}
-
if ( mapping != NULL ) {
+ assert( mapping->m_dst_ad != NULL );
+
+ /* try to normalize mapped Attributes if the original
+ * AttributeType was not normalized */
+ if ((rwmap->rwm_flags & RWM_F_NORMALIZE_MAPPED_ATTRS) &&
+ (!(*ap)->a_desc->ad_type->sat_equality ||
+ !(*ap)->a_desc->ad_type->sat_equality->smr_normalize) &&
+ mapping->m_dst_ad->ad_type->sat_equality &&
+ mapping->m_dst_ad->ad_type->sat_equality->smr_normalize )
+ {
+ int i = 0;
+ for ( last = 0; !BER_BVISNULL( &(*ap)->a_vals[last] ); last++ )
+ /* just count */ ;
+
+ if ( last )
+ {
+ (*ap)->a_nvals = ch_malloc( (last+1) * sizeof(struct berval) );
+
+ for ( i = 0; !BER_BVISNULL( &(*ap)->a_vals[i]); i++ ) {
+ int rc;
+ /*
+ * check that each value is valid per syntax
+ * and pretty if appropriate
+ */
+ rc = mapping->m_dst_ad->ad_type->sat_equality->smr_normalize(
+ SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
+ mapping->m_dst_ad->ad_type->sat_syntax,
+ mapping->m_dst_ad->ad_type->sat_equality,
+ &(*ap)->a_vals[i], &(*ap)->a_nvals[i],
+ NULL );
+
+ if ( rc != LDAP_SUCCESS ) {
+ BER_BVZERO( &(*ap)->a_nvals[i] );
+ }
+ }
+ BER_BVZERO( &(*ap)->a_nvals[i] );
+ }
+ }
+
+ /* rewrite the attribute description */
(*ap)->a_desc = mapping->m_dst_ad;
+
+ /* will need to check for duplicate attrs */
+ check_duplicate_attrs++;
}
}
goto next_attr;
}
- for ( last = 0; !BER_BVISNULL( &(*ap)->a_vals[last] ); last++ )
- /* just count */ ;
+ if ( last == -1 ) { /* not yet counted */
+ for ( last = 0; !BER_BVISNULL( &(*ap)->a_vals[last] ); last++ )
+ /* just count */ ;
+ }
if ( last == 0 ) {
/* empty? leave it in place because of attrsonly and vlv */
rwm_map( &rwmap->rwm_oc, &bv[0], &mapped, RWM_REMAP );
if ( BER_BVISNULL( &mapped ) || BER_BVISEMPTY( &mapped ) ) {
+remove_oc:;
ch_free( bv[0].bv_val );
BER_BVZERO( &bv[0] );
if ( &(*ap)->a_vals[last] > &bv[0] ) {
bv--;
} else if ( mapped.bv_val != bv[0].bv_val ) {
+ int i;
+
+ for ( i = 0; !BER_BVISNULL( &(*ap)->a_vals[ i ] ); i++ ) {
+ if ( &(*ap)->a_vals[ i ] == bv ) {
+ continue;
+ }
+
+ if ( ber_bvstrcasecmp( &mapped, &(*ap)->a_vals[ i ] ) == 0 ) {
+ break;
+ }
+ }
+
+ if ( !BER_BVISNULL( &(*ap)->a_vals[ i ] ) ) {
+ goto remove_oc;
+ }
+
/*
* FIXME: after LBER_FREEing
* the value is replaced by
* ch_alloc'ed memory
*/
ber_bvreplace( &bv[0], &mapped );
+
+ /* FIXME: will need to check
+ * if the structuralObjectClass
+ * changed */
}
}
} else if ( (*ap)->a_desc->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName
|| ( mapping != NULL && mapping->m_src_ad->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName ) )
{
-#ifdef ENABLE_REWRITE
dc.ctx = "searchAttrDN";
-#endif /* ENABLE_REWRITE */
rc = rwm_dnattr_result_rewrite( &dc, (*ap)->a_vals );
if ( rc != LDAP_SUCCESS ) {
goto cleanup_attr;
}
} else if ( (*ap)->a_desc == slap_schema.si_ad_ref ) {
-#ifdef ENABLE_REWRITE
dc.ctx = "searchAttrDN";
-#endif /* ENABLE_REWRITE */
rc = rwm_referral_result_rewrite( &dc, (*ap)->a_vals );
if ( rc != LDAP_SUCCESS ) {
goto cleanup_attr;
}
}
- if ( mapping != NULL ) {
- /* rewrite the attribute description */
- assert( mapping->m_dst_ad != NULL );
- (*ap)->a_desc = mapping->m_dst_ad;
- }
next_attr:;
ap = &(*ap)->a_next;
attr_free( a );
}
+ /* only check if some mapping occurred */
+ if ( check_duplicate_attrs ) {
+ for ( ap = a_first; *ap != NULL; ap = &(*ap)->a_next ) {
+ Attribute **tap;
+
+ for ( tap = &(*ap)->a_next; *tap != NULL; ) {
+ if ( (*tap)->a_desc == (*ap)->a_desc ) {
+ Entry e = { 0 };
+ Modification mod = { 0 };
+ const char *text = NULL;
+ char textbuf[ SLAP_TEXT_BUFLEN ];
+ Attribute *next = (*tap)->a_next;
+
+ BER_BVSTR( &e.e_name, "" );
+ BER_BVSTR( &e.e_nname, "" );
+ e.e_attrs = *ap;
+ mod.sm_op = LDAP_MOD_ADD;
+ mod.sm_desc = (*ap)->a_desc;
+ mod.sm_type = mod.sm_desc->ad_cname;
+ mod.sm_values = (*tap)->a_vals;
+ mod.sm_nvalues = (*tap)->a_nvals;
+
+ (void)modify_add_values( &e, &mod,
+ /* permissive */ 1,
+ &text, textbuf, sizeof( textbuf ) );
+
+ /* should not insert new attrs! */
+ assert( e.e_attrs == *ap );
+
+ attr_free( *tap );
+ *tap = next;
+
+ } else {
+ tap = &(*tap)->a_next;
+ }
+ }
+ }
+ }
+
return 0;
}
* Rewrite the dn of the result, if needed
*/
dc.rwmap = rwmap;
-#ifdef ENABLE_REWRITE
dc.conn = op->o_conn;
dc.rs = NULL;
dc.ctx = "searchEntryDN";
-#else /* ! ENABLE_REWRITE */
- dc.tofrom = 0;
- dc.normalized = 0;
-#endif /* ! ENABLE_REWRITE */
e = rs->sr_entry;
flags = rs->sr_flags;
slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
int rc;
-#ifdef ENABLE_REWRITE
rc = rwm_op_dn_massage( op, rs, "referralCheckDN" );
-#else /* ! ENABLE_REWRITE */
- rc = 1;
- rc = rwm_op_dn_massage( op, rs, &rc );
-#endif /* ! ENABLE_REWRITE */
if ( rc != LDAP_SUCCESS ) {
op->o_bd->bd_info = (BackendInfo *)on->on_info;
send_ldap_error( op, rs, rc, "referralCheckDN massage error" );
int argc,
char **argv )
{
-#ifdef ENABLE_REWRITE
slap_overinst *on = (slap_overinst *) be->bd_info;
struct ldaprwmap *rwmap =
(struct ldaprwmap *)on->on_bi.bi_private;
return rewrite_parse( rwmap->rwm_rw,
fname, lineno, argc, argv );
-#else /* !ENABLE_REWRITE */
- fprintf( stderr, "%s: line %d: rewrite capabilities "
- "are not enabled\n", fname, lineno );
-#endif /* !ENABLE_REWRITE */
-
return 0;
}
struct berval bvnc, nvnc, pvnc, brnc, nrnc, prnc;
int massaged;
-#ifdef ENABLE_REWRITE
int rc;
-#endif /* ENABLE_REWRITE */
/*
* syntax:
return 1;
}
-#ifdef ENABLE_REWRITE
/*
* The suffix massaging is emulated
* by means of the rewrite capabilities
free( nrnc.bv_val );
free( prnc.bv_val );
- return( rc );
-
-#else /* !ENABLE_REWRITE */
- ber_bvarray_add( &rwmap->rwm_suffix_massage, &pvnc );
- ber_bvarray_add( &rwmap->rwm_suffix_massage, &nvnc );
-
- ber_bvarray_add( &rwmap->rwm_suffix_massage, &prnc );
- ber_bvarray_add( &rwmap->rwm_suffix_massage, &nrnc );
-#endif /* !ENABLE_REWRITE */
-
- return 0;
+ return rc;
}
static int
* Rewrite the dn of the referrals, if needed
*/
dc.rwmap = rwmap;
-#ifdef ENABLE_REWRITE
dc.conn = op->o_conn;
dc.rs = NULL;
dc.ctx = "referralDN";
-#else /* ! ENABLE_REWRITE */
- dc.tofrom = 0;
- dc.normalized = 0;
-#endif /* ! ENABLE_REWRITE */
rc = rwm_referral_result_rewrite( &dc, rs->sr_ref );
if ( rc != LDAP_SUCCESS ) {
rc = 1;
}
if ( strcasecmp( argv[ 1 ], "no" ) == 0 ) {
- rwmap->rwm_flags &= ~(RWM_F_SUPPORT_T_F|RWM_F_SUPPORT_T_F_DISCOVER);
+ rwmap->rwm_flags &= ~(RWM_F_SUPPORT_T_F_MASK2);
} else if ( strcasecmp( argv[ 1 ], "yes" ) == 0 ) {
rwmap->rwm_flags |= RWM_F_SUPPORT_T_F;
fname, lineno, argv[ 1 ] );
return 1;
}
+ } else if ( strcasecmp( argv[0], "normalize-mapped-attrs" ) == 0 ) {
+ if ( argc !=2 ) {
+ fprintf( stderr,
+ "%s: line %d: \"normalize-mapped-attrs {no|yes}\" needs 1 argument.\n",
+ fname, lineno );
+ return( 1 );
+ }
+
+ if ( strcasecmp( argv[ 1 ], "no" ) == 0 ) {
+ rwmap->rwm_flags &= ~(RWM_F_NORMALIZE_MAPPED_ATTRS);
+
+ } else if ( strcasecmp( argv[ 1 ], "yes" ) == 0 ) {
+ rwmap->rwm_flags |= RWM_F_NORMALIZE_MAPPED_ATTRS;
+ }
} else {
rc = SLAP_CONF_UNKNOWN;
return rc;
}
+/*
+ * dynamic configuration...
+ */
+
+enum {
+ /* rewrite */
+ RWM_CF_REWRITE = 1,
+ RWM_CF_SUFFIXMASSAGE,
+
+ /* map */
+ RWM_CF_MAP,
+ RWM_CF_T_F_SUPPORT,
+ RWM_CF_NORMALIZE_MAPPED,
+
+ RWM_CF_LAST
+};
+
+static slap_verbmasks t_f_mode[] = {
+ { BER_BVC( "yes" ), RWM_F_SUPPORT_T_F },
+ { BER_BVC( "discover" ), RWM_F_SUPPORT_T_F_DISCOVER },
+ { BER_BVC( "no" ), RWM_F_NONE },
+ { BER_BVNULL, 0 }
+};
+
+static ConfigDriver rwm_cf_gen;
+
+static ConfigTable rwmcfg[] = {
+ { "rwm-rewrite", "rewrite",
+ 2, 0, STRLENOF("rwm-rewrite"),
+ ARG_MAGIC|ARG_QUOTE|RWM_CF_REWRITE, rwm_cf_gen,
+ "( OLcfgOvAt:16.1 NAME 'olcRwmRewrite' "
+ "DESC 'Rewrites strings' "
+ "EQUALITY caseIgnoreMatch "
+ "SYNTAX OMsDirectoryString "
+ "X-ORDERED 'VALUES' )",
+ NULL, NULL },
+
+ { "rwm-suffixmassage", "[virtual]> <real",
+ 2, 3, 0, ARG_MAGIC|RWM_CF_SUFFIXMASSAGE, rwm_cf_gen,
+ NULL, NULL, NULL },
+
+ { "rwm-t-f-support", "true|false|discover",
+ 2, 2, 0, ARG_MAGIC|RWM_CF_T_F_SUPPORT, rwm_cf_gen,
+ "( OLcfgOvAt:16.2 NAME 'olcRwmTFSupport' "
+ "DESC 'Absolute filters support' "
+ "SYNTAX OMsDirectoryString "
+ "SINGLE-VALUE )",
+ NULL, NULL },
+
+ { "rwm-map", "{objectClass|attribute}",
+ 2, 4, 0, ARG_MAGIC|RWM_CF_MAP, rwm_cf_gen,
+ "( OLcfgOvAt:16.3 NAME 'olcRwmMap' "
+ "DESC 'maps attributes/objectClasses' "
+ "SYNTAX OMsDirectoryString "
+ "X-ORDERED 'VALUES' )",
+ NULL, NULL },
+
+ { "rwm-normalize-mapped-attrs", "true|false",
+ 2, 2, 0, ARG_MAGIC|ARG_ON_OFF|RWM_CF_NORMALIZE_MAPPED, rwm_cf_gen,
+ "( OLcfgOvAt:16.4 NAME 'olcRwmNormalizeMapped' "
+ "DESC 'Normalize mapped attributes/objectClasses' "
+ "SYNTAX OMsBoolean "
+ "SINGLE-VALUE )",
+ NULL, NULL },
+
+ { NULL, NULL, 0, 0, 0, ARG_IGNORED }
+};
+
+static ConfigOCs rwmocs[] = {
+ { "( OLcfgOvOc:16.1 "
+ "NAME 'olcRwmConfig' "
+ "DESC 'Rewrite/remap configuration' "
+ "SUP olcOverlayConfig "
+ "MAY ( "
+ "olcRwmRewrite $ "
+ "olcRwmTFSupport $ "
+ "olcRwmMap $ "
+ "olcRwmNormalizeMapped "
+ ") )",
+ Cft_Overlay, rwmcfg, NULL, NULL },
+ { NULL, 0, NULL }
+};
+
+static void
+slap_rewrite_unparse( BerVarray in, BerVarray *out )
+{
+ int i;
+ BerVarray bva = NULL;
+ char ibuf[32], *ptr;
+ struct berval idx;
+
+ assert( in != NULL );
+
+ for ( i = 0; !BER_BVISNULL( &in[i] ); i++ )
+ /* count'em */ ;
+
+ if ( i == 0 ) {
+ return;
+ }
+
+ idx.bv_val = ibuf;
+
+ bva = ch_malloc( ( i + 1 ) * sizeof(struct berval) );
+ BER_BVZERO( &bva[ 0 ] );
+
+ for ( i = 0; !BER_BVISNULL( &in[i] ); i++ ) {
+ idx.bv_len = snprintf( idx.bv_val, sizeof( ibuf ), "{%d}", i );
+ if ( idx.bv_len >= sizeof( ibuf ) ) {
+ ber_bvarray_free( bva );
+ return;
+ }
+
+ bva[i].bv_len = idx.bv_len + in[i].bv_len;
+ bva[i].bv_val = ch_malloc( bva[i].bv_len + 1 );
+ ptr = lutil_strcopy( bva[i].bv_val, ibuf );
+ ptr = lutil_strcopy( ptr, in[i].bv_val );
+ *ptr = '\0';
+ BER_BVZERO( &bva[ i + 1 ] );
+ }
+
+ *out = bva;
+}
+
+static int
+rwm_cf_gen( ConfigArgs *c )
+{
+ slap_overinst *on = (slap_overinst *)c->bi;
+ struct ldaprwmap *rwmap =
+ (struct ldaprwmap *)on->on_bi.bi_private;
+
+ BackendDB db;
+ char *argv0;
+ int rc = 0;
+
+ db = *c->be;
+ db.bd_info = c->bi;
+
+ if ( c->op == SLAP_CONFIG_EMIT ) {
+ struct berval bv = BER_BVNULL;
+
+ switch ( c->type ) {
+ case RWM_CF_REWRITE:
+ if ( rwmap->rwm_bva_rewrite == NULL ) {
+ rc = 1;
+
+ } else {
+ slap_rewrite_unparse( rwmap->rwm_bva_rewrite, &c->rvalue_vals );
+ if ( !c->rvalue_vals ) {
+ rc = 1;
+ }
+ }
+ break;
+
+ case RWM_CF_T_F_SUPPORT:
+ enum_to_verb( t_f_mode, (rwmap->rwm_flags & RWM_F_SUPPORT_T_F_MASK2), &bv );
+ if ( BER_BVISNULL( &bv ) ) {
+ /* there's something wrong... */
+ assert( 0 );
+ rc = 1;
+
+ } else {
+ value_add_one( &c->rvalue_vals, &bv );
+ }
+ break;
+
+ case RWM_CF_MAP:
+ if ( rwmap->rwm_bva_map == NULL ) {
+ rc = 1;
+
+ } else {
+ value_add( &c->rvalue_vals, rwmap->rwm_bva_map );
+ }
+ break;
+
+ case RWM_CF_NORMALIZE_MAPPED:
+ c->value_int = ( rwmap->rwm_flags & RWM_F_NORMALIZE_MAPPED_ATTRS );
+ break;
+
+ default:
+ assert( 0 );
+ rc = 1;
+ }
+
+ return rc;
+
+ } else if ( c->op == LDAP_MOD_DELETE ) {
+ switch ( c->type ) {
+ case RWM_CF_REWRITE:
+ if ( c->valx >= 0 ) {
+ /* single modification is not allowed */
+ rc = 1;
+
+ } else if ( rwmap->rwm_rw != NULL ) {
+ rewrite_info_delete( &rwmap->rwm_rw );
+ assert( rwmap->rwm_rw == NULL );
+
+ ber_bvarray_free( rwmap->rwm_bva_rewrite );
+ rwmap->rwm_bva_rewrite = NULL;
+ }
+ break;
+
+ case RWM_CF_T_F_SUPPORT:
+ rwmap->rwm_flags &= ~RWM_F_SUPPORT_T_F_MASK2;
+ break;
+
+ case RWM_CF_MAP:
+ if ( c->valx >= 0 ) {
+ /* single modification is not allowed */
+ rc = 1;
+
+ } else {
+ avl_free( rwmap->rwm_oc.remap, rwm_mapping_dst_free );
+ avl_free( rwmap->rwm_oc.map, rwm_mapping_free );
+ avl_free( rwmap->rwm_at.remap, rwm_mapping_dst_free );
+ avl_free( rwmap->rwm_at.map, rwm_mapping_free );
+
+ rwmap->rwm_oc.remap = NULL;
+ rwmap->rwm_oc.map = NULL;
+ rwmap->rwm_at.remap = NULL;
+ rwmap->rwm_at.map = NULL;
+
+ ber_bvarray_free( rwmap->rwm_bva_map );
+ rwmap->rwm_bva_map = NULL;
+ }
+ break;
+
+ case RWM_CF_NORMALIZE_MAPPED:
+ rwmap->rwm_flags &= ~RWM_F_NORMALIZE_MAPPED_ATTRS;
+ break;
+
+ default:
+ return 1;
+ }
+ return rc;
+ }
+
+ switch ( c->type ) {
+ case RWM_CF_REWRITE:
+ argv0 = c->argv[ 0 ];
+ c->argv[ 0 ] += STRLENOF( "rwm-" );
+ rc = rwm_rw_config( &db, c->fname, c->lineno, c->argc, c->argv );
+ c->argv[ 0 ] = argv0;
+ if ( rc ) {
+ return 1;
+
+ } else {
+ char *line;
+ struct berval bv;
+
+ line = ldap_charray2str( c->argv, "\" \"" );
+ if ( line != NULL ) {
+ int len = strlen( c->argv[ 0 ] );
+
+ ber_str2bv( line, 0, 0, &bv );
+ AC_MEMCPY( &bv.bv_val[ len ], &bv.bv_val[ len + 1 ],
+ bv.bv_len - ( len + 1 ) );
+ bv.bv_val[ bv.bv_len - 1 ] = '"';
+ ber_bvarray_add( &rwmap->rwm_bva_rewrite, &bv );
+ }
+ }
+ break;
+
+ case RWM_CF_SUFFIXMASSAGE:
+ argv0 = c->argv[ 0 ];
+ c->argv[ 0 ] += STRLENOF( "rwm-" );
+ rc = rwm_suffixmassage_config( &db, c->fname, c->lineno, c->argc, c->argv );
+ c->argv[ 0 ] = argv0;
+ if ( rc ) {
+ return 1;
+
+ } else {
+ char *line;
+ struct berval bv;
+
+ /* FIXME: not optimal; in fact, this keeps track
+ * of the fact that a set of rules was added
+ * using the rwm-suffixmassage shortcut, but the
+ * rules are not clarified */
+
+ line = ldap_charray2str( c->argv, "\" \"" );
+ if ( line != NULL ) {
+ int len = strlen( c->argv[ 0 ] );
+
+ ber_str2bv( line, 0, 0, &bv );
+ AC_MEMCPY( &bv.bv_val[ len ], &bv.bv_val[ len + 1 ],
+ bv.bv_len - ( len + 1 ) );
+ bv.bv_val[ bv.bv_len - 1 ] = '"';
+ ber_bvarray_add( &rwmap->rwm_bva_rewrite, &bv );
+ }
+ }
+ break;
+
+ case RWM_CF_T_F_SUPPORT:
+ rc = verb_to_mask( c->argv[ 1 ], t_f_mode );
+ if ( BER_BVISNULL( &t_f_mode[ rc ].word ) ) {
+ return 1;
+ }
+
+ rwmap->rwm_flags &= ~RWM_F_SUPPORT_T_F_MASK2;
+ rwmap->rwm_flags |= t_f_mode[ rc ].mask;
+ rc = 0;
+ break;
+
+ case RWM_CF_MAP:
+ argv0 = c->argv[ 0 ];
+ c->argv[ 0 ] += STRLENOF( "rwm-" );
+ rc = rwm_m_config( &db, c->fname, c->lineno, c->argc, c->argv );
+ c->argv[ 0 ] = argv0;
+ if ( rc ) {
+ return 1;
+
+ } else {
+ char *line;
+ struct berval bv;
+
+ line = ldap_charray2str( &c->argv[ 1 ], " " );
+ if ( line != NULL ) {
+ ber_str2bv( line, 0, 0, &bv );
+ ber_bvarray_add( &rwmap->rwm_bva_map, &bv );
+ }
+ }
+ break;
+
+ case RWM_CF_NORMALIZE_MAPPED:
+ if ( c->value_int ) {
+ rwmap->rwm_flags |= RWM_F_NORMALIZE_MAPPED_ATTRS;
+ } else {
+ rwmap->rwm_flags &= ~RWM_F_NORMALIZE_MAPPED_ATTRS;
+ }
+ break;
+
+ default:
+ assert( 0 );
+ return 1;
+ }
+
+ return rc;
+}
+
static int
rwm_db_init(
- BackendDB *be )
+ BackendDB *be,
+ ConfigReply *cr )
{
slap_overinst *on = (slap_overinst *) be->bd_info;
struct ldaprwmap *rwmap;
-#ifdef ENABLE_REWRITE
char *rargv[ 3 ];
-#endif /* ENABLE_REWRITE */
int rc = 0;
rwmap = (struct ldaprwmap *)ch_calloc( 1, sizeof( struct ldaprwmap ) );
-#ifdef ENABLE_REWRITE
rwmap->rwm_rw = rewrite_info_init( REWRITE_MODE_USE_DEFAULT );
if ( rwmap->rwm_rw == NULL ) {
rc = -1;
rargv[ 1 ] = "default";
rargv[ 2 ] = NULL;
rewrite_parse( rwmap->rwm_rw, "<suffix massage>", 2, 2, rargv );
-#endif /* ENABLE_REWRITE */
error_return:;
on->on_bi.bi_private = (void *)rwmap;
if ( rc ) {
- (void)rwm_db_destroy( be );
+ (void)rwm_db_destroy( be, NULL );
}
return rc;
static int
rwm_db_destroy(
- BackendDB *be )
+ BackendDB *be,
+ ConfigReply *cr )
{
slap_overinst *on = (slap_overinst *) be->bd_info;
int rc = 0;
struct ldaprwmap *rwmap =
(struct ldaprwmap *)on->on_bi.bi_private;
-#ifdef ENABLE_REWRITE
if ( rwmap->rwm_rw ) {
rewrite_info_delete( &rwmap->rwm_rw );
+ ber_bvarray_free( rwmap->rwm_bva_rewrite );
}
-#else /* !ENABLE_REWRITE */
- if ( rwmap->rwm_suffix_massage ) {
- ber_bvarray_free( rwmap->rwm_suffix_massage );
- }
-#endif /* !ENABLE_REWRITE */
avl_free( rwmap->rwm_oc.remap, rwm_mapping_dst_free );
avl_free( rwmap->rwm_oc.map, rwm_mapping_free );
avl_free( rwmap->rwm_at.remap, rwm_mapping_dst_free );
avl_free( rwmap->rwm_at.map, rwm_mapping_free );
+ ber_bvarray_free( rwmap->rwm_bva_map );
ch_free( rwmap );
}
int
rwm_initialize( void )
{
+ int rc;
+
+ /* Make sure we don't exceed the bits reserved for userland */
+ config_check_userland( RWM_CF_LAST );
+
memset( &rwm, 0, sizeof( slap_overinst ) );
rwm.on_bi.bi_type = "rwm";
rwm.on_bi.bi_operational = rwm_operational;
rwm.on_bi.bi_chk_referrals = 0 /* rwm_chk_referrals */ ;
-#ifdef ENABLE_REWRITE
rwm.on_bi.bi_connection_init = rwm_conn_init;
rwm.on_bi.bi_connection_destroy = rwm_conn_destroy;
-#endif /* ENABLE_REWRITE */
rwm.on_response = rwm_response;
+ rwm.on_bi.bi_cf_ocs = rwmocs;
+
+ rc = config_register_schema( rwmcfg, rwmocs );
+ if ( rc ) {
+ return rc;
+ }
+
return overlay_register( &rwm );
}
#ifndef RWM_H
#define RWM_H
+#ifndef ENABLE_REWRITE
+#error "librewrite must be enabled!"
+#endif /* ENABLE_REWRITE */
+
/* String rewrite library */
-#ifdef ENABLE_REWRITE
#include "rewrite.h"
-#endif /* ENABLE_REWRITE */
LDAP_BEGIN_DECL
/*
* DN rewriting
*/
-#ifdef ENABLE_REWRITE
struct rewrite_info *rwm_rw;
-#else /* !ENABLE_REWRITE */
- /* some time the suffix massaging without librewrite
- * will be disabled */
- BerVarray rwm_suffix_massage;
-#endif /* !ENABLE_REWRITE */
+ BerVarray rwm_bva_rewrite;
/*
* Attribute/objectClass mapping
*/
struct ldapmap rwm_oc;
struct ldapmap rwm_at;
-
-#define RWM_F_NONE 0x0000U
-#define RWM_F_SUPPORT_T_F 0x4000U
-#define RWM_F_SUPPORT_T_F_DISCOVER 0x8000U
+ BerVarray rwm_bva_map;
+
+#define RWM_F_NONE (0x0000U)
+#define RWM_F_NORMALIZE_MAPPED_ATTRS (0x0001U)
+#define RWM_F_SUPPORT_T_F (0x4000U)
+#define RWM_F_SUPPORT_T_F_DISCOVER (0x8000U)
+#define RWM_F_SUPPORT_T_F_MASK (RWM_F_SUPPORT_T_F)
+#define RWM_F_SUPPORT_T_F_MASK2 (RWM_F_SUPPORT_T_F|RWM_F_SUPPORT_T_F_DISCOVER)
unsigned rwm_flags;
};
typedef struct dncookie {
struct ldaprwmap *rwmap;
-#ifdef ENABLE_REWRITE
Connection *conn;
char *ctx;
SlapReply *rs;
-#else /* !ENABLE_REWRITE */
- int normalized;
- int tofrom;
-#endif /* !ENABLE_REWRITE */
} dncookie;
int rwm_dn_massage( dncookie *dc, struct berval *in, struct berval *dn );
struct berval *fstr );
/* suffix massaging by means of librewrite */
-#ifdef ENABLE_REWRITE
-extern int rwm_suffix_massage_config( struct rewrite_info *info,
- struct berval *pvnc, struct berval *nvnc,
- struct berval *prnc, struct berval *nrnc);
-#endif /* ENABLE_REWRITE */
-extern int rwm_dnattr_rewrite(
+extern int
+rwm_suffix_massage_config(
+ struct rewrite_info *info,
+ struct berval *pvnc,
+ struct berval *nvnc,
+ struct berval *prnc,
+ struct berval *nrnc);
+extern int
+rwm_dnattr_rewrite(
Operation *op,
SlapReply *rs,
void *cookie,
BerVarray a_vals,
BerVarray *pa_nvals );
-extern int rwm_referral_rewrite(
+extern int
+rwm_referral_rewrite(
Operation *op,
SlapReply *rs,
void *cookie,
fname, lineno, dst );
goto error_return;
}
-
-#if 0
- mapping[0].m_dst_oc = ch_malloc( sizeof( ObjectClass ) );
- memset( mapping[0].m_dst_oc, 0, sizeof( ObjectClass ) );
- mapping[0].m_dst_oc->soc_cname = mapping[0].m_dst;
- mapping[0].m_flags |= RWMMAP_F_FREE_DST;
-#endif
}
mapping[1].m_src_oc = mapping[0].m_dst_oc;
return 1;
}
-#ifdef ENABLE_REWRITE
static char *
rwm_suffix_massage_regexize( const char *s )
{
return 0;
}
-#endif /* ENABLE_REWRITE */
#endif /* SLAPD_OVER_RWM */
return rc;
}
-#ifdef ENABLE_REWRITE
/*
* massages "in" into "dn"
*
return rc;
}
-#else /* ! ENABLE_REWRITE */
-/*
- * rwm_dn_massage
- *
- * Aliases the suffix; based on suffix_alias (servers/slapd/suffixalias.c).
- */
-int
-rwm_dn_massage(
- dncookie *dc,
- struct berval *in,
- struct berval *dn
-)
-{
- int i, src, dst;
- struct berval tmpin;
-
- assert( dc != NULL );
- assert( in != NULL );
- assert( dn != NULL );
-
- BER_BVZERO( dn );
-
- if ( BER_BVISNULL( in ) ) {
- return LDAP_SUCCESS;
- }
-
- if ( dc->rwmap == NULL || dc->rwmap->rwm_suffix_massage == NULL ) {
- *dn = *in;
- return LDAP_SUCCESS;
- }
-
- if ( dc->tofrom ) {
- src = 0 + dc->normalized;
- dst = 2 + dc->normalized;
-
- tmpin = *in;
-
- } else {
- int rc;
-
- src = 2 + dc->normalized;
- dst = 0 + dc->normalized;
-
- /* DN from remote server may be in arbitrary form.
- * Pretty it so we can parse reliably.
- */
- if ( dc->normalized ) {
- rc = dnNormalize( 0, NULL, NULL, in, &tmpin, NULL );
-
- } else {
- rc = dnPretty( NULL, in, &tmpin, NULL );
- }
-
- if ( rc != LDAP_SUCCESS ) {
- return rc;
- }
- }
-
- for ( i = 0;
- !BER_BVISNULL( &dc->rwmap->rwm_suffix_massage[i] );
- i += 4 )
- {
- int aliasLength = dc->rwmap->rwm_suffix_massage[i+src].bv_len;
- int diff = tmpin.bv_len - aliasLength;
-
- if ( diff < 0 ) {
- /* alias is longer than dn */
- continue;
-
- } else if ( diff > 0 && ( !DN_SEPARATOR(tmpin.bv_val[diff-1])))
- {
- /* FIXME: DN_SEPARATOR() is intended to work
- * on a normalized/pretty DN, so that ';'
- * is never used as a DN separator */
- continue;
- /* At a DN Separator */
- }
-
- if ( !strcmp( dc->rwmap->rwm_suffix_massage[i+src].bv_val,
- &tmpin.bv_val[diff] ) )
- {
- dn->bv_len = diff + dc->rwmap->rwm_suffix_massage[i+dst].bv_len;
- dn->bv_val = ch_malloc( dn->bv_len + 1 );
- strncpy( dn->bv_val, tmpin.bv_val, diff );
- strcpy( &dn->bv_val[diff], dc->rwmap->rwm_suffix_massage[i+dst].bv_val );
- Debug( LDAP_DEBUG_ARGS,
- "rwm_dn_massage:"
- " converted \"%s\" to \"%s\"\n",
- in->bv_val, dn->bv_val, 0 );
-
- break;
- }
- }
-
- if ( tmpin.bv_val != in->bv_val ) {
- ch_free( tmpin.bv_val );
- }
-
- /* Nothing matched, just return the original DN */
- if ( BER_BVISNULL( dn ) ) {
- *dn = *in;
- }
-
- return LDAP_SUCCESS;
-}
-#endif /* ! ENABLE_REWRITE */
-
#endif /* SLAPD_OVER_RWM */
dncookie fdc = *dc;
int rc;
-#ifdef ENABLE_REWRITE
fdc.ctx = "searchFilterAttrDN";
-#endif /* ENABLE_REWRITE */
vtmp = *value;
rc = rwm_dn_massage_normalize( &fdc, value, &vtmp );
fstr->bv_val = ch_malloc( fstr->bv_len + 1 );
snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s=%s)",
- atmp.bv_val, vtmp.bv_val );
+ atmp.bv_val, vtmp.bv_len ? vtmp.bv_val : "" );
ch_free( vtmp.bv_val );
break;
fstr->bv_val = ch_malloc( fstr->bv_len + 1 );
snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s>=%s)",
- atmp.bv_val, vtmp.bv_val );
+ atmp.bv_val, vtmp.bv_len ? vtmp.bv_val : "" );
ch_free( vtmp.bv_val );
break;
fstr->bv_val = ch_malloc( fstr->bv_len + 1 );
snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s<=%s)",
- atmp.bv_val, vtmp.bv_val );
+ atmp.bv_val, vtmp.bv_len ? vtmp.bv_val : "" );
ch_free( vtmp.bv_val );
break;
fstr->bv_val = ch_malloc( fstr->bv_len + 1 );
snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s~=%s)",
- atmp.bv_val, vtmp.bv_val );
+ atmp.bv_val, vtmp.bv_len ? vtmp.bv_val : "" );
ch_free( vtmp.bv_val );
break;
snprintf( &fstr->bv_val[len - 2], vtmp.bv_len + 3,
/* "(attr=" */ "%s*)",
- vtmp.bv_val );
+ vtmp.bv_len ? vtmp.bv_val : "" );
ch_free( vtmp.bv_val );
}
snprintf( &fstr->bv_val[len - 1], vtmp.bv_len + 3,
/* "(attr=[init]*[any*]" */ "%s*)",
- vtmp.bv_val );
+ vtmp.bv_len ? vtmp.bv_val : "" );
ch_free( vtmp.bv_val );
}
}
snprintf( &fstr->bv_val[len - 1], vtmp.bv_len + 3,
/* "(attr=[init*][any*]" */ "%s)",
- vtmp.bv_val );
+ vtmp.bv_len ? vtmp.bv_val : "" );
ch_free( vtmp.bv_val );
}
fstr->bv_val = ch_realloc( fstr->bv_val, fstr->bv_len + 1 );
snprintf( &fstr->bv_val[len-1], vtmp.bv_len + 2,
- /*"("*/ "%s)", vtmp.bv_val );
+ /*"("*/ "%s)", vtmp.bv_len ? vtmp.bv_val : "" );
ch_free( vtmp.bv_val );
}
f->f_mr_dnattrs ? ":dn" : "",
!BER_BVISEMPTY( &f->f_mr_rule_text ) ? ":" : "",
!BER_BVISEMPTY( &f->f_mr_rule_text ) ? f->f_mr_rule_text.bv_val : "",
- vtmp.bv_val );
+ vtmp.bv_len ? vtmp.bv_val : "" );
ch_free( vtmp.bv_val );
break;
}
rc = rwm_int_filter_map_rewrite( op, dc, f, fstr );
-#ifdef ENABLE_REWRITE
if ( rc != 0 ) {
return rc;
}
case REWRITE_REGEXEC_OK:
if ( !BER_BVISNULL( fstr ) ) {
fstr->bv_len = strlen( fstr->bv_val );
- ch_free( ftmp.bv_val );
+ if ( fstr->bv_val != ftmp.bv_val ) {
+ ch_free( ftmp.bv_val );
+ }
} else {
*fstr = ftmp;
rc = LDAP_OTHER;
break;
}
-#endif /* ENABLE_REWRITE */
return rc;
}
* Rewrite the dn if needed
*/
dc.rwmap = rwmap;
-#ifdef ENABLE_REWRITE
dc.conn = op->o_conn;
dc.rs = rs;
dc.ctx = (char *)cookie;
-#else /* ! ENABLE_REWRITE */
- dc.tofrom = ((int *)cookie)[0];
- dc.normalized = 0;
-#endif /* ! ENABLE_REWRITE */
for ( last = 0; !BER_BVISNULL( &a_vals[last] ); last++ )
;
* Rewrite the dn if needed
*/
dc.rwmap = rwmap;
-#ifdef ENABLE_REWRITE
dc.conn = op->o_conn;
dc.rs = rs;
dc.ctx = (char *)cookie;
-#else /* ! ENABLE_REWRITE */
- dc.tofrom = ((int *)cookie)[0];
- dc.normalized = 0;
-#endif /* ! ENABLE_REWRITE */
for ( last = 0; !BER_BVISNULL( &in[last] ); last++ );
last--;
#ifdef SLAPD_OVER_SEQMOD
#include "slap.h"
+#include "config.h"
/* This overlay serializes concurrent attempts to modify a single entry */
static int
seqmod_db_open(
- BackendDB *be
+ BackendDB *be,
+ ConfigReply *cr
)
{
slap_overinst *on = (slap_overinst *)be->bd_info;
static int
seqmod_db_close(
- BackendDB *be
+ BackendDB *be,
+ ConfigReply *cr
)
{
slap_overinst *on = (slap_overinst *)be->bd_info;
} else {
cf.f_choice = LDAP_FILTER_LE;
fop.ors_limit = &fc_limits;
+ memset( &fc_limits, 0, sizeof( fc_limits ));
fc_limits.lms_s_unchecked = 1;
fop.ors_filterstr.bv_len = sprintf( buf, "(entryCSN<=%s)",
cf.f_av_value.bv_val );
BackendDB be;
int rc;
- op = (Operation *) &opbuf;
+ op = &opbuf.ob_op;
*op = *so->s_op;
- op->o_hdr = (Opheader *)(op+1);
- op->o_controls = (void **)(op->o_hdr+1);
- memset( op->o_controls, 0, SLAP_MAX_CIDS * sizeof(void *));
+ op->o_hdr = &opbuf.ob_hdr;
+ op->o_controls = opbuf.ob_controls;
+ memset( op->o_controls, 0, sizeof(opbuf.ob_controls) );
*op->o_hdr = *so->s_op->o_hdr;
ldap_pvt_thread_mutex_lock( &so->s_op->o_conn->c_mutex );
so->s_op->o_conn->c_n_ops_executing--;
so->s_op->o_conn->c_n_ops_completed++;
- LDAP_STAILQ_REMOVE( &so->s_op->o_conn->c_ops, so->s_op, slap_op,
+ LDAP_STAILQ_REMOVE( &so->s_op->o_conn->c_ops, so->s_op, Operation,
o_next );
if ( lock )
ldap_pvt_thread_mutex_unlock( &so->s_op->o_conn->c_mutex );
static void
syncprov_checkpoint( Operation *op, SlapReply *rs, slap_overinst *on )
{
- syncprov_info_t *si = (syncprov_info_t *)on->on_bi.bi_private;
+ syncprov_info_t *si = (syncprov_info_t *)on->on_bi.bi_private;
Modifications mod;
Operation opm;
SlapReply rsm = { 0 };
opm.o_req_ndn = op->o_bd->be_nsuffix[0];
opm.o_bd->bd_info = on->on_info->oi_orig;
opm.o_managedsait = SLAP_CONTROL_NONCRITICAL;
+ opm.o_no_schema_check = 1;
opm.o_bd->be_modify( &opm, &rsm );
if ( mod.sml_next != NULL ) {
slap_mods_free( mod.sml_next, 1 );
}
+ opm.orm_no_opattrs = 0;
}
static void
return 0;
}
+typedef struct SyncOperationBuffer {
+ Operation sob_op;
+ Opheader sob_hdr;
+ AttributeName sob_extra; /* not always present */
+ /* Further data allocated here */
+} SyncOperationBuffer;
+
static void
syncprov_detach_op( Operation *op, syncops *so, slap_overinst *on )
{
+ SyncOperationBuffer *sopbuf2;
Operation *op2;
int i, alen = 0;
size_t size;
alen += op->ors_attrs[i].an_name.bv_len + 1;
}
/* Make a new copy of the operation */
- size = sizeof(Operation) + sizeof(Opheader) +
+ size = offsetof( SyncOperationBuffer, sob_extra ) +
(i ? ( (i+1) * sizeof(AttributeName) + alen) : 0) +
op->o_req_dn.bv_len + 1 +
op->o_req_ndn.bv_len + 1 +
op->o_ndn.bv_len + 1 +
so->s_filterstr.bv_len + 1;
- op2 = (Operation *)ch_calloc( 1, size );
- op2->o_hdr = (Opheader *)(op2+1);
+ sopbuf2 = ch_calloc( 1, size );
+ op2 = &sopbuf2->sob_op;
+ op2->o_hdr = &sopbuf2->sob_hdr;
/* Copy the fields we care about explicitly, leave the rest alone */
*op2->o_hdr = *op->o_hdr;
op2->o_request = op->o_request;
op2->o_private = on;
+ ptr = (char *) sopbuf2 + offsetof( SyncOperationBuffer, sob_extra );
if ( i ) {
- op2->ors_attrs = (AttributeName *)(op2->o_hdr + 1);
- ptr = (char *)(op2->ors_attrs+i+1);
+ op2->ors_attrs = (AttributeName *) ptr;
+ ptr = (char *) &op2->ors_attrs[i+1];
for (i=0; !BER_BVISNULL( &op->ors_attrs[i].an_name ); i++) {
op2->ors_attrs[i] = op->ors_attrs[i];
op2->ors_attrs[i].an_name.bv_val = ptr;
ptr = lutil_strcopy( ptr, op->ors_attrs[i].an_name.bv_val ) + 1;
}
BER_BVZERO( &op2->ors_attrs[i].an_name );
- } else {
- ptr = (char *)(op2->o_hdr + 1);
}
+
op2->o_authz = op->o_authz;
op2->o_ndn.bv_val = ptr;
ptr = lutil_strcopy(ptr, op->o_ndn.bv_val) + 1;
a = attr_find( rs->sr_entry->e_attrs,
slap_schema.si_ad_contextCSN );
}
- free( a->a_vals );
+ if ( a->a_nvals != a->a_vals ) {
+ ber_bvarray_free( a->a_nvals );
+ }
+ a->a_nvals = NULL;
+ ber_bvarray_free( a->a_vals );
+ a->a_vals = NULL;
}
ber_bvarray_dup_x( &a->a_vals, si->si_ctxcsn, NULL );
- a->a_nvals = a->a_vals;
+ ber_bvarray_dup_x( &a->a_nvals, si->si_ctxcsn, NULL );
}
ldap_pvt_thread_rdwr_runlock( &si->si_csn_rwlock );
}
case SP_CHKPT:
if ( si->si_chkops || si->si_chktime ) {
struct berval bv;
- bv.bv_len = sprintf( c->msg, "%d %d",
+ bv.bv_len = sprintf( c->cr_msg, "%d %d",
si->si_chkops, si->si_chktime );
- bv.bv_val = c->msg;
+ bv.bv_val = c->cr_msg;
value_add_one( &c->rvalue_vals, &bv );
} else {
rc = 1;
switch ( c->type ) {
case SP_CHKPT:
if ( lutil_atoi( &si->si_chkops, c->argv[1] ) != 0 ) {
- snprintf( c->msg, sizeof( c->msg ), "%s unable to parse checkpoint ops # \"%s\"",
+ snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s unable to parse checkpoint ops # \"%s\"",
c->argv[0], c->argv[1] );
Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
- "%s: %s\n", c->log, c->msg, 0 );
+ "%s: %s\n", c->log, c->cr_msg, 0 );
return ARG_BAD_CONF;
}
if ( si->si_chkops <= 0 ) {
- snprintf( c->msg, sizeof( c->msg ), "%s invalid checkpoint ops # \"%d\"",
+ snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s invalid checkpoint ops # \"%d\"",
c->argv[0], si->si_chkops );
Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
- "%s: %s\n", c->log, c->msg, 0 );
+ "%s: %s\n", c->log, c->cr_msg, 0 );
return ARG_BAD_CONF;
}
if ( lutil_atoi( &si->si_chktime, c->argv[2] ) != 0 ) {
- snprintf( c->msg, sizeof( c->msg ), "%s unable to parse checkpoint time \"%s\"",
+ snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s unable to parse checkpoint time \"%s\"",
c->argv[0], c->argv[1] );
Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
- "%s: %s\n", c->log, c->msg, 0 );
+ "%s: %s\n", c->log, c->cr_msg, 0 );
return ARG_BAD_CONF;
}
if ( si->si_chktime <= 0 ) {
- snprintf( c->msg, sizeof( c->msg ), "%s invalid checkpoint time \"%d\"",
+ snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s invalid checkpoint time \"%d\"",
c->argv[0], si->si_chkops );
Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
- "%s: %s\n", c->log, c->msg, 0 );
+ "%s: %s\n", c->log, c->cr_msg, 0 );
return ARG_BAD_CONF;
}
si->si_chktime *= 60;
int size = c->value_int;
if ( size < 0 ) {
- snprintf( c->msg, sizeof( c->msg ), "%s size %d is negative",
+ snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s size %d is negative",
c->argv[0], size );
Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
- "%s: %s\n", c->log, c->msg, 0 );
+ "%s: %s\n", c->log, c->cr_msg, 0 );
return ARG_BAD_CONF;
}
sl = si->si_logs;
*/
static int
syncprov_db_open(
- BackendDB *be
+ BackendDB *be,
+ ConfigReply *cr
)
{
slap_overinst *on = (slap_overinst *) be->bd_info;
syncprov_info_t *si = (syncprov_info_t *)on->on_bi.bi_private;
Connection conn = { 0 };
- OperationBuffer opbuf = { 0 };
- Operation *op = (Operation *) &opbuf;
+ OperationBuffer opbuf;
+ Operation *op;
Entry *e = NULL;
Attribute *a;
int rc;
}
thrctx = ldap_pvt_thread_pool_context();
- connection_fake_init( &conn, op, thrctx );
+ connection_fake_init( &conn, &opbuf, thrctx );
+ op = &opbuf.ob_op;
op->o_bd = be;
op->o_dn = be->be_rootdn;
op->o_ndn = be->be_rootndn;
*/
static int
syncprov_db_close(
- BackendDB *be
+ BackendDB *be,
+ ConfigReply *cr
)
{
slap_overinst *on = (slap_overinst *) be->bd_info;
return 0;
}
if ( si->si_numops ) {
- Connection conn;
+ Connection conn = {0};
OperationBuffer opbuf;
- Operation *op = (Operation *) &opbuf;
+ Operation *op;
SlapReply rs = {REP_RESULT};
void *thrctx;
thrctx = ldap_pvt_thread_pool_context();
- connection_fake_init( &conn, op, thrctx );
+ connection_fake_init( &conn, &opbuf, thrctx );
+ op = &opbuf.ob_op;
op->o_bd = be;
op->o_dn = be->be_rootdn;
op->o_ndn = be->be_rootndn;
static int
syncprov_db_init(
- BackendDB *be
+ BackendDB *be,
+ ConfigReply *cr
)
{
slap_overinst *on = (slap_overinst *)be->bd_info;
static int
syncprov_db_destroy(
- BackendDB *be
+ BackendDB *be,
+ ConfigReply *cr
)
{
slap_overinst *on = (slap_overinst *)be->bd_info;
return LDAP_PROTOCOL_ERROR;
}
+ if ( BER_BVISNULL( &ctrl->ldctl_value ) ) {
+ rs->sr_text = "Sync control value is absent";
+ return LDAP_PROTOCOL_ERROR;
+ }
+
if ( BER_BVISEMPTY( &ctrl->ldctl_value ) ) {
- rs->sr_text = "Sync control value is empty (or absent)";
+ rs->sr_text = "Sync control value is empty";
return LDAP_PROTOCOL_ERROR;
}
sr->sr_rhint = rhint;
if (!BER_BVISNULL(&cookie)) {
ber_dupbv_x( &sr->sr_state.octet_str, &cookie, op->o_tmpmemctx );
- slap_parse_sync_cookie( &sr->sr_state, op->o_tmpmemctx );
- if ( sr->sr_state.rid == -1 ) {
+ if ( slap_parse_sync_cookie( &sr->sr_state, op->o_tmpmemctx ) ||
+ sr->sr_state.rid == -1 ) {
rs->sr_text = "Sync control : cookie parsing error";
return LDAP_PROTOCOL_ERROR;
}
Debug(LDAP_DEBUG_TRACE, "==> translucent_cfadd\n", 0, 0, 0);
/* FIXME: should not hardcode "olcDatabase" here */
- bv.bv_len = sprintf( ca->msg, "olcDatabase=%s",
+ bv.bv_len = sprintf( ca->cr_msg, "olcDatabase=%s",
ov->db.bd_info->bi_type );
- bv.bv_val = ca->msg;
+ bv.bv_val = ca->cr_msg;
ca->be = &ov->db;
/* We can only create this entry if the database is table-driven
**
*/
-static int translucent_db_init(BackendDB *be) {
+static int translucent_db_init(BackendDB *be, ConfigReply *cr) {
slap_overinst *on = (slap_overinst *) be->bd_info;
translucent_info *ov;
ov->db.be_private = NULL;
ov->db.be_pcl_mutexp = &ov->db.be_pcl_mutex;
- if ( !backend_db_init( "ldap", &ov->db, -1 )) {
+ if ( !backend_db_init( "ldap", &ov->db, -1, NULL )) {
Debug( LDAP_DEBUG_CONFIG, "translucent: unable to open captive back-ldap\n", 0, 0, 0);
return 1;
}
**
*/
-static int translucent_db_open(BackendDB *be) {
+static int translucent_db_open(BackendDB *be, ConfigReply *cr) {
slap_overinst *on = (slap_overinst *) be->bd_info;
translucent_info *ov = on->on_bi.bi_private;
int rc;
ov->db.be_acl = be->be_acl;
ov->db.be_dfltaccess = be->be_dfltaccess;
- rc = backend_startup_one( &ov->db );
+ rc = backend_startup_one( &ov->db, NULL );
if(rc) Debug(LDAP_DEBUG_TRACE,
"translucent: bi_db_open() returned error %d\n", rc, 0, 0);
*/
static int
-translucent_db_close( BackendDB *be )
+translucent_db_close( BackendDB *be, ConfigReply *cr )
{
slap_overinst *on = (slap_overinst *) be->bd_info;
translucent_info *ov = on->on_bi.bi_private;
Debug(LDAP_DEBUG_TRACE, "==> translucent_db_close\n", 0, 0, 0);
if ( ov && ov->db.bd_info && ov->db.bd_info->bi_db_close ) {
- rc = ov->db.bd_info->bi_db_close(&ov->db);
+ rc = ov->db.bd_info->bi_db_close(&ov->db, NULL);
}
return(rc);
*/
static int
-translucent_db_destroy( BackendDB *be )
+translucent_db_destroy( BackendDB *be, ConfigReply *cr )
{
slap_overinst *on = (slap_overinst *) be->bd_info;
translucent_info *ov = on->on_bi.bi_private;
int rc = 0;
- Debug(LDAP_DEBUG_TRACE, "==> translucent_db_close\n", 0, 0, 0);
+ Debug(LDAP_DEBUG_TRACE, "==> translucent_db_destroy\n", 0, 0, 0);
if ( ov ) {
if ( ov->db.be_private != NULL ) {
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
*
* Copyright 2004-2007 The OpenLDAP Foundation.
- * Portions Copyright 2004 Symas Corporation.
+ * Portions Copyright 2004,2006-2007 Symas Corporation.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* top-level directory of the distribution or, alternatively, at
* <http://www.OpenLDAP.org/license.html>.
*/
-/* ACKNOWLEDGEMENTS:
- * This work was initially developed by Symas Corp. for inclusion in
- * OpenLDAP Software. This work was sponsored by Hewlett-Packard.
+/* ACKNOWLEDGEMENTS:
+ * This work was initially developed by Symas Corporation for
+ * inclusion in OpenLDAP Software, with subsequent enhancements by
+ * Matthew Backes at Symas Corporation. This work was sponsored by
+ * Hewlett-Packard.
*/
#include "portable.h"
#include "slap.h"
#include "config.h"
+#define UNIQUE_DEFAULT_URI ("ldap:///??sub")
+
static slap_overinst unique;
typedef struct unique_attrs_s {
- struct unique_attrs_s *next; /* list of attrs */
+ struct unique_attrs_s *next; /* list of attrs */
AttributeDescription *attr;
} unique_attrs;
+typedef struct unique_domain_uri_s {
+ struct unique_domain_uri_s *next;
+ struct berval *dn;
+ struct berval *ndn;
+ struct berval *filter;
+ struct unique_attrs_s *attrs;
+ int scope;
+} unique_domain_uri;
+
+typedef struct unique_domain_s {
+ struct unique_domain_s *next;
+ struct berval *domain_spec;
+ struct unique_domain_uri_s *uri;
+ char ignore; /* polarity of attributes */
+ char strict; /* null considered unique too */
+} unique_domain;
+
typedef struct unique_data_s {
- const char *message; /* breadcrumbs */
- struct unique_attrs_s *attrs; /* list of known attrs */
- struct unique_attrs_s *ignore; /* list of ignored attrs */
- BerValue dn; /* base of "unique tree" */
- char strict; /* null considered unique too */
+ struct unique_domain_s *domains;
+ struct unique_domain_s *legacy;
+ char legacy_strict_set;
} unique_data;
typedef struct unique_counter_s {
UNIQUE_BASE = 1,
UNIQUE_IGNORE,
UNIQUE_ATTR,
- UNIQUE_STRICT
+ UNIQUE_STRICT,
+ UNIQUE_URI
};
-static ConfigDriver unique_cf_gen;
+static ConfigDriver unique_cf_base;
+static ConfigDriver unique_cf_attrs;
+static ConfigDriver unique_cf_strict;
+static ConfigDriver unique_cf_uri;
static ConfigTable uniquecfg[] = {
{ "unique_base", "basedn", 2, 2, 0, ARG_DN|ARG_MAGIC|UNIQUE_BASE,
- unique_cf_gen, "( OLcfgOvAt:10.1 NAME 'olcUniqueBase' "
+ unique_cf_base, "( OLcfgOvAt:10.1 NAME 'olcUniqueBase' "
"DESC 'Subtree for uniqueness searches' "
+ "EQUALITY distinguishedNameMatch "
"SYNTAX OMsDN SINGLE-VALUE )", NULL, NULL },
{ "unique_ignore", "attribute...", 2, 0, 0, ARG_MAGIC|UNIQUE_IGNORE,
- unique_cf_gen, "( OLcfgOvAt:10.2 NAME 'olcUniqueIgnore' "
+ unique_cf_attrs, "( OLcfgOvAt:10.2 NAME 'olcUniqueIgnore' "
"DESC 'Attributes for which uniqueness shall not be enforced' "
- "EQUALITY caseIgnoreMatch " /* Should use OID syntax */
+ "EQUALITY caseIgnoreMatch "
+ "ORDERING caseIgnoreOrderingMatch "
+ "SUBSTR caseIgnoreSubstringsMatch "
"SYNTAX OMsDirectoryString )", NULL, NULL },
{ "unique_attributes", "attribute...", 2, 0, 0, ARG_MAGIC|UNIQUE_ATTR,
- unique_cf_gen, "( OLcfgOvAt:10.3 NAME 'olcUniqueAttribute' "
+ unique_cf_attrs, "( OLcfgOvAt:10.3 NAME 'olcUniqueAttribute' "
"DESC 'Attributes for which uniqueness shall be enforced' "
"EQUALITY caseIgnoreMatch "
+ "ORDERING caseIgnoreOrderingMatch "
+ "SUBSTR caseIgnoreSubstringsMatch "
"SYNTAX OMsDirectoryString )", NULL, NULL },
- { "unique_strict", "on|off", 1, 2, 0,
- ARG_ON_OFF|ARG_OFFSET|UNIQUE_STRICT,
- (void *)offsetof(unique_data, strict),
- "( OLcfgOvAt:10.4 NAME 'olcUniqueStrict' "
+ { "unique_strict", "on|off", 1, 2, 0, ARG_MAGIC|UNIQUE_STRICT,
+ unique_cf_strict, "( OLcfgOvAt:10.4 NAME 'olcUniqueStrict' "
"DESC 'Enforce uniqueness of null values' "
+ "EQUALITY booleanMatch "
"SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL },
+ { "unique_uri", "ldapuri", 2, 3, 0, ARG_MAGIC|UNIQUE_URI,
+ unique_cf_uri, "( OLcfgOvAt:10.5 NAME 'olcUniqueURI' "
+ "DESC 'List of keywords and LDAP URIs for a uniqueness domain' "
+ "EQUALITY caseExactMatch "
+ "ORDERING caseExactOrderingMatch "
+ "SUBSTR caseExactSubstringsMatch "
+ "SYNTAX OMsDirectoryString )", NULL, NULL },
{ NULL, NULL, 0, 0, 0, ARG_IGNORED }
};
"DESC 'Attribute value uniqueness configuration' "
"SUP olcOverlayConfig "
"MAY ( olcUniqueBase $ olcUniqueIgnore $ "
- "olcUniqueAttribute $ olcUniqueStrict ) )",
+ "olcUniqueAttribute $ olcUniqueStrict $ "
+ "olcUniqueURI ) )",
Cft_Overlay, uniquecfg },
{ NULL, 0, NULL }
};
+static void
+unique_free_domain_uri ( unique_domain_uri *uri )
+{
+ unique_domain_uri *next_uri = NULL;
+ unique_attrs *attr, *next_attr = NULL;
+
+ while ( uri ) {
+ next_uri = uri->next;
+ ber_bvfree ( uri->dn );
+ ber_bvfree ( uri->ndn );
+ ber_bvfree ( uri->filter );
+ attr = uri->attrs;
+ while ( attr ) {
+ next_attr = attr->next;
+ ch_free (attr);
+ attr = next_attr;
+ }
+ ch_free ( uri );
+ uri = next_uri;
+ }
+}
+
+/* free an entire stack of domains */
+static void
+unique_free_domain ( unique_domain *domain )
+{
+ unique_domain *next_domain = NULL;
+
+ while ( domain ) {
+ next_domain = domain->next;
+ ber_bvfree ( domain->domain_spec );
+ unique_free_domain_uri ( domain->uri );
+ ch_free ( domain );
+ domain = next_domain;
+ }
+}
+
static int
-unique_cf_gen( ConfigArgs *c )
+unique_new_domain_uri ( unique_domain_uri **urip,
+ const LDAPURLDesc *url_desc,
+ ConfigArgs *c )
{
- slap_overinst *on = (slap_overinst *)c->bi;
- unique_data *ud = (unique_data *)on->on_bi.bi_private;
+ int i, rc = LDAP_SUCCESS;
+ unique_domain_uri *uri;
+ struct berval bv = {0, NULL};
BackendDB *be = (BackendDB *)c->be;
- unique_attrs *up, *pup, **pupp = NULL;
- AttributeDescription *ad;
- const char *text;
+ char ** attr_str;
+ AttributeDescription * ad;
+ const char * text;
+
+ uri = ch_calloc ( 1, sizeof ( unique_domain_uri ) );
+
+ if ( url_desc->lud_dn && url_desc->lud_dn[0] ) {
+ ber_str2bv( url_desc->lud_dn, 0, 1, &bv );
+ rc = dnPrettyNormal( NULL,
+ &bv,
+ uri->dn,
+ uri->ndn,
+ NULL );
+ if ( rc != LDAP_SUCCESS ) {
+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
+ "<%s> invalid DN %d (%s)",
+ url_desc->lud_dn, rc, ldap_err2string( rc ));
+ rc = ARG_BAD_CONF;
+ goto exit;
+ }
+
+ if ( !dnIsSuffix ( uri->ndn, &be->be_nsuffix[0] ) ) {
+ sprintf ( c->cr_msg,
+ "dn <%s> is not a suffix of backend base dn <%s>",
+ uri->dn->bv_val,
+ be->be_nsuffix[0].bv_val );
+ rc = ARG_BAD_CONF;
+ goto exit;
+ }
+ }
+
+ attr_str = url_desc->lud_attrs;
+ if ( attr_str ) {
+ for ( i=0; attr_str[i]; ++i ) {
+ unique_attrs * attr;
+ ad = NULL;
+ if ( slap_str2ad ( attr_str[i], &ad, &text )
+ == LDAP_SUCCESS) {
+ attr = ch_calloc ( 1,
+ sizeof ( unique_attrs ) );
+ attr->attr = ad;
+ attr->next = uri->attrs;
+ uri->attrs = attr;
+ } else {
+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
+ "unique: attribute: %s: %s",
+ attr_str[i], text );
+ rc = ARG_BAD_CONF;
+ goto exit;
+ }
+ }
+ }
+
+ uri->scope = url_desc->lud_scope;
+ if ( !uri->scope ) {
+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
+ "unique: uri with base scope will always be unique");
+ rc = ARG_BAD_CONF;
+ goto exit;
+ }
+
+ if (url_desc->lud_filter) {
+ Filter * f;
+ uri->filter = ber_str2bv( url_desc->lud_filter, 0, 1, NULL);
+ f = str2filter( uri->filter->bv_val );
+ if ( !f ) {
+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
+ "unique: bad filter");
+ rc = ARG_BAD_CONF;
+ goto exit;
+ }
+ filter_free( f );
+ }
+exit:
+ if ( bv.bv_val ) ber_memfree ( bv.bv_val );
+ uri->next = *urip;
+ *urip = uri;
+ if ( rc ) {
+ Debug ( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
+ "%s: %s\n", c->log, c->cr_msg, 0 );
+ unique_free_domain_uri ( uri );
+ *urip = NULL;
+ }
+ return rc;
+}
+
+static int
+unique_new_domain_uri_basic ( unique_domain_uri **urip,
+ ConfigArgs *c )
+{
+ LDAPURLDesc *url_desc = NULL;
+ int rc;
+
+ rc = ldap_url_parse ( UNIQUE_DEFAULT_URI, &url_desc );
+ if ( rc ) return rc;
+ rc = unique_new_domain_uri ( urip, url_desc, c );
+ ldap_free_urldesc ( url_desc );
+ return rc;
+}
+
+/* if *domain is non-null, it's pushed down the stack.
+ * note that the entire stack is freed if there is an error,
+ * so build added domains in a separate stack before adding them
+ *
+ * domain_specs look like
+ *
+ * [strict ][ignore ]uri[[ uri]...]
+ * e.g. "ldap:///ou=foo,o=bar?uid?sub ldap:///ou=baz,o=bar?uid?sub"
+ * "strict ldap:///ou=accounts,o=bar?uid,uidNumber?one"
+ * etc
+ *
+ * so finally strictness is per-domain
+ * but so is ignore-state, and that would be better as a per-url thing
+ */
+static int
+unique_new_domain ( unique_domain **domainp,
+ char *domain_spec,
+ ConfigArgs *c )
+{
+ char *uri_start;
+ int rc = LDAP_SUCCESS;
+ int uri_err = 0;
+ unique_domain * domain;
+ LDAPURLDesc *url_desc, *url_descs = NULL;
+
+ Debug(LDAP_DEBUG_TRACE, "==> unique_new_domain <%s>\n",
+ domain_spec, 0, 0);
+
+ domain = ch_calloc ( 1, sizeof (unique_domain) );
+ domain->domain_spec = ber_str2bv( domain_spec, 0, 1, NULL );
+
+ uri_start = domain_spec;
+ if ( strncasecmp ( uri_start, "ignore ",
+ STRLENOF( "ignore " ) ) == 0 ) {
+ domain->ignore = 1;
+ uri_start += STRLENOF( "ignore " );
+ }
+ if ( strncasecmp ( uri_start, "strict ",
+ STRLENOF( "strict " ) ) == 0 ) {
+ domain->strict = 1;
+ uri_start += STRLENOF( "strict " );
+ if ( !domain->ignore
+ && strncasecmp ( uri_start, "ignore ",
+ STRLENOF( "ignore " ) ) == 0 ) {
+ domain->ignore = 1;
+ uri_start += STRLENOF( "ignore " );
+ }
+ }
+ rc = ldap_url_parselist_ext ( &url_descs, uri_start, " ", 0 );
+ if ( rc ) {
+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
+ "<%s> invalid ldap urilist",
+ uri_start );
+ rc = ARG_BAD_CONF;
+ goto exit;
+ }
+
+ for ( url_desc = url_descs;
+ url_desc;
+ url_desc = url_descs->lud_next ) {
+ rc = unique_new_domain_uri ( &domain->uri,
+ url_desc,
+ c );
+ if ( rc ) {
+ rc = ARG_BAD_CONF;
+ uri_err = 1;
+ goto exit;
+ }
+ }
+
+exit:
+ if ( url_descs ) ldap_free_urldesc ( url_descs );
+ domain->next = *domainp;
+ *domainp = domain;
+ if ( rc ) {
+ Debug ( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
+ "%s: %s\n", c->log, c->cr_msg, 0 );
+ unique_free_domain ( domain );
+ *domainp = NULL;
+ }
+ return rc;
+}
+
+static int
+unique_cf_base( ConfigArgs *c )
+{
+ BackendDB *be = (BackendDB *)c->be;
+ slap_overinst *on = (slap_overinst *)c->bi;
+ unique_data *private = (unique_data *) on->on_bi.bi_private;
+ unique_domain *domains = private->domains;
+ unique_domain *legacy = private->legacy;
int rc = ARG_BAD_CONF;
- int i;
switch ( c->op ) {
case SLAP_CONFIG_EMIT:
- switch ( c->type ) {
- case UNIQUE_BASE:
- if ( !BER_BVISEMPTY( &ud->dn )) {
- rc = value_add_one( &c->rvalue_vals, &ud->dn );
- if ( rc ) return rc;
- rc = value_add_one( &c->rvalue_nvals, &ud->dn );
- return rc;
- }
+ rc = 0;
+ if ( legacy && legacy->uri && legacy->uri->dn ) {
+ rc = value_add_one ( &c->rvalue_vals,
+ legacy->uri->dn );
+ if ( rc ) return rc;
+ rc = value_add_one ( &c->rvalue_nvals,
+ legacy->uri->ndn );
+ if ( rc ) return rc;
+ }
+ break;
+ case LDAP_MOD_DELETE:
+ assert ( legacy && legacy->uri && legacy->uri->dn );
+ rc = 0;
+ ber_bvfree ( legacy->uri->dn );
+ ber_bvfree ( legacy->uri->ndn );
+ legacy->uri->dn = NULL;
+ legacy->uri->ndn = NULL;
+ if ( !legacy->uri->attrs
+ && !legacy->uri->dn ) {
+ unique_free_domain_uri ( legacy->uri );
+ legacy->uri = NULL;
+ }
+ if ( !legacy->uri && !private->legacy_strict_set ) {
+ unique_free_domain ( legacy );
+ private->legacy = legacy = NULL;
+ }
+ break;
+ case LDAP_MOD_ADD:
+ case SLAP_CONFIG_ADD:
+ if ( domains ) {
+ sprintf ( c->cr_msg,
+ "cannot set legacy attrs when URIs are present" );
+ Debug ( LDAP_DEBUG_CONFIG, "unique config: %s\n",
+ c->cr_msg, NULL, NULL );
+ rc = ARG_BAD_CONF;
break;
- case UNIQUE_IGNORE:
- /* fallthrough to UNIQUE_ATTR */
- case UNIQUE_ATTR:
- if ( c->type == UNIQUE_IGNORE ) up = ud->ignore;
- else up = ud->attrs;
- while ( up ) {
- value_add_one( &c->rvalue_vals,
- &up->attr->ad_cname );
- up = up->next;
- }
- rc = 0;
+ }
+ if ( !dnIsSuffix ( &c->value_ndn,
+ &be->be_nsuffix[0] ) ) {
+ sprintf ( c->cr_msg,
+ "dn is not a suffix of backend base" );
+ Debug ( LDAP_DEBUG_CONFIG, "unique config: %s\n",
+ c->cr_msg, NULL, NULL );
+ rc = ARG_BAD_CONF;
break;
- case UNIQUE_STRICT:
- /* handled via ARG_OFFSET */
- /* fallthrough to default */
- default:
- abort ();
}
+ if ( !legacy ) {
+ unique_new_domain ( &private->legacy,
+ UNIQUE_DEFAULT_URI,
+ c );
+ legacy = private->legacy;
+ }
+ if ( !legacy->uri )
+ unique_new_domain_uri_basic ( &legacy->uri, c );
+ ber_bvfree ( legacy->uri->dn );
+ ber_bvfree ( legacy->uri->ndn );
+ legacy->uri->dn = ber_bvdup ( &c->value_dn );
+ legacy->uri->ndn = ber_bvdup ( &c->value_ndn );
+ rc = 0;
+ break;
+ default:
+ abort();
+ }
+
+ return rc;
+}
+
+static int
+unique_cf_attrs( ConfigArgs *c )
+{
+ slap_overinst *on = (slap_overinst *)c->bi;
+ unique_data *private = (unique_data *) on->on_bi.bi_private;
+ unique_domain *domains = private->domains;
+ unique_domain *legacy = private->legacy;
+ unique_attrs *new_attrs = NULL;
+ unique_attrs *attr, *next_attr, *reverse_attrs;
+ unique_attrs **attrp;
+ int rc = ARG_BAD_CONF;
+ int i;
+
+ switch ( c->op ) {
+ case SLAP_CONFIG_EMIT:
+ if ( legacy
+ && (c->type == UNIQUE_IGNORE) == legacy->ignore
+ && legacy->uri )
+ for ( attr = legacy->uri->attrs;
+ attr;
+ attr = attr->next )
+ value_add_one( &c->rvalue_vals,
+ &attr->attr->ad_cname );
+ rc = 0;
break;
case LDAP_MOD_DELETE:
- switch ( c->type ) {
- case UNIQUE_BASE:
- /* default to the base of our configured database */
- if ( ud->dn.bv_val ) ber_memfree ( ud->dn.bv_val );
- ber_dupbv( &ud->dn, &be->be_nsuffix[0] );
- rc = 0;
+ if ( legacy
+ && (c->type == UNIQUE_IGNORE) == legacy->ignore
+ && legacy->uri
+ && legacy->uri->attrs) {
+ if ( c->valx < 0 ) { /* delete all */
+ for ( attr = legacy->uri->attrs;
+ attr;
+ attr = next_attr ) {
+ next_attr = attr->next;
+ ch_free ( attr );
+ }
+ legacy->uri->attrs = NULL;
+ } else { /* delete by index */
+ attrp = &legacy->uri->attrs;
+ for ( i=0; i < c->valx; ++i )
+ attrp = &(*attrp)->next;
+ attr = *attrp;
+ *attrp = attr->next;
+ ch_free (attr);
+ }
+ if ( !legacy->uri->attrs
+ && !legacy->uri->dn ) {
+ unique_free_domain_uri ( legacy->uri );
+ legacy->uri = NULL;
+ }
+ if ( !legacy->uri && !private->legacy_strict_set ) {
+ unique_free_domain ( legacy );
+ private->legacy = legacy = NULL;
+ }
+ }
+ rc = 0;
+ break;
+ case LDAP_MOD_ADD:
+ case SLAP_CONFIG_ADD:
+ if ( domains ) {
+ sprintf ( c->cr_msg,
+ "cannot set legacy attrs when URIs are present" );
+ Debug ( LDAP_DEBUG_CONFIG, "unique config: %s\n",
+ c->cr_msg, NULL, NULL );
+ rc = ARG_BAD_CONF;
+ break;
+ }
+ if ( legacy
+ && legacy->uri
+ && legacy->uri->attrs
+ && (c->type == UNIQUE_IGNORE) != legacy->ignore ) {
+ sprintf ( c->cr_msg,
+ "cannot set both attrs and ignore-attrs" );
+ Debug ( LDAP_DEBUG_CONFIG, "unique config: %s\n",
+ c->cr_msg, NULL, NULL );
+ rc = ARG_BAD_CONF;
break;
- case UNIQUE_IGNORE:
- /* fallthrough to UNIQUE_ATTR */
- case UNIQUE_ATTR:
- if ( c->type == UNIQUE_IGNORE ) pupp = &ud->ignore;
- else pupp = &ud->attrs;
-
- if ( c->valx < 0 ) {
- up = *pupp;
- *pupp = NULL;
- while ( up ) {
- pup = up;
- up = up->next;
- ch_free ( pup );
+ }
+ if ( !legacy ) {
+ unique_new_domain ( &private->legacy,
+ UNIQUE_DEFAULT_URI,
+ c );
+ legacy = private->legacy;
+ }
+ if ( !legacy->uri )
+ unique_new_domain_uri_basic ( &legacy->uri, c );
+ rc = 0;
+ for ( i=1; c->argv[i]; ++i ) {
+ AttributeDescription * ad = NULL;
+ const char * text;
+ if ( slap_str2ad ( c->argv[i], &ad, &text )
+ == LDAP_SUCCESS) {
+
+ attr = ch_calloc ( 1,
+ sizeof ( unique_attrs ) );
+ attr->attr = ad;
+ attr->next = new_attrs;
+ new_attrs = attr;
+ } else {
+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
+ "unique: attribute: %s: %s",
+ c->argv[i], text );
+ for ( attr = new_attrs;
+ attr;
+ attr=next_attr ) {
+ next_attr = attr->next;
+ ch_free ( attr );
}
+ rc = ARG_BAD_CONF;
+ break;
+ }
+ }
+ if ( rc ) break;
+
+ /* (nconc legacy->uri->attrs (nreverse new_attrs)) */
+ reverse_attrs = NULL;
+ for ( attr = new_attrs;
+ attr;
+ attr = next_attr ) {
+ next_attr = attr->next;
+ attr->next = reverse_attrs;
+ reverse_attrs = attr;
+ }
+ for ( attrp = &legacy->uri->attrs;
+ *attrp;
+ attrp = &(*attrp)->next ) ;
+ *attrp = reverse_attrs;
- } else {
+ legacy->ignore = ( c->type == UNIQUE_IGNORE );
+ break;
+ default:
+ abort();
+ }
- /* delete from linked list */
- for ( i=0; i < c->valx; ++i ) {
- pupp = &(*pupp)->next;
- }
- up = *pupp;
- *pupp = (*pupp)->next;
+ if ( rc ) {
+ Debug ( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
+ "%s: %s\n", c->log, c->cr_msg, 0 );
+ }
+ return rc;
+}
+
+static int
+unique_cf_strict( ConfigArgs *c )
+{
+ slap_overinst *on = (slap_overinst *)c->bi;
+ unique_data *private = (unique_data *) on->on_bi.bi_private;
+ unique_domain *domains = private->domains;
+ unique_domain *legacy = private->legacy;
+ int rc = ARG_BAD_CONF;
- /* AttributeDescriptions are global so
- * shouldn't be freed here... */
- ch_free ( up );
+ switch ( c->op ) {
+ case SLAP_CONFIG_EMIT:
+ /* We process the boolean manually instead of using
+ * ARG_ON_OFF so that we can three-state it;
+ * olcUniqueStrict is either TRUE, FALSE, or missing,
+ * and missing is necessary to add olcUniqueURIs...
+ */
+ if ( private->legacy_strict_set ) {
+ struct berval bv;
+ bv.bv_val = legacy->strict ? "TRUE" : "FALSE";
+ bv.bv_len = legacy->strict ?
+ STRLENOF("TRUE") :
+ STRLENOF("FALSE");
+ value_add_one ( &c->rvalue_vals, &bv );
+ }
+ rc = 0;
+ break;
+ case LDAP_MOD_DELETE:
+ if ( legacy ) {
+ legacy->strict = 0;
+ if ( ! legacy->uri ) {
+ unique_free_domain ( legacy );
+ private->legacy = NULL;
}
- rc = 0;
- break;
- case UNIQUE_STRICT:
- /* handled via ARG_OFFSET */
- /* fallthrough to default */
- default:
- abort ();
}
+ private->legacy_strict_set = 0;
+ rc = 0;
break;
- case SLAP_CONFIG_ADD:
- /* fallthrough to LDAP_MOD_ADD */
case LDAP_MOD_ADD:
- switch ( c->type ) {
- case UNIQUE_BASE:
- if ( !dnIsSuffix ( &c->value_ndn,
- &be->be_nsuffix[0] ) ) {
- sprintf ( c->msg, "%s dn is not a suffix of backend base",
- c->argv[0] );
- Debug ( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
- "%s: %s\n", c->log, c->msg, 0 );
- rc = ARG_BAD_CONF;
- }
- if ( ud->dn.bv_val ) ber_memfree ( ud->dn.bv_val );
- ud->dn = c->value_ndn;
- rc = 0;
+ case SLAP_CONFIG_ADD:
+ if ( domains ) {
+ sprintf ( c->cr_msg,
+ "cannot set legacy attrs when URIs are present" );
+ Debug ( LDAP_DEBUG_CONFIG, "unique config: %s\n",
+ c->cr_msg, NULL, NULL );
+ rc = ARG_BAD_CONF;
break;
- case UNIQUE_IGNORE:
- /* fallthrough to UNIQUE_ATTR */
- case UNIQUE_ATTR:
- rc = 0;
- for ( i=1; i < c->argc; ++i ) {
- ad = NULL;
- if ( slap_str2ad ( c->argv[i], &ad, &text )
- == LDAP_SUCCESS) {
-
- up = ch_malloc (
- sizeof ( unique_attrs ) );
- up->attr = ad;
- if ( c->type == UNIQUE_IGNORE ) {
- up->next = ud->ignore;
- ud->ignore = up;
- } else {
- up->next = ud->attrs;
- ud->attrs = up;
- }
- } else {
- snprintf( c->msg, sizeof( c->msg ),
- "%s <%s>: %s", c->argv[0], c->argv[i], text );
- Debug ( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
- "%s: %s\n", c->log, c->msg, 0 );
- rc = ARG_BAD_CONF;
- }
- }
+ }
+ if ( ! legacy ) {
+ unique_new_domain ( &private->legacy,
+ UNIQUE_DEFAULT_URI,
+ c );
+ legacy = private->legacy;
+ }
+ /* ... not using ARG_ON_OFF makes this necessary too */
+ assert ( c->argc == 2 );
+ legacy->strict = (strcasecmp ( c->argv[1], "TRUE" ) == 0);
+ private->legacy_strict_set = 1;
+ rc = 0;
+ break;
+ default:
+ abort();
+ }
+
+ return rc;
+}
+
+static int
+unique_cf_uri( ConfigArgs *c )
+{
+ slap_overinst *on = (slap_overinst *)c->bi;
+ unique_data *private = (unique_data *) on->on_bi.bi_private;
+ unique_domain *domains = private->domains;
+ unique_domain *legacy = private->legacy;
+ unique_domain *domain = NULL, **domainp = NULL;
+ int rc = ARG_BAD_CONF;
+ int i;
+
+ switch ( c->op ) {
+ case SLAP_CONFIG_EMIT:
+ for ( domain = domains;
+ domain;
+ domain = domain->next ) {
+ rc = value_add_one ( &c->rvalue_vals,
+ domain->domain_spec );
+ if ( rc ) break;
+ rc = value_add_one ( &c->rvalue_nvals,
+ domain->domain_spec );
+ if ( rc ) break;
+ }
+ break;
+ case LDAP_MOD_DELETE:
+ if ( c->valx < 0 ) { /* delete them all! */
+ unique_free_domain ( domains );
+ private->domains = NULL;
+ } else { /* delete just one */
+ domainp = &private->domains;
+ for ( i=0; i < c->valx && *domainp; ++i )
+ domainp = &(*domainp)->next;
+
+ /* If *domainp is null, we walked off the end
+ * of the list. This happens when back-config
+ * and the overlay are out-of-sync, like when
+ * rejecting changes before ITS#4752 gets
+ * fixed.
+ *
+ * This should never happen, but will appear
+ * if you backport this version of
+ * slapo-unique without the config-undo fixes
+ *
+ * test024 Will hit this case in such a
+ * situation.
+ */
+ assert (*domainp != NULL);
+
+ domain = *domainp;
+ *domainp = domain->next;
+ domain->next = NULL;
+ unique_free_domain ( domain );
+ }
+ rc = 0;
+ break;
+
+ case SLAP_CONFIG_ADD: /* fallthrough */
+ case LDAP_MOD_ADD:
+ if ( legacy ) {
+ sprintf ( c->cr_msg,
+ "cannot set Uri when legacy attrs are present" );
+ Debug ( LDAP_DEBUG_CONFIG, "unique config: %s\n",
+ c->cr_msg, NULL, NULL );
+ rc = ARG_BAD_CONF;
break;
- case UNIQUE_STRICT:
- /* handled via ARG_OFFSET */
- /* fallthrough to default */
- default:
- abort ();
}
+ rc = 0;
+ if ( c->line ) rc = unique_new_domain ( &domain, c->line, c );
+ else rc = unique_new_domain ( &domain, c->argv[1], c );
+ if ( rc ) break;
+ assert ( domain->next == NULL );
+ for ( domainp = &private->domains;
+ *domainp;
+ domainp = &(*domainp)->next ) ;
+ *domainp = domain;
+
break;
+
default:
abort ();
}
**
*/
-static int unique_db_init(
- BackendDB *be
+static int
+unique_db_init(
+ BackendDB *be,
+ ConfigReply *cr
)
{
slap_overinst *on = (slap_overinst *)be->bd_info;
- unique_data *ud = ch_calloc(1,sizeof(unique_data));
+ unique_data **privatep = (unique_data **) &on->on_bi.bi_private;
- /* Debug(LDAP_DEBUG_TRACE, "==> unique_init\n", 0, 0, 0); */
+ Debug(LDAP_DEBUG_TRACE, "==> unique_db_init\n", 0, 0, 0);
+
+ *privatep = ch_calloc ( 1, sizeof ( unique_data ) );
- ud->message = "_init";
- on->on_bi.bi_private = ud;
return 0;
}
-static int unique_db_destroy(
- BackendDB *be
+static int
+unique_db_destroy(
+ BackendDB *be,
+ ConfigReply *cr
)
{
slap_overinst *on = (slap_overinst *)be->bd_info;
+ unique_data **privatep = (unique_data **) &on->on_bi.bi_private;
+ unique_data *private = *privatep;
+
+ Debug(LDAP_DEBUG_TRACE, "==> unique_db_destroy\n", 0, 0, 0);
+
+ if ( private ) {
+ unique_domain *domains = private->domains;
+ unique_domain *legacy = private->legacy;
- if ( on->on_bi.bi_private ) {
- ch_free( on->on_bi.bi_private );
- on->on_bi.bi_private = NULL;
+ unique_free_domain ( domains );
+ unique_free_domain ( legacy );
+ ch_free ( private );
+ *privatep = NULL;
}
+
return 0;
}
-/*
-** mostly, just print the init message;
-**
-*/
-
static int
unique_open(
- BackendDB *be
+ BackendDB *be,
+ ConfigReply *cr
)
{
- slap_overinst *on = (slap_overinst *)be->bd_info;
- unique_data *ud = on->on_bi.bi_private;
- ud->message = "_open";
-
Debug(LDAP_DEBUG_TRACE, "unique_open: overlay initialized\n", 0, 0, 0);
- if ( BER_BVISNULL( &ud->dn )) {
- if ( BER_BVISNULL( &be->be_nsuffix[0] ))
- return -1;
-
- /* default to the base of our configured database */
- ber_dupbv(&ud->dn, &be->be_nsuffix[0]);
- }
- return(0);
+ return 0;
}
/*
-** foreach configured attribute:
-** free it;
-** free our basedn;
+** Leave unique_data but wipe out config
**
*/
static int
unique_close(
- BackendDB *be
+ BackendDB *be,
+ ConfigReply *cr
)
{
slap_overinst *on = (slap_overinst *) be->bd_info;
- unique_data *ud = on->on_bi.bi_private;
- unique_attrs *ii, *ij;
- ud->message = "_close";
+ unique_data **privatep = (unique_data **) &on->on_bi.bi_private;
+ unique_data *private = *privatep;
Debug(LDAP_DEBUG_TRACE, "==> unique_close\n", 0, 0, 0);
- for(ii = ud->attrs; ii; ii = ij) {
- ij = ii->next;
- ch_free(ii);
- }
+ if ( private ) {
+ unique_domain *domains = private->domains;
+ unique_domain *legacy = private->legacy;
- for(ii = ud->ignore; ii; ii = ij) {
- ij = ii->next;
- ch_free(ii);
+ unique_free_domain ( domains );
+ unique_free_domain ( legacy );
+ memset ( private, 0, sizeof ( unique_data ) );
}
- ch_free(ud->dn.bv_val);
-
- memset( ud, 0, sizeof(*ud));
-
- return(0);
+ return ( 0 );
}
return(0);
}
-static int count_filter_len(
- unique_data *ud,
+/* count the length of one attribute ad
+ * (and all of its values b)
+ * in the proposed filter
+ */
+static int
+count_filter_len(
+ unique_domain *domain,
+ unique_domain_uri *uri,
AttributeDescription *ad,
- BerVarray b,
- int ks
+ BerVarray b
)
{
- unique_attrs *up;
+ unique_attrs *attr;
int i;
+ int ks = 0;
while ( !is_at_operational( ad->ad_type ) ) {
- if ( ud->ignore ) {
- for ( up = ud->ignore; up; up = up->next ) {
- if (ad == up->attr ) {
- break;
- }
- }
- if ( up ) {
- break;
- }
- }
- if ( ud->attrs ) {
- for ( up = ud->attrs; up; up = up->next ) {
- if ( ad == up->attr ) {
+ if ( uri->attrs ) {
+ for ( attr = uri->attrs; attr; attr = attr->next ) {
+ if ( ad == attr->attr ) {
break;
}
}
- if ( !up ) {
+ if ( ( domain->ignore && attr )
+ || (!domain->ignore && !attr )) {
break;
}
}
/* note: make room for filter escaping... */
ks += ( 3 * b[i].bv_len ) + ad->ad_cname.bv_len + STRLENOF( "(=)" );
}
- } else if ( ud->strict ) {
+ } else if ( domain->strict ) {
ks += ad->ad_cname.bv_len + STRLENOF( "(=*)" ); /* (attr=*) */
}
break;
}
+
return ks;
}
-static char *build_filter(
- unique_data *ud,
+static char *
+build_filter(
+ unique_domain *domain,
+ unique_domain_uri *uri,
AttributeDescription *ad,
BerVarray b,
char *kp,
void *ctx
)
{
- unique_attrs *up;
+ unique_attrs *attr;
int i;
while ( !is_at_operational( ad->ad_type ) ) {
- if ( ud->ignore ) {
- for ( up = ud->ignore; up; up = up->next ) {
- if ( ad == up->attr ) {
+ if ( uri->attrs ) {
+ for ( attr = uri->attrs; attr; attr = attr->next ) {
+ if ( ad == attr->attr ) {
break;
}
}
- if ( up ) {
- break;
- }
- }
- if ( ud->attrs ) {
- for ( up = ud->attrs; up; up = up->next ) {
- if ( ad == up->attr ) {
- break;
- }
- }
- if ( !up ) {
+ if ( ( domain->ignore && attr )
+ || (!domain->ignore && !attr )) {
break;
}
}
ber_memfree_x( bv.bv_val, ctx );
}
}
- } else if ( ud->strict ) {
+ } else if ( domain->strict ) {
kp += sprintf( kp, "(%s=*)", ad->ad_cname.bv_val );
}
break;
return kp;
}
-static int unique_search(
+static int
+unique_search(
Operation *op,
Operation *nop,
+ struct berval * dn,
+ int scope,
SlapReply *rs,
char *key
)
{
slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
- unique_data *ud = on->on_bi.bi_private;
SlapReply nrs = { REP_RESULT };
slap_callback cb = { NULL, NULL, NULL, NULL }; /* XXX */
unique_counter uq = { NULL, 0 };
int rc;
+ Debug(LDAP_DEBUG_TRACE, "==> unique_search %s\n", key, 0, 0);
+
nop->ors_filter = str2filter_x(nop, key);
ber_str2bv(key, 0, 0, &nop->ors_filterstr);
cb.sc_private = &uq;
nop->o_callback = &cb;
nop->o_tag = LDAP_REQ_SEARCH;
- nop->ors_scope = LDAP_SCOPE_SUBTREE;
+ nop->ors_scope = scope;
nop->ors_deref = LDAP_DEREF_NEVER;
nop->ors_limit = NULL;
nop->ors_slimit = SLAP_NO_LIMIT;
uq.ndn = &op->o_req_ndn;
- nop->o_req_ndn = ud->dn;
+ nop->o_req_ndn = *dn;
nop->o_ndn = op->o_bd->be_rootndn;
nop->o_bd = on->on_info->oi_origdb;
return(SLAP_CB_CONTINUE);
}
-#define ALLOC_EXTRA 16 /* extra slop */
-
-static int unique_add(
+static int
+unique_add(
Operation *op,
SlapReply *rs
)
{
slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
- unique_data *ud = on->on_bi.bi_private;
+ unique_data *private = (unique_data *) on->on_bi.bi_private;
+ unique_domain *domains = private->domains;
+ unique_domain *legacy = private->legacy;
+ unique_domain *domain;
Operation nop = *op;
-
Attribute *a;
char *key, *kp;
- int ks = 0;
-
- Debug(LDAP_DEBUG_TRACE, "==> unique_add <%s>\n", op->o_req_dn.bv_val, 0, 0);
-
- if ( !dnIsSuffix( &op->o_req_ndn, &ud->dn ))
- return SLAP_CB_CONTINUE;
-
-/*
-** count everything first;
-** allocate some memory;
-** write the search key;
-**
-*/
-
- if(!(a = op->ora_e->e_attrs)) {
- op->o_bd->bd_info = (BackendInfo *) on->on_info;
- send_ldap_error(op, rs, LDAP_INVALID_SYNTAX,
- "unique_add() got null op.ora_e.e_attrs");
- return(rs->sr_err);
- } else for(; a; a = a->a_next) {
- ks = count_filter_len(ud, a->a_desc, a->a_vals, ks);
- }
-
- if ( !ks )
- return SLAP_CB_CONTINUE;
-
- ks += ALLOC_EXTRA;
- key = op->o_tmpalloc(ks, op->o_tmpmemctx);
+ int rc = SLAP_CB_CONTINUE;
+
+ Debug(LDAP_DEBUG_TRACE, "==> unique_add <%s>\n",
+ op->o_req_dn.bv_val, 0, 0);
+
+ for ( domain = legacy ? legacy : domains;
+ domain;
+ domain = domain->next ) {
+ unique_domain_uri *uri;
+ int ks = 0;
+
+ for ( uri = domain->uri;
+ uri;
+ uri = uri->next ) {
+
+ if ( uri->ndn
+ && !dnIsSuffix( &op->o_req_ndn, uri->ndn ))
+ continue;
+
+ if(!(a = op->ora_e->e_attrs)) {
+ op->o_bd->bd_info = (BackendInfo *) on->on_info;
+ send_ldap_error(op, rs, LDAP_INVALID_SYNTAX,
+ "unique_add() got null op.ora_e.e_attrs");
+ rc = rs->sr_err;
+ break;
- kp = key + sprintf(key, "(|");
+ } else {
+ for(; a; a = a->a_next) {
+ ks += count_filter_len ( domain,
+ uri,
+ a->a_desc,
+ a->a_vals);
+ }
+ }
- for(a = op->ora_e->e_attrs; a; a = a->a_next) {
- kp = build_filter(ud, a->a_desc, a->a_vals, kp, op->o_tmpmemctx);
+ /* skip this domain-uri if it isn't involved */
+ if ( !ks ) continue;
+
+ if ( uri->filter && uri->filter->bv_len )
+ ks += uri->filter->bv_len + STRLENOF ("(&)");
+ kp = key = op->o_tmpalloc(ks, op->o_tmpmemctx);
+
+ if ( uri->filter && uri->filter->bv_len )
+ kp += sprintf (kp, "(&%s", uri->filter->bv_val);
+ kp += sprintf(kp, "(|");
+
+ for(a = op->ora_e->e_attrs; a; a = a->a_next)
+ kp = build_filter(domain,
+ uri,
+ a->a_desc,
+ a->a_vals,
+ kp,
+ op->o_tmpmemctx);
+
+ kp += sprintf(kp, ")");
+ if ( uri->filter && uri->filter->bv_len )
+ kp += sprintf (kp, ")");
+
+ rc = unique_search ( op,
+ &nop,
+ uri->ndn ?
+ uri->ndn :
+ &op->o_bd->be_nsuffix[0],
+ uri->scope,
+ rs,
+ key);
+
+ if ( rc != SLAP_CB_CONTINUE ) break;
+ }
+ if ( rc != SLAP_CB_CONTINUE ) break;
}
- sprintf(kp, ")");
-
- Debug(LDAP_DEBUG_TRACE, "=> unique_add %s\n", key, 0, 0);
-
- return unique_search(op, &nop, rs, key);
+ return rc;
}
-static int unique_modify(
+static int
+unique_modify(
Operation *op,
SlapReply *rs
)
{
slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
- unique_data *ud = on->on_bi.bi_private;
+ unique_data *private = (unique_data *) on->on_bi.bi_private;
+ unique_domain *domains = private->domains;
+ unique_domain *legacy = private->legacy;
+ unique_domain *domain;
Operation nop = *op;
-
Modifications *m;
char *key, *kp;
- int ks = 0;
-
- Debug(LDAP_DEBUG_TRACE, "==> unique_modify <%s>\n", op->o_req_dn.bv_val, 0, 0);
-
- if ( !dnIsSuffix( &op->o_req_ndn, &ud->dn ))
- return SLAP_CB_CONTINUE;
-
-/*
-** count everything first;
-** allocate some memory;
-** write the search key;
-**
-*/
-
- if(!(m = op->orm_modlist)) {
- op->o_bd->bd_info = (BackendInfo *) on->on_info;
- send_ldap_error(op, rs, LDAP_INVALID_SYNTAX,
- "unique_modify() got null op.orm_modlist");
- return(rs->sr_err);
- } else for(; m; m = m->sml_next) {
- if ((m->sml_op & LDAP_MOD_OP) == LDAP_MOD_DELETE) continue;
- ks = count_filter_len(ud, m->sml_desc, m->sml_values, ks);
- }
-
- if ( !ks )
- return SLAP_CB_CONTINUE;
-
- ks += ALLOC_EXTRA;
- key = op->o_tmpalloc(ks, op->o_tmpmemctx);
-
- kp = key + sprintf(key, "(|");
+ int rc = SLAP_CB_CONTINUE;
+
+ Debug(LDAP_DEBUG_TRACE, "==> unique_modify <%s>\n",
+ op->o_req_dn.bv_val, 0, 0);
+
+ for ( domain = legacy ? legacy : domains;
+ domain;
+ domain = domain->next ) {
+ unique_domain_uri *uri;
+ int ks = 0;
+
+ for ( uri = domain->uri;
+ uri;
+ uri = uri->next ) {
+
+ if ( uri->ndn
+ && !dnIsSuffix( &op->o_req_ndn, uri->ndn ))
+ continue;
+
+ if ( !(m = op->orm_modlist) ) {
+ op->o_bd->bd_info = (BackendInfo *) on->on_info;
+ send_ldap_error(op, rs, LDAP_INVALID_SYNTAX,
+ "unique_modify() got null op.orm_modlist");
+ rc = rs->sr_err;
+ break;
- for(m = op->orm_modlist; m; m = m->sml_next) {
- if ((m->sml_op & LDAP_MOD_OP) == LDAP_MOD_DELETE) continue;
- kp = build_filter(ud, m->sml_desc, m->sml_values, kp, op->o_tmpmemctx);
+ } else
+ for ( ; m; m = m->sml_next)
+ if ( (m->sml_op & LDAP_MOD_OP)
+ != LDAP_MOD_DELETE )
+ ks += count_filter_len
+ ( domain,
+ uri,
+ m->sml_desc,
+ m->sml_values);
+
+ /* skip this domain-uri if it isn't involved */
+ if ( !ks ) continue;
+
+ if ( uri->filter && uri->filter->bv_len )
+ ks += uri->filter->bv_len + STRLENOF ("(&)");
+ kp = key = op->o_tmpalloc(ks, op->o_tmpmemctx);
+
+ if ( uri->filter && uri->filter->bv_len )
+ kp += sprintf (kp, "(&%s", uri->filter->bv_val);
+ kp += sprintf(kp, "(|");
+
+ for(m = op->orm_modlist; m; m = m->sml_next)
+ if ( (m->sml_op & LDAP_MOD_OP)
+ != LDAP_MOD_DELETE )
+ kp = build_filter ( domain,
+ uri,
+ m->sml_desc,
+ m->sml_values,
+ kp,
+ op->o_tmpmemctx );
+
+ kp += sprintf (kp, ")");
+ if ( uri->filter && uri->filter->bv_len )
+ kp += sprintf (kp, ")");
+
+ rc = unique_search ( op,
+ &nop,
+ uri->ndn ?
+ uri->ndn :
+ &op->o_bd->be_nsuffix[0],
+ uri->scope,
+ rs,
+ key);
+
+ if ( rc != SLAP_CB_CONTINUE ) break;
+ }
+ if ( rc != SLAP_CB_CONTINUE ) break;
}
- sprintf(kp, ")");
-
- Debug(LDAP_DEBUG_TRACE, "=> unique_modify %s\n", key, 0, 0);
-
- return unique_search(op, &nop, rs, key);
+ return rc;
}
-static int unique_modrdn(
+static int
+unique_modrdn(
Operation *op,
SlapReply *rs
)
{
slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
- unique_data *ud = on->on_bi.bi_private;
+ unique_data *private = (unique_data *) on->on_bi.bi_private;
+ unique_domain *domains = private->domains;
+ unique_domain *legacy = private->legacy;
+ unique_domain *domain;
Operation nop = *op;
-
char *key, *kp;
- int i, ks = 0;
LDAPRDN newrdn;
struct berval bv[2];
+ int rc = SLAP_CB_CONTINUE;
Debug(LDAP_DEBUG_TRACE, "==> unique_modrdn <%s> <%s>\n",
op->o_req_dn.bv_val, op->orr_newrdn.bv_val, 0);
- if ( !dnIsSuffix( &op->o_req_ndn, &ud->dn ) &&
- (!op->orr_nnewSup || !dnIsSuffix( op->orr_nnewSup, &ud->dn )))
- return SLAP_CB_CONTINUE;
-
- if(ldap_bv2rdn_x(&op->oq_modrdn.rs_newrdn, &newrdn,
- (char **)&rs->sr_text, LDAP_DN_FORMAT_LDAP, op->o_tmpmemctx )) {
- op->o_bd->bd_info = (BackendInfo *) on->on_info;
- send_ldap_error(op, rs, LDAP_INVALID_SYNTAX,
- "unknown type(s) used in RDN");
- return(rs->sr_err);
- }
- for(i = 0; newrdn[i]; i++) {
- AttributeDescription *ad = NULL;
- if ( slap_bv2ad( &newrdn[i]->la_attr, &ad, &rs->sr_text )) {
- ldap_rdnfree_x( newrdn, op->o_tmpmemctx );
- rs->sr_err = LDAP_INVALID_SYNTAX;
- send_ldap_result( op, rs );
- return(rs->sr_err);
- }
- newrdn[i]->la_private = ad;
- }
+ for ( domain = legacy ? legacy : domains;
+ domain;
+ domain = domain->next ) {
+ unique_domain_uri *uri;
+ int ks = 0;
+
+ for ( uri = domain->uri;
+ uri;
+ uri = uri->next ) {
+ int i;
+
+ if ( uri->ndn
+ && !dnIsSuffix( &op->o_req_ndn, uri->ndn )
+ && (!op->orr_nnewSup
+ || !dnIsSuffix( op->orr_nnewSup, uri->ndn )))
+ continue;
+
+ if ( ldap_bv2rdn_x ( &op->oq_modrdn.rs_newrdn,
+ &newrdn,
+ (char **)&rs->sr_text,
+ LDAP_DN_FORMAT_LDAP,
+ op->o_tmpmemctx ) ) {
+ op->o_bd->bd_info = (BackendInfo *) on->on_info;
+ send_ldap_error(op, rs, LDAP_INVALID_SYNTAX,
+ "unknown type(s) used in RDN");
+ rc = rs->sr_err;
+ break;
+ }
- bv[1].bv_val = NULL;
- bv[1].bv_len = 0;
+ rc = SLAP_CB_CONTINUE;
+ for ( i=0; newrdn[i]; i++) {
+ AttributeDescription *ad = NULL;
+ if ( slap_bv2ad( &newrdn[i]->la_attr, &ad, &rs->sr_text )) {
+ ldap_rdnfree_x( newrdn, op->o_tmpmemctx );
+ rs->sr_err = LDAP_INVALID_SYNTAX;
+ send_ldap_result( op, rs );
+ rc = rs->sr_err;
+ break;
+ }
+ newrdn[i]->la_private = ad;
+ }
+ if ( rc != SLAP_CB_CONTINUE ) break;
- for(i = 0; newrdn[i]; i++) {
- bv[0] = newrdn[i]->la_value;
- ks = count_filter_len(ud, newrdn[i]->la_private, bv, ks);
- }
+ bv[1].bv_val = NULL;
+ bv[1].bv_len = 0;
- if ( !ks )
- return SLAP_CB_CONTINUE;
+ for ( i=0; newrdn[i]; i++ ) {
+ bv[0] = newrdn[i]->la_value;
+ ks += count_filter_len ( domain,
+ uri,
+ newrdn[i]->la_private,
+ bv);
+ }
- ks += ALLOC_EXTRA;
- key = op->o_tmpalloc(ks, op->o_tmpmemctx);
- kp = key + sprintf(key, "(|");
+ /* skip this domain if it isn't involved */
+ if ( !ks ) continue;
+
+ if ( uri->filter && uri->filter->bv_len )
+ ks += uri->filter->bv_len + STRLENOF ("(&)");
+ kp = key = op->o_tmpalloc(ks, op->o_tmpmemctx);
+
+ if ( uri->filter && uri->filter->bv_len )
+ kp += sprintf (kp, "(&%s", uri->filter->bv_val);
+ kp += sprintf(kp, "(|");
+
+ for ( i=0; newrdn[i]; i++) {
+ bv[0] = newrdn[i]->la_value;
+ kp = build_filter ( domain,
+ uri,
+ newrdn[i]->la_private,
+ bv,
+ kp,
+ op->o_tmpmemctx);
+ }
- for(i = 0; newrdn[i]; i++) {
- bv[0] = newrdn[i]->la_value;
- kp = build_filter(ud, newrdn[i]->la_private, bv, kp, op->o_tmpmemctx);
- }
+ kp += sprintf(kp, ")");
+ if ( uri->filter && uri->filter->bv_len )
+ kp += sprintf (kp, ")");
- sprintf(kp, ")");
+ rc = unique_search ( op,
+ &nop,
+ uri->ndn ?
+ uri->ndn :
+ &op->o_bd->be_nsuffix[0],
+ uri->scope,
+ rs,
+ key);
- Debug(LDAP_DEBUG_TRACE, "=> unique_modrdn %s\n", key, 0, 0);
+ if ( rc != SLAP_CB_CONTINUE ) break;
+ }
+ if ( rc != SLAP_CB_CONTINUE ) break;
+ }
- return unique_search(op, &nop, rs, key);
+ return rc;
}
/*
** it expects to be called automagically during dynamic module initialization
*/
-int unique_initialize() {
+int
+unique_initialize()
+{
int rc;
/* statically declared just after the #includes at top */
+ memset (&unique, 0, sizeof(unique));
+
unique.on_bi.bi_type = "unique";
unique.on_bi.bi_db_init = unique_db_init;
unique.on_bi.bi_db_destroy = unique_db_destroy;
unique.on_bi.bi_op_add = unique_add;
unique.on_bi.bi_op_modify = unique_modify;
unique.on_bi.bi_op_modrdn = unique_modrdn;
- unique.on_bi.bi_op_delete = NULL;
unique.on_bi.bi_cf_ocs = uniqueocs;
rc = config_register_schema( uniquecfg, uniqueocs );
vitmp.vi_ad = NULL;
i = slap_str2ad( c->argv[1], &vitmp.vi_ad, &text );
if ( i ) {
- sprintf( c->msg, "<%s> %s", c->argv[0], text );
+ sprintf( c->cr_msg, "<%s> %s", c->argv[0], text );
Debug( LDAP_DEBUG_ANY, "%s: %s (%s)!\n",
- c->log, c->msg, c->argv[1] );
+ c->log, c->cr_msg, c->argv[1] );
return(1);
}
if ( is_at_single_value( vitmp.vi_ad->ad_type )) {
- sprintf( c->msg, "<%s> %s is single-valued, ignoring", c->argv[0],
+ sprintf( c->cr_msg, "<%s> %s is single-valued, ignoring", c->argv[0],
vitmp.vi_ad->ad_cname.bv_val );
Debug( LDAP_DEBUG_ANY, "%s: %s (%s)!\n",
- c->log, c->msg, c->argv[1] );
+ c->log, c->cr_msg, c->argv[1] );
return(0);
}
is_numeric = ( vitmp.vi_ad->ad_type->sat_syntax == syn_numericString ||
ber_str2bv( c->argv[2], 0, 0, &bv );
i = dnNormalize( 0, NULL, NULL, &bv, &vitmp.vi_dn, NULL );
if ( i ) {
- sprintf( c->msg, "<%s> unable to normalize DN", c->argv[0] );
+ sprintf( c->cr_msg, "<%s> unable to normalize DN", c->argv[0] );
Debug( LDAP_DEBUG_ANY, "%s: %s (%s)!\n",
- c->log, c->msg, c->argv[2] );
+ c->log, c->cr_msg, c->argv[2] );
return(1);
}
i = verb_to_mask( c->argv[3], sorts );
if ( BER_BVISNULL( &sorts[i].word )) {
- sprintf( c->msg, "<%s> unrecognized sort type", c->argv[0] );
+ sprintf( c->cr_msg, "<%s> unrecognized sort type", c->argv[0] );
Debug( LDAP_DEBUG_ANY, "%s: %s (%s)!\n",
- c->log, c->msg, c->argv[3] );
+ c->log, c->cr_msg, c->argv[3] );
return(1);
}
vitmp.vi_sort = sorts[i].mask;
if ( sorts[i].mask == VALSORT_WEIGHTED && c->argc == 5 ) {
i = verb_to_mask( c->argv[4], sorts );
if ( BER_BVISNULL( &sorts[i].word )) {
- sprintf( c->msg, "<%s> unrecognized sort type", c->argv[0] );
+ sprintf( c->cr_msg, "<%s> unrecognized sort type", c->argv[0] );
Debug( LDAP_DEBUG_ANY, "%s: %s (%s)!\n",
- c->log, c->msg, c->argv[4] );
+ c->log, c->cr_msg, c->argv[4] );
return(1);
}
vitmp.vi_sort |= sorts[i].mask;
}
if (( vitmp.vi_sort & VALSORT_NUMERIC ) && !is_numeric ) {
- sprintf( c->msg, "<%s> numeric sort specified for non-numeric syntax",
+ sprintf( c->cr_msg, "<%s> numeric sort specified for non-numeric syntax",
c->argv[0] );
Debug( LDAP_DEBUG_ANY, "%s: %s (%s)!\n",
- c->log, c->msg, c->argv[1] );
+ c->log, c->cr_msg, c->argv[1] );
return(1);
}
vi = ch_malloc( sizeof(valsort_info) );
if ( !(vi->vi_sort & VALSORT_WEIGHTED ))
continue;
for (ml = op->orm_modlist; ml; ml=ml->sml_next ) {
+ /* Must be a Delete Attr op, so no values to consider */
+ if ( !ml->sml_values )
+ continue;
if ( ml->sml_desc == vi->vi_ad )
break;
}
static int
valsort_db_open(
- BackendDB *be
+ BackendDB *be,
+ ConfigReply *cr
)
{
return overlay_register_control( be, LDAP_CONTROL_VALSORT );
static int
valsort_destroy(
- BackendDB *be
+ BackendDB *be,
+ ConfigReply *cr
)
{
slap_overinst *on = (slap_overinst *)be->bd_info;
BerElement *ber = (BerElement *)&berbuf;
ber_int_t flag = 0;
- if ( ctrl->ldctl_value.bv_len == 0 ) {
- rs->sr_text = "valSort control value is empty (or absent)";
+ if ( BER_BVISNULL( &ctrl->ldctl_value )) {
+ rs->sr_text = "valSort control value is absent";
+ return LDAP_PROTOCOL_ERROR;
+ }
+
+ if ( BER_BVISEMPTY( &ctrl->ldctl_value )) {
+ rs->sr_text = "valSort control value is empty";
return LDAP_PROTOCOL_ERROR;
}
req_extended_s qext = op->oq_extended;
Modifications *ml;
slap_callback cb = { NULL, slap_null_cb, NULL, NULL };
- slap_callback cb2 = { NULL, slap_replog_cb, NULL, NULL };
int i, nhash;
char **hashes;
int rc;
BackendDB *op_be;
int freenewpw = 0;
- cb2.sc_next = &cb;
-
assert( ber_bvcmp( &slap_EXOP_MODIFY_PASSWD, &op->ore_reqoid ) == 0 );
if( op->o_dn.bv_len == 0 ) {
rc = rs->sr_err;
goto error_return;
}
- op->o_bd = select_backend( &op->o_req_ndn, 0, 1 );
+ op->o_bd = select_backend( &op->o_req_ndn, 1 );
} else {
ber_dupbv_x( &op->o_req_dn, &op->o_dn, op->o_tmpmemctx );
/* If we've got a glued backend, check the real backend */
op_be = op->o_bd;
if ( SLAP_GLUE_INSTANCE( op->o_bd )) {
- op->o_bd = select_backend( &op->o_req_ndn, 0, 0 );
+ op->o_bd = select_backend( &op->o_req_ndn, 0 );
}
if (backend_check_restrictions( op, rs,
slap_callback *sc = op->o_callback;
op->o_tag = LDAP_REQ_MODIFY;
- op->o_callback = &cb2;
+ op->o_callback = &cb;
op->orm_modlist = qpw->rs_mods;
- cb2.sc_private = qpw; /* let Modify know this was pwdMod,
+ op->orm_no_opattrs = 0;
+
+ cb.sc_private = qpw; /* let Modify know this was pwdMod,
* if it cares... */
rs->sr_err = op->o_bd->be_modify( op, rs );
LDAP_BEGIN_DECL
struct config_args_s; /* config.h */
+struct config_reply_s; /* config.h */
/*
* aci.c
LDAP_SLAPD_F (AttributeName *) str2anlist LDAP_P(( AttributeName *an,
char *str, const char *brkstr ));
+LDAP_SLAPD_F (void) anlist_free LDAP_P(( AttributeName *an,
+ int freename, void *ctx ));
+
LDAP_SLAPD_F (char **) anlist2charray_x LDAP_P((
AttributeName *an, int dup, void *ctx ));
LDAP_SLAPD_F (char **) anlist2charray LDAP_P(( AttributeName *an, int dup ));
LDAP_SLAPD_F (int) backend_add LDAP_P((BackendInfo *aBackendInfo));
LDAP_SLAPD_F (int) backend_num LDAP_P((Backend *be));
LDAP_SLAPD_F (int) backend_startup LDAP_P((Backend *be));
-LDAP_SLAPD_F (int) backend_startup_one LDAP_P((Backend *be));
+LDAP_SLAPD_F (int) backend_startup_one LDAP_P((Backend *be, struct config_reply_s *cr));
LDAP_SLAPD_F (int) backend_sync LDAP_P((Backend *be));
LDAP_SLAPD_F (int) backend_shutdown LDAP_P((Backend *be));
LDAP_SLAPD_F (int) backend_destroy LDAP_P((void));
LDAP_SLAPD_F (BackendInfo *) backend_info LDAP_P(( const char *type ));
LDAP_SLAPD_F (BackendDB *) backend_db_init LDAP_P(( const char *type,
- BackendDB *be, int idx ));
+ BackendDB *be, int idx, struct config_reply_s *cr ));
LDAP_SLAPD_F (void) backend_db_insert LDAP_P((BackendDB *bd, int idx));
LDAP_SLAPD_F (void) backend_db_move LDAP_P((BackendDB *bd, int idx));
LDAP_SLAPD_F (BackendDB *) select_backend LDAP_P((
struct berval * dn,
- int manageDSAit,
int noSubordinates ));
LDAP_SLAPD_F (int) be_issuffix LDAP_P(( Backend *be,
struct berval *suffix ));
+LDAP_SLAPD_F (int) be_issubordinate LDAP_P(( Backend *be,
+ struct berval *subordinate ));
LDAP_SLAPD_F (int) be_isroot LDAP_P(( Operation *op ));
LDAP_SLAPD_F (int) be_isroot_dn LDAP_P(( Backend *be, struct berval *ndn ));
LDAP_SLAPD_F (int) be_isroot_pw LDAP_P(( Operation *op ));
+LDAP_SLAPD_F (int) be_rootdn_bind LDAP_P(( Operation *op, SlapReply *rs ));
LDAP_SLAPD_F (int) be_slurp_update LDAP_P(( Operation *op ));
#define be_isupdate( op ) be_slurp_update( (op) )
LDAP_SLAPD_F (int) be_shadow_update LDAP_P(( Operation *op ));
LDAP_SLAPD_F (int) be_isupdate_dn LDAP_P(( Backend *be, struct berval *ndn ));
LDAP_SLAPD_F (struct berval *) be_root_dn LDAP_P(( Backend *be ));
-LDAP_SLAPD_F (int) be_entry_get_rw LDAP_P(( struct slap_op *o,
+LDAP_SLAPD_F (int) be_entry_get_rw LDAP_P(( Operation *o,
struct berval *ndn, ObjectClass *oc,
AttributeDescription *at, int rw, Entry **e ));
LDAP_SLAPD_F (int) be_entry_release_rw LDAP_P((
int ctrl,
BI_chk_controls fnc ));
+#ifdef SLAP_CONTROL_X_SESSION_TRACKING
+LDAP_SLAPD_F (int)
+slap_ctrl_session_tracking_add LDAP_P((
+ Operation *op,
+ SlapReply *rs,
+ struct berval *ip,
+ struct berval *name,
+ struct berval *id,
+ LDAPControl *ctrl ));
+LDAP_SLAPD_F (int)
+slap_ctrl_session_tracking_request_add LDAP_P((
+ Operation *op, SlapReply *rs, LDAPControl *ctrl ));
+#endif /* SLAP_CONTROL_X_SESSION_TRACKING */
+
/*
* config.c
*/
LDAP_SLAPD_F (void) connection_client_enable LDAP_P(( ber_socket_t s ));
LDAP_SLAPD_F (void) connection_client_stop LDAP_P(( ber_socket_t s ));
+#ifdef LDAP_PF_LOCAL_SENDMSG
+#define LDAP_PF_LOCAL_SENDMSG_ARG(arg) , arg
+#else
+#define LDAP_PF_LOCAL_SENDMSG_ARG(arg)
+#endif
-LDAP_SLAPD_F (long) connection_init LDAP_P((
+LDAP_SLAPD_F (Connection *) connection_init LDAP_P((
ber_socket_t s,
Listener* url,
const char* dnsname,
const char* peername,
int use_tls,
slap_ssf_t ssf,
- struct berval *id ));
+ struct berval *id
+ LDAP_PF_LOCAL_SENDMSG_ARG(struct berval *peerbv)));
LDAP_SLAPD_F (void) connection_closing LDAP_P((
Connection *c, const char *why ));
LDAP_SLAPD_F (void) connection2anonymous LDAP_P((Connection *));
LDAP_SLAPD_F (void) connection_fake_init LDAP_P((
Connection *conn,
- Operation *op,
+ OperationBuffer *opbuf,
void *threadctx ));
LDAP_SLAPD_F (void) connection_fake_init2 LDAP_P((
Connection *conn,
- Operation *op,
+ OperationBuffer *opbuf,
void *threadctx,
int newmem ));
LDAP_SLAPD_F (void) connection_assign_nextid LDAP_P((Connection *));
LDAP_SLAPD_F (Listener **) slapd_get_listeners LDAP_P((void));
LDAP_SLAPD_F (void) slapd_remove LDAP_P((ber_socket_t s, Sockbuf *sb,
int wasactive, int wake, int locked ));
-LDAP_SLAPD_F (void) slapd_sd_lock();
-LDAP_SLAPD_F (void) slapd_sd_unlock();
+LDAP_SLAPD_F (void) slapd_sd_lock LDAP_P((void));
+LDAP_SLAPD_F (void) slapd_sd_unlock LDAP_P((void));
LDAP_SLAPD_F (RETSIGTYPE) slap_sig_shutdown LDAP_P((int sig));
LDAP_SLAPD_F (RETSIGTYPE) slap_sig_wake LDAP_P((int sig));
LDAP_SLAPD_F (void) mru_destroy LDAP_P(( void ));
LDAP_SLAPD_F (int) matching_rule_use_init LDAP_P(( void ));
-LDAP_SLAPD_F (int) mr_schema_info( Entry *e );
-LDAP_SLAPD_F (int) mru_schema_info( Entry *e );
+LDAP_SLAPD_F (int) mr_schema_info LDAP_P(( Entry *e ));
+LDAP_SLAPD_F (int) mru_schema_info LDAP_P(( Entry *e ));
-LDAP_SLAPD_F (int) mr_usable_with_at( MatchingRule *mr,
- AttributeType *at );
+LDAP_SLAPD_F (int) mr_usable_with_at LDAP_P(( MatchingRule *mr,
+ AttributeType *at ));
+LDAP_SLAPD_F (int) mr_make_syntax_compat_with_mr LDAP_P((
+ Syntax *syn,
+ MatchingRule *mr ));
+LDAP_SLAPD_F (int) mr_make_syntax_compat_with_mrs LDAP_P((
+ const char *syntax,
+ char *const *mrs ));
/*
* mra.c
int *err,
const char **text ));
-/*
- * repl.c
- */
-LDAP_SLAPD_F (int) add_replica_info LDAP_P(( Backend *be,
- const char *uri, const char *host ));
-LDAP_SLAPD_F (int) destroy_replica_info LDAP_P (( Backend *be ));
-LDAP_SLAPD_F (int) add_replica_suffix LDAP_P(( Backend *be,
- int nr, const char *suffix ));
-LDAP_SLAPD_F (int) add_replica_attrs LDAP_P(( Backend *be,
- int nr, char *attrs, int exclude ));
-LDAP_SLAPD_F (void) replog LDAP_P(( Operation *op ));
-
/*
* result.c
*/
LDAP_SLAPD_F (int) slap_send_search_entry LDAP_P(( Operation *op, SlapReply *rs ));
LDAP_SLAPD_F (int) slap_null_cb LDAP_P(( Operation *op, SlapReply *rs ));
LDAP_SLAPD_F (int) slap_freeself_cb LDAP_P(( Operation *op, SlapReply *rs ));
-LDAP_SLAPD_F (int) slap_replog_cb LDAP_P(( Operation *op, SlapReply *rs ));
LDAP_SLAPD_V( const struct berval ) slap_pre_read_bv;
LDAP_SLAPD_V( const struct berval ) slap_post_read_bv;
LDAP_SLAPD_F( slap_mr_filter_func ) octetStringFilter;
LDAP_SLAPD_F( int ) numericoidValidate LDAP_P((
- struct slap_syntax *syntax,
+ Syntax *syntax,
struct berval *in ));
+LDAP_SLAPD_F( int ) numericStringValidate LDAP_P((
+ Syntax *syntax,
+ struct berval *in ));
LDAP_SLAPD_F( int ) octetStringMatch LDAP_P((
int *matchp,
slap_mask_t flags,
MatchingRule *mr,
struct berval *value,
void *assertedValue ));
+LDAP_SLAPD_F( int ) octetStringOrderingMatch LDAP_P((
+ int *matchp,
+ slap_mask_t flags,
+ Syntax *syntax,
+ MatchingRule *mr,
+ struct berval *value,
+ void *assertedValue ));
/*
* schema_prep.c
LDAP_SLAPD_F (void) syncinfo_free LDAP_P(( struct syncinfo_s *, int all ));
/* syntax.c */
+LDAP_SLAPD_F (int) syn_is_sup LDAP_P((
+ Syntax *syn,
+ Syntax *sup ));
LDAP_SLAPD_F (Syntax *) syn_find LDAP_P((
const char *synname ));
LDAP_SLAPD_F (Syntax *) syn_find_desc LDAP_P((
LDAP_SLAPD_V (int) slap_tool_thread_max;
LDAP_SLAPD_V (ldap_pvt_thread_mutex_t) entry2str_mutex;
-LDAP_SLAPD_V (ldap_pvt_thread_mutex_t) replog_mutex;
LDAP_SLAPD_V (ldap_pvt_thread_mutex_t) gmtime_mutex;
} while ( 0 )
#else
-# if USE_MP_LONG_LONG
+# ifdef USE_MP_LONG_LONG
# define UI2BV_FORMAT "%llu"
-# elif USE_MP_LONG
+# elif defined USE_MP_LONG
# define UI2BV_FORMAT "%lu"
-# elif HAVE_LONG_LONG
+# elif defined HAVE_LONG_LONG
# define UI2BV_FORMAT "%llu"
# else
# define UI2BV_FORMAT "%lu"
+++ /dev/null
-/* repl.c - log modifications for replication purposes */
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 1998-2007 The OpenLDAP Foundation.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted only as authorized by the OpenLDAP
- * Public License.
- *
- * A copy of this license is available in the file LICENSE in the
- * top-level directory of the distribution or, alternatively, at
- * <http://www.OpenLDAP.org/license.html>.
- */
-/* Portions Copyright (c) 1995 Regents of the University of Michigan.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that this notice is preserved and that due credit is given
- * to the University of Michigan at Ann Arbor. The name of the University
- * may not be used to endorse or promote products derived from this
- * software without specific prior written permission. This software
- * is provided ``as is'' without express or implied warranty.
- */
-
-#include "portable.h"
-
-#include <stdio.h>
-
-#include <ac/string.h>
-#include <ac/ctype.h>
-#include <ac/socket.h>
-
-#ifdef HAVE_SYS_FILE_H
-#include <sys/file.h>
-#endif
-
-#include "slap.h"
-#include "ldif.h"
-
-int
-add_replica_info(
- Backend *be,
- const char *uri,
- const char *host )
-{
- int i = 0;
-
- assert( be != NULL );
- assert( host != NULL );
-
- if ( be->be_replica != NULL ) {
- for ( ; be->be_replica[ i ] != NULL; i++ );
- }
-
- be->be_replica = ch_realloc( be->be_replica,
- sizeof( struct slap_replica_info * )*( i + 2 ) );
-
- be->be_replica[ i ]
- = ch_calloc( sizeof( struct slap_replica_info ), 1 );
- ber_str2bv( uri, 0, 0, &be->be_replica[ i ]->ri_bindconf.sb_uri );
- be->be_replica[ i ]->ri_host = host;
- be->be_replica[ i ]->ri_nsuffix = NULL;
- be->be_replica[ i ]->ri_attrs = NULL;
- be->be_replica[ i + 1 ] = NULL;
-
- return( i );
-}
-
-int
-destroy_replica_info(
- Backend *be )
-{
- int i = 0;
-
- assert( be != NULL );
-
- if ( be->be_replica == NULL ) {
- return 0;
- }
-
- for ( ; be->be_replica[ i ] != NULL; i++ ) {
- ber_bvarray_free( be->be_replica[ i ]->ri_nsuffix );
-
- if ( be->be_replica[ i ]->ri_attrs ) {
- AttributeName *an = be->be_replica[ i ]->ri_attrs;
- int j;
-
- for ( j = 0; !BER_BVISNULL( &an[ j ].an_name ); j++ )
- {
- ch_free( an[ j ].an_name.bv_val );
- }
- ch_free( an );
- }
-
- bindconf_free( &be->be_replica[ i ]->ri_bindconf );
-
- ch_free( be->be_replica[ i ] );
- }
-
- ch_free( be->be_replica );
-
- return 0;
-}
-
-int
-add_replica_suffix(
- Backend *be,
- int nr,
- const char *suffix
-)
-{
- struct berval dn, ndn;
- int rc;
-
- dn.bv_val = (char *) suffix;
- dn.bv_len = strlen( dn.bv_val );
-
- rc = dnNormalize( 0, NULL, NULL, &dn, &ndn, NULL );
- if( rc != LDAP_SUCCESS ) {
- return 2;
- }
-
- if ( select_backend( &ndn, 0, 0 ) != be ) {
- free( ndn.bv_val );
- return 1;
- }
-
- ber_bvarray_add( &be->be_replica[nr]->ri_nsuffix, &ndn );
- return 0;
-}
-
-int
-add_replica_attrs(
- Backend *be,
- int nr,
- char *attrs,
- int exclude
-)
-{
- if ( be->be_replica[nr]->ri_attrs != NULL ) {
- if ( be->be_replica[nr]->ri_exclude != exclude ) {
- fprintf( stderr, "attr selective replication directive '%s' conflicts with previous one (discarded)\n", attrs );
- ch_free( be->be_replica[nr]->ri_attrs );
- be->be_replica[nr]->ri_attrs = NULL;
- }
- }
-
- be->be_replica[nr]->ri_exclude = exclude;
- be->be_replica[nr]->ri_attrs = str2anlist( be->be_replica[nr]->ri_attrs,
- attrs, "," );
- return ( be->be_replica[nr]->ri_attrs == NULL );
-}
-
-static void
-print_vals( FILE *fp, struct berval *type, struct berval *bv );
-static void
-replog1( struct slap_replica_info *ri, Operation *op, FILE *fp, long now);
-
-void
-replog( Operation *op )
-{
- FILE *fp, *lfp;
- int i;
-/* undef NO_LOG_WHEN_NO_REPLICAS */
-#ifdef NO_LOG_WHEN_NO_REPLICAS
- int count = 0;
-#endif /* NO_LOG_WHEN_NO_REPLICAS */
- int subsets = 0;
- long now = slap_get_time();
- char *replogfile;
-
- replogfile = op->o_bd->be_replogfile ? op->o_bd->be_replogfile :
- frontendDB->be_replogfile;
- if ( !replogfile ) {
- return;
- }
-
- ldap_pvt_thread_mutex_lock( &replog_mutex );
- if ( (fp = lock_fopen( replogfile, "a", &lfp )) == NULL ) {
- ldap_pvt_thread_mutex_unlock( &replog_mutex );
- return;
- }
-
- for ( i = 0; op->o_bd->be_replica != NULL && op->o_bd->be_replica[i] != NULL; i++ ) {
- /* check if dn's suffix matches legal suffixes, if any */
- if ( op->o_bd->be_replica[i]->ri_nsuffix != NULL ) {
- int j;
-
- for ( j = 0; op->o_bd->be_replica[i]->ri_nsuffix[j].bv_val; j++ ) {
- if ( dnIsSuffix( &op->o_req_ndn, &op->o_bd->be_replica[i]->ri_nsuffix[j] ) ) {
- break;
- }
- }
-
- if ( !op->o_bd->be_replica[i]->ri_nsuffix[j].bv_val ) {
- /* do not add "replica:" line */
- continue;
- }
- }
- /* See if we only want a subset of attributes */
- if ( op->o_bd->be_replica[i]->ri_attrs != NULL &&
- ( op->o_tag == LDAP_REQ_MODIFY || op->o_tag == LDAP_REQ_ADD || op->o_tag == LDAP_REQ_EXTENDED ) ) {
- if ( !subsets ) {
- subsets = i + 1;
- }
- /* Do attribute subsets by themselves in a second pass */
- continue;
- }
-
- fprintf( fp, "replica: %s\n", op->o_bd->be_replica[i]->ri_host );
-#ifdef NO_LOG_WHEN_NO_REPLICAS
- ++count;
-#endif /* NO_LOG_WHEN_NO_REPLICAS */
- }
-
-#ifdef NO_LOG_WHEN_NO_REPLICAS
- if ( count == 0 && subsets == 0 ) {
- /* if no replicas matched, drop the log
- * (should we log it anyway?) */
- lock_fclose( fp, lfp );
- ldap_pvt_thread_mutex_unlock( &replog_mutex );
-
- return;
- }
-#endif /* NO_LOG_WHEN_NO_REPLICAS */
-
- replog1( NULL, op, fp, now );
-
- if ( subsets > 0 ) {
- for ( i = subsets - 1; op->o_bd->be_replica[i] != NULL; i++ ) {
-
- /* If no attrs, we already did this above */
- if ( op->o_bd->be_replica[i]->ri_attrs == NULL ) {
- continue;
- }
-
- /* check if dn's suffix matches legal suffixes, if any */
- if ( op->o_bd->be_replica[i]->ri_nsuffix != NULL ) {
- int j;
-
- for ( j = 0; op->o_bd->be_replica[i]->ri_nsuffix[j].bv_val; j++ ) {
- if ( dnIsSuffix( &op->o_req_ndn, &op->o_bd->be_replica[i]->ri_nsuffix[j] ) ) {
- break;
- }
- }
-
- if ( !op->o_bd->be_replica[i]->ri_nsuffix[j].bv_val ) {
- /* no matching suffix found, skip it */
- continue;
- }
- }
- switch( op->o_tag ) {
- case LDAP_REQ_EXTENDED:
- /* quick hack for extended operations */
- /* assume change parameter is a Modifications* */
- /* fall thru */
- case LDAP_REQ_MODIFY:
- case LDAP_REQ_ADD:
- break;
- default:
- /* Other operations were logged in the first pass */
- continue;
- }
- replog1( op->o_bd->be_replica[i], op, fp, now );
- }
- }
-
- lock_fclose( fp, lfp );
- ldap_pvt_thread_mutex_unlock( &replog_mutex );
-}
-
-static void
-rephdr(
- struct slap_replica_info *ri,
- Operation *op,
- FILE *fp,
- long now
-)
-{
- if ( ri ) {
- fprintf( fp, "replica: %s\n", ri->ri_host );
- }
- fprintf( fp, "time: %ld\n", now );
- fprintf( fp, "dn: %s\n", op->o_req_dn.bv_val );
-}
-
-static void
-replog1(
- struct slap_replica_info *ri,
- Operation *op,
- FILE *fp,
- long now
-)
-{
- Modifications *ml;
- Attribute *a;
- AttributeName *an;
- int dohdr = 1, ocs = -1;
- struct berval vals[2];
-
- vals[1].bv_val = NULL;
- vals[1].bv_len = 0;
-
- switch ( op->o_tag ) {
- case LDAP_REQ_EXTENDED:
- /* quick hack for extended operations */
- /* assume change parameter is a Modifications* */
- /* fall thru */
-
- case LDAP_REQ_MODIFY:
- for ( ml = op->orm_modlist; ml != NULL; ml = ml->sml_next ) {
- char *did = NULL, *type = ml->sml_desc->ad_cname.bv_val;
- switch ( ml->sml_op ) {
- case LDAP_MOD_ADD:
- did = "add"; break;
-
- case LDAP_MOD_DELETE:
- did = "delete"; break;
-
- case LDAP_MOD_REPLACE:
- did = "replace"; break;
-
- case LDAP_MOD_INCREMENT:
- did = "increment"; break;
- }
- if ( ri && ri->ri_attrs ) {
- int is_in = ad_inlist( ml->sml_desc, ri->ri_attrs );
-
- /* skip if:
- * 1) the attribute is not in the list,
- * and it's not an exclusion list
- * 2) the attribute is in the list
- * and it's an exclusion list,
- * and either the objectClass attribute
- * has already been dealt with or
- * this is not the objectClass attr
- */
- if ( ( !is_in && !ri->ri_exclude )
- || ( ( is_in && ri->ri_exclude )
- && ( !ocs || ml->sml_desc != slap_schema.si_ad_objectClass ) ) )
- {
- continue;
- }
-
- /* If this is objectClass, see if the value is included
- * in any subset, otherwise drop it.
- */
- if ( ocs && ml->sml_desc == slap_schema.si_ad_objectClass
- && ml->sml_values )
- {
- int i, first = 1;
-
- if ( ocs == -1 ) ocs = 0;
-
- for ( i=0; ml->sml_values[i].bv_val; i++ ) {
- int match = 0;
- for ( an = ri->ri_attrs; an->an_name.bv_val; an++ ) {
- if ( an->an_oc ) {
- struct berval bv = an->an_name;
-
- ocs = 1;
- match |= an->an_oc_exclude;
-
- switch ( bv.bv_val[ 0 ] ) {
- case '@':
- case '+':
- case '!':
- bv.bv_val++;
- bv.bv_len--;
- break;
- }
-
- if ( ml->sml_values[i].bv_len == bv.bv_len
- && !strcasecmp(ml->sml_values[i].bv_val,
- bv.bv_val ) )
- {
- match = !an->an_oc_exclude;
- break;
- }
- }
- }
- /* Objectclasses need no special treatment, drop into
- * regular processing
- */
- if ( !ocs ) break;
-
- match ^= ri->ri_exclude;
- /* Found a match, log it */
- if ( match ) {
- if ( dohdr ) {
- rephdr( ri, op, fp, now );
- fprintf( fp, "changetype: modify\n" );
- dohdr = 0;
- }
- if ( first ) {
- fprintf( fp, "%s: %s\n", did, type );
- first = 0;
- }
- vals[0] = ml->sml_values[i];
- print_vals( fp, &ml->sml_desc->ad_cname, vals );
- ocs = 2;
- }
-
- }
- /* Explicit objectclasses have been handled already */
- if ( ocs ) {
- if ( ocs == 2 ) {
- fprintf( fp, "-\n" );
- }
- continue;
- }
- }
- }
- if ( dohdr ) {
- rephdr( ri, op, fp, now );
- fprintf( fp, "changetype: modify\n" );
- dohdr = 0;
- }
- fprintf( fp, "%s: %s\n", did, type );
- if ( ml->sml_values ) {
- print_vals( fp, &ml->sml_desc->ad_cname, ml->sml_values );
- }
- fprintf( fp, "-\n" );
- }
- break;
-
- case LDAP_REQ_ADD:
- for ( a = op->ora_e->e_attrs ; a != NULL; a=a->a_next ) {
- if ( ri && ri->ri_attrs ) {
- int is_in = ad_inlist( a->a_desc, ri->ri_attrs );
-
- /* skip if:
- * 1) the attribute is not in the list,
- * and it's not an exclusion list
- * 2) the attribute is in the list
- * and it's an exclusion list,
- * and either the objectClass attribute
- * has already been dealt with or
- * this is not the objectClass attr
- */
- if ( ( !is_in && !ri->ri_exclude )
- || ( ( is_in && ri->ri_exclude )
- && ( !ocs || a->a_desc != slap_schema.si_ad_objectClass ) ) )
- {
- continue;
- }
-
- /* If the list includes objectClass names,
- * only include those classes in the
- * objectClass attribute
- */
- if ( ocs && a->a_desc == slap_schema.si_ad_objectClass ) {
- int i;
-
- if ( ocs == -1 ) ocs = 0;
-
- for ( i=0; a->a_vals[i].bv_val; i++ ) {
- int match = 0;
- for ( an = ri->ri_attrs; an->an_name.bv_val; an++ ) {
- if ( an->an_oc ) {
- struct berval bv = an->an_name;
-
- ocs = 1;
- match |= an->an_oc_exclude;
-
- switch ( bv.bv_val[ 0 ] ) {
- case '@':
- case '+':
- case '!':
- bv.bv_val++;
- bv.bv_len--;
- break;
- }
-
- if ( a->a_vals[i].bv_len == bv.bv_len
- && !strcasecmp(a->a_vals[i].bv_val,
- bv.bv_val ) )
- {
- match = !an->an_oc_exclude;
- break;
- }
- }
- }
- if ( !ocs ) break;
-
- match ^= ri->ri_exclude;
- if ( match ) {
- if ( dohdr ) {
- rephdr( ri, op, fp, now );
- fprintf( fp, "changetype: add\n" );
- dohdr = 0;
- }
- vals[0] = a->a_nvals[i];
- print_vals( fp, &a->a_desc->ad_cname, vals );
- }
- }
- if ( ocs ) continue;
- }
- }
- if ( dohdr ) {
- rephdr( ri, op, fp, now );
- fprintf( fp, "changetype: add\n" );
- dohdr = 0;
- }
- print_vals( fp, &a->a_desc->ad_cname, a->a_vals );
- }
- break;
-
- case LDAP_REQ_DELETE:
- rephdr( ri, op, fp, now );
- fprintf( fp, "changetype: delete\n" );
- break;
-
- case LDAP_REQ_MODRDN:
- rephdr( ri, op, fp, now );
- fprintf( fp, "changetype: modrdn\n" );
- fprintf( fp, "newrdn: %s\n", op->orr_newrdn.bv_val );
- fprintf( fp, "deleteoldrdn: %d\n", op->orr_deleteoldrdn ? 1 : 0 );
- if( op->orr_newSup != NULL ) {
- fprintf( fp, "newsuperior: %s\n", op->orr_newSup->bv_val );
- }
- }
- fprintf( fp, "\n" );
-}
-
-static void
-print_vals(
- FILE *fp,
- struct berval *type,
- struct berval *bv )
-{
- ber_len_t i, len;
- char *buf, *bufp;
-
- for ( i = 0, len = 0; bv && bv[i].bv_val; i++ ) {
- if ( bv[i].bv_len > len )
- len = bv[i].bv_len;
- }
-
- len = LDIF_SIZE_NEEDED( type->bv_len, len ) + 1;
- buf = (char *) ch_malloc( len );
-
- for ( ; bv && bv->bv_val; bv++ ) {
- bufp = buf;
- ldif_sput( &bufp, LDIF_PUT_VALUE, type->bv_val,
- bv->bv_val, bv->bv_len );
- *bufp = '\0';
-
- fputs( buf, fp );
-
- }
- free( buf );
-}
return SLAP_CB_CONTINUE;
}
-int slap_replog_cb( Operation *op, SlapReply *rs )
-{
- if ( rs->sr_err == LDAP_SUCCESS ) {
- replog( op );
- }
- return SLAP_CB_CONTINUE;
-}
-
static char *v2ref( BerVarray ref, const char *text )
{
size_t len = 0, i = 0;
if( rc == -1 ) return rc;
}
-#ifdef SLAP_SORTED_RESULTS
+#ifdef SLAP_CONTROL_X_SORTEDRESULTS
/* this is a hack to avoid having to modify op->s_ctrls */
if( o->o_sortedresults ) {
BerElementBuffer berbuf;
} else {
rs->sr_rspoid = LDAP_NOTICE_DISCONNECT;
rs->sr_tag = LDAP_RES_EXTENDED;
- rs->sr_msgid = 0;
+ rs->sr_msgid = LDAP_RES_UNSOLICITED;
}
if ( send_ldap_response( op, rs ) == SLAP_CB_CONTINUE ) {
cb.sc_private = &sl;
- op.o_bd = select_backend( &op.o_req_ndn, 0, 1 );
+ op.o_bd = select_backend( &op.o_req_ndn, 1 );
if ( op.o_bd ) {
/* For rootdn, see if we can use the rootpw */
}
if (!conn || !op.o_req_ndn.bv_val) return SASL_BADPARAM;
- op.o_bd = select_backend( &op.o_req_ndn, 0, 1 );
+ op.o_bd = select_backend( &op.o_req_ndn, 1 );
if ( !op.o_bd || !op.o_bd->be_modify ) return SASL_FAIL;
*/
if ( flags == SASL_CU_AUTHID && !auxvals[SLAP_SASL_PROP_AUTHZ].values ) {
conn->c_sasl_dn.bv_val = (char *) in;
+ conn->c_sasl_dn.bv_len = 0;
} else if ( flags == SASL_CU_AUTHZID && conn->c_sasl_dn.bv_val ) {
rc = strcmp( in, conn->c_sasl_dn.bv_val );
conn->c_sasl_dn.bv_val = NULL;
if ( rc != LDAP_SUCCESS ) {
sasl_seterror( sconn, 0, ldap_err2string( rc ) );
return SASL_NOAUTHZ;
- }
+ }
names[0] = slap_propnames[which];
names[1] = NULL;
prop_set( props, names[0], (char *)&dn, sizeof( dn ) );
-
+
Debug( LDAP_DEBUG_ARGS, "SASL Canonicalize [conn=%ld]: %s=\"%s\"\n",
conn ? conn->c_connid : -1, names[0]+1,
dn.bv_val ? dn.bv_val : "<EMPTY>" );
ok:
if (conn->c_sasl_bindop) {
Statslog( LDAP_DEBUG_STATS,
- "conn=%lu op=%lu BIND authcid=\"%s\" authzid=\"%s\"\n",
- conn->c_connid, conn->c_sasl_bindop->o_opid,
- auth_identity, requested_user, 0);
+ "%s BIND authcid=\"%s\" authzid=\"%s\"\n",
+ conn->c_sasl_bindop->o_log_prefix,
+ auth_identity, requested_user, 0, 0 );
}
Debug( LDAP_DEBUG_TRACE, "SASL Authorize [conn=%ld]: "
if ( conn->c_sasl_bindop ) {
Statslog( LDAP_DEBUG_STATS,
- "conn=%lu op=%lu BIND authcid=\"%s\" authzid=\"%s\"\n",
- conn->c_connid, conn->c_sasl_bindop->o_opid,
- authcid, authzid ? authzid : "", 0);
+ "%s BIND authcid=\"%s\" authzid=\"%s\"\n",
+ conn->c_sasl_bindop->o_log_prefix,
+ authcid, authzid ? authzid : "", 0, 0 );
}
*errstr = NULL;
int rc;
thrctx = ldap_pvt_thread_pool_context();
- op = (Operation *)&opbuf;
- connection_fake_init2( &conn, op, thrctx, 0 );
+ connection_fake_init2( &conn, &opbuf, thrctx, 0 );
+ op = &opbuf.ob_op;
op->o_tag = LDAP_REQ_SEARCH;
op->o_req_dn = op->o_req_ndn = sl->base;
- op->o_bd = select_backend( &op->o_req_ndn, 0, 1 );
+ op->o_bd = select_backend( &op->o_req_ndn, 1 );
if ( !op->o_bd ) {
return REWRITE_ERR;
}
ptr = op->ors_filterstr.bv_val = op->o_tmpalloc( rc + 1, op->o_tmpmemctx );
if ( sl->filter.bv_len ) {
ptr = lutil_strcopy( ptr, sl->filter.bv_val );
+ } else {
+ *ptr = '\0';
+ }
+ if ( filter ) {
+ strcpy( ptr, filter );
}
- strcpy( ptr, filter );
op->ors_filter = str2filter_x( op, op->ors_filterstr.bv_val );
if ( !op->ors_filter ) {
op->o_tmpfree( op->ors_filterstr.bv_val, op->o_tmpmemctx );
sprintf( version, "%u.%d.%d", (unsigned)rc >> 24, (rc >> 16) & 0xff,
rc & 0xffff );
Debug( LDAP_DEBUG_ANY, "slap_sasl_init: SASL library version mismatch:"
- " expected " SASL_VERSION_STRING ","
- " got %s\n", version, 0, 0 );
+ " expected %s, got %s\n",
+ SASL_VERSION_STRING, version, 0 );
return -1;
}
#endif
send_ldap_sasl( op, rs );
} else {
+ if ( op->o_conn->c_sasl_dn.bv_len )
+ ch_free( op->o_conn->c_sasl_dn.bv_val );
+ BER_BVZERO( &op->o_conn->c_sasl_dn );
#if SASL_VERSION_MAJOR >= 2
rs->sr_text = sasl_errdetail( ctx );
#endif
"slap_sasl_match: performing internal search (base=%s, scope=%d)\n",
op.o_req_ndn.bv_val, op.ors_scope, 0 );
- op.o_bd = select_backend( &op.o_req_ndn, 0, 1 );
+ op.o_bd = select_backend( &op.o_req_ndn, 1 );
if(( op.o_bd == NULL ) || ( op.o_bd->be_search == NULL)) {
rc = LDAP_INAPPROPRIATE_AUTH;
goto CONCLUDED;
}
/* Must do an internal search */
- op.o_bd = select_backend( &op.o_req_ndn, 0, 1 );
+ op.o_bd = select_backend( &op.o_req_ndn, 1 );
switch ( op.ors_scope ) {
case LDAP_X_SCOPE_EXACT:
SUBSTR caseIgnoreSubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.44{64} )
-attributetype ( 2.5.4.6 NAME ( 'c' 'countryName' )
+# RFC 4519 definition (cannot be loaded because SYNTAX conflicts
+# with that of name).
+#
+attributetype ( 2.5.4.6 NAME 'c'
DESC 'RFC2256: ISO-3166 country 2-letter code'
- SUP name SINGLE-VALUE )
+ SUP name
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.11
+ SINGLE-VALUE )
+
+#attributetype ( 2.5.4.6 NAME ( 'c' 'countryName' )
+# DESC 'RFC2256: ISO-3166 country 2-letter code'
+# SUP name SINGLE-VALUE )
attributetype ( 2.5.4.7 NAME ( 'l' 'localityName' )
DESC 'RFC2256: locality which this object resides in'
# between structural and auxiliary classes. This fact is noted here:
# http://forum.java.sun.com/thread.jspa?threadID=5016864&messageID=9034636
#
-# In accordance with the actual usage in practice, we define it as an
-# auxiliary class.
+# In accordance with other existing implementations, we define it as a
+# structural class.
#
# Our definition of memberURL also does not match theirs but again
# their published definition and what works in practice do not agree.
# In other words, the Netscape definitions are broken and interoperability
# is not guaranteed.
#
+# Also see the new DynGroup proposed spec at
+# http://tools.ietf.org/html/draft-haripriya-dynamicgroup-02
objectIdentifier NetscapeRoot 2.16.840.1.113730
objectIdentifier NetscapeLDAPattributeType NetscapeLDAP:1
objectIdentifier NetscapeLDAPobjectClass NetscapeLDAP:2
+objectIdentifier OpenLDAPExp11 1.3.6.1.4.1.4203.666.11
+objectIdentifier DynGroupBase OpenLDAPExp11:8
+objectIdentifier DynGroupAttr DynGroupBase:1
+objectIdentifier DynGroupOC DynGroupBase:2
+
attributetype ( NetscapeLDAPattributeType:198
NAME 'memberURL'
DESC 'Identifies an URL associated with each member of a group. Any type of labeled URL can be used.'
SUP labeledURI )
+attributetype ( DynGroupAttr:1
+ NAME 'dgIdentity'
+ DESC 'Identity to use when processing the memberURL'
+ SUP distinguishedName SINGLE-VALUE )
+
objectClass ( NetscapeLDAPobjectClass:33
NAME 'groupOfURLs'
SUP top STRUCTURAL
MUST cn
MAY ( memberURL $ businessCategory $ description $ o $ ou $
owner $ seeAlso ) )
+
+# The Haripriya dyngroup schema still needs a lot of work.
+# We're just adding support for the dgIdentity attribute for now...
+objectClass ( DynGroupOC:1
+ NAME 'dgIdentityAux'
+ SUP top AUXILIARY
+ MAY dgIdentity )
e->e_dn, textbuf, 0 );
rc = LDAP_OBJECT_CLASS_VIOLATION;
- goto leave;
+ goto done;
}
if( sc->soc_kind != LDAP_SCHEMA_STRUCTURAL ) {
e->e_dn, textbuf, 0 );
rc = LDAP_OTHER;
- goto leave;
+ goto done;
}
got_soc:
e->e_dn, textbuf, 0 );
rc = LDAP_OBJECT_CLASS_VIOLATION;
- goto leave;
+ goto done;
}
*text = textbuf;
"unrecognized objectClass '%s'",
aoc->a_vals[0].bv_val );
rc = LDAP_OBJECT_CLASS_VIOLATION;
- goto leave;
+ goto done;
} else if ( sc != slap_schema.si_oc_glue && sc != oc ) {
snprintf( textbuf, textlen,
"from '%s' to '%s' not allowed",
asc->a_vals[0].bv_val, oc->soc_cname.bv_val );
rc = LDAP_NO_OBJECT_CLASS_MODS;
- goto leave;
+ goto done;
} else if ( sc == slap_schema.si_oc_glue ) {
sc = oc;
}
if ( !is_entry_glue ( e ) ) {
rc = entry_naming_check( e, manage, text, textbuf, textlen );
if( rc != LDAP_SUCCESS ) {
- goto leave;
+ goto done;
}
} else {
/* Glue Entry */
e->e_dn, textbuf, 0 );
rc = LDAP_OBJECT_CLASS_VIOLATION;
- goto leave;
+ goto done;
}
if( cr->scr_required ) for( i=0; cr->scr_required[i]; i++ ) {
e->e_dn, textbuf, 0 );
rc = LDAP_OBJECT_CLASS_VIOLATION;
- goto leave;
+ goto done;
}
}
e->e_dn, textbuf, 0 );
rc = LDAP_OBJECT_CLASS_VIOLATION;
- goto leave;
+ goto done;
}
}
}
e->e_dn, textbuf, 0 );
rc = LDAP_OBJECT_CLASS_VIOLATION;
- goto leave;
+ goto done;
}
if ( oc->soc_check ) {
rc = (oc->soc_check)( op->o_bd, e, oc,
text, textbuf, textlen );
if( rc != LDAP_SUCCESS ) {
- goto leave;
+ goto done;
}
}
e->e_dn, textbuf, 0 );
rc = LDAP_OBJECT_CLASS_VIOLATION;
- goto leave;
+ goto done;
}
}
e->e_dn, textbuf, 0 );
rc = LDAP_OBJECT_CLASS_VIOLATION;
- goto leave;
+ goto done;
}
}
e->e_dn, textbuf, 0 );
rc = LDAP_OBJECT_CLASS_VIOLATION;
- goto leave;
+ goto done;
}
if( oc == slap_schema.si_oc_extensibleObject ) {
if( extensible ) {
*text = NULL;
rc = LDAP_SUCCESS;
- goto leave;
+ goto done;
}
/* check that each attr in the entry is allowed by some oc */
"Entry (%s), %s\n",
e->e_dn, textbuf, 0 );
- goto leave;
+ goto done;
}
}
*text = NULL;
-leave:
+done:
slap_sl_free( socs, op->o_tmpmemctx );
return rc;
}
for ( i = 0; socs[i]; i++ ) {
/* if we know about the oc */
ObjectClass *oc = socs[i];
+ /* extensibleObject allows all */
+ if ( oc == slap_schema.si_oc_extensibleObject ) {
+ return LDAP_SUCCESS;
+ }
if ( oc != NULL && oc->soc_kind != LDAP_SCHEMA_ABSTRACT &&
( sc == NULL || oc->soc_kind == LDAP_SCHEMA_AUXILIARY ))
{
#include <ac/socket.h>
#include "slap.h"
+#include "../../libraries/liblber/lber-int.h" /* get ber_ptrlen() */
#include "ldap_utf8.h"
-#ifdef HAVE_TLS
-#include <openssl/x509.h>
-#include <openssl/err.h>
-#include <openssl/rsa.h>
-#include <openssl/crypto.h>
-#include <openssl/pem.h>
-#include <openssl/bio.h>
-#include <openssl/asn1.h>
-#include <openssl/x509v3.h>
-#include <openssl/ssl.h>
-#endif
-
#include "lutil.h"
#include "lutil_hash.h"
#define HASH_BYTES LUTIL_HASH_BYTES
#define IA5StringApproxFilter approxFilter
/* Change Sequence Number (CSN) - much of this will change */
-#define csnValidate blobValidate
#define csnMatch octetStringMatch
#define csnOrderingMatch octetStringOrderingMatch
#define csnIndexer generalizedTimeIndexer
ldap_pvt_thread_mutex_t ad_undef_mutex;
ldap_pvt_thread_mutex_t oc_undef_mutex;
+static int
+generalizedTimeValidate(
+ Syntax *syntax,
+ struct berval *in );
+
static int
inValidate(
Syntax *syntax,
return LDAP_SUCCESS;
}
+/* X.509 related stuff */
+
+enum {
+ SLAP_X509_V1 = 0,
+ SLAP_X509_V2 = 1,
+ SLAP_X509_V3 = 2
+};
-#ifdef HAVE_TLS
+#define SLAP_X509_OPTION (LBER_CLASS_CONTEXT|LBER_CONSTRUCTED)
+
+enum {
+ SLAP_X509_OPT_C_VERSION = SLAP_X509_OPTION + 0,
+ SLAP_X509_OPT_C_ISSUERUNIQUEID = SLAP_X509_OPTION + 1,
+ SLAP_X509_OPT_C_SUBJECTUNIQUEID = SLAP_X509_OPTION + 2,
+ SLAP_X509_OPT_C_EXTENSIONS = SLAP_X509_OPTION + 3
+};
+
+enum {
+ SLAP_X509_OPT_CL_CRLEXTENSIONS = SLAP_X509_OPTION + 0
+};
+
+/* X.509 certificate validation */
static int certificateValidate( Syntax *syntax, struct berval *in )
{
- X509 *xcert=NULL;
- unsigned char *p = (unsigned char *)in->bv_val;
-
- xcert = d2i_X509(NULL, &p, in->bv_len);
- if ( !xcert ) return LDAP_INVALID_SYNTAX;
- X509_free(xcert);
+ BerElementBuffer berbuf;
+ BerElement *ber = (BerElement *)&berbuf;
+ ber_tag_t tag;
+ ber_len_t len;
+ ber_int_t version = SLAP_X509_V1;
+
+ ber_init2( ber, in, LBER_USE_DER );
+ tag = ber_skip_tag( ber, &len ); /* Signed wrapper */
+ if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
+ tag = ber_skip_tag( ber, &len ); /* Sequence */
+ if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
+ tag = ber_peek_tag( ber, &len );
+ /* Optional version */
+ if ( tag == SLAP_X509_OPT_C_VERSION ) {
+ tag = ber_skip_tag( ber, &len );
+ tag = ber_get_int( ber, &version );
+ if ( tag != LBER_INTEGER ) return LDAP_INVALID_SYNTAX;
+ }
+ /* NOTE: don't try to parse Serial, because it might be longer
+ * than sizeof(ber_int_t); deferred to certificateExactNormalize() */
+ tag = ber_skip_tag( ber, &len ); /* Serial */
+ if ( tag != LBER_INTEGER ) return LDAP_INVALID_SYNTAX;
+ ber_skip_data( ber, len );
+ tag = ber_skip_tag( ber, &len ); /* Signature Algorithm */
+ if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
+ ber_skip_data( ber, len );
+ tag = ber_skip_tag( ber, &len ); /* Issuer DN */
+ if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
+ ber_skip_data( ber, len );
+ tag = ber_skip_tag( ber, &len ); /* Validity */
+ if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
+ ber_skip_data( ber, len );
+ tag = ber_skip_tag( ber, &len ); /* Subject DN */
+ if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
+ ber_skip_data( ber, len );
+ tag = ber_skip_tag( ber, &len ); /* Subject PublicKeyInfo */
+ if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
+ ber_skip_data( ber, len );
+ tag = ber_skip_tag( ber, &len );
+ if ( tag == SLAP_X509_OPT_C_ISSUERUNIQUEID ) { /* issuerUniqueID */
+ if ( version < SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX;
+ ber_skip_data( ber, len );
+ tag = ber_skip_tag( ber, &len );
+ }
+ if ( tag == SLAP_X509_OPT_C_SUBJECTUNIQUEID ) { /* subjectUniqueID */
+ if ( version < SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX;
+ ber_skip_data( ber, len );
+ tag = ber_skip_tag( ber, &len );
+ }
+ if ( tag == SLAP_X509_OPT_C_EXTENSIONS ) { /* Extensions */
+ if ( version < SLAP_X509_V3 ) return LDAP_INVALID_SYNTAX;
+ tag = ber_skip_tag( ber, &len );
+ if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
+ ber_skip_data( ber, len );
+ tag = ber_skip_tag( ber, &len );
+ }
+ /* signatureAlgorithm */
+ if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
+ ber_skip_data( ber, len );
+ tag = ber_skip_tag( ber, &len );
+ /* Signature */
+ if ( tag != LBER_BITSTRING ) return LDAP_INVALID_SYNTAX;
+ ber_skip_data( ber, len );
+ tag = ber_skip_tag( ber, &len );
+ /* Must be at end now */
+ if ( len || tag != LBER_DEFAULT ) return LDAP_INVALID_SYNTAX;
+ return LDAP_SUCCESS;
+}
+
+/* X.509 certificate list validation */
+static int certificateListValidate( Syntax *syntax, struct berval *in )
+{
+ BerElementBuffer berbuf;
+ BerElement *ber = (BerElement *)&berbuf;
+ ber_tag_t tag;
+ ber_len_t len;
+ ber_int_t version = SLAP_X509_V1;
+
+ ber_init2( ber, in, LBER_USE_DER );
+ tag = ber_skip_tag( ber, &len ); /* Signed wrapper */
+ if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
+ tag = ber_skip_tag( ber, &len ); /* Sequence */
+ if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
+ tag = ber_peek_tag( ber, &len );
+ /* Optional version */
+ if ( tag == LBER_INTEGER ) {
+ tag = ber_get_int( ber, &version );
+ assert( tag == LBER_INTEGER );
+ if ( version != SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX;
+ }
+ tag = ber_skip_tag( ber, &len ); /* Signature Algorithm */
+ if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
+ ber_skip_data( ber, len );
+ tag = ber_skip_tag( ber, &len ); /* Issuer DN */
+ if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
+ ber_skip_data( ber, len );
+ tag = ber_skip_tag( ber, &len ); /* thisUpdate */
+ /* NOTE: in the certificates I'm playing with, the time is UTC.
+ * maybe the tag is different from 0x17U for generalizedTime? */
+ if ( tag != 0x17U ) return LDAP_INVALID_SYNTAX;
+ ber_skip_data( ber, len );
+ /* Optional nextUpdate */
+ tag = ber_skip_tag( ber, &len );
+ if ( tag == 0x17U ) {
+ ber_skip_data( ber, len );
+ tag = ber_skip_tag( ber, &len );
+ }
+ /* Optional revokedCertificates */
+ if ( tag == LBER_SEQUENCE ) {
+ /* Should NOT be empty */
+ ber_skip_data( ber, len );
+ tag = ber_skip_tag( ber, &len );
+ }
+ /* Optional Extensions */
+ if ( tag == SLAP_X509_OPT_CL_CRLEXTENSIONS ) { /* ? */
+ if ( version != SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX;
+ tag = ber_skip_tag( ber, &len );
+ if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
+ ber_skip_data( ber, len );
+ tag = ber_skip_tag( ber, &len );
+ }
+ /* signatureAlgorithm */
+ if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
+ ber_skip_data( ber, len );
+ tag = ber_skip_tag( ber, &len );
+ /* Signature */
+ if ( tag != LBER_BITSTRING ) return LDAP_INVALID_SYNTAX;
+ ber_skip_data( ber, len );
+ tag = ber_skip_tag( ber, &len );
+ /* Must be at end now */
+ if ( len || tag != LBER_DEFAULT ) return LDAP_INVALID_SYNTAX;
return LDAP_SUCCESS;
}
-#else
-#define certificateValidate sequenceValidate
-#endif
int
octetStringMatch(
return LDAP_SUCCESS;
}
-static int
+int
octetStringOrderingMatch(
int *matchp,
slap_mask_t flags,
/* Ignore initial whitespace */
while ( ASCII_SPACE( *p ) ) p++;
- normalized->bv_val = ber_strdup_x( p, ctx );
+ normalized->bv_len = val->bv_len - ( p - val->bv_val );
+ normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
+ AC_MEMCPY( normalized->bv_val, p, normalized->bv_len );
+ normalized->bv_val[normalized->bv_len] = '\0';
+
p = q = normalized->bv_val;
while ( *p ) {
-static int
+int
numericStringValidate(
Syntax *syntax,
struct berval *in )
}
}
- /* we should have copied no more then is in val */
+ /* we should have copied no more than is in val */
assert( (q - normalized->bv_val) <= (p - val->bv_val) );
/* null terminate */
if( rc ) return LDAP_INVALID_SYNTAX;
Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerValidate: OKAY\n",
- in->bv_val, 0, 0 );
+ 0, 0, 0 );
return LDAP_SUCCESS;
}
return LDAP_SUCCESS;
}
-#ifdef HAVE_TLS
static int
certificateExactNormalize(
slap_mask_t usage,
struct berval *normalized,
void *ctx )
{
- int rc = LDAP_INVALID_SYNTAX;
- unsigned char *p;
- char *serial = NULL;
+ BerElementBuffer berbuf;
+ BerElement *ber = (BerElement *)&berbuf;
+ ber_tag_t tag;
+ ber_len_t len;
+ ber_int_t i;
+ char serialbuf[64], *serial = serialbuf;
ber_len_t seriallen;
- struct berval issuer_dn = BER_BVNULL;
- X509_NAME *name = NULL;
- ASN1_INTEGER *sn = NULL;
- X509 *xcert = NULL;
+ struct berval issuer_dn = BER_BVNULL, bvdn;
+ unsigned char *p;
+ int rc = LDAP_INVALID_SYNTAX;
if( BER_BVISEMPTY( val ) ) goto done;
assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
- p = (unsigned char *)val->bv_val;
- xcert = d2i_X509( NULL, &p, val->bv_len);
- if( xcert == NULL ) goto done;
+ ber_init2( ber, val, LBER_USE_DER );
+ tag = ber_skip_tag( ber, &len ); /* Signed Sequence */
+ tag = ber_skip_tag( ber, &len ); /* Sequence */
+ tag = ber_peek_tag( ber, &len ); /* Optional version? */
+ if ( tag == SLAP_X509_OPT_C_VERSION ) {
+ tag = ber_skip_tag( ber, &len );
+ tag = ber_get_int( ber, &i ); /* version */
+ }
+
+ /* NOTE: move the test here from certificateNormalize,
+ * so that we can validate certs with serial longer
+ * than sizeof(ber_int_t) */
+ tag = ber_peek_tag( ber, &len ); /* serial */
+ if ( len > sizeof(ber_int_t) ) {
+ unsigned char *ptr;
+
+ tag = ber_skip_tag( ber, &len );
+ ptr = (unsigned char *)ber->ber_ptr;
+ ber_skip_data( ber, len );
+
+ while ( ptr[0] == '\0' && len > 0 ) {
+ ptr++;
+ len--;
+ }
+
+#if defined(USE_MP_BIGNUM)
+ /* TODO */
+
+#elif defined(USE_MP_GMP)
+ /* TODO */
+ /* hint: use mpz_import(), mpz_get_str() */
+
+#elif defined(USE_MP_LONG_LONG)
+ if ( len <= sizeof( unsigned long long ) ) {
+ unsigned long long sn = 0;
+ int i;
- sn=X509_get_serialNumber(xcert);
- if ( sn == NULL ) goto done;
- serial=i2s_ASN1_INTEGER(0, sn );
- if( serial == NULL ) goto done;
- seriallen=strlen(serial);
+ sn = ptr[0];
- name=X509_get_issuer_name(xcert);
- if( name == NULL ) goto done;
- rc = dnX509normalize( name, &issuer_dn );
+ for ( i = 1; i < len; i++ ) {
+ sn <<= 8;
+ sn += ptr[i];
+ }
+
+ seriallen = snprintf( serialbuf, sizeof(serialbuf), "%llu", sn );
+
+ } else {
+ /* do not accept serialNumber that requires
+ * more than long long */
+ rc = LDAP_INVALID_SYNTAX;
+ goto done;
+ }
+
+#else
+ /* do not accept serialNumber that requires
+ * more than long */
+ rc = LDAP_INVALID_SYNTAX;
+ goto done;
+#endif
+
+ } else {
+ tag = ber_get_int( ber, &i ); /* serial */
+ seriallen = snprintf( serialbuf, sizeof(serialbuf), "%d", i );
+ }
+ tag = ber_skip_tag( ber, &len ); /* SignatureAlg */
+ ber_skip_data( ber, len );
+ tag = ber_peek_tag( ber, &len ); /* IssuerDN */
+ len = ber_ptrlen( ber );
+ bvdn.bv_val = val->bv_val + len;
+ bvdn.bv_len = val->bv_len - len;
+
+ rc = dnX509normalize( &bvdn, &issuer_dn );
if( rc != LDAP_SUCCESS ) goto done;
normalized->bv_len = STRLENOF( "{ serialNumber , issuer \"\" }" )
rc = LDAP_SUCCESS;
done:
- if (xcert) X509_free(xcert);
- if (serial) ch_free(serial);
- if (issuer_dn.bv_val) ber_memfree(issuer_dn.bv_val);
+ if ( issuer_dn.bv_val ) ber_memfree( issuer_dn.bv_val );
+ if ( serial != serialbuf ) ber_memfree_x( serial, ctx );
return rc;
}
-#endif /* HAVE_TLS */
+static int
+hexValidate(
+ Syntax *syntax,
+ struct berval *in )
+{
+ int i;
+
+ assert( in != NULL );
+ assert( !BER_BVISNULL( in ) );
+
+ for ( i = 0; i < in->bv_len; i++ ) {
+ if ( !ASCII_HEX( in->bv_val[ i ] ) ) {
+ return LDAP_INVALID_SYNTAX;
+ }
+ }
+
+ return LDAP_SUCCESS;
+}
+
+/* Normalize a SID as used inside a CSN:
+ * three-digit numeric string */
+static int
+hexNormalize(
+ slap_mask_t usage,
+ Syntax *syntax,
+ MatchingRule *mr,
+ struct berval *val,
+ struct berval *normalized,
+ void *ctx )
+{
+ int i;
+
+ ber_dupbv_x( normalized, val, ctx );
+
+ for ( i = 0; i < normalized->bv_len; i++ ) {
+ if ( !ASCII_HEX( normalized->bv_val[ i ] ) ) {
+ ber_memfree_x( normalized->bv_val, ctx );
+ BER_BVZERO( normalized );
+ return LDAP_INVALID_SYNTAX;
+ }
+
+ normalized->bv_val[ i ] = TOLOWER( normalized->bv_val[ i ] );
+ }
+
+ return LDAP_SUCCESS;
+}
+
+static int
+sidValidate (
+ Syntax *syntax,
+ struct berval *in )
+{
+ assert( in != NULL );
+ assert( !BER_BVISNULL( in ) );
+
+ if ( in->bv_len != 3 ) {
+ return LDAP_INVALID_SYNTAX;
+ }
+
+ return hexValidate( NULL, in );
+}
+
+/* Normalize a SID as used inside a CSN:
+ * three-digit numeric string */
+static int
+sidNormalize(
+ slap_mask_t usage,
+ Syntax *syntax,
+ MatchingRule *mr,
+ struct berval *val,
+ struct berval *normalized,
+ void *ctx )
+{
+ if ( val->bv_len != 3 ) {
+ return LDAP_INVALID_SYNTAX;
+ }
+
+ return hexNormalize( 0, NULL, NULL, val, normalized, ctx );
+}
+
+static int
+sidPretty(
+ Syntax *syntax,
+ struct berval *val,
+ struct berval *out,
+ void *ctx )
+{
+ return sidNormalize( SLAP_MR_VALUE_OF_SYNTAX, NULL, NULL, val, out, ctx );
+}
+
+/* Normalize a SID as used inside a CSN, either as-is
+ * (assertion value) or extracted from the CSN
+ * (attribute value) */
+static int
+csnSidNormalize(
+ slap_mask_t usage,
+ Syntax *syntax,
+ MatchingRule *mr,
+ struct berval *val,
+ struct berval *normalized,
+ void *ctx )
+{
+ struct berval bv;
+ char *ptr,
+ buf[ 4 ];
+
+
+ if ( BER_BVISEMPTY( val ) ) {
+ return LDAP_INVALID_SYNTAX;
+ }
+
+ if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
+ return sidNormalize( 0, NULL, NULL, val, normalized, ctx );
+ }
+
+ assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
+
+ ptr = ber_bvchr( val, '#' );
+ if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
+ return LDAP_INVALID_SYNTAX;
+ }
+
+ bv.bv_val = ptr + 1;
+ bv.bv_len = val->bv_len - ( ptr + 1 - val->bv_val );
+
+ ptr = ber_bvchr( &bv, '#' );
+ if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
+ return LDAP_INVALID_SYNTAX;
+ }
+
+ bv.bv_val = ptr + 1;
+ bv.bv_len = val->bv_len - ( ptr + 1 - val->bv_val );
+
+ ptr = ber_bvchr( &bv, '#' );
+ if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
+ return LDAP_INVALID_SYNTAX;
+ }
+
+ bv.bv_len = ptr - bv.bv_val;
+
+ if ( bv.bv_len == 2 ) {
+ /* OpenLDAP 2.3 SID */
+ buf[ 0 ] = '0';
+ buf[ 1 ] = bv.bv_val[ 0 ];
+ buf[ 2 ] = bv.bv_val[ 1 ];
+ buf[ 3 ] = '\0';
+
+ bv.bv_val = buf;
+ bv.bv_len = 3;
+ }
+
+ return sidNormalize( 0, NULL, NULL, &bv, normalized, ctx );
+}
+
+static int
+csnValidate(
+ Syntax *syntax,
+ struct berval *in )
+{
+ struct berval bv;
+ char *ptr;
+ int rc;
+
+ assert( in != NULL );
+ assert( !BER_BVISNULL( in ) );
+
+ if ( BER_BVISEMPTY( in ) ) {
+ return LDAP_INVALID_SYNTAX;
+ }
+
+ bv = *in;
+
+ ptr = ber_bvchr( &bv, '#' );
+ if ( ptr == NULL || ptr - bv.bv_val == bv.bv_len ) {
+ return LDAP_INVALID_SYNTAX;
+ }
+
+ bv.bv_len = ptr - bv.bv_val;
+ if ( bv.bv_len != STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ" ) &&
+ bv.bv_len != STRLENOF( "YYYYmmddHHMMSSZ" ) )
+ {
+ return LDAP_INVALID_SYNTAX;
+ }
+
+ rc = generalizedTimeValidate( NULL, &bv );
+ if ( rc != LDAP_SUCCESS ) {
+ return rc;
+ }
+
+ bv.bv_val = ptr + 1;
+ bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
+
+ ptr = ber_bvchr( &bv, '#' );
+ if ( ptr == NULL || ptr - in->bv_val == in->bv_len ) {
+ return LDAP_INVALID_SYNTAX;
+ }
+
+ bv.bv_len = ptr - bv.bv_val;
+ if ( bv.bv_len != 6 ) {
+ return LDAP_INVALID_SYNTAX;
+ }
+
+ rc = hexValidate( NULL, &bv );
+ if ( rc != LDAP_SUCCESS ) {
+ return rc;
+ }
+
+ bv.bv_val = ptr + 1;
+ bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
+
+ ptr = ber_bvchr( &bv, '#' );
+ if ( ptr == NULL || ptr - in->bv_val == in->bv_len ) {
+ return LDAP_INVALID_SYNTAX;
+ }
+
+ bv.bv_len = ptr - bv.bv_val;
+ if ( bv.bv_len == 2 ) {
+ /* tolerate old 2-digit replica-id */
+ rc = hexValidate( NULL, &bv );
+
+ } else {
+ rc = sidValidate( NULL, &bv );
+ }
+ if ( rc != LDAP_SUCCESS ) {
+ return rc;
+ }
+
+ bv.bv_val = ptr + 1;
+ bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
+
+ if ( bv.bv_len != 6 ) {
+ return LDAP_INVALID_SYNTAX;
+ }
+
+ return hexValidate( NULL, &bv );
+}
+
+/* Normalize a CSN in OpenLDAP 2.3 format */
+static int
+csnNormalize23(
+ slap_mask_t usage,
+ Syntax *syntax,
+ MatchingRule *mr,
+ struct berval *val,
+ struct berval *normalized,
+ void *ctx )
+{
+ struct berval gt, cnt, sid, mod;
+ char *ptr;
+ int i;
+
+ assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
+ assert( !BER_BVISEMPTY( val ) );
+
+ gt = *val;
+
+ ptr = ber_bvchr( >, '#' );
+ if ( ptr == NULL || ptr - gt.bv_val == gt.bv_len ) {
+ return LDAP_INVALID_SYNTAX;
+ }
+
+ gt.bv_len = ptr - gt.bv_val;
+ assert( gt.bv_len == STRLENOF( "YYYYmmddHHMMSSZ" ) );
+
+ cnt.bv_val = ptr + 1;
+ cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val );
+
+ ptr = ber_bvchr( &cnt, '#' );
+ if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
+ return LDAP_INVALID_SYNTAX;
+ }
+
+ cnt.bv_len = ptr - cnt.bv_val;
+ assert( cnt.bv_len == STRLENOF( "000000" ) );
+
+ sid.bv_val = ptr + 1;
+ sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val );
+
+ ptr = ber_bvchr( &sid, '#' );
+ if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
+ return LDAP_INVALID_SYNTAX;
+ }
+
+ sid.bv_len = ptr - sid.bv_val;
+ assert( sid.bv_len == STRLENOF( "00" ) );
+
+ mod.bv_val = ptr + 1;
+ mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val );
+ assert( mod.bv_len == STRLENOF( "000000" ) );
+
+ normalized->bv_len = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" );
+ normalized->bv_val = ber_memalloc_x( normalized->bv_len + 1, ctx );
+
+ ptr = normalized->bv_val;
+ ptr = lutil_strncopy( ptr, gt.bv_val, gt.bv_len - 1 );
+ ptr = lutil_strcopy( ptr, ".000000Z#" );
+ ptr = lutil_strncopy( ptr, cnt.bv_val, cnt.bv_len );
+ *ptr++ = '#';
+ *ptr++ = '0';
+ for ( i = 0; i < sid.bv_len; i++ ) {
+ *ptr++ = TOLOWER( sid.bv_val[ i ] );
+ }
+ *ptr++ = '#';
+ for ( i = 0; i < mod.bv_len; i++ ) {
+ *ptr++ = TOLOWER( mod.bv_val[ i ] );
+ }
+ *ptr = '\0';
+
+ assert( ptr - normalized->bv_val == normalized->bv_len );
+
+ return LDAP_SUCCESS;
+}
+
+/* Normalize a CSN */
+static int
+csnNormalize(
+ slap_mask_t usage,
+ Syntax *syntax,
+ MatchingRule *mr,
+ struct berval *val,
+ struct berval *normalized,
+ void *ctx )
+{
+ struct berval cnt, sid, mod;
+ char *ptr;
+ int i;
+
+ assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
+
+ if ( BER_BVISEMPTY( val ) ) {
+ return LDAP_INVALID_SYNTAX;
+ }
+
+ if ( val->bv_len == STRLENOF( "YYYYmmddHHMMSSZ#SSSSSS#ID#ssssss" ) ) {
+ /* Openldap <= 2.3 */
+
+ return csnNormalize23( usage, syntax, mr, val, normalized, ctx );
+ }
+
+ assert( val->bv_len == STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ) );
+
+ ptr = ber_bvchr( val, '#' );
+ if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
+ return LDAP_INVALID_SYNTAX;
+ }
+
+ assert( ptr - val->bv_val == STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ" ) );
+
+ cnt.bv_val = ptr + 1;
+ cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val );
+
+ ptr = ber_bvchr( &cnt, '#' );
+ if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
+ return LDAP_INVALID_SYNTAX;
+ }
+
+ assert( ptr - cnt.bv_val == STRLENOF( "000000" ) );
+
+ sid.bv_val = ptr + 1;
+ sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val );
+
+ ptr = ber_bvchr( &sid, '#' );
+ if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
+ return LDAP_INVALID_SYNTAX;
+ }
+
+ sid.bv_len = ptr - sid.bv_val;
+ assert( sid.bv_len == STRLENOF( "000" ) );
+
+ mod.bv_val = ptr + 1;
+ mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val );
+
+ assert( mod.bv_len == STRLENOF( "000000" ) );
+
+ ber_dupbv_x( normalized, val, ctx );
+
+ for ( i = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#" );
+ i < normalized->bv_len; i++ )
+ {
+ /* assume it's already validated that's all hex digits */
+ normalized->bv_val[ i ] = TOLOWER( normalized->bv_val[ i ] );
+ }
+
+ return LDAP_SUCCESS;
+}
+
+static int
+csnPretty(
+ Syntax *syntax,
+ struct berval *val,
+ struct berval *out,
+ void *ctx )
+{
+ return csnNormalize( SLAP_MR_VALUE_OF_SYNTAX, NULL, NULL, val, out, ctx );
+}
#ifndef SUPPORT_OBSOLETE_UTC_SYNTAX
/* slight optimization - does not need the start parameter */
return rc;
}
+static char *country_gen_syn[] = {
+ "1.3.6.1.4.1.1466.115.121.1.15",
+ "1.3.6.1.4.1.1466.115.121.1.26",
+ "1.3.6.1.4.1.1466.115.121.1.44",
+ NULL
+};
#define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
#define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
static slap_syntax_defs_rec syntax_defs[] = {
{"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' "
X_BINARY X_NOT_H_R ")",
- SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL},
+ SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
- 0, NULL, NULL},
+ 0, NULL, NULL, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
- 0, NULL, NULL},
+ 0, NULL, NULL, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' "
X_NOT_H_R ")",
- SLAP_SYNTAX_BLOB, blobValidate, NULL},
+ SLAP_SYNTAX_BLOB, NULL, blobValidate, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' "
X_NOT_H_R ")",
- SLAP_SYNTAX_BER, berValidate, NULL},
+ SLAP_SYNTAX_BER, NULL, berValidate, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
- 0, bitStringValidate, NULL },
+ 0, NULL, bitStringValidate, NULL },
{"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
- 0, booleanValidate, NULL},
+ 0, NULL, booleanValidate, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
X_BINARY X_NOT_H_R ")",
- SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, certificateValidate, NULL},
+ SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
+ NULL, certificateValidate, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
X_BINARY X_NOT_H_R ")",
- SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, sequenceValidate, NULL},
+ SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
+ NULL, certificateListValidate, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
X_BINARY X_NOT_H_R ")",
- SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, sequenceValidate, NULL},
+ SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
+ NULL, sequenceValidate, NULL},
+#if 0 /* need to go __after__ printableString */
{"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
- 0, countryStringValidate, NULL},
+ 0, "1.3.6.1.4.1.1466.115.121.1.44",
+ countryStringValidate, NULL},
+#endif
{"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
- 0, dnValidate, dnPretty},
+ 0, NULL, dnValidate, dnPretty},
{"( 1.2.36.79672281.1.5.0 DESC 'RDN' )",
- 0, rdnValidate, rdnPretty},
+ 0, NULL, rdnValidate, rdnPretty},
#ifdef LDAP_COMP_MATCH
{"( 1.2.36.79672281.1.5.3 DESC 'allComponents' )",
- 0, allComponentsValidate, NULL},
+ 0, NULL, allComponentsValidate, NULL},
{"( 1.2.36.79672281.1.5.2 DESC 'componentFilterMatch assertion') ",
- 0, componentFilterValidate, NULL},
+ 0, NULL, componentFilterValidate, NULL},
#endif
{"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
- 0, NULL, NULL},
+ 0, NULL, NULL, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
- 0, deliveryMethodValidate, NULL},
+ 0, NULL, deliveryMethodValidate, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
- 0, UTF8StringValidate, NULL},
+ 0, NULL, UTF8StringValidate, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
- 0, NULL, NULL},
+ 0, NULL, NULL, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
- 0, NULL, NULL},
+ 0, NULL, NULL, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
- 0, NULL, NULL},
+ 0, NULL, NULL, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
- 0, NULL, NULL},
+ 0, NULL, NULL, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
- 0, NULL, NULL},
+ 0, NULL, NULL, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
- 0, printablesStringValidate, NULL},
+ 0, NULL, printablesStringValidate, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
- SLAP_SYNTAX_BLOB, NULL, NULL},
+ SLAP_SYNTAX_BLOB, NULL, NULL, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
- 0, generalizedTimeValidate, NULL},
+ 0, NULL, generalizedTimeValidate, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
- 0, NULL, NULL},
+ 0, NULL, NULL, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
- 0, IA5StringValidate, NULL},
+ 0, NULL, IA5StringValidate, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
- 0, integerValidate, NULL},
+ 0, NULL, integerValidate, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
- SLAP_SYNTAX_BLOB, blobValidate, NULL},
+ SLAP_SYNTAX_BLOB, NULL, blobValidate, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
- 0, NULL, NULL},
+ 0, NULL, NULL, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
- 0, NULL, NULL},
+ 0, NULL, NULL, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
- 0, NULL, NULL},
+ 0, NULL, NULL, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
- 0, NULL, NULL},
+ 0, NULL, NULL, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
- 0, NULL, NULL},
+ 0, NULL, NULL, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
- 0, nameUIDValidate, nameUIDPretty },
+ 0, NULL, nameUIDValidate, nameUIDPretty },
{"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
- 0, NULL, NULL},
+ 0, NULL, NULL, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
- 0, numericStringValidate, NULL},
+ 0, NULL, numericStringValidate, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
- 0, NULL, NULL},
+ 0, NULL, NULL, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
- 0, numericoidValidate, NULL},
+ 0, NULL, numericoidValidate, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
- 0, IA5StringValidate, NULL},
+ 0, NULL, IA5StringValidate, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
- 0, blobValidate, NULL},
+ 0, NULL, blobValidate, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
- 0, UTF8StringValidate, NULL},
+ 0, NULL, UTF8StringValidate, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
- 0, NULL, NULL},
+ 0, NULL, NULL, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
- 0, NULL, NULL},
+ 0, NULL, NULL, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
- 0, printableStringValidate, NULL},
+ 0, NULL, printableStringValidate, NULL},
+ /* moved here because now depends on Directory String, IA5 String
+ * and Printable String */
+ {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
+ 0, country_gen_syn, countryStringValidate, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' )",
#define subtreeSpecificationValidate UTF8StringValidate /* FIXME */
- 0, subtreeSpecificationValidate, NULL},
+ 0, NULL, subtreeSpecificationValidate, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
X_BINARY X_NOT_H_R ")",
- SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL},
+ SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, berValidate, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
- 0, printableStringValidate, NULL},
+ 0, NULL, printableStringValidate, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
- 0, NULL, NULL},
+ 0, NULL, NULL, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
- 0, printablesStringValidate, NULL},
+ 0, NULL, printablesStringValidate, NULL},
#ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
{"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
- 0, utcTimeValidate, NULL},
+ 0, NULL, utcTimeValidate, NULL},
#endif
{"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
- 0, NULL, NULL},
+ 0, NULL, NULL, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
- 0, NULL, NULL},
+ 0, NULL, NULL, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
- 0, NULL, NULL},
+ 0, NULL, NULL, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
- 0, NULL, NULL},
+ 0, NULL, NULL, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
- 0, NULL, NULL},
+ 0, NULL, NULL, NULL},
/* RFC 2307 NIS Syntaxes */
{"( 1.3.6.1.1.1.0.0 DESC 'RFC2307 NIS Netgroup Triple' )",
- 0, nisNetgroupTripleValidate, NULL},
+ 0, NULL, nisNetgroupTripleValidate, NULL},
{"( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )",
- 0, bootParameterValidate, NULL},
+ 0, NULL, bootParameterValidate, NULL},
/* draft-zeilenga-ldap-x509 */
{"( 1.3.6.1.1.15.1 DESC 'Certificate Exact Assertion' )",
- SLAP_SYNTAX_HIDE,
+ SLAP_SYNTAX_HIDE, NULL,
serialNumberAndIssuerValidate,
serialNumberAndIssuerPretty},
{"( 1.3.6.1.1.15.2 DESC 'Certificate Assertion' )",
- SLAP_SYNTAX_HIDE, NULL, NULL},
+ SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
{"( 1.3.6.1.1.15.3 DESC 'Certificate Pair Exact Assertion' )",
- SLAP_SYNTAX_HIDE, NULL, NULL},
+ SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
{"( 1.3.6.1.1.15.4 DESC 'Certificate Pair Assertion' )",
- SLAP_SYNTAX_HIDE, NULL, NULL},
+ SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
{"( 1.3.6.1.1.15.5 DESC 'Certificate List Exact Assertion' )",
- SLAP_SYNTAX_HIDE, NULL, NULL},
+ SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
{"( 1.3.6.1.1.15.6 DESC 'Certificate List Assertion' )",
- SLAP_SYNTAX_HIDE, NULL, NULL},
+ SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
{"( 1.3.6.1.1.15.7 DESC 'Algorithm Identifier' )",
- SLAP_SYNTAX_HIDE, NULL, NULL},
+ SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
#ifdef SLAPD_AUTHPASSWD
/* needs updating */
{"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
- SLAP_SYNTAX_HIDE, NULL, NULL},
+ SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
#endif
{"( 1.3.6.1.1.16.1 DESC 'UUID' )",
- 0, UUIDValidate, UUIDPretty},
+ 0, NULL, UUIDValidate, UUIDPretty},
{"( 1.3.6.1.4.1.4203.666.11.2.1 DESC 'CSN' )",
- SLAP_SYNTAX_HIDE, csnValidate, NULL},
+ SLAP_SYNTAX_HIDE, NULL, csnValidate, csnPretty },
+
+ {"( 1.3.6.1.4.1.4203.666.11.2.4 DESC 'CSN SID' )",
+ SLAP_SYNTAX_HIDE, NULL, sidValidate, sidPretty },
/* OpenLDAP Void Syntax */
{"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
- SLAP_SYNTAX_HIDE, inValidate, NULL},
+ SLAP_SYNTAX_HIDE, NULL, inValidate, NULL},
/* FIXME: OID is unused, but not registered yet */
{"( 1.3.6.1.4.1.4203.666.2.7 DESC 'OpenLDAP authz' )",
- SLAP_SYNTAX_HIDE, authzValidate, authzPretty},
+ SLAP_SYNTAX_HIDE, NULL, authzValidate, authzPretty},
- {NULL, 0, NULL, NULL}
+ {NULL, 0, NULL, NULL, NULL}
};
+char *csnSIDMatchSyntaxes[] = {
+ "1.3.6.1.4.1.4203.666.11.2.1" /* csn */,
+ NULL
+};
char *certificateExactMatchSyntaxes[] = {
"1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
NULL
{"( 2.5.13.34 NAME 'certificateExactMatch' "
"SYNTAX 1.3.6.1.1.15.1 )",
SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateExactMatchSyntaxes,
-#ifdef HAVE_TLS
NULL, certificateExactNormalize, octetStringMatch,
octetStringIndexer, octetStringFilter,
-#else
- NULL, NULL, NULL, NULL, NULL,
-#endif
NULL },
{"( 2.5.13.35 NAME 'certificateMatch' "
{"( 1.3.6.1.4.1.4203.666.11.2.2 NAME 'CSNMatch' "
"SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
SLAP_MR_HIDE | SLAP_MR_EQUALITY | SLAP_MR_ORDERED_INDEX, NULL,
- NULL, NULL, csnMatch,
+ NULL, csnNormalize, csnMatch,
csnIndexer, csnFilter,
NULL},
NULL, NULL,
"CSNMatch" },
+ {"( 1.3.6.1.4.1.4203.666.11.2.5 NAME 'CSNSIDMatch' "
+ "SYNTAX 1.3.6.1.4.1.4203.666.11.2.4 )",
+ SLAP_MR_EQUALITY | SLAP_MR_EXT, csnSIDMatchSyntaxes,
+ NULL, csnSidNormalize, octetStringMatch,
+ octetStringIndexer, octetStringFilter,
+ NULL },
+
/* FIXME: OID is unused, but not registered yet */
{"( 1.3.6.1.4.1.4203.666.4.12 NAME 'authzMatch' "
"SYNTAX 1.3.6.1.4.1.4203.666.2.7 )",
static int objectClassPretty(
- struct slap_syntax *syntax,
- struct berval * in,
- struct berval * out,
+ Syntax *syntax,
+ struct berval *in,
+ struct berval *out,
void *ctx )
{
ObjectClass *oc;
static int objectSubClassIndexer(
slap_mask_t use,
slap_mask_t mask,
- struct slap_syntax *syntax,
- struct slap_matching_rule *mr,
+ Syntax *syntax,
+ MatchingRule *mr,
struct berval *prefix,
BerVarray values,
BerVarray *keysp,
offsetof(struct slap_internal_schema, si_ad_collectiveExclusions) },
#endif
- { "entryDN", "( 1.3.6.1.4.1.4203.666.1.33 NAME 'entryDN' "
+ { "entryDN", "( 1.3.6.1.1.20 NAME 'entryDN' "
"DESC 'DN of the entry' "
"EQUALITY distinguishedNameMatch "
"SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 "
"SINGLE-VALUE NO-USER-MODIFICATION USAGE directoryOperation )",
- NULL, SLAP_AT_HIDE|SLAP_AT_DYNAMIC,
+ NULL, SLAP_AT_DYNAMIC,
NULL, NULL,
NULL, NULL, NULL, NULL, NULL,
offsetof(struct slap_internal_schema, si_ad_entryDN) },
"Duplicate matchingRule",
"Syntax not found",
"Duplicate ldapSyntax",
+ "Superior syntax not found",
"OID or name required",
"Qualifier not supported",
"Invalid NAME",
cr = ldap_str2contentrule( line, &code, &err, LDAP_SCHEMA_ALLOW_ALL );
if ( !cr ) {
- snprintf( c->msg, sizeof( c->msg ), "%s: %s before %s",
+ snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s: %s before %s",
c->argv[0], ldap_scherr2str( code ), err );
Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
- "%s %s\n", c->log, c->msg, 0 );
+ "%s %s\n", c->log, c->cr_msg, 0 );
cr_usage();
return 1;
}
if ( cr->cr_oid == NULL ) {
- snprintf( c->msg, sizeof( c->msg ), "%s: OID is missing",
+ snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s: OID is missing",
c->argv[0] );
Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
- "%s %s\n", c->log, c->msg, 0 );
+ "%s %s\n", c->log, c->cr_msg, 0 );
cr_usage();
code = 1;
goto done;
code = cr_add( cr, 1, scr, &err );
if ( code ) {
- snprintf( c->msg, sizeof( c->msg ), "%s: %s: \"%s\"",
+ snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s: %s: \"%s\"",
c->argv[0], scherr2str(code), err);
Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
- "%s %s\n", c->log, c->msg, 0 );
+ "%s %s\n", c->log, c->cr_msg, 0 );
code = 1;
goto done;
}
oc = ldap_str2objectclass(line, &code, &err, LDAP_SCHEMA_ALLOW_ALL );
if ( !oc ) {
- snprintf( c->msg, sizeof( c->msg ), "%s: %s before %s",
+ snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s: %s before %s",
c->argv[0], ldap_scherr2str( code ), err );
Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
- "%s %s\n", c->log, c->msg, 0 );
+ "%s %s\n", c->log, c->cr_msg, 0 );
oc_usage();
return 1;
}
if ( oc->oc_oid == NULL ) {
- snprintf( c->msg, sizeof( c->msg ), "%s: OID is missing",
+ snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s: OID is missing",
c->argv[0] );
Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
- "%s %s\n", c->log, c->msg, 0 );
+ "%s %s\n", c->log, c->cr_msg, 0 );
oc_usage();
code = 1;
goto done;
code = oc_add( oc, 1, soc, prev, &err );
if ( code ) {
- snprintf( c->msg, sizeof( c->msg ), "%s: %s: \"%s\"",
+ snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s: %s: \"%s\"",
c->argv[0], scherr2str(code), err);
Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
- "%s %s\n", c->log, c->msg, 0 );
+ "%s %s\n", c->log, c->cr_msg, 0 );
code = 1;
goto done;
}
at = ldap_str2attributetype( line, &code, &err, LDAP_SCHEMA_ALLOW_ALL );
if ( !at ) {
- snprintf( c->msg, sizeof( c->msg ), "%s: %s before %s",
+ snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s: %s before %s",
c->argv[0], ldap_scherr2str(code), err );
Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
- "%s %s\n", c->log, c->msg, 0 );
+ "%s %s\n", c->log, c->cr_msg, 0 );
at_usage();
return 1;
}
if ( at->at_oid == NULL ) {
- snprintf( c->msg, sizeof( c->msg ), "%s: OID is missing",
+ snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s: OID is missing",
c->argv[0] );
Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
- "%s %s\n", c->log, c->msg, 0 );
+ "%s %s\n", c->log, c->cr_msg, 0 );
at_usage();
code = 1;
goto done;
/* operational attributes should be defined internally */
if ( at->at_usage ) {
- snprintf( c->msg, sizeof( c->msg ), "%s: \"%s\" is operational",
+ snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s: \"%s\" is operational",
c->argv[0], at->at_oid );
Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
- "%s %s\n", c->log, c->msg, 0 );
+ "%s %s\n", c->log, c->cr_msg, 0 );
code = 1;
goto done;
}
code = at_add( at, 1, sat, prev, &err);
if ( code ) {
- snprintf( c->msg, sizeof( c->msg ), "%s: %s: \"%s\"",
+ snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s: %s: \"%s\"",
c->argv[0], scherr2str(code), err);
Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
- "%s %s\n", c->log, c->msg, 0 );
+ "%s %s\n", c->log, c->cr_msg, 0 );
code = 1;
goto done;
}
struct berval base = BER_BVNULL;
ber_len_t siz, off, i;
- Debug( LDAP_DEBUG_TRACE, "do_search\n", 0, 0, 0 );
-
+ Debug( LDAP_DEBUG_TRACE, "%s do_search\n",
+ op->o_log_prefix, 0, 0 );
/*
* Parse the search request. It looks like this:
*
rs->sr_err = dnPrettyNormal( NULL, &base, &op->o_req_dn, &op->o_req_ndn, op->o_tmpmemctx );
if( rs->sr_err != LDAP_SUCCESS ) {
- Debug( LDAP_DEBUG_ANY,
- "do_search: invalid dn (%s)\n", base.bv_val, 0, 0 );
+ Debug( LDAP_DEBUG_ANY, "%s do_search: invalid dn (%s)\n",
+ op->o_log_prefix, base.bv_val, 0 );
send_ldap_error( op, rs, LDAP_INVALID_DN_SYNTAX, "invalid DN" );
goto return_results;
}
}
if( get_ctrls( op, rs, 1 ) != LDAP_SUCCESS ) {
- Debug( LDAP_DEBUG_ANY, "do_search: get_ctrls failed\n", 0, 0, 0 );
-
+ Debug( LDAP_DEBUG_ANY, "%s do_search: get_ctrls failed\n",
+ op->o_log_prefix, 0, 0 );
goto return_results;
}
int
fe_op_search( Operation *op, SlapReply *rs )
{
- int manageDSAit;
- int be_manageDSAit;
BackendDB *bd = op->o_bd;
- manageDSAit = get_manageDSAit( op );
-
/* fake while loop to allow breaking out */
while ( op->ors_scope == LDAP_SCOPE_BASE ) {
Entry *entry = NULL;
* if we don't hold it.
*/
- be_manageDSAit = manageDSAit;
-
- op->o_bd = select_backend( &op->o_req_ndn, be_manageDSAit, 1 );
+ op->o_bd = select_backend( &op->o_req_ndn, 1 );
if ( op->o_bd == NULL ) {
rs->sr_ref = referral_rewrite( default_referral,
NULL, &op->o_req_dn, op->ors_scope );
LDAP_BEGIN_DECL
typedef struct slap_set_cookie {
- struct slap_op *set_op;
+ Operation *set_op;
} SetCookie;
/* this routine needs to return the bervals instead of
int i, j;
#ifdef SLAP_NO_SL_MALLOC
- return ber_malloc_x( size, NULL );
+ return ber_memalloc_x( size, NULL );
#endif
/* ber_set_option calls us like this */
LDAP_BEGIN_DECL
#define SLAP_LIGHTWEIGHT_DISPATCHER /* experimental slapd architecture */
-#ifdef LDAP_PVT_THREAD_POOL_SEM_LOAD_CONTROL
-#define SLAP_SEM_LOAD_CONTROL
-#endif
#ifdef LDAP_DEVEL
#define LDAP_COLLECTIVE_ATTRIBUTES
#define LDAP_COMP_MATCH
#define LDAP_SYNC_TIMESTAMP
-#define SLAP_SORTEDRESULTS
+#define SLAP_CONTROL_X_SORTEDRESULTS
+#define SLAP_CONTROL_X_SESSION_TRACKING
#endif
#define LDAP_DYNAMIC_OBJECTS
#define SERVICE_NAME OPENLDAP_PACKAGE "-slapd"
#define SLAPD_ANONYMOUS ""
+#ifdef HAVE_TCPD
+# include <tcpd.h>
+# define SLAP_STRING_UNKNOWN STRING_UNKNOWN
+#else /* ! TCP Wrappers */
+# define SLAP_STRING_UNKNOWN "unknown"
+#endif /* ! TCP Wrappers */
+
/* LDAPMod.mod_op value ===> Must be kept in sync with ldap.h!
* This is a value used internally by the backends. It is needed to allow
* adding values that already exist without getting an error as required by
#define SLAP_SYNTAX_ATTRIBUTETYPES_OID "1.3.6.1.4.1.1466.115.121.1.3"
#define SLAP_SYNTAX_OBJECTCLASSES_OID "1.3.6.1.4.1.1466.115.121.1.37"
#define SLAP_SYNTAX_MATCHINGRULEUSES_OID "1.3.6.1.4.1.1466.115.121.1.31"
-#define SLAP_SYNTAX_CONTENTRULE_OID "1.3.6.1.4.1.1466.115.121.1.16"
+#define SLAP_SYNTAX_CONTENTRULE_OID "1.3.6.1.4.1.1466.115.121.1.16"
/*
* represents schema information for a database
SLAP_SCHERR_MR_DUP,
SLAP_SCHERR_SYN_NOT_FOUND,
SLAP_SCHERR_SYN_DUP,
+ SLAP_SCHERR_SYN_SUP_NOT_FOUND,
SLAP_SCHERR_NO_NAME,
SLAP_SCHERR_NOT_SUPPORTED,
SLAP_SCHERR_BAD_DESCR,
SLAP_SCHERR_LAST
};
-typedef union slap_sockaddr {
+/* forward declarations */
+typedef struct Syntax Syntax;
+typedef struct MatchingRule MatchingRule;
+typedef struct MatchingRuleUse MatchingRuleUse;
+typedef struct MatchingRuleAssertion MatchingRuleAssertion;
+typedef struct OidMacro OidMacro;
+typedef struct ObjectClass ObjectClass;
+typedef struct AttributeType AttributeType;
+typedef struct AttributeDescription AttributeDescription;
+typedef struct AttributeName AttributeName;
+typedef struct ContentRule ContentRule;
+
+typedef struct AttributeAssertion AttributeAssertion;
+typedef struct SubstringsAssertion SubstringsAssertion;
+typedef struct Filter Filter;
+typedef struct ValuesReturnFilter ValuesReturnFilter;
+typedef struct Attribute Attribute;
+#ifdef LDAP_COMP_MATCH
+typedef struct ComponentData ComponentData;
+typedef struct ComponentFilter ComponentFilter;
+#endif
+
+typedef struct Entry Entry;
+typedef struct Modification Modification;
+typedef struct Modifications Modifications;
+typedef struct LDAPModList LDAPModList;
+
+typedef struct BackendInfo BackendInfo; /* per backend type */
+typedef struct BackendDB BackendDB; /* per backend database */
+
+typedef struct Connection Connection;
+typedef struct Operation Operation;
+typedef struct SlapReply SlapReply;
+/* end of forward declarations */
+
+typedef union Sockaddr {
struct sockaddr sa_addr;
struct sockaddr_in sa_in_addr;
#ifdef LDAP_PF_INET6
extern int slap_inet4or6;
#endif
-typedef struct slap_oid_macro {
+struct OidMacro {
struct berval som_oid;
BerVarray som_names;
BerVarray som_subs;
#define SLAP_OM_HARDCODE 0x10000U /* This is hardcoded schema */
int som_flags;
- LDAP_STAILQ_ENTRY(slap_oid_macro) som_next;
-} OidMacro;
-
-/* forward declarations */
-struct slap_syntax;
-struct slap_matching_rule;
+ LDAP_STAILQ_ENTRY(OidMacro) som_next;
+};
typedef int slap_syntax_validate_func LDAP_P((
- struct slap_syntax *syntax,
+ Syntax *syntax,
struct berval * in));
typedef int slap_syntax_transform_func LDAP_P((
- struct slap_syntax *syntax,
+ Syntax *syntax,
struct berval * in,
struct berval * out,
void *memctx));
struct ComponentDesc;
#endif
-typedef struct slap_syntax {
+struct Syntax {
LDAPSyntax ssyn_syn;
#define ssyn_oid ssyn_syn.syn_oid
#define ssyn_desc ssyn_syn.syn_desc
#define SLAP_SYNTAX_HIDE 0x8000U /* hide (do not publish) */
#endif
+ Syntax **ssyn_sups;
+
slap_syntax_validate_func *ssyn_validate;
slap_syntax_transform_func *ssyn_pretty;
struct ComponentDesc* ssync_comp_syntax;
#endif
- LDAP_SLIST_ENTRY(slap_syntax) ssyn_next;
-} Syntax;
+ LDAP_SLIST_ENTRY(Syntax) ssyn_next;
+};
#define slap_syntax_is_flag(s,flag) ((int)((s)->ssyn_flags & (flag)) ? 1 : 0)
#define slap_syntax_is_blob(s) slap_syntax_is_flag((s),SLAP_SYNTAX_BLOB)
typedef struct slap_syntax_defs_rec {
char *sd_desc;
int sd_flags;
+ char **sd_sups;
slap_syntax_validate_func *sd_validate;
slap_syntax_transform_func *sd_pretty;
#ifdef SLAPD_BINARY_CONVERSION
/* Normalizer */
typedef int slap_mr_normalize_func LDAP_P((
slap_mask_t use,
- struct slap_syntax *syntax, /* NULL if in is asserted value */
- struct slap_matching_rule *mr,
- struct berval * in,
- struct berval * out,
+ Syntax *syntax, /* NULL if in is asserted value */
+ MatchingRule *mr,
+ struct berval *in,
+ struct berval *out,
void *memctx ));
/* Match (compare) function */
typedef int slap_mr_match_func LDAP_P((
int *match,
slap_mask_t use,
- struct slap_syntax *syntax, /* syntax of stored value */
- struct slap_matching_rule *mr,
- struct berval * value,
- void * assertValue ));
+ Syntax *syntax, /* syntax of stored value */
+ MatchingRule *mr,
+ struct berval *value,
+ void *assertValue ));
/* Index generation function */
typedef int slap_mr_indexer_func LDAP_P((
slap_mask_t use,
slap_mask_t mask,
- struct slap_syntax *syntax, /* syntax of stored value */
- struct slap_matching_rule *mr,
+ Syntax *syntax, /* syntax of stored value */
+ MatchingRule *mr,
struct berval *prefix,
BerVarray values,
BerVarray *keys,
typedef int slap_mr_filter_func LDAP_P((
slap_mask_t use,
slap_mask_t mask,
- struct slap_syntax *syntax, /* syntax of stored value */
- struct slap_matching_rule *mr,
+ Syntax *syntax, /* syntax of stored value */
+ MatchingRule *mr,
struct berval *prefix,
- void * assertValue,
+ void *assertValue,
BerVarray *keys,
void *memctx ));
-typedef struct slap_matching_rule_use MatchingRuleUse;
-
-typedef struct slap_matching_rule {
+struct MatchingRule {
LDAPMatchingRule smr_mrule;
MatchingRuleUse *smr_mru;
/* RFC 4512 string representation */
struct berval smr_bvoid;
#define smr_oidlen smr_bvoid.bv_len
- slap_mask_t smr_usage;
+ slap_mask_t smr_usage;
#ifdef LDAP_DEVEL
#define SLAP_MR_HIDE 0x0000U
#define SLAP_MR_HIDE 0x8000U
#endif
-#define SLAP_MR_MUTATION_NORMALIZER 0x4000U
+#define SLAP_MR_MUTATION_NORMALIZER 0x4000U
#define SLAP_MR_TYPE_MASK 0x0F00U
-#define SLAP_MR_SUBTYPE_MASK 0x00F0U
+#define SLAP_MR_SUBTYPE_MASK 0x00F0U
#define SLAP_MR_USAGE 0x000FU
#define SLAP_MR_NONE 0x0000U
#define SLAP_MR_EQUALITY 0x0100U
#define SLAP_MR_ORDERING 0x0200U
#define SLAP_MR_SUBSTR 0x0400U
-#define SLAP_MR_EXT 0x0800U /* implicitly extensible */
-#define SLAP_MR_ORDERED_INDEX 0x1000U
+#define SLAP_MR_EXT 0x0800U /* implicitly extensible */
+#define SLAP_MR_ORDERED_INDEX 0x1000U
#ifdef LDAP_COMP_MATCH
#define SLAP_MR_COMPONENT 0x2000U
#endif
#define SLAP_MR_EQUALITY_APPROX ( SLAP_MR_EQUALITY | 0x0010U )
#define SLAP_MR_SUBSTR_INITIAL ( SLAP_MR_SUBSTR | 0x0010U )
-#define SLAP_MR_SUBSTR_ANY ( SLAP_MR_SUBSTR | 0x0020U )
+#define SLAP_MR_SUBSTR_ANY ( SLAP_MR_SUBSTR | 0x0020U )
#define SLAP_MR_SUBSTR_FINAL ( SLAP_MR_SUBSTR | 0x0040U )
*/
#define SLAP_MR_VALUE_OF_ASSERTION_SYNTAX 0x0001U
#define SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX 0x0002U
-#define SLAP_MR_VALUE_OF_SYNTAX 0x0003U
+#define SLAP_MR_VALUE_OF_SYNTAX 0x0003U
#define SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX( usage ) \
((usage) & SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX )
#define SLAP_IS_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH( usage ) \
((usage) & SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH )
- Syntax *smr_syntax;
+ Syntax *smr_syntax;
slap_mr_convert_func *smr_convert;
slap_mr_normalize_func *smr_normalize;
- slap_mr_match_func *smr_match;
+ slap_mr_match_func *smr_match;
slap_mr_indexer_func *smr_indexer;
- slap_mr_filter_func *smr_filter;
+ slap_mr_filter_func *smr_filter;
/*
* null terminated array of syntaxes compatible with this syntax
* note: when MS_EXT is set, this MUST NOT contain the assertion
* syntax of the rule. When MS_EXT is not set, it MAY.
*/
- Syntax **smr_compat_syntaxes;
+ Syntax **smr_compat_syntaxes;
/*
* For equality rules, refers to an associated approximate rule.
* For non-equality rules, refers to an associated equality rule.
*/
- struct slap_matching_rule *smr_associated;
+ MatchingRule *smr_associated;
#define SLAP_MR_ASSOCIATED(mr,amr) \
(((mr) == (amr)) || ((mr)->smr_associated == (amr)))
- LDAP_SLIST_ENTRY(slap_matching_rule)smr_next;
+ LDAP_SLIST_ENTRY(MatchingRule) smr_next;
#define smr_oid smr_mrule.mr_oid
#define smr_names smr_mrule.mr_names
#define smr_obsolete smr_mrule.mr_obsolete
#define smr_syntax_oid smr_mrule.mr_syntax_oid
#define smr_extensions smr_mrule.mr_extensions
-} MatchingRule;
+};
-struct slap_matching_rule_use {
+struct MatchingRuleUse {
LDAPMatchingRuleUse smru_mruleuse;
MatchingRule *smru_mr;
/* RFC 4512 string representation */
struct berval smru_str;
- LDAP_SLIST_ENTRY(slap_matching_rule_use) smru_next;
+ LDAP_SLIST_ENTRY(MatchingRuleUse) smru_next;
#define smru_oid smru_mruleuse.mru_oid
#define smru_names smru_mruleuse.mru_names
char * mrd_associated;
} slap_mrule_defs_rec;
-struct slap_backend_db;
-struct slap_entry;
-struct slap_attr;
-
typedef int (AttributeTypeSchemaCheckFN)(
- struct slap_backend_db *be,
- struct slap_entry *e,
- struct slap_attr *attr,
+ BackendDB *be,
+ Entry *e,
+ Attribute *attr,
const char** text,
char *textbuf, size_t textlen );
-typedef struct slap_attribute_type {
+struct AttributeType {
LDAPAttributeType sat_atype;
struct berval sat_cname;
- struct slap_attribute_type *sat_sup;
- struct slap_attribute_type **sat_subtypes;
+ AttributeType *sat_sup;
+ AttributeType **sat_subtypes;
MatchingRule *sat_equality;
MatchingRule *sat_approx;
MatchingRule *sat_ordering;
MatchingRule *sat_substr;
- Syntax *sat_syntax;
+ Syntax *sat_syntax;
AttributeTypeSchemaCheckFN *sat_check;
- char *sat_oidmacro;
+ char *sat_oidmacro;
#define SLAP_AT_NONE 0x0000U
#define SLAP_AT_ABSTRACT 0x0100U /* cannot be instantiated */
#define SLAP_AT_ORDERED_SIB 0x0002U /* siblings are ordered */
#define SLAP_AT_ORDERED 0x0003U /* value has order index */
-#define SLAP_AT_HARDCODE 0x10000U /* hardcoded schema */
-#define SLAP_AT_DELETED 0x20000U
+#define SLAP_AT_HARDCODE 0x10000U /* hardcoded schema */
+#define SLAP_AT_DELETED 0x20000U
- slap_mask_t sat_flags;
+ slap_mask_t sat_flags;
- LDAP_STAILQ_ENTRY(slap_attribute_type) sat_next;
+ LDAP_STAILQ_ENTRY(AttributeType) sat_next;
#define sat_oid sat_atype.at_oid
#define sat_names sat_atype.at_names
#define sat_desc sat_atype.at_desc
-#define sat_obsolete sat_atype.at_obsolete
+#define sat_obsolete sat_atype.at_obsolete
#define sat_sup_oid sat_atype.at_sup_oid
-#define sat_equality_oid sat_atype.at_equality_oid
-#define sat_ordering_oid sat_atype.at_ordering_oid
-#define sat_substr_oid sat_atype.at_substr_oid
-#define sat_syntax_oid sat_atype.at_syntax_oid
-#define sat_single_value sat_atype.at_single_value
-#define sat_collective sat_atype.at_collective
-#define sat_no_user_mod sat_atype.at_no_user_mod
+#define sat_equality_oid sat_atype.at_equality_oid
+#define sat_ordering_oid sat_atype.at_ordering_oid
+#define sat_substr_oid sat_atype.at_substr_oid
+#define sat_syntax_oid sat_atype.at_syntax_oid
+#define sat_single_value sat_atype.at_single_value
+#define sat_collective sat_atype.at_collective
+#define sat_no_user_mod sat_atype.at_no_user_mod
#define sat_usage sat_atype.at_usage
-#define sat_extensions sat_atype.at_extensions
+#define sat_extensions sat_atype.at_extensions
- struct slap_attr_desc *sat_ad;
+ AttributeDescription *sat_ad;
ldap_pvt_thread_mutex_t sat_ad_mutex;
-} AttributeType;
+};
#define is_at_operational(at) ((at)->sat_usage)
#define is_at_single_value(at) ((at)->sat_single_value)
#define is_at_obsolete(at) ((at)->sat_obsolete)
#define is_at_no_user_mod(at) ((at)->sat_no_user_mod)
-struct slap_object_class;
-
typedef int (ObjectClassSchemaCheckFN)(
- struct slap_backend_db *be,
- struct slap_entry *e,
- struct slap_object_class *oc,
+ BackendDB *be,
+ Entry *e,
+ ObjectClass *oc,
const char** text,
char *textbuf, size_t textlen );
-typedef struct slap_object_class {
+struct ObjectClass {
LDAPObjectClass soc_oclass;
struct berval soc_cname;
- struct slap_object_class **soc_sups;
- AttributeType **soc_required;
- AttributeType **soc_allowed;
+ ObjectClass **soc_sups;
+ AttributeType **soc_required;
+ AttributeType **soc_allowed;
ObjectClassSchemaCheckFN *soc_check;
- char *soc_oidmacro;
- slap_mask_t soc_flags;
+ char *soc_oidmacro;
+ slap_mask_t soc_flags;
#define soc_oid soc_oclass.oc_oid
#define soc_names soc_oclass.oc_names
#define soc_desc soc_oclass.oc_desc
-#define soc_obsolete soc_oclass.oc_obsolete
-#define soc_sup_oids soc_oclass.oc_sup_oids
+#define soc_obsolete soc_oclass.oc_obsolete
+#define soc_sup_oids soc_oclass.oc_sup_oids
#define soc_kind soc_oclass.oc_kind
-#define soc_at_oids_must soc_oclass.oc_at_oids_must
-#define soc_at_oids_may soc_oclass.oc_at_oids_may
-#define soc_extensions soc_oclass.oc_extensions
+#define soc_at_oids_must soc_oclass.oc_at_oids_must
+#define soc_at_oids_may soc_oclass.oc_at_oids_may
+#define soc_extensions soc_oclass.oc_extensions
- LDAP_STAILQ_ENTRY(slap_object_class) soc_next;
-} ObjectClass;
+ LDAP_STAILQ_ENTRY(ObjectClass) soc_next;
+};
#define SLAP_OCF_SET_FLAGS 0x1
#define SLAP_OCF_CHECK_SUP 0x2
/*
* DIT content rule
*/
-typedef struct slap_content_rule {
+struct ContentRule {
LDAPContentRule scr_crule;
- ObjectClass *scr_sclass;
- ObjectClass **scr_auxiliaries; /* optional */
+ ObjectClass *scr_sclass;
+ ObjectClass **scr_auxiliaries; /* optional */
AttributeType **scr_required; /* optional */
AttributeType **scr_allowed; /* optional */
AttributeType **scr_precluded; /* optional */
-#define scr_oid scr_crule.cr_oid
-#define scr_names scr_crule.cr_names
-#define scr_desc scr_crule.cr_desc
+#define scr_oid scr_crule.cr_oid
+#define scr_names scr_crule.cr_names
+#define scr_desc scr_crule.cr_desc
#define scr_obsolete scr_crule.cr_obsolete
#define scr_oc_oids_aux scr_crule.cr_oc_oids_aux
#define scr_at_oids_must scr_crule.cr_at_oids_must
#define scr_at_oids_may scr_crule.cr_at_oids_may
#define scr_at_oids_not scr_crule.cr_at_oids_not
- char *scr_oidmacro;
-#define SLAP_CR_HARDCODE 0x10000U
- int scr_flags;
+ char *scr_oidmacro;
+#define SLAP_CR_HARDCODE 0x10000U
+ int scr_flags;
- LDAP_STAILQ_ENTRY( slap_content_rule ) scr_next;
-} ContentRule;
+ LDAP_STAILQ_ENTRY( ContentRule ) scr_next;
+};
/* Represents a recognized attribute description ( type + options ). */
-typedef struct slap_attr_desc {
- struct slap_attr_desc *ad_next;
- AttributeType *ad_type; /* attribute type, must be specified */
- struct berval ad_cname; /* canonical name, must be specified */
- struct berval ad_tags; /* empty if no tagging options */
+struct AttributeDescription {
+ AttributeDescription *ad_next;
+ AttributeType *ad_type; /* attribute type, must be specified */
+ struct berval ad_cname; /* canonical name, must be specified */
+ struct berval ad_tags; /* empty if no tagging options */
unsigned ad_flags;
-#define SLAP_DESC_NONE 0x00U
-#define SLAP_DESC_BINARY 0x01U
-#define SLAP_DESC_TAG_RANGE 0x80U
-#define SLAP_DESC_TEMPORARY 0x1000U
-} AttributeDescription;
+#define SLAP_DESC_NONE 0x00U
+#define SLAP_DESC_BINARY 0x01U
+#define SLAP_DESC_TAG_RANGE 0x80U
+#define SLAP_DESC_TEMPORARY 0x1000U
+};
/* flags to slap_*2undef_ad to register undefined (0, the default)
* or proxied (SLAP_AD_PROXIED) AttributeDescriptions; the additional
* SLAP_AD_NOINSERT is to lookup without insert */
-#define SLAP_AD_UNDEF 0x00U
-#define SLAP_AD_PROXIED 0x01U
-#define SLAP_AD_NOINSERT 0x02U
-
-typedef struct slap_attr_name {
- struct berval an_name;
- AttributeDescription *an_desc;
- int an_oc_exclude;
- ObjectClass *an_oc;
-} AttributeName;
+#define SLAP_AD_UNDEF 0x00U
+#define SLAP_AD_PROXIED 0x01U
+#define SLAP_AD_NOINSERT 0x02U
+
+struct AttributeName {
+ struct berval an_name;
+ AttributeDescription *an_desc;
+ int an_oc_exclude;
+ ObjectClass *an_oc;
+};
#define slap_ad_is_tagged(ad) ( (ad)->ad_tags.bv_len != 0 )
#define slap_ad_is_tag_range(ad) \
Syntax *si_syn_objectClassDesc;
};
-typedef struct slap_attr_assertion {
+struct AttributeAssertion {
AttributeDescription *aa_desc;
- struct berval aa_value;
+ struct berval aa_value;
#ifdef LDAP_COMP_MATCH
- struct slap_component_filter *aa_cf;/* for attribute aliasing */
+ ComponentFilter *aa_cf; /* for attribute aliasing */
#endif
-} AttributeAssertion;
+};
-typedef struct slap_ss_assertion {
+struct SubstringsAssertion {
AttributeDescription *sa_desc;
struct berval sa_initial;
struct berval *sa_any;
struct berval sa_final;
-} SubstringsAssertion;
-
-#ifdef LDAP_COMP_MATCH
-struct slap_component_filter;
-#endif
+};
-typedef struct slap_mr_assertion {
+struct MatchingRuleAssertion {
MatchingRule *ma_rule; /* optional */
- struct berval ma_rule_text; /* optional */
+ struct berval ma_rule_text; /* optional */
AttributeDescription *ma_desc; /* optional */
- int ma_dnattrs; /* boolean */
+ int ma_dnattrs; /* boolean */
struct berval ma_value; /* required */
#ifdef LDAP_COMP_MATCH
- struct slap_component_filter* ma_cf; /* component filter */
+ ComponentFilter *ma_cf; /* component filter */
#endif
-} MatchingRuleAssertion;
+};
/*
* represents a search filter
*/
-typedef struct slap_filter {
+struct Filter {
ber_tag_t f_choice; /* values taken from ldap.h, plus: */
#define SLAPD_FILTER_COMPUTED 0
#define SLAPD_FILTER_MASK 0x7fff
union f_un_u {
/* precomputed result */
- ber_int_t f_un_result;
+ ber_int_t f_un_result;
/* present */
- AttributeDescription *f_un_desc;
+ AttributeDescription *f_un_desc;
/* simple value assertion */
- AttributeAssertion *f_un_ava;
+ AttributeAssertion *f_un_ava;
/* substring assertion */
- SubstringsAssertion *f_un_ssa;
+ SubstringsAssertion *f_un_ssa;
/* matching rule assertion */
- MatchingRuleAssertion *f_un_mra;
+ MatchingRuleAssertion *f_un_mra;
#define f_desc f_un.f_un_desc
#define f_ava f_un.f_un_ava
#define f_av_value f_un.f_un_ava->aa_value
#define f_sub f_un.f_un_ssa
#define f_sub_desc f_un.f_un_ssa->sa_desc
-#define f_sub_initial f_un.f_un_ssa->sa_initial
+#define f_sub_initial f_un.f_un_ssa->sa_initial
#define f_sub_any f_un.f_un_ssa->sa_any
#define f_sub_final f_un.f_un_ssa->sa_final
#define f_mra f_un.f_un_mra
#define f_mr_rule f_un.f_un_mra->ma_rule
-#define f_mr_rule_text f_un.f_un_mra->ma_rule_text
+#define f_mr_rule_text f_un.f_un_mra->ma_rule_text
#define f_mr_desc f_un.f_un_mra->ma_desc
#define f_mr_value f_un.f_un_mra->ma_value
-#define f_mr_dnattrs f_un.f_un_mra->ma_dnattrs
+#define f_mr_dnattrs f_un.f_un_mra->ma_dnattrs
/* and, or, not */
- struct slap_filter *f_un_complex;
+ Filter *f_un_complex;
} f_un;
#define f_result f_un.f_un_result
#define f_not f_un.f_un_complex
#define f_list f_un.f_un_complex
- struct slap_filter *f_next;
-} Filter;
+ Filter *f_next;
+};
/* compare routines can return undefined */
#define SLAPD_COMPARE_UNDEFINED ((ber_int_t) -1)
-typedef struct slap_valuesreturnfilter {
+struct ValuesReturnFilter {
ber_tag_t vrf_choice;
union vrf_un_u {
} vrf_un;
- struct slap_valuesreturnfilter *vrf_next;
-} ValuesReturnFilter;
-
-#ifdef LDAP_COMP_MATCH
-struct slap_component_syntax_info;
-typedef struct slap_component_data {
- void* cd_mem_op;/* nibble memory handler */
- struct slap_component_syntax_info** cd_tree;/* component tree */
-} ComponentData;
-#endif
+ ValuesReturnFilter *vrf_next;
+};
/*
* represents an attribute (description + values)
*/
-typedef struct slap_attr {
- AttributeDescription *a_desc;
- BerVarray a_vals; /* preserved values */
- BerVarray a_nvals; /* normalized values */
+struct Attribute {
+ AttributeDescription *a_desc;
+ BerVarray a_vals; /* preserved values */
+ BerVarray a_nvals; /* normalized values */
#ifdef LDAP_COMP_MATCH
- ComponentData *a_comp_data; /* component values */
+ ComponentData *a_comp_data; /* component values */
#endif
- struct slap_attr *a_next;
- unsigned a_flags;
-#define SLAP_ATTR_IXADD 0x1U
-#define SLAP_ATTR_IXDEL 0x2U
+ Attribute *a_next;
+ unsigned a_flags;
+#define SLAP_ATTR_IXADD 0x1U
+#define SLAP_ATTR_IXDEL 0x2U
#define SLAP_ATTR_DONT_FREE_DATA 0x4U
#define SLAP_ATTR_DONT_FREE_VALS 0x8U
-} Attribute;
+};
/*
typedef unsigned long ID;
#define NOID ((ID)~0)
-typedef struct slap_entry_header {
+typedef struct EntryHeader {
struct berval bv;
char *data;
int nattrs;
/*
* represents an entry in core
*/
-typedef struct slap_entry {
+struct Entry {
/*
* The ID field should only be changed before entry is
* inserted into a cache. The ID value is backend
/* for use by the backend for any purpose */
void* e_private;
-} Entry;
+};
/*
* A list of LDAPMods
*/
-typedef struct slap_mod {
+struct Modification {
short sm_op;
short sm_flags;
/* Set for internal mods, will bypass ACL checks. Only needed when
struct berval sm_type;
BerVarray sm_values;
BerVarray sm_nvalues;
-} Modification;
+};
-typedef struct slap_mod_list {
- Modification sml_mod;
+struct Modifications {
+ Modification sml_mod;
#define sml_op sml_mod.sm_op
#define sml_flags sml_mod.sm_flags
#define sml_desc sml_mod.sm_desc
#define sml_type sml_mod.sm_type
#define sml_values sml_mod.sm_values
#define sml_nvalues sml_mod.sm_nvalues
- struct slap_mod_list *sml_next;
-} Modifications;
+ Modifications *sml_next;
+};
-typedef struct slap_ldap_modlist {
- LDAPMod ml_mod;
- struct slap_ldap_modlist *ml_next;
+struct LDAPModList {
+ LDAPMod ml_mod;
+ LDAPModList *ml_next;
#define ml_op ml_mod.mod_op
#define ml_type ml_mod.mod_type
#define ml_values ml_mod.mod_values
-} LDAPModList;
+};
/*
* represents an access control list
*/
-typedef enum slap_access_e {
+typedef enum slap_access_t {
ACL_INVALID_ACCESS = -1,
ACL_NONE = 0,
ACL_DISCLOSE,
ACL_STYLE_PATH
} slap_style_t;
-typedef struct slap_authz_info {
+typedef struct AuthorizationInformation {
ber_tag_t sai_method; /* LDAP_AUTH_* from <ldap.h> */
struct berval sai_mech; /* SASL Mechanism */
struct berval sai_dn; /* DN for reporting purposes */
slap_ssf_t sai_sasl_ssf; /* SASL SSF */
} AuthorizationInformation;
-
#ifdef SLAP_DYNACL
-struct slap_op;
/*
* "dynamic" ACL infrastructure (for ACIs and more)
typedef int (slap_dynacl_unparse) LDAP_P(( void *priv, struct berval *bv ));
typedef int (slap_dynacl_mask) LDAP_P((
void *priv,
- struct slap_op *op,
+ Operation *op,
Entry *e,
AttributeDescription *desc,
struct berval *val,
} slap_dn_access;
/* the "by" part */
-typedef struct slap_access {
+typedef struct Access {
slap_control_t a_type;
/* strip qualifiers */
/* ACL Groups */
slap_style_t a_group_style;
struct berval a_group_pat;
- ObjectClass *a_group_oc;
+ ObjectClass *a_group_oc;
AttributeDescription *a_group_at;
- struct slap_access *a_next;
+ struct Access *a_next;
} Access;
/* the "to" part */
-typedef struct slap_acl {
+typedef struct AccessControl {
/* "to" part: the entries this acl applies to */
Filter *acl_filter;
slap_style_t acl_dn_style;
/* "by" part: list of who has what access to the entries */
Access *acl_access;
- struct slap_acl *acl_next;
+ struct AccessControl *acl_next;
} AccessControl;
typedef enum {
ACL_STATE_RECORDED = ( ACL_STATE_RECORDED_VD | ACL_STATE_RECORDED_NV )
} slap_acl_state_t;
-typedef struct slap_acl_state {
+typedef struct AccessControlState {
/* Access state */
AccessControl *as_vi_acl;
AccessControl *as_vd_acl;
* represents a backend
*/
-typedef struct slap_backend_info BackendInfo; /* per backend type */
-typedef struct slap_backend_db BackendDB; /* per backend database */
-typedef LDAP_STAILQ_HEAD(BeI, slap_backend_info) slap_bi_head;
-typedef LDAP_STAILQ_HEAD(BeDB, slap_backend_db) slap_be_head;
+typedef LDAP_STAILQ_HEAD(BeI, BackendInfo) slap_bi_head;
+typedef LDAP_STAILQ_HEAD(BeDB, BackendDB) slap_be_head;
LDAP_SLAPD_V (int) nBackendInfo;
LDAP_SLAPD_V (int) nBackendDB;
#endif
} slap_bindconf;
-struct slap_replica_info {
- const char *ri_host; /* points to host part of uri */
- BerVarray ri_nsuffix; /* array of suffixes this replica accepts */
- AttributeName *ri_attrs; /* attrs to replicate, NULL=all */
- int ri_exclude; /* 1 => exclude ri_attrs */
- slap_bindconf ri_bindconf; /* for back-config */
-};
-
typedef struct slap_verbmasks {
struct berval word;
const slap_mask_t mask;
struct ConfigOCs; /* config.h */
-struct slap_backend_db {
+struct BackendDB {
BackendInfo *bd_info; /* pointer to shared backend info */
/* fields in this structure (and routines acting on this structure)
#define be_modrdn bd_info->bi_op_modrdn
#define be_search bd_info->bi_op_search
#define be_abandon bd_info->bi_op_abandon
-#define be_cancel bd_info->bi_op_cancel
#define be_extended bd_info->bi_extended
+#define be_cancel bd_info->bi_op_cancel
#define be_chk_referrals bd_info->bi_chk_referrals
#define be_chk_controls bd_info->bi_chk_controls
#define be_entry_put bd_info->bi_tool_entry_put
#define be_sync bd_info->bi_tool_sync
#define be_dn2id_get bd_info->bi_tool_dn2id_get
-#define be_id2entry_get bd_info->bi_tool_id2entry_get
#define be_entry_modify bd_info->bi_tool_entry_modify
#endif
slap_access_t be_dfltaccess; /* access given if no acl matches */
/* Replica Information */
- struct slap_replica_info **be_replica; /* replicas of this backend (in master) */
- char *be_replogfile; /* replication log file (in master) */
- char *be_replica_argsfile; /* per-replog replica args file */
- char *be_replica_pidfile; /* per-replog replica pid file */
- int be_replicationinterval; /* per-replog replicationinterval */
struct berval be_update_ndn; /* allowed to make changes (in replicas) */
BerVarray be_update_refs; /* where to refer modifying clients to */
struct be_pcl *be_pending_csn_list;
struct ConfigOCs *be_cf_ocs;
void *be_private; /* anything the backend database needs */
- LDAP_STAILQ_ENTRY(slap_backend_db) be_next;
+ LDAP_STAILQ_ENTRY(BackendDB) be_next;
};
-struct slap_conn;
-struct slap_op;
-
/* Backend function typedefs */
typedef int (BI_bi_func) LDAP_P((BackendInfo *bi));
typedef BI_bi_func BI_init;
const char *fname, int lineno,
int argc, char **argv));
-typedef int (BI_db_func) LDAP_P((Backend *bd));
+struct config_reply_s ; /* config.h */
+typedef int (BI_db_func) LDAP_P((Backend *bd, struct config_reply_s *c));
typedef BI_db_func BI_db_init;
typedef BI_db_func BI_db_open;
typedef BI_db_func BI_db_close;
struct berval rb_cred;
struct berval rb_edn;
slap_ssf_t rb_ssf;
- struct berval rb_tmp_mech; /* FIXME: temporary */
+ struct berval rb_mech;
} req_bind_s;
typedef struct req_search_s {
AttributeAssertion *rs_ava;
} req_compare_s;
-typedef struct req_modify_s {
+typedef struct req_modifications_s {
Modifications *rs_modlist;
- int rs_increment; /* FIXME: temporary */
char rs_no_opattrs; /* don't att modify operational attrs */
+} req_modifications_s;
+
+typedef struct req_modify_s {
+ req_modifications_s rs_mods; /* NOTE: must be first in req_modify_s & req_modrdn_s */
+ int rs_increment;
} req_modify_s;
typedef struct req_modrdn_s {
- Modifications *rs_modlist;
+ req_modifications_s rs_mods; /* NOTE: must be first in req_modify_s & req_modrdn_s */
+ int rs_deleteoldrdn;
struct berval rs_newrdn;
struct berval rs_nnewrdn;
struct berval *rs_newSup;
struct berval *rs_nnewSup;
- int rs_deleteoldrdn;
} req_modrdn_s;
typedef struct req_add_s {
- Modifications *rs_modlist; /* FIXME: temporary */
+ Modifications *rs_modlist;
Entry *rs_e;
} req_add_s;
BerVarray r_v2ref;
} rep_search_s;
-typedef struct slap_rep {
+struct SlapReply {
slap_reply_t sr_type;
ber_tag_t sr_tag;
ber_int_t sr_msgid;
#define REP_NO_ENTRYDN 0x1000U
#define REP_NO_SUBSCHEMA 0x2000U
#define REP_NO_OPERATIONALS (REP_NO_ENTRYDN|REP_NO_SUBSCHEMA)
-} SlapReply;
+};
/* short hands for response members */
#define sr_attrs sr_un.sru_search.r_attrs
#define sr_rspdata sr_un.sru_extended.r_rspdata
#define sr_sasldata sr_un.sru_sasl.r_sasldata
-typedef int (BI_op_func) LDAP_P(( struct slap_op *op, struct slap_rep *rs ));
+typedef int (BI_op_func) LDAP_P(( Operation *op, SlapReply *rs ));
typedef BI_op_func BI_op_bind;
typedef BI_op_func BI_op_unbind;
typedef BI_op_func BI_op_search;
typedef BI_op_func BI_op_add;
typedef BI_op_func BI_op_delete;
typedef BI_op_func BI_op_abandon;
-typedef BI_op_func BI_op_cancel;
typedef BI_op_func BI_op_extended;
+typedef BI_op_func BI_op_cancel;
typedef BI_op_func BI_chk_referrals;
typedef BI_op_func BI_chk_controls;
typedef int (BI_entry_release_rw)
- LDAP_P(( struct slap_op *op, Entry *e, int rw ));
-typedef int (BI_entry_get_rw) LDAP_P(( struct slap_op *op, struct berval *ndn,
+ LDAP_P(( Operation *op, Entry *e, int rw ));
+typedef int (BI_entry_get_rw) LDAP_P(( Operation *op, struct berval *ndn,
ObjectClass *oc, AttributeDescription *at, int rw, Entry **e ));
-typedef int (BI_operational) LDAP_P(( struct slap_op *op, struct slap_rep *rs ));
-typedef int (BI_has_subordinates) LDAP_P(( struct slap_op *op,
+typedef int (BI_operational) LDAP_P(( Operation *op, SlapReply *rs ));
+typedef int (BI_has_subordinates) LDAP_P(( Operation *op,
Entry *e, int *hasSubs ));
-typedef int (BI_access_allowed) LDAP_P(( struct slap_op *op, Entry *e,
+typedef int (BI_access_allowed) LDAP_P(( Operation *op, Entry *e,
AttributeDescription *desc, struct berval *val, slap_access_t access,
AccessControlState *state, slap_mask_t *maskp ));
-typedef int (BI_acl_group) LDAP_P(( struct slap_op *op, Entry *target,
+typedef int (BI_acl_group) LDAP_P(( Operation *op, Entry *target,
struct berval *gr_ndn, struct berval *op_ndn,
ObjectClass *group_oc, AttributeDescription *group_at ));
-typedef int (BI_acl_attribute) LDAP_P(( struct slap_op *op, Entry *target,
+typedef int (BI_acl_attribute) LDAP_P(( Operation *op, Entry *target,
struct berval *entry_ndn, AttributeDescription *entry_at,
BerVarray *vals, slap_access_t access ));
-typedef int (BI_conn_func) LDAP_P(( BackendDB *bd, struct slap_conn *c ));
+typedef int (BI_conn_func) LDAP_P(( BackendDB *bd, Connection *c ));
typedef BI_conn_func BI_connection_init;
typedef BI_conn_func BI_connection_destroy;
typedef int (BI_tool_entry_reindex) LDAP_P(( BackendDB *be, ID id, AttributeDescription **adv ));
typedef int (BI_tool_sync) LDAP_P(( BackendDB *be ));
typedef ID (BI_tool_dn2id_get) LDAP_P(( BackendDB *be, struct berval *dn ));
-typedef int (BI_tool_id2entry_get) LDAP_P(( BackendDB *be, ID id, Entry **e ));
typedef ID (BI_tool_entry_modify) LDAP_P(( BackendDB *be, Entry *e,
struct berval *text ));
-struct slap_backend_info {
+struct BackendInfo {
char *bi_type; /* type of backend */
/*
BI_op_add *bi_op_add;
BI_op_delete *bi_op_delete;
BI_op_abandon *bi_op_abandon;
- BI_op_cancel *bi_op_cancel;
/* Extended Operations Helper */
BI_op_extended *bi_extended;
+ BI_op_cancel *bi_op_cancel;
/* Auxilary Functions */
BI_operational *bi_operational;
BI_tool_entry_reindex *bi_tool_entry_reindex;
BI_tool_sync *bi_tool_sync;
BI_tool_dn2id_get *bi_tool_dn2id_get;
- BI_tool_id2entry_get *bi_tool_id2entry_get;
BI_tool_entry_modify *bi_tool_entry_modify;
#define SLAP_INDEX_ADD_OP 0x0001
char **bi_obsolete_names;
void *bi_extra; /* backend type-specific APIs */
void *bi_private; /* backend type-specific config data */
- LDAP_STAILQ_ENTRY(slap_backend_info) bi_next ;
+ LDAP_STAILQ_ENTRY(BackendInfo) bi_next ;
};
#define c_authtype c_authz.sai_method
#define c_authmech c_authz.sai_mech
#define c_dn c_authz.sai_dn
#define c_ndn c_authz.sai_ndn
-#define c_ssf c_authz.sai_ssf
+#define c_ssf c_authz.sai_ssf
#define c_transport_ssf c_authz.sai_transport_ssf
-#define c_tls_ssf c_authz.sai_tls_ssf
-#define c_sasl_ssf c_authz.sai_sasl_ssf
+#define c_tls_ssf c_authz.sai_tls_ssf
+#define c_sasl_ssf c_authz.sai_sasl_ssf
#define o_authtype o_authz.sai_method
#define o_authmech o_authz.sai_mech
#define o_dn o_authz.sai_dn
#define o_ndn o_authz.sai_ndn
-#define o_ssf o_authz.sai_ssf
+#define o_ssf o_authz.sai_ssf
#define o_transport_ssf o_authz.sai_transport_ssf
-#define o_tls_ssf o_authz.sai_tls_ssf
-#define o_sasl_ssf o_authz.sai_sasl_ssf
+#define o_tls_ssf o_authz.sai_tls_ssf
+#define o_sasl_ssf o_authz.sai_sasl_ssf
-typedef int (slap_response)( struct slap_op *, struct slap_rep * );
+typedef int (slap_response)( Operation *, SlapReply * );
typedef struct slap_callback {
struct slap_callback *sc_next;
op_add,
op_delete,
op_abandon,
- op_cancel,
op_extended,
+ op_cancel,
op_aux_operational,
op_aux_chk_referrals,
op_aux_chk_controls,
* Paged Results state
*/
typedef unsigned long PagedResultsCookie;
-typedef struct slap_paged_state {
+typedef struct PagedResultsState {
Backend *ps_be;
ber_int_t ps_size;
PagedResultsCookie ps_cookie;
/*
* Caches the result of a backend_group check for ACL evaluation
*/
-typedef struct slap_gacl {
- struct slap_gacl *ga_next;
+typedef struct GroupAssertion {
+ struct GroupAssertion *ga_next;
Backend *ga_be;
ObjectClass *ga_oc;
AttributeDescription *ga_at;
int sc_proxyAuthz;
int sc_relax;
int sc_searchOptions;
-#ifdef SLAP_SORTEDRESULTS
+#ifdef SLAP_CONTROL_X_SORTEDRESULTS
int sc_sortedResults;
#endif
int sc_subentries;
+#ifdef SLAP_CONTROL_X_TREE_DELETE
int sc_treeDelete;
+#endif
#ifdef LDAP_X_TXN
int sc_txnSpec;
+#endif
+#ifdef SLAP_CONTROL_X_SESSION_TRACKING
+ int sc_sessionTracking;
#endif
int sc_valuesReturnFilter;
};
/*
* represents an operation pending from an ldap client
*/
-typedef struct slap_op_header {
- unsigned long oh_opid; /* id of this operation */
- unsigned long oh_connid; /* id of conn initiating this op */
- struct slap_conn *oh_conn; /* connection spawning this op */
+typedef struct Opheader {
+ unsigned long oh_opid; /* id of this operation */
+ unsigned long oh_connid; /* id of conn initiating this op */
+ Connection *oh_conn; /* connection spawning this op */
ber_int_t oh_msgid; /* msgid of the request */
ber_int_t oh_protocol; /* version of the LDAP protocol used by client */
void *oh_tmpmemctx; /* slab malloc context */
BerMemoryFunctions *oh_tmpmfuncs;
- char oh_log_prefix[sizeof("conn=18446744073709551615 op=18446744073709551615")];
+ char oh_log_prefix[ /* sizeof("conn=18446744073709551615 op=18446744073709551615") */ SLAP_TEXT_BUFLEN ];
#ifdef LDAP_SLAPI
void *oh_extensions; /* NS-SLAPI plugin */
#endif
} Opheader;
-typedef union slap_op_request {
+typedef union OpRequest {
req_add_s oq_add;
req_bind_s oq_bind;
req_compare_s oq_compare;
req_pwdexop_s oq_pwdexop;
} OpRequest;
-typedef struct slap_op {
+struct Operation {
Opheader *o_hdr;
#define o_opid o_hdr->oh_opid
#define orb_cred oq_bind.rb_cred
#define orb_edn oq_bind.rb_edn
#define orb_ssf oq_bind.rb_ssf
-#define orb_tmp_mech oq_bind.rb_tmp_mech
+#define orb_mech oq_bind.rb_mech
#define ors_scope oq_search.rs_scope
#define ors_deref oq_search.rs_deref
#define ors_filter oq_search.rs_filter
#define ors_filterstr oq_search.rs_filterstr
+#define orr_modlist oq_modrdn.rs_mods.rs_modlist
+#define orr_no_opattrs oq_modrdn.rs_mods.rs_no_opattrs
+#define orr_deleteoldrdn oq_modrdn.rs_deleteoldrdn
#define orr_newrdn oq_modrdn.rs_newrdn
#define orr_nnewrdn oq_modrdn.rs_nnewrdn
#define orr_newSup oq_modrdn.rs_newSup
#define orr_nnewSup oq_modrdn.rs_nnewSup
-#define orr_deleteoldrdn oq_modrdn.rs_deleteoldrdn
-#define orr_modlist oq_modrdn.rs_modlist
#define orc_ava oq_compare.rs_ava
+
#define ora_e oq_add.rs_e
#define ora_modlist oq_add.rs_modlist
+
#define orn_msgid oq_abandon.rs_msgid
-#define orm_modlist oq_modify.rs_modlist
+
+#define orm_modlist oq_modify.rs_mods.rs_modlist
+#define orm_no_opattrs oq_modify.rs_mods.rs_no_opattrs
#define orm_increment oq_modify.rs_increment
-#define orm_no_opattrs oq_modify.rs_no_opattrs
#define ore_reqoid oq_extended.rs_reqoid
#define ore_flags oq_extended.rs_flags
#define o_domain_scope o_ctrlflag[slap_cids.sc_domainScope]
#define get_domainScope(op) ((int)(op)->o_domain_scope)
+#ifdef SLAP_CONTROL_X_TREE_DELETE
#define o_tree_delete o_ctrlflag[slap_cids.sc_treeDelete]
#define get_treeDelete(op) ((int)(op)->o_tree_delete)
+#endif
#define o_preread o_ctrlflag[slap_cids.sc_preRead]
#define o_postread o_ctrlflag[slap_cids.sc_postRead]
#define o_pagedresults_state o_controls[slap_cids.sc_pagedResults]
#define get_pagedresults(op) ((int)(op)->o_pagedresults)
-#ifdef SLAP_SORTEDRESULTS
+#ifdef SLAP_CONTROL_X_SORTEDRESULTS
#define o_sortedresults o_ctrlflag[slap_cids.sc_sortedResults]
#endif
#define o_txnSpec o_ctrlflag[slap_cids.sc_txnSpec]
#endif
+#ifdef SLAP_CONTROL_X_SESSION_TRACKING
+#define o_session_tracking o_ctrlflag[slap_cids.sc_sessionTracking]
+#define o_tracked_sessions o_controls[slap_cids.sc_sessionTracking]
+#define get_sessionTracking(op) ((int)(op)->o_session_tracking)
+#endif
+
#define o_sync o_ctrlflag[slap_cids.sc_LDAPsync]
AuthorizationInformation o_authz;
void *o_private; /* anything the backend needs */
- LDAP_STAILQ_ENTRY(slap_op) o_next; /* next operation in list */
-} Operation;
-
-#define OPERATION_BUFFER_SIZE ( sizeof(Operation) + sizeof(Opheader) + \
- SLAP_MAX_CIDS*sizeof(void *) )
+ LDAP_STAILQ_ENTRY(Operation) o_next; /* next operation in list */
+};
-typedef LBER_ALIGNED_BUFFER(operation_buffer_u,OPERATION_BUFFER_SIZE)
- OperationBuffer;
+typedef struct OperationBuffer {
+ Operation ob_op;
+ Opheader ob_hdr;
+ void *ob_controls[SLAP_MAX_CIDS];
+} OperationBuffer;
#define send_ldap_error( op, rs, err, text ) do { \
(rs)->sr_err = err; (rs)->sr_text = text; \
} while (0)
typedef void (SEND_LDAP_RESULT)(
- struct slap_op *op, struct slap_rep *rs);
+ Operation *op, SlapReply *rs);
typedef int (SEND_SEARCH_ENTRY)(
- struct slap_op *op, struct slap_rep *rs);
+ Operation *op, SlapReply *rs);
typedef int (SEND_SEARCH_REFERENCE)(
- struct slap_op *op, struct slap_rep *rs);
+ Operation *op, SlapReply *rs);
typedef void (SEND_LDAP_EXTENDED)(
- struct slap_op *op, struct slap_rep *rs);
+ Operation *op, SlapReply *rs);
typedef void (SEND_LDAP_INTERMEDIATE)(
- struct slap_op *op, struct slap_rep *rs);
+ Operation *op, SlapReply *rs);
#define send_ldap_result( op, rs ) \
((op)->o_conn->c_send_ldap_result)( op, rs )
/*
* represents a connection from an ldap client
*/
-typedef struct slap_conn {
+struct Connection {
int c_struct_state; /* structure management state */
int c_conn_state; /* connection state */
int c_conn_idx; /* slot in connections array */
ber_int_t c_protocol; /* version of the LDAP protocol used by client */
- LDAP_STAILQ_HEAD(c_o, slap_op) c_ops; /* list of operations being processed */
- LDAP_STAILQ_HEAD(c_po, slap_op) c_pending_ops; /* list of pending operations */
+ LDAP_STAILQ_HEAD(c_o, Operation) c_ops; /* list of operations being processed */
+ LDAP_STAILQ_HEAD(c_po, Operation) c_pending_ops; /* list of pending operations */
ldap_pvt_thread_mutex_t c_write_mutex; /* only one pdu written at a time */
ldap_pvt_thread_cond_t c_write_cv; /* used to wait for sd write-ready*/
#define CONN_IS_TLS 1
#define CONN_IS_UDP 2
-#define CONN_IS_CLIENT 3
+#define CONN_IS_CLIENT 4
+#define CONN_IS_IPC 8
#ifdef LDAP_CONNECTIONLESS
int c_is_udp; /* true if this is (C)LDAP over UDP */
void *c_sasl_authctx; /* SASL authentication context */
void *c_sasl_sockctx; /* SASL security layer context */
void *c_sasl_extra; /* SASL session extra stuff */
- struct slap_op *c_sasl_bindop; /* set to current op if it's a bind */
+ Operation *c_sasl_bindop; /* set to current op if it's a bind */
#ifdef LDAP_X_TXN
#define CONN_TXN_INACTIVE 0
int c_txn;
Backend *c_txn_backend;
- LDAP_STAILQ_HEAD(c_to, slap_op) c_txn_ops; /* list of operations in txn */
+ LDAP_STAILQ_HEAD(c_to, Operation) c_txn_ops; /* list of operations in txn */
#endif
PagedResultsState c_pagedresults_state; /* paged result state */
SEND_SEARCH_REFERENCE *c_send_search_reference;
SEND_LDAP_EXTENDED *c_send_ldap_extended;
SEND_LDAP_INTERMEDIATE *c_send_ldap_intermediate;
-} Connection;
+};
#ifdef LDAP_DEBUG
#ifdef LDAP_SYSLOG
typedef enum {
SLAP_OP_BIND = 0,
SLAP_OP_UNBIND,
+ SLAP_OP_SEARCH,
+ SLAP_OP_COMPARE,
+ SLAP_OP_MODIFY,
+ SLAP_OP_MODRDN,
SLAP_OP_ADD,
SLAP_OP_DELETE,
- SLAP_OP_MODRDN,
- SLAP_OP_MODIFY,
- SLAP_OP_COMPARE,
- SLAP_OP_SEARCH,
SLAP_OP_ABANDON,
SLAP_OP_EXTENDED,
SLAP_OP_LAST
#define LDAP_COMP_FILTER_ITEM ((ber_tag_t) 0xa3U)
#define LDAP_COMP_FILTER_UNDEFINED ((ber_tag_t) 0xa4U)
-typedef struct slap_component_id {
- int ci_type;
- struct slap_component_id *ci_next;
+typedef struct ComponentId ComponentId;
+typedef struct ComponentReference ComponentReference;
+typedef struct ComponentAssertion ComponentAssertion;
+typedef struct ComponentAssertionValue ComponentAssertionValue;
+typedef struct ComponentSyntaxInfo ComponentSyntaxInfo;
+typedef struct ComponentDesc ComponentDesc;
+
+struct ComponentData {
+ void *cd_mem_op; /* nibble memory handler */
+ ComponentSyntaxInfo** cd_tree; /* component tree */
+};
+
+struct ComponentId {
+ int ci_type;
+ ComponentId *ci_next;
union comp_id_value{
BerValue ci_identifier;
BerValue ci_select_value;
char ci_all;
} ci_val;
-} ComponentId;
+};
-typedef struct slap_component_reference {
+struct ComponentReference {
ComponentId *cr_list;
ComponentId *cr_curr;
struct berval cr_string;
slap_mask_t cr_indexmask;
AttributeDescription* cr_ad;
BerVarray cr_nvals;
- struct slap_component_reference* cr_next;
-} ComponentReference;
+ ComponentReference* cr_next;
+};
-typedef struct slap_component_assertion {
+struct ComponentAssertion {
ComponentReference *ca_comp_ref;
ber_int_t ca_use_def;
MatchingRule *ca_ma_rule;
struct berval ca_ma_value;
ComponentData ca_comp_data; /* componentized assertion */
- struct slap_component_filter *ca_cf;
+ ComponentFilter *ca_cf;
MatchingRuleAssertion *ca_mra;
-} ComponentAssertion;
+};
-typedef struct slap_component_filter {
- ber_tag_t cf_choice;
+struct ComponentFilter {
+ ber_tag_t cf_choice;
union cf_un_u {
- ber_int_t cf_un_result;
- ComponentAssertion *cf_un_ca;
- struct slap_component_filter *cf_un_complex;
+ ber_int_t cf_un_result;
+ ComponentAssertion *cf_un_ca;
+ ComponentFilter *cf_un_complex;
} cf_un;
#define cf_ca cf_un.cf_un_ca
#define cf_not cf_un.cf_un_complex
#define cf_any cf_un.cf_un_complex
- struct slap_component_filter *cf_next;
-} ComponentFilter;
+ ComponentFilter *cf_next;
+};
-typedef struct slap_component_assertion_value {
+struct ComponentAssertionValue {
char* cav_buf;
char* cav_ptr;
char* cav_end;
-} ComponentAssertionValue;
+};
typedef int encoder_func LDAP_P((
void* b,
void* comp));
-struct slap_component_syntax_info;
-
typedef int gser_decoder_func LDAP_P((
void* mem_op,
void* b,
- struct slap_component_syntax_info** comp_syn_info,
+ ComponentSyntaxInfo** comp_syn_info,
int* len,
int mode));
void* b,
int tag,
int elmtLen,
- struct slap_component_syntax_info* comp_syn_info,
+ ComponentSyntaxInfo* comp_syn_info,
int* len,
int mode));
typedef int ber_tag_decoder_func LDAP_P((
void* mem_op,
void* b,
- struct slap_component_syntax_info* comp_syn_info,
+ ComponentSyntaxInfo* comp_syn_info,
int* len,
int mode));
typedef void free_nibble_func LDAP_P ((
void* nm ));
-struct slap_component_syntax_info;
typedef void convert_assert_to_comp_func LDAP_P ((
void *mem_op,
- struct slap_component_syntax_info* csi_attr,
+ ComponentSyntaxInfo* csi_attr,
struct berval* bv,
- struct slap_component_syntax_info** csi,
+ ComponentSyntaxInfo** csi,
int* len,
int mode ));
typedef int convert_asn_to_ldap_func LDAP_P ((
- struct slap_component_syntax_info* csi,
+ ComponentSyntaxInfo* csi,
struct berval *bv ));
typedef void free_component_func LDAP_P ((
typedef int test_component_func LDAP_P ((
void* attr_mem_op,
void* assert_mem_op,
- struct slap_component_syntax_info* csi,
- struct slap_component_assertion* ca));
+ ComponentSyntaxInfo* csi,
+ ComponentAssertion* ca));
typedef void* test_membership_func LDAP_P ((
void* in ));
typedef void* get_component_info_func LDAP_P ((
int in ));
-struct slap_component_syntax_info;
-
typedef int component_encoder_func LDAP_P ((
void* mem_op,
- struct slap_component_syntax_info* csi,
+ ComponentSyntaxInfo* csi,
struct berval* nvals ));
typedef int allcomponent_matching_func LDAP_P((
char* oid,
- struct slap_component_syntax_info* comp1,
- struct slap_component_syntax_info* comp));
+ ComponentSyntaxInfo* comp1,
+ ComponentSyntaxInfo* comp));
-typedef struct slap_component_desc {
+struct ComponentDesc {
/* Don't change the order of following four fields */
- int cd_tag;
- AttributeType *cd_comp_type;
- struct berval cd_ad_type;/* ad_type, ad_cname */
- struct berval cd_ad_cname;/* ad_type, ad_cname */
- unsigned cd_flags; /*ad_flags*/
- int cd_type;
- int cd_type_id;
- encoder_func *cd_ldap_encoder;
- encoder_func *cd_gser_encoder;
- encoder_func *cd_ber_encoder;
- gser_decoder_func *cd_gser_decoder;
- ber_decoder_func *cd_ber_decoder;
- comp_free_func *cd_free;
+ int cd_tag;
+ AttributeType *cd_comp_type;
+ struct berval cd_ad_type; /* ad_type, ad_cname */
+ struct berval cd_ad_cname; /* ad_type, ad_cname */
+ unsigned cd_flags; /* ad_flags */
+ int cd_type;
+ int cd_type_id;
+ encoder_func *cd_ldap_encoder;
+ encoder_func *cd_gser_encoder;
+ encoder_func *cd_ber_encoder;
+ gser_decoder_func *cd_gser_decoder;
+ ber_decoder_func *cd_ber_decoder;
+ comp_free_func *cd_free;
extract_component_from_id_func* cd_extract_i;
allcomponent_matching_func *cd_all_match;
-} ComponentDesc;
+};
-typedef struct slap_component_syntax_info {
- Syntax* csi_syntax;
- ComponentDesc* csi_comp_desc;
-} ComponentSyntaxInfo;
+struct ComponentSyntaxInfo {
+ Syntax *csi_syntax;
+ ComponentDesc *csi_comp_desc;
+};
-#endif
+#endif /* LDAP_COMP_MATCH */
/* slab heap data structures */
argv = &argv[ optind ];
argc -= optind;
- op = (Operation *) &opbuf;
- connection_fake_init( &conn, op, &conn );
+ connection_fake_init( &conn, &opbuf, &conn );
+ op = &opbuf.ob_op;
conn.c_listener = &listener;
conn.c_listener_url = listener_url;
if ( !be->be_entry_open ||
!be->be_entry_close ||
!be->be_dn2id_get ||
- !be->be_id2entry_get )
+ !be->be_entry_get )
{
fprintf( stderr, "%s: target database "
"doesn't support necessary operations; "
rc = 1;
goto destroy;
}
- if ( be->be_id2entry_get( be, id, &ep ) != 0 ) {
+ ep = be->be_entry_get( be, id );
+ if ( ep == NULL ) {
fprintf( stderr, "%s: unable to fetch entry \"%s\" (%lu)\n",
progname, e.e_nname.bv_val, id );
rc = 1;
ber_memfree( e.e_nname.bv_val );
}
if ( !dryrun && be ) {
- if ( ep != &e ) {
+ if ( ep && ep != &e ) {
be_entry_release_r( op, ep );
}
if ( doclose ) {
#include "slapcommon.h"
static char csnbuf[ LDAP_LUTIL_CSNSTR_BUFSIZE ];
-static char maxcsnbuf[ LDAP_LUTIL_CSNSTR_BUFSIZE ];
+static char maxcsnbuf[ LDAP_LUTIL_CSNSTR_BUFSIZE * ( SLAP_SYNC_SID_MAX + 1 ) ];
int
slapadd( int argc, char **argv )
const char *progname = "slapadd";
struct berval csn;
- struct berval maxcsn;
+ struct berval maxcsn[ SLAP_SYNC_SID_MAX + 1 ];
+ unsigned long sid;
struct berval bvtext;
Attribute *attr;
Entry *ctxcsn_e;
Operation *op;
int match;
- int ret;
int checkvals;
int lineno, nextline;
int lmax;
int rc = EXIT_SUCCESS;
int manage = 0;
+ /* default "000" */
+ csnsid = 0;
+
slap_tool_init( progname, SLAPADD, argc, argv );
memset( &opbuf, 0, sizeof(opbuf) );
- op = (Operation *) &opbuf;
- op->o_hdr = (Opheader *)(op+1);
+ op = &opbuf.ob_op;
+ op->o_hdr = &opbuf.ob_hdr;
if( !be->be_entry_open ||
!be->be_entry_close ||
!be->be_entry_put ||
(update_ctxcsn &&
(!be->be_dn2id_get ||
- !be->be_id2entry_get ||
+ !be->be_entry_get ||
!be->be_entry_modify)) )
{
fprintf( stderr, "%s: database doesn't support necessary operations.\n",
lmax = 0;
nextline = 0;
+ /* enforce schema checking unless not disabled */
+ if ( (slapMode & SLAP_TOOL_NO_SCHEMA_CHECK) == 0) {
+ SLAP_DBFLAGS(be) &= ~(SLAP_DBFLAG_NO_SCHEMA_CHECK);
+ }
+
if( !dryrun && be->be_entry_open( be, 1 ) != 0 ) {
fprintf( stderr, "%s: could not open database.\n",
progname );
}
if ( update_ctxcsn ) {
- maxcsn.bv_val = maxcsnbuf;
- maxcsn.bv_len = 0;
+ maxcsn[ 0 ].bv_val = maxcsnbuf;
+ for ( sid = 1; sid <= SLAP_SYNC_SID_MAX; sid++ ) {
+ maxcsn[ sid ].bv_val = maxcsn[ sid - 1 ].bv_val + LDAP_LUTIL_CSNSTR_BUFSIZE;
+ maxcsn[ sid ].bv_len = 0;
+ }
}
/* nextline is the line number of the end of the current entry */
}
/* check backend */
- if( select_backend( &e->e_nname, is_entry_referral(e), nosubordinates )
+ if( select_backend( &e->e_nname, nosubordinates )
!= be )
{
fprintf( stderr, "%s: line %d: "
nvals[1].bv_len = 0;
nvals[1].bv_val = NULL;
- csn.bv_len = lutil_csnstr( csnbuf, sizeof( csnbuf ), 0, 0 );
+ csn.bv_len = lutil_csnstr( csnbuf, sizeof( csnbuf ), csnsid, 0 );
csn.bv_val = csnbuf;
timestamp.bv_val = timebuf;
}
if ( update_ctxcsn ) {
+ int rc_sid;
+
attr = attr_find( e->e_attrs, slap_schema.si_ad_entryCSN );
- if ( maxcsn.bv_len != 0 ) {
- match = 0;
- value_match( &match, slap_schema.si_ad_entryCSN,
- slap_schema.si_ad_entryCSN->ad_type->sat_ordering,
- SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
- &maxcsn, &attr->a_nvals[0], &text );
+ assert( attr != NULL );
+
+ rc_sid = slap_parse_csn_sid( &attr->a_nvals[ 0 ] );
+ if ( rc_sid < 0 ) {
+ Debug( LDAP_DEBUG_ANY, "%s: could not "
+ "extract SID from entryCSN=%s\n",
+ progname, attr->a_nvals[ 0 ].bv_val, 0 );
+
} else {
- match = -1;
- }
- if ( match < 0 ) {
- strcpy( maxcsn.bv_val, attr->a_nvals[0].bv_val );
- maxcsn.bv_len = attr->a_nvals[0].bv_len;
+ assert( rc_sid <= SLAP_SYNC_SID_MAX );
+
+ sid = (unsigned)rc_sid;
+ if ( maxcsn[ sid ].bv_len != 0 ) {
+ match = 0;
+ value_match( &match, slap_schema.si_ad_entryCSN,
+ slap_schema.si_ad_entryCSN->ad_type->sat_ordering,
+ SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
+ &maxcsn[ sid ], &attr->a_nvals[0], &text );
+ } else {
+ match = -1;
+ }
+ if ( match < 0 ) {
+ strcpy( maxcsn[ sid ].bv_val, attr->a_nvals[0].bv_val );
+ maxcsn[ sid ].bv_len = attr->a_nvals[0].bv_len;
+ }
}
}
}
bvtext.bv_val = textbuf;
bvtext.bv_val[0] = '\0';
- if ( rc == EXIT_SUCCESS && update_ctxcsn && !dryrun && maxcsn.bv_len ) {
+ if ( rc == EXIT_SUCCESS && update_ctxcsn && !dryrun && sid != SLAP_SYNC_SID_MAX + 1 ) {
ctxcsn_id = be->be_dn2id_get( be, be->be_nsuffix );
if ( ctxcsn_id == NOID ) {
fprintf( stderr, "%s: context entry is missing\n", progname );
rc = EXIT_FAILURE;
} else {
- ret = be->be_id2entry_get( be, ctxcsn_id, &ctxcsn_e );
- if ( ret == LDAP_SUCCESS ) {
- attr = attr_find( ctxcsn_e->e_attrs,
- slap_schema.si_ad_contextCSN );
+ ctxcsn_e = be->be_entry_get( be, ctxcsn_id );
+ if ( ctxcsn_e != NULL ) {
+ Entry *e = entry_dup( ctxcsn_e );
+ attr = attr_find( e->e_attrs, slap_schema.si_ad_contextCSN );
if ( attr ) {
- value_match( &match, slap_schema.si_ad_entryCSN,
- slap_schema.si_ad_entryCSN->ad_type->sat_ordering,
- SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
- &maxcsn, &attr->a_nvals[0], &text );
- if ( match > 0 ) {
- AC_MEMCPY( attr->a_vals[0].bv_val, maxcsn.bv_val, maxcsn.bv_len );
- attr->a_vals[0].bv_val[maxcsn.bv_len] = '\0';
- attr->a_vals[0].bv_len = maxcsn.bv_len;
+ int i;
+
+ for ( i = 0; !BER_BVISNULL( &attr->a_nvals[ i ] ); i++ ) {
+ int rc_sid;
+
+ rc_sid = slap_parse_csn_sid( &attr->a_nvals[ i ] );
+ if ( rc_sid < 0 ) {
+ Debug( LDAP_DEBUG_ANY,
+ "%s: unable to extract SID "
+ "from #%d contextCSN=%s\n",
+ progname, i,
+ attr->a_nvals[ i ].bv_val );
+ continue;
+ }
+
+ assert( rc_sid <= SLAP_SYNC_SID_MAX );
+
+ sid = (unsigned)rc_sid;
+
+ if ( maxcsn[ sid ].bv_len == 0 ) {
+ match = -1;
+
+ } else {
+ value_match( &match, slap_schema.si_ad_entryCSN,
+ slap_schema.si_ad_entryCSN->ad_type->sat_ordering,
+ SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
+ &maxcsn[ sid ], &attr->a_nvals[i], &text );
+ }
+
+ if ( match < 0 ) {
+ AC_MEMCPY( maxcsn[ sid ].bv_val,
+ attr->a_nvals[ i ].bv_val,
+ attr->a_nvals[ i ].bv_len );
+ maxcsn[ sid ].bv_val[ attr->a_nvals[ i ].bv_len ] = '\0';
+ maxcsn[ sid ].bv_len = attr->a_nvals[ i ].bv_len;
+ }
}
- } else {
- match = 1;
- attr_merge_one( ctxcsn_e, slap_schema.si_ad_contextCSN, &maxcsn, NULL );
+
+ if ( attr->a_nvals != attr->a_nvals ) {
+ ber_bvarray_free( attr->a_nvals );
+ }
+ attr->a_nvals = NULL;
+ ber_bvarray_free( attr->a_vals );
+ attr->a_vals = NULL;
}
- if ( match > 0 ) {
- ctxcsn_id = be->be_entry_modify( be, ctxcsn_e, &bvtext );
- if( ctxcsn_id == NOID ) {
- fprintf( stderr, "%s: could not modify ctxcsn\n",
- progname);
- rc = EXIT_FAILURE;
- } else if ( verbose ) {
- fprintf( stderr, "modified: \"%s\" (%08lx)\n",
- ctxcsn_e->e_dn, (long) ctxcsn_id );
+
+ for ( sid = 0; sid <= SLAP_SYNC_SID_MAX; sid++ ) {
+ if ( maxcsn[ sid ].bv_len ) {
+ attr_merge_one( e, slap_schema.si_ad_contextCSN,
+ &maxcsn[ sid], NULL );
}
}
+
+ ctxcsn_id = be->be_entry_modify( be, e, &bvtext );
+ if( ctxcsn_id == NOID ) {
+ fprintf( stderr, "%s: could not modify ctxcsn\n",
+ progname);
+ rc = EXIT_FAILURE;
+ } else if ( verbose ) {
+ fprintf( stderr, "modified: \"%s\" (%08lx)\n",
+ e->e_dn, (long) ctxcsn_id );
+ }
+ entry_free( e );
}
}
}
argv = &argv[ optind ];
argc -= optind;
- op = (Operation *) &opbuf;
- connection_fake_init( &conn, op, &conn );
+ connection_fake_init( &conn, &opbuf, &conn );
+ op = &opbuf.ob_op;
conn.c_sasl_bind_mech = mech;
static LDIFFP dummy;
-#ifdef LDAP_SYSLOG
+#if defined(LDAP_SYSLOG) && defined(LDAP_DEBUG)
int start_syslog;
static char **syslog_unknowns;
#ifdef LOG_LOCAL4
static int syslogUser = SLAP_DEFAULT_SYSLOG_USER;
#endif /* LOG_LOCAL4 */
-#endif /* LDAP_SYSLOG */
+#endif /* LDAP_DEBUG && LDAP_SYSLOG */
static void
usage( int tool, const char *progname )
} else if ( strncasecmp( optarg, "authzDN", len ) == 0 ) {
ber_str2bv( p, 0, 1, &authzDN );
-#ifdef LDAP_SYSLOG
+#if defined(LDAP_SYSLOG) && defined(LDAP_DEBUG)
} else if ( strncasecmp( optarg, "syslog", len ) == 0 ) {
if ( parse_debug_level( p, &ldap_syslog, &syslog_unknowns ) ) {
return -1;
}
start_syslog = 1;
#endif /* LOG_LOCAL4 */
-#endif /* LDAP_SYSLOG */
+#endif /* LDAP_DEBUG && LDAP_SYSLOG */
} else {
return -1;
switch( tool ) {
case SLAPADD:
- options = "b:cd:f:F:gj:l:n:o:qstuvw";
+ options = "b:cd:f:F:gj:l:n:o:qsS:tuvw";
break;
case SLAPCAT:
break;
case SLAPTEST:
- options = "d:f:F:o:uv";
+ options = "d:f:F:o:Quv";
mode |= SLAP_TOOL_READMAIN | SLAP_TOOL_READONLY;
break;
dn_mode = SLAP_TOOL_LDAPDN_PRETTY;
break;
+ case 'Q':
+ quiet++;
+ slap_debug = 0;
+ break;
+
case 'q': /* turn on quick */
mode |= SLAP_TOOL_QUICK;
break;
realm = optarg;
break;
+ case 'S':
+ if ( lutil_atoul( &csnsid, optarg )
+ || csnsid > SLAP_SYNC_SID_MAX )
+ {
+ usage( tool, progname );
+ }
+ break;
+
case 's': /* dump subtree */
if ( tool == SLAPADD )
mode |= SLAP_TOOL_NO_SCHEMA_CHECK;
}
}
-#ifdef LDAP_SYSLOG
+#if defined(LDAP_SYSLOG) && defined(LDAP_DEBUG)
if ( start_syslog ) {
char *logName;
#ifdef HAVE_EBCDIC
#ifdef LOG_LOCAL4
openlog( logName, OPENLOG_OPTIONS, syslogUser );
-#elif LOG_DEBUG
+#elif defined LOG_DEBUG
openlog( logName, OPENLOG_OPTIONS );
#endif
#ifdef HAVE_EBCDIC
free( logName );
#endif
}
-#endif /* LDAP_SYSLOG */
+#endif /* LDAP_DEBUG && LDAP_SYSLOG */
switch ( tool ) {
case SLAPADD:
exit( EXIT_FAILURE );
}
-#ifdef LDAP_SYSLOG
+#if defined(LDAP_SYSLOG) && defined(LDAP_DEBUG)
if ( syslog_unknowns ) {
rc = parse_debug_unknowns( syslog_unknowns, &ldap_syslog );
ldap_charray_free( syslog_unknowns );
exit( EXIT_FAILURE );
}
- be = select_backend( &nbase, 0, 0 );
+ be = select_backend( &nbase, 0 );
ber_memfree( nbase.bv_val );
switch ( tool ) {
if ( !BER_BVISNULL( &authcDN ) ) {
ch_free( authcDN.bv_val );
}
+
+ if ( ldiffp && ldiffp != &dummy ) {
+ ldif_close( ldiffp );
+ }
}
typedef struct tool_vars {
Backend *tv_be;
int tv_verbose;
+ int tv_quiet;
int tv_update_ctxcsn;
int tv_continuemode;
int tv_nosubordinates;
slap_ssf_t tv_tls_ssf;
slap_ssf_t tv_sasl_ssf;
unsigned tv_dn_mode;
+ unsigned int tv_csnsid;
} tool_vars;
extern tool_vars tool_globals;
#define be tool_globals.tv_be
#define verbose tool_globals.tv_verbose
+#define quiet tool_globals.tv_quiet
#define jumpline tool_globals.tv_jumpline
#define update_ctxcsn tool_globals.tv_update_ctxcsn
#define continuemode tool_globals.tv_continuemode
#define tls_ssf tool_globals.tv_tls_ssf
#define sasl_ssf tool_globals.tv_sasl_ssf
#define dn_mode tool_globals.tv_dn_mode
+#define csnsid tool_globals.tv_csnsid
#define SLAP_TOOL_LDAPDN_PRETTY SLAP_LDAPDN_PRETTY
#define SLAP_TOOL_LDAPDN_NORMAL (SLAP_LDAPDN_PRETTY << 1)
/*
* Quick 'n' dirty to make struct slapi_* in slapi-plugin.h opaque
*/
-#define slapi_entry slap_entry
-#define slapi_attr slap_attr
+#define slapi_entry Entry
+#define slapi_attr Attribute
#define slapi_value berval
#define slapi_valueset berval *
-#define slapi_filter slap_filter
+#define slapi_filter Filter
LDAP_END_DECL
LDAP_STAILQ_INIT( &conn->c_pending_ops );
- op = (Operation *) slapi_ch_calloc( 1, OPERATION_BUFFER_SIZE );
- op->o_hdr = (Opheader *)(op + 1);
- op->o_controls = (void **)(op->o_hdr + 1);
+ op = (Operation *) slapi_ch_calloc( 1, sizeof(OperationBuffer) );
+ op->o_hdr = &((OperationBuffer *) op)->ob_hdr;
+ op->o_controls = ((OperationBuffer *) op)->ob_controls;
op->o_callback = (slap_callback *) slapi_ch_calloc( 1, sizeof(slap_callback) );
op->o_callback->sc_response = slapi_int_response;
if ( BER_BVISNULL( &op->o_ndn ) ) {
/* set to root DN */
- be = select_backend( &op->o_req_ndn, get_manageDSAit( op ), 1 );
+ be = select_backend( &op->o_req_ndn, 1 );
if ( be != NULL ) {
ber_dupbv( &op->o_dn, &be->be_rootdn );
ber_dupbv( &op->o_ndn, &be->be_rootndn );
#include "slap.h"
#include "slapi.h"
+#include "config.h"
#ifdef LDAP_SLAPI
op->o_log_prefix,
BER_BVISNULL( &op->o_conn->c_dn )
? "<empty>" : op->o_conn->c_dn.bv_val,
- BER_BVISNULL( &op->orb_tmp_mech )
- ? "<empty>" : op->orb_tmp_mech.bv_val, 0, 0 );
+ BER_BVISNULL( &op->orb_mech )
+ ? "<empty>" : op->orb_mech.bv_val, 0, 0 );
return -1;
}
GroupAssertion *g;
SlapReply rs = { REP_RESULT };
- op->o_bd = select_backend( gr_ndn, 0, 0 );
+ op->o_bd = select_backend( gr_ndn, 0 );
for ( g = op->o_groups; g; g = g->ga_next ) {
if ( g->ga_be != op->o_bd || g->ga_oc != group_oc ||
}
static int
-slapi_over_db_open( BackendDB *be )
+slapi_over_db_open(
+ BackendDB *be,
+ ConfigReply *cr )
{
Slapi_PBlock *pb;
int rc;
}
static int
-slapi_over_db_close( BackendDB *be )
+slapi_over_db_close(
+ BackendDB *be,
+ ConfigReply *cr )
{
Slapi_PBlock *pb;
int rc;
op = pb->pb_op;
be_orig = op->o_bd;
- op->o_bd = select_backend( &op->o_req_ndn, 0, 0 );
+ op->o_bd = select_backend( &op->o_req_ndn, 0 );
rc = (*bep)( op );
op->o_bd = be_orig;
break;
case SLAPI_BACKEND:
PBLOCK_ASSERT_OP( pb, 0 );
- *((BackendDB **)value) = select_backend( &pb->pb_op->o_req_ndn, 0, 0 );
+ *((BackendDB **)value) = select_backend( &pb->pb_op->o_req_ndn, 0 );
break;
case SLAPI_BE_TYPE:
PBLOCK_ASSERT_OP( pb, 0 );
slapi_pblock_set( pb, SLAPI_TARGET_DN, slapi_entry_get_dn( (Entry *)e ) );
- pb->pb_op->o_bd = select_backend( (struct berval *)&e->e_nname, 0, 0 );
+ pb->pb_op->o_bd = select_backend( (struct berval *)&e->e_nname, 0 );
if ( pb->pb_op->o_bd != NULL ) {
pb->pb_op->o_bd->be_has_subordinates( pb->pb_op, (Entry *)e, &hasSubordinates );
}
ndn.bv_len = strlen( ldn );
ndn.bv_val = ldn;
- be = select_backend( &pb->pb_op->o_req_ndn, 0, 0 );
+ be = select_backend( &pb->pb_op->o_req_ndn, 0 );
if ( be == NULL ) {
return 0;
}
return NULL;
}
- be = select_backend( &pb->pb_op->o_req_ndn, 0, 0 );
+ be = select_backend( &pb->pb_op->o_req_ndn, 0 );
if ( be == NULL || be_issuffix( be, &normalizedDN ) == 0 ) {
dnParent( &prettyDN, &parentDN );
be_orig = pb->pb_op->o_bd;
- pb->pb_op->o_bd = select_backend( &e->e_nname, 0, 0 );
+ pb->pb_op->o_bd = select_backend( &e->e_nname, 0 );
if ( pb->pb_op->o_bd != NULL ) {
rc = entry_schema_check( pb->pb_op, e, NULL, 0, 0,
&text, textbuf, textlen );
slapi_sdn_get_ndn( sdn );
- be = select_backend( (struct berval *)&sdn->ndn, 0, 0 );
+ be = select_backend( (struct berval *)&sdn->ndn, 0 );
return be;
}
}
}
- fprintf( stderr, "config file testing succeeded\n");
+ if ( !quiet ) {
+ fprintf( stderr, "config file testing succeeded\n");
+ }
slap_tool_destroy();
typedef struct syncinfo_s {
struct syncinfo_s *si_next;
- struct slap_backend_db *si_be;
- struct slap_backend_db *si_wbe;
- struct re_s *si_re;
- int si_rid;
- char si_ridtxt[8];
+ BackendDB *si_be;
+ BackendDB *si_wbe;
+ struct re_s *si_re;
+ int si_rid;
+ char si_ridtxt[ STRLENOF("rid=4095") + 1 ];
slap_bindconf si_bindconf;
struct berval si_base;
struct berval si_logbase;
struct berval si_filterstr;
struct berval si_logfilterstr;
- int si_scope;
- int si_attrsonly;
- char *si_anfile;
+ int si_scope;
+ int si_attrsonly;
+ char *si_anfile;
AttributeName *si_anlist;
AttributeName *si_exanlist;
- char **si_attrs;
- char **si_exattrs;
- int si_allattrs;
- int si_allopattrs;
- int si_schemachecking;
- int si_type; /* the active type */
- int si_ctype; /* the configured type */
- time_t si_interval;
- time_t *si_retryinterval;
- int *si_retrynum_init;
- int *si_retrynum;
+ char **si_attrs;
+ char **si_exattrs;
+ int si_allattrs;
+ int si_allopattrs;
+ int si_schemachecking;
+ int si_type; /* the active type */
+ int si_ctype; /* the configured type */
+ time_t si_interval;
+ time_t *si_retryinterval;
+ int *si_retrynum_init;
+ int *si_retrynum;
struct sync_cookie si_syncCookie;
cookie_state *si_cookieState;
- int si_cookieAge;
- int si_manageDSAit;
- int si_slimit;
- int si_tlimit;
- int si_refreshDelete;
- int si_refreshPresent;
- int si_syncdata;
- int si_logstate;
- int si_conn_setup;
- Avlnode *si_presentlist;
- LDAP *si_ld;
- LDAP_LIST_HEAD(np, nonpresent_entry) si_nonpresentlist;
+ int si_cookieAge;
+ int si_manageDSAit;
+ int si_slimit;
+ int si_tlimit;
+ int si_refreshDelete;
+ int si_refreshPresent;
+ int si_syncdata;
+ int si_logstate;
+ int si_conn_setup;
+ Avlnode *si_presentlist;
+ LDAP *si_ld;
+ LDAP_LIST_HEAD(np, nonpresent_entry) si_nonpresentlist;
ldap_pvt_thread_mutex_t si_mutex;
} syncinfo_t;
struct berval *, struct berval *, void * );
/* callback functions */
-static int dn_callback( struct slap_op *, struct slap_rep * );
-static int nonpresent_callback( struct slap_op *, struct slap_rep * );
-static int null_callback( struct slap_op *, struct slap_rep * );
+static int dn_callback( Operation *, SlapReply * );
+static int nonpresent_callback( Operation *, SlapReply * );
+static int null_callback( Operation *, SlapReply * );
static AttributeDescription *sync_descs[4];
+static const char *
+syncrepl_state2str( int state )
+{
+ switch ( state ) {
+ case LDAP_SYNC_PRESENT:
+ return "PRESENT";
+
+ case LDAP_SYNC_ADD:
+ return "ADD";
+
+ case LDAP_SYNC_MODIFY:
+ return "MODIFY";
+
+ case LDAP_SYNC_DELETE:
+ return "DELETE";
+ }
+
+ return "UNKNOWN";
+}
+
static void
init_syncrepl(syncinfo_t *si)
{
attrs = ( char ** ) ch_realloc( attrs, (n + 4)*sizeof( char * ) );
}
- if ( attrs == NULL ) {
- Debug( LDAP_DEBUG_ANY, "out of memory\n", 0, 0, 0 );
- }
-
/* Add Attributes */
if ( si->si_allopattrs ) {
attrs[n++] = ch_strdup( sync_descs[0]->ad_cname.bv_val );
BerElementBuffer berbuf;
BerElement *ber = (BerElement *)&berbuf;
LDAPControl c[2], *ctrls[3];
- struct timeval timeout;
ber_int_t msgid;
int rc;
int rhint;
ctrls[1] = NULL;
}
- timeout.tv_sec = si->si_tlimit;
- timeout.tv_usec = 0;
-
rc = ldap_search_ext( si->si_ld, base, scope, filter, attrs, attrsonly,
- ctrls, NULL, si->si_tlimit > 0 ? &timeout : NULL,
- si->si_slimit, &msgid );
+ ctrls, NULL, NULL, si->si_slimit, &msgid );
ber_free_buf( ber );
return rc;
}
op->o_ssf = ( op->o_sasl_ssf > op->o_tls_ssf )
? op->o_sasl_ssf : op->o_tls_ssf;
+ ldap_set_option( si->si_ld, LDAP_OPT_TIMELIMIT, &si->si_tlimit );
+
/* We've just started up, or the remote server hasn't sent us
* any meaningful state.
*/
si->si_syncCookie.sid );
} else {
AttributeName at[2];
- Attribute a = { slap_schema.si_ad_contextCSN };
+ Attribute a = {0};
Entry e = {0};
SlapReply rs = {0};
int i, j, changed = 0;
* allowed, and all changes will already be reflected in
* the cookieState.
*/
+ a.a_desc = slap_schema.si_ad_contextCSN;
e.e_attrs = &a;
e.e_name = si->si_wbe->be_suffix[0];
e.e_nname = si->si_wbe->be_nsuffix[0];
at[0].an_name = a.a_desc->ad_cname;
at[0].an_desc = a.a_desc;
BER_BVZERO( &at[1].an_name );
+ op->o_req_dn = e.e_name;
+ op->o_req_ndn = e.e_nname;
ldap_pvt_thread_mutex_lock( &si->si_cookieState->cs_mutex );
rc = backend_operational( op, &rs );
struct sync_cookie syncCookie_req = { NULL };
struct berval cookie = BER_BVNULL;
- int rc, err;
+ int rc,
+ err = LDAP_SUCCESS;
ber_len_t len;
struct berval *psub;
/* we can't work without the control */
rctrlp = NULL;
if ( rctrls ) {
+ LDAPControl **next;
/* NOTE: make sure we use the right one;
* a better approach would be to run thru
* the whole list and take care of all */
- rctrlp = ldap_find_control( LDAP_CONTROL_SYNC_STATE, rctrls );
+ rctrlp = ldap_control_find( LDAP_CONTROL_SYNC_STATE, rctrls, &next );
+ if ( next && ldap_control_find( LDAP_CONTROL_SYNC_STATE, next, NULL ) )
+ {
+ Debug( LDAP_DEBUG_ANY, "do_syncrep2: %s "
+ "got search entry with multiple "
+ "Sync State control\n", si->si_ridtxt, 0, 0 );
+ rc = -1;
+ goto done;
+ }
}
if ( rctrlp == NULL ) {
Debug( LDAP_DEBUG_ANY, "do_syncrep2: %s "
* (happens with back-sql...) */
if ( BER_BVISEMPTY( &syncUUID ) ) {
Debug( LDAP_DEBUG_ANY, "do_syncrep2: %s "
- "got empty syncUUID\n", si->si_ridtxt, 0, 0 );
+ "got empty syncUUID with LDAP_SYNC_%s\n",
+ si->si_ridtxt,
+ syncrepl_state2str( syncstate ), 0 );
ldap_controls_free( rctrls );
rc = -1;
goto done;
}
if ( rc == -1 ) {
- const char *errstr;
-
ldap_get_option( si->si_ld, LDAP_OPT_ERROR_NUMBER, &rc );
- errstr = ldap_err2string( rc );
-
- Debug( LDAP_DEBUG_ANY,
- "do_syncrep2: %s %s\n", si->si_ridtxt, errstr, 0 );
+ err = rc;
}
done:
+ if ( err != LDAP_SUCCESS ) {
+ Debug( LDAP_DEBUG_ANY,
+ "do_syncrep2: %s (%d) %s\n",
+ si->si_ridtxt, err, ldap_err2string( err ) );
+ }
+
slap_sync_cookie_free( &syncCookie, 0 );
slap_sync_cookie_free( &syncCookie_req, 0 );
int rc = LDAP_SUCCESS;
int dostop = 0;
ber_socket_t s;
- int i, defer = 1;
+ int i, defer = 1, fail = 0;
Backend *be;
Debug( LDAP_DEBUG_TRACE, "=>do_syncrepl %s\n", si->si_ridtxt, 0, 0 );
return NULL;
}
- op = (Operation *) &opbuf;
- connection_fake_init( &conn, op, ctx );
+ connection_fake_init( &conn, &opbuf, ctx );
+ op = &opbuf.ob_op;
/* use global malloc for now */
op->o_tmpmemctx = NULL;
/* If we're glued, send writes through the glue parent */
if ( !si->si_wbe ) {
if ( SLAP_GLUE_SUBORDINATE( be )) {
- si->si_wbe = select_backend( &be->be_nsuffix[0], 0, 1 );
+ si->si_wbe = select_backend( &be->be_nsuffix[0], 1 );
} else {
si->si_wbe = be;
}
if ( !si->si_ctype
|| !si->si_retrynum || si->si_retrynum[i] == RETRYNUM_TAIL ) {
ldap_pvt_runqueue_remove( &slapd_rq, rtask );
+ fail = RETRYNUM_TAIL;
} else if ( RETRYNUM_VALID( si->si_retrynum[i] ) ) {
if ( si->si_retrynum[i] > 0 )
si->si_retrynum[i]--;
+ fail = si->si_retrynum[i];
rtask->interval.tv_sec = si->si_retryinterval[i];
ldap_pvt_runqueue_resched( &slapd_rq, rtask, 0 );
slap_wake_listener();
}
}
-
+
ldap_pvt_thread_mutex_unlock( &slapd_rq.rq_mutex );
ldap_pvt_thread_mutex_unlock( &si->si_mutex );
+ if ( rc ) {
+ if ( fail == RETRYNUM_TAIL ) {
+ Debug( LDAP_DEBUG_ANY,
+ "do_syncrepl: rid %03d quitting\n",
+ si->si_rid, 0, 0 );
+ } else if ( fail > 0 ) {
+ Debug( LDAP_DEBUG_ANY,
+ "do_syncrepl: rid %03d retrying (%d retries left)\n",
+ si->si_rid, fail, 0 );
+ } else {
+ Debug( LDAP_DEBUG_ANY,
+ "do_syncrepl: rid %03d retrying\n",
+ si->si_rid, 0, 0 );
+ }
+ }
+
/* Do final delete cleanup */
if ( !si->si_ctype ) {
cookie_state *cs = NULL;
op->orm_modlist = modlist;
op->o_bd = si->si_wbe;
rc = op->o_bd->be_modify( op, &rs );
+ modlist = op->orm_modlist;
Debug( rc ? LDAP_DEBUG_ANY : LDAP_DEBUG_SYNC,
"syncrepl_message_to_op: %s be_modify %s (%d)\n",
si->si_ridtxt, op->o_req_dn.bv_val, rc );
slap_callback cb = { NULL, NULL, NULL, NULL };
struct berval *syncuuid_bv = NULL;
struct berval syncUUID_strrep = BER_BVNULL;
- struct berval uuid_bv = BER_BVNULL;
SlapReply rs_search = {REP_RESULT};
SlapReply rs_delete = {REP_RESULT};
struct berval pdn = BER_BVNULL;
dninfo dni = {0};
int retry = 1;
+ int freecsn = 1;
- switch( syncstate ) {
- case LDAP_SYNC_PRESENT:
- Debug( LDAP_DEBUG_SYNC, "syncrepl_entry: %s %s\n",
- si->si_ridtxt,
- "LDAP_RES_SEARCH_ENTRY(LDAP_SYNC_PRESENT)", 0 );
- break;
- case LDAP_SYNC_ADD:
- Debug( LDAP_DEBUG_SYNC, "syncrepl_entry: %s %s\n",
- si->si_ridtxt,
- "LDAP_RES_SEARCH_ENTRY(LDAP_SYNC_ADD)", 0 );
- break;
- case LDAP_SYNC_DELETE:
- Debug( LDAP_DEBUG_SYNC, "syncrepl_entry: %s %s\n",
- si->si_ridtxt,
- "LDAP_RES_SEARCH_ENTRY(LDAP_SYNC_DELETE)", 0 );
- break;
- case LDAP_SYNC_MODIFY:
- Debug( LDAP_DEBUG_SYNC, "syncrepl_entry: %s %s\n",
- si->si_ridtxt,
- "LDAP_RES_SEARCH_ENTRY(LDAP_SYNC_MODIFY)", 0 );
- break;
- default:
- Debug( LDAP_DEBUG_ANY, "syncrepl_entry: %s %s\n",
- si->si_ridtxt,
- "LDAP_RES_SEARCH_ENTRY(UNKNOWN syncstate)", 0 );
- }
+ Debug( LDAP_DEBUG_SYNC,
+ "syncrepl_entry: %s LDAP_RES_SEARCH_ENTRY(LDAP_SYNC_%s)\n",
+ si->si_ridtxt, syncrepl_state2str( syncstate ), 0 );
if (( syncstate == LDAP_SYNC_PRESENT || syncstate == LDAP_SYNC_ADD ) ) {
if ( !si->si_refreshPresent ) {
si->si_ridtxt, dni.dn.bv_val ? dni.dn.bv_val : "(null)", 0 );
}
+ assert( BER_BVISNULL( &op->o_csn ) );
+
slap_op_time( &op->o_time, &op->o_tincr );
switch ( syncstate ) {
case LDAP_SYNC_ADD:
*/
assert( BER_BVISNULL( &op->o_csn ) );
op->o_csn = a->a_vals[0];
+ freecsn = 0;
}
}
retry_add:;
/* Setup opattrs too */
{
- AttributeDescription *opattrs[] = {
- slap_schema.si_ad_entryCSN,
- slap_schema.si_ad_modifiersName,
- slap_schema.si_ad_modifyTimestamp,
- NULL
+ static AttributeDescription *nullattr = NULL;
+ static AttributeDescription **const opattrs[] = {
+ &slap_schema.si_ad_entryCSN,
+ &slap_schema.si_ad_modifiersName,
+ &slap_schema.si_ad_modifyTimestamp,
+ &nullattr
};
+ AttributeDescription *opattr;
Modifications *mod, **modtail, **ml;
int i;
modtail = &mod->sml_next;
/* pull mod off incoming modlist, append to orr_modlist */
- for ( i = 0; opattrs[i]; i++ ) {
+ for ( i = 0; (opattr = *opattrs[i]) != NULL; i++ ) {
for ( ml = modlist; *ml; ml = &(*ml)->sml_next )
{
- if ( (*ml)->sml_desc == opattrs[i] ) {
+ if ( (*ml)->sml_desc == opattr ) {
mod = *ml;
*ml = mod->sml_next;
mod->sml_next = NULL;
rc = op->o_bd->be_modify( op, &rs_modify );
slap_mods_free( op->orm_modlist, 1 );
+ op->orm_no_opattrs = 0;
Debug( LDAP_DEBUG_SYNC,
"syncrepl_entry: %s be_modify (%d)\n",
si->si_ridtxt, rc, 0 );
if ( !BER_BVISNULL( &dni.dn ) ) {
op->o_tmpfree( dni.dn.bv_val, op->o_tmpmemctx );
}
- if ( entry )
+ if ( entry ) {
entry_free( entry );
+ }
+ if ( !BER_BVISNULL( &op->o_csn ) && freecsn ) {
+ op->o_tmpfree( op->o_csn.bv_val, op->o_tmpmemctx );
+ }
BER_BVZERO( &op->o_csn );
return rc;
}
ber_bvfree( np_prev->npe_name );
ber_bvfree( np_prev->npe_nname );
ch_free( np_prev );
+
+ if ( slapd_shutdown ) {
+ break;
+ }
}
slap_graduate_commit_csn( op );
Modifications mod[2];
struct berval first = BER_BVNULL;
- int rc, i, j;
+ int rc, i, j, len;
slap_callback cb = { NULL };
SlapReply rs_modify = {REP_RESULT};
for ( j=0; j<si->si_cookieState->cs_num; j++ ) {
if ( syncCookie->sids[i] != si->si_cookieState->cs_sids[j] )
continue;
- if ( ber_bvcmp( &syncCookie->ctxcsn[i],
- &si->si_cookieState->cs_vals[j] ) > 0 ) {
+ len = syncCookie->ctxcsn[i].bv_len;
+ if ( len > si->si_cookieState->cs_vals[j].bv_len )
+ len = si->si_cookieState->cs_vals[j].bv_len;
+ if ( memcmp( syncCookie->ctxcsn[i].bv_val,
+ si->si_cookieState->cs_vals[j].bv_val, len ) > 0 ) {
ber_bvarray_add_x( &mod[0].sml_values,
&si->si_cookieState->cs_vals[j], op->o_tmpmemctx );
ber_bvarray_add_x( &mod[1].sml_values,
first = syncCookie->ctxcsn[i];
}
}
+ /* Should never happen, ITS#5065 */
+ if ( BER_BVISNULL( &first )) {
+ ldap_pvt_thread_mutex_unlock( &si->si_cookieState->cs_mutex );
+ return 0;
+ }
op->o_bd = si->si_wbe;
slap_queue_csn( op, &first );
op->orm_no_opattrs = 1;
rc = op->o_bd->be_modify( op, &rs_modify );
+ op->orm_no_opattrs = 0;
op->o_msgid = 0;
if ( rs_modify.sr_err == LDAP_SUCCESS ) {
modtail = *mret;
if ( old ) {
- int n, o, d, a, *adds, *dels;
+ int n, o, nn, no;
+ struct berval **adds, **dels;
/* count old and new */
for ( o=0; old->a_vals[o].bv_val; o++ ) ;
for ( n=0; new->a_vals[n].bv_val; n++ ) ;
- adds = op->o_tmpalloc( sizeof(int) * n, op->o_tmpmemctx );
- dels = op->o_tmpalloc( sizeof(int) * o, op->o_tmpmemctx );
- d = 0;
- a = 0;
- i = 0;
- j = 0;
+ adds = op->o_tmpalloc( sizeof(struct berval *) * n, op->o_tmpmemctx );
+ dels = op->o_tmpalloc( sizeof(struct berval *) * o, op->o_tmpmemctx );
- while ( i < o && j < n ) {
- int k;
- if ( bvmatch( &old->a_vals[i], &new->a_vals[j] ) ) {
- i++;
- j++;
- continue;
- }
- for ( k = j + 1; k<n; k++ ) {
- if ( bvmatch( &old->a_vals[i], &new->a_vals[k] ) ) {
- break;
- }
- }
- /* an old value was deleted */
- if ( k == n ) {
- dels[d++] = i++;
- continue;
- }
- for ( k = i + 1; k < o; k++ ) {
- if ( bvmatch( &old->a_vals[k], &new->a_vals[j] ) ) {
+ for ( i=0; i<o; i++ ) dels[i] = &old->a_vals[i];
+ for ( i=0; i<n; i++ ) adds[i] = &new->a_vals[i];
+
+ nn = n; no = o;
+
+ for ( i=0; i<o; i++ ) {
+ for ( j=0; j<n; j++ ) {
+ if ( !adds[j] )
+ continue;
+ if ( bvmatch( dels[i], adds[j] ) ) {
+ no--;
+ nn--;
+ adds[j] = NULL;
+ dels[i] = NULL;
break;
}
}
- if ( k == o ) {
- adds[a++] = j++;
- }
}
- while ( i < o )
- dels[d++] = i++;
- while ( j < n )
- adds[a++] = j++;
+ i = j;
/* all old values were deleted, just use the replace op */
- if ( d == o ) {
+ if ( no == o ) {
i = j-1;
- } else if ( d ) {
+ } else if ( no ) {
/* delete some values */
mod = ch_malloc( sizeof( Modifications ) );
mod->sml_op = LDAP_MOD_DELETE;
mod->sml_flags = 0;
mod->sml_desc = old->a_desc;
mod->sml_type = mod->sml_desc->ad_cname;
- mod->sml_values = ch_malloc( ( d + 1 ) * sizeof(struct berval) );
+ mod->sml_values = ch_malloc( ( no + 1 ) * sizeof(struct berval) );
if ( old->a_vals != old->a_nvals ) {
- mod->sml_nvalues = ch_malloc( ( d + 1 ) * sizeof(struct berval) );
+ mod->sml_nvalues = ch_malloc( ( no + 1 ) * sizeof(struct berval) );
} else {
mod->sml_nvalues = NULL;
}
- for ( i = 0; i < d; i++ ) {
- ber_dupbv( &mod->sml_values[i], &old->a_vals[dels[i]] );
+ j = 0;
+ for ( i = 0; i < o; i++ ) {
+ if ( !dels[i] ) continue;
+ ber_dupbv( &mod->sml_values[j], &old->a_vals[i] );
if ( mod->sml_nvalues ) {
- ber_dupbv( &mod->sml_nvalues[i], &old->a_nvals[dels[i]] );
+ ber_dupbv( &mod->sml_nvalues[j], &old->a_nvals[i] );
}
+ j++;
}
- BER_BVZERO( &mod->sml_values[i] );
+ BER_BVZERO( &mod->sml_values[j] );
if ( mod->sml_nvalues ) {
- BER_BVZERO( &mod->sml_nvalues[i] );
+ BER_BVZERO( &mod->sml_nvalues[j] );
}
*modtail = mod;
modtail = &mod->sml_next;
}
op->o_tmpfree( dels, op->o_tmpmemctx );
/* some values were added */
- if ( a && d < o ) {
+ if ( nn && no < o ) {
mod = ch_malloc( sizeof( Modifications ) );
mod->sml_op = LDAP_MOD_ADD;
mod->sml_flags = 0;
mod->sml_desc = old->a_desc;
mod->sml_type = mod->sml_desc->ad_cname;
- mod->sml_values = ch_malloc( ( a + 1 ) * sizeof(struct berval) );
+ mod->sml_values = ch_malloc( ( nn + 1 ) * sizeof(struct berval) );
if ( old->a_vals != old->a_nvals ) {
- mod->sml_nvalues = ch_malloc( ( a + 1 ) * sizeof(struct berval) );
+ mod->sml_nvalues = ch_malloc( ( nn + 1 ) * sizeof(struct berval) );
} else {
mod->sml_nvalues = NULL;
}
- for ( i = 0; i < a; i++ ) {
- ber_dupbv( &mod->sml_values[i], &new->a_vals[adds[i]] );
+ j = 0;
+ for ( i = 0; i < n; i++ ) {
+ if ( !adds[i] ) continue;
+ ber_dupbv( &mod->sml_values[j], &new->a_vals[i] );
if ( mod->sml_nvalues ) {
- ber_dupbv( &mod->sml_nvalues[i], &new->a_nvals[adds[i]] );
+ ber_dupbv( &mod->sml_nvalues[j], &new->a_nvals[i] );
}
+ j++;
}
- BER_BVZERO( &mod->sml_values[i] );
+ BER_BVZERO( &mod->sml_values[j] );
if ( mod->sml_nvalues ) {
- BER_BVZERO( &mod->sml_nvalues[i] );
+ BER_BVZERO( &mod->sml_nvalues[j] );
}
*modtail = mod;
modtail = &mod->sml_next;
if ( dni->new_entry ) {
Modifications **modtail, **ml;
Attribute *old, *new;
- int i, is_ctx;
+ int is_ctx;
is_ctx = dn_match( &rs->sr_entry->e_nname,
&op->o_bd->be_nsuffix[0] );
slap_schema.si_ad_entryCSN );
new = attr_find( dni->new_entry->e_attrs,
slap_schema.si_ad_entryCSN );
- if ( new && old && ber_bvcmp( &old->a_vals[0],
- &new->a_vals[0] ) >= 0 ) {
- Debug( LDAP_DEBUG_SYNC,
- "dn_callback : new entry is older than ours "
- "%s ours %s, new %s\n",
- rs->sr_entry->e_name.bv_val,
- old->a_vals[0].bv_val,
- new->a_vals[0].bv_val );
- return LDAP_SUCCESS;
+ if ( new && old ) {
+ int rc, len = old->a_vals[0].bv_len;
+ if ( len > new->a_vals[0].bv_len )
+ len = new->a_vals[0].bv_len;
+ rc = memcmp( old->a_vals[0].bv_val,
+ new->a_vals[0].bv_val, len );
+ if ( rc > 0 ) {
+ Debug( LDAP_DEBUG_SYNC,
+ "dn_callback : new entry is older than ours "
+ "%s ours %s, new %s\n",
+ rs->sr_entry->e_name.bv_val,
+ old->a_vals[0].bv_val,
+ new->a_vals[0].bv_val );
+ return LDAP_SUCCESS;
+ } else if ( rc == 0 ) {
+ Debug( LDAP_DEBUG_SYNC,
+ "dn_callback : entries have identical CSN "
+ "%s ours %s, new %s\n",
+ rs->sr_entry->e_name.bv_val,
+ old->a_vals[0].bv_val,
+ new->a_vals[0].bv_val );
+ return LDAP_SUCCESS;
+ }
}
/* We assume that attributes are saved in the same order
struct berval* normalized,
void *ctx )
{
+#if 0
struct berval *new;
unsigned char nibble;
int i, d = 0;
}
new->bv_val[new->bv_len] = '\0';
+ return new;
+#endif
+
+ struct berval *new;
+ int rc = 0;
+
+ if ( normalized == NULL ) return NULL;
+ if ( normalized->bv_len != 16 ) return NULL;
+
+ if ( uuidstr ) {
+ new = uuidstr;
+
+ } else {
+ new = (struct berval *)slap_sl_malloc( sizeof(struct berval), ctx );
+ if ( new == NULL ) {
+ return NULL;
+ }
+ }
+
+ new->bv_len = 36;
+
+ if ( ( new->bv_val = slap_sl_malloc( new->bv_len + 1, ctx ) ) == NULL ) {
+ rc = 1;
+ goto done;
+ }
+
+ rc = lutil_uuidstr_from_normalized( normalized->bv_val,
+ normalized->bv_len, new->bv_val, new->bv_len + 1 );
+
+done:;
+ if ( rc == -1 ) {
+ if ( new != NULL ) {
+ if ( new->bv_val != NULL ) {
+ slap_sl_free( new->bv_val, ctx );
+ }
+
+ if ( new != uuidstr ) {
+ slap_sl_free( new, ctx );
+ }
+ }
+ new = NULL;
+
+ } else {
+ new->bv_len = rc;
+ }
+
return new;
}
/* '\0' string terminator accounts for '=' */
val = c->argv[ i ] + STRLENOF( IDSTR "=" );
if ( lutil_atoi( &tmp, val ) != 0 ) {
- snprintf( c->msg, sizeof( c->msg ),
+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
"Error: parse_syncrepl_line: "
"unable to parse syncrepl id \"%s\"", val );
- Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
return -1;
}
- if ( tmp >= 1000 || tmp < 0 ) {
- snprintf( c->msg, sizeof( c->msg ),
+ if ( tmp > SLAP_SYNC_SID_MAX || tmp < 0 ) {
+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
"Error: parse_syncrepl_line: "
- "syncrepl id %d is out of range [0..999]", tmp );
- Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+ "syncrepl id %d is out of range [0..4095]", tmp );
+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
return -1;
}
si->si_rid = tmp;
- sprintf( si->si_ridtxt, IDSTR "=%03d", si->si_rid );
+ sprintf( si->si_ridtxt, IDSTR "=%d", si->si_rid );
gots |= GOT_ID;
} else if ( !strncasecmp( c->argv[ i ], PROVIDERSTR "=",
STRLENOF( PROVIDERSTR "=" ) ) )
ber_str2bv( val, 0, 0, &bv );
rc = dnNormalize( 0, NULL, NULL, &bv, &si->si_base, NULL );
if ( rc != LDAP_SUCCESS ) {
- snprintf( c->msg, sizeof( c->msg ),
+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
"Invalid base DN \"%s\": %d (%s)",
val, rc, ldap_err2string( rc ) );
- Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
+ return -1;
+ }
+ if ( !be_issubordinate( c->be, &si->si_base ) ) {
+ ch_free( si->si_base.bv_val );
+ BER_BVZERO( &si->si_base );
+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
+ "Base DN \"%s\" is not within the database naming context",
+ val );
+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
return -1;
}
gots |= GOT_BASE;
ber_str2bv( val, 0, 0, &bv );
rc = dnNormalize( 0, NULL, NULL, &bv, &si->si_logbase, NULL );
if ( rc != LDAP_SUCCESS ) {
- snprintf( c->msg, sizeof( c->msg ),
+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
"Invalid logbase DN \"%s\": %d (%s)",
val, rc, ldap_err2string( rc ) );
- Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
return -1;
}
} else if ( !strncasecmp( c->argv[ i ], SCOPESTR "=",
}
}
if ( BER_BVISNULL(&scopes[j].key) ) {
- snprintf( c->msg, sizeof( c->msg ),
+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
"Error: parse_syncrepl_line: "
"unknown scope \"%s\"", val);
- Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
return -1;
}
} else if ( !strncasecmp( c->argv[ i ], ATTRSONLYSTR,
si->si_type = si->si_ctype = LDAP_SYNC_REFRESH_AND_PERSIST;
si->si_interval = 60;
} else {
- snprintf( c->msg, sizeof( c->msg ),
+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
"Error: parse_syncrepl_line: "
"unknown sync type \"%s\"", val);
- Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
return -1;
}
} else if ( !strncasecmp( c->argv[ i ], INTERVALSTR "=",
* should go before the call to strtoul() */
dd = strtoul( ptr, &next, 10 );
if ( ptr[ 0 ] == '-' || next == ptr || next[0] != ':' ) {
- snprintf( c->msg, sizeof( c->msg ),
+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
"Error: parse_syncrepl_line: "
"invalid interval \"%s\", unable to parse days", val );
- Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
return -1;
}
ptr = next + 1;
hh = strtoul( ptr, &next, 10 );
if ( ptr[ 0 ] == '-' || next == ptr || next[0] != ':' || hh > 24 ) {
- snprintf( c->msg, sizeof( c->msg ),
+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
"Error: parse_syncrepl_line: "
"invalid interval \"%s\", unable to parse hours", val );
- Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
return -1;
}
ptr = next + 1;
mm = strtoul( ptr, &next, 10 );
if ( ptr[ 0 ] == '-' || next == ptr || next[0] != ':' || mm > 60 ) {
- snprintf( c->msg, sizeof( c->msg ),
+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
"Error: parse_syncrepl_line: "
"invalid interval \"%s\", unable to parse minutes", val );
- Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
return -1;
}
ptr = next + 1;
ss = strtoul( ptr, &next, 10 );
if ( ptr[ 0 ] == '-' || next == ptr || next[0] != '\0' || ss > 60 ) {
- snprintf( c->msg, sizeof( c->msg ),
+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
"Error: parse_syncrepl_line: "
"invalid interval \"%s\", unable to parse seconds", val );
- Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
return -1;
}
si->si_interval = (( dd * 24 + hh ) * 60 + mm ) * 60 + ss;
unsigned long t;
if ( lutil_parse_time( val, &t ) != 0 ) {
- snprintf( c->msg, sizeof( c->msg ),
+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
"Error: parse_syncrepl_line: "
"invalid interval \"%s\"", val );
- Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
return -1;
}
si->si_interval = (time_t)t;
}
if ( si->si_interval < 0 ) {
- snprintf( c->msg, sizeof( c->msg ),
+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
"Error: parse_syncrepl_line: "
"invalid interval \"%ld\"",
(long) si->si_interval);
- Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
return -1;
}
} else if ( !strncasecmp( c->argv[ i ], RETRYSTR "=",
for ( k = 0; retry_list && retry_list[k]; k++ ) ;
n = k / 2;
if ( k % 2 ) {
- snprintf( c->msg, sizeof( c->msg ),
+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
"Error: incomplete syncrepl retry list" );
- Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
for ( k = 0; retry_list && retry_list[k]; k++ ) {
ch_free( retry_list[k] );
}
for ( j = 0; j < n; j++ ) {
unsigned long t;
if ( lutil_atoul( &t, retry_list[j*2] ) != 0 ) {
- snprintf( c->msg, sizeof( c->msg ),
+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
"Error: invalid retry interval \"%s\" (#%d)",
retry_list[j*2], j );
- Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
/* do some cleanup */
return 1;
}
if ( lutil_atoi( &si->si_retrynum_init[j], retry_list[j*2+1] ) != 0
|| si->si_retrynum_init[j] <= 0 )
{
- snprintf( c->msg, sizeof( c->msg ),
+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
"Error: invalid initial retry number \"%s\" (#%d)",
retry_list[j*2+1], j );
- Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
/* do some cleanup */
return 1;
}
if ( lutil_atoi( &si->si_retrynum[j], retry_list[j*2+1] ) != 0
|| si->si_retrynum[j] <= 0 )
{
- snprintf( c->msg, sizeof( c->msg ),
+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
"Error: invalid retry number \"%s\" (#%d)",
retry_list[j*2+1], j );
- Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
/* do some cleanup */
return 1;
}
if ( lutil_atoi( &si->si_manageDSAit, val ) != 0
|| si->si_manageDSAit < 0 || si->si_manageDSAit > 1 )
{
- snprintf( c->msg, sizeof( c->msg ),
+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
"invalid manageDSAit value \"%s\".\n",
val );
- Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
return 1;
}
} else if ( !strncasecmp( c->argv[ i ], SLIMITSTR "=",
si->si_slimit = 0;
} else if ( lutil_atoi( &si->si_slimit, val ) != 0 || si->si_slimit < 0 ) {
- snprintf( c->msg, sizeof( c->msg ),
+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
"invalid size limit value \"%s\".\n",
val );
- Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
return 1;
}
} else if ( !strncasecmp( c->argv[ i ], TLIMITSTR "=",
si->si_tlimit = 0;
} else if ( lutil_atoi( &si->si_tlimit, val ) != 0 || si->si_tlimit < 0 ) {
- snprintf( c->msg, sizeof( c->msg ),
+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
"invalid time limit value \"%s\".\n",
val );
- Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
return 1;
}
} else if ( !strncasecmp( c->argv[ i ], SYNCDATASTR "=",
val = c->argv[ i ] + STRLENOF( SYNCDATASTR "=" );
si->si_syncdata = verb_to_mask( val, datamodes );
} else if ( bindconf_parse( c->argv[i], &si->si_bindconf ) ) {
- snprintf( c->msg, sizeof( c->msg ),
+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
"Error: parse_syncrepl_line: "
"unable to parse \"%s\"\n", c->argv[ i ] );
- Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
return -1;
}
}
if ( gots != GOT_ALL ) {
- snprintf( c->msg, sizeof( c->msg ),
+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
"Error: Malformed \"syncrepl\" line in slapd config file, missing%s%s%s",
gots & GOT_ID ? "" : " "IDSTR,
gots & GOT_PROVIDER ? "" : " "PROVIDERSTR,
gots & GOT_BASE ? "" : " "SEARCHBASESTR );
- Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
return -1;
}
int rc = 0;
if ( !( c->be->be_search && c->be->be_add && c->be->be_modify && c->be->be_delete ) ) {
- snprintf( c->msg, sizeof(c->msg), "database %s does not support "
+ snprintf( c->cr_msg, sizeof(c->cr_msg), "database %s does not support "
"operations required for syncrepl", c->be->be_type );
- Debug( LDAP_DEBUG_ANY, "%s: %s\n", c->log, c->msg, 0 );
+ Debug( LDAP_DEBUG_ANY, "%s: %s\n", c->log, c->cr_msg, 0 );
return 1;
}
if ( BER_BVISEMPTY( &c->be->be_rootdn ) ) {
- strcpy( c->msg, "rootDN must be defined before syncrepl may be used" );
- Debug( LDAP_DEBUG_ANY, "%s: %s\n", c->log, c->msg, 0 );
+ strcpy( c->cr_msg, "rootDN must be defined before syncrepl may be used" );
+ Debug( LDAP_DEBUG_ANY, "%s: %s\n", c->log, c->cr_msg, 0 );
return 1;
}
si = (syncinfo_t *) ch_calloc( 1, sizeof( syncinfo_t ) );
else
rc = -1;
}
+ } else {
+ /* mirrormode still needs to see this flag in tool mode */
+ rc = config_sync_shadow( c ) ? -1 : 0;
}
}
si->si_bindconf.sb_version = LDAP_VERSION3;
ptr = buf;
- ptr += snprintf( ptr, WHATSLEFT, IDSTR "=%03ld " PROVIDERSTR "=%s",
+ assert( si->si_rid >= 0 && si->si_rid <= SLAP_SYNC_SID_MAX );
+ ptr += snprintf( ptr, WHATSLEFT, IDSTR "=%d " PROVIDERSTR "=%s",
si->si_rid, si->si_bindconf.sb_uri.bv_val );
if ( ptr - buf >= sizeof( buf ) ) return;
if ( !BER_BVISNULL( &bc ) ) {
};
static Avlnode *syn_index = NULL;
-static LDAP_SLIST_HEAD(SyntaxList, slap_syntax) syn_list
+static LDAP_SLIST_HEAD(SyntaxList, Syntax) syn_list
= LDAP_SLIST_HEAD_INITIALIZER(&syn_list);
static int
return( NULL );
}
+int
+syn_is_sup( Syntax *syn, Syntax *sup )
+{
+ int i;
+
+ assert( syn != NULL );
+ assert( sup != NULL );
+
+ if ( syn == sup ) {
+ return 1;
+ }
+
+ if ( syn->ssyn_sups == NULL ) {
+ return 0;
+ }
+
+ for ( i = 0; syn->ssyn_sups[i]; i++ ) {
+ if ( syn->ssyn_sups[i] == sup ) {
+ return 1;
+ }
+
+ if ( syn_is_sup( syn->ssyn_sups[i], sup ) ) {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
void
syn_destroy( void )
{
- Syntax *s;
-
- avl_free(syn_index, ldap_memfree);
- while( !LDAP_SLIST_EMPTY(&syn_list) ) {
- s = LDAP_SLIST_FIRST(&syn_list);
- LDAP_SLIST_REMOVE_HEAD(&syn_list, ssyn_next);
- ldap_syntax_free((LDAPSyntax *)s);
+ Syntax *s;
+
+ avl_free( syn_index, ldap_memfree );
+ while( !LDAP_SLIST_EMPTY( &syn_list ) ) {
+ s = LDAP_SLIST_FIRST( &syn_list );
+ LDAP_SLIST_REMOVE_HEAD( &syn_list, ssyn_next );
+ if ( s->ssyn_sups ) {
+ SLAP_FREE( s->ssyn_sups );
+ }
+ ldap_syntax_free( (LDAPSyntax *)s );
}
}
)
{
Syntax *ssyn;
- int code;
+ int code = 0;
ssyn = (Syntax *) SLAP_CALLOC( 1, sizeof(Syntax) );
- if( ssyn == NULL ) {
+ if ( ssyn == NULL ) {
Debug( LDAP_DEBUG_ANY, "SLAP_CALLOC Error\n", 0, 0, 0 );
- return LDAP_OTHER;
+ return SLAP_SCHERR_OUTOFMEM;
}
AC_MEMCPY( &ssyn->ssyn_syn, syn, sizeof(LDAPSyntax) );
ssyn->ssyn_validate = def->sd_validate;
ssyn->ssyn_pretty = def->sd_pretty;
+ ssyn->ssyn_sups = NULL;
+
#ifdef SLAPD_BINARY_CONVERSION
ssyn->ssyn_ber2str = def->sd_ber2str;
ssyn->ssyn_str2ber = def->sd_str2ber;
#endif
- code = syn_insert(ssyn, err);
+ if ( def->sd_sups != NULL ) {
+ int cnt;
+
+ for ( cnt = 0; def->sd_sups[cnt] != NULL; cnt++ )
+ ;
+
+ ssyn->ssyn_sups = (Syntax **)SLAP_CALLOC( cnt + 1,
+ sizeof( Syntax * ) );
+ if ( ssyn->ssyn_sups == NULL ) {
+ Debug( LDAP_DEBUG_ANY, "SLAP_CALLOC Error\n", 0, 0, 0 );
+ code = SLAP_SCHERR_OUTOFMEM;
+
+ } else {
+ for ( cnt = 0; def->sd_sups[cnt] != NULL; cnt++ ) {
+ ssyn->ssyn_sups[cnt] = syn_find( def->sd_sups[cnt] );
+ if ( ssyn->ssyn_sups[cnt] == NULL ) {
+ *err = def->sd_sups[cnt];
+ code = SLAP_SCHERR_SYN_SUP_NOT_FOUND;
+ }
+ }
+ }
+ }
+
+ if ( code == 0 ) {
+ code = syn_insert( ssyn, err );
+
+ }
+
+ if ( code != 0 && ssyn != NULL ) {
+ if ( ssyn->ssyn_sups != NULL ) {
+ SLAP_FREE( ssyn->ssyn_sups );
+ }
+ SLAP_FREE( ssyn );
+ }
+
return code;
}
int
do_unbind( Operation *op, SlapReply *rs )
{
- Debug( LDAP_DEBUG_TRACE, "do_unbind\n", 0, 0, 0 );
+ Debug( LDAP_DEBUG_TRACE, "%s do_unbind\n",
+ op->o_log_prefix, 0, 0 );
/*
* Parse the unbind request. It looks like this:
/* Skip past the assertion index */
if ( bv.bv_val[0] == '{' ) {
- char *ptr;
+ char *ptr;
ptr = ber_bvchr( &bv, '}' );
- if ( ptr == NULL ) {
- return LDAP_INVALID_SYNTAX;
+ if ( ptr != NULL ) {
+ struct berval ns;
+
+ ns.bv_val = bv.bv_val + 1;
+ ns.bv_len = ptr - ns.bv_val;
+
+ if ( numericStringValidate( NULL, &ns ) == LDAP_SUCCESS ) {
+ ptr++;
+ bv.bv_len -= ptr - bv.bv_val;
+ bv.bv_val = ptr;
+ in = &bv;
+ /* If deleting by index, just succeed */
+ if ( mop == LDAP_MOD_DELETE && BER_BVISEMPTY( &bv ) ) {
+ return LDAP_SUCCESS;
+ }
+ }
}
- ptr++;
- bv.bv_len -= ptr - bv.bv_val;
- bv.bv_val = ptr;
- in = &bv;
- /* If deleting by index, just succeed */
- if ( mop == LDAP_MOD_DELETE && BER_BVISEMPTY( &bv ))
- return LDAP_SUCCESS;
}
}
char *ptr;
ptr = ber_bvchr( &bv, '}' );
- if ( ptr == NULL ) {
- return LDAP_INVALID_SYNTAX;
- }
- ptr++;
+ if ( ptr != NULL ) {
+ struct berval ns;
+
+ ns.bv_val = bv.bv_val + 1;
+ ns.bv_len = ptr - ns.bv_val;
- idx = bv;
- idx.bv_len = ptr - bv.bv_val;
+ if ( numericStringValidate( NULL, &ns ) == LDAP_SUCCESS ) {
+ ptr++;
- bv.bv_len -= idx.bv_len;
- bv.bv_val = ptr;
+ idx = bv;
+ idx.bv_len = ptr - bv.bv_val;
- val = &bv;
+ bv.bv_len -= idx.bv_len;
+ bv.bv_val = ptr;
+
+ val = &bv;
+ }
+ }
}
}
char *ptr;
ptr = ber_bvchr( &bv, '}' );
- if ( ptr == NULL ) {
- return LDAP_INVALID_SYNTAX;
- }
- ptr++;
+ if ( ptr != NULL ) {
+ struct berval ns;
+
+ ns.bv_val = bv.bv_val + 1;
+ ns.bv_len = ptr - ns.bv_val;
- idx = bv;
- idx.bv_len = ptr - bv.bv_val;
+ if ( numericStringValidate( NULL, &ns ) == LDAP_SUCCESS ) {
+ ptr++;
- bv.bv_len -= idx.bv_len;
- bv.bv_val = ptr;
+ idx = bv;
+ idx.bv_len = ptr - bv.bv_val;
- /* validator will already prevent this for Adds */
- if ( BER_BVISEMPTY( &bv )) {
- ber_dupbv_x( normalized, &idx, ctx );
- return LDAP_SUCCESS;
+ bv.bv_len -= idx.bv_len;
+ bv.bv_val = ptr;
+
+ /* validator will already prevent this for Adds */
+ if ( BER_BVISEMPTY( &bv )) {
+ ber_dupbv_x( normalized, &idx, ctx );
+ return LDAP_SUCCESS;
+ }
+ val = &bv;
+ }
}
- val = &bv;
}
}
*/
if ( ad->ad_type->sat_flags & SLAP_AT_ORDERED ) {
char *ptr;
- struct berval iv;
+ struct berval ns1 = BER_BVNULL, ns2 = BER_BVNULL;
bv1 = *v1;
bv2 = *v2;
- iv = bv2;
/* Skip past the assertion index */
if ( bv2.bv_val[0] == '{' ) {
ptr = ber_bvchr( &bv2, '}' );
- if ( ptr == NULL ) {
- return LDAP_INVALID_SYNTAX;
+ if ( ptr != NULL ) {
+ ns2.bv_val = bv2.bv_val + 1;
+ ns2.bv_len = ptr - ns2.bv_val;
+
+ if ( numericStringValidate( NULL, &ns2 ) == LDAP_SUCCESS ) {
+ ptr++;
+ bv2.bv_len -= ptr - bv2.bv_val;
+ bv2.bv_val = ptr;
+ v2 = &bv2;
+ }
}
- ptr++;
- bv2.bv_len -= ptr - bv2.bv_val;
- bv2.bv_val = ptr;
- v2 = &bv2;
}
- if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX( flags )) {
- if ( iv.bv_val[0] == '{' && bv1.bv_val[0] == '{' ) {
- /* compare index values first */
- long l1, l2, ret;
-
- l1 = strtol( bv1.bv_val+1, NULL, 0 );
- l2 = strtol( iv.bv_val+1, &ptr, 0 );
+ /* Skip past the attribute index */
+ if ( bv1.bv_val[0] == '{' ) {
+ ptr = ber_bvchr( &bv1, '}' );
+ if ( ptr != NULL ) {
+ ns1.bv_val = bv1.bv_val + 1;
+ ns1.bv_len = ptr - ns1.bv_val;
+
+ if ( numericStringValidate( NULL, &ns1 ) == LDAP_SUCCESS ) {
+ ptr++;
+ bv1.bv_len -= ptr - bv1.bv_val;
+ bv1.bv_val = ptr;
+ v1 = &bv1;
+ }
+ }
+ }
- ret = l1 - l2;
+ if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX( flags )) {
+ if ( !BER_BVISNULL( &ns2 ) && !BER_BVISNULL( &ns1 ) ) {
+ /* compare index values first */
+ (void)octetStringOrderingMatch( match, 0, NULL, NULL, &ns1, &ns2 );
/* If not equal, or we're only comparing the index,
* return result now.
*/
- if ( ret || ptr == iv.bv_val + iv.bv_len - 1 ) {
- *match = ( ret < 0 ) ? -1 : (ret > 0 );
+ if ( *match != 0 || BER_BVISEMPTY( &bv2 ) ) {
return LDAP_SUCCESS;
}
}
}
- /* Skip past the attribute index */
- if ( bv1.bv_val[0] == '{' ) {
- ptr = ber_bvchr( &bv1, '}' );
- if ( ptr == NULL ) {
- return LDAP_INVALID_SYNTAX;
- }
- ptr++;
- bv1.bv_len -= ptr - bv1.bv_val;
- bv1.bv_val = ptr;
- v1 = &bv1;
- }
+
}
if ( !mr || !mr->smr_match ) {
k = -1;
if ( vals[i].bv_val[0] == '{' ) {
+ /* FIXME: strtol() could go past end... */
k = strtol( vals[i].bv_val + 1, &next, 0 );
if ( next == vals[i].bv_val + 1 ||
next[ 0 ] != '}' ||
+++ /dev/null
-Design Notes: slurpd
-
-This new version differs significantly from previous versions:
-
-- It uses a multithreaded, single-process model. Previous versions forked
- a separate process for each replica. This new design should facilitate
- porting to NT, and is more straightforward.
-
-- Only one copy of the replication log is made. Previous versions made
-one copy of the replication log for each replica
-
-- This newer version is more object-oriented. Although still written in
- ANSI C (and compilable on k&r compilers), it encapsulates within the
- major data structures the methods used to access "private" data.
-
-General design overview:
-
-The main data structure in slurpd is a replication queue (struct rq).
-The rq data structure is currently implemented as a linked list of
-replication entries (struct re). The rq structure contains member functions
-used to initialize, add to, remove, and return the next re struct.
-
-In addition to the rq structure, there is one ri (replication information)
-struct for each replica. The ri struct encapsulates all information
-about a particular replica, e.g. hostname, port, bind dn. The single
-public member function, ri_process, is called to begin processing
-the replication entries in the queue.
-
-There is also a status structure (struct st) which contains the timestamp
-of the last successful replication operation for each replica. The
-contents of the st struct are flushed to disk after every successful
-operation. This disk file is read upon startup, and is used to allow
-slapd to "pick up where it left off".
-
-Threading notes:
-
-The LDAP liblthread quasi-pthreads interface is used for threading. At
-this point, machines which do not support pthreads, sun threads or lwp
-will probably not be able to run slurpd. Given the current threading
-method, discussed in the next paragraph, it will probably be necessary to
-have a separate hunk of code which handles non-threaded architectures
-(or we might just not worry about it). This needs further discussion.
-
-Upon startup, command-line arguments and the slapd configuration file
-are processed. One thread is started for each replica. Thread replicas,
-when no more work exists, wait on a condition variable, and the main
-thread's file manager routine broadcasts on this condition variable
-when new work is added to the queue.
-
-Additional notes:
- See doc/devel/replication-notes.txt
+++ /dev/null
-# Makefile.in for slurpd
-# $OpenLDAP$
-## This work is part of OpenLDAP Software <http://www.openldap.org/>.
-##
-## Copyright 1998-2007 The OpenLDAP Foundation.
-## All rights reserved.
-##
-## Redistribution and use in source and binary forms, with or without
-## modification, are permitted only as authorized by the OpenLDAP
-## Public License.
-##
-## A copy of this license is available in the file LICENSE in the
-## top-level directory of the distribution or, alternatively, at
-## <http://www.OpenLDAP.org/license.html>.
-
-PROGRAMS = slurpd
-XPROGRAMS = sslurpd
-
-XSRCS = version.c
-
-NT_SRCS = nt_svc.c
-NT_OBJS = nt_svc.o ../../libraries/liblutil/slapdmsg.res
-
-SRCS = admin.c args.c ch_malloc.c config.c \
- fm.c globals.c ldap_op.c lock.c main.c re.c \
- reject.c replica.c replog.c ri.c rq.c sanity.c st.c \
- $(@PLAT@_SRCS)
-OBJS = admin.o args.o ch_malloc.o config.o \
- fm.o globals.o ldap_op.o lock.o main.o re.o \
- reject.o replica.o replog.o ri.o rq.o sanity.o st.o \
- $(@PLAT@_OBJS)
-
-LDAP_INCDIR= ../../include
-LDAP_LIBDIR= ../../libraries
-
-BUILD_OPT = "--enable-slurpd"
-BUILD_SRV = @BUILD_SLURPD@
-
-all-local-srv: $(PROGRAMS)
-
-# $(LTHREAD_LIBS) must be last!
-XLIBS = $(SLURPD_L)
-XXLIBS = $(SLURPD_LIBS) $(SECURITY_LIBS) $(LUTIL_LIBS)
-XXXLIBS = $(LTHREAD_LIBS)
-
-slurpd: version.o
- $(LTLINK) -o $@ $(OBJS) version.o $(LIBS)
-
-sslurpd: version.o
- $(LTLINK) -static -o $@ $(OBJS) version.o $(LIBS)
-
-version.c: Makefile
- @-$(RM) $@
- $(MKVERSION) -s -n Versionstr slurpd > $@
-
-version.o: version.c $(OBJS) $(SLURPD_L)
-
-install-local-srv: FORCE
- -$(MKDIR) $(DESTDIR)$(libexecdir)
- @-$(INSTALL) -m 700 -d $(DESTDIR)$(localstatedir)/openldap-slurp
- @( \
- for prg in $(PROGRAMS); do \
- $(LTINSTALL) $(INSTALLFLAGS) $(STRIP) -m 755 $$prg$(EXEEXT) \
- $(DESTDIR)$(libexecdir); \
- done \
- )
-
+++ /dev/null
-Written by Ganesan Rajagopal <rganesan@debian.org> and placed in the public
-domain.
-
-Replication in OpenLDAP
------------------------
-
-Please read "Section 10. Replication with slurpd" in the OpenLDAP guide for
-an overview and configuration of single-master replication. This document
-describes the internals of the replication mechanism.
-
-slapd/repl.c contains routines add_replica_info() and
-add_replica_suffix(). add_replica_info() adds a new host to the list of
-replicas for a backend. add_replica_info() returns a number for the
-replica. add_replica_suffix() must then be called with the replica number to
-add a suffix that is hosted on this replica. add_replica_info() and add_replica_suffix() do not lock the
-replog_mutex.
-
-Replicas are specified in the slapd.conf file. When slapd/config.c sees a
-"replica" line in slapd.conf, it calls add_replica_info() with the host
-specified in the "host=" directive and then calls add_replica_suffix() with
-the replica number and and the suffix specified in the "suffix="
-directive.
-
-slapd writes out a replication log file containing LDIF change records for
-each configured replica for a suffix. The change records are generated for
-add, modify, delete and modrdn operations. A function called replog() is
-called at the end of the routines do_add (slapd/add.c),
-do_modify(slapd/modify.c), do_delete(slapd/delete.c) and
-do_modrdn(slapd/modrnd.c) to write out the change records.
-
-In master/slave replication, updates are not allowed on slave
-replicas. Therefore replog() is not called if the suffix is configured with
-a updatedn (which indicates that this is a slave replica), instead a
-referral is returned back to the client. If multi-master replication is
-enabled, replog() is always called whenever any of the above updates happen
-unless the dn which is making the change is the updatedn. When the dn making
-the change is the same as the updatedn, it is assumed that this entry is
-being replicated by a slurpd instance on another host. (Note: For this
-reason, the updatedn must not be a "regular" admin/user object in
-multi-master replication).
-
-The function replog() in slapd/repl.c generates the actual change
-records. Each change record is preceded by the list of replicas to which
-this change record needs to be replicated, the time when this change
-happened and the dn this change applies to. The pseudo code for replog() is
-follows
-
-1. Check that a replog exists.
-2. Lock the replog mutex.
-3. Open and lock the replog file.
-4. Normalize the dn for the entry and write out a "replica:" entry for each
- replica with a matching suffix.
-5. Write out the the timestamp and the dn for the entry.
-6. Depending on the type of change, write out an appropriate changetype
- record.
-7. Close the replication log
-8. Unlock the replog mutex
-
-slurpd has a file manager routine (function fm()) which watches for any
-change in the replication log. Whenever fm() detects a change in the
-replication log it locks the log, appends the records to slurpd's private
-copy of the replication log and truncates the log. See the slurpd/DESIGN
-file for a description of how slurpd works.
-
-slapd can be configured to write out a replication log even if no replicas
-are configured. In this case the administrator has to truncate the
-replication log manually (under a lock!).
+++ /dev/null
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 1998-2007 The OpenLDAP Foundation.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted only as authorized by the OpenLDAP
- * Public License.
- *
- * A copy of this license is available in file LICENSE in the
- * top-level directory of the distribution or, alternatively, at
- * <http://www.OpenLDAP.org/license.html>.
- */
-/* Portions Copyright (c) 1996 Regents of the University of Michigan.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that this notice is preserved and that due credit is given
- * to the University of Michigan at Ann Arbor. The name of the University
- * may not be used to endorse or promote products derived from this
- * software without specific prior written permission. This software
- * is provided ``as is'' without express or implied warranty.
- */
-/* ACKNOWLEDGEMENTS:
- * This work was originally developed by the University of Michigan
- * (as part of U-MICH LDAP).
- */
-
-/*
- * admin.c - routines for performing administrative tasks, e.g. on-the-fly
- * reconfiguration of slurpd.
- */
-
-#include "portable.h"
-
-#include <stdio.h>
-#include <ac/stdlib.h>
-
-#include <ac/signal.h>
-
-#include "slurp.h"
-#include "globals.h"
-
-
-/*
- * Eventually, do_admin will be the entry point for performing
- * administrative tasks. General idea: put commands in a file
- * somewhere, send slurpd a USR2 signal. The handler for
- * USR2 (this routine) reads the file and takes some action.
- *
- * For right now, this routine has been hijacked for debugging. When
- * slurpd receives a USR2 signal, it will dump its replication
- * queue to the disk file given by SLURPD_DUMPFILE.
- */
-RETSIGTYPE
-do_admin( int sig )
-{
- sglob->rq->rq_dump( sglob->rq );
- (void) SIGNAL_REINSTALL( sig, do_admin );
-}
+++ /dev/null
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 1998-2007 The OpenLDAP Foundation.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted only as authorized by the OpenLDAP
- * Public License.
- *
- * A copy of this license is available in file LICENSE in the
- * top-level directory of the distribution or, alternatively, at
- * <http://www.OpenLDAP.org/license.html>.
- */
-/* Portions Copyright (c) 1996 Regents of the University of Michigan.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that this notice is preserved and that due credit is given
- * to the University of Michigan at Ann Arbor. The name of the University
- * may not be used to endorse or promote products derived from this
- * software without specific prior written permission. This software
- * is provided ``as is'' without express or implied warranty.
- */
-/* ACKNOWLEDGEMENTS:
- * This work was originally developed by the University of Michigan
- * (as part of U-MICH LDAP).
- */
-
-/*
- * args.c - process command-line arguments, and set appropriate globals.
- */
-
-#include "portable.h"
-
-#include <stdio.h>
-
-#include <ac/stdlib.h>
-#include <ac/string.h>
-#include <ac/time.h>
-#include <ac/unistd.h>
-
-#include <ldap.h>
-#include <lutil.h>
-
-#include "slurp.h"
-#include "globals.h"
-
-
-static void
-usage( char *name )
-{
- fprintf( stderr, "usage: %s\t[-d debug-level] [-s syslog-level]\n", name );
- fprintf( stderr, "\t\t[-f slapd-config-file] [-r replication-log-file]\n" );
- fprintf( stderr, "\t\t[-t tmp-dir] [-o]\n" );
- fprintf( stderr, "\t\t[-n service-name]\n" );
-}
-
-
-
-/*
- * Interpret argv, and fill in any appropriate globals.
- */
-int
-doargs(
- int argc,
- char **argv,
- Globals *g
-)
-{
- int i;
- int rflag = 0;
-
- g->myname = strdup( lutil_progname( "slurpd", argc, argv ));
-
- while ( (i = getopt( argc, argv, "d:f:n:or:t:V" )) != EOF ) {
- switch ( i ) {
- case 'd': { /* set debug level and 'do not detach' flag */
- int level;
- g->no_detach = 1;
- if ( optarg[0] == '?' ) {
-#ifdef LDAP_DEBUG
- printf( "Debug levels:\n" );
- printf( "\tLDAP_DEBUG_TRACE\t%d\n",
- LDAP_DEBUG_TRACE );
- printf( "\tLDAP_DEBUG_PACKETS\t%d\n",
- LDAP_DEBUG_PACKETS );
- printf( "\tLDAP_DEBUG_ARGS\t\t%d\n",
- LDAP_DEBUG_ARGS );
- printf( "\tLDAP_DEBUG_CONNS\t%d\n",
- LDAP_DEBUG_CONNS );
- printf( "\tLDAP_DEBUG_BER\t\t%d\n",
- LDAP_DEBUG_BER );
- printf( "\tLDAP_DEBUG_FILTER\t%d\n",
- LDAP_DEBUG_FILTER );
- printf( "\tLDAP_DEBUG_CONFIG\t%d\n",
- LDAP_DEBUG_CONFIG );
- printf( "\tLDAP_DEBUG_ACL\t\t%d\n",
- LDAP_DEBUG_ACL );
- printf( "\tLDAP_DEBUG_ANY\t\t%d\n",
- LDAP_DEBUG_ANY );
- puts( "\tThe -d flag also prevents slurpd from detaching." );
-#endif /* LDAP_DEBUG */
- puts( "\tDebugging is disabled. -d 0 prevents slurpd from detaching." );
- return( -1 );
- }
-#ifdef LDAP_DEBUG
- if ( lutil_atoix( &level, optarg, 0 ) != 0 ) {
- fprintf( stderr, "unable to parse debug flag \"%s\".\n", optarg );
- usage( g->myname );
- return( -1 );
- }
- ldap_debug |= level;
-#else /* !LDAP_DEBUG */
- if ( lutil_atoi( &level, optarg ) != 0 || level != 0 )
- /* can't enable debugging - not built with debug code */
- fputs( "must compile with LDAP_DEBUG for debugging\n",
- stderr );
-#endif /* LDAP_DEBUG */
- } break;
- case 'f': /* slapd config file */
- LUTIL_SLASHPATH( optarg );
- g->slapd_configfile = strdup( optarg );
- break;
- case 'n': /* NT service name */
- if ( g->serverName ) free( g->serverName );
- g->serverName = strdup( optarg );
- break;
- case 'o':
- g->one_shot_mode = 1;
- break;
- case 'r': /* slapd replog file */
- LUTIL_SLASHPATH( optarg );
- snprintf( g->slapd_replogfile, sizeof g->slapd_replogfile,
- "%s", optarg );
- rflag++;
- break;
- case 't': { /* dir to use for our copies of replogs */
- size_t sz;
- LUTIL_SLASHPATH( optarg );
- g->slurpd_rdir = (char *)malloc (sz = (strlen(optarg) + sizeof(LDAP_DIRSEP "replica")));
- snprintf(g->slurpd_rdir, sz,
- "%s" LDAP_DIRSEP "replica", optarg);
- } break;
- case 'V':
- (g->version)++;
- break;
- default:
- usage( g->myname );
- return( -1 );
- }
- }
-
- if ( g->one_shot_mode && !rflag ) {
- fprintf( stderr, "If -o flag is given, -r flag must also be given.\n" );
- usage( g->myname );
- return( -1 );
- }
-
- /* Set location/name of our private copy of the slapd replog file */
- snprintf( g->slurpd_replogfile, sizeof g->slurpd_replogfile,
- "%s" LDAP_DIRSEP "%s", g->slurpd_rdir,
- DEFAULT_SLURPD_REPLOGFILE );
-
- /* Set location/name of the slurpd status file */
- snprintf( g->slurpd_status_file, sizeof g->slurpd_status_file,
- "%s" LDAP_DIRSEP "%s", g->slurpd_rdir,
- DEFAULT_SLURPD_STATUS_FILE );
-
- ber_set_option(NULL, LBER_OPT_DEBUG_LEVEL, &ldap_debug);
- ldap_set_option(NULL, LDAP_OPT_DEBUG_LEVEL, &ldap_debug);
- ldif_debug = ldap_debug;
-
-#ifdef LOG_LOCAL4
- openlog( g->myname, OPENLOG_OPTIONS, LOG_LOCAL4 );
-#elif LOG_DEBUG
- openlog( g->myname, OPENLOG_OPTIONS );
-#endif
-
- return 0;
-}
+++ /dev/null
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 1998-2007 The OpenLDAP Foundation.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted only as authorized by the OpenLDAP
- * Public License.
- *
- * A copy of this license is available in file LICENSE in the
- * top-level directory of the distribution or, alternatively, at
- * <http://www.OpenLDAP.org/license.html>.
- */
-/* Portions Copyright (c) 1996 Regents of the University of Michigan.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that this notice is preserved and that due credit is given
- * to the University of Michigan at Ann Arbor. The name of the University
- * may not be used to endorse or promote products derived from this
- * software without specific prior written permission. This software
- * is provided ``as is'' without express or implied warranty.
- */
-/* ACKNOWLEDGEMENTS:
- * This work was originally developed by the University of Michigan
- * (as part of U-MICH LDAP).
- */
-
-#define CH_FREE 1
-
-/*
- * ch_malloc.c - malloc() and friends, with check for NULL return.
- */
-
-#include "portable.h"
-
-#include <stdio.h>
-
-#include <ac/stdlib.h>
-#include <ac/socket.h>
-
-#include "../slapd/slap.h"
-
-
-#ifndef CSRIMALLOC
-
-/*
- * Just like malloc, except we check the returned value and exit
- * if anything goes wrong.
- */
-void *
-ch_malloc(
- ber_len_t size
-)
-{
- void *new;
-
- if ( (new = (void *) ber_memalloc( size )) == NULL ) {
- fprintf( stderr, "malloc of %lu bytes failed\n",
- (long) size );
- exit( EXIT_FAILURE );
- }
-
- return( new );
-}
-
-
-
-
-/*
- * Just like realloc, except we check the returned value and exit
- * if anything goes wrong.
- */
-void *
-ch_realloc(
- void *block,
- ber_len_t size
-)
-{
- void *new;
-
- if ( block == NULL ) {
- return( ch_malloc( size ) );
- }
-
- if ( size == 0 ) {
- ch_free( block );
- }
-
- if ( (new = (void *) ber_memrealloc( block, size )) == NULL ) {
- fprintf( stderr, "realloc of %lu bytes failed\n",
- (long) size );
- exit( EXIT_FAILURE );
- }
-
- return( new );
-}
-
-
-
-
-/*
- * Just like calloc, except we check the returned value and exit
- * if anything goes wrong.
- */
-void *
-ch_calloc(
- ber_len_t nelem,
- ber_len_t size
-)
-{
- void *new;
-
- if ( (new = (void *) ber_memcalloc( nelem, size )) == NULL ) {
- fprintf( stderr, "calloc of %lu elems of %lu bytes failed\n",
- (long) nelem, (long) size );
- exit( EXIT_FAILURE );
- }
-
- return( new );
-}
-
-/*
- * Just like strdup, except we check the returned value and exit
- * if anything goes wrong.
- */
-char *
-ch_strdup(
- const char *string
-)
-{
- char *new;
-
- if ( (new = ber_strdup( string )) == NULL ) {
- fprintf( stderr, "ch_strdup: duplication of \"%s\" failed\n",
- string );
- exit( EXIT_FAILURE );
- }
-
- return( new );
-}
-
-/*
- * Just like free, except we check to see if p is null.
- */
-void
-ch_free(
- void *p
-)
-{
- if ( p != NULL ) {
- ber_memfree( p );
- }
- return;
-}
-
-#endif
+++ /dev/null
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 1998-2007 The OpenLDAP Foundation.
- * Portions Copyright 2003 Mark Benson.
- * Portions Copyright 2002 John Morrissey.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted only as authorized by the OpenLDAP
- * Public License.
- *
- * A copy of this license is available in file LICENSE in the
- * top-level directory of the distribution or, alternatively, at
- * <http://www.OpenLDAP.org/license.html>.
- */
-/* Portions Copyright (c) 1996 Regents of the University of Michigan.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that this notice is preserved and that due credit is given
- * to the University of Michigan at Ann Arbor. The name of the University
- * may not be used to endorse or promote products derived from this
- * software without specific prior written permission. This software
- * is provided ``as is'' without express or implied warranty.
- */
-/* ACKNOWLEDGEMENTS:
- * This work was originally developed by the University of Michigan
- * (as part of U-MICH LDAP). Additional signficant contributors
- * include:
- * John Morrissey
- * Mark Benson
- */
-
-
-/*
- * config.c - configuration file handling routines
- */
-
-#include "portable.h"
-
-#include <stdio.h>
-
-#include <ac/stdlib.h>
-#include <ac/string.h>
-#include <ac/socket.h>
-#include <ac/ctype.h>
-
-#include <ldap.h>
-#include <lutil.h>
-
-#include "slurp.h"
-#include "globals.h"
-
-#define ARGS_STEP 512
-
-/* Forward declarations */
-static void add_replica LDAP_P(( char **, int ));
-static int parse_replica_line LDAP_P(( char **, int, Ri *));
-static void parse_line LDAP_P(( char * ));
-static char *slurpd_getline LDAP_P(( FILE * ));
-static char *strtok_quote LDAP_P(( char *, char * ));
-
-int cargc = 0, cargv_size = 0;
-char **cargv;
-/* current config file line # */
-static int lineno;
-
-char *slurpd_pid_file = NULL;
-char *slurpd_args_file = NULL;
-
-/*
- * Read the slapd config file, looking only for config options we're
- * interested in. Since we haven't detached from the controlling
- * terminal yet, we just perror() and fprintf here.
- */
-int
-slurpd_read_config(
- char *fname
-)
-{
- FILE *fp;
- char *line;
-
-#define GOT_REPLOG_NO (0)
-#define GOT_REPLOG_ONE (1)
-#define GOT_REPLOG_YES (2)
-#define GOT_REPLOG_DONE (3)
-#define GOT_REPLOG_MASK (0xF)
-#define GOT_REPLOG(i) ((i) & GOT_REPLOG_MASK)
-#define GOT_REPLOG_SET(i,v) ((i) = ((i) & ~GOT_REPLOG_MASK) | ((v) & GOT_REPLOG_MASK))
-
-#define GOT_REPLOG_PID (0x10)
-#define GOT_REPLOG_ARGS (0x20)
-#define GOT_REPLOG_INTERVAL (0x40)
- int got_replog = GOT_REPLOG_NO;
-
- /*
- * replica-pidfile and replica-argsfile can appear before any replog;
- * in this case they're global (legacy behavior); otherwise, since
- * each replog needs a slurpd, they can appear after a replogfile line;
- * in that case, the replog specific values are used.
- */
-
- if ( cargv == NULL ) {
- cargv = ch_calloc( ARGS_STEP + 1, sizeof(*cargv) );
- cargv_size = ARGS_STEP + 1;
- }
-
- Debug( LDAP_DEBUG_CONFIG, "Config: opening config file \"%s\"\n",
- fname, 0, 0 );
-
- if ( (fp = fopen( fname, "r" )) == NULL ) {
- perror( fname );
- exit( EXIT_FAILURE );
- }
-
- lineno = 0;
- while ( (line = slurpd_getline( fp )) != NULL ) {
- /* skip comments and blank lines */
- if ( line[0] == '#' || line[0] == '\0' ) {
- continue;
- }
-
- Debug( LDAP_DEBUG_CONFIG, "Config: (%s)\n", line, 0, 0 );
-
- parse_line( line );
-
- if ( cargc < 1 ) {
- fprintf( stderr, "line %d: bad config line (ignored)\n", lineno );
- continue;
- }
-
- /* replication log file to which changes are appended */
- if ( strcasecmp( cargv[0], "replogfile" ) == 0 ) {
- /*
- * if slapd_replogfile has a value, the -r option was given,
- * so use that value. If slapd_replogfile has length == 0,
- * then we should use the value in the config file we're reading.
- */
- if ( cargc < 2 ) {
- fprintf( stderr,
- "line %d: missing filename in \"replogfile ",
- lineno );
- fprintf( stderr, "<filename>\" line\n" );
- exit( EXIT_FAILURE );
-
- } else if ( cargc > 2 && *cargv[2] != '#' ) {
- fprintf( stderr,
- "line %d: extra cruft at the end of \"replogfile %s\"",
- lineno, cargv[1] );
- fprintf( stderr, "line (ignored)\n" );
- }
-
- LUTIL_SLASHPATH( cargv[1] );
- if ( sglob->slapd_replogfile[0] == '\0' ) {
- strcpy( sglob->slapd_replogfile, cargv[1] );
- GOT_REPLOG_SET(got_replog, GOT_REPLOG_YES);
-
- } else {
- if ( strcmp( sglob->slapd_replogfile, cargv[1] ) == 0 ) {
- GOT_REPLOG_SET(got_replog, GOT_REPLOG_YES);
-
- } else if ( GOT_REPLOG(got_replog) == GOT_REPLOG_YES ) {
- GOT_REPLOG_SET(got_replog, GOT_REPLOG_DONE);
-
- } else {
- GOT_REPLOG_SET(got_replog, GOT_REPLOG_ONE);
- }
- }
-
- } else if ( strcasecmp( cargv[0], "replica" ) == 0 ) {
- add_replica( cargv, cargc );
-
- /* include another config file */
- } else if ( strcasecmp( cargv[0], "include" ) == 0 ) {
- char *savefname;
- int savelineno;
-
- if ( cargc < 2 ) {
- Debug( LDAP_DEBUG_ANY,
- "%s: line %d: missing filename in \"include <filename>\" line\n",
- fname, lineno, 0 );
-
- fclose( fp );
- return( 1 );
- }
- LUTIL_SLASHPATH( cargv[1] );
- savefname = strdup( cargv[1] );
- savelineno = lineno;
-
- if ( slurpd_read_config( savefname ) != 0 ) {
- fclose( fp );
- return( 1 );
- }
-
- free( savefname );
- lineno = savelineno - 1;
-
- } else if ( strcasecmp( cargv[0], "replica-pidfile" ) == 0 ) {
- if ( cargc < 2 ) {
- Debug( LDAP_DEBUG_ANY,
- "%s: line %d: missing file name in \"replica-pidfile <file>\" line\n",
- fname, lineno, 0 );
-
- fclose( fp );
- return( 1 );
- }
-
- switch ( GOT_REPLOG(got_replog) ) {
- case GOT_REPLOG_YES:
- Debug( LDAP_DEBUG_CONFIG, "%s: line %d: "
- "got replog specific replica-pidfile \"%s\".\n",
- fname, lineno, cargv[1] );
- case GOT_REPLOG_NO:
- LUTIL_SLASHPATH( cargv[1] );
- if ( slurpd_pid_file != NULL ) {
- ch_free( slurpd_pid_file );
- }
- slurpd_pid_file = ch_strdup( cargv[1] );
- got_replog |= GOT_REPLOG_PID;
- break;
-
- default:
- Debug( LDAP_DEBUG_CONFIG, "%s: line %d: "
- "replica-pidfile \"%s\" not mine.\n",
- fname, lineno, cargv[1] );
- break;
- }
-
- } else if ( strcasecmp( cargv[0], "replica-argsfile" ) == 0 ) {
- if ( cargc < 2 ) {
- Debug( LDAP_DEBUG_ANY,
- "%s: line %d: missing file name in \"argsfile <file>\" line\n",
- fname, lineno, 0 );
-
- fclose( fp );
- return( 1 );
- }
-
- switch ( GOT_REPLOG(got_replog) ) {
- case GOT_REPLOG_YES:
- Debug( LDAP_DEBUG_CONFIG, "%s: line %d: "
- "got replog specific replica-argsfile \"%s\".\n",
- fname, lineno, cargv[1] );
- case GOT_REPLOG_NO:
- LUTIL_SLASHPATH( cargv[1] );
- if ( slurpd_args_file != NULL ) {
- ch_free( slurpd_args_file );
- }
- slurpd_args_file = ch_strdup( cargv[1] );
- got_replog |= GOT_REPLOG_ARGS;
- break;
-
- default:
- Debug( LDAP_DEBUG_CONFIG, "%s: line %d: "
- "replica-argsfile \"%s\" not mine.\n",
- fname, lineno, cargv[1] );
- break;
- }
-
- } else if ( strcasecmp( cargv[0], "replicationinterval" ) == 0 ) {
- int c;
-
- if ( cargc < 2 ) {
- Debug( LDAP_DEBUG_ANY, "%s: line %d: missing interval in "
- "\"replicationinterval <seconds>\" line\n",
- fname, lineno, 0 );
- fclose( fp );
- return( 1 );
- }
-
- if ( lutil_atoi( &c, cargv[1] ) != 0 || c < 1 ) {
- Debug( LDAP_DEBUG_ANY, "%s: line %d: invalid interval "
- "(%d) in \"replicationinterval <seconds>\" line\n",
- fname, lineno, c );
-
- fclose( fp );
- return( 1 );
- }
-
- switch ( GOT_REPLOG(got_replog) ) {
- case GOT_REPLOG_YES:
- Debug( LDAP_DEBUG_CONFIG, "%s: line %d: "
- "got replog specific replicationinterval \"%s\".\n",
- fname, lineno, cargv[1] );
- case GOT_REPLOG_NO:
- sglob->no_work_interval = c;
- got_replog |= GOT_REPLOG_INTERVAL;
- break;
-
- default:
- Debug( LDAP_DEBUG_CONFIG, "%s: line %d: "
- "replicationinterval \"%s\" not mine.\n",
- fname, lineno, cargv[1] );
- break;
- }
- }
- }
-
- fclose( fp );
- Debug( LDAP_DEBUG_CONFIG,
- "Config: ** configuration file successfully read and parsed\n",
- 0, 0, 0 );
- return 0;
-}
-
-
-
-
-/*
- * Parse one line of input.
- */
-static void
-parse_line(
- char *line
-)
-{
- char * token;
-
- cargc = 0;
- for ( token = strtok_quote( line, " \t" ); token != NULL;
- token = strtok_quote( NULL, " \t" ) )
- {
- if ( cargc == cargv_size - 1 ) {
- char **tmp;
- tmp = ch_realloc( cargv, (cargv_size + ARGS_STEP) *
- sizeof(*cargv) );
- if (tmp == NULL) {
- cargc = 0;
- return;
- }
- cargv = tmp;
- cargv_size += ARGS_STEP;
- }
-
- cargv[cargc++] = token;
- }
- cargv[cargc] = NULL;
-}
-
-
-
-
-static char *
-strtok_quote(
- char *line,
- char *sep
-)
-{
- int inquote;
- char *tmp;
- static char *next;
-
- if ( line != NULL ) {
- next = line;
- }
- while ( *next && strchr( sep, *next ) ) {
- next++;
- }
-
- if ( *next == '\0' ) {
- next = NULL;
- return( NULL );
- }
- tmp = next;
-
- for ( inquote = 0; *next; ) {
- switch ( *next ) {
- case '"':
- if ( inquote ) {
- inquote = 0;
- } else {
- inquote = 1;
- }
- AC_MEMCPY( next, next + 1, strlen( next + 1 ) + 1 );
- break;
-
- case '\\':
- if ( next[1] )
- AC_MEMCPY( next, next + 1, strlen( next + 1 ) + 1 );
- next++; /* dont parse the escaped character */
- break;
-
- default:
- if ( ! inquote ) {
- if ( strchr( sep, *next ) != NULL ) {
- *next++ = '\0';
- return( tmp );
- }
- }
- next++;
- break;
- }
- }
-
- return( tmp );
-}
-
-#define CATLINE( buf ) { \
- int len; \
- len = strlen( buf ); \
- while ( lcur + len + 1 > lmax ) { \
- lmax += BUFSIZ; \
- line = (char *) ch_realloc( line, lmax ); \
- } \
- strcpy( line + lcur, buf ); \
- lcur += len; \
-}
-
-
-
-/*
- * Get a line of input.
- */
-static char *
-slurpd_getline(
- FILE *fp
-)
-{
- char *p;
- static char buf[BUFSIZ];
- static char *line;
- static int lmax, lcur;
-
- lcur = 0;
- CATLINE( buf );
- while ( fgets( buf, sizeof(buf), fp ) != NULL ) {
- if ( (p = strchr( buf, '\n' )) != NULL ) {
- if( p > buf && p[-1] == '\r' ) --p;
- *p = '\0';
- }
- lineno++;
- if ( ! isspace( (unsigned char) buf[0] ) ) {
- return( line );
- }
-
- /* change leading whitespace to space */
- buf[0] = ' ';
-
- CATLINE( buf );
- }
- buf[0] = '\0';
-
- return( line[0] ? line : NULL );
-}
-
-
-/*
- * Add a node to the array of replicas.
- */
-static void
-add_replica(
- char **cargv,
- int cargc
-)
-{
- int nr;
-
- nr = ++sglob->num_replicas;
- sglob->replicas = (Ri **) ch_realloc( sglob->replicas,
- ( nr + 1 ) * sizeof( Re * ));
- if ( sglob->replicas == NULL ) {
- fprintf( stderr, "out of memory, add_replica\n" );
- exit( EXIT_FAILURE );
- }
- sglob->replicas[ nr ] = NULL;
-
- if ( Ri_init( &(sglob->replicas[ nr - 1 ])) < 0 ) {
- fprintf( stderr, "out of memory, Ri_init\n" );
- exit( EXIT_FAILURE );
- }
- if ( parse_replica_line( cargv, cargc,
- sglob->replicas[ nr - 1] ) < 0 ) {
- /* Something bad happened - back out */
- fprintf( stderr,
- "Warning: failed to add replica \"%s:%d - ignoring replica\n",
- sglob->replicas[ nr - 1 ]->ri_hostname == NULL ?
- "(null)" : sglob->replicas[ nr - 1 ]->ri_hostname,
- sglob->replicas[ nr - 1 ]->ri_port );
- sglob->replicas[ nr - 1] = NULL;
- sglob->num_replicas--;
- } else {
- Debug( LDAP_DEBUG_CONFIG,
- "Config: ** successfully added replica \"%s:%d\"\n",
- sglob->replicas[ nr - 1 ]->ri_hostname == NULL ?
- "(null)" : sglob->replicas[ nr - 1 ]->ri_hostname,
- sglob->replicas[ nr - 1 ]->ri_port, 0 );
- sglob->replicas[ nr - 1]->ri_stel =
- sglob->st->st_add( sglob->st,
- sglob->replicas[ nr - 1 ] );
- if ( sglob->replicas[ nr - 1]->ri_stel == NULL ) {
- fprintf( stderr, "Failed to add status element structure\n" );
- exit( EXIT_FAILURE );
- }
- }
-}
-
-
-
-/*
- * Parse a "replica" line from the config file. replica lines should be
- * in the following format:
- * replica host=<hostname:portnumber> binddn=<binddn>
- * bindmethod="simple" credentials=<creds>
- *
- * where:
- * <hostname:portnumber> describes the host name and port number where the
- * replica is running,
- *
- * <binddn> is the DN to bind to the replica slapd as,
- *
- * bindmethod is "simple", and
- *
- * <creds> are the credentials (e.g. password) for binddn. <creds> are
- * only used for bindmethod=simple.
- *
- * The "replica" config file line may be split across multiple lines. If
- * a line begins with whitespace, it is considered a continuation of the
- * previous line.
- */
-#define GOT_HOST 1
-#define GOT_DN 2
-#define GOT_METHOD 4
-#define GOT_ALL ( GOT_HOST | GOT_DN | GOT_METHOD )
-#define GOT_MECH 8
-
-static int
-parse_replica_line(
- char **cargv,
- int cargc,
- Ri *ri
-)
-{
- int gots = 0;
- int i;
- char *hp, *val;
- LDAPURLDesc *ludp;
-
- for ( i = 1; i < cargc; i++ ) {
- if ( !strncasecmp( cargv[ i ], HOSTSTR, sizeof( HOSTSTR ) - 1 ) ) {
- if ( gots & GOT_HOST ) {
- fprintf( stderr, "Error: Malformed \"replica\" line in slapd config " );
- fprintf( stderr, "file, too many host or uri names specified, line %d\n",
- lineno );
- return -1;
- }
- val = cargv[ i ] + sizeof( HOSTSTR ); /* '\0' string terminator accounts for '=' */
- if (( hp = strchr( val, ':' )) != NULL ) {
- *hp = '\0';
- hp++;
- if ( lutil_atoi( &ri->ri_port, hp ) != 0 ) {
- fprintf( stderr, "unable to parse port \"%s\", line %d\n",
- hp, lineno );
- return -1;
- }
- }
- if ( ri->ri_port <= 0 ) {
- ri->ri_port = LDAP_PORT;
- }
- ri->ri_hostname = strdup( val );
- gots |= GOT_HOST;
- } else if ( !strncasecmp( cargv[ i ], URISTR, sizeof( URISTR ) - 1 ) ) {
- if ( gots & GOT_HOST ) {
- fprintf( stderr, "Error: Malformed \"replica\" line in slapd config " );
- fprintf( stderr, "file, too many host or uri names specified, line %d\n",
- lineno );
- return -1;
- }
- if ( ldap_url_parse( cargv[ i ] + sizeof( URISTR ), &ludp ) != LDAP_SUCCESS ) {
- fprintf( stderr, "Error: Malformed \"replica\" line in slapd config " );
- fprintf( stderr, "file, bad uri format specified, line %d\n",
- lineno );
- return -1;
- }
- if (ludp->lud_host == NULL) {
- fprintf( stderr, "Error: Malformed \"replica\" line in slapd config " );
- fprintf( stderr, "file, missing uri hostname, line %d\n",
- lineno );
- ldap_free_urldesc( ludp );
- return -1;
- }
- ri->ri_hostname = strdup ( ludp->lud_host );
- ri->ri_port = ludp->lud_port;
- ri->ri_uri = strdup ( cargv[ i ] + sizeof( URISTR ) );
- ldap_free_urldesc( ludp );
- gots |= GOT_HOST;
- } else if ( !strncasecmp( cargv[ i ],
- ATTRSTR, sizeof( ATTRSTR ) - 1 ) ) {
- /* ignore it */ ;
- } else if ( !strncasecmp( cargv[ i ],
- SUFFIXSTR, sizeof( SUFFIXSTR ) - 1 ) ) {
- /* ignore it */ ;
- } else if ( !strncasecmp( cargv[i], STARTTLSSTR, sizeof(STARTTLSSTR)-1 )) {
- val = cargv[ i ] + sizeof( STARTTLSSTR );
- if( !strcasecmp( val, CRITICALSTR ) ) {
- ri->ri_tls = TLS_CRITICAL;
- } else {
- ri->ri_tls = TLS_ON;
- }
- } else if ( !strncasecmp( cargv[ i ], TLSSTR, sizeof( TLSSTR ) - 1 ) ) {
- val = cargv[ i ] + sizeof( TLSSTR );
- if( !strcasecmp( val, CRITICALSTR ) ) {
- ri->ri_tls = TLS_CRITICAL;
- } else {
- ri->ri_tls = TLS_ON;
- }
- } else if ( !strncasecmp( cargv[ i ],
- BINDDNSTR, sizeof( BINDDNSTR ) - 1 ) ) {
- val = cargv[ i ] + sizeof( BINDDNSTR );
- ri->ri_bind_dn = strdup( val );
- gots |= GOT_DN;
- } else if ( !strncasecmp( cargv[ i ], BINDMETHSTR,
- sizeof( BINDMETHSTR ) - 1 ) ) {
- val = cargv[ i ] + sizeof( BINDMETHSTR );
- if ( !strcasecmp( val, SIMPLESTR )) {
- ri->ri_bind_method = LDAP_AUTH_SIMPLE;
- gots |= GOT_METHOD;
- } else if ( !strcasecmp( val, SASLSTR )) {
- ri->ri_bind_method = LDAP_AUTH_SASL;
- gots |= GOT_METHOD;
- } else {
- ri->ri_bind_method = -1;
- }
- } else if ( !strncasecmp( cargv[ i ],
- SASLMECHSTR, sizeof( SASLMECHSTR ) - 1 ) ) {
- val = cargv[ i ] + sizeof( SASLMECHSTR );
- gots |= GOT_MECH;
- ri->ri_saslmech = strdup( val );
- } else if ( !strncasecmp( cargv[ i ],
- CREDSTR, sizeof( CREDSTR ) - 1 ) ) {
- val = cargv[ i ] + sizeof( CREDSTR );
- ri->ri_password = strdup( val );
- } else if ( !strncasecmp( cargv[ i ],
- SECPROPSSTR, sizeof( SECPROPSSTR ) - 1 ) ) {
- val = cargv[ i ] + sizeof( SECPROPSSTR );
- ri->ri_secprops = strdup( val );
- } else if ( !strncasecmp( cargv[ i ],
- REALMSTR, sizeof( REALMSTR ) - 1 ) ) {
- val = cargv[ i ] + sizeof( REALMSTR );
- ri->ri_realm = strdup( val );
- } else if ( !strncasecmp( cargv[ i ],
- AUTHCSTR, sizeof( AUTHCSTR ) - 1 ) ) {
- val = cargv[ i ] + sizeof( AUTHCSTR );
- ri->ri_authcId = strdup( val );
- } else if ( !strncasecmp( cargv[ i ],
- OLDAUTHCSTR, sizeof( OLDAUTHCSTR ) - 1 ) ) {
- /* Old authcID is provided for some backwards compatibility */
- val = cargv[ i ] + sizeof( OLDAUTHCSTR );
- ri->ri_authcId = strdup( val );
- } else if ( !strncasecmp( cargv[ i ],
- AUTHZSTR, sizeof( AUTHZSTR ) - 1 ) ) {
- val = cargv[ i ] + sizeof( AUTHZSTR );
- ri->ri_authzId = strdup( val );
- } else {
- fprintf( stderr,
- "Error: parse_replica_line: unknown keyword \"%s\"\n",
- cargv[ i ] );
- }
- }
-
- if ( ri->ri_bind_method == LDAP_AUTH_SASL) {
- if ((gots & GOT_MECH) == 0) {
- fprintf( stderr, "Error: \"replica\" line needs SASLmech flag in " );
- fprintf( stderr, "slapd config file, line %d\n", lineno );
- return -1;
- }
- } else if ( gots != GOT_ALL ) {
- fprintf( stderr, "Error: Malformed \"replica\" line in slapd " );
- fprintf( stderr, "config file, line %d\n", lineno );
- return -1;
- }
- return 0;
-}
-
+++ /dev/null
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 1998-2007 The OpenLDAP Foundation.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted only as authorized by the OpenLDAP
- * Public License.
- *
- * A copy of this license is available in file LICENSE in the
- * top-level directory of the distribution or, alternatively, at
- * <http://www.OpenLDAP.org/license.html>.
- */
-/* Portions Copyright (c) 1996 Regents of the University of Michigan.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that this notice is preserved and that due credit is given
- * to the University of Michigan at Ann Arbor. The name of the University
- * may not be used to endorse or promote products derived from this
- * software without specific prior written permission. This software
- * is provided ``as is'' without express or implied warranty.
- */
-/* ACKNOWLEDGEMENTS:
- * This work was originally developed by the University of Michigan
- * (as part of U-MICH LDAP).
- */
-
-/*
- * fm.c - file management routines.
- */
-
-#include "portable.h"
-
-#include <stdio.h>
-
-#include <ac/stdlib.h>
-#include <ac/string.h>
-#include <ac/signal.h>
-#include <ac/socket.h>
-#include <ac/unistd.h>
-
-#include "slurp.h"
-#include "globals.h"
-#include "lutil.h"
-
-
-/*
- * Forward references
- */
-static char *get_record LDAP_P(( FILE * ));
-static void populate_queue LDAP_P(( char *f ));
-
-
-/*
- * Main file manager routine. Watches for new data to be appended to the
- * slapd replication log. When new data is appended, fm does the following:
- * - appends the data to slurpd's private copy of the replication log.
- * - truncates the slapd replog
- * - adds items to the internal queue of replication work to do
- * - signals the replication threads to let them know new work has arrived.
- */
-void *
-fm(
- void *arg
-)
-{
- int rc;
- int i;
- fd_set readfds;
-
- /* Set up our signal handlers:
- * SIG{TERM,INT,HUP} causes a shutdown
- */
- (void) SIGNAL( SIGTERM, slurp_set_shutdown );
- (void) SIGNAL( SIGINT, slurp_set_shutdown );
-#ifdef SIGHUP
- (void) SIGNAL( SIGHUP, slurp_set_shutdown );
-#endif
-#if defined(SIGBREAK)
- (void) SIGNAL( SIGBREAK, slurp_set_shutdown );
-#endif
-
- if ( sglob->one_shot_mode ) {
- if ( file_nonempty( sglob->slapd_replogfile )) {
- populate_queue( sglob->slapd_replogfile );
- }
- printf( "Processing in one-shot mode:\n" );
- printf( "%d total replication records in file,\n",
- sglob->rq->rq_getcount( sglob->rq, RQ_COUNT_ALL ));
- printf( "%d replication records to process.\n",
- sglob->rq->rq_getcount( sglob->rq, RQ_COUNT_NZRC ));
- return NULL;
- }
- /*
- * There may be some leftover replication records in our own
- * copy of the replication log. If any exist, add them to the
- * queue.
- */
- if ( file_nonempty( sglob->slurpd_replogfile )) {
- populate_queue( sglob->slurpd_replogfile );
- }
-
- FD_ZERO( &readfds );
-
- while ( !sglob->slurpd_shutdown ) {
- if ( file_nonempty( sglob->slapd_replogfile )) {
- /* New work found - copy to slurpd replog file */
- Debug( LDAP_DEBUG_ARGS, "new work in %s\n",
- sglob->slapd_replogfile, 0, 0 );
- if (( rc = copy_replog( sglob->slapd_replogfile,
- sglob->slurpd_replogfile )) == 0 ) {
- populate_queue( sglob->slurpd_replogfile );
- } else {
- if ( rc < 0 ) {
- Debug( LDAP_DEBUG_ANY,
- "Fatal error while copying replication log\n",
- 0, 0, 0 );
- sglob->slurpd_shutdown = 1;
- }
- }
- } else {
- struct timeval tv;
-
- FD_SET( sglob->wake_sds[0], &readfds );
- tv.tv_sec = sglob->no_work_interval;
- tv.tv_usec = 0;
-
- rc = select( sglob->wake_sds[0]+1, &readfds, NULL, NULL, &tv );
- }
-
- /* Garbage-collect queue */
- sglob->rq->rq_gc( sglob->rq );
-
- /* Trim replication log file, if needed */
- if ( sglob->rq->rq_needtrim( sglob->rq )) {
- FILE *fp, *lfp;
- if (( rc = acquire_lock( sglob->slurpd_replogfile, &fp,
- &lfp )) < 0 ) {
- Debug( LDAP_DEBUG_ANY,
- "Error: cannot acquire lock on \"%s\" for trimming\n",
- sglob->slurpd_replogfile, 0, 0 );
- } else {
- sglob->rq->rq_write( sglob->rq, fp );
- (void) relinquish_lock( sglob->slurpd_replogfile, fp, lfp );
- }
- }
- }
- sglob->rq->rq_lock( sglob->rq ); /* lock queue */
- ldap_pvt_thread_cond_broadcast( &(sglob->rq->rq_more) ); /* wake repl threads */
- for ( i = 0; i < sglob->num_replicas; i++ ) {
- (sglob->replicas[ i ])->ri_wake( sglob->replicas[ i ]);
- }
- sglob->rq->rq_unlock( sglob->rq ); /* unlock queue */
- Debug( LDAP_DEBUG_ARGS, "fm: exiting\n", 0, 0, 0 );
- return NULL;
-}
-
-
-
-
-/*
- * Set a global flag which signals that we're shutting down.
- */
-RETSIGTYPE
-slurp_set_shutdown(int sig)
-{
-#if HAVE_NT_SERVICE_MANAGER && SIGBREAK
- if (is_NT_Service && sig == SIGBREAK) {
- /* empty */;
- } else
-#endif
- {
- sglob->slurpd_shutdown = 1; /* set flag */
- tcp_write( sglob->wake_sds[1], "0", 1); /* wake up file mgr */
- }
-
- (void) SIGNAL_REINSTALL( sig, slurp_set_shutdown ); /* reinstall handlers */
-}
-
-
-
-
-/*
- * A do-nothing signal handler.
- */
-RETSIGTYPE
-do_nothing(int sig)
-{
- (void) SIGNAL_REINSTALL( sig, do_nothing );
-}
-
-
-
-
-/*
- * Open the slurpd replication log, seek to our last known position, and
- * process any pending replication entries.
- */
-static void
-populate_queue(
- char *f
-)
-{
- FILE *fp, *lfp;
- char *p;
-
- if ( acquire_lock( f, &fp, &lfp ) < 0 ) {
- Debug( LDAP_DEBUG_ANY,
- "error: can't lock file \"%s\": %s\n",
- f, sys_errlist[ errno ], 0 );
- return;
- }
-
- /*
- * Read replication records from fp and append them the
- * the queue.
- */
- if ( fseek( fp, sglob->srpos, 0 ) < 0 ) {
- Debug( LDAP_DEBUG_ANY,
- "error: can't seek to offset %ld in file \"%s\"\n",
- sglob->srpos, f, 0 );
- } else {
- while (( p = get_record( fp )) != NULL ) {
- if ( sglob->rq->rq_add( sglob->rq, p ) < 0 ) {
- char *t;
- /* Print an error message. Only print first line. */
- if (( t = strchr( p, '\n' )) != NULL ) {
- *t = '\0';
- }
- Debug( LDAP_DEBUG_ANY,
- "error: malformed replog entry (begins with \"%s\")\n",
- p, 0, 0 );
- }
- free( p );
- ldap_pvt_thread_yield();
- }
- sglob->srpos = ftell( fp );
- }
- (void) relinquish_lock( f, fp, lfp );
-}
-
-
-
-
-/*
- * Get the next "record" from the file pointed to by fp. A "record"
- * is delimited by two consecutive newlines. Returns NULL on EOF.
- */
-static char *
-get_record(
- FILE *fp
-)
-{
- int len;
- static char line[BUFSIZ];
- char *buf = NULL;
- static int lcur, lmax;
-
- lcur = lmax = 0;
-
- while (( fgets( line, sizeof(line), fp ) != NULL ) &&
- (( len = strlen( line )) > 1 )) {
-
- while ( lcur + len + 1 > lmax ) {
- lmax += BUFSIZ;
- buf = (char *) ch_realloc( buf, lmax );
- }
- strcpy( buf + lcur, line );
- lcur += len;
- }
- return( buf );
-}
+++ /dev/null
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 1998-2007 The OpenLDAP Foundation.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted only as authorized by the OpenLDAP
- * Public License.
- *
- * A copy of this license is available in file LICENSE in the
- * top-level directory of the distribution or, alternatively, at
- * <http://www.OpenLDAP.org/license.html>.
- */
-/* Portions Copyright (c) 1996 Regents of the University of Michigan.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that this notice is preserved and that due credit is given
- * to the University of Michigan at Ann Arbor. The name of the University
- * may not be used to endorse or promote products derived from this
- * software without specific prior written permission. This software
- * is provided ``as is'' without express or implied warranty.
- */
-/* ACKNOWLEDGEMENTS:
- * This work was originally developed by the University of Michigan
- * (as part of U-MICH LDAP).
- */
-
-/*
- * globals.c - initialization code for global data
- */
-
-#include "portable.h"
-
-#include <stdio.h>
-
-#include <ac/stdlib.h>
-#include <ac/string.h>
-
-#include "slurp.h"
-#include "globals.h"
-
-Globals *sglob;
-static Globals glob;
-
-int ldap_syslog = 0;
-#ifdef LOG_DEBUG
-int ldap_syslog_level = LOG_DEBUG;
-#else
-int ldap_syslog_level = 0;
-#endif
-int ldap_debug = 0;
-
-/*
- * Initialize the globals
- */
-Globals *
-init_globals( void )
-{
- Globals *g;
-
- g = &glob;
-
- g->wake_sds[0] = -1;
- g->wake_sds[1] = -1;
-
-#ifdef HAVE_NT_SERVICE_MANAGER
- g->slapd_configfile = ".\\slapd.conf";
- g->slurpd_rdir = ".\\replica";
-#else
- g->slapd_configfile = SLAPD_DEFAULT_CONFIGFILE;
- g->slurpd_rdir = DEFAULT_SLURPD_REPLICA_DIR "/replica";
-#endif
-
- g->no_work_interval = DEFAULT_NO_WORK_INTERVAL;
- g->slurpd_shutdown = 0;
- g->num_replicas = 0;
- g->replicas = NULL;
- g->slapd_replogfile[ 0 ] = '\0';
- g->slurpd_replogfile[ 0 ] = '\0';
- g->slurpd_status_file[ 0 ] = '\0';
- g->one_shot_mode = 0;
- g->no_detach = 0;
- g->myname = NULL;
- g->serverName = NULL;
- g->srpos = 0L;
- g->version = 0;
- if ( St_init( &(g->st)) < 0 ) {
- fprintf( stderr, "Cannot initialize status data\n" );
- exit( EXIT_FAILURE );
- }
- ldap_pvt_thread_mutex_init( &(g->rej_mutex) );
- if ( Rq_init( &(g->rq)) < 0 ) {
- fprintf( stderr, "Cannot initialize queue\n" );
- exit( EXIT_FAILURE );
- }
-
- return g;
-}
+++ /dev/null
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 1998-2007 The OpenLDAP Foundation.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted only as authorized by the OpenLDAP
- * Public License.
- *
- * A copy of this license is available in file LICENSE in the
- * top-level directory of the distribution or, alternatively, at
- * <http://www.OpenLDAP.org/license.html>.
- */
-/* Portions Copyright (c) 1996 Regents of the University of Michigan.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that this notice is preserved and that due credit is given
- * to the University of Michigan at Ann Arbor. The name of the University
- * may not be used to endorse or promote products derived from this
- * software without specific prior written permission. This software
- * is provided ``as is'' without express or implied warranty.
- */
-/* ACKNOWLEDGEMENTS:
- * This work was originally developed by the University of Michigan
- * (as part of U-MICH LDAP).
- */
-
-#ifndef SLURPD_GLOBALS_H
-#define SLURPD_GLOBALS_H 1
-
-/*
- * globals.h - definition of structure holding global data.
- */
-
-#include "slurp.h"
-
-LDAP_BEGIN_DECL
-
-typedef struct globals {
- /* Thread ID for file manager thread */
- ldap_pvt_thread_t fm_tid;
- /* pipe/socket used to wake manager from signal handler */
- int wake_sds[2];
- /* The name of the slapd config file (which is also our config file) */
- char *slapd_configfile;
- /* How long the master slurpd sleeps when there's no work to do */
- int no_work_interval;
- /* We keep running until slurpd_shutdown is nonzero. HUP signal set this */
- sig_atomic_t slurpd_shutdown;
- /* Number of replicas we're servicing */
- int num_replicas;
- /* Array of pointers to replica info */
- Ri **replicas;
- /* Directory where our replica files are written/read */
- char *slurpd_rdir;
- /* Name of slurpd status file (timestamp of last replog */
- char slurpd_status_file[ MAXPATHLEN ];
- /* Name of the replication log slapd is writing (and we are reading) */
- char slapd_replogfile[ MAXPATHLEN ];
- /* Name of local copy of replogfile we maintain */
- char slurpd_replogfile[ MAXPATHLEN ];
- /* Non-zero if we were given a replog file to process on command-line */
- int one_shot_mode;
- /* Non-zero if we should not detach the process */
- int no_detach;
- /* Name of program */
- char *myname;
- /* NT service name */
- char *serverName;
- /* Current offset into slurpd replica logfile */
- off_t srpos;
- /* mutex to serialize access to reject file */
- ldap_pvt_thread_mutex_t rej_mutex;
- /* pointer to status struct */
- St *st;
- /* Pointer to replication queue */
- Rq *rq;
- /* Non-zero if we shall print the version */
- int version;
-} Globals;
-
-
-extern Globals *sglob;
-
-LDAP_END_DECL
-
-#endif /* SLURPD_GLOBALS_H */
+++ /dev/null
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 1998-2007 The OpenLDAP Foundation.
- * Portions Copyright 2003 Mark Benson.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted only as authorized by the OpenLDAP
- * Public License.
- *
- * A copy of this license is available in file LICENSE in the
- * top-level directory of the distribution or, alternatively, at
- * <http://www.OpenLDAP.org/license.html>.
- */
-/* Portions Copyright (c) 1996 Regents of the University of Michigan.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that this notice is preserved and that due credit is given
- * to the University of Michigan at Ann Arbor. The name of the University
- * may not be used to endorse or promote products derived from this
- * software without specific prior written permission. This software
- * is provided ``as is'' without express or implied warranty.
- */
-/* ACKNOWLEDGEMENTS:
- * This work was originally developed by the University of Michigan
- * (as part of U-MICH LDAP). Additional significant contributors
- * include:
- * Mark Benson
- */
-
-/*
- * ldap_op.c - routines to perform LDAP operations
- */
-
-#include "portable.h"
-
-#include <stdio.h>
-
-#include <ac/stdlib.h>
-
-#include <ac/errno.h>
-#include <ac/string.h>
-#include <ac/ctype.h>
-#include <ac/time.h>
-#include <ac/unistd.h>
-
-#define LDAP_DEPRECATED 1
-#include <ldap.h>
-#include "lutil_ldap.h"
-#include "slurp.h"
-
-/* Forward references */
-static struct berval **make_singlevalued_berval LDAP_P(( char *, int ));
-static int op_ldap_add LDAP_P(( Ri *, Re *, char **, int * ));
-static int op_ldap_modify LDAP_P(( Ri *, Re *, char **, int * ));
-static int op_ldap_delete LDAP_P(( Ri *, Re *, char **, int * ));
-static int op_ldap_modrdn LDAP_P(( Ri *, Re *, char **, int * ));
-static LDAPMod *alloc_ldapmod LDAP_P(( void ));
-static void free_ldapmod LDAP_P(( LDAPMod * ));
-static void free_ldmarr LDAP_P(( LDAPMod ** ));
-static int getmodtype LDAP_P(( char * ));
-#ifdef SLAPD_UNUSED
-static void dump_ldm_array LDAP_P(( LDAPMod ** ));
-#endif
-static int do_bind LDAP_P(( Ri *, int * ));
-static int do_unbind LDAP_P(( Ri * ));
-
-
-/*
- * Determine the type of ldap operation being performed and call the
- * appropriate routine.
- * - If successful, returns DO_LDAP_OK
- * - If a retryable error occurs, ERR_DO_LDAP_RETRYABLE is returned.
- * The caller should wait a while and retry the operation.
- * - If a fatal error occurs, ERR_DO_LDAP_FATAL is returned. The caller
- * should reject the operation and continue with the next replication
- * entry.
- */
-int
-do_ldap(
- Ri *ri,
- Re *re,
- char **errmsg,
- int *errfree
-)
-{
- int retry = 2;
- *errmsg = NULL;
- *errfree = 0;
-
- do {
- int lderr;
- if ( ri->ri_ldp == NULL ) {
- lderr = do_bind( ri, &lderr );
-
- if ( lderr != BIND_OK ) {
- return DO_LDAP_ERR_RETRYABLE;
- }
- }
-
- switch ( re->re_changetype ) {
- case T_ADDCT:
- lderr = op_ldap_add( ri, re, errmsg, errfree );
- if ( lderr != LDAP_SUCCESS ) {
- Debug( LDAP_DEBUG_ANY,
- "Error: ldap_add_s failed adding DN \"%s\": %s\n",
- re->re_dn, *errmsg && (*errmsg)[0] ?
- *errmsg : ldap_err2string( lderr ), 0 );
- }
- break;
-
- case T_MODIFYCT:
- lderr = op_ldap_modify( ri, re, errmsg, errfree );
- if ( lderr != LDAP_SUCCESS ) {
- Debug( LDAP_DEBUG_ANY,
- "Error: ldap_modify_s failed modifying DN \"%s\": %s\n",
- re->re_dn, *errmsg && (*errmsg)[0] ?
- *errmsg : ldap_err2string( lderr ), 0 );
- }
- break;
-
- case T_DELETECT:
- lderr = op_ldap_delete( ri, re, errmsg, errfree );
- if ( lderr != LDAP_SUCCESS ) {
- Debug( LDAP_DEBUG_ANY,
- "Error: ldap_delete_s failed deleting DN \"%s\": %s\n",
- re->re_dn, *errmsg && (*errmsg)[0] ?
- *errmsg : ldap_err2string( lderr ), 0 );
- }
- break;
-
- case T_MODRDNCT:
- lderr = op_ldap_modrdn( ri, re, errmsg, errfree );
- if ( lderr != LDAP_SUCCESS ) {
- Debug( LDAP_DEBUG_ANY,
- "Error: ldap_modrdn_s failed modifying DN \"%s\": %s\n",
- re->re_dn, *errmsg && (*errmsg)[0] ?
- *errmsg : ldap_err2string( lderr ), 0 );
- }
- break;
-
- default:
- Debug( LDAP_DEBUG_ANY,
- "Error: do_ldap: bad op \"%d\", DN \"%s\"\n",
- re->re_changetype, re->re_dn, 0 );
- return DO_LDAP_ERR_FATAL;
- }
-
- /*
- * Analyze return code. If ok, just return. If LDAP_SERVER_DOWN,
- * we may have been idle long enough that the remote slapd timed
- * us out. Rebind and try again.
- */
- switch( lderr ) {
- case LDAP_SUCCESS:
- return DO_LDAP_OK;
-
- default:
- return DO_LDAP_ERR_FATAL;
-
- case LDAP_SERVER_DOWN: /* server went down */
- (void) do_unbind( ri );
- retry--;
- }
- } while ( retry > 0 );
-
- return DO_LDAP_ERR_RETRYABLE;
-}
-
-
-
-/*
- * Perform an ldap add operation.
- */
-static int
-op_ldap_add(
- Ri *ri,
- Re *re,
- char **errmsg,
- int *errfree
-)
-{
- Mi *mi;
- int nattrs, rc = 0, i;
- LDAPMod *ldm, **ldmarr;
- int lderr = 0;
-
- nattrs = i = 0;
- ldmarr = NULL;
-
- /*
- * Construct a null-terminated array of LDAPMod structs.
- */
- mi = re->re_mods;
- while ( mi[ i ].mi_type != NULL ) {
- ldm = alloc_ldapmod();
- ldmarr = ( LDAPMod ** ) ch_realloc( ldmarr,
- ( nattrs + 2 ) * sizeof( LDAPMod * ));
- ldmarr[ nattrs ] = ldm;
- ldm->mod_op = LDAP_MOD_BVALUES;
- ldm->mod_type = mi[ i ].mi_type;
- ldm->mod_bvalues =
- make_singlevalued_berval( mi[ i ].mi_val, mi[ i ].mi_len );
- i++;
- nattrs++;
- }
-
- if ( ldmarr != NULL ) {
- ldmarr[ nattrs ] = NULL;
-
- /* Perform the operation */
- Debug( LDAP_DEBUG_ARGS, "replica %s:%d - add dn \"%s\"\n",
- ri->ri_hostname, ri->ri_port, re->re_dn );
- rc = ldap_add_s( ri->ri_ldp, re->re_dn, ldmarr );
-
- ldap_get_option( ri->ri_ldp, LDAP_OPT_RESULT_CODE, &lderr);
- ldap_get_option( ri->ri_ldp, LDAP_OPT_DIAGNOSTIC_MESSAGE, errmsg);
- *errfree = 1;
-
- } else {
- *errmsg = "No modifications to do";
- Debug( LDAP_DEBUG_ANY,
- "Error: op_ldap_add: no mods to do (%s)!\n", re->re_dn, 0, 0 );
- }
- free_ldmarr( ldmarr );
- return( lderr );
-}
-
-
-
-
-/*
- * Perform an ldap modify operation.
- */
-#define AWAITING_OP -1
-static int
-op_ldap_modify(
- Ri *ri,
- Re *re,
- char **errmsg,
- int *errfree
-)
-{
- Mi *mi;
- int state; /* This code is a simple-minded state machine */
- int nvals; /* Number of values we're modifying */
- int nops; /* Number of LDAPMod structs in ldmarr */
- LDAPMod *ldm = NULL, **ldmarr;
- int i, len;
- char *type, *value;
- int rc = 0;
-
- state = AWAITING_OP;
- nvals = 0;
- nops = 0;
- ldmarr = NULL;
-
- if ( re->re_mods == NULL ) {
- *errmsg = "No arguments given";
- Debug( LDAP_DEBUG_ANY, "Error: op_ldap_modify: no arguments\n",
- 0, 0, 0 );
- return -1;
- }
-
- /*
- * Construct a null-terminated array of LDAPMod structs.
- */
- for ( mi = re->re_mods, i = 0; mi[ i ].mi_type != NULL; i++ ) {
- type = mi[ i ].mi_type;
- value = mi[ i ].mi_val;
- len = mi[ i ].mi_len;
- switch ( getmodtype( type )) {
- case T_MODSEP:
- state = T_MODSEP; /* Got a separator line "-\n" */
- continue;
- case T_MODOPADD:
- state = T_MODOPADD;
- ldmarr = ( LDAPMod ** )
- ch_realloc(ldmarr, (( nops + 2 ) * ( sizeof( LDAPMod * ))));
- ldmarr[ nops ] = ldm = alloc_ldapmod();
- ldm->mod_op = LDAP_MOD_ADD | LDAP_MOD_BVALUES;
- ldm->mod_type = value;
- nvals = 0;
- nops++;
- break;
- case T_MODOPREPLACE:
- state = T_MODOPREPLACE;
- ldmarr = ( LDAPMod ** )
- ch_realloc(ldmarr, (( nops + 2 ) * ( sizeof( LDAPMod * ))));
- ldmarr[ nops ] = ldm = alloc_ldapmod();
- ldm->mod_op = LDAP_MOD_REPLACE | LDAP_MOD_BVALUES;
- ldm->mod_type = value;
- nvals = 0;
- nops++;
- break;
- case T_MODOPDELETE:
- state = T_MODOPDELETE;
- ldmarr = ( LDAPMod ** )
- ch_realloc(ldmarr, (( nops + 2 ) * ( sizeof( LDAPMod * ))));
- ldmarr[ nops ] = ldm = alloc_ldapmod();
- ldm->mod_op = LDAP_MOD_DELETE | LDAP_MOD_BVALUES;
- ldm->mod_type = value;
- nvals = 0;
- nops++;
- break;
- case T_MODOPINCREMENT:
- state = T_MODOPINCREMENT;
- ldmarr = ( LDAPMod ** )
- ch_realloc(ldmarr, (( nops + 2 ) * ( sizeof( LDAPMod * ))));
- ldmarr[ nops ] = ldm = alloc_ldapmod();
- ldm->mod_op = LDAP_MOD_INCREMENT | LDAP_MOD_BVALUES;
- ldm->mod_type = value;
- nvals = 0;
- nops++;
- break;
- default:
- if ( state == AWAITING_OP ) {
- Debug( LDAP_DEBUG_ANY,
- "Error: op_ldap_modify: unknown mod type \"%s\"\n",
- type, 0, 0 );
- continue;
- }
-
- assert( ldm != NULL );
-
- /*
- * We should have an attribute: value pair here.
- * Construct the mod_bvalues part of the ldapmod struct.
- */
- if ( strcasecmp( type, ldm->mod_type )) {
- Debug( LDAP_DEBUG_ANY,
- "Error: malformed modify op, %s: %s (expecting %s:)\n",
- type, value, ldm->mod_type );
- continue;
- }
- ldm->mod_bvalues = ( struct berval ** )
- ch_realloc( ldm->mod_bvalues,
- ( nvals + 2 ) * sizeof( struct berval * ));
- ldm->mod_bvalues[ nvals + 1 ] = NULL;
- ldm->mod_bvalues[ nvals ] = ( struct berval * )
- ch_malloc( sizeof( struct berval ));
- ldm->mod_bvalues[ nvals ]->bv_val = value;
- ldm->mod_bvalues[ nvals ]->bv_len = len;
- nvals++;
- }
- }
- ldmarr[ nops ] = NULL;
-
- if ( nops > 0 ) {
- /* Actually perform the LDAP operation */
- Debug( LDAP_DEBUG_ARGS, "replica %s:%d - modify dn \"%s\"\n",
- ri->ri_hostname, ri->ri_port, re->re_dn );
- rc = ldap_modify_s( ri->ri_ldp, re->re_dn, ldmarr );
- ldap_get_option( ri->ri_ldp, LDAP_OPT_DIAGNOSTIC_MESSAGE, errmsg);
- *errfree = 1;
- }
- free_ldmarr( ldmarr );
- return( rc );
-}
-
-
-
-
-/*
- * Perform an ldap delete operation.
- */
-static int
-op_ldap_delete(
- Ri *ri,
- Re *re,
- char **errmsg,
- int *errfree
-)
-{
- int rc;
-
- Debug( LDAP_DEBUG_ARGS, "replica %s:%d - delete dn \"%s\"\n",
- ri->ri_hostname, ri->ri_port, re->re_dn );
- rc = ldap_delete_s( ri->ri_ldp, re->re_dn );
- ldap_get_option( ri->ri_ldp, LDAP_OPT_DIAGNOSTIC_MESSAGE, errmsg);
- *errfree = 1;
-
- return( rc );
-}
-
-
-
-
-/*
- * Perform an ldap modrdn operation.
- */
-#define GOT_NEWRDN 0x1
-#define GOT_DELOLDRDN 0x2
-#define GOT_NEWSUP 0x4
-
-#define GOT_MODDN_REQ (GOT_NEWRDN|GOT_DELOLDRDN)
-#define GOT_ALL_MODDN(f) (((f) & GOT_MODDN_REQ) == GOT_MODDN_REQ)
-static int
-op_ldap_modrdn(
- Ri *ri,
- Re *re,
- char **errmsg,
- int *errfree
-)
-{
- int rc = 0;
- Mi *mi;
- int i;
- int lderr = 0;
- int state = 0;
- int drdnflag = -1;
- char *newrdn = NULL;
- char *newsup = NULL;
-
- if ( re->re_mods == NULL ) {
- *errmsg = "No arguments given";
- Debug( LDAP_DEBUG_ANY, "Error: op_ldap_modrdn: no arguments\n",
- 0, 0, 0 );
- return -1;
- }
-
- /*
- * Get the arguments: should see newrdn: and deleteoldrdn: args.
- */
- for ( mi = re->re_mods, i = 0; mi[ i ].mi_type != NULL; i++ ) {
- if ( !strcmp( mi[ i ].mi_type, T_NEWRDNSTR )) {
- if( state & GOT_NEWRDN ) {
- Debug( LDAP_DEBUG_ANY,
- "Error: op_ldap_modrdn: multiple newrdn arg \"%s\"\n",
- mi[ i ].mi_val, 0, 0 );
- *errmsg = "Multiple newrdn argument";
- return -1;
- }
-
- newrdn = mi[ i ].mi_val;
- state |= GOT_NEWRDN;
-
- } else if ( !strcmp( mi[ i ].mi_type, T_DELOLDRDNSTR )) {
- if( state & GOT_DELOLDRDN ) {
- Debug( LDAP_DEBUG_ANY,
- "Error: op_ldap_modrdn: multiple deleteoldrdn arg \"%s\"\n",
- mi[ i ].mi_val, 0, 0 );
- *errmsg = "Multiple newrdn argument";
- return -1;
- }
-
- state |= GOT_DELOLDRDN;
- if ( !strcmp( mi[ i ].mi_val, "0" )) {
- drdnflag = 0;
- } else if ( !strcmp( mi[ i ].mi_val, "1" )) {
- drdnflag = 1;
- } else {
- Debug( LDAP_DEBUG_ANY,
- "Error: op_ldap_modrdn: bad deleteoldrdn arg \"%s\"\n",
- mi[ i ].mi_val, 0, 0 );
- *errmsg = "Incorrect argument to deleteoldrdn";
- return -1;
- }
-
- } else if ( !strcmp( mi[ i ].mi_type, T_NEWSUPSTR )) {
- if( state & GOT_NEWSUP ) {
- Debug( LDAP_DEBUG_ANY,
- "Error: op_ldap_modrdn: multiple newsuperior arg \"%s\"\n",
- mi[ i ].mi_val, 0, 0 );
- *errmsg = "Multiple newsuperior argument";
- return -1;
- }
-
- newsup = mi[ i ].mi_val;
- state |= GOT_NEWSUP;
-
- } else {
- Debug( LDAP_DEBUG_ANY, "Error: op_ldap_modrdn: bad type \"%s\"\n",
- mi[ i ].mi_type, 0, 0 );
- *errmsg = "Bad value in replication log entry";
- return -1;
- }
- }
-
- /*
- * Punt if we don't have all the args.
- */
- if ( !GOT_ALL_MODDN(state) ) {
- Debug( LDAP_DEBUG_ANY, "Error: op_ldap_modrdn: missing arguments\n",
- 0, 0, 0 );
- *errmsg = "Missing argument: requires \"newrdn\" and \"deleteoldrdn\"";
- return -1;
- }
-
-#ifdef LDAP_DEBUG
- if ( ldap_debug & LDAP_DEBUG_ARGS ) {
- char buf[ 256 ];
- char *buf2;
- int buf2len = strlen( re->re_dn ) + strlen( mi->mi_val ) + 11;
-
- snprintf( buf, sizeof(buf), "%s:%d", ri->ri_hostname, ri->ri_port );
-
- buf2 = (char *) ch_malloc( buf2len );
- snprintf( buf2, buf2len, "(\"%s\" -> \"%s\")", re->re_dn, mi->mi_val );
-
- Debug( LDAP_DEBUG_ARGS,
- "replica %s - modify rdn %s (flag: %d)\n",
- buf, buf2, drdnflag );
- free( buf2 );
- }
-#endif /* LDAP_DEBUG */
-
- assert( newrdn != NULL );
-
- /* Do the modrdn */
- rc = ldap_rename2_s( ri->ri_ldp, re->re_dn, newrdn, newsup, drdnflag );
-
- ldap_get_option( ri->ri_ldp, LDAP_OPT_RESULT_CODE, &lderr);
- ldap_get_option( ri->ri_ldp, LDAP_OPT_DIAGNOSTIC_MESSAGE, errmsg);
- *errfree = 1;
- return( lderr );
-}
-
-
-
-/*
- * Allocate and initialize an ldapmod struct.
- */
-static LDAPMod *
-alloc_ldapmod( void )
-{
- LDAPMod *ldm;
-
- ldm = ( struct ldapmod * ) ch_malloc( sizeof ( struct ldapmod ));
- ldm->mod_type = NULL;
- ldm->mod_bvalues = ( struct berval ** ) NULL;
- return( ldm );
-}
-
-
-
-/*
- * Free an ldapmod struct associated mod_bvalues. NOTE - it is assumed
- * that mod_bvalues and mod_type contain pointers to the same block of memory
- * pointed to by the repl struct. Therefore, it's not freed here.
- */
-static void
-free_ldapmod(
-LDAPMod *ldm )
-{
- int i;
-
- if ( ldm == NULL ) {
- return;
- }
- if ( ldm->mod_bvalues != NULL ) {
- for ( i = 0; ldm->mod_bvalues[ i ] != NULL; i++ ) {
- free( ldm->mod_bvalues[ i ] );
- }
- free( ldm->mod_bvalues );
- }
- free( ldm );
- return;
-}
-
-
-/*
- * Free an an array of LDAPMod pointers and the LDAPMod structs they point
- * to.
- */
-static void
-free_ldmarr(
-LDAPMod **ldmarr )
-{
- int i;
-
- for ( i = 0; ldmarr[ i ] != NULL; i++ ) {
- free_ldapmod( ldmarr[ i ] );
- }
- free( ldmarr );
-}
-
-
-/*
- * Create a berval with a single value.
- */
-static struct berval **
-make_singlevalued_berval(
-char *value,
-int len )
-{
- struct berval **p;
-
- p = ( struct berval ** ) ch_malloc( 2 * sizeof( struct berval * ));
- p[ 0 ] = ( struct berval * ) ch_malloc( sizeof( struct berval ));
- p[ 1 ] = NULL;
- p[ 0 ]->bv_val = value;
- p[ 0 ]->bv_len = len;
- return( p );
-}
-
-
-/*
- * Given a modification type (string), return an enumerated type.
- * Avoids ugly copy in op_ldap_modify - lets us use a switch statement
- * there.
- */
-static int
-getmodtype(
-char *type )
-{
- if ( !strcmp( type, T_MODSEPSTR )) {
- return( T_MODSEP );
- }
- if ( !strcmp( type, T_MODOPADDSTR )) {
- return( T_MODOPADD );
- }
- if ( !strcmp( type, T_MODOPREPLACESTR )) {
- return( T_MODOPREPLACE );
- }
- if ( !strcmp( type, T_MODOPDELETESTR )) {
- return( T_MODOPDELETE );
- }
- if ( !strcmp( type, T_MODOPINCREMENTSTR )) {
- return( T_MODOPINCREMENT );
- }
- return( T_ERR );
-}
-
-
-/*
- * Perform an LDAP unbind operation. If replica is NULL, or the
- * repl_ldp is NULL, just return LDAP_SUCCESS. Otherwise, unbind,
- * set the ldp to NULL, and return the result of the unbind call.
- */
-static int
-do_unbind(
- Ri *ri
-)
-{
- int rc = LDAP_SUCCESS;
-
- if (( ri != NULL ) && ( ri->ri_ldp != NULL )) {
- rc = ldap_unbind( ri->ri_ldp );
- if ( rc != LDAP_SUCCESS ) {
- Debug( LDAP_DEBUG_ANY,
- "Error: do_unbind: ldap_unbind failed for %s:%d: %s\n",
- ri->ri_hostname, ri->ri_port, ldap_err2string( rc ) );
- }
- ri->ri_ldp = NULL;
- }
- return rc;
-}
-
-
-
-/*
- * Perform an LDAP bind operation to the replication site given
- * by replica. If replica->repl_ldp is non-NULL, then we unbind
- * from the replica before rebinding. It should be safe to call
- * this to re-connect if the replica's connection goes away
- * for some reason.
- *
- * Returns 0 on success, -1 if an LDAP error occurred, and a return
- * code > 0 if some other error occurred, e.g. invalid bind method.
- * If an LDAP error occurs, the LDAP error is returned in lderr.
- */
-static int
-do_bind(
- Ri *ri,
- int *lderr
-)
-{
- int ldrc;
- int do_tls;
-
- *lderr = 0;
-
- if ( ri == NULL ) {
- Debug( LDAP_DEBUG_ANY, "Error: do_bind: null ri ptr\n", 0, 0, 0 );
- return( BIND_ERR_BADRI );
- }
-
- do_tls = ri->ri_tls;
-
-retry:
- if ( ri->ri_ldp != NULL ) {
- ldrc = ldap_unbind( ri->ri_ldp );
- if ( ldrc != LDAP_SUCCESS ) {
- Debug( LDAP_DEBUG_ANY,
- "Error: do_bind: ldap_unbind failed: %s\n",
- ldap_err2string( ldrc ), 0, 0 );
- }
- ri->ri_ldp = NULL;
- }
-
- if ( ri->ri_uri != NULL ) { /* new URI style */
- Debug( LDAP_DEBUG_ARGS, "Initializing session to %s\n",
- ri->ri_uri, 0, 0 );
-
- ldrc = ldap_initialize( &(ri->ri_ldp), ri->ri_uri);
-
- if (ldrc != LDAP_SUCCESS) {
- Debug( LDAP_DEBUG_ANY, "Error: ldap_initialize(0, %s) failed: %s\n",
- ri->ri_uri, ldap_err2string(ldrc), 0 );
- return( BIND_ERR_OPEN );
- }
- } else { /* old HOST style */
- Debug( LDAP_DEBUG_ARGS, "Initializing session to %s:%d\n",
- ri->ri_hostname, ri->ri_port, 0 );
-
- ri->ri_ldp = ldap_init( ri->ri_hostname, ri->ri_port );
- if ( ri->ri_ldp == NULL ) {
- Debug( LDAP_DEBUG_ANY, "Error: ldap_init(%s, %d) failed: %s\n",
- ri->ri_hostname, ri->ri_port, sys_errlist[ errno ] );
- return( BIND_ERR_OPEN );
- }
- }
-
- { /* set version 3 */
- int err, version = LDAP_VERSION3;
- err = ldap_set_option(ri->ri_ldp,
- LDAP_OPT_PROTOCOL_VERSION, &version);
-
- if( err != LDAP_OPT_SUCCESS ) {
- Debug( LDAP_DEBUG_ANY,
- "Error: ldap_set_option(%s, LDAP_OPT_VERSION, 3) failed!\n",
- ri->ri_hostname, NULL, NULL );
-
- ldap_unbind( ri->ri_ldp );
- ri->ri_ldp = NULL;
- return BIND_ERR_VERSION;
- }
- }
-
- /*
- * Set ldap library options to (1) not follow referrals, and
- * (2) restart the select() system call.
- */
- {
- int err;
- err = ldap_set_option(ri->ri_ldp, LDAP_OPT_REFERRALS, LDAP_OPT_OFF);
-
- if( err != LDAP_OPT_SUCCESS ) {
- Debug( LDAP_DEBUG_ANY,
- "Error: ldap_set_option(%s,REFERRALS, OFF) failed!\n",
- ri->ri_hostname, NULL, NULL );
- ldap_unbind( ri->ri_ldp );
- ri->ri_ldp = NULL;
- return BIND_ERR_REFERRALS;
- }
- }
- ldap_set_option(ri->ri_ldp, LDAP_OPT_RESTART, LDAP_OPT_ON);
-
- if( do_tls ) {
- int err = ldap_start_tls_s(ri->ri_ldp, NULL, NULL);
-
- if( err != LDAP_SUCCESS ) {
- Debug( LDAP_DEBUG_ANY,
- "%s: ldap_start_tls failed: %s (%d)\n",
- ri->ri_tls == TLS_CRITICAL ? "Error" : "Warning",
- ldap_err2string( err ), err );
-
- if( ri->ri_tls == TLS_CRITICAL ) {
- *lderr = err;
- ldap_unbind( ri->ri_ldp );
- ri->ri_ldp = NULL;
- return BIND_ERR_TLS_FAILED;
- }
- do_tls = TLS_OFF;
- goto retry;
- }
- }
-
- switch ( ri->ri_bind_method ) {
- case LDAP_AUTH_SIMPLE:
- /*
- * Bind with a plaintext password.
- */
- Debug( LDAP_DEBUG_ARGS, "bind to %s:%d as %s (simple)\n",
- ri->ri_hostname, ri->ri_port, ri->ri_bind_dn );
- ldrc = ldap_simple_bind_s( ri->ri_ldp, ri->ri_bind_dn,
- ri->ri_password );
- if ( ldrc != LDAP_SUCCESS ) {
- Debug( LDAP_DEBUG_ANY,
- "Error: ldap_simple_bind_s for %s:%d failed: %s\n",
- ri->ri_hostname, ri->ri_port, ldap_err2string( ldrc ));
- *lderr = ldrc;
- ldap_unbind( ri->ri_ldp );
- ri->ri_ldp = NULL;
- return( BIND_ERR_SIMPLE_FAILED );
- }
- break;
-
- case LDAP_AUTH_SASL:
- Debug( LDAP_DEBUG_ARGS, "bind to %s as %s via %s (SASL)\n",
- ri->ri_hostname,
- ri->ri_authcId ? ri->ri_authcId : "-",
- ri->ri_saslmech );
-
-#ifdef HAVE_CYRUS_SASL
- if( ri->ri_secprops != NULL ) {
- int err = ldap_set_option(ri->ri_ldp,
- LDAP_OPT_X_SASL_SECPROPS, ri->ri_secprops);
-
- if( err != LDAP_OPT_SUCCESS ) {
- Debug( LDAP_DEBUG_ANY,
- "Error: ldap_set_option(%s,SECPROPS,\"%s\") failed!\n",
- ri->ri_hostname, ri->ri_secprops, NULL );
- ldap_unbind( ri->ri_ldp );
- ri->ri_ldp = NULL;
- return BIND_ERR_SASL_FAILED;
- }
- }
-
- {
- void *defaults = lutil_sasl_defaults( ri->ri_ldp, ri->ri_saslmech,
- ri->ri_realm, ri->ri_authcId, ri->ri_password, ri->ri_authzId );
-
- ldrc = ldap_sasl_interactive_bind_s( ri->ri_ldp, ri->ri_bind_dn,
- ri->ri_saslmech, NULL, NULL,
- LDAP_SASL_QUIET, lutil_sasl_interact, defaults );
-
- lutil_sasl_freedefs( defaults );
- if ( ldrc != LDAP_SUCCESS ) {
- Debug( LDAP_DEBUG_ANY, "Error: LDAP SASL for %s:%d failed: %s\n",
- ri->ri_hostname, ri->ri_port, ldap_err2string( ldrc ));
- *lderr = ldrc;
- ldap_unbind( ri->ri_ldp );
- ri->ri_ldp = NULL;
- return( BIND_ERR_SASL_FAILED );
- }
- }
- break;
-#else
- Debug( LDAP_DEBUG_ANY,
- "Error: do_bind: SASL not supported %s:%d\n",
- ri->ri_hostname, ri->ri_port, NULL );
- ldap_unbind( ri->ri_ldp );
- ri->ri_ldp = NULL;
- return( BIND_ERR_BAD_ATYPE );
-#endif
-
- default:
- Debug( LDAP_DEBUG_ANY,
- "Error: do_bind: unknown auth type \"%d\" for %s:%d\n",
- ri->ri_bind_method, ri->ri_hostname, ri->ri_port );
- ldap_unbind( ri->ri_ldp );
- ri->ri_ldp = NULL;
- return( BIND_ERR_BAD_ATYPE );
- }
-
- {
- int err;
- LDAPControl c;
- LDAPControl *ctrls[2];
- ctrls[0] = &c;
- ctrls[1] = NULL;
-
- c.ldctl_oid = LDAP_CONTROL_MANAGEDSAIT;
- c.ldctl_value.bv_val = NULL;
- c.ldctl_value.bv_len = 0;
- c.ldctl_iscritical = 0;
-
- err = ldap_set_option(ri->ri_ldp, LDAP_OPT_SERVER_CONTROLS, &ctrls);
-
- if( err != LDAP_OPT_SUCCESS ) {
- Debug( LDAP_DEBUG_ANY, "Error: "
- "ldap_set_option(%s, SERVER_CONTROLS, ManageDSAit) failed!\n",
- ri->ri_hostname, NULL, NULL );
- ldap_unbind( ri->ri_ldp );
- ri->ri_ldp = NULL;
- return BIND_ERR_MANAGEDSAIT;
- }
- }
-
- return( BIND_OK );
-}
-
-
-
-
-
-/*
- * For debugging. Print the contents of an ldmarr array.
- */
-#ifdef SLAPD_UNUSED
-static void
-dump_ldm_array(
- LDAPMod **ldmarr
-)
-{
- int i, j;
- LDAPMod *ldm;
- struct berval *b;
- char *msgbuf;
-
- for ( i = 0; ldmarr[ i ] != NULL; i++ ) {
- ldm = ldmarr[ i ];
- Debug( LDAP_DEBUG_TRACE,
- "Trace (%ld): *** ldmarr[ %d ] contents:\n",
- (long) getpid(), i, 0 );
- Debug( LDAP_DEBUG_TRACE,
- "Trace (%ld): *** ldm->mod_op: %d\n",
- (long) getpid(), ldm->mod_op, 0 );
- Debug( LDAP_DEBUG_TRACE,
- "Trace (%ld): *** ldm->mod_type: %s\n",
- (long) getpid(), ldm->mod_type, 0 );
- if ( ldm->mod_bvalues != NULL ) {
- for ( j = 0; ( b = ldm->mod_bvalues[ j ] ) != NULL; j++ ) {
- msgbuf = ch_malloc( b->bv_len + 512 );
- sprintf( msgbuf, "***** bv[ %d ] len = %ld, val = <%s>",
- j, b->bv_len, b->bv_val );
- Debug( LDAP_DEBUG_TRACE,
- "Trace (%ld):%s\n", (long) getpid(), msgbuf, 0 );
- free( msgbuf );
- }
- }
- }
-}
-#endif
+++ /dev/null
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 1998-2007 The OpenLDAP Foundation.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted only as authorized by the OpenLDAP
- * Public License.
- *
- * A copy of this license is available in file LICENSE in the
- * top-level directory of the distribution or, alternatively, at
- * <http://www.OpenLDAP.org/license.html>.
- */
-/* Portions Copyright (c) 1996 Regents of the University of Michigan.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that this notice is preserved and that due credit is given
- * to the University of Michigan at Ann Arbor. The name of the University
- * may not be used to endorse or promote products derived from this
- * software without specific prior written permission. This software
- * is provided ``as is'' without express or implied warranty.
- */
-/* ACKNOWLEDGEMENTS:
- * This work was originally developed by the University of Michigan
- * (as part of U-MICH LDAP).
- */
-
-/*
- * lock.c - routines to open and apply an advisory lock to a file
- */
-
-#include "portable.h"
-
-#include <stdio.h>
-
-#include <ac/param.h>
-#include <ac/string.h>
-#include <ac/socket.h>
-#include <ac/time.h>
-#include <ac/unistd.h>
-
-#ifdef HAVE_SYS_FILE_H
-#include <sys/file.h>
-#endif
-
-#include "slurp.h"
-
-
-FILE *
-lock_fopen(
- const char *fname,
- const char *type,
- FILE **lfp
-)
-{
- FILE *fp;
- char buf[MAXPATHLEN];
-
- /* open the lock file */
- snprintf( buf, sizeof buf, "%s.lock", fname );
-
- if ( (*lfp = fopen( buf, "w" )) == NULL ) {
- Debug( LDAP_DEBUG_ANY,
- "Error: could not open \"%s\"\n", buf, 0, 0 );
- return( NULL );
- }
-
- /* acquire the lock */
- ldap_lockf( fileno(*lfp) );
-
- /* open the log file */
- if ( (fp = fopen( fname, type )) == NULL ) {
- Debug( LDAP_DEBUG_ANY,
- "Error: could not open \"%s\"\n", fname, 0, 0 );
- ldap_unlockf( fileno(*lfp) );
- fclose( *lfp );
- *lfp = NULL;
- return( NULL );
- }
-
- return( fp );
-}
-
-
-
-int
-lock_fclose(
- FILE *fp,
- FILE *lfp
-)
-{
- int rc = fclose( fp );
-
- /* unlock */
- ldap_unlockf( fileno(lfp) );
- fclose( lfp );
-
- return( rc );
-}
-
-
-
-/*
- * Apply an advisory lock on a file. Just calls lock_fopen()
- */
-int
-acquire_lock(
- const char *file,
- FILE **rfp,
- FILE **lfp
-)
-{
- if (( *rfp = lock_fopen( file, "r+", lfp )) == NULL ) {
- Debug( LDAP_DEBUG_ANY,
- "Error: acquire_lock(%ld): Could not acquire lock on \"%s\"\n",
- (long) getpid(), file, 0);
- return( -1 );
- }
- return( 0 );
-}
-
-
-
-/*
- * Relinquish a lock on a file. Calls lock_fclose() and also removes the
- * lock file.
- */
-int
-relinquish_lock(
- const char *file,
- FILE *rfp,
- FILE *lfp
-)
-{
- if ( lock_fclose( rfp, lfp ) == EOF ) {
- Debug( LDAP_DEBUG_ANY,
- "Error: relinquish_lock (%ld): Error closing \"%s\"\n",
- (long) getpid(), file, 0 );
- return( -1 );
- }
- return( 0 );
-}
+++ /dev/null
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 1998-2007 The OpenLDAP Foundation.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted only as authorized by the OpenLDAP
- * Public License.
- *
- * A copy of this license is available in file LICENSE in the
- * top-level directory of the distribution or, alternatively, at
- * <http://www.OpenLDAP.org/license.html>.
- */
-/* Portions Copyright (c) 1996 Regents of the University of Michigan.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that this notice is preserved and that due credit is given
- * to the University of Michigan at Ann Arbor. The name of the University
- * may not be used to endorse or promote products derived from this
- * software without specific prior written permission. This software
- * is provided ``as is'' without express or implied warranty.
- */
-/* ACKNOWLEDGEMENTS:
- * This work was originally developed by the University of Michigan
- * (as part of U-MICH LDAP). Additional significant contributors
- * include:
- * Howard Chu
- */
-
-
-/*
- * main.c - main routine for slurpd.
- */
-
-#include "portable.h"
-
-#include <stdio.h>
-#include <sys/stat.h>
-#include <ac/stdlib.h>
-#include <ac/unistd.h>
-
-#include "slurp.h"
-#include "globals.h"
-#include "lutil.h"
-
-#include <ldap_pvt.h>
-
-#ifdef HAVE_NT_SERVICE_MANAGER
-#define MAIN_RETURN(x) return
-#define SERVICE_EXIT( e, n ) do { \
- if ( is_NT_Service ) { \
- lutil_ServiceStatus.dwWin32ExitCode = (e); \
- lutil_ServiceStatus.dwServiceSpecificExitCode = (n); \
- } \
-} while ( 0 )
-#else
-#define SERVICE_EXIT( e, n )
-#define MAIN_RETURN(x) return(x)
-#endif
-
-#ifndef HAVE_MKVERSION
-const char Versionstr[] =
- OPENLDAP_PACKAGE " " OPENLDAP_VERSION " Standalone LDAP Replicator (slurpd)";
-#endif
-
-#ifdef HAVE_NT_SERVICE_MANAGER
-void WINAPI ServiceMain( DWORD argc, LPTSTR *argv )
-#else
-int main( int argc, char **argv )
-#endif
-{
-#ifdef NO_THREADS
- /* Haven't yet written the non-threaded version */
- fputs( "slurpd currently requires threads support\n", stderr );
- return( 1 );
-#else
-
- int i, rc = 0;
-
- /* initialize thread package */
- ldap_pvt_thread_initialize();
-
- /*
- * Create and initialize globals. init_globals() also initializes
- * the main replication queue.
- */
- if (( sglob = init_globals()) == NULL ) {
- fprintf( stderr, "Out of memory initializing globals\n" );
- SERVICE_EXIT( ERROR_NOT_ENOUGH_MEMORY, 0 );
- rc = 1;
- goto stop;
- }
-
-#ifdef HAVE_NT_SERVICE_MANAGER
- {
- int *i;
- char *newConfigFile;
- char *regService = NULL;
-
- if ( is_NT_Service ) {
- sglob->serverName = argv[0];
- lutil_CommenceStartupProcessing( sglob->serverName, slurp_set_shutdown );
- if ( strcmp(sglob->serverName, SERVICE_NAME) )
- regService = sglob->serverName;
- }
-
- i = (int*)lutil_getRegParam( regService, "DebugLevel" );
- if ( i != NULL )
- {
- ldap_debug = *i;
- Debug( LDAP_DEBUG_ANY, "new debug level from registry is: %d\n", ldap_debug, 0, 0 );
- }
-
- newConfigFile = (char*)lutil_getRegParam( regService, "ConfigFile" );
- if ( newConfigFile != NULL )
- {
- sglob->slapd_configfile = newConfigFile;
- Debug ( LDAP_DEBUG_ANY, "new config file from registry is: %s\n", sglob->slapd_configfile, 0, 0 );
-
- }
- }
-#endif
-
- /*
- * Process command-line args and fill in globals.
- */
- if ( doargs( argc, argv, sglob ) < 0 ) {
- SERVICE_EXIT( ERROR_SERVICE_SPECIFIC_ERROR, 15 );
- rc = 1;
- goto stop;
- }
-
- if ( sglob->version ) {
- fprintf(stderr, "%s\n", Versionstr);
- if (sglob->version > 1 ) {
- rc = 1;
- goto stop;
- }
- }
-
- Debug ( LDAP_DEBUG_ANY, "%s\n", Versionstr, 0, 0 );
-
- /*
- * Read slapd config file and initialize Re (per-replica) structs.
- */
- if ( slurpd_read_config( sglob->slapd_configfile ) < 0 ) {
- fprintf( stderr,
- "Errors encountered while processing config file \"%s\"\n",
- sglob->slapd_configfile );
- SERVICE_EXIT( ERROR_SERVICE_SPECIFIC_ERROR, 19 );
- rc = 1;
- goto stop;
- }
-
-#ifdef HAVE_TLS
- if( ldap_pvt_tls_init() || ldap_pvt_tls_init_def_ctx( 0 ) ) {
- rc = 0;
- /* See if we actually need TLS */
- for ( i=0; i < sglob->num_replicas; i++ ) {
- if ( sglob->replicas[i]->ri_tls || ( sglob->replicas[i]->ri_uri &&
- !strncmp( sglob->replicas[i]->ri_uri, "ldaps:", 6 ))) {
- rc = 1;
- break;
- }
- }
- if ( rc ) {
- fprintf( stderr, "TLS Initialization failed.\n" );
- SERVICE_EXIT( ERROR_SERVICE_SPECIFIC_ERROR, 20 );
- goto stop;
- }
- }
-#endif
-
- /*
- * Make sure our directory exists
- */
- if ( mkdir(sglob->slurpd_rdir, 0755) == -1 && errno != EEXIST) {
- perror(sglob->slurpd_rdir);
- SERVICE_EXIT( ERROR_SERVICE_SPECIFIC_ERROR, 16 );
- rc = 1;
- goto stop;
- }
-
- /*
- * Get any saved state information off the disk.
- */
- if ( sglob->st->st_read( sglob->st )) {
- fprintf( stderr, "Malformed slurpd status file \"%s\"\n",
- sglob->slurpd_status_file );
- SERVICE_EXIT( ERROR_SERVICE_SPECIFIC_ERROR, 17 );
- rc = 1;
- goto stop;
- }
-
- /*
- * All readonly data should now be initialized.
- * Check for any fatal error conditions before we get started
- */
- if ( sanity() < 0 ) {
- SERVICE_EXIT( ERROR_SERVICE_SPECIFIC_ERROR, 18 );
- rc = 1;
- goto stop;
- }
-
-
- /*
- * Detach from the controlling terminal
- * unless the -d flag is given or in one-shot mode.
- */
-#ifndef HAVE_WINSOCK
- if ( ! (sglob->no_detach || sglob->one_shot_mode) ) {
- lutil_detach( 0, 0 );
- }
-#endif
-
- /*
- * don't open pid/args file in one-shot mode (ITS#4152)
- *
- * bail out if files were specified but cannot be opened (ITS#4074)
- */
- if ( !sglob->one_shot_mode) {
- if ( slurpd_pid_file != NULL ) {
- FILE *fp = fopen( slurpd_pid_file, "w" );
-
- if ( fp == NULL ) {
- int save_errno = errno;
-
- fprintf( stderr, "unable to open pid file "
- "\"%s\": %d (%s)\n",
- slurpd_pid_file,
- save_errno, strerror( save_errno ) );
-
- free( slurpd_pid_file );
- slurpd_pid_file = NULL;
-
- rc = 1;
- goto stop;
- }
-
- fprintf( fp, "%d\n", (int) getpid() );
- fclose( fp );
- }
-
- if ( slurpd_args_file != NULL ) {
- FILE *fp = fopen( slurpd_args_file, "w" );
-
- if ( fp == NULL ) {
- int save_errno = errno;
-
- fprintf( stderr, "unable to open args file "
- "\"%s\": %d (%s)\n",
- slurpd_args_file,
- save_errno, strerror( save_errno ) );
-
- free( slurpd_args_file );
- slurpd_pid_file = NULL;
-
- rc = 1;
- goto stop;
- }
-
- for ( i = 0; i < argc; i++ ) {
- fprintf( fp, "%s ", argv[i] );
- }
- fprintf( fp, "\n" );
- fclose( fp );
- }
- }
-
- if ( (rc = lutil_pair( sglob->wake_sds )) < 0 ) {
- SERVICE_EXIT( ERROR_SERVICE_SPECIFIC_ERROR, 16 );
- rc = 1;
- goto stop;
- }
-
-#ifdef HAVE_NT_EVENT_LOG
- if (is_NT_Service) lutil_LogStartedEvent( sglob->serverName, ldap_debug, sglob->slapd_configfile, "n/a" );
-#endif
-
- /*
- * Start the main file manager thread (in fm.c).
- */
- if ( ldap_pvt_thread_create( &(sglob->fm_tid),
- 0, fm, (void *) NULL ) != 0 )
- {
- Debug( LDAP_DEBUG_ANY, "file manager ldap_pvt_thread_create failed\n",
- 0, 0, 0 );
- SERVICE_EXIT( ERROR_SERVICE_SPECIFIC_ERROR, 21 );
- rc = 1;
- goto stop;
-
- }
-
- /*
- * wait for fm to finish if in oneshot mode
- */
- if ( sglob->one_shot_mode ) {
- ldap_pvt_thread_join( sglob->fm_tid, (void *) NULL );
- }
-
- /*
- * Start threads - one thread for each replica
- */
- for ( i = 0; sglob->replicas[ i ] != NULL; i++ ) {
- start_replica_thread( sglob->replicas[ i ]);
- }
-
-#ifdef HAVE_NT_SERVICE_MANAGER
- if ( started_event ) ldap_pvt_thread_cond_signal( &started_event );
-#endif
-
- /*
- * Wait for the fm thread to finish.
- */
- if ( !sglob->one_shot_mode ) {
- ldap_pvt_thread_join( sglob->fm_tid, (void *) NULL );
- }
-
- /*
- * Wait for the replica threads to finish.
- */
- for ( i = 0; sglob->replicas[ i ] != NULL; i++ ) {
- ldap_pvt_thread_join( sglob->replicas[ i ]->ri_tid, (void *) NULL );
- }
-
-stop:
-#ifdef HAVE_NT_SERVICE_MANAGER
- if (is_NT_Service) {
- ldap_pvt_thread_cond_destroy( &started_event );
- lutil_LogStoppedEvent( sglob->serverName );
- lutil_ReportShutdownComplete();
- }
-#endif
- /* destroy the thread package */
- ldap_pvt_thread_destroy();
-
-#ifdef HAVE_TLS
- ldap_pvt_tls_destroy();
-#endif
-
- Debug( LDAP_DEBUG_ANY, "slurpd: terminated.\n", 0, 0, 0 );
-
- if ( slurpd_pid_file != NULL ) {
- unlink( slurpd_pid_file );
- }
- if ( slurpd_args_file != NULL ) {
- unlink( slurpd_args_file );
- }
-
-
- MAIN_RETURN(rc);
-#endif /* !NO_THREADS */
-}
+++ /dev/null
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 1998-2007 The OpenLDAP Foundation.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted only as authorized by the OpenLDAP
- * Public License.
- *
- * A copy of this license is available in file LICENSE in the
- * top-level directory of the distribution or, alternatively, at
- * <http://www.OpenLDAP.org/license.html>.
- */
-
-#include "portable.h"
-#include <stdio.h>
-#include <ac/string.h>
-#include <ac/stdlib.h>
-#include "slurp.h"
-#include "lutil.h"
-
-#ifdef HAVE_NT_SERVICE_MANAGER
-
-/* in main.c */
-void WINAPI ServiceMain( DWORD argc, LPTSTR *argv );
-
-int main( int argc, LPTSTR *argv )
-{
- int length;
- char filename[MAX_PATH], *fname_start;
-
- /*
- * Because the service was registered as SERVICE_WIN32_OWN_PROCESS,
- * the lpServiceName element of the SERVICE_TABLE_ENTRY will be
- * ignored.
- */
-
- SERVICE_TABLE_ENTRY DispatchTable[] = {
- { "", (LPSERVICE_MAIN_FUNCTION) ServiceMain },
- { NULL, NULL }
- };
-
- /*
- * set the service's current directory to the installation directory
- * for the service. this way we don't have to write absolute paths
- * in the configuration files
- */
- GetModuleFileName( NULL, filename, sizeof( filename ) );
- fname_start = strrchr( filename, *LDAP_DIRSEP );
-
- if ( argc > 1 ) {
- if ( _stricmp( "install", argv[1] ) == 0 )
- {
- char *svcName = SERVICE_NAME;
- char *displayName = "OpenLDAP Replication Service";
- BOOL auto_start = FALSE;
-
- if ( (argc > 2) && (argv[2] != NULL) )
- svcName = argv[2];
-
- if ( argc > 3 && argv[3])
- displayName = argv[3];
-
- if ( argc > 4 && stricmp(argv[4], "auto") == 0)
- auto_start = TRUE;
-
- strcat(filename, " service");
- if ( !lutil_srv_install(svcName, displayName, filename, auto_start) )
- {
- fputs( "service failed installation ...\n", stderr );
- return EXIT_FAILURE;
- }
- fputs( "service has been installed ...\n", stderr );
- return EXIT_SUCCESS;
- }
-
- if ( _stricmp( "remove", argv[1] ) == 0 )
- {
- char *svcName = SERVICE_NAME;
- if ( (argc > 2) && (argv[2] != NULL) )
- svcName = argv[2];
- if ( !lutil_srv_remove(svcName, filename) )
- {
- fputs( "failed to remove the service ...\n", stderr );
- return EXIT_FAILURE;
- }
- fputs( "service has been removed ...\n", stderr );
- return EXIT_SUCCESS;
- }
- if ( _stricmp( "service", argv[1] ) == 0 )
- {
- is_NT_Service = 1;
- *fname_start = '\0';
- SetCurrentDirectory( filename );
- }
- }
-
- if (is_NT_Service)
- {
- StartServiceCtrlDispatcher(DispatchTable);
- } else
- {
- ServiceMain( argc, argv );
- }
-
- return EXIT_SUCCESS;
-}
-
-#endif
+++ /dev/null
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 1998-2007 The OpenLDAP Foundation.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted only as authorized by the OpenLDAP
- * Public License.
- *
- * A copy of this license is available in file LICENSE in the
- * top-level directory of the distribution or, alternatively, at
- * <http://www.OpenLDAP.org/license.html>.
- */
-/* Portions Copyright (c) 1996 Regents of the University of Michigan.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that this notice is preserved and that due credit is given
- * to the University of Michigan at Ann Arbor. The name of the University
- * may not be used to endorse or promote products derived from this
- * software without specific prior written permission. This software
- * is provided ``as is'' without express or implied warranty.
- */
-/* ACKNOWLEDGEMENTS:
- * This work was originally developed by the University of Michigan
- * (as part of U-MICH LDAP).
- */
-
-#ifndef _PROTO_SLURP
-#define _PROTO_SLURP
-
-#include <ldap_cdefs.h>
-
-struct globals;
-
-/* admin.c */
-RETSIGTYPE do_admin LDAP_P((int sig));
-
-/* args.c */
-int doargs LDAP_P((int argc, char **argv, struct globals *g));
-
-/* ch_malloc.c */
-#ifdef CSRIMALLOC
-#define ch_malloc malloc
-#define ch_realloc realloc
-#define ch_calloc calloc
-#define ch_strdup strdup
-#define ch_free free
-#else
-void *ch_malloc LDAP_P((ber_len_t size));
-void *ch_realloc LDAP_P((void *block, ber_len_t size));
-void *ch_calloc LDAP_P((ber_len_t nelem, ber_len_t size));
-char *ch_strdup LDAP_P((const char *str));
-void ch_free LDAP_P((void *p));
-#endif
-
-/* config.c */
-int slurpd_read_config LDAP_P((char *fname));
-
-extern char *slurpd_pid_file;
-extern char *slurpd_args_file;
-
-/* ch_malloc.c */
-void ch_free LDAP_P(( void *p ));
-
-/* fm.c */
-void *fm LDAP_P((void *arg));
-RETSIGTYPE do_nothing LDAP_P((int i));
-RETSIGTYPE slurp_set_shutdown LDAP_P((int));
-
-/* globals.c */
-extern struct globals *sglob;
-extern int ldap_syslog;
-extern int ldap_syslog_level;
-extern int ldap_debug;
-extern struct globals *init_globals LDAP_P((void));
-
-/* ldap_op.c */
-int do_ldap LDAP_P((Ri *ri, Re *re, char **errmsg, int *errfree));
-
-/* lock.c */
-FILE *lock_fopen LDAP_P((const char *fname, const char *type, FILE **lfp));
-int lock_fclose LDAP_P((FILE *fp, FILE *lfp));
-int acquire_lock LDAP_P((const char *file, FILE **rfp, FILE **lfp));
-int relinquish_lock LDAP_P((const char *file, FILE *rfp, FILE *lfp));
-
-/* reject.c */
-void write_reject LDAP_P((Ri *ri, Re *re, int lderr, char *errmsg));
-
-/* replica.c */
-int start_replica_thread LDAP_P((Ri *ri));
-
-/* replog.c */
-int copy_replog LDAP_P((char *src, char *dst));
-int file_nonempty LDAP_P((char *filename));
-
-/* sanity.c */
-int sanity LDAP_P((void));
-
-/* st.c */
-int St_init LDAP_P((St **st));
-
-/* tsleep.c */
-int tsleep LDAP_P((time_t interval));
-#if defined( HAVE_LWP )
-void start_lwp_scheduler LDAP_P(( void ));
-#endif
-
-/*main.c */
-extern const char Versionstr[];
-
-#endif /* _PROTO_SLURP */
+++ /dev/null
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 1998-2007 The OpenLDAP Foundation.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted only as authorized by the OpenLDAP
- * Public License.
- *
- * A copy of this license is available in file LICENSE in the
- * top-level directory of the distribution or, alternatively, at
- * <http://www.OpenLDAP.org/license.html>.
- */
-/* Portions Copyright (c) 1996 Regents of the University of Michigan.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that this notice is preserved and that due credit is given
- * to the University of Michigan at Ann Arbor. The name of the University
- * may not be used to endorse or promote products derived from this
- * software without specific prior written permission. This software
- * is provided ``as is'' without express or implied warranty.
- */
-/* ACKNOWLEDGEMENTS:
- * This work was originally developed by the University of Michigan
- * (as part of U-MICH LDAP).
- */
-
-/*
- * re.c - routines which deal with Re (Replication entry) structures.
- * An Re struct is an in-core representation of one replication to
- * be performed, along with member functions which are called by other
- * routines. The Re struct is defined in slurp.h.
- */
-
-
-#include "portable.h"
-
-#include <stdio.h>
-
-#include <ac/stdlib.h>
-#include <ac/errno.h>
-#include <ac/socket.h>
-#include <ac/string.h>
-#include <ac/ctype.h>
-
-#include "../slapd/slap.h"
-
-#include "slurp.h"
-#include "globals.h"
-#include "lutil.h"
-
-/* Forward references */
-static Rh *get_repl_hosts LDAP_P(( char *, int *, char ** ));
-static int gettype LDAP_P(( char * ));
-static int getchangetype LDAP_P(( char * ));
-static int Re_parse LDAP_P(( Re *re, char *replbuf ));
-static void Re_dump LDAP_P(( Re *re, FILE *fp ));
-static void warn_unknown_replica LDAP_P(( char *, int port ));
-
-/* Globals, scoped within this file */
-static int nur = 0; /* Number of unknown replicas */
-static Rh *ur = NULL; /* array of unknown replica names */
-
-
-/*
- * Return the next Re in a linked list.
- */
-static Re *
-Re_getnext(
- Re *re
-)
-{
- return(( re == NULL ) ? NULL : re->re_next );
-}
-
-
-
-
-/*
- * Free an Re
- * ??? Something should apparently return nonzero here, but I dont know what.
- */
-static int
-Re_free(
- Re *re
-)
-{
- Rh *rh;
- Mi *mi;
- int i;
-
- if ( re == NULL ) {
- return 0;
- }
- if ( re->re_refcnt > 0 ) {
- Debug( LDAP_DEBUG_ANY,
- "Warning: freeing re (dn: %s) with nonzero refcnt\n",
- re->re_dn, 0, 0 );
- }
-
- ldap_pvt_thread_mutex_destroy( &re->re_mutex );
-
- if (( rh = re->re_replicas ) != NULL ) {
- for ( i = 0; rh[ i ].rh_hostname != NULL; i++ ) {
- free( rh[ i ].rh_hostname );
- }
- free( rh );
- }
- ch_free( re->re_dn );
- if (( mi = re->re_mods ) != NULL ) {
- for ( i = 0; mi[ i ].mi_type != NULL; i++ ) {
- free( mi[ i ].mi_type );
- ch_free( mi[ i ].mi_val );
- }
- free( mi );
- }
- free( re );
- return 0;
-}
-
-
-
-
-/*
- * Read a buffer of data from a replication log file and fill in
- * an (already allocated) Re.
- */
-
-#define BEGIN 0
-#define GOT_DN 1
-#define GOT_TIME 2
-#define GOT_CHANGETYPE 4
-#define GOT_ALL ( GOT_DN | GOT_TIME | GOT_CHANGETYPE )
-
-static int
-Re_parse(
- Re *re,
- char *replbuf
-)
-{
- int state;
- int nml;
- char *buf, *rp, *p;
- size_t buflen;
- char *type, *value;
- ber_len_t len;
- int nreplicas;
-
- if ( re == NULL ) {
- Debug( LDAP_DEBUG_ANY, "Re_parse: error: re is NULL\n", 0, 0, 0 );
- return -1;
- }
- if ( replbuf == NULL ) {
- Debug( LDAP_DEBUG_ANY, "Re_parse: error: replbuf is NULL\n", 0, 0, 0 );
- return -1;
- }
-
- state = BEGIN;
- nml = 0; /* number of modification information entries */
- rp = replbuf;
-
- re->re_replicas = get_repl_hosts( replbuf, &nreplicas, &rp );
- re->re_refcnt = sglob->num_replicas;
-
- for (;;) {
- if (( state == GOT_ALL ) || ( buf = ldif_getline( &rp )) == NULL ) {
- break;
- }
- /*
- * If we're processing a rejection log, then the first line
- * of each replication record will begin with "ERROR" - just
- * ignore it.
- */
- if ( strncmp( buf, ERROR_STR, strlen( ERROR_STR )) == 0 ) {
- continue;
- }
- buflen = strlen( buf );
- if ( ldif_parse_line( buf, &type, &value, &len ) < 0 ) {
- Debug( LDAP_DEBUG_ANY,
- "Error: Re_parse: malformed replog file\n",
- 0, 0, 0 );
- return -1;
- }
- switch ( gettype( type )) {
- case T_CHANGETYPE:
- re->re_changetype = getchangetype( value );
- state |= GOT_CHANGETYPE;
- break;
- case T_TIME: {
- unsigned long t;
-
- if (( p = strchr( value, '.' )) != NULL ) {
- /* there was a sequence number */
- *p++ = '\0';
- }
- if ( lutil_atoul( &t, value ) != 0 ) {
- Debug( LDAP_DEBUG_ANY,
- "Error: Re_parse: unable to parse timestamp \"%s\"\n",
- value, 0, 0 );
- return -1;
- }
- re->re_timestamp = (time_t)t;
- if ( p != NULL && isdigit( (unsigned char) *p )
- && lutil_atoi( &re->re_seq, p ) != 0 )
- {
- Debug( LDAP_DEBUG_ANY,
- "Error: Re_parse: unable to parse sequence number \"%s\"\n",
- p, 0, 0 );
- return -1;
- }
- state |= GOT_TIME;
- } break;
- case T_DN:
- re->re_dn = ch_malloc( len + 1 );
- AC_MEMCPY( re->re_dn, value, len );
- re->re_dn[ len ]='\0';
- state |= GOT_DN;
- break;
- default:
- if ( !( state == GOT_ALL )) {
- Debug( LDAP_DEBUG_ANY,
- "Error: Re_parse: bad type <%s>\n",
- type, 0, 0 );
- free( type );
- free( value );
- return -1;
- }
- }
- free( type );
- free( value );
- }
-
- if ( state != GOT_ALL ) {
- Debug( LDAP_DEBUG_ANY,
- "Error: Re_parse: malformed replog file\n",
- 0, 0, 0 );
- return -1;
- }
-
- for (;;) {
- char *const dash = "-";
-
- if (( buf = ldif_getline( &rp )) == NULL ) {
- break;
- }
- buflen = strlen( buf );
- if (( buflen == 1 ) && ( buf[ 0 ] == '-' )) {
- type = dash;
- value = NULL;
- } else {
- if ( ldif_parse_line( buf, &type, &value, &len ) < 0 ) {
- Debug( LDAP_DEBUG_ANY,
- "Error: malformed replog line \"%s\"\n",
- buf, 0, 0 );
- return -1;
- }
- }
- re->re_mods = ( Mi *) ch_realloc( (char *) re->re_mods,
- sizeof( Mi ) * ( nml + 2 ));
- re->re_mods[ nml ].mi_type = strdup( type );
- if ( value != NULL ) {
- re->re_mods[ nml ].mi_val = ch_malloc( len + 1 );
- AC_MEMCPY( re->re_mods[ nml ].mi_val, value, len );
- re->re_mods[ nml ].mi_val[ len ] = '\0';
- re->re_mods[ nml ].mi_len = len;
- } else {
- re->re_mods[ nml ].mi_val = NULL;
- re->re_mods[ nml ].mi_len = 0;
- }
- re->re_mods[ nml + 1 ].mi_type = NULL;
- re->re_mods[ nml + 1 ].mi_val = NULL;
- nml++;
-
- if ( type != dash )
- free( type );
- if ( value != NULL )
- free( value );
- }
- return 0;
-}
-
-
-
-/*
- * Extract the replication hosts from a repl buf. Check to be sure that
- * each replica host and port number are ones we know about (that is, they're
- * in the slapd config file we read at startup). Without that information
- * from the config file, we won't have the appropriate credentials to
- * make modifications. If there are any unknown replica names, don't
- * add them the the Re struct. Instead, log a warning message.
- */
-static Rh *
-get_repl_hosts(
- char *replbuf,
- int *r_nreplicas,
- char **r_rp
-)
-{
- char *type, *value, *line, *p;
- Rh *rh = NULL;
- int nreplicas;
- ber_len_t len;
- int port;
- int repl_ok;
- int i;
-
- if ( replbuf == NULL ) {
- return( NULL );
- }
-
- nreplicas = 0;
-
- /*
- * Get the host names of the replicas
- */
- *r_nreplicas = 0;
- *r_rp = replbuf;
- for (;;) {
- /* If this is a reject log, we need to skip over the ERROR: line */
- if ( !strncmp( *r_rp, ERROR_STR, strlen( ERROR_STR ))) {
- line = ldif_getline( r_rp );
- if ( line == NULL ) {
- break;
- }
- }
- if ( strncasecmp( *r_rp, "replica:", 7 )) {
- break;
- }
- line = ldif_getline( r_rp );
- if ( line == NULL ) {
- break;
- }
- if ( ldif_parse_line( line, &type, &value, &len ) < 0 ) {
- return( NULL );
- }
- port = LDAP_PORT;
- if (( p = strchr( value, ':' )) != NULL ) {
- *p = '\0';
- p++;
- if ( *p != '\0' && lutil_atoi( &port, p ) != 0 ) {
- return( NULL );
- }
- }
-
- /* Verify that we've heard of this replica before */
- repl_ok = 0;
- for ( i = 0; i < sglob->num_replicas; i++ ) {
- if ( strcmp( sglob->replicas[ i ]->ri_hostname, value )) {
- continue;
- }
- if ( sglob->replicas[ i ]->ri_port == port ) {
- repl_ok = 1;
- break;
- }
- }
- free( type );
- if ( !repl_ok ) {
- warn_unknown_replica( value, port );
- free( value );
- continue;
- }
-
- rh = (Rh *) ch_realloc((char *) rh, ( nreplicas + 2 ) * sizeof( Rh ));
- if ( rh == NULL ) {
- Debug( LDAP_DEBUG_ANY, "Out of memory in get_repl_hosts\n",
- 0, 0, 0 );
- return NULL;
- }
- rh[ nreplicas ].rh_hostname = strdup( value );
- rh[ nreplicas ].rh_port = port;
- nreplicas++;
-
- free( value );
- }
-
- if ( nreplicas == 0 ) {
- return( NULL );
- }
-
- rh[ nreplicas ].rh_hostname = NULL;
- *r_nreplicas = nreplicas;
-
- return( rh );
-}
-
-
-
-
-
-/*
- * Convert "type" to an int.
- */
-static int
-gettype(
- char *type
-)
-{
- if ( !strcmp( type, T_CHANGETYPESTR )) {
- return( T_CHANGETYPE );
- }
- if ( !strcmp( type, T_TIMESTR )) {
- return( T_TIME );
- }
- if ( !strcmp( type, T_DNSTR )) {
- return( T_DN );
- }
- return( T_ERR );
-}
-
-
-
-/*
- * Convert "changetype" to an int.
- */
-static int
-getchangetype(
- char *changetype
-)
-{
- if ( !strcmp( changetype, T_ADDCTSTR )) {
- return( T_ADDCT );
- }
- if ( !strcmp( changetype, T_MODIFYCTSTR )) {
- return( T_MODIFYCT );
- }
- if ( !strcmp( changetype, T_DELETECTSTR )) {
- return( T_DELETECT );
- }
- if ( !strcmp( changetype, T_MODRDNCTSTR )) {
- return( T_MODRDNCT );
- }
- return( T_ERR );
-}
-
-
-
-
-#if 0
-/*
- * Find the first line which is not a "replica:" line in buf.
- * Returns a pointer to the line. Returns NULL if there are
- * only "replica:" lines in buf.
- */
-static char *
-skip_replica_lines(
- char *buf
-)
-{
- char *p = buf;
- for (;;) {
- if ( strncasecmp( p, "replica:", 8 )) {
- return( p );
- }
- while (( *p != '\0' ) && ( *p != '\n' )) {
- p++;
- }
- if ( *p == '\0' ) {
- return ( NULL );
- } else {
- p++;
- }
- }
-}
-#endif /* 0 */
-
-
-
-
-/*
- * For debugging purposes: dump the contents of a replication entry.
- * to the given stream.
- */
-static void
-Re_dump(
- Re *re,
- FILE *fp
-)
-{
- int i;
- Mi *mi;
-
- if ( re == NULL ) {
- Debug( LDAP_DEBUG_TRACE, "Re_dump: re is NULL\n", 0, 0, 0 );
- return;
- }
- fprintf( fp, "Re_dump: ******\n" );
- fprintf( fp, "re_refcnt: %d\n", re->re_refcnt );
- fprintf( fp, "re_timestamp: %ld\n", (long) re->re_timestamp );
- fprintf( fp, "re_seq: %d\n", re->re_seq );
- for ( i = 0; re->re_replicas && re->re_replicas[ i ].rh_hostname != NULL;
- i++ ) {
- fprintf( fp, "re_replicas[%d]: %s:%d\n",
- i, re->re_replicas[ i ].rh_hostname,
- re->re_replicas[ i ].rh_port );
- }
- fprintf( fp, "re_dn: %s\n", re->re_dn );
- switch ( re->re_changetype ) {
- case T_ADDCT:
- fprintf( fp, "re_changetype: add\n" );
- break;
- case T_MODIFYCT:
- fprintf( fp, "re_changetype: modify\n" );
- break;
- case T_DELETECT:
- fprintf( fp, "re_changetype: delete\n" );
- break;
- case T_MODRDNCT:
- fprintf( fp, "re_changetype: modrdn\n" );
- break;
- default:
- fprintf( fp, "re_changetype: (unknown, type = %d\n",
- re->re_changetype );
- }
- if ( re->re_mods == NULL ) {
- fprintf( fp, "re_mods: (none)\n" );
- } else {
- mi = re->re_mods;
- fprintf( fp, "re_mods:\n" );
- for ( i = 0; mi[ i ].mi_type != NULL; i++ ) {
- fprintf( fp, " %s, \"%s\", (%d bytes)\n",
- mi[ i ].mi_type,
- mi[ i ].mi_val == NULL ? "(null)" : mi[ i ].mi_val,
- mi[ i ].mi_len );
- }
- }
- return;
-}
-
-
-/*
- * Given an Ri, an Re, and a file pointer, write a replication record to
- * the file pointer. If ri is NULL, then include all replicas in the
- * output. If ri is non-NULL, then only include a single "replica:" line
- * (used when writing rejection records). Returns 0 on success, -1
- * on failure. Note that Re_write will not write anything out if the
- * refcnt is zero.
- */
-static int
-Re_write(
- Ri *ri,
- Re *re,
- FILE *fp )
-{
- int i;
- char *s;
- int rc = 0;
-
- if ( re == NULL || fp == NULL ) {
- Debug( LDAP_DEBUG_ANY, "Internal error: Re_write: NULL argument\n",
- 0, 0, 0 );
- return -1;
- }
-
- if ( re->re_refcnt < 1 ) {
- return 0; /* this is not an error */
- }
-
- if ( ri != NULL ) { /* write a single "replica:" line */
- if ( ri->ri_port != 0 ) {
- rc = fprintf( fp, "replica: %s:%d\n", ri->ri_hostname,
- ri->ri_port );
- } else {
- rc = fprintf( fp, "replica: %s\n", ri->ri_hostname );
- }
- if ( rc < 0 ) {
- rc = -1;
- goto bad;
- }
- rc = 0;
-
- } else { /* write multiple "replica:" lines */
- for ( i = 0; re->re_replicas && re->re_replicas[ i ].rh_hostname != NULL; i++ ) {
- if ( fprintf( fp, "replica: %s:%d\n",
- re->re_replicas[ i ].rh_hostname,
- re->re_replicas[ i ].rh_port ) < 0 ) {
- rc = -1;
- goto bad;
- }
- }
- }
- if ( fprintf( fp, "time: %ld.%d\n", (long) re->re_timestamp, re->re_seq ) < 0 ) {
- rc = -1;
- goto bad;
- }
- if ( fprintf( fp, "dn: %s\n", re->re_dn ) < 0 ) {
- rc = -1;
- goto bad;
- }
- if ( fprintf( fp, "changetype: " ) < 0 ) {
- rc = -1;
- goto bad;
- }
- switch ( re->re_changetype ) {
- case T_ADDCT:
- s = T_ADDCTSTR;
- break;
- case T_MODIFYCT:
- s = T_MODIFYCTSTR;
- break;
- case T_DELETECT:
- s = T_DELETECTSTR;
- break;
- case T_MODRDNCT:
- s = T_MODRDNCTSTR;
- break;
- default:
- s = "IllegalModifyType!!!";
- }
- if ( fprintf( fp, "%s\n", s ) < 0 ) {
- rc = -1;
- goto bad;
- }
- for ( i = 0; (( re->re_mods != NULL ) &&
- ( re->re_mods[ i ].mi_type != NULL )); i++ ) {
- if ( !strcmp( re->re_mods[ i ].mi_type, T_MODSEPSTR )) {
- if ( fprintf( fp, "%s\n", T_MODSEPSTR ) < 0 ) {
- rc = -1;
- goto bad;
- }
- } else {
- char *obuf;
- obuf = ldif_put( LDIF_PUT_VALUE,
- re->re_mods[ i ].mi_type,
- re->re_mods[ i ].mi_val ? re->re_mods[ i ].mi_val : "",
- re->re_mods[ i ].mi_len );
- if ( fputs( obuf, fp ) < 0 ) {
- rc = -1;
- free( obuf );
- goto bad;
- } else {
- ber_memfree( obuf );
- }
- }
- }
- if ( fprintf( fp, "\n" ) < 0 ) {
- rc = -1;
- goto bad;
- }
- if ( fflush( fp ) != 0 ) {
- rc = -1;
- goto bad;
- }
-bad:
- if ( rc != 0 ) {
- Debug( LDAP_DEBUG_ANY, "Error while writing: %s\n",
- sys_errlist[ errno ], 0, 0 );
- }
- return rc;
-}
-
-
-
-
-/*
- * Decrement the refcnt. Locking handled internally.
- */
-static int
-Re_decrefcnt(
- Re *re
-)
-{
- re->re_lock( re );
- re->re_refcnt--;
- re->re_unlock( re );
- return 0;
-}
-
-
-
-/*
- * Get the refcnt. Locking handled internally.
- */
-static int
-Re_getrefcnt(
- Re *re
-)
-{
- int ret;
-
- re->re_lock( re );
- ret = re->re_refcnt;
- re->re_unlock( re );
- return ret;
-}
-
-
-
-
-
-/*
- * Lock this replication entry
- */
-static int
-Re_lock(
- Re *re
-)
-{
- return( ldap_pvt_thread_mutex_lock( &re->re_mutex ));
-}
-
-
-
-
-/*
- * Unlock this replication entry
- */
-static int
-Re_unlock(
- Re *re
-)
-{
- return( ldap_pvt_thread_mutex_unlock( &re->re_mutex ));
-}
-
-
-
-
-/*
- * Instantiate and initialize an Re.
- */
-int
-Re_init(
- Re **re
-)
-{
- /* Instantiate */
- (*re) = (Re *) malloc( sizeof( Re ));
- if ( *re == NULL ) {
- return -1;
- }
-
- /* Fill in the member function pointers */
- (*re)->re_free = Re_free;
- (*re)->re_getnext = Re_getnext;
- (*re)->re_parse = Re_parse;
- (*re)->re_write = Re_write;
- (*re)->re_dump = Re_dump;
- (*re)->re_lock = Re_lock;
- (*re)->re_unlock = Re_unlock;
- (*re)->re_decrefcnt = Re_decrefcnt;
- (*re)->re_getrefcnt = Re_getrefcnt;
-
- /* Initialize private data */
- (*re)->re_refcnt = sglob->num_replicas;
- (*re)->re_timestamp = (time_t) 0L;
- (*re)->re_replicas = NULL;
- (*re)->re_dn = NULL;
- (*re)->re_changetype = 0;
- (*re)->re_seq = 0;
- (*re)->re_mods = NULL;
- (*re)->re_next = NULL;
-
- ldap_pvt_thread_mutex_init( &((*re)->re_mutex) );
- return 0;
-}
-
-
-
-
-/*
- * Given a host and port, generate a warning message iff we haven't already
- * generated a message for this host:port combination.
- */
-static void
-warn_unknown_replica(
- char *host,
- int port
-)
-{
- int found = 0;
- int i;
-
- for ( i = 0; i < nur; i++ ) {
- if ( strcmp( ur[ i ].rh_hostname, host )) {
- continue;
- }
- if ( ur[ i ].rh_port == port ) {
- found = 1;
- break;
- }
- }
- if ( !found ) {
- Debug( LDAP_DEBUG_ANY,
- "Warning: unknown replica %s:%d found in replication log\n",
- host, port, 0 );
- nur++;
- ur = (Rh *) ch_realloc( (char *) ur, ( nur * sizeof( Rh )));
- ur[ nur - 1 ].rh_hostname = strdup( host );
- ur[ nur - 1 ].rh_port = port;
- }
-}
+++ /dev/null
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 1998-2007 The OpenLDAP Foundation.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted only as authorized by the OpenLDAP
- * Public License.
- *
- * A copy of this license is available in file LICENSE in the
- * top-level directory of the distribution or, alternatively, at
- * <http://www.OpenLDAP.org/license.html>.
- */
-/* Portions Copyright (c) 1996 Regents of the University of Michigan.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that this notice is preserved and that due credit is given
- * to the University of Michigan at Ann Arbor. The name of the University
- * may not be used to endorse or promote products derived from this
- * software without specific prior written permission. This software
- * is provided ``as is'' without express or implied warranty.
- */
-/* ACKNOWLEDGEMENTS:
- * This work was originally developed by the University of Michigan
- * (as part of U-MICH LDAP).
- */
-
-
-/*
- * reject.c - routines to write replication records to reject files.
- * An Re struct is writted to a reject file if it cannot be propagated
- * to a replica LDAP server.
- */
-
-#include "portable.h"
-
-#include <stdio.h>
-
-#include <ac/stdlib.h>
-#include <ac/string.h>
-#include <ac/errno.h>
-#include <ac/unistd.h>
-
-#include <sys/stat.h>
-#include <fcntl.h>
-
-#include "slurp.h"
-#include "globals.h"
-
-#include "lber_pvt.h"
-#include "lutil.h"
-
-#ifdef _WIN32
-#define PORTSEP ","
-#else
-#define PORTSEP ":"
-#endif
-
-/*
- * Write a replication record to a reject file. The reject file has the
- * same name as the replica's private copy of the file but with ".rej"
- * appended (e.g. "/usr/tmp/<hostname>:<port>.rej")
- *
- * If errmsg is non-NULL, use that as the error message in the reject
- * file. Otherwise, use ldap_err2string( lderr ).
- */
-void
-write_reject(
- Ri *ri,
- Re *re,
- int lderr,
- char *errmsg
-)
-{
- char rejfile[ MAXPATHLEN ];
- FILE *rfp, *lfp;
- int rc;
-
- ldap_pvt_thread_mutex_lock( &sglob->rej_mutex );
- snprintf( rejfile, sizeof rejfile, "%s" LDAP_DIRSEP "%s" PORTSEP "%d.rej",
- sglob->slurpd_rdir, ri->ri_hostname, ri->ri_port );
-
- if ( access( rejfile, F_OK ) < 0 ) {
- /* Doesn't exist - try to create */
- int rjfd;
- if (( rjfd = open( rejfile, O_RDWR|O_APPEND|O_CREAT|O_EXCL,
- S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP )) < 0 ) {
- Debug( LDAP_DEBUG_ANY,
- "Error: write_reject: Cannot create \"%s\": %s\n",
- rejfile, sys_errlist[ errno ], 0 );
- ldap_pvt_thread_mutex_unlock( &sglob->rej_mutex );
- return;
- } else {
- close( rjfd );
- }
- }
- if (( rc = acquire_lock( rejfile, &rfp, &lfp )) < 0 ) {
- Debug( LDAP_DEBUG_ANY, "Error: cannot open reject file \"%s\"\n",
- rejfile, 0, 0 );
- } else {
- struct berval bv = BER_BVNULL,
- errstrbv,
- errmsgbv = BER_BVNULL;
- char *ptr;
-
- ber_str2bv( ldap_err2string( lderr ), 0, 0, &errstrbv );
- if ( errmsg && *errmsg ) {
- ber_str2bv( errmsg, 0, 0, &errmsgbv );
- bv.bv_len = errstrbv.bv_len
- + STRLENOF( ": " ) + errmsgbv.bv_len;
-
- ptr = bv.bv_val = ber_memalloc( bv.bv_len + 1 );
- ptr = lutil_strcopy( ptr, errstrbv.bv_val );
- ptr = lutil_strcopy( ptr, ": " );
- ptr = lutil_strcopy( ptr, errmsgbv.bv_val );
-
- } else {
- bv = errstrbv;
- }
-
- fseek( rfp, 0, 2 );
-
- ptr = ldif_put( LDIF_PUT_VALUE, ERROR_STR, bv.bv_val, bv.bv_len );
- if ( bv.bv_val != errstrbv.bv_val ) {
- ber_memfree( bv.bv_val );
- }
- if ( ptr == NULL ) {
- Debug( LDAP_DEBUG_ANY,
- "Error: cannot convert error message(s) \"%s%s%s\" "
- "into LDIF format\n",
- errstrbv.bv_val,
- BER_BVISNULL( &errmsgbv ) ? "" : ": ",
- BER_BVISNULL( &errmsgbv ) ? "" : errmsgbv.bv_val );
- return;
- }
-
- fputs( ptr, rfp );
- ber_memfree( ptr );
-
- if ((rc = re->re_write( ri, re, rfp )) < 0 ) {
- Debug( LDAP_DEBUG_ANY,
- "Error: cannot write reject file \"%s\"\n",
- rejfile, 0, 0 );
- }
- (void) relinquish_lock( rejfile, rfp, lfp );
- Debug( LDAP_DEBUG_ANY,
- "Error: ldap operation failed, data written to \"%s\"\n",
- rejfile, 0, 0 );
- }
- ldap_pvt_thread_mutex_unlock( &sglob->rej_mutex );
- return;
-}
-
+++ /dev/null
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 1998-2007 The OpenLDAP Foundation.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted only as authorized by the OpenLDAP
- * Public License.
- *
- * A copy of this license is available in file LICENSE in the
- * top-level directory of the distribution or, alternatively, at
- * <http://www.OpenLDAP.org/license.html>.
- */
-/* Portions Copyright (c) 1996 Regents of the University of Michigan.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that this notice is preserved and that due credit is given
- * to the University of Michigan at Ann Arbor. The name of the University
- * may not be used to endorse or promote products derived from this
- * software without specific prior written permission. This software
- * is provided ``as is'' without express or implied warranty.
- */
-/* ACKNOWLEDGEMENTS:
- * This work was originally developed by the University of Michigan
- * (as part of U-MICH LDAP).
- */
-
-
-/*
- * replica.c - code to start up replica threads.
- */
-
-#include "portable.h"
-
-#include <stdio.h>
-#include <ac/stdlib.h>
-
-#include "slurp.h"
-#include "globals.h"
-
-/*
- * Just invoke the Ri's process() member function, and log the start and
- * finish.
- */
-static void *
-replicate(
- void *ri_arg
-)
-{
- Ri *ri = (Ri *) ri_arg;
-
- Debug( LDAP_DEBUG_ARGS, "begin replication thread for %s:%d\n",
- ri->ri_hostname, ri->ri_port, 0 );
-
- ri->ri_process( ri );
-
- Debug( LDAP_DEBUG_ARGS, "end replication thread for %s:%d\n",
- ri->ri_hostname, ri->ri_port, 0 );
- return NULL;
-}
-
-
-
-/*
- * Start a detached thread for the given replica.
- */
-int
-start_replica_thread(
- Ri *ri
-)
-{
- /* POSIX_THREADS or compatible */
- if ( ldap_pvt_thread_create( &(ri->ri_tid), 0, replicate,
- (void *) ri ) != 0 ) {
- Debug( LDAP_DEBUG_ANY, "replica \"%s:%d\" ldap_pvt_thread_create failed\n",
- ri->ri_hostname, ri->ri_port, 0 );
- return -1;
- }
-
- return 0;
-}
+++ /dev/null
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 1998-2007 The OpenLDAP Foundation.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted only as authorized by the OpenLDAP
- * Public License.
- *
- * A copy of this license is available in file LICENSE in the
- * top-level directory of the distribution or, alternatively, at
- * <http://www.OpenLDAP.org/license.html>.
- */
-/* Portions Copyright (c) 1996 Regents of the University of Michigan.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that this notice is preserved and that due credit is given
- * to the University of Michigan at Ann Arbor. The name of the University
- * may not be used to endorse or promote products derived from this
- * software without specific prior written permission. This software
- * is provided ``as is'' without express or implied warranty.
- */
-/* ACKNOWLEDGEMENTS:
- * This work was originally developed by the University of Michigan
- * (as part of U-MICH LDAP).
- */
-
-
-/*
- * replog.c - routines which read and write replication log files.
- */
-
-#include "portable.h"
-
-#include <stdio.h>
-
-#include <ac/stdlib.h>
-#include <ac/errno.h>
-#include <ac/param.h>
-#include <ac/string.h>
-#include <ac/syslog.h>
-#include <ac/time.h>
-#include <ac/unistd.h>
-
-#include <sys/stat.h>
-
-#include <fcntl.h>
-
-#include "slurp.h"
-#include "globals.h"
-
-/*
- * Copy the replication log. Returns 0 on success, 1 if a temporary
- * error occurs, and -1 if a fatal error occurs.
- */
-int
-copy_replog(
- char *src,
- char *dst
-)
-{
- int rc = 0;
- FILE *rfp; /* replog fp */
- FILE *lfp; /* replog lockfile fp */
- FILE *dfp; /* duplicate replog fp */
- FILE *dlfp; /* duplicate replog lockfile fp */
- static char buf[ MAXPATHLEN ];
- static char rbuf[ 1024 ];
- char *p;
-
- Debug( LDAP_DEBUG_ARGS,
- "copy replog \"%s\" to \"%s\"\n",
- src, dst, 0 );
-
- /*
- * Make sure the destination directory is writable. If not, exit
- * with a fatal error.
- */
- strcpy( buf, src );
- if (( p = strrchr( buf, LDAP_DIRSEP[0] )) == NULL ) {
- strcpy( buf, "." );
- } else {
- *p = '\0';
- }
- if ( access( buf, W_OK ) < 0 ) {
- Debug( LDAP_DEBUG_ANY,
- "Error: copy_replog (%ld): Directory %s is not writable\n",
- (long) getpid(), buf, 0 );
- return( -1 );
- }
- strcpy( buf, dst );
- if (( p = strrchr( buf, LDAP_DIRSEP[0] )) == NULL ) {
- strcpy( buf, "." );
- } else {
- *p = '\0';
- }
- if ( access( buf, W_OK ) < 0 ) {
- Debug( LDAP_DEBUG_ANY,
- "Error: copy_replog (%ld): Directory %s is not writable\n",
- (long) getpid(), buf, 0 );
- return( -1 );
- }
-
- /* lock src */
- rfp = lock_fopen( src, "r", &lfp );
- if ( rfp == NULL ) {
- Debug( LDAP_DEBUG_ANY,
- "Error: copy_replog: Can't lock replog \"%s\" for read: %s\n",
- src, sys_errlist[ errno ], 0 );
- return( 1 );
- }
-
- /* lock dst */
- dfp = lock_fopen( dst, "a", &dlfp );
- if ( dfp == NULL ) {
- Debug( LDAP_DEBUG_ANY,
- "Error: copy_replog: Can't lock replog \"%s\" for write: %s\n",
- dst, sys_errlist[ errno ], 0 );
- lock_fclose( rfp, lfp );
- return( 1 );
- }
-
- /*
- * Make our own private copy of the replication log.
- */
- while (( p = fgets( rbuf, sizeof( rbuf ), rfp )) != NULL ) {
- fputs( rbuf, dfp );
- }
- /* Only truncate the source file if we're not in one-shot mode */
- if ( !sglob->one_shot_mode ) {
- /* truncate replication log */
- truncate( src, (off_t) 0 );
- }
-
- if ( lock_fclose( dfp, dlfp ) == EOF ) {
- Debug( LDAP_DEBUG_ANY,
- "Error: copy_replog: Error closing \"%s\"\n",
- dst, 0, 0 );
- }
- if ( lock_fclose( rfp, lfp ) == EOF ) {
- Debug( LDAP_DEBUG_ANY,
- "Error: copy_replog: Error closing \"%s\"\n",
- src, 0, 0 );
- }
- return( rc );
-}
-
-
-
-
-/*
- * Return 1 if the given file exists and has a nonzero size,
- * 0 if it is empty or nonexistent.
- */
-int
-file_nonempty(
- char *filename
-)
-{
- static struct stat stbuf;
-
- if ( stat( filename, &stbuf ) < 0 ) {
- return( 0 );
- } else {
- return( stbuf.st_size > (off_t ) 0 );
- }
-}
+++ /dev/null
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 1998-2007 The OpenLDAP Foundation.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted only as authorized by the OpenLDAP
- * Public License.
- *
- * A copy of this license is available in file LICENSE in the
- * top-level directory of the distribution or, alternatively, at
- * <http://www.OpenLDAP.org/license.html>.
- */
-/* Portions Copyright (c) 1996 Regents of the University of Michigan.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that this notice is preserved and that due credit is given
- * to the University of Michigan at Ann Arbor. The name of the University
- * may not be used to endorse or promote products derived from this
- * software without specific prior written permission. This software
- * is provided ``as is'' without express or implied warranty.
- */
-/* ACKNOWLEDGEMENTS:
- * This work was originally developed by the University of Michigan
- * (as part of U-MICH LDAP).
- */
-
-/*
- * ri.c - routines used to manipulate Ri structures. An Ri (Replica
- * information) struct contains all information about one replica
- * instance. The Ri struct is defined in slurp.h
- */
-
-
-#include "portable.h"
-
-#include <stdio.h>
-
-#include <ac/stdlib.h>
-#include <ac/string.h>
-#include <ac/signal.h>
-
-#include "slurp.h"
-#include "globals.h"
-
-
-/* Forward references */
-static int ismine LDAP_P(( Ri *, Re * ));
-static int isnew LDAP_P(( Ri *, Re * ));
-
-
-/*
- * Process any unhandled replication entries in the queue.
- */
-static int
-Ri_process(
- Ri *ri
-)
-{
- Rq *rq = sglob->rq;
- Re *re = NULL, *new_re = NULL;
- int rc ;
- char *errmsg;
- int errfree;
-
- (void) SIGNAL( LDAP_SIGUSR1, do_nothing );
-#ifdef SIGPIPE
- (void) SIGNAL( SIGPIPE, SIG_IGN );
-#endif
- if ( ri == NULL ) {
- Debug( LDAP_DEBUG_ANY, "Error: Ri_process: ri == NULL!\n", 0, 0, 0 );
- return -1;
- }
-
- /*
- * Startup code. See if there's any work to do. If not, wait on the
- * rq->rq_more condition variable.
- */
- rq->rq_lock( rq );
- while ( !sglob->slurpd_shutdown &&
- (( re = rq->rq_gethead( rq )) == NULL )) {
- /* No work */
- if ( sglob->one_shot_mode ) {
- /* give up if in one shot mode */
- rq->rq_unlock( rq );
- return 0;
- }
- /* wait on condition variable */
- ldap_pvt_thread_cond_wait( &rq->rq_more, &rq->rq_mutex );
- }
-
- /*
- * When we get here, there's work in the queue, and we have the
- * queue locked. re should be pointing to the head of the queue.
- */
- rq->rq_unlock( rq );
- while ( !sglob->slurpd_shutdown ) {
- if ( re != NULL ) {
- if ( !ismine( ri, re )) {
- /* The Re doesn't list my host:port */
- Debug( LDAP_DEBUG_TRACE,
- "Replica %s:%d, skip repl record for %s (not mine)\n",
- ri->ri_hostname, ri->ri_port, re->re_dn );
- } else if ( !isnew( ri, re )) {
- /* This Re is older than my saved status information */
- Debug( LDAP_DEBUG_TRACE,
- "Replica %s:%d, skip repl record for %s (old)\n",
- ri->ri_hostname, ri->ri_port, re->re_dn );
- } else {
- rc = do_ldap( ri, re, &errmsg, &errfree );
- switch ( rc ) {
- case DO_LDAP_ERR_RETRYABLE:
- ldap_pvt_thread_sleep( RETRY_SLEEP_TIME );
- Debug( LDAP_DEBUG_ANY,
- "Retrying operation for DN %s on replica %s:%d\n",
- re->re_dn, ri->ri_hostname, ri->ri_port );
- continue;
- break;
- case DO_LDAP_ERR_FATAL: {
- /* Non-retryable error. Write rejection log. */
- int ld_errno = 0;
- ldap_get_option(ri->ri_ldp, LDAP_OPT_RESULT_CODE, &ld_errno);
- write_reject( ri, re, ld_errno, errmsg );
- /* Update status ... */
- (void) sglob->st->st_update( sglob->st, ri->ri_stel, re );
- /* ... and write to disk */
- (void) sglob->st->st_write( sglob->st );
- } break;
- default:
- /* LDAP op completed ok - update status... */
- (void) sglob->st->st_update( sglob->st, ri->ri_stel, re );
- /* ... and write to disk */
- (void) sglob->st->st_write( sglob->st );
- break;
- }
- if ( errfree && errmsg ) {
- ch_free( errmsg );
- }
- }
- } else {
- Debug( LDAP_DEBUG_ANY, "Error: re is null in Ri_process\n",
- 0, 0, 0 );
- }
- rq->rq_lock( rq );
- while ( !sglob->slurpd_shutdown &&
- ((new_re = re->re_getnext( re )) == NULL )) {
- if ( sglob->one_shot_mode ) {
- rq->rq_unlock( rq );
- return 0;
- }
- /* No work - wait on condition variable */
- ldap_pvt_thread_cond_wait( &rq->rq_more, &rq->rq_mutex );
- }
- re->re_decrefcnt( re );
- re = new_re;
- rq->rq_unlock( rq );
- if ( sglob->slurpd_shutdown ) {
- if ( ri->ri_ldp ) {
- ldap_unbind_ext( ri->ri_ldp, NULL, NULL );
- ri->ri_ldp = NULL;
- }
- return 0;
- }
- }
- return 0;
-}
-
-
-/*
- * Wake a replication thread which may be sleeping.
- * Send it a LDAP_SIGUSR1.
- */
-static void
-Ri_wake(
- Ri *ri
-)
-{
- if ( ri == NULL ) {
- return;
- }
- ldap_pvt_thread_kill( ri->ri_tid, LDAP_SIGUSR1 );
-}
-
-
-
-/*
- * Allocate and initialize an Ri struct.
- */
-int
-Ri_init(
- Ri **ri
-)
-{
- (*ri) = ( Ri * ) calloc( 1, sizeof( Ri ));
- if ( *ri == NULL ) {
- return -1;
- }
-
- /* Initialize member functions */
- (*ri)->ri_process = Ri_process;
- (*ri)->ri_wake = Ri_wake;
-
- /* Initialize private data */
- (*ri)->ri_hostname = NULL;
- (*ri)->ri_uri = NULL;
- (*ri)->ri_ldp = NULL;
- (*ri)->ri_bind_dn = NULL;
- (*ri)->ri_password = NULL;
- (*ri)->ri_authcId = NULL;
- (*ri)->ri_curr = NULL;
-
- return 0;
-}
-
-
-
-
-/*
- * Return 1 if the hostname and port in re match the hostname and port
- * in ri, otherwise return zero.
- */
-static int
-ismine(
- Ri *ri,
- Re *re
-)
-{
- Rh *rh;
- int i;
-
- if ( ri == NULL || re == NULL || ri->ri_hostname == NULL ||
- re->re_replicas == NULL ) {
- return 0;
- }
- rh = re->re_replicas;
- for ( i = 0; rh[ i ].rh_hostname != NULL; i++ ) {
- if ( !strcmp( rh[ i ].rh_hostname, ri->ri_hostname) &&
- rh[ i ].rh_port == ri->ri_port ) {
- return 1;
- }
- }
- return 0;
-}
-
-
-
-
-/*
- * Return 1 if the Re's timestamp/seq combination are greater than the
- * timestamp and seq in the Ri's ri_stel member. In other words, if we
- * find replication entries in the log which we've already processed,
- * don't process them. If the re is "old," return 0.
- * No check for NULL pointers is done.
- */
-static int
-isnew(
- Ri *ri,
- Re *re
-)
-{
- long x;
- int ret;
-
- /* Lock the St struct to avoid a race */
- sglob->st->st_lock( sglob->st );
- x = re->re_timestamp - ri->ri_stel->last;
- if ( x > 0 ) {
- /* re timestamp is newer */
- ret = 1;
- } else if ( x < 0 ) {
- ret = 0;
- } else {
- /* timestamps were equal */
- if ( re->re_seq > ri->ri_stel->seq ) {
- /* re seq is newer */
- ret = 1;
- } else {
- ret = 0;
- }
- }
- sglob->st->st_unlock( sglob->st );
- return ret;
-}
+++ /dev/null
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 1998-2007 The OpenLDAP Foundation.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted only as authorized by the OpenLDAP
- * Public License.
- *
- * A copy of this license is available in file LICENSE in the
- * top-level directory of the distribution or, alternatively, at
- * <http://www.OpenLDAP.org/license.html>.
- */
-/* Portions Copyright (c) 1996 Regents of the University of Michigan.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that this notice is preserved and that due credit is given
- * to the University of Michigan at Ann Arbor. The name of the University
- * may not be used to endorse or promote products derived from this
- * software without specific prior written permission. This software
- * is provided ``as is'' without express or implied warranty.
- */
-/* ACKNOWLEDGEMENTS:
- * This work was originally developed by the University of Michigan
- * (as part of U-MICH LDAP).
- */
-
-/*
- * rq.c - routines used to manage the queue of replication entries.
- * An Rq (Replication queue) struct contains a linked list of Re
- * (Replication entry) structures.
- *
- * Routines wishing to access the replication queue should do so through
- * the Rq struct's member functions, e.g. rq->rq_gethead() and friends.
- * For example, Re structs should be added to the queue by calling
- * the rq_add() member function.
- *
- * Access to the queue is serialized by a mutex. Member functions which do
- * not do their own locking should only be called after locking the queue
- * using the rq_lock() member function. The queue should be unlocked with
- * the rq_unlock() member function.
- *
- * Note that some member functions handle their own locking internally.
- * Callers should not lock the queue before calling these functions.
- * See the comment block for each function below.
- *
- */
-
-#include "portable.h"
-
-#include <stdio.h>
-#include <sys/stat.h>
-
-#include <ac/stdlib.h>
-#include <ac/string.h>
-#include <ac/unistd.h> /* get ftruncate() */
-
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-#ifdef HAVE_FCNTL_H
-#include <fcntl.h>
-#endif
-
-#include "slurp.h"
-#include "globals.h"
-
-/*
- * Lock the replication queue.
- */
-static int
-Rq_lock(
- Rq *rq
-)
-{
- return( ldap_pvt_thread_mutex_lock( &rq->rq_mutex ));
-}
-
-
-/*
- * Unlock the replication queue.
- */
-static int
-Rq_unlock(
- Rq *rq
-)
-{
- return( ldap_pvt_thread_mutex_unlock( &rq->rq_mutex ));
-}
-
-
-
-/*
- * Return the head of the queue. Callers should lock the queue before
- * calling this routine.
- */
-static Re *
-Rq_gethead(
- Rq *rq
-)
-{
- return( rq == NULL ? NULL : rq->rq_head );
-}
-
-
-/*
- * Return the next item in the queue. Callers should lock the queue before
- * calling this routine.
- */
-static Re *
-Rq_getnext(
- Re *re
-)
-{
- if ( re == NULL ) {
- return NULL;
- } else {
- return( re->re_getnext( re ));
- }
-}
-
-
-/*
- * Delete the item at the head of the list. The queue should be locked
- * by the caller before calling this routine.
- */
-static int
-Rq_delhead(
- Rq *rq
-)
-{
- Re *savedhead;
- int rc;
-
- if ( rq == NULL ) {
- return( -1 );
- }
-
- savedhead = rq->rq_head;
- if ( savedhead == NULL ) {
- return( 0 );
- }
-
- if ( savedhead->re_getrefcnt( savedhead ) != 0 ) {
- Debug( LDAP_DEBUG_ANY, "Warning: attempt to delete when refcnt != 0\n",
- 0, 0, 0 );
- return( -1 );
- }
-
- rq->rq_head = rq->rq_head->re_getnext( rq->rq_head );
- rc = savedhead->re_free( savedhead );
- rq->rq_nre--; /* decrement count of Re's in queue */
- return( rc );
-}
-
-
-/*
- * Add an entry to the tail of the replication queue. Locking is handled
- * internally. When items are added to the queue, this routine wakes
- * up any threads which are waiting for more work by signaling on the
- * rq->rq_more condition variable.
- */
-static int
-Rq_add(
- Rq *rq,
- char *buf
-)
-{
- Re *re;
- int wasempty = 0;
-
- /* Lock the queue */
- rq->rq_lock( rq );
-
- /* Create a new Re */
- if ( Re_init( &re ) < 0 ) {
- rq->rq_unlock( rq );
- return -1;
- }
-
- /* parse buf and fill in the re struct */
- if ( re->re_parse( re, buf ) < 0 ) {
- re->re_free( re );
- rq->rq_unlock( rq );
- return -1;
- }
-
- /* Insert into queue */
- if ( rq->rq_head == NULL ) {
- rq->rq_head = re;
- rq->rq_tail = re;
- wasempty = 1;
- } else {
- rq->rq_tail->re_next = re;
- }
-
- /* set the sequence number */
- re->re_seq = 0;
- if ( !wasempty && ( rq->rq_tail->re_timestamp == re->re_timestamp )) {
- /*
- * Our new re has the same timestamp as the tail's timestamp.
- * Increment the seq number in the tail and use it as our seq number.
- */
- re->re_seq = rq->rq_tail->re_seq + 1;
- }
- rq->rq_tail = re;
-
- /* Increment count of items in queue */
- rq->rq_nre++;
- /* wake up any threads waiting for more work */
- ldap_pvt_thread_cond_broadcast( &rq->rq_more );
-
- /* ... and unlock the queue */
- rq->rq_unlock( rq );
-
- return 0;
-}
-
-
-/*
- * Garbage-collect the replication queue. Locking is handled internally.
- */
-static void
-Rq_gc(
- Rq *rq
-)
-{
- if ( rq == NULL ) {
- Debug( LDAP_DEBUG_ANY, "Rq_gc: rq is NULL!\n", 0, 0, 0 );
- return;
- }
- rq->rq_lock( rq );
- while (( rq->rq_head != NULL ) &&
- ( rq->rq_head->re_getrefcnt( rq->rq_head ) == 0 )) {
- rq->rq_delhead( rq );
- rq->rq_ndel++; /* increment count of deleted entries */
- }
- rq->rq_unlock( rq );
- return;
-}
-
-
-/*
- * For debugging: dump the contents of the replication queue to a file.
- * Locking is handled internally.
- */
-static void
-Rq_dump(
- Rq *rq
-)
-{
- Re *re;
- FILE *fp;
- int tmpfd;
-
- if ( rq == NULL ) {
- Debug( LDAP_DEBUG_ANY, "Rq_dump: rq is NULL!\n", 0, 0, 0 );
- return;
- }
-
- if (unlink(SLURPD_DUMPFILE) == -1 && errno != ENOENT) {
- Debug( LDAP_DEBUG_ANY, "Rq_dump: \"%s\" exists, and cannot unlink\n",
- SLURPD_DUMPFILE, 0, 0 );
- return;
- }
- if (( tmpfd = open(SLURPD_DUMPFILE, O_CREAT|O_RDWR|O_EXCL, 0600)) == -1) {
- Debug( LDAP_DEBUG_ANY, "Rq_dump: cannot open \"%s\" for write\n",
- SLURPD_DUMPFILE, 0, 0 );
- return;
- }
- if (( fp = fdopen( tmpfd, "w" )) == NULL ) {
- Debug( LDAP_DEBUG_ANY, "Rq_dump: cannot fdopen \"%s\" for write\n",
- SLURPD_DUMPFILE, 0, 0 );
- return;
- }
-
- rq->rq_lock( rq );
- for ( re = rq->rq_gethead( rq ); re != NULL; re = rq->rq_getnext( re )) {
- re->re_dump( re, fp );
- }
- rq->rq_unlock( rq );
- fclose( fp );
- return;
-}
-
-
-/*
- * Write the contents of a replication queue to a file. Returns zero if
- * successful, -1 if not. Handles queue locking internally. Callers should
- * provide an open file pointer, which should refer to a locked file.
- */
-static int
-Rq_write(
- Rq *rq,
- FILE *fp
-)
-{
- Re *re;
- time_t now;
-
- if ( rq == NULL ) {
- return -1;
- }
-
- Debug( LDAP_DEBUG_ARGS, "re-write on-disk replication log\n",
- 0, 0, 0 );
-#ifndef SEEK_SET
-#define SEEK_SET 0
-#endif
- fseek( fp, 0L, SEEK_SET ); /* Go to beginning of file */
- rq->rq_lock( rq );
-
- for ( re = rq->rq_gethead( rq ); re != NULL; re = rq->rq_getnext( re )) {
- if ( re->re_write( NULL, re, fp ) < 0 ) {
- fflush( fp );
- rq->rq_unlock( rq );
- return -1;
- }
- }
- fflush( fp );
- sglob->srpos = ftell( fp ); /* update replog file position */
- /* and truncate to correct len */
- if ( ftruncate( fileno( fp ), sglob->srpos ) < 0 ) {
- Debug( LDAP_DEBUG_ANY, "Error truncating replication log: %s\n",
- sys_errlist[ errno ], 0, 0 );
- }
- rq->rq_ndel = 0; /* reset count of deleted re's */
- time( &now );
- rq->rq_lasttrim = now; /* reset last trim time */
- rq->rq_unlock( rq );
- return 0;
-}
-
-
-/*
- * Check to see if the private slurpd replication log needs trimming.
- * The current criteria are:
- * - The last trim was more than 5 minutes ago, *and*
- * - We've finished with at least 50 replication log entries since the
- * last time we re-wrote the replication log.
- *
- * Return 1 if replogfile should be trimmed, 0 if not.
- * Any different policy should be implemented by replacing this function.
- */
-static int
-Rq_needtrim(
- Rq *rq
-)
-{
- int rc = 0;
- time_t now;
-
- if ( rq == NULL ) {
- return 0;
- }
-
- rq->rq_lock( rq );
-
- time( &now );
-
- if ( now > ( rq->rq_lasttrim + TRIMCHECK_INTERVAL )) {
- rc = ( rq->rq_ndel >= 50 );
- } else {
- rc = 0;
- }
- rq->rq_unlock( rq );
- return rc;
-}
-
-
-/*
- * Return counts of Re structs in the queue.
- */
-static int
-Rq_getcount(
- Rq *rq,
- int type
-)
-{
- int count = 0;
- Re *re;
-
- if ( rq == NULL ) {
- return 0;
- }
-
- rq->rq_lock( rq );
- if ( type == RQ_COUNT_ALL ) {
- count = rq->rq_nre;
- } else {
- for ( re = rq->rq_gethead( rq ); re != NULL;
- re = rq->rq_getnext( re )) {
- if ( type == RQ_COUNT_NZRC ) {
- if ( re->re_getrefcnt( re ) > 0 ) {
- count++;
- }
- }
- }
- }
- rq->rq_unlock( rq );
- return count;
-}
-
-
-/*
- * Allocate and initialize an Rq object.
- */
-int
-Rq_init(
- Rq **rq
-)
-{
- /* Instantiate the struct */
- (*rq) = (Rq *) malloc( sizeof( Rq ));
- if ( *rq == NULL ) {
- return -1;
- }
-
- /* Fill in all the function pointers */
- (*rq)->rq_gethead = Rq_gethead;
- (*rq)->rq_getnext = Rq_getnext;
- (*rq)->rq_delhead = Rq_delhead;
- (*rq)->rq_add = Rq_add;
- (*rq)->rq_gc = Rq_gc;
- (*rq)->rq_lock = Rq_lock;
- (*rq)->rq_unlock = Rq_unlock;
- (*rq)->rq_dump = Rq_dump;
- (*rq)->rq_needtrim = Rq_needtrim;
- (*rq)->rq_write = Rq_write;
- (*rq)->rq_getcount = Rq_getcount;
-
- /* Initialize private data */
- ldap_pvt_thread_mutex_init( &((*rq)->rq_mutex) );
- ldap_pvt_thread_cond_init( &((*rq)->rq_more) );
- (*rq)->rq_head = NULL;
- (*rq)->rq_tail = NULL;
- (*rq)->rq_nre = 0;
- (*rq)->rq_ndel = 0;
- (*rq)->rq_lasttrim = (time_t) 0L;
-
- return 0;
-}
+++ /dev/null
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 1998-2007 The OpenLDAP Foundation.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted only as authorized by the OpenLDAP
- * Public License.
- *
- * A copy of this license is available in file LICENSE in the
- * top-level directory of the distribution or, alternatively, at
- * <http://www.OpenLDAP.org/license.html>.
- */
-/* Portions Copyright (c) 1996 Regents of the University of Michigan.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that this notice is preserved and that due credit is given
- * to the University of Michigan at Ann Arbor. The name of the University
- * may not be used to endorse or promote products derived from this
- * software without specific prior written permission. This software
- * is provided ``as is'' without express or implied warranty.
- */
-/* ACKNOWLEDGEMENTS:
- * This work was originally developed by the University of Michigan
- * (as part of U-MICH LDAP).
- */
-
-
-/*
- * sanity.c - perform sanity checks on the environment at startup time,
- * and report any errors before we disassociate from the controlling tty,
- * start up our threads, and do other stuff which makes it hard to give
- * feedback to the users.
- */
-
-#include "portable.h"
-
-#include <stdio.h>
-
-#include <ac/stdlib.h>
-#include <ac/unistd.h>
-#include <ac/string.h>
-
-#include "slurp.h"
-#include "globals.h"
-
-#define FC_DIRBAD 1
-#define FC_DIRUNREAD 2
-#define FC_DIRUNWRITE 4
-#define FC_FILEBAD 8
-#define FC_FILEUNREAD 16
-#define FC_FILEUNWRITE 32
-
-
-/*
- * Forward declarations
- */
-static unsigned int filecheck LDAP_P(( char * ));
-
-
-
-/*
- * Take a look around to catch any fatal errors. For example, make sure the
- * destination directory for our working files exists, check that all
- * pathnames make sense, and so on. Returns 0 is everything's ok,
- # -1 if there's something wrong which will keep us from functioning
- * correctly.
- *
- * We do all these checks at startup so we can print a reasonable error
- * message on stderr before we disassociate from the controlling tty. This
- * keeps some fatal error messages from "disappearing" into syslog.
- */
-
-int
-sanity( void )
-{
- int err = 0;
- int rc;
-
- /*
- * Are there any replicas listed in the slapd config file?
- */
- if ( sglob->replicas == NULL ) {
- fprintf( stderr, "No replicas in slapd.conf file \"%s\"!\n",
- sglob->slapd_configfile );
- err++;
- }
-
- /*
- * Make sure the directory housing the slapd replogfile exists, and
- * that the slapd replogfile is readable, if it exists.
- */
- if ( sglob->slapd_replogfile == NULL ) {
- fprintf( stderr, "Fatal error: no \"replogfile\" "
- "slapd.conf directive given\n" );
- err++;
- } else {
- rc = filecheck( sglob->slapd_replogfile );
- if ( rc & FC_DIRBAD ) {
- fprintf( stderr, "Error: %s: directory specified in "
- "\"replogfile\" slapd.conf directive does not exist\n",
- sglob->slapd_replogfile );
- err++;
- } else if ( rc & FC_DIRUNREAD ) {
- fprintf( stderr, "Error: %s: directory specified in "
- "\"replogfile\" slapd.conf directive is not readable\n",
- sglob->slapd_replogfile );
- err++;
- } else if (!( rc & FC_FILEBAD) && ( rc & FC_FILEUNREAD )) {
- fprintf( stderr, "Error: %s: file specified in "
- "\"replogfile\" slapd.conf directive is not readable\n",
- sglob->slapd_replogfile );
- err++;
- }
- }
-
- /*
- * Make sure the directory for the slurpd replogfile is there, and
- * that the slurpd replogfile is readable and writable, if it exists.
- */
- if ( sglob->slurpd_replogfile == NULL ) {
- fprintf( stderr, "Fatal error: no \"replogfile\" directive given\n" );
- err++;
- } else {
- rc = filecheck( sglob->slurpd_replogfile );
- if ( rc & FC_DIRBAD ) {
- fprintf( stderr, "Error: %s: slurpd \"replogfile\" "
- "directory does not exist\n",
- sglob->slurpd_replogfile );
- err++;
- } else if ( rc & FC_DIRUNREAD ) {
- fprintf( stderr, "Error: %s: slurpd \"replogfile\" "
- "directory not readable\n",
- sglob->slurpd_replogfile );
- err++;
- } else if ( !( rc & FC_FILEBAD ) && ( rc & FC_FILEUNREAD )) {
- fprintf( stderr, "Error: %s: slurpd \"replogfile\" not readable\n",
- sglob->slurpd_replogfile );
- err++;
- } else if ( !( rc & FC_FILEBAD ) && ( rc & FC_FILEUNWRITE )) {
- fprintf( stderr, "Error: %s: slurpd \"replogfile\" not writeable\n",
- sglob->slurpd_replogfile );
- err++;
- }
- }
-
- /*
- * Make sure that the directory for the slurpd status file is there, and
- * that the slurpd status file is writable, if it exists.
- */
- rc = filecheck( sglob->slurpd_status_file );
- if ( rc & FC_DIRBAD ) {
- fprintf( stderr, "Error: %s: status directory does not exist\n",
- sglob->slurpd_status_file );
- err++;
- } else if ( rc & FC_DIRUNREAD ) {
- fprintf( stderr, "Error: %s: status directory not readable\n",
- sglob->slurpd_status_file );
- err++;
- } else if ( !( rc & FC_FILEBAD ) && ( rc & FC_FILEUNREAD )) {
- fprintf( stderr, "Error: %s: status file not readable\n",
- sglob->slurpd_status_file );
- err++;
- } else if ( !( rc & FC_FILEBAD ) && ( rc & FC_FILEUNWRITE )) {
- fprintf( stderr, "Error: %s: status file not writeable\n",
- sglob->slurpd_status_file );
- err++;
- }
-
- return ( err == 0 ? 0 : -1 );
-}
-
-
-
-/*
- * Check for the existence of the file and directory leading to the file.
- * Returns a bitmask which is the logical OR of the following flags:
- *
- * FC_DIRBAD: directory containing "f" does not exist.
- * FC_DIRUNREAD: directory containing "f" exists but is not readable.
- * FC_DIRUNWRITE: directory containing "f" exists but is not writable.
- * FC_FILEBAD: "f" does not exist.
- * FC_FILEUNREAD: "f" exists but is unreadable.
- * FC_FILEUNWRITE: "f" exists but is unwritable.
- *
- * The calling routine is responsible for determining which, if any, of
- * the returned flags is a problem for a particular file.
- */
-static unsigned int
-filecheck(
- char *f
-)
-{
- char dir[ MAXPATHLEN ];
- char *p;
- unsigned int ret = 0;
-
- snprintf( dir, sizeof dir, "%s", f );
- p = strrchr( dir, LDAP_DIRSEP[0] );
- if ( p != NULL ) {
- *p = '\0';
- }
- if ( access( dir, F_OK ) < 0 ) {
- ret |= FC_DIRBAD;
- }
- if ( access( dir, R_OK ) < 0 ) {
- ret |= FC_DIRUNREAD;
- }
- if ( access( dir, W_OK ) < 0 ) {
- ret |= FC_DIRUNWRITE;
- }
- if ( access( f, F_OK ) < 0 ) {
- ret |= FC_FILEBAD;
- }
- if ( access( f, R_OK ) < 0 ) {
- ret |= FC_FILEUNREAD;
- }
- if ( access( f, W_OK ) < 0 ) {
- ret |= FC_FILEUNWRITE;
- }
-
- return ret;
-}
+++ /dev/null
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 1998-2007 The OpenLDAP Foundation.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted only as authorized by the OpenLDAP
- * Public License.
- *
- * A copy of this license is available in file LICENSE in the
- * top-level directory of the distribution or, alternatively, at
- * <http://www.OpenLDAP.org/license.html>.
- */
-/* Portions Copyright (c) 1996 Regents of the University of Michigan.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that this notice is preserved and that due credit is given
- * to the University of Michigan at Ann Arbor. The name of the University
- * may not be used to endorse or promote products derived from this
- * software without specific prior written permission. This software
- * is provided ``as is'' without express or implied warranty.
- */
-/* ACKNOWLEDGEMENTS:
- * This work was originally developed by the University of Michigan
- * (as part of U-MICH LDAP).
- */
-
-/* slurp.h - Standalone Ldap Update Replication Daemon (slurpd) */
-
-#ifndef _SLURPD_H_
-#define _SLURPD_H_
-
-#if !defined(HAVE_WINSOCK) && !defined(LDAP_SYSLOG)
-#define LDAP_SYSLOG 1
-#endif
-
-#include <ac/errno.h>
-#include <ac/param.h>
-#include <ac/signal.h>
-#include <ac/syslog.h>
-#include <ac/time.h>
-
-#include <sys/types.h>
-
-#include <ldap.h>
-
-#undef ldap_debug
-#define ldap_debug slurp_debug
-#include "ldap_log.h"
-
-#include "ldap_pvt_thread.h"
-#include "ldap_defaults.h"
-#include "ldif.h"
-
-#ifdef HAVE_WINSOCK
- /* should be moved to portable.h.nt */
-#define ftruncate(a,b) _chsize(a,b)
-#define truncate(a,b) _lclose( _lcreat(a, 0))
-#define mkdir(a,b) mkdir(a)
-#define S_IRGRP 0
-#define S_IWGRP 0
-#ifndef F_OK
-#define F_OK 0
-#endif
-#ifndef W_OK
-#define W_OK 2
-#endif
-#ifndef R_OK
-#define R_OK 4
-#endif
-#ifndef S_IRUSR
-#define S_IRUSR S_IREAD
-#endif
-#ifndef S_IWUSR
-#define S_IWUSR S_IWRITE
-#endif
-#endif
-
-#undef SERVICE_NAME
-#define SERVICE_NAME OPENLDAP_PACKAGE "-slurpd"
-
-/* Default directory for slurpd's private copy of replication logs */
-#define DEFAULT_SLURPD_REPLICA_DIR LDAP_RUNDIR LDAP_DIRSEP "openldap-slurp"
-
-/* Default name for slurpd's private copy of the replication log */
-#define DEFAULT_SLURPD_REPLOGFILE "slurpd.replog"
-
-/* Name of file which stores saved slurpd state info, for restarting */
-#define DEFAULT_SLURPD_STATUS_FILE "slurpd.status"
-
-/* slurpd dump file - contents of rq struct are written here (debugging) */
-#define SLURPD_DUMPFILE LDAP_TMPDIR LDAP_DIRSEP "slurpd.dump"
-
-/* Amount of time to sleep if no more work to do */
-#define DEFAULT_NO_WORK_INTERVAL 3
-
-/* The time we wait between checks to see if the replog file needs trimming */
-#define TRIMCHECK_INTERVAL ( 60 * 5 )
-
-/* Only try to trim slurpd replica files larger than this size */
-#define MIN_TRIM_FILESIZE ( 10L * 1024L )
-
-/* Maximum line length we can read from replication log */
-#define REPLBUFLEN 256
-
-/* TLS flags */
-#define TLS_OFF 0
-#define TLS_ON 1
-#define TLS_CRITICAL 2
-
-/* Rejection records are prefaced with this string */
-#define ERROR_STR "ERROR"
-
-/* Strings found in replication entries */
-#define T_CHANGETYPESTR "changetype"
-#define T_CHANGETYPE 1
-#define T_TIMESTR "time"
-#define T_TIME 2
-#define T_DNSTR "dn"
-#define T_DN 3
-
-#define T_ADDCTSTR "add"
-#define T_ADDCT 4
-#define T_MODIFYCTSTR "modify"
-#define T_MODIFYCT 5
-#define T_DELETECTSTR "delete"
-#define T_DELETECT 6
-#define T_MODRDNCTSTR "modrdn"
-#define T_MODDNCTSTR "moddn"
-#define T_RENAMECTSTR "rename"
-#define T_MODRDNCT 7
-
-#define T_MODOPADDSTR "add"
-#define T_MODOPADD 8
-#define T_MODOPREPLACESTR "replace"
-#define T_MODOPREPLACE 9
-#define T_MODOPDELETESTR "delete"
-#define T_MODOPDELETE 10
-#define T_MODOPINCREMENTSTR "increment"
-#define T_MODOPINCREMENT 11
-#define T_MODSEPSTR "-"
-#define T_MODSEP 12
-
-#define T_NEWRDNSTR "newrdn"
-#define T_DELOLDRDNSTR "deleteoldrdn"
-#define T_NEWSUPSTR "newsuperior"
-
-#define T_ERR -1
-
-/* Config file keywords */
-#define HOSTSTR "host"
-#define URISTR "uri"
-#define ATTRSTR "attr"
-#define SUFFIXSTR "suffix"
-#define BINDDNSTR "binddn"
-#define BINDMETHSTR "bindmethod"
-#define SIMPLESTR "simple"
-#define SASLSTR "sasl"
-#define CREDSTR "credentials"
-#define OLDAUTHCSTR "bindprincipal"
-#define AUTHCSTR "authcID"
-#define AUTHZSTR "authzID"
-#define SASLMECHSTR "saslmech"
-#define REALMSTR "realm"
-#define SECPROPSSTR "secprops"
-#define STARTTLSSTR "starttls"
-#define TLSSTR "tls"
-#define CRITICALSTR "critical"
-
-#define REPLICA_SLEEP_TIME ( 10 )
-
-/* Enumeration of various types of bind failures */
-#define BIND_OK 0
-#define BIND_ERR_BADLDP 1
-#define BIND_ERR_OPEN 2
-#define BIND_ERR_BAD_ATYPE 3
-#define BIND_ERR_SIMPLE_FAILED 4
-#define BIND_ERR_BADRI 6
-#define BIND_ERR_VERSION 7
-#define BIND_ERR_REFERRALS 8
-#define BIND_ERR_MANAGEDSAIT 9
-#define BIND_ERR_SASL_FAILED 10
-#define BIND_ERR_TLS_FAILED 11
-
-/* Return codes for do_ldap() */
-#define DO_LDAP_OK 0
-#define DO_LDAP_ERR_RETRYABLE 1
-#define DO_LDAP_ERR_FATAL 2
-
-/*
- * Types of counts one can request from the Rq rq_getcount()
- * member function
- */
-/* all elements */
-#define RQ_COUNT_ALL 1
-/* all elements with nonzero refcnt */
-#define RQ_COUNT_NZRC 2
-
-/* Amount of time, in seconds, for a thread to sleep when it encounters
- * a retryable error in do_ldap().
- */
-#define RETRY_SLEEP_TIME 60
-
-
-LDAP_BEGIN_DECL
-
-/*
- * ****************************************************************************
- * Data types for replication queue and queue elements.
- * ****************************************************************************
- */
-
-
-/*
- * Replica host information. An Ri struct will contain an array of these,
- * with one entry for each replica. The end of the array is signaled
- * by a NULL value in the rh_hostname field.
- */
-typedef struct rh {
- char *rh_hostname; /* replica hostname */
- int rh_port; /* replica port */
-} Rh;
-
-
-/*
- * Per-replica information.
- *
- * Notes:
- * - Private data should not be manipulated expect by Ri member functions.
- */
-typedef struct ri Ri;
-struct ri {
- /* Private data */
- char *ri_hostname; /* canonical hostname of replica */
- int ri_port; /* port where slave slapd running */
- char *ri_uri; /* e.g. "ldaps://ldap-1.example.com:636" */
- LDAP *ri_ldp; /* LDAP struct for this replica */
- int ri_tls; /* TLS: 0=no, 1=yes, 2=critical */
- int ri_bind_method; /* AUTH_SIMPLE or AUTH_SASL */
- char *ri_bind_dn; /* DN to bind as when replicating */
- char *ri_password; /* Password for any method */
- char *ri_secprops; /* SASL security properties */
- char *ri_realm; /* realm for any mechanism */
- char *ri_authcId; /* authentication ID for any mechanism */
- char *ri_authzId; /* authorization ID for any mechanism */
- char *ri_saslmech; /* SASL mechanism to use */
- struct re *ri_curr; /* current repl entry being processed */
- struct stel *ri_stel; /* pointer to Stel for this replica */
- unsigned long
- ri_seq; /* seq number of last repl */
- ldap_pvt_thread_t ri_tid; /* ID of thread for this replica */
-
- /* Member functions */
- int (*ri_process) LDAP_P(( Ri * )); /* process the next repl entry */
- void (*ri_wake) LDAP_P(( Ri * )); /* wake up a sleeping thread */
-};
-
-
-
-/*
- * Information about one particular modification to make. This data should
- * be considered private to routines in re.c, and to routines in ri.c.
- */
-typedef struct mi {
- /* Private data */
- char *mi_type; /* attr or type */
- char *mi_val; /* value */
- int mi_len; /* length of mi_val */
-} Mi;
-
-
-
-/*
- * Information about one particular replication entry. Only routines in
- * re.c and rq.c should touch the private data. Other routines should
- * only use member functions.
- */
-typedef struct re Re;
-struct re {
- /* Private data */
- ldap_pvt_thread_mutex_t
- re_mutex; /* mutex for this Re */
- int re_refcnt; /* ref count, 0 = done */
- time_t re_timestamp; /* timestamp of this re */
- int re_seq; /* sequence number */
- Rh *re_replicas; /* array of replica info */
- char *re_dn; /* dn of entry being modified */
- int re_changetype; /* type of modification */
- Mi *re_mods; /* array of modifications to make */
- struct re *re_next; /* pointer to next element */
-
- /* Public functions */
- int (*re_free) LDAP_P(( Re * )); /* free an re struct */
- Re *(*re_getnext) LDAP_P(( Re * )); /* return next Re in linked list */
- int (*re_parse) LDAP_P(( Re *, char * )); /* parse replication log entry */
- int (*re_write) LDAP_P(( Ri *, Re *, FILE * )); /* write repl. log entry */
- void (*re_dump) LDAP_P(( Re *, FILE * )); /* debugging - print contents */
- int (*re_lock) LDAP_P(( Re * )); /* lock this re */
- int (*re_unlock) LDAP_P(( Re * )); /* unlock this re */
- int (*re_decrefcnt) LDAP_P(( Re * )); /* decrement the refcnt */
- int (*re_getrefcnt) LDAP_P(( Re * )); /* get the refcnt */
-};
-
-
-
-
-/*
- * Definition for the queue of replica information. Private data is
- * private to rq.c. Other routines should only touch public data or
- * use member functions. Note that although we have a member function
- * for locking the queue's mutex, we need to expose the rq_mutex
- * variable so routines in ri.c can use it as a mutex for the
- * rq_more condition variable.
- */
-typedef struct rq Rq;
-struct rq {
-
- /* Private data */
- Re *rq_head; /* pointer to head */
- Re *rq_tail; /* pointer to tail */
- int rq_nre; /* total number of Re's in queue */
- int rq_ndel; /* number of deleted Re's in queue */
- time_t rq_lasttrim; /* Last time we trimmed file */
-
- /* Public data */
- ldap_pvt_thread_mutex_t
- rq_mutex; /* mutex for whole queue */
- ldap_pvt_thread_cond_t
- rq_more; /* condition var - more work added */
-
- /* Member functions */
- Re * (*rq_gethead) LDAP_P(( Rq * )); /* get the element at head */
- Re * (*rq_getnext) LDAP_P(( Re * )); /* get the next element */
- int (*rq_delhead) LDAP_P(( Rq * )); /* delete the element at head */
- int (*rq_add) LDAP_P(( Rq *, char * )); /* add at tail */
- void (*rq_gc) LDAP_P(( Rq * )); /* garbage-collect queue */
- int (*rq_lock) LDAP_P(( Rq * )); /* lock the queue */
- int (*rq_unlock) LDAP_P(( Rq * )); /* unlock the queue */
- int (*rq_needtrim) LDAP_P(( Rq * )); /* see if queue needs trimming */
- int (*rq_write) LDAP_P(( Rq *, FILE * )); /*write Rq contents to file*/
- int (*rq_getcount) LDAP_P(( Rq *, int )); /* return queue counts */
- void (*rq_dump) LDAP_P(( Rq * )); /* debugging - print contents */
-};
-
-
-/*
- * An Stel (status element) contains information about one replica.
- * Stel structs are associated with the St (status) struct, defined
- * below.
- */
-typedef struct stel {
- char *hostname; /* host name of replica */
- int port; /* port number of replica */
- time_t last; /* timestamp of last successful repl */
- int seq; /* Sequence number of last repl */
-} Stel;
-
-
-/*
- * An St struct in an in-core structure which contains the current
- * slurpd state. Most importantly, it contains an array of Stel
- * structs which contain the timestamp and sequence number of the last
- * successful replication for each replica. The st_write() member
- * function is called periodically to flush status information to
- * disk. At startup time, slurpd checks for the status file, and
- * if present, uses the timestamps to avoid "replaying" replications
- * which have already been sent to a given replica.
- */
-typedef struct st St;
-struct st {
- /* Private data */
- ldap_pvt_thread_mutex_t
- st_mutex; /* mutex to serialize access */
- Stel **st_data; /* array of pointers to Stel structs */
- int st_nreplicas; /* number of repl hosts */
- int st_err_logged; /* 1 if fopen err logged */
- FILE *st_fp; /* st file kept open */
- FILE *st_lfp; /* lockfile fp */
-
- /* Public member functions */
- int (*st_update) LDAP_P(( St *, Stel*, Re* ));/*update entry for a host*/
- Stel*(*st_add) LDAP_P(( St *, Ri * )); /*add a new repl host*/
- int (*st_write) LDAP_P(( St * )); /* write status to disk */
- int (*st_read) LDAP_P(( St * )); /* read status info from disk */
- int (*st_lock) LDAP_P(( St * )); /* read status info from disk */
- int (*st_unlock) LDAP_P(( St * )); /* read status info from disk */
-};
-
-#if defined( HAVE_LWP )
-typedef struct tl {
- thread_t tl_tid; /* thread being managed */
- time_t tl_wake; /* time thread should be resumed */
- struct tl *tl_next; /* next node in list */
-} tl_t;
-
-typedef struct tsl {
- tl_t *tsl_list;
- mon_t tsl_mon;
-} tsl_t;
-#endif /* HAVE_LWP */
-
-/*
- * Public functions used to instantiate and initialize queue objects.
- */
-extern int Ri_init LDAP_P(( Ri **ri ));
-extern int Rq_init LDAP_P(( Rq **rq ));
-extern int Re_init LDAP_P(( Re **re ));
-
-#include "proto-slurp.h"
-
-LDAP_END_DECL
-
-#endif /* _SLURPD_H_ */
+++ /dev/null
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 1998-2007 The OpenLDAP Foundation.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted only as authorized by the OpenLDAP
- * Public License.
- *
- * A copy of this license is available in file LICENSE in the
- * top-level directory of the distribution or, alternatively, at
- * <http://www.OpenLDAP.org/license.html>.
- */
-/* Portions Copyright (c) 1996 Regents of the University of Michigan.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that this notice is preserved and that due credit is given
- * to the University of Michigan at Ann Arbor. The name of the University
- * may not be used to endorse or promote products derived from this
- * software without specific prior written permission. This software
- * is provided ``as is'' without express or implied warranty.
- */
-/* ACKNOWLEDGEMENTS:
- * This work was originally developed by the University of Michigan
- * (as part of U-MICH LDAP).
- */
-
-
-/*
- * st.c - routines for managing the status structure, and for reading and
- * writing status information to disk.
- */
-
-#include "portable.h"
-
-#include <stdio.h>
-
-#include <ac/stdlib.h>
-#include <ac/string.h>
-#include <ac/unistd.h>
-
-#include "slurp.h"
-#include "globals.h"
-#include "lutil.h"
-
-/*
- * Add information about replica host specified by Ri to list
- * of hosts.
- */
-static Stel *
-St_add(
- St *st,
- Ri *ri
-)
-{
- int ind;
-
- if ( st == NULL || ri == NULL ) {
- return NULL;
- }
-
- /* Serialize access to the St struct */
- ldap_pvt_thread_mutex_lock( &(st->st_mutex ));
-
- st->st_nreplicas++;
- ind = st->st_nreplicas - 1;
- st->st_data = ( Stel ** ) ch_realloc( st->st_data,
- ( st->st_nreplicas * sizeof( Stel * )));
- if ( st->st_data == NULL ) {
- ldap_pvt_thread_mutex_unlock( &(st->st_mutex ));
- return NULL;
- }
- st->st_data[ ind ] = ( Stel * ) ch_malloc( sizeof( Stel ) );
- if ( st->st_data[ ind ] == NULL ) {
- ldap_pvt_thread_mutex_unlock( &(st->st_mutex ));
- return NULL;
- }
-
- st->st_data[ ind ]->hostname = strdup( ri->ri_hostname );
- st->st_data[ ind ]->port = ri->ri_port;
- st->st_data[ ind ]->last = 0;
- st->st_data[ ind ]->seq = 0;
-
- ldap_pvt_thread_mutex_unlock( &(st->st_mutex ));
- return st->st_data[ ind ];
-}
-
-
-
-/*
- * Write the contents of an St to disk.
- */
-static int
-St_write (
- St *st
-)
-{
- int rc;
- Stel *stel;
- int i;
-
- if ( st == NULL ) {
- return -1;
- }
- ldap_pvt_thread_mutex_lock( &(st->st_mutex ));
- if ( st->st_fp == NULL ) {
- /* Open file */
- if (( rc = acquire_lock( sglob->slurpd_status_file, &(st->st_fp),
- &(st->st_lfp))) < 0 ) {
- if ( !st->st_err_logged ) {
- Debug( LDAP_DEBUG_ANY,
- "Error: cannot open status file \"%s\": %s\n",
- sglob->slurpd_status_file, sys_errlist[ errno ], 0 );
- st->st_err_logged = 1;
- ldap_pvt_thread_mutex_unlock( &(st->st_mutex ));
- return -1;
- }
- } else {
- st->st_err_logged = 0;
- }
- }
-
- /* Write data to the file */
- truncate( sglob->slurpd_status_file, 0L );
- fseek( st->st_fp, 0L, 0 );
- for ( i = 0; i < st->st_nreplicas; i++ ) {
- stel = st->st_data[ i ];
- fprintf( st->st_fp, "%s:%d:%ld:%d\n",
- stel->hostname, stel->port,
- (long) stel->last, stel->seq );
- }
- fflush( st->st_fp );
-
- ldap_pvt_thread_mutex_unlock( &(st->st_mutex ));
-
- return 0;
-}
-
-
-
-
-/*
- * Update the entry for a given host.
- */
-static int
-St_update(
- St *st,
- Stel *stel,
- Re *re
-)
-{
- if ( stel == NULL || re == NULL ) {
- return -1;
- }
-
- ldap_pvt_thread_mutex_lock( &(st->st_mutex ));
- stel->last = re->re_timestamp;
- stel->seq = re->re_seq;
- ldap_pvt_thread_mutex_unlock( &(st->st_mutex ));
- return 0;
-}
-
-
-
-
-/*
- * Read status information from disk file.
- */
-static int
-St_read(
- St *st
-)
-{
- FILE *fp;
- FILE *lfp;
- char buf[ 255 ];
- int i;
- int rc;
- char *hostname, *port, *timestamp, *seq, *p, *t;
- int found;
-
- if ( st == NULL ) {
- return -1;
- }
- ldap_pvt_thread_mutex_lock( &(st->st_mutex ));
- if ( access( sglob->slurpd_status_file, F_OK ) < 0 ) {
- /*
- * File doesn't exist, so create it and return.
- */
- if (( fp = fopen( sglob->slurpd_status_file, "w" )) == NULL ) {
- Debug( LDAP_DEBUG_ANY, "Error: cannot create status file \"%s\"\n",
- sglob->slurpd_status_file, 0, 0 );
- ldap_pvt_thread_mutex_unlock( &(st->st_mutex ));
- return -1;
- }
- (void) fclose( fp );
- ldap_pvt_thread_mutex_unlock( &(st->st_mutex ));
- Debug( LDAP_DEBUG_ARGS, "No status file found, defaulting values\n",
- 0, 0, 0 );
- return 0;
- }
- if (( rc = acquire_lock( sglob->slurpd_status_file, &fp, &lfp)) < 0 ) {
- ldap_pvt_thread_mutex_unlock( &(st->st_mutex ));
- return 0;
- }
- while ( fgets( buf, sizeof( buf ), fp ) != NULL ) {
- p = buf;
- hostname = p;
- if (( t = strchr( p, ':' )) == NULL ) {
- goto bad;
- }
- *t++ = '\0';
- p = t;
- port = p;
- if (( t = strchr( p, ':' )) == NULL ) {
- goto bad;
- }
- *t++ = '\0';
- p = t;
- timestamp = p;
- if (( t = strchr( p, ':' )) == NULL ) {
- goto bad;
- }
- *t++ = '\0';
- seq = t;
- if (( t = strchr( seq, '\n' )) != NULL ) {
- *t = '\0';
- }
-
- found = 0;
- for ( i = 0; i < sglob->st->st_nreplicas; i++ ) {
- int p;
- if ( !strcmp( hostname, sglob->st->st_data[ i ]->hostname ) &&
- lutil_atoi( &p, port ) == 0 && p == sglob->st->st_data[ i ]->port )
- {
- found = 1;
- if ( lutil_atol( &sglob->st->st_data[ i ]->last, timestamp ) != 0
- || lutil_atoi( &sglob->st->st_data[ i ]->seq, seq ) != 0 )
- {
- found = 0;
- }
- break;
- }
- }
- if ( found ) {
- char tbuf[ 255 ];
- sprintf( tbuf, "%s.%s", timestamp, seq );
- Debug( LDAP_DEBUG_ARGS,
- "Retrieved state information for %s:%s (timestamp %s)\n",
- hostname, port, tbuf );
- } else {
- Debug( LDAP_DEBUG_ANY,
- "Warning: saved state for %s:%s, not a known replica\n",
- hostname, port, 0 );
- }
- }
- (void) relinquish_lock( sglob->slurpd_status_file, fp, lfp);
- ldap_pvt_thread_mutex_unlock( &(st->st_mutex ));
- return 0;
-
-bad:
- (void) relinquish_lock( sglob->slurpd_status_file, fp, lfp);
- ldap_pvt_thread_mutex_unlock( &(st->st_mutex ));
- return -1;
-}
-
-
-
-
-/*
- * Lock an St struct.
- */
-static int
-St_lock(
- St *st
-)
-{
- return( ldap_pvt_thread_mutex_lock( &st->st_mutex ));
-}
-
-
-
-
-/*
- * Lock an St struct.
- */
-static int
-St_unlock(
- St *st
-)
-{
- return( ldap_pvt_thread_mutex_unlock( &st->st_mutex ));
-}
-
-
-
-
-/*
- * Allocate and initialize an St struct.
- */
-int
-St_init(
- St **st
-)
-{
- if ( st == NULL ) {
- return -1;
- }
-
- (*st) = (St *) malloc( sizeof( St ));
- if ( *st == NULL ) {
- return -1;
- }
-
- ldap_pvt_thread_mutex_init( &((*st)->st_mutex) );
- (*st)->st_data = NULL;
- (*st)->st_fp = NULL;
- (*st)->st_lfp = NULL;
- (*st)->st_nreplicas = 0;
- (*st)->st_err_logged = 0;
- (*st)->st_update = St_update;
- (*st)->st_add = St_add;
- (*st)->st_write = St_write;
- (*st)->st_read = St_read;
- (*st)->st_lock = St_lock;
- (*st)->st_unlock = St_unlock;
- return 0;
-}
-
its: regressions
clean-local: FORCE
- -$(RM) -r testrun *leak *gmon *core
+ -$(RM) -r testrun configpw configpw.conf *leak *gmon *core
veryclean-local: FORCE
@-$(RM) run testdata schema ucdata
This directory contains a series of test scripts which are used to
-verify basic functionality of the LDAP libraries, slapd, and slurpd.
+verify basic functionality of the LDAP libraries and slapd.
To run all of the tests, type "make test".
To run BDB tests, type "make bdb".
# Testing list compare with manageDSAit...
FALSE
+# Testing list search without dgIdentity...
+dn: cn=Dynamic List of Members,ou=Dynamic Lists,dc=example,dc=com
+objectClass: groupOfURLs
+cn: Dynamic List of Members
+memberURL: ldap:///ou=People,dc=example,dc=com??sub?(objectClass=person)
+
+# Testing list search with dgIdentity...
+dn: cn=Dynamic List of Members,ou=Dynamic Lists,dc=example,dc=com
+objectClass: groupOfURLs
+objectClass: dgIdentityAux
+cn: Dynamic List of Members
+memberURL: ldap:///ou=People,dc=example,dc=com??sub?(objectClass=person)
+dgIdentity: cn=Bjorn Jensen,ou=Information Technology Division,ou=People,dc=ex
+ ample,dc=com
+member: cn=Barbara Jensen,ou=Information Technology Division,ou=People,dc=exam
+ ple,dc=com
+member: cn=Bjorn Jensen,ou=Information Technology Division,ou=People,dc=exampl
+ e,dc=com
+member: cn=Dorothy Stevens,ou=Alumni Association,ou=People,dc=example,dc=com
+member: cn=James A Jones 1,ou=Alumni Association,ou=People,dc=example,dc=com
+member: cn=James A Jones 2,ou=Information Technology Division,ou=People,dc=exa
+ mple,dc=com
+member: cn=Jane Doe,ou=Alumni Association,ou=People,dc=example,dc=com
+member: cn=Jennifer Smith,ou=Alumni Association,ou=People,dc=example,dc=com
+member: cn=John Doe,ou=Information Technology Division,ou=People,dc=example,dc
+ =com
+member: cn=Mark Elliot,ou=Alumni Association,ou=People,dc=example,dc=com
+member: cn=Ursula Hampster,ou=Alumni Association,ou=People,dc=example,dc=com
+
access to dn=""
by * read
+
access to dn="cn=Subschema"
by * read
#bdb#index cn,sn,uid pres,eq,sub
#hdb#index objectClass eq
#hdb#index cn,sn,uid pres,eq,sub
-#ldbm#index objectClass eq
-#ldbm#index cn,sn,uid pres,eq,sub
access to dn.subtree="dc=example,dc=com"
by dynacl/aci write
#monitor#database monitor
-
+#monitor#rootdn "cn=Monitor"
#######################################################################
database @BACKEND@
-#ldbm#cachesize 0
+
suffix "dc=example,dc=com"
directory @TESTDIR@/db.1.a
rootdn "cn=Manager,dc=example,dc=com"
#bdb#index cn,sn,uid pres,eq,sub
#hdb#index objectClass eq
#hdb#index cn,sn,uid pres,eq,sub
-#ldbm#index objectClass eq
-#ldbm#index cn,sn,uid pres,eq,sub
#access to attrs=objectclass dn.subtree="dc=example,dc=com"
access to attrs=objectclass
#bdb#index cn,sn,uid pres,eq,sub
#hdb#index objectClass eq
#hdb#index cn,sn,uid pres,eq,sub
-#ldbm#index objectClass eq
-#ldbm#index cn,sn,uid pres,eq,sub
#monitor#database monitor
#
database @BACKEND@
-#ldbm#cachesize 0
+
suffix "dc=example,dc=com"
directory @TESTDIR@/db.1.a
rootdn "cn=Manager,dc=example,dc=com"
#bdb#index cn,sn,uid pres,eq,sub
#hdb#index objectClass eq
#hdb#index cn,sn,uid pres,eq,sub
-#ldbm#index objectClass eq
-#ldbm#index cn,sn,uid pres,eq,sub
#monitor#database monitor
#
database @BACKEND@
-#ldbm#cachesize 0
+
suffix "dc=example,dc=com"
directory @TESTDIR@/db.2.a
rootdn "cn=Manager,dc=example,dc=com"
#bdb#index cn,sn,uid pres,eq,sub
#hdb#index objectClass eq
#hdb#index cn,sn,uid pres,eq,sub
-#ldbm#index objectClass eq
-#ldbm#index cn,sn,uid pres,eq,sub
#
# uses the chain overlay as database specific;
rootpw secret
#bdb#index objectClass eq
#hdb#index objectClass eq
-#ldbm#index objectClass eq
#monitor#database monitor
#bdb#index cn,sn,uid pres,eq,sub
#hdb#index objectClass eq
#hdb#index cn,sn,uid pres,eq,sub
-#ldbm#index objectClass eq
-#ldbm#index cn,sn,uid pres,eq,sub
#monitor#database monitor
database config
-include "configpw.conf"
+include @TESTDIR@/configpw.conf
#hdb#index objectClass eq
#hdb#index cn,sn,uid pres,eq,sub
#hdb#index entryExpireTimestamp eq
-#ldbm#index objectClass eq
-#ldbm#index cn,sn,uid pres,eq,sub
-#ldbm#index entryExpireTimestamp eq
overlay dds
dds-max-ttl 1d
#bdb#index entryUUID,entryCSN eq
#hdb#index objectClass eq
#hdb#index entryUUID,entryCSN eq
-#ldbm#index objectClass eq
-#ldbm#index entryUUID,entryCSN eq
overlay syncprov
syncprov-reloadhint true
#hdb#index objectClass eq
#hdb#index cn,sn,uid pres,eq,sub
#hdb#index entryUUID,entryCSN eq
-#ldbm#index objectClass eq
-#ldbm#index cn,sn,uid pres,eq,sub
+
+
access to *
by users write
by * read
#bdb#index cn,sn,uid pres,eq,sub
#hdb#index objectClass eq
#hdb#index cn,sn,uid pres,eq,sub
-#ldbm#index objectClass eq
-#ldbm#index cn,sn,uid pres,eq,sub
# Don't change syncrepl spec yet
syncrepl rid=1
#bdb#index cn,sn,uid pres,eq,sub
#hdb#index objectClass eq
#hdb#index cn,sn,uid pres,eq,sub
-#ldbm#index objectClass eq
-#ldbm#index cn,sn,uid pres,eq,sub
#monitor#database monitor
dn: olcDatabase={0}config,cn=config
objectClass: olcDatabaseConfig
olcDatabase: {0}config
-olcRootPW:< file:configpw
+olcRootPW:< file://@TESTDIR@/configpw
#bdb#index cn,sn,uid pres,eq,sub
#hdb#index objectClass eq
#hdb#index cn,sn,uid pres,eq,sub
-#ldbm#index objectClass eq
-#ldbm#index cn,sn,uid pres,eq,sub
+# we'll reconfigure the attrset dynamically
overlay dynlist
-### DO NOT ADD ANY DIRECTIVE BELOW THIS; TEST APPENDS STUFF ###
+dynlist-attrset groupOfURLs memberURL
+
+database config
+include @TESTDIR@/configpw.conf
#bdb#index cn,sn,uid pres,eq,sub
#hdb#index objectClass eq
#hdb#index cn,sn,uid pres,eq,sub
-#ldbm#index objectClass eq
-#ldbm#index cn,sn,uid pres,eq,sub
access to attrs=userPassword
by dn.exact="cn=Manager,c=US" write
#bdb#index cn,sn,uid pres,eq,sub
#hdb#index objectClass eq
#hdb#index cn,sn,uid pres,eq,sub
-#ldbm#index objectClass eq
-#ldbm#index cn,sn,uid pres,eq,sub
access to attrs=userPassword
by self =wx
#hdb#index uid pres,eq,sub
#hdb#index cn,sn pres,eq,sub,subany
#hdb#index entryUUID,entryCSN pres
-#ldbm#index objectclass eq
-#ldbm#index uid pres,eq,sub
-#ldbm#index cn,sn pres,eq,sub,subany
-#ldbm#dbnosync
-#ldbm#dbnolocking
+
overlay syncprov
database @BACKEND@
#hdb#index uid pres,eq,sub
#hdb#index cn,sn pres,eq,sub,subany
#hdb#index entryUUID,entryCSN pres
-#ldbm#index objectclass eq
-#ldbm#index uid pres,eq,sub
-#ldbm#index cn,sn pres,eq,sub,subany
-#ldbm#dbnosync
-#ldbm#dbnolocking
+
syncrepl rid=1
provider=@URI2@
binddn="cn=Manager 2,dc=example,dc=com"
#hdb#index objectclass eq
#hdb#index uid pres,eq,sub
#hdb#index cn,sn pres,eq,sub,subany
-#ldbm#index objectclass eq
-#ldbm#index uid pres,eq,sub
-#ldbm#index cn,sn pres,eq,sub,subany
-#ldbm#dbnosync
-#ldbm#dbnolocking
+
#overlay syncprov
#monitor#database monitor
#hdb#index uid pres,eq,sub
#hdb#index cn,sn pres,eq,sub,subany
#hdb#index entryUUID,entryCSN pres
-#ldbm#index objectclass eq
-#ldbm#index uid pres,eq,sub
-#ldbm#index cn,sn pres,eq,sub,subany
-#ldbm#dbnosync
-#ldbm#dbnolocking
+
+
syncrepl rid=2
provider=@URI1@
binddn="cn=Manager 1,dc=example,dc=com"
#hdb#index uid pres,eq,sub
#hdb#index cn,sn pres,eq,sub,subany
#hdb#index entryUUID,entryCSN pres
-#ldbm#index objectclass eq
-#ldbm#index uid pres,eq,sub
-#ldbm#index cn,sn pres,eq,sub,subany
-#ldbm#dbnosync
-#ldbm#dbnolocking
+
+
overlay syncprov
#hdb#index objectclass eq
#hdb#index uid pres,eq,sub
#hdb#index cn,sn pres,eq,sub,subany
-#ldbm#index objectclass eq
-#ldbm#index uid pres,eq,sub
-#ldbm#index cn,sn pres,eq,sub,subany
-#ldbm#dbnosync
-#ldbm#dbnolocking
+
+
#overlay syncprov
#monitor#database monitor
#hdb#index objectclass eq
#hdb#index uid pres,eq,sub
#hdb#index cn,sn pres,eq,sub,subany
-#ldbm#index objectclass eq
-#ldbm#index uid pres,eq,sub
-#ldbm#index cn,sn pres,eq,sub,subany
-#ldbm#dbnosync
-#ldbm#dbnolocking
database @BACKEND@
suffix "ou=Groups,dc=example,dc=com"
#hdb#index objectclass eq
#hdb#index uid pres,eq,sub
#hdb#index cn,sn pres,eq,sub,subany
-#ldbm#index objectclass eq
-#ldbm#index uid pres,eq,sub
-#ldbm#index cn,sn pres,eq,sub,subany
-#ldbm#dbnosync
-#ldbm#dbnolocking
database @BACKEND@
suffix "dc=example,dc=com"
#hdb#index objectclass eq
#hdb#index uid pres,eq,sub
#hdb#index cn,sn pres,eq,sub,subany
-#ldbm#index objectclass eq
-#ldbm#index uid pres,eq,sub
-#ldbm#index cn,sn pres,eq,sub,subany
-#ldbm#dbnosync
-#ldbm#dbnolocking
#monitor#database monitor
by * search
database @BACKEND@
-#ldbm#cachesize 0
+
suffix "dc=example,dc=com"
directory @TESTDIR@/db.1.a
rootdn "cn=Manager,dc=example,dc=com"
#bdb#index cn,sn,uid pres,eq,sub
#hdb#index objectClass eq
#hdb#index cn,sn,uid pres,eq,sub
-#ldbm#index objectClass eq
-#ldbm#index cn,sn,uid pres,eq,sub
access to dn.exact="cn=Proxy,ou=Admin,dc=example,dc=com"
attrs=authzTo
by * =x
database @BACKEND@
-#ldbm#cachesize 0
+
suffix "dc=example,dc=it"
directory @TESTDIR@/db.2.a
rootdn "cn=Manager,dc=example,dc=it"
#bdb#index cn,sn,uid pres,eq,sub
#hdb#index objectClass eq
#hdb#index cn,sn,uid pres,eq,sub
-#ldbm#index objectClass eq
-#ldbm#index cn,sn,uid pres,eq,sub
database ldap
suffix "o=Example,c=US"
#bdb#index cn,sn,uid pres,eq,sub
#hdb#index objectClass eq
#hdb#index cn,sn,uid pres,eq,sub
-#ldbm#index objectClass eq
-#ldbm#index cn,sn,uid pres,eq,sub
#monitor#database monitor
#bdb#index cn,sn,uid pres,eq,sub
#hdb#index objectClass eq
#hdb#index cn,sn,uid pres,eq,sub
-#ldbm#index objectClass eq
-#ldbm#index cn,sn,uid pres,eq,sub
#monitor#database monitor
#bdb#index cn,sn,uid pres,eq,sub
#hdb#index objectClass eq
#hdb#index cn,sn,uid pres,eq,sub
-#ldbm#index objectClass eq
-#ldbm#index cn,sn,uid pres,eq,sub
#monitor#database monitor
#bdb#index uid eq
#hdb#index objectClass eq
#hdb#index uid eq
-#ldbm#index objectClass eq
-#ldbm#index uid eq
# Need extra limits for pagedResults on backends that support it...
#bdb#limits dn.exact="cn=Unlimited User,ou=Paged Results Users,dc=example,dc=com" size=4 size.pr=unlimited
rootpw secret
#bdb#index objectClass eq
#hdb#index objectClass eq
-#ldbm#index objectClass eq
#monitor#database monitor
rootpw secret
#bdb#index objectClass eq
#hdb#index objectClass eq
-#ldbm#index objectClass eq
#monitor#database monitor
rootpw secret
#bdb#index objectClass eq
#hdb#index objectClass eq
-#ldbm#index objectClass eq
+
overlay ppolicy
ppolicy_default "cn=Standard Policy,ou=Policies,dc=example,dc=com"
ppolicy_use_lockout
#bdb#cachesize 20
#hdb#cachesize 20
-#ldbm#cachesize 20
+
directory @TESTDIR@/db.2.a
#bdb#index objectClass eq
#bdb#index cn,sn,uid,mail pres,eq,sub
#hdb#index objectClass eq
#hdb#index cn,sn,uid,mail pres,eq,sub
-#ldbm#index objectClass eq
-#ldbm#index cn,sn,uid,mail pres,eq,sub
#monitor#database monitor
#######################################################################
database @BACKEND@
-#ldbm#cachesize 0
+
suffix "dc=example,dc=com"
directory @TESTDIR@/db.1.a
rootdn "cn=Manager,dc=example,dc=com"
#bdb#index cn,sn,uid pres,eq,sub
#hdb#index objectClass eq
#hdb#index cn,sn,uid pres,eq,sub
-#ldbm#index objectClass eq
-#ldbm#index cn,sn,uid pres,eq,sub
#
# normal installations should protect root dse,
database @BACKEND@
#bdb#cachesize 0
#hdb#cachesize 0
-#ldbm#cachesize 0
+
suffix "o=University of Mich,c=US"
directory @TESTDIR@/db.2.a
rootdn "cn=Manager,o=University of Mich,c=US"
#bdb#index cn,sn,uid pres,eq,sub
#hdb#index objectClass eq
#hdb#index cn,sn,uid pres,eq,sub
-#ldbm#index objectClass eq
-#ldbm#index cn,sn,uid pres,eq,sub
#monitor#database monitor
rootpw secret
#bdb#index objectClass eq
#hdb#index objectClass eq
-#ldbm#index objectClass eq
#monitor#database monitor
#bdb#index cn,sn,uid pres,eq,sub
#hdb#index objectClass eq
#hdb#index cn,sn,uid pres,eq,sub
-#ldbm#index objectClass eq
-#ldbm#index cn,sn,uid pres,eq,sub
overlay refint
refint_attributes manager secretary member
rootpw secret
#bdb#index objectClass eq
#hdb#index objectClass eq
-#ldbm#index objectClass eq
database @RELAY@
suffix "o=Example,c=US"
### back-relay can automatically instantiate the rwm overlay
-#relay-relay#relay "dc=example,dc=com" massage
+#relay-relay#relay "dc=example,dc=com"
+#relay-relay#overlay rwm
+#relay-relay#rwm-suffixmassage "dc=example,dc=com"
#relay-relay#rwm-map objectClass groupOfNames groupOfUniqueNames
#relay-relay#rwm-map objectClass uidObject dcObject
#relay-relay#rwm-map attribute member uniqueMember
database @RELAY@
suffix "o=Beispiel,c=DE"
### back-relay can automatically instantiate the rwm overlay
-#relay-relay#relay "dc=example,dc=com" massage
+#relay-relay#relay "dc=example,dc=com"
+#relay-relay#overlay rwm
+#relay-relay#rwm-suffixmassage "dc=example,dc=com"
### back-ldap needs explicit instantiation of the rwm overlay
#relay-ldap#uri "@URI1@"
#relay-ldap#overlay rwm
+++ /dev/null
-# master slapd config -- for testing of replication
-# $OpenLDAP: pkg/ldap/tests/data/slapd-repl-master.conf,v 1.27.2.4 2003/12/15
- 22:05:29 kurt Exp $
-## This work is part of OpenLDAP Software <http://www.openldap.org/>.
-##
-## Copyright 1998-2007 The OpenLDAP Foundation.
-## All rights reserved.
-##
-## Redistribution and use in source and binary forms, with or without
-## modification, are permitted only as authorized by the OpenLDAP
-## Public License.
-##
-## A copy of this license is available in the file LICENSE in the
-## top-level directory of the distribution or, alternatively, at
-## <http://www.OpenLDAP.org/license.html>.
-
-include @SCHEMADIR@/core.schema
-include @SCHEMADIR@/cosine.schema
-include @SCHEMADIR@/inetorgperson.schema
-include @SCHEMADIR@/openldap.schema
-include @SCHEMADIR@/nis.schema
-#
-pidfile @TESTDIR@/slapd.1.pid
-argsfile @TESTDIR@/slapd.1.args
-
-#mod#modulepath ../servers/slapd/back-@BACKEND@/
-#mod#moduleload back_@BACKEND@.la
-#monitormod#modulepath ../servers/slapd/back-monitor/
-#monitormod#moduleload back_monitor.la
-
-#######################################################################
-# database definitions
-#######################################################################
-
-database @BACKEND@
-#ldbm#cachesize 0
-suffix "dc=example,dc=com"
-directory @TESTDIR@/db.1.a
-rootdn "cn=Manager,dc=example,dc=com"
-rootpw secret
-#bdb#index objectClass eq
-#bdb#index cn,sn,uid pres,eq,sub
-#hdb#index objectClass eq
-#hdb#index cn,sn,uid pres,eq,sub
-#ldbm#index objectClass eq
-#ldbm#index cn,sn,uid pres,eq,sub
-
-replogfile @TESTDIR@/slapd.1.replog
-
-replica-argsfile @TESTDIR@/replica.1.args
-replica-pidfile @TESTDIR@/replica.1.pid
-
-replica host=localhost:@PORT2@
- binddn="cn=Replica,dc=example,dc=com"
- bindmethod=simple
- credentials=secret
-
-#monitor#database monitor
by * read
database @BACKEND@
-#ldbm#cachesize 0
+
suffix "dc=example,dc=com"
directory @TESTDIR@/db.2.a
rootdn "cn=Replica,dc=example,dc=com"
+++ /dev/null
-# slave slapd config -- for testing of replication
-# $OpenLDAP: pkg/ldap/tests/data/slapd-repl-slave.conf,v 1.31.2.4 2003/12/15 2
- 2:05:29 kurt Exp $
-## This work is part of OpenLDAP Software <http://www.openldap.org/>.
-##
-## Copyright 1998-2007 The OpenLDAP Foundation.
-## All rights reserved.
-##
-## Redistribution and use in source and binary forms, with or without
-## modification, are permitted only as authorized by the OpenLDAP
-## Public License.
-##
-## A copy of this license is available in the file LICENSE in the
-## top-level directory of the distribution or, alternatively, at
-## <http://www.OpenLDAP.org/license.html>.
-
-include @SCHEMADIR@/core.schema
-include @SCHEMADIR@/cosine.schema
-include @SCHEMADIR@/inetorgperson.schema
-include @SCHEMADIR@/openldap.schema
-include @SCHEMADIR@/nis.schema
-#
-pidfile @TESTDIR@/slapd.2.pid
-argsfile @TESTDIR@/slapd.2.args
-
-#mod#modulepath ../servers/slapd/back-@BACKEND@/
-#mod#moduleload back_@BACKEND@.la
-#monitormod#modulepath ../servers/slapd/back-monitor/
-#monitormod#moduleload back_monitor.la
-#ldapmod#modulepath ../servers/slapd/back-ldap/
-#ldapmod#moduleload back_ldap.la
-
-#ldapyes#overlay chain
-#ldapyes#chain-uri @URI1@
-#ldapyes#chain-idassert-bind bindmethod=simple binddn="cn=Manager,dc=example,dc=com" credentials=secret mode=self
-#ldapmod#overlay chain
-#ldapmod#chain-uri @URI1@
-#ldapmod#chain-idassert-bind bindmethod=simple binddn="cn=Manager,dc=example,dc=com" credentials=secret mode=self
-
-#######################################################################
-# database definitions
-#######################################################################
-
-database @BACKEND@
-#ldbm#cachesize 0
-suffix "dc=example,dc=com"
-directory @TESTDIR@/db.2.a
-rootdn "cn=Replica,dc=example,dc=com"
-rootpw secret
-updatedn "cn=Replica,dc=example,dc=com"
-updateref @URI1@
-#bdb#index objectClass eq
-#bdb#index cn,sn,uid pres,eq,sub
-#hdb#index objectClass eq
-#hdb#index cn,sn,uid pres,eq,sub
-#ldbm#index objectClass eq
-#ldbm#index cn,sn,uid pres,eq,sub
-
-#monitor#database monitor
#bdb#index cn,sn,uid pres,eq,sub
#hdb#index objectClass eq
#hdb#index cn,sn,uid pres,eq,sub
-#ldbm#index objectClass eq
-#ldbm#index cn,sn,uid pres,eq,sub
overlay retcode
retcode-parent "ou=RetCodes,dc=example,dc=com"
directory @TESTDIR@/db.1.a
#bdb#index objectClass eq
#hdb#index objectClass eq
-#ldbm#index objectClass eq
#database @BACKEND@
#suffix "dc=example,dc=com"
#hdb#index objectClass eq
#hdb#index cn,sn,uid pres,eq,sub
#hdb#index entryUUID,entryCSN eq
-#ldbm#index objectClass eq
-#ldbm#index cn,sn,uid pres,eq,sub
overlay syncprov
#syncprov-sessionlog 100
#hdb#index objectClass eq
#hdb#index cn,sn,uid pres,eq,sub
#hdb#index entryUUID,entryCSN eq
-#ldbm#index objectClass eq
-#ldbm#index cn,sn,uid pres,eq,sub
overlay syncprov
syncprov-sessionlog 100
#bdb#index cn,sn,uid pres,eq,sub
#hdb#index objectClass eq
#hdb#index cn,sn,uid pres,eq,sub
-#ldbm#index objectClass eq
-#ldbm#index cn,sn,uid pres,eq,sub
# Don't change syncrepl spec yet
syncrepl rid=1
#hdb#index objectClass eq
#hdb#index cn,sn,uid pres,eq,sub
#hdb#index entryUUID,entryCSN eq
-#ldbm#index objectClass eq
-#ldbm#index cn,sn,uid pres,eq,sub
# Don't change syncrepl spec yet
syncrepl rid=1
#hdb#index objectClass eq
#hdb#index cn,sn,uid pres,eq,sub
#hdb#index entryUUID,entryCSN eq
-#ldbm#index objectClass eq
-#ldbm#index cn,sn,uid pres,eq,sub
# Don't change syncrepl spec yet
syncrepl rid=1
#hdb#index objectClass eq
#hdb#index cn,sn,uid pres,eq,sub
#hdb#index entryUUID,entryCSN eq
-#ldbm#index objectClass eq
-#ldbm#index cn,sn,uid pres,eq,sub
-#ldbm#index entryUUID eq
# Don't change syncrepl spec yet
syncrepl rid=1
#hdb#index objectClass eq
#hdb#index cn,sn,uid pres,eq,sub
#hdb#index entryUUID,entryCSN eq
-#ldbm#index objectClass eq
-#ldbm#index cn,sn,uid pres,eq,sub
-#ldbm#index entryUUID eq
# Don't change syncrepl spec yet
syncrepl rid=1
#bdb#index cn,sn,uid pres,eq,sub
#hdb#index objectClass eq
#hdb#index cn,sn,uid pres,eq,sub
-#ldbm#index objectClass eq
-#ldbm#index cn,sn,uid pres,eq,sub
overlay translucent
translucent_no_glue
acl-bind binddn="uid=binder,o=translucent" credentials="bindtest"
database config
-include "configpw.conf"
+include @TESTDIR@/configpw.conf
#bdb#index cn,sn,uid pres,eq,sub
#hdb#index objectClass eq
#hdb#index cn,sn,uid pres,eq,sub
-#ldbm#index objectClass eq
-#ldbm#index cn,sn,uid pres,eq,sub
-
#bdb#index cn,sn,uid pres,eq,sub
#hdb#index objectClass eq
#hdb#index cn,sn,uid pres,eq,sub
-#ldbm#index objectClass eq
-#ldbm#index cn,sn,uid pres,eq,sub
overlay unique
-unique_ignore o cn sn ou objectClass
+
unique_attributes employeeNumber displayName
+unique_base o=unique
+
+#unique_uri ldap:///?description?one
+#unique_uri ldap:///?employeeNumber,displayName?sub
#monitor#database monitor
+
+database config
+include @TESTDIR@/configpw.conf
#bdb#index cn,sn,uid pres,eq,sub
#hdb#index objectClass eq
#hdb#index cn,sn,uid pres,eq,sub
-#ldbm#index objectClass eq
-#ldbm#index cn,sn,uid pres,eq,sub
overlay valsort
valsort-attr sn ou=users,o=valsort alpha-ascend
valsort-attr employeeType ou=users,o=valsort weighted alpha-ascend
database config
-include configpw.conf
+include @TESTDIR@/configpw.conf
#monitor#database monitor
by * read
database @BACKEND@
-#ldbm#cachesize 0
+
suffix "dc=example,dc=com"
directory @TESTDIR@/db.1.a
rootdn "cn=Manager,dc=example,dc=com"
#bdb#index cn,sn,uid pres,eq,sub
#hdb#index objectClass eq
#hdb#index cn,sn,uid pres,eq,sub
-#ldbm#index objectClass eq
-#ldbm#index cn,sn,uid pres,eq,sub
#monitor#database monitor
#bdb#index cn,sn,uid pres,eq,sub
#hdb#index objectClass eq
#hdb#index cn,sn,uid pres,eq,sub
-#ldbm#index objectClass eq
-#ldbm#index cn,sn,uid pres,eq,sub
#monitor#database monitor
dc: example
# Testing onelevel search...
+dn: cn=Akakiy Zinberstein,dc=example,dc=com
+objectClass: inetOrgPerson
+objectClass: pkiUser
+cn: Akakiy Zinberstein
+sn: Zinberstein
+givenName: Akakiy
+userCertificate;binary:: MIIDazCCAtSgAwIBAgIBAjANBgkqhkiG9w0BAQQFADB3MQswCQYDV
+ QQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEfMB0GA1UEChMWT3BlbkxEQVAgRXhhbXBsZSwgTH
+ RkLjETMBEGA1UEAxMKRXhhbXBsZSBDQTEdMBsGCSqGSIb3DQEJARYOY2FAZXhhbXBsZS5jb20wHhc
+ NMDMxMDE3MTYzMzE5WhcNMDQxMDE2MTYzMzE5WjB+MQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2Fs
+ aWZvcm5pYTEfMB0GA1UEChMWT3BlbkxEQVAgRXhhbXBsZSwgTHRkLjEYMBYGA1UEAxMPVXJzdWxhI
+ EhhbXBzdGVyMR8wHQYJKoZIhvcNAQkBFhB1aGFtQGV4YW1wbGUuY29tMIGfMA0GCSqGSIb3DQEBAQ
+ UAA4GNADCBiQKBgQDuxgp5ELV9LmhxWMpV7qc4028QQT3+zzFDXhruuXE7ji2n3S3ea8bOwDtJh+q
+ nsDe561DhHHHlgIjMKCiDEizYMpxvJPYEXmvp0huRkMgpKZgmel95BSkt6TYmJ0erS3aoimOHLEFi
+ mmnTLolNRMiWqNBvqwobx940PGwUWEePKQIDAQABo4H/MIH8MAkGA1UdEwQCMAAwLAYJYIZIAYb4Q
+ gENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0GA1UdDgQWBBSjI94TbBmuDEeUUO
+ iC37EK0Uf0XjCBoQYDVR0jBIGZMIGWgBRLbyEaNiTSkPlDsFNHLX3hwOaYI6F7pHkwdzELMAkGA1U
+ EBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExHzAdBgNVBAoTFk9wZW5MREFQIEV4YW1wbGUsIEx0
+ ZC4xEzARBgNVBAMTCkV4YW1wbGUgQ0ExHTAbBgkqhkiG9w0BCQEWDmNhQGV4YW1wbGUuY29tggEAM
+ A0GCSqGSIb3DQEBBAUAA4GBAIgUcARb3OlWYNbmr1nmqESuxLn16uqI1Ot6WkcICvpkdQ+Bo+R9AP
+ 05xpoXocZtKdNvBu3FNxB/jFkiOcLU2lX7Px1Ijnsjh60qVRy9HOsHCungIKlGcnXLKHmKu0y//5j
+ ds/HnaJsGcHI5JRG7CBJbW+wrwge3trJ1xHJI8prN
+
dn: documentTitle=book1,dc=example,dc=com
objectClass: document
description: abstract1
documentAuthor: cn=Mitya Kovalev,dc=example,dc=com
documentIdentifier: document 2
-# refldap://localhost:9012/dc=example,dc=com??one
-
dn: cn=Mitya Kovalev,dc=example,dc=com
objectClass: inetOrgPerson
cn: Mitya Kovalev
givenName: Torvlobnor
telephoneNumber: 545-4563
+# refldap://localhost:9012/dc=example,dc=com??one
+
+# Testing subtree search...
dn: cn=Akakiy Zinberstein,dc=example,dc=com
objectClass: inetOrgPerson
+objectClass: pkiUser
cn: Akakiy Zinberstein
sn: Zinberstein
givenName: Akakiy
+userCertificate;binary:: MIIDazCCAtSgAwIBAgIBAjANBgkqhkiG9w0BAQQFADB3MQswCQYDV
+ QQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEfMB0GA1UEChMWT3BlbkxEQVAgRXhhbXBsZSwgTH
+ RkLjETMBEGA1UEAxMKRXhhbXBsZSBDQTEdMBsGCSqGSIb3DQEJARYOY2FAZXhhbXBsZS5jb20wHhc
+ NMDMxMDE3MTYzMzE5WhcNMDQxMDE2MTYzMzE5WjB+MQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2Fs
+ aWZvcm5pYTEfMB0GA1UEChMWT3BlbkxEQVAgRXhhbXBsZSwgTHRkLjEYMBYGA1UEAxMPVXJzdWxhI
+ EhhbXBzdGVyMR8wHQYJKoZIhvcNAQkBFhB1aGFtQGV4YW1wbGUuY29tMIGfMA0GCSqGSIb3DQEBAQ
+ UAA4GNADCBiQKBgQDuxgp5ELV9LmhxWMpV7qc4028QQT3+zzFDXhruuXE7ji2n3S3ea8bOwDtJh+q
+ nsDe561DhHHHlgIjMKCiDEizYMpxvJPYEXmvp0huRkMgpKZgmel95BSkt6TYmJ0erS3aoimOHLEFi
+ mmnTLolNRMiWqNBvqwobx940PGwUWEePKQIDAQABo4H/MIH8MAkGA1UdEwQCMAAwLAYJYIZIAYb4Q
+ gENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0GA1UdDgQWBBSjI94TbBmuDEeUUO
+ iC37EK0Uf0XjCBoQYDVR0jBIGZMIGWgBRLbyEaNiTSkPlDsFNHLX3hwOaYI6F7pHkwdzELMAkGA1U
+ EBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExHzAdBgNVBAoTFk9wZW5MREFQIEV4YW1wbGUsIEx0
+ ZC4xEzARBgNVBAMTCkV4YW1wbGUgQ0ExHTAbBgkqhkiG9w0BCQEWDmNhQGV4YW1wbGUuY29tggEAM
+ A0GCSqGSIb3DQEBBAUAA4GBAIgUcARb3OlWYNbmr1nmqESuxLn16uqI1Ot6WkcICvpkdQ+Bo+R9AP
+ 05xpoXocZtKdNvBu3FNxB/jFkiOcLU2lX7Px1Ijnsjh60qVRy9HOsHCungIKlGcnXLKHmKu0y//5j
+ ds/HnaJsGcHI5JRG7CBJbW+wrwge3trJ1xHJI8prN
-# Testing subtree search...
dn: documentTitle=book1,dc=example,dc=com
objectClass: document
description: abstract1
documentAuthor: cn=Mitya Kovalev,dc=example,dc=com
documentIdentifier: document 2
-# refldap://localhost:9012/dc=example,dc=com??sub
-
dn: dc=example,dc=com
objectClass: organization
objectClass: dcObject
givenName: Torvlobnor
telephoneNumber: 545-4563
+# refldap://localhost:9012/dc=example,dc=com??sub
+
+# Testing subtree search with manageDSAit...
dn: cn=Akakiy Zinberstein,dc=example,dc=com
objectClass: inetOrgPerson
+objectClass: pkiUser
cn: Akakiy Zinberstein
sn: Zinberstein
givenName: Akakiy
+userCertificate;binary:: MIIDazCCAtSgAwIBAgIBAjANBgkqhkiG9w0BAQQFADB3MQswCQYDV
+ QQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEfMB0GA1UEChMWT3BlbkxEQVAgRXhhbXBsZSwgTH
+ RkLjETMBEGA1UEAxMKRXhhbXBsZSBDQTEdMBsGCSqGSIb3DQEJARYOY2FAZXhhbXBsZS5jb20wHhc
+ NMDMxMDE3MTYzMzE5WhcNMDQxMDE2MTYzMzE5WjB+MQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2Fs
+ aWZvcm5pYTEfMB0GA1UEChMWT3BlbkxEQVAgRXhhbXBsZSwgTHRkLjEYMBYGA1UEAxMPVXJzdWxhI
+ EhhbXBzdGVyMR8wHQYJKoZIhvcNAQkBFhB1aGFtQGV4YW1wbGUuY29tMIGfMA0GCSqGSIb3DQEBAQ
+ UAA4GNADCBiQKBgQDuxgp5ELV9LmhxWMpV7qc4028QQT3+zzFDXhruuXE7ji2n3S3ea8bOwDtJh+q
+ nsDe561DhHHHlgIjMKCiDEizYMpxvJPYEXmvp0huRkMgpKZgmel95BSkt6TYmJ0erS3aoimOHLEFi
+ mmnTLolNRMiWqNBvqwobx940PGwUWEePKQIDAQABo4H/MIH8MAkGA1UdEwQCMAAwLAYJYIZIAYb4Q
+ gENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0GA1UdDgQWBBSjI94TbBmuDEeUUO
+ iC37EK0Uf0XjCBoQYDVR0jBIGZMIGWgBRLbyEaNiTSkPlDsFNHLX3hwOaYI6F7pHkwdzELMAkGA1U
+ EBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExHzAdBgNVBAoTFk9wZW5MREFQIEV4YW1wbGUsIEx0
+ ZC4xEzARBgNVBAMTCkV4YW1wbGUgQ0ExHTAbBgkqhkiG9w0BCQEWDmNhQGV4YW1wbGUuY29tggEAM
+ A0GCSqGSIb3DQEBBAUAA4GBAIgUcARb3OlWYNbmr1nmqESuxLn16uqI1Ot6WkcICvpkdQ+Bo+R9AP
+ 05xpoXocZtKdNvBu3FNxB/jFkiOcLU2lX7Px1Ijnsjh60qVRy9HOsHCungIKlGcnXLKHmKu0y//5j
+ ds/HnaJsGcHI5JRG7CBJbW+wrwge3trJ1xHJI8prN
-# Testing subtree search with manageDSAit...
dn: documentTitle=book1,dc=example,dc=com
objectClass: document
description: abstract1
documentAuthor: cn=Mitya Kovalev,dc=example,dc=com
documentIdentifier: document 2
-dn: ou=Referral,dc=example,dc=com
-objectClass: referral
-objectClass: extensibleObject
-ou: Referral
-ref: ldap://localhost:9012/
-
dn: dc=example,dc=com
objectClass: organization
objectClass: dcObject
telephoneNumber: 222-3234
telephoneNumber: 332-2334
+dn: ou=Referral,dc=example,dc=com
+objectClass: referral
+objectClass: extensibleObject
+ou: Referral
+ref: ldap://localhost:9012/
+
dn: cn=Torvlobnor Puzdoy,dc=example,dc=com
objectClass: inetOrgPerson
cn: Torvlobnor Puzdoy
givenName: Torvlobnor
telephoneNumber: 545-4563
-dn: cn=Akakiy Zinberstein,dc=example,dc=com
-objectClass: inetOrgPerson
-cn: Akakiy Zinberstein
-sn: Zinberstein
-givenName: Akakiy
-
# Testing invalid filter...
# Testing exact search...
-# refldap://localhost:9012/dc=example,dc=com??sub
-
dn: cn=Mitya Kovalev,dc=example,dc=com
objectClass: inetOrgPerson
cn: Mitya Kovalev
telephoneNumber: 222-3234
telephoneNumber: 332-2334
-# Testing substrings initial search...
# refldap://localhost:9012/dc=example,dc=com??sub
+# Testing substrings initial search...
dn: cn=Mitya Kovalev,dc=example,dc=com
objectClass: inetOrgPerson
cn: Mitya Kovalev
telephoneNumber: 222-3234
telephoneNumber: 332-2334
-# Testing substrings any search...
# refldap://localhost:9012/dc=example,dc=com??sub
+# Testing substrings any search...
dn: cn=Mitya Kovalev,dc=example,dc=com
objectClass: inetOrgPerson
cn: Mitya Kovalev
telephoneNumber: 222-3234
telephoneNumber: 332-2334
-# Testing substrings final search...
# refldap://localhost:9012/dc=example,dc=com??sub
+# Testing substrings final search...
dn: cn=Mitya Kovalev,dc=example,dc=com
objectClass: inetOrgPerson
cn: Mitya Kovalev
telephoneNumber: 222-3234
telephoneNumber: 332-2334
-# Testing approx search...
# refldap://localhost:9012/dc=example,dc=com??sub
+# Testing approx search...
dn: cn=Mitya Kovalev,dc=example,dc=com
objectClass: inetOrgPerson
cn: Mitya Kovalev
telephoneNumber: 222-3234
telephoneNumber: 332-2334
-# Testing extensible filter search...
# refldap://localhost:9012/dc=example,dc=com??sub
+# Testing extensible filter search...
dn: cn=Mitya Kovalev,dc=example,dc=com
objectClass: inetOrgPerson
cn: Mitya Kovalev
telephoneNumber: 222-3234
telephoneNumber: 332-2334
-# Testing search for telephoneNumber...
# refldap://localhost:9012/dc=example,dc=com??sub
+# Testing search for telephoneNumber...
dn: cn=Mitya Kovalev,dc=example,dc=com
objectClass: inetOrgPerson
cn: Mitya Kovalev
telephoneNumber: 222-3234
telephoneNumber: 332-2334
-# Testing AND search...
# refldap://localhost:9012/dc=example,dc=com??sub
+# Testing AND search...
dn: cn=Mitya Kovalev,dc=example,dc=com
objectClass: inetOrgPerson
cn: Mitya Kovalev
telephoneNumber: 222-3234
telephoneNumber: 332-2334
+# refldap://localhost:9012/dc=example,dc=com??sub
+
# Testing AND search on objectClass...
dn: dc=example,dc=com
objectClass: organization
dc: example
# Testing OR search...
-# refldap://localhost:9012/dc=example,dc=com??sub
-
dn: cn=Mitya Kovalev,dc=example,dc=com
objectClass: inetOrgPerson
cn: Mitya Kovalev
telephoneNumber: 222-3234
telephoneNumber: 332-2334
+# refldap://localhost:9012/dc=example,dc=com??sub
+
# Testing OR search on objectClass...
dn: documentTitle=book1,dc=example,dc=com
objectClass: document
dc: example
# Testing NOT search...
+dn: cn=Akakiy Zinberstein,dc=example,dc=com
+objectClass: inetOrgPerson
+objectClass: pkiUser
+cn: Akakiy Zinberstein
+sn: Zinberstein
+givenName: Akakiy
+userCertificate;binary:: MIIDazCCAtSgAwIBAgIBAjANBgkqhkiG9w0BAQQFADB3MQswCQYDV
+ QQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEfMB0GA1UEChMWT3BlbkxEQVAgRXhhbXBsZSwgTH
+ RkLjETMBEGA1UEAxMKRXhhbXBsZSBDQTEdMBsGCSqGSIb3DQEJARYOY2FAZXhhbXBsZS5jb20wHhc
+ NMDMxMDE3MTYzMzE5WhcNMDQxMDE2MTYzMzE5WjB+MQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2Fs
+ aWZvcm5pYTEfMB0GA1UEChMWT3BlbkxEQVAgRXhhbXBsZSwgTHRkLjEYMBYGA1UEAxMPVXJzdWxhI
+ EhhbXBzdGVyMR8wHQYJKoZIhvcNAQkBFhB1aGFtQGV4YW1wbGUuY29tMIGfMA0GCSqGSIb3DQEBAQ
+ UAA4GNADCBiQKBgQDuxgp5ELV9LmhxWMpV7qc4028QQT3+zzFDXhruuXE7ji2n3S3ea8bOwDtJh+q
+ nsDe561DhHHHlgIjMKCiDEizYMpxvJPYEXmvp0huRkMgpKZgmel95BSkt6TYmJ0erS3aoimOHLEFi
+ mmnTLolNRMiWqNBvqwobx940PGwUWEePKQIDAQABo4H/MIH8MAkGA1UdEwQCMAAwLAYJYIZIAYb4Q
+ gENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0GA1UdDgQWBBSjI94TbBmuDEeUUO
+ iC37EK0Uf0XjCBoQYDVR0jBIGZMIGWgBRLbyEaNiTSkPlDsFNHLX3hwOaYI6F7pHkwdzELMAkGA1U
+ EBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExHzAdBgNVBAoTFk9wZW5MREFQIEV4YW1wbGUsIEx0
+ ZC4xEzARBgNVBAMTCkV4YW1wbGUgQ0ExHTAbBgkqhkiG9w0BCQEWDmNhQGV4YW1wbGUuY29tggEAM
+ A0GCSqGSIb3DQEBBAUAA4GBAIgUcARb3OlWYNbmr1nmqESuxLn16uqI1Ot6WkcICvpkdQ+Bo+R9AP
+ 05xpoXocZtKdNvBu3FNxB/jFkiOcLU2lX7Px1Ijnsjh60qVRy9HOsHCungIKlGcnXLKHmKu0y//5j
+ ds/HnaJsGcHI5JRG7CBJbW+wrwge3trJ1xHJI8prN
+
dn: cn=Torvlobnor Puzdoy,dc=example,dc=com
objectClass: inetOrgPerson
cn: Torvlobnor Puzdoy
givenName: Torvlobnor
telephoneNumber: 545-4563
-dn: cn=Akakiy Zinberstein,dc=example,dc=com
-objectClass: inetOrgPerson
-cn: Akakiy Zinberstein
-sn: Zinberstein
-givenName: Akakiy
-
# Testing NOT search on objectClass...
dn: documentTitle=book1,dc=example,dc=com
objectClass: document
documentAuthor: cn=Mitya Kovalev,dc=example,dc=com
documentIdentifier: document 2
-# refldap://localhost:9012/dc=example,dc=com??sub
-
dn: dc=example,dc=com
objectClass: organization
objectClass: dcObject
o: Example
dc: example
+# refldap://localhost:9012/dc=example,dc=com??sub
+
# Testing NOT search on "auxiliary" objectClass...
+dn: cn=Akakiy Zinberstein,dc=example,dc=com
+objectClass: inetOrgPerson
+objectClass: pkiUser
+cn: Akakiy Zinberstein
+sn: Zinberstein
+givenName: Akakiy
+userCertificate;binary:: MIIDazCCAtSgAwIBAgIBAjANBgkqhkiG9w0BAQQFADB3MQswCQYDV
+ QQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEfMB0GA1UEChMWT3BlbkxEQVAgRXhhbXBsZSwgTH
+ RkLjETMBEGA1UEAxMKRXhhbXBsZSBDQTEdMBsGCSqGSIb3DQEJARYOY2FAZXhhbXBsZS5jb20wHhc
+ NMDMxMDE3MTYzMzE5WhcNMDQxMDE2MTYzMzE5WjB+MQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2Fs
+ aWZvcm5pYTEfMB0GA1UEChMWT3BlbkxEQVAgRXhhbXBsZSwgTHRkLjEYMBYGA1UEAxMPVXJzdWxhI
+ EhhbXBzdGVyMR8wHQYJKoZIhvcNAQkBFhB1aGFtQGV4YW1wbGUuY29tMIGfMA0GCSqGSIb3DQEBAQ
+ UAA4GNADCBiQKBgQDuxgp5ELV9LmhxWMpV7qc4028QQT3+zzFDXhruuXE7ji2n3S3ea8bOwDtJh+q
+ nsDe561DhHHHlgIjMKCiDEizYMpxvJPYEXmvp0huRkMgpKZgmel95BSkt6TYmJ0erS3aoimOHLEFi
+ mmnTLolNRMiWqNBvqwobx940PGwUWEePKQIDAQABo4H/MIH8MAkGA1UdEwQCMAAwLAYJYIZIAYb4Q
+ gENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0GA1UdDgQWBBSjI94TbBmuDEeUUO
+ iC37EK0Uf0XjCBoQYDVR0jBIGZMIGWgBRLbyEaNiTSkPlDsFNHLX3hwOaYI6F7pHkwdzELMAkGA1U
+ EBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExHzAdBgNVBAoTFk9wZW5MREFQIEV4YW1wbGUsIEx0
+ ZC4xEzARBgNVBAMTCkV4YW1wbGUgQ0ExHTAbBgkqhkiG9w0BCQEWDmNhQGV4YW1wbGUuY29tggEAM
+ A0GCSqGSIb3DQEBBAUAA4GBAIgUcARb3OlWYNbmr1nmqESuxLn16uqI1Ot6WkcICvpkdQ+Bo+R9AP
+ 05xpoXocZtKdNvBu3FNxB/jFkiOcLU2lX7Px1Ijnsjh60qVRy9HOsHCungIKlGcnXLKHmKu0y//5j
+ ds/HnaJsGcHI5JRG7CBJbW+wrwge3trJ1xHJI8prN
+
dn: documentTitle=book1,dc=example,dc=com
objectClass: document
description: abstract1
documentAuthor: cn=Mitya Kovalev,dc=example,dc=com
documentIdentifier: document 2
-# refldap://localhost:9012/dc=example,dc=com??sub
-
dn: cn=Mitya Kovalev,dc=example,dc=com
objectClass: inetOrgPerson
cn: Mitya Kovalev
givenName: Torvlobnor
telephoneNumber: 545-4563
-dn: cn=Akakiy Zinberstein,dc=example,dc=com
-objectClass: inetOrgPerson
-cn: Akakiy Zinberstein
-sn: Zinberstein
-givenName: Akakiy
+# refldap://localhost:9012/dc=example,dc=com??sub
# Testing attribute inheritance in filter...
dn: dc=example,dc=com
dc: example
# Testing undefined attribute in filter...
-# refldap://localhost:9012/dc=example,dc=com??sub
-
dn: dc=example,dc=com
objectClass: organization
objectClass: dcObject
o: Example
dc: example
+# refldap://localhost:9012/dc=example,dc=com??sub
+
# Testing objectClass inheritance in filter...
+dn: cn=Akakiy Zinberstein,dc=example,dc=com
+objectClass: inetOrgPerson
+objectClass: pkiUser
+cn: Akakiy Zinberstein
+sn: Zinberstein
+givenName: Akakiy
+userCertificate;binary:: MIIDazCCAtSgAwIBAgIBAjANBgkqhkiG9w0BAQQFADB3MQswCQYDV
+ QQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEfMB0GA1UEChMWT3BlbkxEQVAgRXhhbXBsZSwgTH
+ RkLjETMBEGA1UEAxMKRXhhbXBsZSBDQTEdMBsGCSqGSIb3DQEJARYOY2FAZXhhbXBsZS5jb20wHhc
+ NMDMxMDE3MTYzMzE5WhcNMDQxMDE2MTYzMzE5WjB+MQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2Fs
+ aWZvcm5pYTEfMB0GA1UEChMWT3BlbkxEQVAgRXhhbXBsZSwgTHRkLjEYMBYGA1UEAxMPVXJzdWxhI
+ EhhbXBzdGVyMR8wHQYJKoZIhvcNAQkBFhB1aGFtQGV4YW1wbGUuY29tMIGfMA0GCSqGSIb3DQEBAQ
+ UAA4GNADCBiQKBgQDuxgp5ELV9LmhxWMpV7qc4028QQT3+zzFDXhruuXE7ji2n3S3ea8bOwDtJh+q
+ nsDe561DhHHHlgIjMKCiDEizYMpxvJPYEXmvp0huRkMgpKZgmel95BSkt6TYmJ0erS3aoimOHLEFi
+ mmnTLolNRMiWqNBvqwobx940PGwUWEePKQIDAQABo4H/MIH8MAkGA1UdEwQCMAAwLAYJYIZIAYb4Q
+ gENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0GA1UdDgQWBBSjI94TbBmuDEeUUO
+ iC37EK0Uf0XjCBoQYDVR0jBIGZMIGWgBRLbyEaNiTSkPlDsFNHLX3hwOaYI6F7pHkwdzELMAkGA1U
+ EBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExHzAdBgNVBAoTFk9wZW5MREFQIEV4YW1wbGUsIEx0
+ ZC4xEzARBgNVBAMTCkV4YW1wbGUgQ0ExHTAbBgkqhkiG9w0BCQEWDmNhQGV4YW1wbGUuY29tggEAM
+ A0GCSqGSIb3DQEBBAUAA4GBAIgUcARb3OlWYNbmr1nmqESuxLn16uqI1Ot6WkcICvpkdQ+Bo+R9AP
+ 05xpoXocZtKdNvBu3FNxB/jFkiOcLU2lX7Px1Ijnsjh60qVRy9HOsHCungIKlGcnXLKHmKu0y//5j
+ ds/HnaJsGcHI5JRG7CBJbW+wrwge3trJ1xHJI8prN
+
dn: cn=Mitya Kovalev,dc=example,dc=com
objectClass: inetOrgPerson
cn: Mitya Kovalev
givenName: Torvlobnor
telephoneNumber: 545-4563
-dn: cn=Akakiy Zinberstein,dc=example,dc=com
-objectClass: inetOrgPerson
-cn: Akakiy Zinberstein
-sn: Zinberstein
-givenName: Akakiy
-
# Testing "auxiliary" objectClass in filter...
dn: dc=example,dc=com
objectClass: organization
dc: example
# Testing hasSubordinates in filter...
-# refldap://localhost:9012/dc=example,dc=com??sub
-
dn: dc=example,dc=com
objectClass: organization
objectClass: dcObject
o: Example
dc: example
+# refldap://localhost:9012/dc=example,dc=com??sub
+
# Testing entryUUID in filter...
dn: cn=Mitya Kovalev,dc=example,dc=com
objectClass: inetOrgPerson
telephoneNumber: 332-2334
# Testing attribute inheritance in requested attributes...
-# refldap://localhost:9012/dc=example,dc=com??sub
-
dn: cn=Mitya Kovalev,dc=example,dc=com
cn: Mitya Kovalev
sn: Kovalev
givenName: Mitya
+# refldap://localhost:9012/dc=example,dc=com??sub
+
# Testing objectClass in requested attributes...
+dn: cn=Akakiy Zinberstein,dc=example,dc=com
+objectClass: inetOrgPerson
+objectClass: pkiUser
+
dn: documentTitle=book1,dc=example,dc=com
objectClass: document
dn: documentTitle=book2,dc=example,dc=com
objectClass: document
-# refldap://localhost:9012/dc=example,dc=com??sub
-
dn: dc=example,dc=com
objectClass: organization
objectClass: dcObject
dn: cn=Torvlobnor Puzdoy,dc=example,dc=com
objectClass: inetOrgPerson
-dn: cn=Akakiy Zinberstein,dc=example,dc=com
-objectClass: inetOrgPerson
+# refldap://localhost:9012/dc=example,dc=com??sub
# Testing operational attributes in request...
+dn: cn=Akakiy Zinberstein,dc=example,dc=com
+structuralObjectClass: inetOrgPerson
+entryDN: cn=Akakiy Zinberstein,dc=example,dc=com
+subschemaSubentry: cn=Subschema
+hasSubordinates: FALSE
+entryUUID: 00000001-0000-0003-0000-000000000000
+
dn: documentTitle=book1,dc=example,dc=com
structuralObjectClass: document
entryDN: documentTitle=book1,dc=example,dc=com
hasSubordinates: FALSE
entryUUID: 00000002-0000-0002-0000-000000000000
-# refldap://localhost:9012/dc=example,dc=com??sub
-
dn: dc=example,dc=com
structuralObjectClass: organization
entryDN: dc=example,dc=com
hasSubordinates: FALSE
entryUUID: 00000001-0000-0002-0000-000000000000
-dn: cn=Akakiy Zinberstein,dc=example,dc=com
-structuralObjectClass: inetOrgPerson
-entryDN: cn=Akakiy Zinberstein,dc=example,dc=com
-subschemaSubentry: cn=Subschema
-hasSubordinates: FALSE
-entryUUID: 00000001-0000-0003-0000-000000000000
+# refldap://localhost:9012/dc=example,dc=com??sub
# Using ldapsearch to retrieve all the entries...
dn: cn=Akakiy Zinberstein,dc=example,dc=com
objectClass: inetOrgPerson
+objectClass: pkiUser
cn: Akakiy Zinberstein
sn: Zinberstein
givenName: Akakiy
+userCertificate;binary:: MIIDazCCAtSgAwIBAgIBAjANBgkqhkiG9w0BAQQFADB3MQswCQYDV
+ QQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEfMB0GA1UEChMWT3BlbkxEQVAgRXhhbXBsZSwgTH
+ RkLjETMBEGA1UEAxMKRXhhbXBsZSBDQTEdMBsGCSqGSIb3DQEJARYOY2FAZXhhbXBsZS5jb20wHhc
+ NMDMxMDE3MTYzMzE5WhcNMDQxMDE2MTYzMzE5WjB+MQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2Fs
+ aWZvcm5pYTEfMB0GA1UEChMWT3BlbkxEQVAgRXhhbXBsZSwgTHRkLjEYMBYGA1UEAxMPVXJzdWxhI
+ EhhbXBzdGVyMR8wHQYJKoZIhvcNAQkBFhB1aGFtQGV4YW1wbGUuY29tMIGfMA0GCSqGSIb3DQEBAQ
+ UAA4GNADCBiQKBgQDuxgp5ELV9LmhxWMpV7qc4028QQT3+zzFDXhruuXE7ji2n3S3ea8bOwDtJh+q
+ nsDe561DhHHHlgIjMKCiDEizYMpxvJPYEXmvp0huRkMgpKZgmel95BSkt6TYmJ0erS3aoimOHLEFi
+ mmnTLolNRMiWqNBvqwobx940PGwUWEePKQIDAQABo4H/MIH8MAkGA1UdEwQCMAAwLAYJYIZIAYb4Q
+ gENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0GA1UdDgQWBBSjI94TbBmuDEeUUO
+ iC37EK0Uf0XjCBoQYDVR0jBIGZMIGWgBRLbyEaNiTSkPlDsFNHLX3hwOaYI6F7pHkwdzELMAkGA1U
+ EBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExHzAdBgNVBAoTFk9wZW5MREFQIEV4YW1wbGUsIEx0
+ ZC4xEzARBgNVBAMTCkV4YW1wbGUgQ0ExHTAbBgkqhkiG9w0BCQEWDmNhQGV4YW1wbGUuY29tggEAM
+ A0GCSqGSIb3DQEBBAUAA4GBAIgUcARb3OlWYNbmr1nmqESuxLn16uqI1Ot6WkcICvpkdQ+Bo+R9AP
+ 05xpoXocZtKdNvBu3FNxB/jFkiOcLU2lX7Px1Ijnsjh60qVRy9HOsHCungIKlGcnXLKHmKu0y//5j
+ ds/HnaJsGcHI5JRG7CBJbW+wrwge3trJ1xHJI8prN
dn: documentTitle=book1,dc=example,dc=com
objectClass: document
# Using ldapsearch to retrieve all the entries...
dn: cn=Akakiy Zinberstein,dc=example,dc=com
objectClass: inetOrgPerson
+objectClass: pkiUser
cn: Akakiy Zinberstein
sn: Zinberstein
givenName: Akakiy
+userCertificate;binary:: MIIDazCCAtSgAwIBAgIBAjANBgkqhkiG9w0BAQQFADB3MQswCQYDV
+ QQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEfMB0GA1UEChMWT3BlbkxEQVAgRXhhbXBsZSwgTH
+ RkLjETMBEGA1UEAxMKRXhhbXBsZSBDQTEdMBsGCSqGSIb3DQEJARYOY2FAZXhhbXBsZS5jb20wHhc
+ NMDMxMDE3MTYzMzE5WhcNMDQxMDE2MTYzMzE5WjB+MQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2Fs
+ aWZvcm5pYTEfMB0GA1UEChMWT3BlbkxEQVAgRXhhbXBsZSwgTHRkLjEYMBYGA1UEAxMPVXJzdWxhI
+ EhhbXBzdGVyMR8wHQYJKoZIhvcNAQkBFhB1aGFtQGV4YW1wbGUuY29tMIGfMA0GCSqGSIb3DQEBAQ
+ UAA4GNADCBiQKBgQDuxgp5ELV9LmhxWMpV7qc4028QQT3+zzFDXhruuXE7ji2n3S3ea8bOwDtJh+q
+ nsDe561DhHHHlgIjMKCiDEizYMpxvJPYEXmvp0huRkMgpKZgmel95BSkt6TYmJ0erS3aoimOHLEFi
+ mmnTLolNRMiWqNBvqwobx940PGwUWEePKQIDAQABo4H/MIH8MAkGA1UdEwQCMAAwLAYJYIZIAYb4Q
+ gENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0GA1UdDgQWBBSjI94TbBmuDEeUUO
+ iC37EK0Uf0XjCBoQYDVR0jBIGZMIGWgBRLbyEaNiTSkPlDsFNHLX3hwOaYI6F7pHkwdzELMAkGA1U
+ EBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExHzAdBgNVBAoTFk9wZW5MREFQIEV4YW1wbGUsIEx0
+ ZC4xEzARBgNVBAMTCkV4YW1wbGUgQ0ExHTAbBgkqhkiG9w0BCQEWDmNhQGV4YW1wbGUuY29tggEAM
+ A0GCSqGSIb3DQEBBAUAA4GBAIgUcARb3OlWYNbmr1nmqESuxLn16uqI1Ot6WkcICvpkdQ+Bo+R9AP
+ 05xpoXocZtKdNvBu3FNxB/jFkiOcLU2lX7Px1Ijnsjh60qVRy9HOsHCungIKlGcnXLKHmKu0y//5j
+ ds/HnaJsGcHI5JRG7CBJbW+wrwge3trJ1xHJI8prN
dn: o=An Org,dc=example,dc=com
objectClass: organization
# Using ldapsearch to retrieve all the entries...
dn: cn=Akakiy Zinberstein,dc=example,dc=com
objectClass: inetOrgPerson
+objectClass: pkiUser
cn: Akakiy Zinberstein
sn: Zinberstein
givenName: Akakiy
+userCertificate;binary:: MIIDazCCAtSgAwIBAgIBAjANBgkqhkiG9w0BAQQFADB3MQswCQYDV
+ QQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEfMB0GA1UEChMWT3BlbkxEQVAgRXhhbXBsZSwgTH
+ RkLjETMBEGA1UEAxMKRXhhbXBsZSBDQTEdMBsGCSqGSIb3DQEJARYOY2FAZXhhbXBsZS5jb20wHhc
+ NMDMxMDE3MTYzMzE5WhcNMDQxMDE2MTYzMzE5WjB+MQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2Fs
+ aWZvcm5pYTEfMB0GA1UEChMWT3BlbkxEQVAgRXhhbXBsZSwgTHRkLjEYMBYGA1UEAxMPVXJzdWxhI
+ EhhbXBzdGVyMR8wHQYJKoZIhvcNAQkBFhB1aGFtQGV4YW1wbGUuY29tMIGfMA0GCSqGSIb3DQEBAQ
+ UAA4GNADCBiQKBgQDuxgp5ELV9LmhxWMpV7qc4028QQT3+zzFDXhruuXE7ji2n3S3ea8bOwDtJh+q
+ nsDe561DhHHHlgIjMKCiDEizYMpxvJPYEXmvp0huRkMgpKZgmel95BSkt6TYmJ0erS3aoimOHLEFi
+ mmnTLolNRMiWqNBvqwobx940PGwUWEePKQIDAQABo4H/MIH8MAkGA1UdEwQCMAAwLAYJYIZIAYb4Q
+ gENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0GA1UdDgQWBBSjI94TbBmuDEeUUO
+ iC37EK0Uf0XjCBoQYDVR0jBIGZMIGWgBRLbyEaNiTSkPlDsFNHLX3hwOaYI6F7pHkwdzELMAkGA1U
+ EBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExHzAdBgNVBAoTFk9wZW5MREFQIEV4YW1wbGUsIEx0
+ ZC4xEzARBgNVBAMTCkV4YW1wbGUgQ0ExHTAbBgkqhkiG9w0BCQEWDmNhQGV4YW1wbGUuY29tggEAM
+ A0GCSqGSIb3DQEBBAUAA4GBAIgUcARb3OlWYNbmr1nmqESuxLn16uqI1Ot6WkcICvpkdQ+Bo+R9AP
+ 05xpoXocZtKdNvBu3FNxB/jFkiOcLU2lX7Px1Ijnsjh60qVRy9HOsHCungIKlGcnXLKHmKu0y//5j
+ ds/HnaJsGcHI5JRG7CBJbW+wrwge3trJ1xHJI8prN
dn: o=An Org,dc=example,dc=com
objectClass: organization
# Using ldapsearch to retrieve all the entries...
dn: cn=Akakiy Zinberstein,dc=example,dc=com
objectClass: inetOrgPerson
+objectClass: pkiUser
cn: Akakiy Zinberstein
sn: Zinberstein
givenName: Akakiy
+userCertificate;binary:: MIIDazCCAtSgAwIBAgIBAjANBgkqhkiG9w0BAQQFADB3MQswCQYDV
+ QQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEfMB0GA1UEChMWT3BlbkxEQVAgRXhhbXBsZSwgTH
+ RkLjETMBEGA1UEAxMKRXhhbXBsZSBDQTEdMBsGCSqGSIb3DQEJARYOY2FAZXhhbXBsZS5jb20wHhc
+ NMDMxMDE3MTYzMzE5WhcNMDQxMDE2MTYzMzE5WjB+MQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2Fs
+ aWZvcm5pYTEfMB0GA1UEChMWT3BlbkxEQVAgRXhhbXBsZSwgTHRkLjEYMBYGA1UEAxMPVXJzdWxhI
+ EhhbXBzdGVyMR8wHQYJKoZIhvcNAQkBFhB1aGFtQGV4YW1wbGUuY29tMIGfMA0GCSqGSIb3DQEBAQ
+ UAA4GNADCBiQKBgQDuxgp5ELV9LmhxWMpV7qc4028QQT3+zzFDXhruuXE7ji2n3S3ea8bOwDtJh+q
+ nsDe561DhHHHlgIjMKCiDEizYMpxvJPYEXmvp0huRkMgpKZgmel95BSkt6TYmJ0erS3aoimOHLEFi
+ mmnTLolNRMiWqNBvqwobx940PGwUWEePKQIDAQABo4H/MIH8MAkGA1UdEwQCMAAwLAYJYIZIAYb4Q
+ gENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0GA1UdDgQWBBSjI94TbBmuDEeUUO
+ iC37EK0Uf0XjCBoQYDVR0jBIGZMIGWgBRLbyEaNiTSkPlDsFNHLX3hwOaYI6F7pHkwdzELMAkGA1U
+ EBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExHzAdBgNVBAoTFk9wZW5MREFQIEV4YW1wbGUsIEx0
+ ZC4xEzARBgNVBAMTCkV4YW1wbGUgQ0ExHTAbBgkqhkiG9w0BCQEWDmNhQGV4YW1wbGUuY29tggEAM
+ A0GCSqGSIb3DQEBBAUAA4GBAIgUcARb3OlWYNbmr1nmqESuxLn16uqI1Ot6WkcICvpkdQ+Bo+R9AP
+ 05xpoXocZtKdNvBu3FNxB/jFkiOcLU2lX7Px1Ijnsjh60qVRy9HOsHCungIKlGcnXLKHmKu0y//5j
+ ds/HnaJsGcHI5JRG7CBJbW+wrwge3trJ1xHJI8prN
dn: o=An Org,dc=example,dc=com
objectClass: organization
# Using ldapsearch to retrieve all the entries...
dn: cn=Akakiy Zinberstein,dc=example,dc=com
objectClass: inetOrgPerson
+objectClass: pkiUser
cn: Akakiy Zinberstein
sn: Zinberstein
givenName: Akakiy
+userCertificate;binary:: MIIDazCCAtSgAwIBAgIBAjANBgkqhkiG9w0BAQQFADB3MQswCQYDV
+ QQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEfMB0GA1UEChMWT3BlbkxEQVAgRXhhbXBsZSwgTH
+ RkLjETMBEGA1UEAxMKRXhhbXBsZSBDQTEdMBsGCSqGSIb3DQEJARYOY2FAZXhhbXBsZS5jb20wHhc
+ NMDMxMDE3MTYzMzE5WhcNMDQxMDE2MTYzMzE5WjB+MQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2Fs
+ aWZvcm5pYTEfMB0GA1UEChMWT3BlbkxEQVAgRXhhbXBsZSwgTHRkLjEYMBYGA1UEAxMPVXJzdWxhI
+ EhhbXBzdGVyMR8wHQYJKoZIhvcNAQkBFhB1aGFtQGV4YW1wbGUuY29tMIGfMA0GCSqGSIb3DQEBAQ
+ UAA4GNADCBiQKBgQDuxgp5ELV9LmhxWMpV7qc4028QQT3+zzFDXhruuXE7ji2n3S3ea8bOwDtJh+q
+ nsDe561DhHHHlgIjMKCiDEizYMpxvJPYEXmvp0huRkMgpKZgmel95BSkt6TYmJ0erS3aoimOHLEFi
+ mmnTLolNRMiWqNBvqwobx940PGwUWEePKQIDAQABo4H/MIH8MAkGA1UdEwQCMAAwLAYJYIZIAYb4Q
+ gENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0GA1UdDgQWBBSjI94TbBmuDEeUUO
+ iC37EK0Uf0XjCBoQYDVR0jBIGZMIGWgBRLbyEaNiTSkPlDsFNHLX3hwOaYI6F7pHkwdzELMAkGA1U
+ EBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExHzAdBgNVBAoTFk9wZW5MREFQIEV4YW1wbGUsIEx0
+ ZC4xEzARBgNVBAMTCkV4YW1wbGUgQ0ExHTAbBgkqhkiG9w0BCQEWDmNhQGV4YW1wbGUuY29tggEAM
+ A0GCSqGSIb3DQEBBAUAA4GBAIgUcARb3OlWYNbmr1nmqESuxLn16uqI1Ot6WkcICvpkdQ+Bo+R9AP
+ 05xpoXocZtKdNvBu3FNxB/jFkiOcLU2lX7Px1Ijnsjh60qVRy9HOsHCungIKlGcnXLKHmKu0y//5j
+ ds/HnaJsGcHI5JRG7CBJbW+wrwge3trJ1xHJI8prN
dn: dc=example,dc=com
objectClass: organization
# Using ldapsearch to retrieve all the entries...
dn: cn=Akakiy Zinberstein,dc=example,dc=com
objectClass: inetOrgPerson
+objectClass: pkiUser
cn: Akakiy Zinberstein
sn: Zinberstein
givenName: Akakiy
+userCertificate;binary:: MIIDazCCAtSgAwIBAgIBAjANBgkqhkiG9w0BAQQFADB3MQswCQYDV
+ QQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEfMB0GA1UEChMWT3BlbkxEQVAgRXhhbXBsZSwgTH
+ RkLjETMBEGA1UEAxMKRXhhbXBsZSBDQTEdMBsGCSqGSIb3DQEJARYOY2FAZXhhbXBsZS5jb20wHhc
+ NMDMxMDE3MTYzMzE5WhcNMDQxMDE2MTYzMzE5WjB+MQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2Fs
+ aWZvcm5pYTEfMB0GA1UEChMWT3BlbkxEQVAgRXhhbXBsZSwgTHRkLjEYMBYGA1UEAxMPVXJzdWxhI
+ EhhbXBzdGVyMR8wHQYJKoZIhvcNAQkBFhB1aGFtQGV4YW1wbGUuY29tMIGfMA0GCSqGSIb3DQEBAQ
+ UAA4GNADCBiQKBgQDuxgp5ELV9LmhxWMpV7qc4028QQT3+zzFDXhruuXE7ji2n3S3ea8bOwDtJh+q
+ nsDe561DhHHHlgIjMKCiDEizYMpxvJPYEXmvp0huRkMgpKZgmel95BSkt6TYmJ0erS3aoimOHLEFi
+ mmnTLolNRMiWqNBvqwobx940PGwUWEePKQIDAQABo4H/MIH8MAkGA1UdEwQCMAAwLAYJYIZIAYb4Q
+ gENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0GA1UdDgQWBBSjI94TbBmuDEeUUO
+ iC37EK0Uf0XjCBoQYDVR0jBIGZMIGWgBRLbyEaNiTSkPlDsFNHLX3hwOaYI6F7pHkwdzELMAkGA1U
+ EBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExHzAdBgNVBAoTFk9wZW5MREFQIEV4YW1wbGUsIEx0
+ ZC4xEzARBgNVBAMTCkV4YW1wbGUgQ0ExHTAbBgkqhkiG9w0BCQEWDmNhQGV4YW1wbGUuY29tggEAM
+ A0GCSqGSIb3DQEBBAUAA4GBAIgUcARb3OlWYNbmr1nmqESuxLn16uqI1Ot6WkcICvpkdQ+Bo+R9AP
+ 05xpoXocZtKdNvBu3FNxB/jFkiOcLU2lX7Px1Ijnsjh60qVRy9HOsHCungIKlGcnXLKHmKu0y//5j
+ ds/HnaJsGcHI5JRG7CBJbW+wrwge3trJ1xHJI8prN
dn: dc=example,dc=com
objectClass: organization
name 'testPerson' sup OpenLDAPperson
may testTime )
-objectClass ( 1.3.6.1.3.1.4203.666.3.16
+objectClass ( 1.3.6.1.4.1.4203.666.3.17
name 'obsoletePerson'
obsolete auxiliary
may ( testObsolete ) )
#include <stdio.h>
-#include <ac/stdlib.h>
+#include "ac/stdlib.h"
-#include <ac/ctype.h>
-#include <ac/param.h>
-#include <ac/socket.h>
-#include <ac/string.h>
-#include <ac/unistd.h>
-#include <ac/wait.h>
+#include "ac/ctype.h"
+#include "ac/param.h"
+#include "ac/socket.h"
+#include "ac/string.h"
+#include "ac/unistd.h"
+#include "ac/wait.h"
-#include <ldap.h>
-#include <lutil.h>
+#include "ldap.h"
+#include "lutil.h"
#include "slapd-common.h"
#include <stdio.h>
-#include <ac/stdlib.h>
-#include <ac/time.h>
-
-#include <ac/ctype.h>
-#include <ac/param.h>
-#include <ac/socket.h>
-#include <ac/string.h>
-#include <ac/unistd.h>
-#include <ac/wait.h>
-#include <ac/time.h>
-
-#include <ldap.h>
-#include <lutil.h>
-#include <lber_pvt.h>
-#include <ldap_pvt.h>
+#include "ac/stdlib.h"
+#include "ac/time.h"
+
+#include "ac/ctype.h"
+#include "ac/param.h"
+#include "ac/socket.h"
+#include "ac/string.h"
+#include "ac/unistd.h"
+#include "ac/wait.h"
+#include "ac/time.h"
+
+#include "ldap.h"
+#include "lutil.h"
+#include "lber_pvt.h"
+#include "ldap_pvt.h"
#include "slapd-common.h"
#include <stdio.h>
-#include <ac/stdlib.h>
-#include <ac/unistd.h>
-#include <ac/string.h>
-#include <ac/errno.h>
+#include "ac/stdlib.h"
+#include "ac/unistd.h"
+#include "ac/string.h"
+#include "ac/errno.h"
-#include <ldap.h>
+#include "ldap.h"
#include "ldap_pvt.h"
#include "slapd-common.h"
#include <stdio.h>
-#include <ac/stdlib.h>
+#include "ac/stdlib.h"
-#include <ac/ctype.h>
-#include <ac/param.h>
-#include <ac/socket.h>
-#include <ac/string.h>
-#include <ac/unistd.h>
-#include <ac/wait.h>
+#include "ac/ctype.h"
+#include "ac/param.h"
+#include "ac/socket.h"
+#include "ac/string.h"
+#include "ac/unistd.h"
+#include "ac/wait.h"
-#include <ldap.h>
-#include <lutil.h>
+#include "ldap.h"
+#include "lutil.h"
#include "slapd-common.h"
#include <stdio.h>
-#include <ac/stdlib.h>
+#include "ac/stdlib.h"
-#include <ac/ctype.h>
-#include <ac/param.h>
-#include <ac/socket.h>
-#include <ac/string.h>
-#include <ac/unistd.h>
-#include <ac/wait.h>
+#include "ac/ctype.h"
+#include "ac/param.h"
+#include "ac/socket.h"
+#include "ac/string.h"
+#include "ac/unistd.h"
+#include "ac/wait.h"
-#include <ldap.h>
-#include <lutil.h>
+#include "ldap.h"
+#include "lutil.h"
#include "slapd-common.h"
#include <stdio.h>
-#include <ac/stdlib.h>
+#include "ac/stdlib.h"
-#include <ac/ctype.h>
-#include <ac/param.h>
-#include <ac/socket.h>
-#include <ac/string.h>
-#include <ac/unistd.h>
-#include <ac/wait.h>
+#include "ac/ctype.h"
+#include "ac/param.h"
+#include "ac/socket.h"
+#include "ac/string.h"
+#include "ac/unistd.h"
+#include "ac/wait.h"
-#include <ldap.h>
-#include <lutil.h>
+#include "ldap.h"
+#include "lutil.h"
+
+#include "ldap_pvt.h"
#include "slapd-common.h"
static void
do_read( char *uri, char *manager, struct berval *passwd,
- char *entry, LDAP **ld, int noattrs, int nobind, int maxloop,
+ char *entry, LDAP **ld,
+ char **attrs, int noattrs, int nobind, int maxloop,
int maxretries, int delay, int force, int chaserefs );
static void
do_random( char *uri, char *manager, struct berval *passwd,
- char *sbase, char *filter, int noattrs, int nobind,
+ char *sbase, char *filter, char **attrs, int noattrs, int nobind,
int innerloop, int maxretries, int delay, int force, int chaserefs );
static void
"[-l <loops>] "
"[-L <outerloops>] "
"[-r <maxretries>] "
- "[-t <delay>]\n",
+ "[-t <delay>] "
+ "[-T <attrs>] "
+ "[<attrs>] "
+ "\n",
name );
exit( EXIT_FAILURE );
}
int delay = 0;
int force = 0;
int chaserefs = 0;
+ char *srchattrs[] = { "1.1", NULL };
+ char **attrs = srchattrs;
int noattrs = 0;
int nobind = 0;
/* by default, tolerate referrals and no such object */
tester_ignore_str2errlist( "REFERRAL,NO_SUCH_OBJECT" );
- while ( (i = getopt( argc, argv, "ACD:e:Ff:H:h:i:L:l:p:r:t:w:" )) != EOF ) {
+ while ( (i = getopt( argc, argv, "ACD:e:Ff:H:h:i:L:l:p:r:t:T:w:" )) != EOF ) {
switch ( i ) {
case 'A':
noattrs++;
}
break;
+ case 'T':
+ attrs = ldap_str2charray( optarg, "," );
+ if ( attrs == NULL ) {
+ usage( argv[0] );
+ }
+ break;
+
default:
usage( argv[0] );
break;
exit( EXIT_FAILURE );
}
+ if ( argv[optind] != NULL ) {
+ attrs = &argv[optind];
+ }
+
uri = tester_uri( uri, host, port );
for ( i = 0; i < outerloops; i++ ) {
if ( filter != NULL ) {
- do_random( uri, manager, &passwd, entry, filter,
+ do_random( uri, manager, &passwd, entry, filter, attrs,
noattrs, nobind, loops, retries, delay, force,
chaserefs );
} else {
- do_read( uri, manager, &passwd, entry, NULL, noattrs, nobind,
- loops, retries, delay, force, chaserefs );
+ do_read( uri, manager, &passwd, entry, NULL, attrs,
+ noattrs, nobind, loops, retries, delay, force,
+ chaserefs );
}
}
static void
do_random( char *uri, char *manager, struct berval *passwd,
- char *sbase, char *filter, int noattrs, int nobind,
+ char *sbase, char *filter, char **srchattrs, int noattrs, int nobind,
int innerloop, int maxretries, int delay, int force, int chaserefs )
{
LDAP *ld = NULL;
int r = ((double)nvalues)*rand()/(RAND_MAX + 1.0);
do_read( uri, manager, passwd, values[ r ], &ld,
- noattrs, nobind, 1, maxretries, delay, force,
- chaserefs );
+ srchattrs, noattrs, nobind, 1, maxretries,
+ delay, force, chaserefs );
}
free( values );
break;
static void
do_read( char *uri, char *manager, struct berval *passwd, char *entry,
- LDAP **ldp, int noattrs, int nobind, int maxloop,
+ LDAP **ldp, char **attrs, int noattrs, int nobind, int maxloop,
int maxretries, int delay, int force, int chaserefs )
{
LDAP *ld = ldp ? *ldp : NULL;
int i = 0, do_retry = maxretries;
- char *attrs[] = { "1.1", NULL };
int rc = LDAP_SUCCESS;
int version = LDAP_VERSION3;
case LDAP_UNAVAILABLE:
if ( do_retry > 0 ) {
ldap_unbind_ext( ld, NULL, NULL );
+ ld = NULL;
do_retry--;
if ( delay != 0 ) {
sleep( delay );
#include <stdio.h>
-#include <ac/stdlib.h>
+#include "ac/stdlib.h"
-#include <ac/ctype.h>
-#include <ac/param.h>
-#include <ac/socket.h>
-#include <ac/string.h>
-#include <ac/unistd.h>
-#include <ac/wait.h>
+#include "ac/ctype.h"
+#include "ac/param.h"
+#include "ac/socket.h"
+#include "ac/string.h"
+#include "ac/unistd.h"
+#include "ac/wait.h"
-#include <ldap.h>
-#include <lutil.h>
+#include "ldap.h"
+#include "lutil.h"
+#include "ldap_pvt.h"
#include "slapd-common.h"
static void
do_search( char *uri, char *manager, struct berval *passwd,
- char *sbase, char *filter, LDAP **ldp, int noattrs, int nobind,
+ char *sbase, int scope, char *filter, LDAP **ldp,
+ char **attrs, int noattrs, int nobind,
int innerloop, int maxretries, int delay, int force, int chaserefs );
static void
do_random( char *uri, char *manager, struct berval *passwd,
- char *sbase, char *filter, char *attr, int noattrs, int nobind,
+ char *sbase, int scope, char *filter, char *attr,
+ char **attrs, int noattrs, int nobind,
int innerloop, int maxretries, int delay, int force, int chaserefs );
static void
-usage( char *name )
+usage( char *name, char o )
{
+ if ( o != '\0' ) {
+ fprintf( stderr, "unknown/incorrect option \"%c\"\n", o );
+ }
+
fprintf( stderr,
"usage: %s "
"-H <uri> | ([-h <host>] -p <port>) "
"-D <manager> "
"-w <passwd> "
"-b <searchbase> "
+ "-s <scope> "
"-f <searchfilter> "
"[-a <attr>] "
"[-A] "
"[-l <loops>] "
"[-L <outerloops>] "
"[-r <maxretries>] "
- "[-t <delay>]\n",
+ "[-t <delay>] "
+ "[<attrs>] "
+ "\n",
name );
exit( EXIT_FAILURE );
}
char *manager = NULL;
struct berval passwd = { 0, NULL };
char *sbase = NULL;
+ int scope = LDAP_SCOPE_SUBTREE;
char *filter = NULL;
char *attr = NULL;
+ char *srchattrs[] = { "cn", "sn", NULL };
+ char **attrs = srchattrs;
int loops = LOOPS;
int outerloops = 1;
int retries = RETRIES;
/* by default, tolerate referrals and no such object */
tester_ignore_str2errlist( "REFERRAL,NO_SUCH_OBJECT" );
- while ( ( i = getopt( argc, argv, "Aa:b:CD:f:FH:h:i:l:L:Np:r:t:w:" ) ) != EOF )
+ while ( ( i = getopt( argc, argv, "Aa:b:CD:f:FH:h:i:l:L:Np:r:s:t:T:w:" ) ) != EOF )
{
switch ( i ) {
case 'A':
case 'p': /* the servers port */
if ( lutil_atoi( &port, optarg ) != 0 ) {
- usage( argv[0] );
+ usage( argv[0], i );
}
break;
case 'l': /* number of loops */
if ( lutil_atoi( &loops, optarg ) != 0 ) {
- usage( argv[0] );
+ usage( argv[0], i );
}
break;
case 'L': /* number of loops */
if ( lutil_atoi( &outerloops, optarg ) != 0 ) {
- usage( argv[0] );
+ usage( argv[0], i );
}
break;
case 'r': /* number of retries */
if ( lutil_atoi( &retries, optarg ) != 0 ) {
- usage( argv[0] );
+ usage( argv[0], i );
}
break;
case 't': /* delay in seconds */
if ( lutil_atoi( &delay, optarg ) != 0 ) {
- usage( argv[0] );
+ usage( argv[0], i );
+ }
+ break;
+
+ case 'T':
+ attrs = ldap_str2charray( optarg, "," );
+ if ( attrs == NULL ) {
+ usage( argv[0], i );
+ }
+ break;
+
+ case 's':
+ scope = ldap_pvt_str2scope( optarg );
+ if ( scope == -1 ) {
+ usage( argv[0], i );
}
break;
default:
- usage( argv[0] );
+ usage( argv[0], i );
break;
}
}
if (( sbase == NULL ) || ( filter == NULL ) || ( port == -1 && uri == NULL ))
- usage( argv[0] );
+ usage( argv[0], '\0' );
if ( *filter == '\0' ) {
}
+ if ( argv[optind] != NULL ) {
+ attrs = &argv[optind];
+ }
+
uri = tester_uri( uri, host, port );
for ( i = 0; i < outerloops; i++ ) {
if ( attr != NULL ) {
- do_random( uri, manager, &passwd, sbase, filter, attr,
- noattrs, nobind, loops, retries, delay, force, chaserefs );
+ do_random( uri, manager, &passwd,
+ sbase, scope, filter, attr,
+ attrs, noattrs, nobind,
+ loops, retries, delay, force, chaserefs );
} else {
- do_search( uri, manager, &passwd, sbase, filter, NULL,
- noattrs, nobind, loops, retries, delay, force, chaserefs );
+ do_search( uri, manager, &passwd,
+ sbase, scope, filter, NULL,
+ attrs, noattrs, nobind,
+ loops, retries, delay, force, chaserefs );
}
}
static void
do_random( char *uri, char *manager, struct berval *passwd,
- char *sbase, char *filter, char *attr, int noattrs, int nobind,
+ char *sbase, int scope, char *filter, char *attr,
+ char **srchattrs, int noattrs, int nobind,
int innerloop, int maxretries, int delay, int force, int chaserefs )
{
LDAP *ld = NULL;
snprintf( buf, sizeof( buf ), "(%s=%s)", attr, values[ r ] );
- do_search( uri, manager, passwd, sbase, buf, &ld, noattrs, nobind,
- 1, maxretries, delay, force, chaserefs );
+ do_search( uri, manager, passwd,
+ sbase, scope, buf, &ld,
+ srchattrs, noattrs, nobind,
+ 1, maxretries, delay, force, chaserefs );
}
break;
static void
do_search( char *uri, char *manager, struct berval *passwd,
- char *sbase, char *filter, LDAP **ldp, int noattrs, int nobind,
+ char *sbase, int scope, char *filter, LDAP **ldp,
+ char **attrs, int noattrs, int nobind,
int innerloop, int maxretries, int delay, int force, int chaserefs )
{
LDAP *ld = ldp ? *ldp : NULL;
int i = 0, do_retry = maxretries;
- char *attrs[] = { "cn", "sn", NULL };
int rc = LDAP_SUCCESS;
int version = LDAP_VERSION3;
char buf[ BUFSIZ ];
chaserefs ? LDAP_OPT_ON : LDAP_OPT_OFF );
if ( do_retry == maxretries ) {
- fprintf( stderr, "PID=%ld - Search(%d): base=\"%s\", filter=\"%s\".\n",
- (long) pid, innerloop, sbase, filter );
+ fprintf( stderr,
+ "PID=%ld - Search(%d): "
+ "base=\"%s\" scope=%s filter=\"%s\" "
+ "attrs=%s%s.\n",
+ (long) pid, innerloop,
+ sbase, ldap_pvt_scope2str( scope ), filter,
+ attrs[0], attrs[1] ? " (more...)" : "" );
}
if ( nobind == 0 ) {
case LDAP_UNAVAILABLE:
if ( do_retry > 0 ) {
ldap_unbind_ext( ld, NULL, NULL );
+ ld = NULL;
do_retry--;
if ( delay != 0 ) {
sleep( delay );
for ( ; i < innerloop; i++ ) {
LDAPMessage *res = NULL;
- rc = ldap_search_ext_s( ld, sbase, LDAP_SCOPE_SUBTREE,
+ rc = ldap_search_ext_s( ld, sbase, scope,
filter, attrs, noattrs, NULL, NULL,
NULL, LDAP_NO_LIMIT, &res );
if ( res != NULL ) {
#include <stdio.h>
-#include <ac/stdlib.h>
+#include "ac/stdlib.h"
-#include <ac/ctype.h>
-#include <ac/dirent.h>
-#include <ac/param.h>
-#include <ac/socket.h>
-#include <ac/string.h>
-#include <ac/unistd.h>
-#include <ac/wait.h>
+#include "ac/ctype.h"
+#include "ac/dirent.h"
+#include "ac/param.h"
+#include "ac/socket.h"
+#include "ac/string.h"
+#include "ac/unistd.h"
+#include "ac/wait.h"
#include "ldap_defaults.h"
#define TBINDFILE "do_bind.0"
static char *get_file_name( char *dirname, char *filename );
-static int get_search_filters( char *filename, char *filters[], char *attrs[], char *bases[] );
+static int get_search_filters( char *filename, char *filters[], char *attrs[], char *bases[], LDAPURLDesc *luds[] );
static int get_read_entries( char *filename, char *entries[], char *filters[] );
static void fork_child( char *prog, char **args );
static void wait4kids( int nkidval );
char *sreqs[MAXREQS];
char *sattrs[MAXREQS];
char *sbase[MAXREQS];
+ LDAPURLDesc *slud[MAXREQS];
int snum = 0;
char *sargs[MAXARGS];
int sanum;
+ int sextra_args = 0;
char scmd[MAXPATHLEN];
/* static so that its address can be used in initializer below. */
static char sloops[] = "18446744073709551615UL";
char *rargs[MAXARGS];
char *rflts[MAXREQS];
int ranum;
+ int rextra_args = 0;
char rcmd[MAXPATHLEN];
static char rloops[] = "18446744073709551615UL";
/* addel */
passwd = pw.bv_val;
}
+ if ( !sfile && !rfile && !nfile && !mfile && !bfile && !anum ) {
+ fprintf( stderr, "no data files found.\n" );
+ exit( EXIT_FAILURE );
+ }
+
/* look for search requests */
if ( sfile ) {
- snum = get_search_filters( sfile, sreqs, sattrs, sbase );
+ snum = get_search_filters( sfile, sreqs, sattrs, sbase, slud );
+ if ( snum < 0 ) {
+ fprintf( stderr,
+ "unable to parse file \"%s\" line %d\n",
+ sfile, -2*(snum + 1));
+ exit( EXIT_FAILURE );
+ }
}
/* look for read requests */
if ( rfile ) {
rnum = get_read_entries( rfile, rreqs, rflts );
+ if ( rnum < 0 ) {
+ fprintf( stderr,
+ "unable to parse file \"%s\" line %d\n",
+ rfile, -2*(rnum + 1) );
+ exit( EXIT_FAILURE );
+ }
}
/* look for modrdn requests */
if ( nfile ) {
nnum = get_read_entries( nfile, nreqs, NULL );
+ if ( nnum < 0 ) {
+ fprintf( stderr,
+ "unable to parse file \"%s\" line %d\n",
+ nfile, -2*(nnum + 1) );
+ exit( EXIT_FAILURE );
+ }
}
/* look for modify requests */
if ( mfile ) {
- mnum = get_search_filters( mfile, mreqs, NULL, mdn );
+ mnum = get_search_filters( mfile, mreqs, NULL, mdn, NULL );
+ if ( mnum < 0 ) {
+ fprintf( stderr,
+ "unable to parse file \"%s\" line %d\n",
+ mfile, -2*(mnum + 1) );
+ exit( EXIT_FAILURE );
+ }
}
/* look for bind requests */
if ( bfile ) {
- bnum = get_search_filters( bfile, bcreds, battrs, breqs );
+ bnum = get_search_filters( bfile, bcreds, battrs, breqs, NULL );
+ if ( bnum < 0 ) {
+ fprintf( stderr,
+ "unable to parse file \"%s\" line %d\n",
+ bfile, -2*(bnum + 1) );
+ exit( EXIT_FAILURE );
+ }
}
/* setup friendly option */
}
sargs[sanum++] = "-b";
sargs[sanum++] = NULL; /* will hold the search base */
+ sargs[sanum++] = "-s";
+ sargs[sanum++] = NULL; /* will hold the search scope */
sargs[sanum++] = "-f";
sargs[sanum++] = NULL; /* will hold the search request */
sargs[sanum++] = NULL;
- sargs[sanum] = NULL; /* might hold the "attr" request */
+ sargs[sanum++] = NULL; /* might hold the "attr" request */
+ sextra_args += 2;
- sargs[sanum + 1] = NULL;
+ sargs[sanum] = NULL;
/*
* generate the read clients
rargs[ranum++] = NULL; /* will hold the read entry */
rargs[ranum++] = NULL;
- rargs[ranum] = NULL; /* might hold the filter arg */
+ rargs[ranum++] = NULL; /* might hold the filter arg */
+ rextra_args += 2;
- rargs[ranum + 1] = NULL;
+ rargs[ranum] = NULL;
/*
* generate the modrdn clients
}
nargs[nanum++] = "-e";
nargs[nanum++] = NULL; /* will hold the modrdn entry */
- nargs[nanum++] = NULL;
+ nargs[nanum] = NULL;
/*
* generate the modify clients
margs[manum++] = NULL; /* will hold the modify entry */
margs[manum++] = "-a";;
margs[manum++] = NULL; /* will hold the ava */
- margs[manum++] = NULL;
+ margs[manum] = NULL;
/*
* generate the add/delete clients
}
aargs[aanum++] = "-f";
aargs[aanum++] = NULL; /* will hold the add data file */
- aargs[aanum++] = NULL;
+ aargs[aanum] = NULL;
/*
* generate the bind clients
bargs[banum++] = NULL;
bargs[banum++] = "-w";
bargs[banum++] = NULL;
- bargs[banum++] = NULL;
+ bargs[banum] = NULL;
#define DOREQ(n,j) ((n) && ((maxkids > (n)) ? ((j) < maxkids ) : ((j) < (n))))
for ( j = 0; j < MAXREQS; j++ ) {
+ /* search */
if ( DOREQ( snum, j ) ) {
int jj = j % snum;
+ int x = sanum - sextra_args;
- sargs[sanum - 2] = sreqs[jj];
- sargs[sanum - 4] = sbase[jj];
- if ( sattrs[jj] != NULL ) {
- sargs[sanum - 1] = "-a";
- sargs[sanum] = sattrs[jj];
+ /* base */
+ if ( sbase[jj] != NULL ) {
+ sargs[sanum - 7] = sbase[jj];
+
+ } else {
+ sargs[sanum - 7] = slud[jj]->lud_dn;
+ }
+
+ /* scope */
+ if ( slud[jj] != NULL ) {
+ sargs[sanum - 5] = (char *)ldap_pvt_scope2str( slud[jj]->lud_scope );
+
+ } else {
+ sargs[sanum - 5] = "sub";
+ }
+
+ /* filter */
+ if ( sreqs[jj] != NULL ) {
+ sargs[sanum - 3] = sreqs[jj];
+
+ } else if ( slud[jj]->lud_filter != NULL ) {
+ sargs[sanum - 3] = slud[jj]->lud_filter;
} else {
- sargs[sanum - 1] = NULL;
+ sargs[sanum - 3] = "(objectClass=*)";
}
+
+ /* extras */
+ sargs[x] = NULL;
+
+ /* attr */
+ if ( sattrs[jj] != NULL ) {
+ sargs[x++] = "-a";
+ sargs[x++] = sattrs[jj];
+ }
+
+ /* attrs */
+ if ( slud[jj] != NULL && slud[jj]->lud_attrs != NULL ) {
+ int i;
+
+ for ( i = 0; slud[jj]->lud_attrs[ i ] != NULL && x + i < MAXARGS - 1; i++ ) {
+ sargs[x + i] = slud[jj]->lud_attrs[ i ];
+ }
+ sargs[x + i] = NULL;
+ }
+
fork_child( scmd, sargs );
}
+ /* read */
if ( DOREQ( rnum, j ) ) {
int jj = j % rnum;
+ int x = ranum - rextra_args;
- rargs[ranum - 2] = rreqs[jj];
+ rargs[ranum - 3] = rreqs[jj];
if ( rflts[jj] != NULL ) {
- rargs[ranum - 1] = "-f";
- rargs[ranum] = rflts[jj];
-
- } else {
- rargs[ranum - 1] = NULL;
+ rargs[x++] = "-f";
+ rargs[x++] = rflts[jj];
}
+ rargs[x] = NULL;
fork_child( rcmd, rargs );
}
+ /* rename */
if ( j < nnum ) {
- nargs[nanum - 2] = nreqs[j];
+ nargs[nanum - 1] = nreqs[j];
fork_child( ncmd, nargs );
}
+ /* modify */
if ( j < mnum ) {
- margs[manum - 4] = mdn[j];
- margs[manum - 2] = mreqs[j];
+ margs[manum - 3] = mdn[j];
+ margs[manum - 1] = mreqs[j];
fork_child( mcmd, margs );
}
+ /* add/delete */
if ( j < anum ) {
- aargs[aanum - 2] = afiles[j];
+ aargs[aanum - 1] = afiles[j];
fork_child( acmd, aargs );
}
+ /* bind */
if ( DOREQ( bnum, j ) ) {
int jj = j % bnum;
}
if ( battrs[jj] != NULL ) {
- bargs[banum - 4] = manager ? manager : "";
- bargs[banum - 2] = passwd ? passwd : "";
-
- bargs[banum - 1] = "-b";
- bargs[banum] = breqs[jj];
- bargs[banum + 1] = "-f";
- bargs[banum + 2] = bcreds[jj];
- bargs[banum + 3] = "-a";
- bargs[banum + 4] = battrs[jj];
+ bargs[banum - 3] = manager ? manager : "";
+ bargs[banum - 1] = passwd ? passwd : "";
+
+ bargs[banum - 2] = "-b";
+ bargs[banum - 1] = breqs[jj];
+ bargs[banum + 0] = "-f";
+ bargs[banum + 1] = bcreds[jj];
+ bargs[banum + 2] = "-a";
+ bargs[banum + 3] = battrs[jj];
+
} else {
- bargs[banum - 4] = breqs[jj];
- bargs[banum - 2] = bcreds[jj];
- bargs[banum - 1] = NULL;
+ bargs[banum - 3] = breqs[jj];
+ bargs[banum - 1] = bcreds[jj];
+ bargs[banum] = NULL;
}
fork_child( bcmd, bargs );
- bargs[banum - 1] = NULL;
+ bargs[banum] = NULL;
}
}
static int
-get_search_filters( char *filename, char *filters[], char *attrs[], char *bases[] )
+get_search_filters( char *filename, char *filters[], char *attrs[], char *bases[], LDAPURLDesc *luds[] )
{
FILE *fp;
int filter = 0;
char line[BUFSIZ];
while (( filter < MAXREQS ) && ( fgets( line, BUFSIZ, fp ))) {
- char *nl;
+ char *nl;
+ int got_URL = 0;
if (( nl = strchr( line, '\r' )) || ( nl = strchr( line, '\n' )))
*nl = '\0';
- bases[filter] = ArgDup( line );
+
+ if ( luds ) luds[filter] = NULL;
+
+ if ( luds && strncmp( line, "ldap:///", STRLENOF( "ldap:///" ) ) == 0 ) {
+ LDAPURLDesc *lud;
+
+ got_URL = 1;
+ bases[filter] = NULL;
+ if ( ldap_url_parse( line, &lud ) != LDAP_URL_SUCCESS ) {
+ filter = -filter - 1;
+ break;
+ }
+
+ if ( lud->lud_dn == NULL || lud->lud_exts != NULL ) {
+ filter = -filter - 1;
+ ldap_free_urldesc( lud );
+ break;
+ }
+
+ luds[filter] = lud;
+
+ } else {
+ bases[filter] = ArgDup( line );
+ }
fgets( line, BUFSIZ, fp );
if (( nl = strchr( line, '\r' )) || ( nl = strchr( line, '\n' )))
*nl = '\0';
if ( filters[filter][0] == '+') {
char *sep = strchr( filters[filter], ':' );
+ attrs[ filter ] = &filters[ filter ][ 1 ];
if ( sep != NULL ) {
- attrs[ filter ] = &filters[ filter ][ 1 ];
sep[ 0 ] = '\0';
/* NOTE: don't free this! */
filters[ filter ] = &sep[ 1 ];
}
} else {
- attrs[ filter] = NULL;
+ attrs[ filter ] = NULL;
}
}
filter++;
fclose( fp );
}
- return( filter );
+ return filter;
}
LDAPURLDesc *lud;
if ( ldap_url_parse( &line[1], &lud ) != LDAP_URL_SUCCESS ) {
- entry = -1;
+ entry = -entry - 1;
break;
}
if ( lud->lud_dn == NULL || lud->lud_dn[ 0 ] == '\0' ) {
ldap_free_urldesc( lud );
- entry = -1;
+ entry = -entry - 1;
break;
}
AC_LIBS_DYNAMIC=lib@BUILD_LIBS_DYNAMIC@
# sanitize
-if test "${AC_ldap}" = "ldapmod" -a "${AC_LIBS_DYNAMIC}" = "static" ; then
+if test "${AC_ldap}" = "ldapmod" && test "${AC_LIBS_DYNAMIC}" = "static" ; then
AC_ldap="ldapno"
fi
-if test "${AC_meta}" = "metamod" -a "${AC_LIBS_DYNAMIC}" = "static" ; then
+if test "${AC_meta}" = "metamod" && test "${AC_LIBS_DYNAMIC}" = "static" ; then
AC_meta="metano"
fi
/bin/rm -rf ${TESTDIR}/db.*
fi
fi
+mkdir -p ${TESTDIR}
if test $USERDATA = yes ; then
if test ! -d userdata ; then
echo "User data directory (userdata) does not exist."
exit 1
fi
- mkdir -p ${TESTDIR}
cp -R userdata/* ${TESTDIR}
fi
# disable LDAP initialization
LDAPNOINIT=true; export LDAPNOINIT
-$SLAPPASSWD -g -n >$CONFIGPWF
-echo "rootpw `$SLAPPASSWD -T $CONFIGPWF`" >configpw.conf
-
echo "Running ${SCRIPT}..."
$SCRIPT $*
RC=$?
## top-level directory of the distribution or, alternatively, at
## <http://www.OpenLDAP.org/license.html>.
-SHTOOL="$SRCDIR/../build/shtool"
-TB=`$SHTOOL echo -e "%B"`
-TN=`$SHTOOL echo -e "%b"`
+. $SRCDIR/scripts/defines.sh
+
+TB="" TN=""
+if test -t 1 ; then
+ TB=`$SHTOOL echo -e "%B" 2>/dev/null`
+ TN=`$SHTOOL echo -e "%b" 2>/dev/null`
+fi
+
SLEEPTIME=10
echo ">>>>> Executing all LDAP tests for $BACKEND"
for CMD in $SRCDIR/scripts/test*; do
# remove cruft from prior test
if test $PRESERVE = yes ; then
- /bin/rm -rf testrun/db.*
+ /bin/rm -rf $TESTDIR/db.*
else
- /bin/rm -rf testrun
+ /bin/rm -rf $TESTDIR
fi
echo ">>>>> Starting ${TB}`basename $CMD`${TN} ..."
umask 077
+TESTWD=`pwd`
+
# backends
MONITORDB=${AC_monitor-no}
BACKLDAP=${AC_ldap-ldapno}
# misc
WITH_SASL=${AC_WITH_SASL-no}
USE_SASL=${SLAPD_USE_SASL-no}
-WITHTLS=${AC_WITHTLS-yes}
ACI=${AC_ACI_ENABLED-acino}
THREADS=${AC_THREADS-threadsno}
# dirs
PROGDIR=./progs
DATADIR=${USER_DATADIR-./testdata}
-TESTDIR=${USER_TESTDIR-./testrun}
+TESTDIR=${USER_TESTDIR-$TESTWD/testrun}
SCHEMADIR=${USER_SCHEMADIR-./schema}
DBDIR1A=$TESTDIR/db.1.a
WHOAMICONF=$DATADIR/slapd-whoami.conf
ACLCONF=$DATADIR/slapd-acl.conf
RCONF=$DATADIR/slapd-referrals.conf
-MASTERCONF=$DATADIR/slapd-repl-master.conf
SRMASTERCONF=$DATADIR/slapd-syncrepl-master.conf
DSRMASTERCONF=$DATADIR/slapd-deltasync-master.conf
DSRSLAVECONF=$DATADIR/slapd-deltasync-slave.conf
-SLAVECONF=$DATADIR/slapd-repl-slave.conf
PPOLICYCONF=$DATADIR/slapd-ppolicy.conf
PROXYCACHECONF=$DATADIR/slapd-proxycache.conf
CACHEMASTERCONF=$DATADIR/slapd-cache-master.conf
CONF5=$TESTDIR/slapd.5.conf
CONF6=$TESTDIR/slapd.6.conf
ADDCONF=$TESTDIR/slapadd.conf
+CONFLDIF=$TESTDIR/slapd-dynamic.ldif
LOG1=$TESTDIR/slapd.1.log
LOG2=$TESTDIR/slapd.2.log
SLAPADDLOG1=$TESTDIR/slapadd.1.log
SLURPLOG=$TESTDIR/slurp.log
-CONFIGPWF=./configpw
+CONFIGPWF=$TESTDIR/configpw
# args
TOOLARGS="-x $LDAP_TOOLARGS"
LDIFFILTER=$SRCDIR/scripts/acfilter.sh
CONFFILTER=$SRCDIR/scripts/conf.sh
-SLAPADD="`pwd`/../servers/slapd/slapd -Ta -d 0 $LDAP_VERBOSE"
-SLAPCAT="`pwd`/../servers/slapd/slapd -Tc -d 0 $LDAP_VERBOSE"
-SLAPINDEX="`pwd`/../servers/slapd/slapd -Ti -d 0 $LDAP_VERBOSE"
-SLAPPASSWD="`pwd`/../servers/slapd/slapd -Tpasswd"
+SLAPADD="$TESTWD/../servers/slapd/slapd -Ta -d 0 $LDAP_VERBOSE"
+SLAPCAT="$TESTWD/../servers/slapd/slapd -Tc -d 0 $LDAP_VERBOSE"
+SLAPINDEX="$TESTWD/../servers/slapd/slapd -Ti -d 0 $LDAP_VERBOSE"
+SLAPPASSWD="$TESTWD/../servers/slapd/slapd -Tpasswd"
unset DIFF_OPTIONS
# NOTE: -u/-c is not that portable...
CMP="diff -i"
BCMP="diff -iB"
CMPOUT=/dev/null
-SLAPD="`pwd`/../servers/slapd/slapd -s0"
-SLURPD="`pwd`/../servers/slurpd/slurpd"
+SLAPD="$TESTWD/../servers/slapd/slapd -s0"
LDAPPASSWD="$CLIENTDIR/ldappasswd $TOOLARGS"
LDAPSASLSEARCH="$CLIENTDIR/ldapsearch $TOOLPROTO $LDAP_TOOLARGS -LLL"
LDAPSEARCH="$CLIENTDIR/ldapsearch $TOOLPROTO $TOOLARGS -LLL"
ACIOUT=$DATADIR/aci.out
DYNLISTOUT=$DATADIR/dynlist.out
DDSOUT=$DATADIR/dds.out
+SHTOOL="$SRCDIR/../build/shtool"
# Just in case we linked the binaries dynamically
-LD_LIBRARY_PATH=`pwd`/../libraries:${LD_LIBRARY_PATH} export LD_LIBRARY_PATH
+LD_LIBRARY_PATH=$TESTWD/../libraries:${LD_LIBRARY_PATH} export LD_LIBRARY_PATH
## <http://www.OpenLDAP.org/license.html>.
SHTOOL="$SRCDIR/../build/shtool"
-TB=`$SHTOOL echo -e "%B"`
-TN=`$SHTOOL echo -e "%b"`
+
+TB="" TN=""
+if test -t 1 ; then
+ TB=`$SHTOOL echo -e "%B" 2>/dev/null`
+ TN=`$SHTOOL echo -e "%b" 2>/dev/null`
+fi
echo "#######################################################################"
echo "### ###"
exit $RC
fi
- echo ">>>>> waiting for things to exit"
echo ""
done
## <http://www.OpenLDAP.org/license.html>.
SHTOOL="$SRCDIR/../build/shtool"
-TB=`$SHTOOL echo -e "%B"`
-TN=`$SHTOOL echo -e "%b"`
+
+TB="" TN=""
+if test -t 1 ; then
+ TB=`$SHTOOL echo -e "%B" 2>/dev/null`
+ TN=`$SHTOOL echo -e "%b" 2>/dev/null`
+fi
+
SLEEPTIME=10
echo "#######################################################################"
echo "Testing baseobject search..."
echo "# Testing baseobject search..." >> $SEARCHOUT
-$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" -s base >> $SEARCHOUT 2>&1
+$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" -s base -S "" \
+ >> $SEARCHOUT 2>&1
RC=$?
if test $RC != 0 ; then
echo "Testing onelevel search..."
echo "# Testing onelevel search..." >> $SEARCHOUT
-$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" -s one >> $SEARCHOUT 2>&1
+$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" -s one -S "" \
+ >> $SEARCHOUT 2>&1
RC=$?
if test $RC != 0 ; then
echo "Testing subtree search..."
echo "# Testing subtree search..." >> $SEARCHOUT
-$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" >> $SEARCHOUT 2>&1
+$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" -S "" \
+ >> $SEARCHOUT 2>&1
RC=$?
if test $RC != 0 ; then
echo "Testing subtree search with manageDSAit..."
echo "# Testing subtree search with manageDSAit..." >> $SEARCHOUT
-$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" -M '*' ref >> $SEARCHOUT 2>&1
+$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" -M -S "" '*' ref \
+ >> $SEARCHOUT 2>&1
RC=$?
if test $RC != 0 ; then
echo "Testing invalid filter..."
echo "# Testing invalid filter..." >> $SEARCHOUT
-$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" \
- "(foo=)" >> $SEARCHOUT 2>&1
+$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" -S "" "(foo=)" \
+ >> $SEARCHOUT 2>&1
RC=$?
if test $RC != 0 ; then
echo "Testing exact search..."
echo "# Testing exact search..." >> $SEARCHOUT
-$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" \
- "(sn=Kovalev)" >> $SEARCHOUT 2>&1
+$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" -S "" "(sn=Kovalev)" \
+ >> $SEARCHOUT 2>&1
RC=$?
if test $RC != 0 ; then
echo "Testing substrings initial search..."
echo "# Testing substrings initial search..." >> $SEARCHOUT
-$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" \
- "(cn=m*)" >> $SEARCHOUT 2>&1
+$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" -S "" "(cn=m*)" \
+ >> $SEARCHOUT 2>&1
RC=$?
if test $RC != 0 ; then
echo "Testing substrings any search..."
echo "# Testing substrings any search..." >> $SEARCHOUT
-$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" \
- "(cn=*m*)" >> $SEARCHOUT 2>&1
+$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" -S "" "(cn=*m*)" \
+ >> $SEARCHOUT 2>&1
RC=$?
if test $RC != 0 ; then
echo "Testing substrings final search..."
echo "# Testing substrings final search..." >> $SEARCHOUT
-$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" \
- "(cn=*v)" >> $SEARCHOUT 2>&1
+$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" -S "" "(cn=*v)" \
+ >> $SEARCHOUT 2>&1
RC=$?
if test $RC != 0 ; then
echo "Testing approx search..."
echo "# Testing approx search..." >> $SEARCHOUT
-$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" \
- "(sn~=kovalev)" >> $SEARCHOUT 2>&1
+$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" -S "" "(sn~=kovalev)" \
+ >> $SEARCHOUT 2>&1
RC=$?
if test $RC != 0 ; then
echo "Testing extensible filter search..."
echo "# Testing extensible filter search..." >> $SEARCHOUT
-$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" \
+$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" -S "" \
"(sn:caseExactMatch:=Kovalev)" >> $SEARCHOUT 2>&1
RC=$?
echo "Testing search for telephoneNumber..."
echo "# Testing search for telephoneNumber..." >> $SEARCHOUT
-$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" \
+$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" -S "" \
"(telephoneNumber=3322334)" >> $SEARCHOUT 2>&1
RC=$?
echo "Testing AND search..."
echo "# Testing AND search..." >> $SEARCHOUT
-$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" \
+$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" -S "" \
"(&(sn=kovalev)(givenName=mitya))" >> $SEARCHOUT 2>&1
RC=$?
echo "Testing AND search on objectClass..."
echo "# Testing AND search on objectClass..." >> $SEARCHOUT
-$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" \
+$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" -S "" \
"(&(objectClass=organization)(objectClass=dcObject))" >> $SEARCHOUT 2>&1
RC=$?
echo "Testing OR search..."
echo "# Testing OR search..." >> $SEARCHOUT
-$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" \
+$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" -S "" \
"(|(sn=kovalev)(givenName=mitya))" >> $SEARCHOUT 2>&1
RC=$?
echo "Testing OR search on objectClass..."
echo "# Testing OR search on objectClass..." >> $SEARCHOUT
-$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" \
- "(|(objectClass=document)(objectClass=organization))" >> $SEARCHOUT 2>&1
+$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" -S "" \
+ "(|(objectClass=document)(objectClass=organization))" \
+ >> $SEARCHOUT 2>&1
RC=$?
if test $RC != 0 ; then
echo "Testing NOT search..."
echo "# Testing NOT search..." >> $SEARCHOUT
-$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" \
+$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" -S "" \
'(!(sn=kovalev))' >> $SEARCHOUT 2>&1
RC=$?
echo "Testing NOT search on objectClass..."
echo "# Testing NOT search on objectClass..." >> $SEARCHOUT
-$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" \
+$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" -S "" \
'(!(objectClass=inetOrgPerson))' >> $SEARCHOUT 2>&1
RC=$?
echo "Testing NOT search on \"auxiliary\" objectClass..."
echo "# Testing NOT search on \"auxiliary\" objectClass..." >> $SEARCHOUT
-$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" \
+$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" -S "" \
'(!(objectClass=dcObject))' >> $SEARCHOUT 2>&1
RC=$?
#### Needs work...
echo "Testing NOT presence search... (disabled)"
###echo "# Testing NOT presence search..." >> $SEARCHOUT
-###$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" \
+###$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" -S "" \
### '(!(sn=*))' >> $SEARCHOUT 2>&1
###
###RC=$?
echo "Testing attribute inheritance in filter..."
echo "# Testing attribute inheritance in filter..." >> $SEARCHOUT
-$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" \
+$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" -S "" \
"(name=example)" >> $SEARCHOUT 2>&1
RC=$?
# ITS#4604
echo "Testing undefined attribute in filter..."
echo "# Testing undefined attribute in filter..." >> $SEARCHOUT
-$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" \
+$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" -S "" \
"(|(o=example)(foobar=x))" >> $SEARCHOUT 2>&1
RC=$?
echo "Testing objectClass inheritance in filter..."
echo "# Testing objectClass inheritance in filter..." >> $SEARCHOUT
-$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" \
+$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" -S "" \
"(objectClass=person)" >> $SEARCHOUT 2>&1
RC=$?
echo "Testing \"auxiliary\" objectClass in filter..."
echo "# Testing \"auxiliary\" objectClass in filter..." >> $SEARCHOUT
-$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" \
+$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" -S "" \
"(objectClass=dcObject)" >> $SEARCHOUT 2>&1
RC=$?
echo "Testing hasSubordinates in filter..."
echo "# Testing hasSubordinates in filter..." >> $SEARCHOUT
-$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" \
+$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" -S "" \
"(hasSubordinates=TRUE)" >> $SEARCHOUT 2>&1
RC=$?
echo "Testing entryUUID in filter..."
echo "# Testing entryUUID in filter..." >> $SEARCHOUT
-$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" \
+$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" -S "" \
"(entryUUID=00000001-0000-0001-0000-000000000000)" >> $SEARCHOUT 2>&1
RC=$?
echo "Testing attribute inheritance in requested attributes..."
echo "# Testing attribute inheritance in requested attributes..." >> $SEARCHOUT
-$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" \
+$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" -S "" \
"(sn=kovalev)" name >> $SEARCHOUT 2>&1
RC=$?
echo "Testing objectClass in requested attributes..."
echo "# Testing objectClass in requested attributes..." >> $SEARCHOUT
-$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" \
+$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" -S "" \
objectClass >> $SEARCHOUT 2>&1
RC=$?
echo "Testing operational attributes in request..."
echo "# Testing operational attributes in request..." >> $SEARCHOUT
-$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" \
+$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" -S "" \
'+' 2>&1 > $SEARCHFLT
RC=$?
+++ /dev/null
-#! /bin/sh
-# $OpenLDAP$
-## This work is part of OpenLDAP Software <http://www.openldap.org/>.
-##
-## Copyright 1998-2007 The OpenLDAP Foundation.
-## All rights reserved.
-##
-## Redistribution and use in source and binary forms, with or without
-## modification, are permitted only as authorized by the OpenLDAP
-## Public License.
-##
-## A copy of this license is available in the file LICENSE in the
-## top-level directory of the distribution or, alternatively, at
-## <http://www.OpenLDAP.org/license.html>.
-
-echo "running defines.sh"
-. $SRCDIR/scripts/defines.sh
-
-if test ! -x $SLURPD ; then
- echo ">>>>> $SLURPD is not executable or does not exist."
- echo ">>>>> Test skipped."
- exit 0
-fi
-
-mkdir -p $TESTDIR $DBDIR1A $DBDIR1B $DBDIR2
-
-#
-# Test replication:
-# - start master (slapd1)
-# - start slave (slapd2)
-# - start slurpd
-# - populate over ldap
-# - perform some modifies and deleted
-# - attempt to modify the slave (referral or chain)
-# - retrieve database over ldap and compare against expected results
-#
-
-echo "Starting master slapd on TCP/IP port $PORT1..."
-. $CONFFILTER $BACKEND $MONITORDB < $MASTERCONF > $CONF1
-$SLAPD -f $CONF1 -h $URI1 -d $LVL $TIMING > $LOG1 2>&1 &
-PID=$!
-if test $WAIT != 0 ; then
- echo PID $PID
- read foo
-fi
-KILLPIDS="$PID"
-
-echo "Starting slave slapd on TCP/IP port $PORT2..."
-. $CONFFILTER $BACKEND $MONITORDB < $SLAVECONF > $CONF2
-$SLAPD -f $CONF2 -h $URI2 -d $LVL $TIMING > $LOG2 2>&1 &
-SLAVEPID=$!
-if test $WAIT != 0 ; then
- echo SLAVEPID $SLAVEPID
- read foo
-fi
-KILLPIDS="$KILLPIDS $SLAVEPID"
-
-sleep 1
-
-echo "Using ldapsearch to check that master slapd is running..."
-for i in 0 1 2 3 4 5; do
- $LDAPSEARCH -s base -b "$MONITOR" -h $LOCALHOST -p $PORT1 \
- 'objectclass=*' > /dev/null 2>&1
- RC=$?
- if test $RC = 0 ; then
- break
- fi
- echo "Waiting 5 seconds for slapd to start..."
- sleep 5
-done
-
-echo "Using ldapsearch to check that slave slapd is running..."
-for i in 0 1 2 3 4 5; do
- $LDAPSEARCH -s base -b "$MONITOR" -h $LOCALHOST -p $PORT2 \
- 'objectclass=*' > /dev/null 2>&1
- RC=$?
- if test $RC = 0 ; then
- break
- fi
- echo "Waiting 5 seconds for slapd to start..."
- sleep 5
-done
-
-echo "Starting slurpd..."
-$SLURPD -f $CONF1 -d ${SLURPD_DEBUG-5} -t $DBDIR1B > $SLURPLOG 2>&1 &
-SLURPPID=$!
-if test $WAIT != 0 ; then
- echo SLURPPID $SLURPPID
- read foo
-fi
-KILLPIDS="$KILLPIDS $SLURPPID"
-
-echo "Using ldapadd to populate the master directory..."
-$LDAPADD -D "$MANAGERDN" -h $LOCALHOST -p $PORT1 -w $PASSWD < \
- $LDIFORDERED > /dev/null 2>&1
-RC=$?
-if test $RC != 0 ; then
- echo "ldapadd failed ($RC)!"
- test $KILLSERVERS != no && kill -HUP $KILLPIDS
- exit $RC
-fi
-
-echo "Waiting 15 seconds for slurpd to send changes..."
-sleep 15
-
-echo "Using ldapmodify to modify master directory..."
-
-#
-# Do some modifications
-#
-
-$LDAPMODIFY -v -D "$MANAGERDN" -h $LOCALHOST -p $PORT1 -w $PASSWD > \
- $TESTOUT 2>&1 << EOMODS
-dn: cn=James A Jones 1, ou=Alumni Association, ou=People, dc=example, dc=com
-changetype: modify
-add: drink
-drink: Orange Juice
--
-delete: sn
-sn: Jones
--
-add: sn
-sn: Jones
-
-dn: cn=Bjorn Jensen, ou=Information Technology Division, ou=People, dc=example, dc=com
-changetype: modify
-replace: drink
-drink: Iced Tea
-drink: Mad Dog 20/20
-
-dn: cn=ITD Staff,ou=Groups,dc=example, dc=com
-changetype: modify
-delete: uniqueMember
-uniqueMember: cn=James A Jones 2, ou=Information Technology Division,
- ou=People, dc=example, dc=com
-uniqueMember: cn=Bjorn Jensen, ou=Information Technology Division, ou=People, dc=example, dc=com
--
-add: uniqueMember
-uniqueMember: cn=Dorothy Stevens, ou=Alumni Association, ou=People, dc=example, dc=com
-uniqueMember: cn=James A Jones 1, ou=Alumni Association, ou=People, dc=example, dc=com
-
-dn: cn=All Staff,ou=Groups,dc=example, dc=com
-changetype: modify
-delete: description
-
-dn: cn=Gern Jensen, ou=Information Technology Division, ou=People, dc=example, dc=com
-changetype: add
-objectclass: OpenLDAPperson
-cn: Gern Jensen
-sn: Jensen
-uid: gjensen
-title: Chief Investigator, ITD
-postaladdress: ITD $ 535 W. William St $ Ann Arbor, MI 48103
-seealso: cn=All Staff, ou=Groups, dc=example, dc=com
-drink: Coffee
-homepostaladdress: 844 Brown St. Apt. 4 $ Ann Arbor, MI 48104
-description: Very odd
-facsimiletelephonenumber: +1 313 555 7557
-telephonenumber: +1 313 555 8343
-mail: gjensen@mailgw.example.com
-homephone: +1 313 555 8844
-
-dn: ou=Retired, ou=People, dc=example, dc=com
-changetype: add
-objectclass: organizationalUnit
-ou: Retired
-
-dn: cn=Rosco P. Coltrane, ou=Information Technology Division, ou=People, dc=example, dc=com
-changetype: add
-objectclass: OpenLDAPperson
-cn: Rosco P. Coltrane
-sn: Coltrane
-uid: rosco
-
-dn: cn=Rosco P. Coltrane, ou=Information Technology Division, ou=People, dc=example, dc=com
-changetype: modrdn
-newrdn: cn=Rosco P. Coltrane
-deleteoldrdn: 1
-newsuperior: ou=Retired, ou=People, dc=example, dc=com
-
-dn: cn=James A Jones 2, ou=Information Technology Division, ou=People, dc=example, dc=com
-changetype: delete
-
-EOMODS
-
-RC=$?
-if test $RC != 0 ; then
- echo "ldapmodify failed ($RC)!"
- test $KILLSERVERS != no && kill -HUP $KILLPIDS
- exit $RC
-fi
-
-echo "Waiting 15 seconds for slurpd to send changes..."
-sleep 15
-
-echo "Stopping the slave..."
-kill -HUP $SLAVEPID
-KILLPIDS="$PID $SLURPPID"
-
-echo "Waiting for slave slapd to die..."
-wait $SLAVEPID
-
-echo "Applying more changes to the master slapd..."
-$LDAPMODIFY -v -D "$MANAGERDN" -h $LOCALHOST -p $PORT1 -w $PASSWD > \
- $TESTOUT 2>&1 << EOMODS
-dn: cn=James A Jones 1, ou=Alumni Association, ou=People, dc=example, dc=com
-changetype: modify
-add: description
-description: This change was applied after killing the slave slapd...
-
-EOMODS
-
-RC=$?
-
-if test $RC != 0 ; then
- echo "ldapmodify failed ($RC)!"
- test $KILLSERVERS != no && kill -HUP $KILLPIDS
- exit $RC
-fi
-
-
-echo "Stopping slurpd..."
-kill -HUP $SLURPPID
-KILLPIDS="$PID"
-
-echo "Waiting for slurpd to die..."
-wait $SLURPPID
-
-echo "Applying more changes to the master slapd..."
-$LDAPMODIFY -v -D "$MANAGERDN" -h $LOCALHOST -p $PORT1 -w $PASSWD > \
- $TESTOUT 2>&1 << EOMODS
-dn: cn=James A Jones 1, ou=Alumni Association, ou=People, dc=example, dc=com
-changetype: modify
-add: description
-description: This change was applied after killing slurpd...
-
-EOMODS
-
-RC=$?
-
-if test $RC != 0 ; then
- echo "ldapmodify failed ($RC)!"
- test $KILLSERVERS != no && kill -HUP $KILLPIDS
- exit $RC
-fi
-
-echo "Restarting slave slapd on TCP/IP port $PORT2..."
-echo "RESTART" >> $LOG2
-$SLAPD -f $CONF2 -h $URI2 -d $LVL $TIMING >> $LOG2 2>&1 &
-SLAVEPID=$!
-if test $WAIT != 0 ; then
- echo SLAVEPID $SLAVEPID
- read foo
-fi
-KILLPIDS="$KILLPIDS $SLAVEPID"
-
-sleep 1
-
-echo "Using ldapsearch to check that slave slapd is running..."
-for i in 0 1 2 3 4 5; do
- $LDAPSEARCH -s base -b "$MONITOR" -h $LOCALHOST -p $PORT2 \
- 'objectclass=*' > /dev/null 2>&1
- RC=$?
- if test $RC = 0 ; then
- break
- fi
- echo "Waiting 5 seconds for slapd to start..."
- sleep 5
-done
-
-echo "Restarting slurpd..."
-echo "RESTART" >> $SLURPLOG
-$SLURPD -f $CONF1 -d ${SLURPD_DEBUG-5} -t $DBDIR1B >> $SLURPLOG 2>&1 &
-SLURPPID=$!
-if test $WAIT != 0 ; then
- echo SLURPPID $SLURPPID
- read foo
-fi
-KILLPIDS="$KILLPIDS $SLURPPID"
-
-echo "Waiting 15 seconds for slurpd to send changes..."
-sleep 15
-
-if test ! $BACKLDAP = "ldapno" ; then
- echo "Try updating the slave slapd..."
- $LDAPMODIFY -v -D "$MANAGERDN" -h $LOCALHOST -p $PORT2 -w $PASSWD > \
- $TESTOUT 2>&1 << EOMODS
-dn: cn=James A Jones 1, ou=Alumni Association, ou=People, dc=example, dc=com
-changetype: modify
-add: description
-description: This write must fail because directed to a shadow context,
-description: unless the chain overlay is configured appropriately ;)
-
-EOMODS
-
- RC=$?
- if test $RC != 0 ; then
- echo "ldapmodify failed ($RC)!"
- test $KILLSERVERS != no && kill -HUP $KILLPIDS
- exit $RC
- fi
-
- echo "Waiting 15 seconds for slurpd to send changes..."
- sleep 15
-fi
-
-echo "Using ldapsearch to read all the entries from the master..."
-$LDAPSEARCH -S "" -b "$BASEDN" -h $LOCALHOST -p $PORT1 \
- 'objectclass=*' > $MASTEROUT 2>&1
-RC=$?
-
-if test $RC != 0 ; then
- echo "ldapsearch failed ($RC)!"
- test $KILLSERVERS != no && kill -HUP $KILLPIDS
- exit $RC
-fi
-
-echo "Using ldapsearch to read all the entries from the slave..."
-$LDAPSEARCH -S "" -b "$BASEDN" -h $LOCALHOST -p $PORT2 \
- 'objectclass=*' > $SLAVEOUT 2>&1
-RC=$?
-
-if test $RC != 0 ; then
- echo "ldapsearch failed ($RC)!"
- test $KILLSERVERS != no && kill -HUP $KILLPIDS
- exit $RC
-fi
-
-test $KILLSERVERS != no && kill -HUP $KILLPIDS
-
-echo "Filtering master results..."
-. $LDIFFILTER < $MASTEROUT > $MASTERFLT
-echo "Filtering slave results..."
-. $LDIFFILTER < $SLAVEOUT > $SLAVEFLT
-
-echo "Comparing retrieved entries from master and slave..."
-$CMP $MASTERFLT $SLAVEFLT > $CMPOUT
-
-if test $? != 0 ; then
- echo "test failed - master and slave databases differ"
- exit 1
-fi
-
-echo ">>>>> Test succeeded"
-
-test $KILLSERVERS != no && wait
-
-exit 0
# expect 10 (LDAP_REFERRAL)...
if test $RC != 10 ; then
- echo "ldapmodify should have failed ($RC)!"
+ echo "ldapmodify should have returned referral ($RC)!"
test $KILLSERVERS != no && kill -HUP $KILLPIDS
exit $RC
fi
exit $RC
fi
+echo "Using ldappasswd to change some passwords..."
+$LDAPPASSWD -D "$MANAGERDN" -h $LOCALHOST -p $PORT1 -w $PASSWD \
+ 'cn=Bjorn Jensen,ou=Information Technology Division,ou=People,dc=example,dc=com' \
+ > $TESTOUT 2>&1
+RC=$?
+if test $RC != 0 ; then
+ echo "ldapmodify failed ($RC)!"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit $RC
+fi
+
echo "Waiting 15 seconds for syncrepl to receive changes..."
sleep 15
exit $RC
fi
+ # ITS#4964
+ echo "Trying to change some passwords on the consumer..."
+ $LDAPPASSWD -D "$MANAGERDN" -h $LOCALHOST -p $PORT4 -w $PASSWD \
+ 'cn=Barbara Jensen,ou=Information Technology Division,ou=People,dc=example,dc=com' \
+ > $TESTOUT 2>&1
+ RC=$?
+ if test $RC != 0 ; then
+ echo "ldapmodify failed ($RC)!"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit $RC
+ fi
+
echo "Waiting 15 seconds for syncrepl to receive changes..."
sleep 15
fi
echo "running defines.sh"
. $SRCDIR/scripts/defines.sh
-if test "$AC_WITH_TLS" != "yes" ; then
- echo "test disabled, requires --with-tls"
- exit 0
-fi
-
mkdir -p $TESTDIR $DBDIR1
echo "Running slapadd to build slapd database..."
test $KILLSERVERS != no && kill -HUP $KILLPIDS
-if test "$WITHTLS" = no ; then
- echo "Certificate matching not suported without TLS"
- LDIF=$CERTIFICATEOUT
-else
- LDIF=$CERTIFICATETLS
-fi
+LDIF=$CERTIFICATETLS
echo "Filtering ldapsearch results..."
. $LDIFFILTER < $SEARCHOUT > $SEARCHFLT
exit $RC
fi
+if test $BACKEND = "hdb" ; then
+ $LDAPMODIFY -v -D "$REFINTDN" -h $LOCALHOST -p $PORT1 -w $PASSWD > \
+ $TESTOUT 2>&1 << EDEL
+version: 1
+dn: cn=group,o=refint
+changetype: add
+objectClass: groupOfNames
+cn: group
+member: uid=bill,ou=users,o=refint
+member: uid=bob,ou=users,o=refint
+member: uid=dave,ou=users,o=refint
+member: uid=jorge,ou=users,o=refint
+member: uid=theman,ou=users,o=refint
+member: uid=richard,ou=users,o=refint
+EDEL
+
+ RC=$?
+ if test $RC != 0 ; then
+ echo "ldapmodify failed ($RC)!"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit $RC
+ fi
+
+ sleep 1;
+
+ $LDAPSEARCH -S "" -b "o=refint" -h $LOCALHOST -p $PORT1 \
+ manager member secretary > $SEARCHOUT 2>&1
+ RC=$?
+ if test $RC != 0 ; then
+ echo "ldapsearch failed ($RC)!"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit $RC
+ fi
+
+ $EGREP_CMD "(manager|member|secretary):" $SEARCHOUT \
+ | sed "s/ou=users/ou=people/g" | \
+ sort > $TESTOUT 2>&1
+
+ echo "testing subtree rename"
+ $LDAPMODRDN -D "$REFINTDN" -r -h $LOCALHOST -p $PORT1 -w $PASSWD > \
+ /dev/null 2>&1 'ou=users,o=refint' 'ou=people'
+ RC=$?
+ if test $RC != 0 ; then
+ echo "ldapmodrdn failed ($RC)!"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit $RC
+ fi
+
+ sleep 1;
+
+ echo "Using ldapsearch to check dependents new rdn..."
+
+ $LDAPSEARCH -S "" -b "o=refint" -h $LOCALHOST -p $PORT1 \
+ manager member secretary > $SEARCHOUT 2>&1
+
+ RC=$?
+ if test $RC != 0 ; then
+ echo "ldapsearch failed ($RC)!"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit $RC
+ fi
+
+ $EGREP_CMD "(manager|member|secretary):" $SEARCHOUT \
+ | sort > $SEARCHFLT 2>&1
+
+ echo "Comparing ldapsearch results against original..."
+ $CMP $TESTOUT $SEARCHFLT > $CMPOUT
+
+ if test $? != 0 ; then
+ echo "comparison failed - subtree rename operations did not complete correctly"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit 1
+ fi
+fi
+
test $KILLSERVERS != no && kill -HUP $KILLPIDS
echo ">>>>> Test succeeded"
echo "running defines.sh"
. $SRCDIR/scripts/defines.sh
-if test $UNIQUE = uniqueno; then
+if test $UNIQUE = uniqueno; then
echo "Attribute Uniqueness overlay not available, test skipped"
exit 0
-fi
+fi
mkdir -p $TESTDIR $DBDIR1
+$SLAPPASSWD -g -n >$CONFIGPWF
+echo "rootpw `$SLAPPASSWD -T $CONFIGPWF`" >$TESTDIR/configpw.conf
+
echo "Running slapadd to build slapd database..."
. $CONFFILTER $BACKEND $MONITORDB < $UNIQUECONF > $CONF1
-$SLAPADD -f $CONF1 -l $LDIFUNIQUE
+$SLAPADD -f $CONF1 -l $LDIFUNIQUE -d7
RC=$?
if test $RC != 0 ; then
echo "slapadd failed ($RC)!"
fi
echo "Starting slapd on TCP/IP port $PORT1..."
-$SLAPD -f $CONF1 -h $URI1 -d $LVL $TIMING > $LOG1 2>&1 &
+mkdir testrun/confdir
+$SLAPD -f $CONF1 -F testrun/confdir -h $URI1 -d $LVL $TIMING > $LOG1 2>&1 &
PID=$!
if test $WAIT != 0 ; then
echo PID $PID
fi
echo "Adding a unique record..."
-
-#$LDAPADD -D "$UNIQUEDN" -h $LOCALHOST -p $PORT1 -w $PASSWD > \
-# $TESTOUT 2>&1 << EOTUNIQ1
$LDAPADD -D "$UNIQUEDN" -h $LOCALHOST -p $PORT1 -w $PASSWD \
> /dev/null << EOTUNIQ1
dn: uid=dave,ou=users,o=unique
employeeType: contractor
givenName: Dave
EOTUNIQ1
-
RC=$?
if test $RC != 0 ; then
echo "ldapadd failed ($RC)!"
exit $RC
fi
-#echo ----------------------
-#$LDAPSEARCH -S "" -b "o=unique" -h $LOCALHOST -p $PORT1
+echo "Adding a non-unique record..."
+$LDAPADD -D "$UNIQUEDN" -h $LOCALHOST -p $PORT1 -w $PASSWD > \
+ $TESTOUT 2>&1 << EOTUNIQ2
+dn: uid=bill,ou=users,o=unique
+objectClass: inetOrgPerson
+uid: bill
+sn: johnson
+cn: bill
+businessCategory: rtest
+carLicense: ABC123
+departmentNumber: 42
+displayName: Bill
+employeeNumber: 5150
+employeeType: contractor
+givenName: Bill
+EOTUNIQ2
+RC=$?
+if test $RC != 19 ; then
+ echo "unique check failed ($RC)!"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit -1
+fi
+
+echo Dynamically retrieving initial configuration...
+$LDAPSEARCH -S "" -b olcOverlay='{0}'unique,olcDatabase='{1}'$BACKEND,cn=config -D cn=config -y $CONFIGPWF -h $LOCALHOST -p $PORT1 -LLL | tr -d \\r >testrun/initial-config.ldif
+cat <<EOF >testrun/initial-reference.ldif
+dn: olcOverlay={0}unique,olcDatabase={1}$BACKEND,cn=config
+objectClass: olcOverlayConfig
+objectClass: olcUniqueConfig
+olcOverlay: {0}unique
+olcUniqueBase: o=unique
+olcUniqueAttribute: employeeNumber
+olcUniqueAttribute: displayName
+
+EOF
+diff testrun/initial-config.ldif testrun/initial-reference.ldif > /dev/null 2>&1
+RC=$?
+if test $RC != 0 ; then
+ echo "Initial configuration is not reported correctly."
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit -1
+fi
+
+echo Dynamically trying to add a URI with legacy attrs present...
+$LDAPMODIFY -D cn=config -h $LOCALHOST -p $PORT1 -y $CONFIGPWF \
+ > $TESTOUT 2>&1 <<EOF
+dn: olcOverlay={0}unique,olcDatabase={1}$BACKEND,cn=config
+changetype: modify
+add: olcUniqueURI
+olcUniqueURI: ldap:///?employeeNumber,displayName?sub
+EOF
+RC=$?
+if test $RC != 80 ; then
+ echo "legacy and unique_uri allowed together"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit -1
+fi
+
+echo Dynamically trying to add legacy ignored attrs with legacy attrs present...
+$LDAPMODIFY -D cn=config -h $LOCALHOST -p $PORT1 -y $CONFIGPWF \
+ > $TESTOUT 2>&1 <<EOF
+dn: olcOverlay={0}unique,olcDatabase={1}$BACKEND,cn=config
+changetype: modify
+add: olcUniqueIgnore
+olcUniqueIgnore: objectClass
+EOF
+RC=$?
+if test $RC != 80 ; then
+ echo "legacy attrs and legacy ignore attrs allowed together"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit -1
+fi
+
+echo Verifying initial configuration intact...
+$LDAPSEARCH -S "" -b olcOverlay='{0}'unique,olcDatabase='{1}'$BACKEND,cn=config -D cn=config -y $CONFIGPWF -h $LOCALHOST -p $PORT1 -LLL | tr -d \\r >testrun/initial-config-recheck.ldif
+diff testrun/initial-config-recheck.ldif testrun/initial-reference.ldif > /dev/null 2>&1
+RC=$?
+if test $RC != 0 ; then
+ echo "Initial configuration damaged by unsuccessful modifies."
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit -1
+fi
+
+echo Dynamically removing legacy base...
+$LDAPMODIFY -D cn=config -h $LOCALHOST -p $PORT1 -y $CONFIGPWF \
+ > $TESTOUT 2>&1 <<EOF
+dn: olcOverlay={0}unique,olcDatabase={1}$BACKEND,cn=config
+changetype: modify
+delete: olcUniqueBase
+EOF
+RC=$?
+if test $RC != 0 ; then
+ echo "base removal failed"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit -1
+fi
+
+echo Verifying base removal...
+$LDAPSEARCH -S "" -b olcOverlay='{0}'unique,olcDatabase='{1}'$BACKEND,cn=config -D cn=config -y $CONFIGPWF -h $LOCALHOST -p $PORT1 -LLL | tr -d \\r >testrun/baseremoval-config.ldif
+cat >testrun/baseremoval-reference.ldif <<EOF
+dn: olcOverlay={0}unique,olcDatabase={1}$BACKEND,cn=config
+objectClass: olcOverlayConfig
+objectClass: olcUniqueConfig
+olcOverlay: {0}unique
+olcUniqueAttribute: employeeNumber
+olcUniqueAttribute: displayName
+
+EOF
+diff testrun/baseremoval-config.ldif testrun/baseremoval-reference.ldif > /dev/null 2>&1
+RC=$?
+if test $RC != 0 ; then
+ echo "Configuration damaged by base removal"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit -1
+fi
echo "Adding a non-unique record..."
+$LDAPADD -D "$UNIQUEDN" -h $LOCALHOST -p $PORT1 -w $PASSWD > \
+ $TESTOUT 2>&1 << EOTUNIQ2
+dn: uid=bill,ou=users,o=unique
+objectClass: inetOrgPerson
+uid: bill
+sn: johnson
+cn: bill
+businessCategory: rtest
+carLicense: ABC123
+departmentNumber: 42
+displayName: Bill
+employeeNumber: 5150
+employeeType: contractor
+givenName: Bill
+EOTUNIQ2
+RC=$?
+if test $RC != 19 ; then
+ echo "unique check failed ($RC)!"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit -1
+fi
+echo Trying a legacy base outside of the backend...
+$LDAPMODIFY -D cn=config -h $LOCALHOST -p $PORT1 -y $CONFIGPWF \
+ > $TESTOUT 2>&1 <<EOF
+dn: olcOverlay={0}unique,olcDatabase={1}$BACKEND,cn=config
+changetype: modify
+add: olcUniqueBase
+olcUniqueBase: cn=config
+EOF
+RC=$?
+if test $RC != 80 ; then
+ echo "out of backend scope base allowed"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit -1
+fi
+
+echo "Adding and removing attrs..."
+$LDAPMODIFY -D cn=config -h $LOCALHOST -p $PORT1 -y $CONFIGPWF \
+ > $TESTOUT 2>&1 <<EOF
+dn: olcOverlay={0}unique,olcDatabase={1}$BACKEND,cn=config
+changetype: modify
+add: olcUniqueAttribute
+olcUniqueAttribute: description
+olcUniqueAttribute: telephoneNumber
+-
+delete: olcUniqueAttribute
+olcUniqueAttribute: displayName
+EOF
+RC=$?
+if test $RC != 0 ; then
+ echo "Unable to remove an attribute"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit -1
+fi
+
+echo "Verifying we removed the right attr..."
$LDAPADD -D "$UNIQUEDN" -h $LOCALHOST -p $PORT1 -w $PASSWD > \
$TESTOUT 2>&1 << EOTUNIQ2
dn: uid=bill,ou=users,o=unique
employeeType: contractor
givenName: Bill
EOTUNIQ2
+RC=$?
+if test $RC != 19 ; then
+ echo "olcUniqueAttribtue single deletion hit the wrong value"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit -1
+fi
+echo Removing legacy config and adding URIs...
+$LDAPMODIFY -D cn=config -h $LOCALHOST -p $PORT1 -y $CONFIGPWF \
+ > $TESTOUT 2>&1 <<EOF
+dn: olcOverlay={0}unique,olcDatabase={1}$BACKEND,cn=config
+changetype: modify
+delete: olcUniqueAttribute
+-
+add: olcUniqueURI
+olcUniqueURI: ldap:///?employeeNumber,displayName?sub
+olcUniqueURI: ldap:///?description?one
+EOF
+RC=$?
+if test $RC != 0 ; then
+ echo "Reconfiguration to URIs failed"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit -1
+fi
+
+echo Dynamically retrieving second configuration...
+$LDAPSEARCH -S "" -b olcOverlay='{0}'unique,olcDatabase='{1}'$BACKEND,cn=config -D cn=config -y $CONFIGPWF -h $LOCALHOST -p $PORT1 -LLL | tr -d \\r >testrun/second-config.ldif
+cat >testrun/second-reference.ldif <<EOF
+dn: olcOverlay={0}unique,olcDatabase={1}$BACKEND,cn=config
+objectClass: olcOverlayConfig
+objectClass: olcUniqueConfig
+olcOverlay: {0}unique
+olcUniqueURI: ldap:///?employeeNumber,displayName?sub
+olcUniqueURI: ldap:///?description?one
+
+EOF
+diff testrun/second-config.ldif testrun/second-reference.ldif > /dev/null 2>&1
+RC=$?
+if test $RC != 0 ; then
+ echo "Second configuration is not reported correctly."
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit -1
+fi
+
+echo "Adding a non-unique record..."
+$LDAPADD -D "$UNIQUEDN" -h $LOCALHOST -p $PORT1 -w $PASSWD > \
+ $TESTOUT 2>&1 << EOTUNIQ2
+dn: uid=bill,ou=users,o=unique
+objectClass: inetOrgPerson
+uid: bill
+sn: johnson
+cn: bill
+businessCategory: rtest
+carLicense: ABC123
+departmentNumber: 42
+displayName: Bill
+employeeNumber: 5150
+employeeType: contractor
+givenName: Bill
+EOTUNIQ2
RC=$?
if test $RC != 19 ; then
echo "unique check failed ($RC)!"
exit -1
fi
+echo Dynamically trying to add legacy base
+$LDAPMODIFY -D cn=config -h $LOCALHOST -p $PORT1 -y $CONFIGPWF \
+ > $TESTOUT 2>&1 <<EOF
+dn: olcOverlay={0}unique,olcDatabase={1}$BACKEND,cn=config
+changetype: modify
+add: olcUniqueBase
+olcUniqueBase: o=unique
+EOF
+RC=$?
+if test $RC != 80 ; then
+ echo "legacy base allowed with URIs"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit -1
+fi
+
+echo Dynamically trying to add legacy attrs
+$LDAPMODIFY -D cn=config -h $LOCALHOST -p $PORT1 -y $CONFIGPWF \
+ > $TESTOUT 2>&1 <<EOF
+dn: olcOverlay={0}unique,olcDatabase={1}$BACKEND,cn=config
+changetype: modify
+add: olcUniqueAttribute
+olcUniqueAttribute: description
+EOF
+RC=$?
+if test $RC != 80 ; then
+ echo "legacy attributes allowed with URIs"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit -1
+fi
+
+echo Dynamically trying to add legacy strictness
+$LDAPMODIFY -D cn=config -h $LOCALHOST -p $PORT1 -y $CONFIGPWF \
+ > $TESTOUT 2>&1 <<EOF
+dn: olcOverlay={0}unique,olcDatabase={1}$BACKEND,cn=config
+changetype: modify
+add: olcUniqueStrict
+olcUniqueStrict: TRUE
+EOF
+RC=$?
+if test $RC != 80 ; then
+ echo "legacy strictness allowed with URIs"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit -1
+fi
+
+#echo ----------------------
+echo Dynamically trying a bad filter...
+$LDAPMODIFY -D cn=config -h $LOCALHOST -p $PORT1 -y $CONFIGPWF \
+ > $TESTOUT 2>&1 <<EOF
+dn: olcOverlay={0}unique,olcDatabase={1}$BACKEND,cn=config
+changetype: modify
+replace: olcUniqueURI
+olcUniqueURI: ldap:///?sn?sub?((cn=e*))
+EOF
+RC=$?
+if test $RC != 80 ; then
+ echo "bad filter allowed"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit -1
+fi
+
+echo Verifying second configuration intact...
+$LDAPSEARCH -S "" -b olcOverlay='{0}'unique,olcDatabase='{1}'$BACKEND,cn=config -D cn=config -y $CONFIGPWF -h $LOCALHOST -p $PORT1 -LLL | tr -d \\r >testrun/second-config-recheck.ldif
+diff testrun/second-config-recheck.ldif testrun/second-reference.ldif > /dev/null 2>&1
+RC=$?
+if test $RC != 0 ; then
+ echo "Second configuration damaged by rejected modifies."
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit -1
+fi
+
+#echo ----------------------
+echo Dynamically reconfiguring to use different URIs...
+$LDAPMODIFY -D cn=config -h $LOCALHOST -p $PORT1 -y $CONFIGPWF \
+ > $TESTOUT 2>&1 <<EOF
+dn: olcOverlay={0}unique,olcDatabase={1}$BACKEND,cn=config
+changetype: modify
+add: olcUniqueURI
+olcUniqueURI: ldap:///?sn?sub?(cn=e*)
+-
+delete: olcUniqueURI
+olcUniqueURI: ldap:///?description?one
+EOF
+RC=$?
+if test $RC != 0 ; then
+ echo "unable to reconfigure"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit -1
+fi
+
+echo Dynamically retrieving third configuration...
+$LDAPSEARCH -S "" -b olcOverlay='{0}'unique,olcDatabase='{1}'$BACKEND,cn=config -D cn=config -y $CONFIGPWF -h $LOCALHOST -p $PORT1 -LLL | tr -d \\r >testrun/third-config.ldif
+cat >testrun/third-reference.ldif <<EOF
+dn: olcOverlay={0}unique,olcDatabase={1}$BACKEND,cn=config
+objectClass: olcOverlayConfig
+objectClass: olcUniqueConfig
+olcOverlay: {0}unique
+olcUniqueURI: ldap:///?employeeNumber,displayName?sub
+olcUniqueURI: ldap:///?sn?sub?(cn=e*)
+
+EOF
+diff testrun/third-config.ldif testrun/third-reference.ldif > /dev/null 2>&1
+RC=$?
+if test $RC != 0 ; then
+ echo "Third configuration is not reported correctly."
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit -1
+fi
+
+echo "Adding a record unique in both domains if filtered..."
+
+$LDAPADD -D "$UNIQUEDN" -h $LOCALHOST -p $PORT1 -w $PASSWD > \
+ $TESTOUT 2>&1 << EOF
+dn: uid=edgar,ou=users,o=unique
+objectClass: inetOrgPerson
+uid: edgar
+sn: johnson
+cn: edgar
+EOF
+
+RC=$?
+if test $RC != 0 ; then
+ echo "unique check failed ($RC)!"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit -1
+fi
+
+echo "Adding a record unique in one domain, non-unique in the filtered domain..."
+
+$LDAPADD -D "$UNIQUEDN" -h $LOCALHOST -p $PORT1 -w $PASSWD > \
+ $TESTOUT 2>&1 << EOF
+dn: uid=elvis,ou=users,o=unique
+objectClass: inetOrgPerson
+uid: elvis
+sn: johnson
+cn: elvis
+EOF
+
+RC=$?
+if test $RC != 19 ; then
+ echo "unique check failed ($RC)!"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit -1
+fi
#echo ----------------------
-#$LDAPSEARCH -S "" -b "o=unique" -h $LOCALHOST -p $PORT1
+echo Dynamically reconfiguring to use attribute-ignore URIs...
+$LDAPMODIFY -D cn=config -h $LOCALHOST -p $PORT1 -y $CONFIGPWF \
+ > $TESTOUT 2>&1 <<EOF
+dn: olcOverlay={0}unique,olcDatabase={1}$BACKEND,cn=config
+changetype: modify
+replace: olcUniqueURI
+olcUniqueURI: ignore ldap:///?objectClass,uid,cn,sn?sub
+EOF
+RC=$?
+if test $RC != 0 ; then
+ echo "unable to reconfigure"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit -1
+fi
+echo Dynamically retrieving fourth configuration...
+$LDAPSEARCH -S "" -b olcOverlay='{0}'unique,olcDatabase='{1}'$BACKEND,cn=config -D cn=config -y $CONFIGPWF -h $LOCALHOST -p $PORT1 -LLL | tr -d \\r >testrun/fourth-config.ldif
+cat >testrun/fourth-reference.ldif <<EOF
+dn: olcOverlay={0}unique,olcDatabase={1}$BACKEND,cn=config
+objectClass: olcOverlayConfig
+objectClass: olcUniqueConfig
+olcOverlay: {0}unique
+olcUniqueURI: ignore ldap:///?objectClass,uid,cn,sn?sub
+EOF
+diff testrun/fourth-config.ldif testrun/fourth-reference.ldif > /dev/null 2>&1
+RC=$?
+if test $RC != 0 ; then
+ echo "Fourth configuration is not reported correctly."
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit -1
+fi
+
+echo "Adding a record unique in the ignore-domain..."
+
+$LDAPADD -D "$UNIQUEDN" -h $LOCALHOST -p $PORT1 -w $PASSWD > \
+ $TESTOUT 2>&1 << EOF
+dn: uid=elvis,ou=users,o=unique
+objectClass: inetOrgPerson
+uid: elvis
+sn: johnson
+cn: elvis
+description: left the building
+EOF
+
+RC=$?
+if test $RC != 0 ; then
+ echo "unique check failed ($RC)!"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit -1
+fi
+
+echo "Adding a record non-unique in the ignore-domain..."
+
+$LDAPADD -D "$UNIQUEDN" -h $LOCALHOST -p $PORT1 -w $PASSWD > \
+ $TESTOUT 2>&1 << EOF
+dn: uid=harry,ou=users,o=unique
+objectClass: inetOrgPerson
+uid: harry
+sn: johnson
+cn: harry
+description: left the building
+EOF
+
+RC=$?
+if test $RC != 19 ; then
+ echo "unique check failed ($RC)!"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit -1
+fi
test $KILLSERVERS != no && kill -HUP $KILLPIDS
# configure backside
mkdir -p $TESTDIR $DBDIR1
+$SLAPPASSWD -g -n >$CONFIGPWF
+echo "rootpw `$SLAPPASSWD -T $CONFIGPWF`" >$TESTDIR/configpw.conf
+
+if test $MONITORDB != no ; then
+ DBIX=2
+else
+ DBIX=1
+fi
+
. $CONFFILTER $BACKEND $MONITORDB < $TRANSLUCENTREMOTECONF > $CONF1
echo "Running slapadd to build remote slapd database..."
$SLAPADD -f $CONF1 -l $LDIFTRANSLUCENTCONFIG
echo "Dynamically configuring local slapd without translucent_no_glue..."
$LDAPMODIFY -D cn=config -H $URI2 -y $CONFIGPWF <<EOF
-dn: olcOverlay={0}translucent,olcDatabase={2}$BACKEND,cn=config
+dn: olcOverlay={0}translucent,olcDatabase={$DBIX}$BACKEND,cn=config
changetype: modify
replace: olcTranslucentNoGlue
olcTranslucentNoGlue: FALSE
echo "Dynamically configuring local slapd with translucent_no_glue and translucent_strict..."
$LDAPMODIFY -D cn=config -H $URI2 -y $CONFIGPWF <<EOF
-dn: olcOverlay={0}translucent,olcDatabase={2}$BACKEND,cn=config
+dn: olcOverlay={0}translucent,olcDatabase={$DBIX}$BACKEND,cn=config
changetype: modify
replace: olcTranslucentNoGlue
olcTranslucentNoGlue: TRUE
mkdir -p $TESTDIR $DBDIR1
+$SLAPPASSWD -g -n >$CONFIGPWF
+echo "rootpw `$SLAPPASSWD -T $CONFIGPWF`" >$TESTDIR/configpw.conf
+
echo "Running slapadd to build slapd database..."
. $CONFFILTER $BACKEND $MONITORDB < $VALSORTCONF > $CONF1
$SLAPADD -f $CONF1 -l $LDIFVALSORT
test $KILLSERVERS != no && kill -HUP $KILLPIDS
echo "Filtering producer results..."
-. $LDIFFILTER < $MASTEROUT | grep -iv ^auditcontext: > $MASTERFLT
+. $LDIFFILTER < $MASTEROUT | grep -iv "^auditcontext:" > $MASTERFLT
echo "Filtering consumer results..."
-. $LDIFFILTER < $SLAVEOUT | grep -iv ^auditcontext: > $SLAVEFLT
+. $LDIFFILTER < $SLAVEOUT | grep -iv "^auditcontext:" > $SLAVEFLT
echo "Comparing retrieved entries from producer and consumer..."
$CMP $MASTERFLT $SLAVEFLT > $CMPOUT
mkdir -p $TESTDIR $DBDIR1
+$SLAPPASSWD -g -n >$CONFIGPWF
+echo "rootpw `$SLAPPASSWD -T $CONFIGPWF`" >$TESTDIR/configpw.conf
+
echo "Running slapadd to build slapd database..."
. $CONFFILTER $BACKEND $MONITORDB < $MCONF > $ADDCONF
$SLAPADD -f $ADDCONF -l $LDIFORDERED
fi
. $CONFFILTER $BACKEND $MONITORDB < $DYNLISTCONF > $CONF1
-echo "dynlist-attrset groupOfURLs memberURL" >> $CONF1
-
-echo "Running slapindex to index slapd database..."
-$SLAPINDEX -f $CONF1
-RC=$?
-if test $RC != 0 ; then
- echo "warning: slapindex failed ($RC)"
- echo " assuming no indexing support"
-fi
echo "Starting slapd on TCP/IP port $PORT1..."
$SLAPD -f $CONF1 -h $URI1 -d $LVL $TIMING > $LOG1 2>&1 &
esac
echo "" >> $SEARCHOUT
-echo "Stopping slapd..."
-kill -HUP $KILLPIDS
-wait $KILLPIDS
-
echo "Reconfiguring slapd..."
-. $CONFFILTER $BACKEND $MONITORDB < $DYNLISTCONF > $CONF1
-echo "dynlist-attrset groupOfURLs memberURL member" >> $CONF1
+$LDAPMODIFY -x -D cn=config -h $LOCALHOST -p $PORT1 -y $CONFIGPWF > \
+ $TESTOUT 2>&1 << EOMODS
+version: 1
+dn: olcOverlay={0}dynlist,olcDatabase={2}$BACKEND,cn=config
+changetype: modify
+delete: olcDLattrSet
+olcDLattrSet: {0}
+-
+add: olcDLattrSet
+olcDLattrSet: groupOfURLs memberURL member
+EOMODS
echo "==========================================================" >> $LOG1
-echo "Starting slapd on TCP/IP port $PORT1..."
-$SLAPD -f $CONF1 -h $URI1 -d $LVL $TIMING >> $LOG1 2>&1 &
-PID=$!
-if test $WAIT != 0 ; then
- echo PID $PID
- read foo
-fi
-KILLPIDS="$PID"
-
-sleep 1
-
-echo "Testing slapd searching..."
-for i in 0 1 2 3 4 5; do
- $LDAPSEARCH -s base -b "$MONITOR" -h $LOCALHOST -p $PORT1 \
- '(objectclass=*)' > /dev/null 2>&1
- RC=$?
- if test $RC = 0 ; then
- break
- fi
- echo "Waiting 5 seconds for slapd to start..."
- sleep 5
-done
-
-if test $RC != 0 ; then
- echo "ldapsearch failed ($RC)!"
- test $KILLSERVERS != no && kill -HUP $KILLPIDS
- exit $RC
-fi
-
echo "Adding a dynamic list..."
$LDAPADD -v -D "$MANAGERDN" -h $LOCALHOST -p $PORT1 -w $PASSWD \
> $TESTOUT 2>&1 << EOMODS
esac
echo "" >> $SEARCHOUT
+echo "==========================================================" >> $LOG1
+
+echo "Testing dgIdentity..."
+
+# Set ACL, require authentication to get list contents
+$LDAPMODIFY -x -D cn=config -h $LOCALHOST -p $PORT1 -y $CONFIGPWF > \
+ $TESTOUT 2>&1 << EOMODS
+version: 1
+dn: olcDatabase={2}$BACKEND,cn=config
+changetype: modify
+add: olcAccess
+olcAccess: to dn.base="cn=Dynamic List of Members,$LISTDN" by * read
+olcAccess: to * by users read by * search
+EOMODS
+
+echo "Testing list search without dgIdentity..."
+echo "# Testing list search without dgIdentity..." >> $SEARCHOUT
+$LDAPSEARCH -S "" -b "$LISTDN" -h $LOCALHOST -p $PORT1 \
+ '(cn=Dynamic List of Members)' '*' \
+ >> $SEARCHOUT 2>&1
+RC=$?
+if test $RC != 0 ; then
+ echo "ldapsearch failed ($RC)!"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit $RC
+fi
+
+$LDAPMODIFY -v -D "$MANAGERDN" -h $LOCALHOST -p $PORT1 -w $PASSWD \
+ > $TESTOUT 2>&1 << EOMODS
+dn: cn=Dynamic List of Members,$LISTDN
+changetype: modify
+add: objectClass
+objectClass: dgIdentityAux
+-
+add: dgIdentity
+dgIdentity: $CMPDN
+EOMODS
+
+echo "Testing list search with dgIdentity..."
+echo "# Testing list search with dgIdentity..." >> $SEARCHOUT
+$LDAPSEARCH -S "" -b "$LISTDN" -h $LOCALHOST -p $PORT1 \
+ '(cn=Dynamic List of Members)' '*' \
+ >> $SEARCHOUT 2>&1
+RC=$?
+if test $RC != 0 ; then
+ echo "ldapsearch failed ($RC)!"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit $RC
+fi
+
test $KILLSERVERS != no && kill -HUP $KILLPIDS
LDIF=$DYNLISTOUT
$LDAPSEARCH -s base -b "$MONITOR" -h $LOCALHOST -p $PORT3 \
'(objectClass=*)' > /dev/null 2>&1
RC=$?
- if test $RC = 0 -o $RC = 53 ; then
+ if test $RC = 0 || test $RC = 53 ; then
break
fi
echo "Waiting 5 seconds for slapd to start..."
DBCON=$CONDIR/db
CFPRO=$PRODIR/slapd.d
CFCON=$CONDIR/slapd.d
-LOG1=slapd.1.log
-LOG2=slapd.2.log
mkdir -p $TESTDIR $PRODIR $CONDIR $DBPRO $DBCON $CFPRO $CFCON
+$SLAPPASSWD -g -n >$CONFIGPWF
+
#
# Test replication of dynamic config:
# - start producer
#
echo "Starting producer slapd on TCP/IP port $PORT1..."
-$SLAPADD -F $CFPRO -n 0 -l $DYNAMICCONF
+. $CONFFILTER $BACKEND $MONITORDB < $DYNAMICCONF > $CONFLDIF
+$SLAPADD -F $CFPRO -n 0 -l $CONFLDIF
cd $PRODIR
-$SLAPD -F ./slapd.d -h $URI1 -d $LVL $TIMING > ../$LOG1 2>&1 &
+$SLAPD -F ./slapd.d -h $URI1 -d $LVL $TIMING > $LOG1 2>&1 &
PID=$!
if test $WAIT != 0 ; then
echo PID $PID
read foo
fi
KILLPIDS="$PID"
-cd ../..
+cd $TESTWD
sleep 1
exit $RC
fi
fi
-CONFIGPW=`cat $CONFIGPWF`
+read CONFIGPW < $CONFIGPWF
$LDAPMODIFY -D cn=config -H $URI1 -y $CONFIGPWF <<EOF >> $TESTOUT 2>&1
dn: olcDatabase={0}config,cn=config
changetype: modify
fi
echo "Starting consumer slapd on TCP/IP port $PORT2..."
-$SLAPADD -F $CFCON -n 0 -l $DYNAMICCONF
+$SLAPADD -F $CFCON -n 0 -l $CONFLDIF
cd $CONDIR
-$SLAPD -F ./slapd.d -h $URI2 -d $LVL $TIMING > ../$LOG2 2>&1 &
+$SLAPD -F ./slapd.d -h $URI2 -d $LVL $TIMING > $LOG2 2>&1 &
SLAVEPID=$!
if test $WAIT != 0 ; then
echo SLAVEPID $SLAVEPID
read foo
fi
KILLPIDS="$KILLPIDS $SLAVEPID"
-cd ../..
+cd $TESTWD
sleep 1
DBCON=$CONDIR/db
CFPRO=$PRODIR/slapd.d
CFCON=$CONDIR/slapd.d
-LOG1=slapd.1.log
-LOG2=slapd.2.log
mkdir -p $TESTDIR $PRODIR $CONDIR $DBPRO $DBCON $CFPRO $CFCON
+$SLAPPASSWD -g -n >$CONFIGPWF
+
#
# Test replication of dynamic config:
# - start producer
dn: olcDatabase={0}config,cn=config
objectClass: olcDatabaseConfig
olcDatabase: {0}config
-olcRootPW:< file:configpw
+olcRootPW:< file://$CONFIGPWF
EOF
$SLAPADD -F $CFPRO -n 0 <<EOF
dn: olcDatabase={0}config,cn=config
objectClass: olcDatabaseConfig
olcDatabase: {0}config
-olcRootPW:< file:configpw
+olcRootPW:< file://$CONFIGPWF
EOF
echo "Starting producer slapd on TCP/IP port $PORT1..."
cd $PRODIR
-$SLAPD -F ./slapd.d -h $URI1 -d $LVL $TIMING > ../$LOG1 2>&1 &
+$SLAPD -F slapd.d -h $URI1 -d $LVL $TIMING > $LOG1 2>&1 &
PID=$!
if test $WAIT != 0 ; then
echo PID $PID
read foo
fi
KILLPIDS="$PID"
-cd ../..
+cd $TESTWD
sleep 1
# neither server will progress. The timeout will drop the syncrepl
# attempt and allow the modifies to complete.
#
-CONFIGPW=`cat $CONFIGPWF`
+read CONFIGPW < $CONFIGPWF
$LDAPMODIFY -D cn=config -H $URI1 -y $CONFIGPWF <<EOF >> $TESTOUT 2>&1
dn: cn=config
changetype: modify
echo "Starting consumer slapd on TCP/IP port $PORT2..."
cd $CONDIR
-$SLAPD -F ./slapd.d -h $URI2 -d $LVL $TIMING > ../$LOG2 2>&1 &
+$SLAPD -F ./slapd.d -h $URI2 -d $LVL $TIMING > $LOG2 2>&1 &
SLAVEPID=$!
if test $WAIT != 0 ; then
echo SLAVEPID $SLAVEPID
read foo
fi
KILLPIDS="$KILLPIDS $SLAVEPID"
-cd ../..
+cd $TESTWD
sleep 1
echo "Restarting servers..."
echo "Starting producer slapd on TCP/IP port $PORT1..."
cd $PRODIR
-echo "======================= RESTART =======================" >> ../$LOG1
-$SLAPD -F ./slapd.d -h $URI1 -d $LVL $TIMING >> ../$LOG1 2>&1 &
+echo "======================= RESTART =======================" >> $LOG1
+$SLAPD -F ./slapd.d -h $URI1 -d $LVL $TIMING >> $LOG1 2>&1 &
PID=$!
if test $WAIT != 0 ; then
echo PID $PID
read foo
fi
KILLPIDS="$PID"
-cd ../..
+cd $TESTWD
echo "Using ldapsearch to check that producer slapd is running..."
for i in 0 1 2 3 4 5; do
$LDAPSEARCH -s base -b "" -H $URI1 \
#exit 0
echo "Starting consumer slapd on TCP/IP port $PORT2..."
cd $CONDIR
-echo "======================= RESTART =======================" >> ../$LOG2
-$SLAPD -F ./slapd.d -h $URI2 -d $LVL $TIMING >> ../$LOG2 2>&1 &
+echo "======================= RESTART =======================" >> $LOG2
+$SLAPD -F ./slapd.d -h $URI2 -d $LVL $TIMING >> $LOG2 2>&1 &
SLAVEPID=$!
if test $WAIT != 0 ; then
echo SLAVEPID $SLAVEPID
read foo
fi
KILLPIDS="$KILLPIDS $SLAVEPID"
-cd ../..
+cd $TESTWD
sleep 1
mkdir -p $TESTDIR $DBDIR1
+$SLAPPASSWD -g -n >$CONFIGPWF
+echo "rootpw `$SLAPPASSWD -T $CONFIGPWF`" >$TESTDIR/configpw.conf
+
echo "Running slapadd to build slapd database..."
. $CONFFILTER $BACKEND $MONITORDB < $UNDOCONF > $CONF1
$SLAPADD -f $CONF1 <<EOF
fi
echo "Starting slapd on TCP/IP port $PORT1..."
-mkdir testrun/confdir
-$SLAPD -f $CONF1 -F testrun/confdir -h $URI1 -d $LVL $TIMING > $LOG1 2>&1 &
+mkdir $TESTDIR/confdir
+$SLAPD -f $CONF1 -F $TESTDIR/confdir -h $URI1 -d $LVL $TIMING > $LOG1 2>&1 &
PID=$!
if test $WAIT != 0 ; then
echo PID $PID
fi
echo Surveying the damage
-$LDAPMODIFY -D cn=manager,o=undo -w secret -h $LOCALHOST -p $PORT1 <<EOF
+$LDAPMODIFY -D "cn=manager,o=undo" -w secret -h $LOCALHOST -p $PORT1 <<EOF
dn: o=foo,o=undo
changetype: add
objectClass: organization