OpenLDAP 2.4 Change Log
-OpenLDAP 2.4.0alpha Release
+OpenLDAP 2.4.1alpha Engineering
Changes not tracked
echo "No guide"
fi
+if test -e $RELNAME/libraries/liblunicode/ucdata/uctable.h ; then
+ echo "touching uctable.h..."
+ touch $RELNAME/libraries/liblunicode/ucdata/uctable.h
+fi
+
if test ! -e $RELNAME/build/version.sh ; then
echo "No build version"
OL_STRING="something"
ol_package=OpenLDAP
ol_major=2
ol_minor=4
-ol_patch=0alpha
+ol_patch=X
ol_api_inc=20400
ol_api_current=0
ol_api_revision=0
return rc;
}
- if( verbose || code != LDAP_SUCCESS ||
- (matcheddn && *matcheddn) || (text && *text) || (refs && *refs) )
+ if( code != LDAP_SUCCESS ) {
+ tool_perror( "ldap_delete", code, NULL, matcheddn, text, refs );
+ } else if ( verbose &&
+ ((matcheddn && *matcheddn) || (text && *text) || (refs && *refs) ))
{
printf( _("Delete Result: %s (%d)\n"),
ldap_err2string( code ), code );
}
if (ldif < 2 ) {
+ char *realbase = base;
+
+ if ( realbase == NULL ) {
+ ldap_get_option( ld, LDAP_OPT_DEFBASE, (void **)&realbase );
+ }
+
printf( "#\n" );
printf(_("# LDAPv%d\n"), protocol);
- printf(_("# base <%s> with scope %s\n"),
- base ? base : "",
+ printf(_("# base <%s>%s with scope %s\n"),
+ realbase ? realbase : "",
+ ( realbase == NULL || realbase != base ) ? " (default)" : "",
((scope == LDAP_SCOPE_BASE) ? "baseObject"
: ((scope == LDAP_SCOPE_ONELEVEL) ? "oneLevel"
: ((scope == LDAP_SCOPE_SUBORDINATE) ? "children"
}
printf( _("\n#\n\n") );
+
+ if ( realbase && realbase != base ) {
+ ldap_memfree( realbase );
+ }
}
if ( infile == NULL ) {
if( text ) {
if( *text ) {
- if( !ldif ) {
- tool_write_ldif( LDIF_PUT_TEXT, "text",
- text, strlen(text) );
- } else {
- fprintf( stderr, _("Additional information: %s\n"), text );
- }
+ if( !ldif ) {
+ if ( err == LDAP_PARTIAL_RESULTS ) {
+ char *line;
+
+ for ( line = text; line != NULL; ) {
+ char *next = strchr( line, '\n' );
+
+ tool_write_ldif( LDIF_PUT_TEXT,
+ "text", line,
+ next ? next - line : strlen( line ) );
+
+ line = next ? next + 1 : NULL;
+ }
+
+ } else {
+ tool_write_ldif( LDIF_PUT_TEXT, "text",
+ text, strlen(text) );
+ }
+ } else {
+ fprintf( stderr, _("Additional information: %s\n"), text );
+ }
}
ber_memfree( text );
#! /bin/sh
-# From configure.in OpenLDAP: pkg/ldap/configure.in,v 1.631.2.1 2006/04/11 16:07:14 kurt Exp .
+# From configure.in OpenLDAP: pkg/ldap/configure.in,v 1.633 2006/04/29 08:09:31 hyc 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_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 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_files=''
# Initialize some variables set by options.
--enable-overlays enable all available overlays no|yes|mod
--enable-accesslog In-Directory Access Logging overlay no|yes|mod [no]
--enable-auditlog Audit Logging overlay no|yes|mod [no]
+ --enable-constraint Attribute Constraint overlay no|yes|mod [no]
--enable-dds Dynamic Directory Services overlay no|yes|mod [no]
--enable-denyop Deny Operation overlay no|yes|mod [no]
--enable-dyngroup Dynamic Group overlay no|yes|mod [no]
Overlays="accesslog \
auditlog \
+ constraint \
dds \
denyop \
dyngroup \
fi;
# end --enable-auditlog
+# OpenLDAP --enable-constraint
+
+ # Check whether --enable-constraint or --disable-constraint was given.
+if test "${enable_constraint+set}" = set; then
+ enableval="$enable_constraint"
+
+ 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-constraint" >&5
+echo "$as_me: error: bad value $enableval for --enable-constraint" >&2;}
+ { (exit 1); exit 1; }; }
+ fi
+ ol_enable_constraint="$ol_arg"
+
+else
+ ol_enable_constraint=${ol_enable_overlays:-no}
+fi;
+# end --enable-constraint
+
# OpenLDAP --enable-dds
# Check whether --enable-dds or --disable-dds was given.
BUILD_ACCESSLOG=no
BUILD_AUDITLOG=no
+BUILD_CONSTRAINT=no
BUILD_DDS=no
BUILD_DENYOP=no
BUILD_DYNGROUP=no
;;
*-*-irix6*)
# Find out which ABI we are using.
- echo '#line 5638 "configure"' > conftest.$ac_ext
+ echo '#line 5665 "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:7618: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:7645: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
- echo "$as_me:7622: \$? = $ac_status" >&5
+ echo "$as_me:7649: \$? = $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:7880: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:7907: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
- echo "$as_me:7884: \$? = $ac_status" >&5
+ echo "$as_me:7911: \$? = $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:7942: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:7969: $lt_compile\"" >&5)
(eval "$lt_compile" 2>out/conftest.err)
ac_status=$?
cat out/conftest.err >&5
- echo "$as_me:7946: \$? = $ac_status" >&5
+ echo "$as_me:7973: \$? = $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 10190 "configure"
+#line 10217 "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 10288 "configure"
+#line 10315 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
fi
+if test "$ol_enable_constraint" != no ; then
+ BUILD_CONSTRAINT=$ol_enable_constraint
+ if test "$ol_enable_constraint" = mod ; then
+ MFLAG=SLAPD_MOD_DYNAMIC
+ SLAPD_DYNAMIC_OVERLAYS="$SLAPD_DYNAMIC_OVERLAYS constraint.la"
+ else
+ MFLAG=SLAPD_MOD_STATIC
+ SLAPD_STATIC_OVERLAYS="$SLAPD_STATIC_OVERLAYS constraint.o"
+ fi
+
+cat >>confdefs.h <<_ACEOF
+#define SLAPD_OVER_CONSTRAINT $MFLAG
+_ACEOF
+
+fi
+
if test "$ol_enable_dds" != no ; then
BUILD_DDS=$ol_enable_dds
if test "$ol_enable_dds" = mod ; then
+
# Check whether --with-xxinstall or --without-xxinstall was given.
s,@BUILD_SQL@,$BUILD_SQL,;t t
s,@BUILD_ACCESSLOG@,$BUILD_ACCESSLOG,;t t
s,@BUILD_AUDITLOG@,$BUILD_AUDITLOG,;t t
+s,@BUILD_CONSTRAINT@,$BUILD_CONSTRAINT,;t t
s,@BUILD_DDS@,$BUILD_DDS,;t t
s,@BUILD_DENYOP@,$BUILD_DENYOP,;t t
s,@BUILD_DYNGROUP@,$BUILD_DYNGROUP,;t t
dnl SLAPD Overlay Options
Overlays="accesslog \
auditlog \
+ constraint \
dds \
denyop \
dyngroup \
no, [no yes mod], ol_enable_overlays)
OL_ARG_ENABLE(auditlog,[ --enable-auditlog Audit Logging overlay],
no, [no yes mod], ol_enable_overlays)
+OL_ARG_ENABLE(constraint,[ --enable-constraint Attribute Constraint overlay],
+ no, [no yes mod], ol_enable_overlays)
OL_ARG_ENABLE(dds,[ --enable-dds Dynamic Directory Services overlay],
no, [no yes mod], ol_enable_overlays)
OL_ARG_ENABLE(denyop,[ --enable-denyop Deny Operation overlay],
BUILD_ACCESSLOG=no
BUILD_AUDITLOG=no
+BUILD_CONSTRAINT=no
BUILD_DDS=no
BUILD_DENYOP=no
BUILD_DYNGROUP=no
AC_DEFINE_UNQUOTED(SLAPD_OVER_AUDITLOG,$MFLAG,[define for Audit Logging overlay])
fi
+if test "$ol_enable_constraint" != no ; then
+ BUILD_CONSTRAINT=$ol_enable_constraint
+ if test "$ol_enable_constraint" = mod ; then
+ MFLAG=SLAPD_MOD_DYNAMIC
+ SLAPD_DYNAMIC_OVERLAYS="$SLAPD_DYNAMIC_OVERLAYS constraint.la"
+ else
+ MFLAG=SLAPD_MOD_STATIC
+ SLAPD_STATIC_OVERLAYS="$SLAPD_STATIC_OVERLAYS constraint.o"
+ fi
+ AC_DEFINE_UNQUOTED(SLAPD_OVER_CONSTRAINT,$MFLAG,[define for Attribute Constraint overlay])
+fi
+
if test "$ol_enable_dds" != no ; then
BUILD_DDS=$ol_enable_dds
if test "$ol_enable_dds" = mod ; then
dnl overlays
AC_SUBST(BUILD_ACCESSLOG)
AC_SUBST(BUILD_AUDITLOG)
+ AC_SUBST(BUILD_CONSTRAINT)
AC_SUBST(BUILD_DDS)
AC_SUBST(BUILD_DENYOP)
AC_SUBST(BUILD_DYNGROUP)
This directory contains native slapd plugins for password mechanisms that
are not actively supported by the project. Currently this includes the
-Kerberos and Netscape MTA-MD5 password mechanisms.
+Kerberos, Netscape MTA-MD5 and RADIUS password mechanisms.
To use the Kerberos plugin, add:
to your slapd configuration file.
+To use the RADIUS plugin, add:
+
+moduleload pw-radius.so
+
+to your slapd configuration file; optionally, the path to a configuration
+file can be appended in the form
+
+moduleload pw-radius.so config="/etc/radius.conf"
+
No Makefile is provided. Use a command line similar to:
gcc -shared -I../../../include -Wall -g -DHAVE_KRB5 -o pw-kerberos.so kerberos.c
gcc -shared -I../../../include -Wall -g -o pw-netscape.so netscape.c
+The corresponding command for the RADIUS plugin would be:
+
+gcc -shared -I../../../include -Wall -g -o pw-radius.so radius.c -lradius
+
+(Actually, you might want to statically link the RADIUS client library
+libradius.a into the module).
+
--- /dev/null
+/* $OpenLDAP$ */
+/*
+ * Copyright 1998-2006 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 <stdio.h>
+
+#include <lber.h>
+#include <lber_pvt.h> /* BER_BVC definition */
+#include "lutil.h"
+#include <ac/string.h>
+#include <ac/unistd.h>
+
+#include <radlib.h>
+
+static LUTIL_PASSWD_CHK_FUNC chk_radius;
+static const struct berval scheme = BER_BVC("{RADIUS}");
+static char *config_filename;
+
+static int
+chk_radius(
+ const struct berval *sc,
+ const struct berval *passwd,
+ const struct berval *cred,
+ const char **text )
+{
+ unsigned int i;
+ int rc = LUTIL_PASSWD_ERR;
+
+ struct rad_handle *h = NULL;
+
+ for ( i = 0; i < cred->bv_len; i++ ) {
+ if ( cred->bv_val[ i ] == '\0' ) {
+ return LUTIL_PASSWD_ERR; /* NUL character in cred */
+ }
+ }
+
+ if ( cred->bv_val[ i ] != '\0' ) {
+ return LUTIL_PASSWD_ERR; /* cred must behave like a string */
+ }
+
+ for ( i = 0; i < passwd->bv_len; i++ ) {
+ if ( passwd->bv_val[ i ] == '\0' ) {
+ return LUTIL_PASSWD_ERR; /* NUL character in password */
+ }
+ }
+
+ if ( passwd->bv_val[ i ] != '\0' ) {
+ return LUTIL_PASSWD_ERR; /* passwd must behave like a string */
+ }
+
+ h = rad_auth_open();
+ if ( h == NULL ) {
+ return LUTIL_PASSWD_ERR;
+ }
+
+ if ( rad_config( h, config_filename ) != 0 ) {
+ goto done;
+ }
+
+ if ( rad_create_request( h, RAD_ACCESS_REQUEST ) ) {
+ goto done;
+ }
+
+ if ( rad_put_string( h, RAD_USER_NAME, passwd->bv_val ) != 0 ) {
+ goto done;
+ }
+
+ if ( rad_put_string( h, RAD_USER_PASSWORD, cred->bv_val ) != 0 ) {
+ goto done;
+ }
+
+ if ( rad_send_request( h ) == RAD_ACCESS_ACCEPT ) {
+ rc = LUTIL_PASSWD_OK;
+ }
+
+done:;
+ rad_close( h );
+
+ return rc;
+}
+
+int
+init_module( int argc, char *argv[] )
+{
+ int i;
+
+ for ( i = 0; i < argc; i++ ) {
+ if ( strncasecmp( argv[ i ], "config=", STRLENOF( "config=" ) ) == 0 ) {
+ /* FIXME: what if multiple loads of same module?
+ * does it make sense (e.g. override an existing one)? */
+ if ( config_filename == NULL ) {
+ config_filename = ber_strdup( &argv[ i ][ STRLENOF( "config=" ) ] );
+ }
+
+ } else {
+ fprintf( stderr, "init_module(radius): unknown arg#%d=\"%s\".\n",
+ i, argv[ i ] );
+ return 1;
+ }
+ }
+
+ return lutil_passwd_add( (struct berval *)&scheme, chk_radius, NULL );
+}
This marks the beginning of a new {{TERM:BDB}} database instance.
-H4: olcAccess: to <what> [ by <who> <accesslevel> <control> ]+
+H4: olcAccess: to <what> [ by <who> [<accesslevel>] [<control>] ]+
This directive grants access (specified by <accesslevel>) to a
set of entries and/or attributes (specified by <what>) by one or
> olcAccess: <access directive>
> <access directive> ::= to <what>
-> [by <who> <access> <control>]+
+> [by <who> [<access>] [<control>] ]+
> <what> ::= * |
> [dn[.<basic-style>]=<regex> | dn.<scope-style>=<DN>]
> [filter=<ldapfilter>] [attrs=<attrlist>]
by actual text are shown in brackets {{EX:<>}}.
-H4: access to <what> [ by <who> <accesslevel> <control> ]+
+H4: access to <what> [ by <who> [<accesslevel>] [<control>] ]+
This directive grants access (specified by <accesslevel>) to a
set of entries and/or attributes (specified by <what>) by one or
access line is:
> <access directive> ::= access to <what>
-> [by <who> <access> <control>]+
+> [by <who> [<access>] [<control>] ]+
> <what> ::= * |
> [dn[.<basic-style>]=<regex> | dn.<scope-style>=<DN>]
> [filter=<ldapfilter>] [attrs=<attrlist>]
argument, resulting in the underlying library automatically
call the first server of the list that responds, e.g.
-\fBuri "ldap://host/ ldap://backup-host"\fP
+\fBuri "ldap://host/ ldap://backup-host/"\fP
The URI list is space- or comma-separated.
-This statement is mandatory.
+.\"This statement is mandatory.
.\".TP
.\".B server <hostport>
.\"Obsolete option; same as `uri ldap://<hostport>/'.
.BR acl-passwd .
.RE
+.TP
+.B chase-referrals {YES|no}
+enable/disable automatic referral chasing, which is delegated to the
+underlying libldap, with rebinding eventually performed if the
+\fBrebind-as-user\fP directive is used. The default is to chase referrals.
+
+.TP
+.B conn-ttl <time>
+This directive causes a cached connection to be dropped an recreated
+after a given ttl, regardless of being idle or not.
+
+.TP
+.B idassert-authzFrom <authz-regexp>
+if defined, selects what
+.I local
+identities are authorized to exploit the identity assertion feature.
+The string
+.B <authz-regexp>
+follows the rules defined for the
+.I authzFrom
+attribute.
+See
+.BR slapd.conf (5),
+section related to
+.BR authz-policy ,
+for details on the syntax of this field.
+
.HP
.hy 0
.B idassert-bind
.RE
.TP
-.B idassert-authzFrom <authz-regexp>
-if defined, selects what
-.I local
-identities are authorized to exploit the identity assertion feature.
-The string
-.B <authz-regexp>
-follows the rules defined for the
-.I authzFrom
-attribute.
-See
-.BR slapd.conf (5),
-section related to
-.BR authz-policy ,
-for details on the syntax of this field.
+.B idle-timeout <time>
+This directive causes a cached connection to be dropped an recreated
+after it has been idle for the specified time.
.TP
-.B proxy-whoami {NO|yes}
+.B protocol\-version {0,2,3}
+This directive indicates what protocol version must be used to contact
+the remote server.
+If set to 0 (the default), the proxy uses the same protocol version
+used by the client, otherwise the requested protocol is used.
+The proxy returns \fIunwillingToPerform\fP if an operation that is
+incompatible with the requested protocol is attempted.
+
+.TP
+.B single\-conn {NO|yes}
+Discards current cached connection when the client rebinds.
+
+.TP
+.B proxy\-whoami {NO|yes}
Turns on proxying of the WhoAmI extended operation. If this option is
given, back-ldap will replace slapd's original WhoAmI routine with its
own. On slapd sessions that were authenticated by back-ldap, the WhoAmI
for rebinds when chasing referrals. Useful when
\fBchase-referrals\fP is set to \fByes\fP, useless otherwise.
-.TP
-.B chase-referrals {YES|no}
-enable/disable automatic referral chasing, which is delegated to the
-underlying libldap, with rebinding eventually performed if the
-\fBrebind-as-user\fP directive is used. The default is to chase referrals.
-
-.TP
-.B tls {[try-]start|[try-]propagate}
-execute the StartTLS extended operation when the connection is initialized;
-only works if the URI directive protocol scheme is not \fBldaps://\fP.
-\fBpropagate\fP issues the StartTLS operation only if the original
-connection did.
-The \fBtry-\fP prefix instructs the proxy to continue operations
-if the StartTLS operation failed; its use is highly deprecated.
-
.TP
.B t-f-support {NO|yes|discover}
enable if the remote server supports absolute filters
so the client will not know if the operation eventually succeeded or not.
.TP
-.B idle-timeout <time>
-This directive causes a cached connection to be dropped an recreated
-after it has been idle for the specified time.
-
-.TP
-.B conn-ttl <time>
-This directive causes a cached connection to be dropped an recreated
-after a given ttl, regardless of being idle or not.
+.B tls {[try-]start|[try-]propagate}
+execute the StartTLS extended operation when the connection is initialized;
+only works if the URI directive protocol scheme is not \fBldaps://\fP.
+\fBpropagate\fP issues the StartTLS operation only if the original
+connection did.
+The \fBtry-\fP prefix instructs the proxy to continue operations
+if the StartTLS operation failed; its use is highly deprecated.
.SH BACKWARD COMPATIBILITY
The LDAP backend has been heavily reworked between releases 2.2 and 2.3;
as an error is returned by one target, and the error is immediately
propagated to the client.
+.TP
+.B protocol\-version {0,2,3}
+This directive indicates what protocol version must be used to contact
+the remote server.
+If set to 0 (the default), the proxy uses the same protocol version
+used by the client, otherwise the requested protocol is used.
+The proxy returns \fIunwillingToPerform\fP if an operation that is
+incompatible with the requested protocol is attempted.
+If set before any target specification, it affects all targets, unless
+overridden by any per-target directive.
+
.TP
.B pseudoroot-bind-defer {NO|yes}
This directive, when set to
If this option is given, the client's bind credentials are remembered
for rebinds when chasing referrals.
+.TP
+.B single\-conn {NO|yes}
+Discards current cached connection when the client rebinds.
+
.SH TARGET SPECIFICATION
Target specification starts with a "uri" directive:
does not respond.
.RE
-.TP
-.B subtree-exclude "<DN>"
-This directive instructs back-meta to ignore the current target
-for operations whose requestDN is subordinate to
-.BR DN .
-There may be multiple occurrences of the
-.B subtree-exclude
-directive for each of the targets.
-
.TP
.B acl-authcDN "<administrative DN for access control purposes>"
DN which is used to query the target server for acl checking,
.B rewrite* ...
The rewrite options are described in the "REWRITING" section.
+.TP
+.B subtree-exclude "<DN>"
+This directive instructs back-meta to ignore the current target
+for operations whose requestDN is subordinate to
+.BR DN .
+There may be multiple occurrences of the
+.B subtree-exclude
+directive for each of the targets.
+
.TP
.B suffixmassage "<virtual naming context>" "<real naming context>"
All the directives starting with "rewrite" refer to the rewrite engine
.br
- Updates return success (unless readonly is on) but do nothing.
.br
-- Binds fail unless the database option "bind on" is given.
+- Binds other than as the rootdn fail unless the database option "bind
+on" is given.
.br
- The
.BR slapadd (8)
Operations for which a command is not supplied will be refused with an
"unwilling to perform" error.
.LP
-The commands - except \fBunbind\fP - should output:
+The \fBsearch\fP command should output the entries in LDIF format,
+each entry followed by a blank line, and after these the RESULT below.
+.LP
+All commands except \fBunbind\fP should then output:
.RS
.nf
RESULT
info: <text>
.fi
.RE
-where only RESULT is mandatory.
-The \fBsearch\fP RESULT should be preceded by the entries in LDIF
-format, each entry followed by a blank line.
+where only the RESULT line is mandatory.
Lines starting with `#' or `DEBUG:' are ignored.
.SH ACCESS CONTROL
The
.SH THE ACCESS DIRECTIVE
The structure of the access control directives is
.TP
-.B access to <what> "[ by <who> <access> [ <control> ] ]+"
+.B access to <what> "[ by <who> [ <access> ] [ <control> ] ]+"
Grant access (specified by
.BR <access> )
to a set of entries and/or attributes (specified by
.BR <what> )
by one or more requestors (specified by
.BR <who> ).
+
+.LP
+Lists of access directives are evaluated in the order they appear
+in \fIslapd.conf\fP.
+When a
+.B <what>
+clause matches the datum whose access is being evaluated, its
+.B <who>
+clause list is checked.
+When a
+.B <who>
+clause matches the accessor's properties, its
+.B <access>
+and
+.B <control>
+clauses are evaluated.
+Access control checking stops at the first match of the
+.B <what>
+and
+.B <who>
+clause, unless otherwise dictated by the
+.B <control>
+clause.
+Each
+.B <who>
+clause list is implicitly terminated by a
+.LP
+.nf
+ by * none stop
+.fi
+.LP
+clause that results in stopping the access control with no access
+privileges granted.
+Each
+.B <what>
+clause list is implicitly terminated by a
+.LP
+.nf
+ access to *
+ by * none
+.fi
+.LP
+clause that results in granting no access privileges to an otherwise
+unspecified datum.
.SH THE <WHAT> FIELD
The field
.BR <what>
It can have the forms
.LP
.nf
- [dn[.<dnstyle>]=]<dnpattern>
+ dn[.<dnstyle>]=<dnpattern>
filter=<ldapfilter>
attrs=<attrlist>[ val[/matchingRule][.<attrstyle>]=<attrval>]
.fi
The statement
.B dn=<dnpattern>
selects the entries based on their naming context.
-The
-.B dn=
-part is optional.
The
.B <dnpattern>
is a string representation of the entry's DN.
.LP
The
.B <dnstyle>
-is also optional; however, it is recommended to specify both the
-.B dn=
-and the
-.B <dnstyle>
-to avoid ambiguities.
+is optional; however, it is recommended to specify it to avoid ambiguities.
.B Base
(synonym of
.BR baseObject ),
set the minimum required Security Strength Factor (ssf) needed
to grant access. The value should be positive integer.
.SH THE <ACCESS> FIELD
-The field
+The optional field
.B <access> ::= [[real]self]{<level>|<priv>}
determines the access level or the specific access privileges the
.B who
More than one of the above privileges can be added in one statement.
.B 0
indicates no privileges and is used only by itself (e.g., +0).
+.LP
If no access is given, it defaults to
.BR +0 .
.SH THE <CONTROL> FIELD
.hy 0
.B syncrepl rid=<replica ID>
.B provider=ldap[s]://<hostname>[:port]
+.B searchbase=<base DN>
.B [type=refreshOnly|refreshAndPersist]
.B [interval=dd:hh:mm:ss]
.B [retry=[<retry interval> <# of retries>]+]
-.B [searchbase=<base DN>]
.B [filter=<filter str>]
.B [scope=sub|one|base|subord]
.B [attrs=<attr list>]
.B [sizelimit=<limit>]
.B [timelimit=<limit>]
.B [schemachecking=on|off]
-.B [starttls=yes|critical]
.B [bindmethod=simple|sasl]
.B [binddn=<dn>]
.B [saslmech=<mech>]
.B [credentials=<passwd>]
.B [realm=<realm>]
.B [secprops=<properties>]
+.B [starttls=yes|critical]
+.B [tls_cert=<file>]
+.B [tls_key=<file>]
+.B [tls_cacert=<file>]
+.B [tls_cacertdir=<path>]
+.B [tls_reqcert=never|allow|try|demand]
+.B [tls_ciphersuite=<ciphers>]
+.B [tls_crlcheck=none|peer|all]
.B [logbase=<base DN>]
.B [logfilter=<filter str>]
.B [syncdata=default|accesslog|changelog]
consumer site by turning on the
.B schemachecking
parameter. The default is off.
-The
-.B starttls
-parameter specifies use of the StartTLS extended operation
-to establish a TLS session before Binding to the provider. If the
-.B critical
-argument is supplied, the session will be aborted if the StartTLS request
-fails. Otherwise the syncrepl session continues without TLS.
A
.B bindmethod
of
.B realm
option.
+The
+.B starttls
+parameter specifies use of the StartTLS extended operation
+to establish a TLS session before Binding to the provider. If the
+.B critical
+argument is supplied, the session will be aborted if the StartTLS request
+fails. Otherwise the syncrepl session continues without TLS. Note that the
+main slapd TLS settings are not used by the syncrepl engine;
+by default the TLS parameters from ETCDIR/ldap.conf will be used.
+TLS settings may be specified here, in which case the ldap.conf settings
+will be completely ignored.
+
Rather than replicating whole entries, the consumer can query logs of
data modifications. This mode of operation is referred to as \fIdelta
syncrepl\fP. In addition to the above parameters, the
all operations
.RE
.TP
+.B logold <filter>
+Specify a filter for matching against Deleted and Modified entries. If
+the entry matches the filter, the old contents of the entry will be
+logged along with the current request.
+.TP
+.B logoldattr <attr> ...
+Specify a list of attributes whose old contents are always logged in
+Modify and ModRDN requests. Usually only the contents of attributes that were
+actually modified will be logged; by default no old attributes are logged
+for ModRDN requests.
+.TP
.B logpurge <age> <interval>
Specify the maximum age for log entries to be retained in the database,
and how often to scan the database for old entries. Both the
overlay accesslog
logdb cn=log
logops writes reads
+ logold (objectclass=person)
.fi
.SH SCHEMA
This schema is specifically designed for
.B accesslog
auditing and is not intended to be used otherwise. It is also
-noted that the schema describe here is
+noted that the schema described here is
.I a work in
.IR progress ,
and hence subject to change without notice.
attribute: value
.RE
.PD
-This option is not yet implemented.
+The
+.B reqOld
+attribute is only populated if the entry being deleted matches the
+configured
+.B logold
+filter.
.LP
.RS 4
optionally contain the previous contents of any modified attributes in the
.B reqOld
attribute, using the same format as described above for the Delete operation.
-This option is not yet implemented.
+The
+.B reqOld
+attribute is only populated if the entry being modified matches the
+configured
+.B logold
+filter.
.LP
.RS 4
DESC 'ModRDN operation'
SUP auditWriteObject STRUCTURAL
MUST ( reqNewRDN $ reqDeleteOldRDN )
- MAY reqNewSuperior )
+ MAY ( reqNewSuperior $ reqOld ) )
.RE
.P
The
.B reqNewSuperior
attribute carries the DN of the new parent entry if the request specified
the new parent.
+The
+.B reqOld
+attribute is only populated if the entry being modified matches the
+configured
+.B logold
+filter and contains attributes in the
+.B logoldattr
+list.
.LP
.RS 4
.B subordinate
of this one are also output, unless \fB-g\fP is specified.
.LP
-The LDIF generated by this tool is suitable for use with
+The entry records are presented in database order, not superior first
+order. The entry records will include all (user and operational)
+attributes stored in the database. The entry records will not include
+dynamically generated attributes (such as subschemaSubentry).
+.LP
+The output of slapcat is intended to be used as input to
.BR slapadd (8).
-As the entries are in database order, not superior first order,
-they cannot be loaded with
+The output of slapcat cannot generally be used as input to
.BR ldapadd (1)
-without first being reordered.
+or other LDAP clients without first editing the output.
+This editing would normally include reordering the records
+into superior first order and removing no-user-modification
+operational attributes.
.SH OPTIONS
.TP
.B \-v
.B [\-F slapd\-config\-directory]
.B [\-h URLs]
.B [\-n service\-name] [\-s syslog\-level] [\-l syslog\-local\-user]
+.B [\-o option[=value]]
.B [\-r directory]
.B [\-u user] [\-g group]
.B [\-c cookie]
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.
+different kind of debugging information. See <ldap_log.h> for details.
Comma-separated arrays of friendly names can be specified to select
debugging output of the corresponding debugging information.
All the names recognized by the \fIloglevel\fP directive
is the commit sequence number received by a previous synchronization
and represents the state of the consumer replica content which the
syncrepl engine will synchronize to the current provider content.
+.TP
+.BI \-o " option[=value]"
+This option provides a generic means to specify options without the need to reserve
+a separate letter for them.
+
+It supports the following options:
+.RS
+.TP
+slp={\fBon\fP|\fBoff\fP|\fIslp\-attrs\fP}
+When SLP support is compiled into slapd, disable it (
+.B off
+), enable it by registering at SLP DAs without specific SLP attributes (
+.B on
+), or with specific SLP attributes
+.I slp\-attrs
+that must be an SLP attribute list definition according to the SLP standard.
+
+For example, "-o slp=(tree=production),(server-type=OpenLDAP),(server-version=2.3.20)"
+registers at SLP DAs with the three SLP attributes tree, server-type and server-version
+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.
+.RE
.SH EXAMPLES
To start
.I slapd
.B SBINDIR/slappasswd
.B [\-v]
.B [\-u]
-.B [\-s secret|\-T file]
+.B [\-g|\-s secret|\-T file]
.B [\-h hash]
.B [\-c salt-format]
+.B [\-n]
.B
.LP
.SH DESCRIPTION
.TP
.BI \-s " secret"
The secret to hash.
-If this and
+If this,
+.B \-g
+and
.B \-T
are absent, the user will be prompted for the secret to hash.
+.BR \-s ,
+.B \-g
+and
+.B \-T
+and mutually exclusive flags.
+.TP
+.BI \-g
+Generate the secret.
+If this,
.B \-s
and
.B \-T
+are absent, the user will be prompted for the secret to hash.
+.BR \-s ,
+.B \-g
+and
+.B \-T
and mutually exclusive flags.
+If this is present,
+.I {CLEARTEXT}
+is used as scheme.
+.B \-g
+and
+.B \-h
+are mutually exclusive flags.
.TP
.BI \-T " file"
Hash the contents of the file.
-If this and
+If this,
+.B \-g
+and
.B \-s
are absent, the user will be prompted for the secret to hash.
-.B \-s
+.BR \-s ,
+.B \-g
and
.B \-T
and mutually exclusive flags.
.B {CLEARTEXT}
indicates that the new password should be added to userPassword as
clear text.
+Unless
+.I {CLEARTEXT}
+is used, this flag is incompatible with
+.BR \-g .
.TP
.BI \-c " crypt-salt-format"
Specify the format of the salt passed to
versions of crypt(3) to use an MD5 algorithm and provides
8 random characters of salt. The default is '%s', which
provides 31 characters of salt.
+.TP
+.BI \-n
+Omit the trailing newline; useful to pipe the credentials
+into a command.
.SH LIMITATIONS
The practice storing hashed passwords in userPassword violates
Standard Track (RFC 2256) schema specifications and may hinder
#define LDAP_OPT_URI 0x5006
#define LDAP_OPT_REFERRAL_URLS 0x5007 /* Referral URLs */
#define LDAP_OPT_SOCKBUF 0x5008 /* sockbuf */
+#define LDAP_OPT_DEFBASE 0x5009 /* searchbase */
/* OpenLDAP TLS options */
#define LDAP_OPT_X_TLS 0x6000
LDAP_NEXTREF_PROC *nextref_proc,
void *params ));
+/* V3 URLLIST Function Callback Prototype */
+typedef int (LDAP_URLLIST_PROC) LDAP_P((
+ LDAP *ld,
+ LDAPURLDesc **urllist,
+ LDAPURLDesc **url,
+ void *params ));
+
+LDAP_F( int )
+ldap_set_urllist_proc LDAP_P((
+ LDAP *ld,
+ LDAP_URLLIST_PROC *urllist_proc,
+ void *params ));
+
/*
* in controls.c:
*/
typedef struct ldap_int_thread_pool_s * ldap_int_thread_pool_t;
#endif
+typedef struct ldap_int_thread_rmutex_s * ldap_int_thread_rmutex_t;
LDAP_END_DECL
lutil_debug( ldap_debug, (level), (fmt), (arg1), (arg2), (arg3), (arg4), (arg5) ); \
} while ( 0 )
#define Debug( level, fmt, arg1, arg2, arg3 ) \
- Log3( (level), (fmt), (arg1), (arg2), (arg3) )
+ Log3( (level), 0, (fmt), (arg1), (arg2), (arg3) )
#define LogTest(level) ( ldap_debug & (level) )
#endif /* ! LDAP_SYSLOG */
#else /* ! LDAP_DEBUG */
struct ldap_url_desc; /* avoid pulling in <ldap.h> */
+#define LDAP_PVT_URL_PARSE_NONE (0x00U)
+#define LDAP_PVT_URL_PARSE_NOEMPTY_HOST (0x01U)
+#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)
LDAP_F( int )
ldap_url_parse_ext LDAP_P((
LDAP_CONST char *url,
- struct ldap_url_desc **ludpp ));
+ struct ldap_url_desc **ludpp,
+ unsigned flags ));
+
+LDAP_F (int) ldap_url_parselist_ext LDAP_P((
+ struct ldap_url_desc **ludlist,
+ const char *url,
+ const char *sep,
+ unsigned flags ));
+
+LDAP_F (char *) ldap_url_list2urls LDAP_P((
+ struct ldap_url_desc *ludlist ));
+
+LDAP_F (void) ldap_free_urllist LDAP_P((
+ struct ldap_url_desc *ludlist ));
LDAP_F( char * )
ldap_pvt_ctime LDAP_P((
typedef ldap_int_thread_cond_t ldap_pvt_thread_cond_t;
typedef ldap_int_thread_rdwr_t ldap_pvt_thread_rdwr_t;
#endif
+typedef ldap_int_thread_rmutex_t ldap_pvt_thread_rmutex_t;
#endif /* !LDAP_PVT_THREAD_H_DONE */
#if 0 && defined(LDAP_DEVEL)
LDAP_F( int )
ldap_pvt_thread_mutex_unlock LDAP_P(( ldap_pvt_thread_mutex_t *mutex ));
+LDAP_F( int )
+ldap_pvt_thread_rmutex_init LDAP_P(( ldap_pvt_thread_rmutex_t *rmutex ));
+
+LDAP_F( int )
+ldap_pvt_thread_rmutex_destroy LDAP_P(( ldap_pvt_thread_rmutex_t *rmutex ));
+
+LDAP_F( int )
+ldap_pvt_thread_rmutex_lock LDAP_P(( ldap_pvt_thread_rmutex_t *rmutex,
+ ldap_pvt_thread_t owner));
+
+LDAP_F( int )
+ldap_pvt_thread_rmutex_trylock LDAP_P(( ldap_pvt_thread_rmutex_t *rmutex,
+ ldap_pvt_thread_t owner));
+
+LDAP_F( int )
+ldap_pvt_thread_rmutex_unlock LDAP_P(( ldap_pvt_thread_rmutex_t *rmutex,
+ ldap_pvt_thread_t owner));
+
LDAP_F( ldap_pvt_thread_t )
ldap_pvt_thread_self LDAP_P(( void ));
LDAP_F( void )
ldap_pvt_thread_pool_context_reset LDAP_P(( void *key ));
+LDAP_F( ldap_pvt_thread_t )
+ldap_pvt_thread_pool_tid LDAP_P(( void *ctx ));
+
LDAP_END_DECL
#define LDAP_PVT_THREAD_H_DONE
-#endif /* _LDAP_THREAD_H */
+#endif /* _LDAP_PVT_THREAD_H */
LDAP_F( struct re_s* )
ldap_pvt_runqueue_next_sched(
struct runqueue_s* rq,
- struct timeval** next_run
+ struct timeval* next_run
);
LDAP_F( void )
/* define for Audit Logging overlay */
#undef SLAPD_OVER_AUDITLOG
+/* define for Attribute Constraint overlay */
+#undef SLAPD_OVER_CONSTRAINT
+
/* define for Dynamic Directory Services overlay */
#undef SLAPD_OVER_DDS
* <http://www.OpenLDAP.org/license.html>.
*/
/* ACKNOWLEDGEMENTS:
- * This program was orignally developed by Kurt D. Zeilenga for inclusion
+ * This program was originally developed by Kurt D. Zeilenga for inclusion
* in OpenLDAP Software.
*/
return ld->ld_errno;
}
+ rc = 0;
+#ifdef LDAP_R_COMPILE
+ ldap_pvt_thread_mutex_lock( &ld->ld_req_mutex );
+#endif
ber_sockbuf_ctrl( ld->ld_sb, LBER_SB_OPT_GET_FD, &sd );
if ( sd == AC_SOCKET_INVALID ) {
/* not connected yet */
- int rc;
rc = ldap_open_defconn( ld );
- if( rc < 0 ) return ld->ld_errno;
- ber_sockbuf_ctrl( ld->ld_defconn->lconn_sb,
- LBER_SB_OPT_GET_FD, &sd );
+ if ( rc == 0 ) {
+ ber_sockbuf_ctrl( ld->ld_defconn->lconn_sb,
+ LBER_SB_OPT_GET_FD, &sd );
- if( sd == AC_SOCKET_INVALID ) {
- ld->ld_errno = LDAP_LOCAL_ERROR;
- return ld->ld_errno;
+ if( sd == AC_SOCKET_INVALID ) {
+ ld->ld_errno = LDAP_LOCAL_ERROR;
+ rc = ld->ld_errno;
+ }
}
}
+#ifdef LDAP_R_COMPILE
+ ldap_pvt_thread_mutex_unlock( &ld->ld_req_mutex );
+#endif
+ if( rc != 0 ) return ld->ld_errno;
oldctx = ld->ld_defconn->lconn_sasl_authctx;
return( NULL );
}
+ err = 0;
+#ifdef LDAP_R_COMPILE
+ ldap_pvt_thread_mutex_lock( &ld->ld_req_mutex );
+#endif
if ( ber_sockbuf_ctrl( ld->ld_sb, LBER_SB_OPT_GET_FD, NULL ) == -1 ) {
/* not connected yet */
- int rc = ldap_open_defconn( ld );
-
- if( rc < 0 ) return NULL;
+ err = ldap_open_defconn( ld );
}
+#ifdef LDAP_R_COMPILE
+ ldap_pvt_thread_mutex_unlock( &ld->ld_req_mutex );
+#endif
+ if ( err < 0 ) return NULL;
krbinstance = ld->ld_defconn->lconn_krbinstance;
void *ldo_rebind_params;
LDAP_NEXTREF_PROC *ldo_nextref_proc;
void *ldo_nextref_params;
+ LDAP_URLLIST_PROC *ldo_urllist_proc;
+ void *ldo_urllist_params;
LDAP_BOOLEANS ldo_booleans; /* boolean options */
};
#define ld_rebind_params ld_options.ldo_rebind_params
#define ld_nextref_proc ld_options.ldo_nextref_proc
#define ld_nextref_params ld_options.ldo_nextref_params
+#define ld_urllist_proc ld_options.ldo_urllist_proc
+#define ld_urllist_params ld_options.ldo_urllist_params
#define ld_version ld_options.ldo_version
LDAP_F (BerElement *) ldap_alloc_ber_with_options( LDAP *ld );
LDAP_F (void) ldap_set_ber_options( LDAP *ld, BerElement *ber );
-LDAP_F (int) ldap_send_server_request( LDAP *ld, BerElement *ber, ber_int_t msgid, LDAPRequest *parentreq, LDAPURLDesc *srvlist, LDAPConn *lc, LDAPreqinfo *bind );
-LDAP_F (LDAPConn *) ldap_new_connection( LDAP *ld, LDAPURLDesc *srvlist, int use_ldsb, int connect, LDAPreqinfo *bind );
+LDAP_F (int) ldap_send_server_request( LDAP *ld, BerElement *ber, ber_int_t msgid, LDAPRequest *parentreq, LDAPURLDesc **srvlist, LDAPConn *lc, LDAPreqinfo *bind );
+LDAP_F (LDAPConn *) ldap_new_connection( LDAP *ld, LDAPURLDesc **srvlist, int use_ldsb, int connect, LDAPreqinfo *bind );
LDAP_F (LDAPRequest *) ldap_find_request_by_msgid( LDAP *ld, ber_int_t msgid );
LDAP_F (void) ldap_free_request( LDAP *ld, LDAPRequest *lr );
LDAP_F (void) ldap_free_connection( LDAP *ld, LDAPConn *lc, int force, int unbind );
LDAPURLDesc **ludlist,
const char *url ));
-LDAP_F (int) ldap_url_parselist_ext LDAP_P((
- LDAPURLDesc **ludlist,
- const char *url,
- const char *sep ));
-
LDAP_F (int) ldap_url_parsehosts LDAP_P((
LDAPURLDesc **ludlist,
const char *hosts,
LDAP_F (char *) ldap_url_list2hosts LDAP_P((
LDAPURLDesc *ludlist ));
-LDAP_F (char *) ldap_url_list2urls LDAP_P((
- LDAPURLDesc *ludlist ));
-
-LDAP_F (void) ldap_free_urllist LDAP_P((
- LDAPURLDesc *ludlist ));
-
/*
* in cyrus.c
*/
#include "ldap-int.h"
#include "ldap_log.h"
+/* Caller should hold the req_mutex if simultaneous accesses are possible */
int ldap_open_defconn( LDAP *ld )
{
ld->ld_defconn = ldap_new_connection( ld,
- ld->ld_options.ldo_defludp, 1, 1, NULL );
+ &ld->ld_options.ldo_defludp, 1, 1, NULL );
if( ld->ld_defconn == NULL ) {
ld->ld_errno = LDAP_SERVER_DOWN;
#define LDAP_OPT_NEXTREF_PROC 0x4e815d
#define LDAP_OPT_NEXTREF_PARAMS 0x4e815e
+#define LDAP_OPT_URLLIST_PROC 0x4e816d
+#define LDAP_OPT_URLLIST_PARAMS 0x4e816e
+
static const LDAPAPIFeatureInfo features[] = {
#ifdef LDAP_API_FEATURE_X_OPENLDAP
{ /* OpenLDAP Extensions API Feature */
* (char **) outvalue = ldap_url_list2urls(lo->ldo_defludp);
return LDAP_OPT_SUCCESS;
+ case LDAP_OPT_DEFBASE:
+ if( lo->ldo_defbase == NULL ) {
+ * (char **) outvalue = NULL;
+ } else {
+ * (char **) outvalue = LDAP_STRDUP(lo->ldo_defbase);
+ }
+
+ return LDAP_OPT_SUCCESS;
+
case LDAP_OPT_ERROR_NUMBER:
if(ld == NULL) {
/* bad param */
* must want global default returned
* to initial condition.
*/
- rc = ldap_url_parselist(&ludlist, "ldap://localhost/");
+ rc = ldap_url_parselist_ext(&ludlist, "ldap://localhost/", NULL,
+ LDAP_PVT_URL_PARSE_NOEMPTY_HOST
+ | LDAP_PVT_URL_PARSE_DEF_PORT );
} else {
/*
int rc = LDAP_OPT_SUCCESS;
if(urls != NULL) {
- rc = ldap_url_parselist(&ludlist, urls);
+ rc = ldap_url_parselist_ext(&ludlist, urls, NULL,
+ LDAP_PVT_URL_PARSE_NOEMPTY_HOST
+ | LDAP_PVT_URL_PARSE_DEF_PORT );
} else if(ld == NULL) {
/*
* must want global default returned
* to initial condition.
*/
- rc = ldap_url_parselist(&ludlist, "ldap://localhost/");
+ rc = ldap_url_parselist_ext(&ludlist, "ldap://localhost/", NULL,
+ LDAP_PVT_URL_PARSE_NOEMPTY_HOST
+ | LDAP_PVT_URL_PARSE_DEF_PORT );
} else {
/*
ludlist = ldap_url_duplist(
ldap_int_global_options.ldo_defludp);
if (ludlist == NULL)
- rc = LDAP_NO_MEMORY;
+ rc = LDAP_URL_ERR_MEM;
}
switch (rc) {
break;
}
- if (rc == LDAP_OPT_SUCCESS) {
+ if (rc == LDAP_SUCCESS) {
if (lo->ldo_defludp != NULL)
ldap_free_urllist(lo->ldo_defludp);
lo->ldo_defludp = ludlist;
return rc;
}
+ case LDAP_OPT_DEFBASE: {
+ const char *newbase = (const char *) invalue;
+ char *defbase = NULL;
+
+ if ( newbase != NULL ) {
+ defbase = LDAP_STRDUP( newbase );
+ if ( defbase == NULL ) return LDAP_NO_MEMORY;
+
+ } else if ( ld != NULL ) {
+ defbase = LDAP_STRDUP( ldap_int_global_options.ldo_defbase );
+ if ( defbase == NULL ) return LDAP_NO_MEMORY;
+ }
+
+ if ( lo->ldo_defbase != NULL )
+ LDAP_FREE( lo->ldo_defbase );
+ lo->ldo_defbase = defbase;
+ } return LDAP_OPT_SUCCESS;
+
case LDAP_OPT_ERROR_STRING: {
const char *err = (const char *) invalue;
lo->ldo_nextref_params = (void *)invalue;
} return LDAP_OPT_SUCCESS;
+ /* Only accessed from inside this function by ldap_set_urllist_proc() */
+ case LDAP_OPT_URLLIST_PROC: {
+ lo->ldo_urllist_proc = (LDAP_URLLIST_PROC *)invalue;
+ } return LDAP_OPT_SUCCESS;
+ case LDAP_OPT_URLLIST_PARAMS: {
+ lo->ldo_urllist_params = (void *)invalue;
+ } return LDAP_OPT_SUCCESS;
+
/* read-only options */
case LDAP_OPT_API_INFO:
case LDAP_OPT_DESC:
rc = ldap_set_option( ld, LDAP_OPT_NEXTREF_PARAMS, (void *)params );
return rc;
}
+
+int
+ldap_set_urllist_proc( LDAP *ld, LDAP_URLLIST_PROC *proc, void *params )
+{
+ int rc;
+ rc = ldap_set_option( ld, LDAP_OPT_URLLIST_PROC, (void *)proc );
+ if( rc != LDAP_OPT_SUCCESS ) return rc;
+
+ rc = ldap_set_option( ld, LDAP_OPT_URLLIST_PARAMS, (void *)params );
+ return rc;
+}
#ifdef LDAP_CONTROL_PASSWORDPOLICYREQUEST
-#define PPOLICY_WARNING 0xa0L
-#define PPOLICY_ERROR 0xa1L
+/* IMPLICIT TAGS, all context-specific */
+#define PPOLICY_WARNING 0xa0L /* constructed + 0 */
+#define PPOLICY_ERROR 0x81L /* primitive + 1 */
-#define PPOLICY_EXPIRE 0xa0L
-#define PPOLICY_GRACE 0xa1L
+#define PPOLICY_EXPIRE 0x80L /* primitive + 0 */
+#define PPOLICY_GRACE 0x81L /* primitive + 1 */
/*---
ldap_create_passwordpolicy_control
BerElement *ber,
ber_int_t msgid)
{
- int rc;
+ int rc = 1;
Debug( LDAP_DEBUG_TRACE, "ldap_send_initial_request\n", 0, 0, 0 );
+#ifdef LDAP_R_COMPILE
+ ldap_pvt_thread_mutex_lock( &ld->ld_req_mutex );
+#endif
if ( ber_sockbuf_ctrl( ld->ld_sb, LBER_SB_OPT_GET_FD, NULL ) == -1 ) {
/* not connected yet */
- int rc = ldap_open_defconn( ld );
-
- if( rc < 0 ) {
- ber_free( ber, 1 );
- return( -1 );
- }
+ rc = ldap_open_defconn( ld );
+ }
+#ifdef LDAP_R_COMPILE
+ ldap_pvt_thread_mutex_unlock( &ld->ld_req_mutex );
+#endif
+ if( rc < 0 ) {
+ ber_free( ber, 1 );
+ return( -1 );
+ } else if ( rc == 0 ) {
Debug( LDAP_DEBUG_TRACE,
"ldap_open_defconn: successful\n",
0, 0, 0 );
BerElement *ber,
ber_int_t msgid,
LDAPRequest *parentreq,
- LDAPURLDesc *srvlist,
+ LDAPURLDesc **srvlist,
LDAPConn *lc,
LDAPreqinfo *bind )
{
if ( srvlist == NULL ) {
lc = ld->ld_defconn;
} else {
- lc = find_connection( ld, srvlist, 1 );
+ lc = find_connection( ld, *srvlist, 1 );
if ( lc == NULL ) {
if ( (bind != NULL) && (parentreq != NULL) ) {
/* Remember the bind in the parent */
}
LDAPConn *
-ldap_new_connection( LDAP *ld, LDAPURLDesc *srvlist, int use_ldsb,
+ldap_new_connection( LDAP *ld, LDAPURLDesc **srvlist, int use_ldsb,
int connect, LDAPreqinfo *bind )
{
LDAPConn *lc;
- LDAPURLDesc *srv;
Debug( LDAP_DEBUG_TRACE, "ldap_new_connection %d %d %d\n",
use_ldsb, connect, (bind != NULL) );
}
if ( connect ) {
- for ( srv = srvlist; srv != NULL; srv = srv->lud_next ) {
- if ( ldap_int_open_connection( ld, lc, srv, 0 ) != -1 )
+ LDAPURLDesc **srvp, *srv = NULL;
+
+ for ( srvp = srvlist; *srvp != NULL; srvp = &(*srvp)->lud_next ) {
+ if ( ldap_int_open_connection( ld, lc, *srvp, 0 ) != -1 )
{
+ srv = *srvp;
+
+ if ( ld->ld_urllist_proc ) {
+ ld->ld_urllist_proc( ld, srvlist, srvp, ld->ld_urllist_params );
+ }
+
break;
}
}
ldap_pvt_thread_mutex_unlock( &ld->ld_conn_mutex );
#endif
- /*
- * XXX for now, we always do a synchronous bind. This will have
- * to change in the long run...
- */
- if ( bind != NULL) {
+ if ( bind != NULL ) {
int err = 0;
LDAPConn *savedefconn;
if ( ld->ld_rebind_proc != NULL) {
LDAPURLDesc *srvfunc;
- srvfunc = ldap_url_dup( srvlist );
+ srvfunc = ldap_url_dup( *srvlist );
if ( srvfunc == NULL ) {
ld->ld_errno = LDAP_NO_MEMORY;
err = -1;
if ( lr->lr_ber != NULL ) {
ber_free( lr->lr_ber, 1 );
+ lr->lr_ber = NULL;
}
if ( lr->lr_res_error != NULL ) {
LDAP_FREE( lr->lr_res_error );
+ lr->lr_res_error = NULL;
}
if ( lr->lr_res_matched != NULL ) {
LDAP_FREE( lr->lr_res_matched );
+ lr->lr_res_matched = NULL;
}
LDAP_FREE( lr );
{
/* Parse the referral URL */
- if (( rc = ldap_url_parse_ext( refarray[i], &srv)) != LDAP_SUCCESS) {
- ld->ld_errno = rc;
+ rc = ldap_url_parse_ext( refarray[i], &srv, LDAP_PVT_URL_PARSE_NOEMPTY_DN );
+ if ( rc != LDAP_URL_SUCCESS ) {
+ /* ldap_url_parse_ext() returns LDAP_URL_* errors
+ * which do not map on API errors */
+ ld->ld_errno = LDAP_PARAM_ERROR;
rc = -1;
goto done;
}
goto done;
}
- /* treat ldap://hostpart and ldap://hostpart/ the same */
- if ( srv->lud_dn && srv->lud_dn[0] == '\0' ) {
- LDAP_FREE( srv->lud_dn );
- srv->lud_dn = NULL;
- }
-
/* check connection for re-bind in progress */
if (( lc = find_connection( ld, srv, 1 )) != NULL ) {
/* See if we've already requested this DN with this conn */
ldap_pvt_thread_mutex_lock( &ld->ld_req_mutex );
#endif
rc = ldap_send_server_request( ld, ber, id,
- origreq, srv, NULL, &rinfo );
+ origreq, &srv, NULL, &rinfo );
#ifdef LDAP_R_COMPILE
ldap_pvt_thread_mutex_unlock( &ld->ld_req_mutex );
#endif
*p++ = '\0';
}
- rc = ldap_url_parse_ext( ref, &srv );
-
+ rc = ldap_url_parse_ext( ref, &srv, LDAP_PVT_URL_PARSE_NOEMPTY_DN );
if ( rc != LDAP_URL_SUCCESS ) {
Debug( LDAP_DEBUG_TRACE,
- "ignoring unknown referral <%s>\n", ref, 0, 0 );
+ "ignoring %s referral <%s>\n",
+ ref, rc == LDAP_URL_ERR_BADSCHEME ? "unknown" : "incorrect", 0 );
rc = ldap_append_referral( ld, &unfollowed, ref );
*hadrefp = 1;
continue;
}
- if ( srv->lud_dn != NULL && srv->lud_dn == '\0' ) {
- LDAP_FREE( srv->lud_dn );
- srv->lud_dn = NULL;
- }
-
Debug( LDAP_DEBUG_TRACE,
"chasing LDAP referral: <%s>\n", ref, 0, 0 );
ldap_pvt_thread_mutex_lock( &ld->ld_req_mutex );
#endif
rc = ldap_send_server_request( ld, ber, id,
- lr, srv, NULL, &rinfo );
+ lr, &srv, NULL, &rinfo );
#ifdef LDAP_R_COMPILE
ldap_pvt_thread_mutex_unlock( &ld->ld_req_mutex );
#endif
ber_int_t scope;
int rc;
BerElement tmpber, *ber;
- struct berval orig_dn;
- char *dn;
+ struct berval dn;
Debug( LDAP_DEBUG_TRACE,
"re_encode_request: new msgid %ld, new dn <%s>\n",
assert( tag != 0);
if ( tag == LDAP_REQ_BIND ) {
/* bind requests have a version number before the DN & other stuff */
- rtag = ber_scanf( &tmpber, "{im" /*}*/, &ver, &orig_dn );
+ rtag = ber_scanf( &tmpber, "{im" /*}*/, &ver, &dn );
} else if ( tag == LDAP_REQ_DELETE ) {
/* delete requests don't have a DN wrapping sequence */
- rtag = ber_scanf( &tmpber, "m", &orig_dn );
+ rtag = ber_scanf( &tmpber, "m", &dn );
} else if ( tag == LDAP_REQ_SEARCH ) {
/* search requests need to be re-scope-ed */
- rtag = ber_scanf( &tmpber, "{me" /*"}"*/, &orig_dn, &scope );
+ rtag = ber_scanf( &tmpber, "{me" /*"}"*/, &dn, &scope );
if( srv->lud_scope != LDAP_SCOPE_DEFAULT ) {
/* use the scope provided in reference */
}
} else {
- rtag = ber_scanf( &tmpber, "{m" /*}*/, &orig_dn );
+ rtag = ber_scanf( &tmpber, "{m" /*}*/, &dn );
}
if( rtag == LBER_ERROR ) {
return NULL;
}
+ /* restore character zero'd out by ber_scanf*/
+ dn.bv_val[dn.bv_len] = tmpber.ber_tag;
+
if (( ber = ldap_alloc_ber_with_options( ld )) == NULL ) {
return NULL;
}
- if ( srv->lud_dn == NULL ) {
- dn = orig_dn.bv_val;
- } else {
- dn = srv->lud_dn;
+ if ( srv->lud_dn ) {
+ ber_str2bv( srv->lud_dn, 0, 0, &dn );
}
if ( tag == LDAP_REQ_BIND ) {
- rc = ber_printf( ber, "{it{is" /*}}*/, msgid, tag, ver, dn );
+ rc = ber_printf( ber, "{it{iO" /*}}*/, msgid, tag, ver, &dn );
} else if ( tag == LDAP_REQ_DELETE ) {
- rc = ber_printf( ber, "{itsN}", msgid, tag, dn );
+ rc = ber_printf( ber, "{itON}", msgid, tag, &dn );
} else if ( tag == LDAP_REQ_SEARCH ) {
- rc = ber_printf( ber, "{it{se" /*}}*/, msgid, tag, dn, scope );
+ rc = ber_printf( ber, "{it{Oe" /*}}*/, msgid, tag, &dn, scope );
} else {
- rc = ber_printf( ber, "{it{s" /*}}*/, msgid, tag, dn );
+ rc = ber_printf( ber, "{it{O" /*}}*/, msgid, tag, &dn );
}
if ( rc == -1 ) {
nextresp3:
#endif
tag = ber_get_next( lc->lconn_sb, &len, ber );
- if ( tag == LDAP_TAG_MESSAGE ) {
+ switch ( tag ) {
+ case LDAP_TAG_MESSAGE:
/*
* We read a complete message.
* The connection should no longer need this ber.
*/
lc->lconn_ber = NULL;
- }
- if ( tag != LDAP_TAG_MESSAGE ) {
- if ( tag == LBER_DEFAULT) {
+ break;
+
+ case LBER_DEFAULT:
#ifdef LDAP_DEBUG
- Debug( LDAP_DEBUG_CONNS,
- "ber_get_next failed.\n", 0, 0, 0 );
+ Debug( LDAP_DEBUG_CONNS,
+ "ber_get_next failed.\n", 0, 0, 0 );
#endif
#ifdef EWOULDBLOCK
- if (errno==EWOULDBLOCK) return LDAP_MSG_X_KEEP_LOOKING;
+ if ( errno == EWOULDBLOCK ) return LDAP_MSG_X_KEEP_LOOKING;
#endif
#ifdef EAGAIN
- if (errno == EAGAIN) return LDAP_MSG_X_KEEP_LOOKING;
+ if ( errno == EAGAIN ) return LDAP_MSG_X_KEEP_LOOKING;
#endif
- ld->ld_errno = LDAP_SERVER_DOWN;
- return -1;
- }
+ ld->ld_errno = LDAP_SERVER_DOWN;
+ return -1;
+
+ default:
ld->ld_errno = LDAP_LOCAL_ERROR;
return -1;
}
ber_free( ber, 1 );
ber = NULL;
if ( build_result_ber( ld, &ber, lr )
- == LBER_ERROR ) {
+ == LBER_ERROR )
+ {
rc = -1; /* fatal error */
}
}
LDAP_VFREE( et[i].et_vals );
}
*ep = ohead;
-
+ (*chain)->lm_chain_tail = otail ? otail : etail;
+
LDAP_FREE( (char *) et );
return( 0 );
#endif
}
- Debug( LDAP_DEBUG_ANY,"TLS: can't connect.\n",0,0,0);
+ Debug( LDAP_DEBUG_ANY,"TLS: can't connect: %s.\n",
+ ld->ld_error ? ld->ld_error : "" ,0,0);
ber_sockbuf_remove_io( sb, &sb_tls_sbio,
LBER_SBIOD_LEVEL_TRANSPORT );
}
int
-ldap_url_parse_ext( LDAP_CONST char *url_in, LDAPURLDesc **ludpp )
+ldap_url_parse_ext( LDAP_CONST char *url_in, LDAPURLDesc **ludpp, unsigned flags )
{
/*
* Pick apart the pieces of an LDAP URL.
const char *url_tmp;
char *url;
+ int check_dn = 1;
+
if( url_in == NULL || ludpp == NULL ) {
return LDAP_URL_ERR_PARAM;
}
ludp->lud_port = 0;
ludp->lud_dn = NULL;
ludp->lud_attrs = NULL;
- ludp->lud_scope = LDAP_SCOPE_DEFAULT;
+ ludp->lud_scope = ( flags & LDAP_PVT_URL_PARSE_NODEF_SCOPE ) ? LDAP_SCOPE_BASE : LDAP_SCOPE_DEFAULT;
ludp->lud_filter = NULL;
ludp->lud_exts = 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;
+ }
+ }
+
ldap_pvt_hex_unescape( url );
/* If [ip address]:port syntax, url is [ip and we skip the [ */
return LDAP_URL_ERR_MEM;
}
+ if ( ( flags & LDAP_PVT_URL_PARSE_NOEMPTY_HOST )
+ && ludp->lud_host != NULL
+ && *ludp->lud_host == '\0' )
+ {
+ LDAP_FREE( ludp->lud_host );
+ ludp->lud_host = NULL;
+ }
+
/*
* Kludge. ldap://111.222.333.444:389??cn=abc,o=company
*
/* parse dn part */
ldap_pvt_hex_unescape( q );
ludp->lud_dn = LDAP_STRDUP( q );
- } else {
+
+ } else if ( !( flags & LDAP_PVT_URL_PARSE_NOEMPTY_DN ) ) {
ludp->lud_dn = LDAP_STRDUP( "" );
+
+ } else {
+ check_dn = 0;
}
- if( ludp->lud_dn == NULL ) {
+ if ( check_dn && ludp->lud_dn == NULL ) {
LDAP_FREE( url );
ldap_free_urldesc( ludp );
return LDAP_URL_ERR_MEM;
/* parse dn part */
ldap_pvt_hex_unescape( p );
ludp->lud_dn = LDAP_STRDUP( p );
- } else {
+
+ } else if ( !( flags & LDAP_PVT_URL_PARSE_NOEMPTY_DN ) ) {
ludp->lud_dn = LDAP_STRDUP( "" );
+
+ } else {
+ check_dn = 0;
}
- if( ludp->lud_dn == NULL ) {
+ if( check_dn && ludp->lud_dn == NULL ) {
LDAP_FREE( url );
ldap_free_urldesc( ludp );
return LDAP_URL_ERR_MEM;
int
ldap_url_parse( LDAP_CONST char *url_in, LDAPURLDesc **ludpp )
{
- int rc = ldap_url_parse_ext( url_in, ludpp );
-
- if( rc != LDAP_URL_SUCCESS ) {
- return rc;
- }
-
- if ((*ludpp)->lud_scope == LDAP_SCOPE_DEFAULT) {
- (*ludpp)->lud_scope = LDAP_SCOPE_BASE;
- }
-
- if ((*ludpp)->lud_host != NULL && *(*ludpp)->lud_host == '\0') {
- LDAP_FREE( (*ludpp)->lud_host );
- (*ludpp)->lud_host = NULL;
- }
-
- if ((*ludpp)->lud_port == 0) {
- if( strcmp((*ludpp)->lud_scheme, "ldap") == 0 ) {
- (*ludpp)->lud_port = LDAP_PORT;
-#ifdef LDAP_CONNECTIONLESS
- } else if( strcmp((*ludpp)->lud_scheme, "cldap") == 0 ) {
- (*ludpp)->lud_port = LDAP_PORT;
-#endif
- } else if( strcmp((*ludpp)->lud_scheme, "ldaps") == 0 ) {
- (*ludpp)->lud_port = LDAPS_PORT;
- }
- }
-
- return rc;
+ return ldap_url_parse_ext( url_in, ludpp, LDAP_PVT_URL_PARSE_HISTORIC );
}
LDAPURLDesc *
}
static int
-ldap_url_parselist_int (LDAPURLDesc **ludlist, const char *url, const char *sep,
- int (*url_parse)( const char *, LDAPURLDesc ** ) )
+ldap_url_parselist_int (LDAPURLDesc **ludlist, const char *url, const char *sep, unsigned flags )
+
{
int i, rc;
LDAPURLDesc *ludp;
*ludlist = NULL;
- urls = ldap_str2charray(url, sep);
+ if ( sep == NULL ) {
+ sep = ", ";
+ }
+
+ urls = ldap_str2charray( url, sep );
if (urls == NULL)
return LDAP_URL_ERR_MEM;
for (i = 0; urls[i] != NULL; i++) ;
/* ...and put them in the "stack" backward */
while (--i >= 0) {
- rc = url_parse( urls[i], &ludp );
+ rc = ldap_url_parse_ext( urls[i], &ludp, flags );
if ( rc != 0 ) {
- ldap_charray_free(urls);
- ldap_free_urllist(*ludlist);
+ ldap_charray_free( urls );
+ ldap_free_urllist( *ludlist );
*ludlist = NULL;
return rc;
}
ludp->lud_next = *ludlist;
*ludlist = ludp;
}
- ldap_charray_free(urls);
+ ldap_charray_free( urls );
return LDAP_URL_SUCCESS;
}
int
ldap_url_parselist (LDAPURLDesc **ludlist, const char *url )
{
- return ldap_url_parselist_int( ludlist, url, ", ", ldap_url_parse );
+ return ldap_url_parselist_int( ludlist, url, ", ", LDAP_PVT_URL_PARSE_HISTORIC );
}
int
-ldap_url_parselist_ext (LDAPURLDesc **ludlist, const char *url, const char *sep )
+ldap_url_parselist_ext (LDAPURLDesc **ludlist, const char *url, const char *sep, unsigned flags )
{
- return ldap_url_parselist_int( ludlist, url, sep, ldap_url_parse_ext );
+ return ldap_url_parselist_int( ludlist, url, sep, flags );
}
int
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
-SRCS = threads.c rdwr.c tpool.c rq.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
-OBJS = threads.lo rdwr.lo tpool.lo rq.lo \
+OBJS = threads.lo rdwr.lo rmutex.lo tpool.lo rq.lo \
thr_posix.lo thr_cthreads.lo thr_thr.lo thr_lwp.lo thr_nt.lo \
thr_pth.lo thr_stub.lo thr_debug.lo \
bind.lo open.lo result.lo error.lo compare.lo search.lo \
--- /dev/null
+/* $OpenLDAP$ */
+/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
+ *
+ * Copyright 2006 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>.
+ */
+/* This work was initially developed by Howard Chu for inclusion
+ * in OpenLDAP Software.
+ */
+
+/*
+ * This is an implementation of recursive mutexes.
+ */
+
+#include "portable.h"
+
+#include <ac/stdlib.h>
+
+#include <ac/errno.h>
+#include <ac/string.h>
+#include <ac/time.h>
+
+#include "ldap-int.h"
+#include "ldap_pvt_thread.h" /* Get the thread interface */
+
+struct ldap_int_thread_rmutex_s {
+ ldap_pvt_thread_mutex_t ltrm_mutex;
+ ldap_pvt_thread_cond_t ltrm_cond;
+ ldap_pvt_thread_t ltrm_owner;
+ int ltrm_valid;
+#define LDAP_PVT_THREAD_RMUTEX_VALID 0x0cdb
+ int ltrm_depth;
+ int ltrm_waits;
+};
+
+static const ldap_pvt_thread_t tid_zero;
+
+int
+ldap_pvt_thread_rmutex_init( ldap_pvt_thread_rmutex_t *rmutex )
+{
+ struct ldap_int_thread_rmutex_s *rm;
+
+ assert( rmutex != NULL );
+
+ rm = (struct ldap_int_thread_rmutex_s *) LDAP_CALLOC( 1,
+ sizeof( struct ldap_int_thread_rmutex_s ) );
+ if ( !rm )
+ return LDAP_NO_MEMORY;
+
+ /* we should check return results */
+ ldap_pvt_thread_mutex_init( &rm->ltrm_mutex );
+ ldap_pvt_thread_cond_init( &rm->ltrm_cond );
+
+ rm->ltrm_valid = LDAP_PVT_THREAD_RMUTEX_VALID;
+
+ *rmutex = rm;
+ return 0;
+}
+
+int
+ldap_pvt_thread_rmutex_destroy( ldap_pvt_thread_rmutex_t *rmutex )
+{
+ struct ldap_int_thread_rmutex_s *rm;
+
+ assert( rmutex != NULL );
+ rm = *rmutex;
+
+ assert( rm != NULL );
+ assert( rm->ltrm_valid == LDAP_PVT_THREAD_RMUTEX_VALID );
+
+ if( rm->ltrm_valid != LDAP_PVT_THREAD_RMUTEX_VALID )
+ return LDAP_PVT_THREAD_EINVAL;
+
+ ldap_pvt_thread_mutex_lock( &rm->ltrm_mutex );
+
+ assert( rm->ltrm_depth >= 0 );
+ assert( rm->ltrm_waits >= 0 );
+
+ /* in use? */
+ if( rm->ltrm_depth > 0 || rm->ltrm_waits > 0 ) {
+ ldap_pvt_thread_mutex_unlock( &rm->ltrm_mutex );
+ return LDAP_PVT_THREAD_EBUSY;
+ }
+
+ rm->ltrm_valid = 0;
+
+ ldap_pvt_thread_mutex_unlock( &rm->ltrm_mutex );
+
+ ldap_pvt_thread_mutex_destroy( &rm->ltrm_mutex );
+ ldap_pvt_thread_cond_destroy( &rm->ltrm_cond );
+
+ LDAP_FREE(rm);
+ *rmutex = NULL;
+ return 0;
+}
+
+int ldap_pvt_thread_rmutex_lock( ldap_pvt_thread_rmutex_t *rmutex,
+ ldap_pvt_thread_t owner )
+{
+ struct ldap_int_thread_rmutex_s *rm;
+
+ assert( rmutex != NULL );
+ rm = *rmutex;
+
+ assert( rm != NULL );
+ assert( rm->ltrm_valid == LDAP_PVT_THREAD_RMUTEX_VALID );
+
+ if( rm->ltrm_valid != LDAP_PVT_THREAD_RMUTEX_VALID )
+ return LDAP_PVT_THREAD_EINVAL;
+
+ ldap_pvt_thread_mutex_lock( &rm->ltrm_mutex );
+
+ assert( rm->ltrm_depth >= 0 );
+ assert( rm->ltrm_waits >= 0 );
+
+ if( rm->ltrm_depth > 0 ) {
+ /* already locked */
+ if ( !ldap_pvt_thread_equal( rm->ltrm_owner, owner )) {
+ rm->ltrm_waits++;
+ do {
+ ldap_pvt_thread_cond_wait( &rm->ltrm_cond,
+ &rm->ltrm_mutex );
+ } while( rm->ltrm_depth > 0 );
+
+ rm->ltrm_waits--;
+ assert( rm->ltrm_waits >= 0 );
+ rm->ltrm_owner = owner;
+ }
+ } else {
+ rm->ltrm_owner = owner;
+ }
+
+ rm->ltrm_depth++;
+
+ ldap_pvt_thread_mutex_unlock( &rm->ltrm_mutex );
+
+ return 0;
+}
+
+int ldap_pvt_thread_rmutex_trylock( ldap_pvt_thread_rmutex_t *rmutex,
+ ldap_pvt_thread_t owner )
+{
+ struct ldap_int_thread_rmutex_s *rm;
+
+ assert( rmutex != NULL );
+ rm = *rmutex;
+
+ assert( rm != NULL );
+ assert( rm->ltrm_valid == LDAP_PVT_THREAD_RMUTEX_VALID );
+
+ if( rm->ltrm_valid != LDAP_PVT_THREAD_RMUTEX_VALID )
+ return LDAP_PVT_THREAD_EINVAL;
+
+ ldap_pvt_thread_mutex_lock( &rm->ltrm_mutex );
+
+ assert( rm->ltrm_depth >= 0 );
+ assert( rm->ltrm_waits >= 0 );
+
+ if( rm->ltrm_depth > 0 ) {
+ if ( !ldap_pvt_thread_equal( owner, rm->ltrm_owner )) {
+ ldap_pvt_thread_mutex_unlock( &rm->ltrm_mutex );
+ return LDAP_PVT_THREAD_EBUSY;
+ }
+ } else {
+ rm->ltrm_owner = owner;
+ }
+
+ rm->ltrm_depth++;
+
+ ldap_pvt_thread_mutex_unlock( &rm->ltrm_mutex );
+
+ return 0;
+}
+
+int ldap_pvt_thread_rmutex_unlock( ldap_pvt_thread_rmutex_t *rmutex,
+ ldap_pvt_thread_t owner )
+{
+ struct ldap_int_thread_rmutex_s *rm;
+
+ assert( rmutex != NULL );
+ rm = *rmutex;
+
+ assert( rm != NULL );
+ assert( rm->ltrm_valid == LDAP_PVT_THREAD_RMUTEX_VALID );
+
+ if( rm->ltrm_valid != LDAP_PVT_THREAD_RMUTEX_VALID )
+ return LDAP_PVT_THREAD_EINVAL;
+
+ ldap_pvt_thread_mutex_lock( &rm->ltrm_mutex );
+
+ if( !ldap_pvt_thread_equal( owner, rm->ltrm_owner )) {
+ ldap_pvt_thread_mutex_unlock( &rm->ltrm_mutex );
+ return LDAP_PVT_THREAD_EINVAL;
+ }
+
+ rm->ltrm_depth--;
+ if ( !rm->ltrm_depth )
+ rm->ltrm_owner = tid_zero;
+
+ assert( rm->ltrm_depth >= 0 );
+ assert( rm->ltrm_waits >= 0 );
+
+ if ( !rm->ltrm_depth && rm->ltrm_waits ) {
+ ldap_pvt_thread_cond_signal( &rm->ltrm_cond );
+ }
+
+ ldap_pvt_thread_mutex_unlock( &rm->ltrm_mutex );
+
+ return 0;
+}
+
struct re_s*
ldap_pvt_runqueue_next_sched(
struct runqueue_s* rq,
- struct timeval** next_run
+ struct timeval* next_run
)
{
struct re_s* entry;
entry = LDAP_STAILQ_FIRST( &rq->task_list );
- if ( entry == NULL ) {
- *next_run = NULL;
- return NULL;
- } else if ( entry->next_sched.tv_sec == 0 ) {
- *next_run = NULL;
+ if ( entry == NULL || entry->next_sched.tv_sec == 0 ) {
return NULL;
} else {
- *next_run = &entry->next_sched;
+ *next_run = entry->next_sched;
return entry;
}
}
enum { threadID = 0 };
#endif
static int nodebug, noabort, noerror, nosync, tracethreads;
+static int wrap_threads;
static int options_done;
}
unwrap_offset = -(wrap_offset = (wraptype == Wrap_adjptr));
#endif
+ wrap_threads = (tracethreads || threadID || count);
options_done = 1;
}
resource_counts[which] += adjust;
rc = ldap_int_thread_mutex_unlock( &resource_mutexes[which] );
assert( rc == 0 );
+ break;
case Count_reported:
fputs( "== thr_debug: More thread activity after exit ==\n", stderr );
count = Count_reported_more;
return 0;
}
+static void
+thread_exiting( const char *how, const char *msg )
+{
+ ldap_pvt_thread_t thread;
+ ERROR_IF( !threading_enabled, msg );
+ thread = ldap_pvt_thread_self();
+ if( tracethreads ) {
+ char buf[40];
+ fprintf( stderr, "== thr_debug: %s thread %s ==\n",
+ how, thread_name( buf, sizeof(buf), thread ) );
+ }
+ if( threadID ) {
+ with_thread_info_lock({
+ ldap_debug_thread_t *t = get_thread_info(
+ &thread, msg );
+ if( thread_info_detached( t ) )
+ remove_thread_info( t, msg );
+ });
+ }
+ adjust_count( Idx_unexited_thread, -1 );
+}
+
+void
+ldap_pvt_thread_exit( void *retval )
+{
+ thread_exiting( "Exiting", "ldap_pvt_thread_exit" );
+ ldap_int_thread_exit( retval );
+}
+
+typedef struct {
+ void *(*start_routine)( void * );
+ void *arg;
+} ldap_debug_thread_call_t;
+
+static void *
+ldap_debug_thread_wrapper( void *arg )
+{
+ void *ret;
+ ldap_debug_thread_call_t call = *(ldap_debug_thread_call_t *)arg;
+ free( arg );
+ ret = call.start_routine( call.arg );
+ thread_exiting( "Returning from", "ldap_debug_thread_wrapper" );
+ return ret;
+}
+
int
ldap_pvt_thread_create(
ldap_pvt_thread_t *thread,
if( !options_done )
get_options();
ERROR_IF( !threading_enabled, "ldap_pvt_thread_create" );
+ if( wrap_threads ) {
+ ldap_debug_thread_call_t *call = malloc(
+ sizeof( ldap_debug_thread_call_t ) );
+ assert( call != NULL );
+ call->start_routine = start_routine;
+ call->arg = arg;
+ start_routine = ldap_debug_thread_wrapper;
+ arg = call;
+ }
if( threadID ) {
with_thread_info_lock({
rc = ldap_int_thread_create( thread, detach, start_routine, arg );
return rc;
}
-void
-ldap_pvt_thread_exit( void *retval )
-{
- ldap_pvt_thread_t thread;
- ERROR_IF( !threading_enabled, "ldap_pvt_thread_exit" );
- thread = ldap_pvt_thread_self();
- if( tracethreads ) {
- char buf[40];
- fprintf( stderr, "== thr_debug: Exiting thread %s ==\n",
- thread_name( buf, sizeof(buf), thread ) );
- }
- if( threadID ) {
- with_thread_info_lock({
- ldap_debug_thread_t *t = get_thread_info(
- &thread, "ldap_pvt_thread_exit" );
- if( thread_info_detached( t ) )
- remove_thread_info( t, "ldap_pvt_thread_exit" );
- });
- }
- adjust_count( Idx_unexited_thread, -1 );
- ldap_int_thread_exit( retval );
-}
-
int
ldap_pvt_thread_join( ldap_pvt_thread_t thread, void **thread_return )
{
{
int rc;
static int init = 0;
+ ldap_pvt_thread_rmutex_t rm;
+ ldap_pvt_thread_t tid;
/* we only get one shot at this */
if( init++ ) return -1;
if( rc ) return rc;
#endif
+ /* kludge to pull symbol definitions in */
+ ldap_pvt_thread_rmutex_init( &rm );
+ tid = ldap_pvt_thread_self();
+ ldap_pvt_thread_rmutex_lock( &rm, tid );
+ ldap_pvt_thread_rmutex_trylock( &rm, tid );
+ ldap_pvt_thread_rmutex_unlock( &rm, tid );
+ ldap_pvt_thread_rmutex_unlock( &rm, tid );
+ ldap_pvt_thread_rmutex_destroy( &rm );
+
return 0;
}
#define MAXKEYS 32
#define LDAP_MAXTHR 1024 /* must be a power of 2 */
+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;
static struct {
ldap_pvt_thread_t id;
- ldap_int_thread_key_t *ctx;
+ ldap_int_thread_userctx_t *ctx;
} thread_keys[LDAP_MAXTHR];
static ldap_pvt_thread_t ldap_int_main_tid;
-static ldap_int_thread_key_t ldap_int_main_thrctx[LDAP_MAXTHR];
+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;
return ldap_pvt_thread_mutex_init(&ldap_pvt_thread_pool_mutex);
}
struct ldap_int_thread_pool_s *pool;
while ((pool = LDAP_STAILQ_FIRST(&ldap_int_thread_pool_list)) != NULL) {
- LDAP_STAILQ_REMOVE_HEAD(&ldap_int_thread_pool_list, ltp_next);
(ldap_pvt_thread_pool_destroy)(&pool, 0); /* ignore thr_debug macro */
}
ldap_pvt_thread_mutex_destroy(&ldap_pvt_thread_pool_mutex);
{
struct ldap_int_thread_pool_s *pool = xpool;
ldap_int_thread_ctx_t *ctx;
- ldap_int_thread_key_t ltc_key[MAXKEYS];
- ldap_pvt_thread_t tid;
+ ldap_int_thread_userctx_t uctx;
int i, keyslot, hash;
if (pool == NULL)
return NULL;
for ( i=0; i<MAXKEYS; i++ ) {
- ltc_key[i].ltk_key = NULL;
+ uctx.ltu_key[i].ltk_key = NULL;
}
- tid = ldap_pvt_thread_self();
+ uctx.ltu_id = ldap_pvt_thread_self();
ldap_pvt_thread_mutex_lock(&pool->ltp_mutex);
/* store pointer to our keys */
- TID_HASH(tid, hash);
+ TID_HASH(uctx.ltu_id, hash);
for (i = hash & (LDAP_MAXTHR-1);
- !ldap_pvt_thread_equal(thread_keys[i].id, tid);
+ !ldap_pvt_thread_equal(thread_keys[i].id, uctx.ltu_id);
i = (i+1) & (LDAP_MAXTHR-1));
- thread_keys[i].ctx = ltc_key;
+ thread_keys[i].ctx = &uctx;
keyslot = i;
while (pool->ltp_state != LDAP_INT_THREAD_POOL_STOPPING) {
pool->ltp_active_count++;
ldap_pvt_thread_mutex_unlock(&pool->ltp_mutex);
- ctx->ltc_start_routine(ltc_key, ctx->ltc_arg);
+ ctx->ltc_start_routine(&uctx, ctx->ltc_arg);
#ifdef LDAP_PVT_THREAD_POOL_SEM_LOAD_CONTROL
ldap_lazy_sem_post( thread_pool_sem );
}
}
- for ( i=0; i<MAXKEYS && ltc_key[i].ltk_key; i++ ) {
- if (ltc_key[i].ltk_free)
- ltc_key[i].ltk_free(
- ltc_key[i].ltk_key,
- ltc_key[i].ltk_data );
+ for ( i=0; i<MAXKEYS && uctx.ltu_key[i].ltk_key; i++ ) {
+ if (uctx.ltu_key[i].ltk_free)
+ uctx.ltu_key[i].ltk_free(
+ uctx.ltu_key[i].ltk_key,
+ uctx.ltu_key[i].ltk_data );
}
thread_keys[keyslot].ctx = NULL;
void **data,
ldap_pvt_thread_pool_keyfree_t **kfree )
{
- ldap_int_thread_key_t *ctx = xctx;
+ ldap_int_thread_userctx_t *ctx = xctx;
int i;
if ( !ctx || !data ) return EINVAL;
- for ( i=0; i<MAXKEYS && ctx[i].ltk_key; i++ ) {
- if ( ctx[i].ltk_key == key ) {
- *data = ctx[i].ltk_data;
- if ( kfree ) *kfree = ctx[i].ltk_free;
+ for ( i=0; i<MAXKEYS && ctx->ltu_key[i].ltk_key; i++ ) {
+ if ( ctx->ltu_key[i].ltk_key == key ) {
+ *data = ctx->ltu_key[i].ltk_data;
+ if ( kfree ) *kfree = ctx->ltu_key[i].ltk_free;
return 0;
}
}
void *data,
ldap_pvt_thread_pool_keyfree_t *kfree )
{
- ldap_int_thread_key_t *ctx = xctx;
+ ldap_int_thread_userctx_t *ctx = xctx;
int i;
if ( !ctx || !key ) return EINVAL;
for ( i=0; i<MAXKEYS; i++ ) {
- if ( !ctx[i].ltk_key || ctx[i].ltk_key == key ) {
- ctx[i].ltk_key = key;
- ctx[i].ltk_data = data;
- ctx[i].ltk_free = kfree;
+ 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;
}
}
void ldap_pvt_thread_pool_purgekey( void *key )
{
int i, j;
- ldap_int_thread_key_t *ctx;
+ ldap_int_thread_userctx_t *ctx;
for ( i=0; i<LDAP_MAXTHR; i++ ) {
if ( thread_keys[i].ctx ) {
ctx = thread_keys[i].ctx;
for ( j=0; j<MAXKEYS; j++ ) {
- if ( ctx[j].ltk_key == key ) {
- if (ctx[j].ltk_free)
- ctx[j].ltk_free( ctx[j].ltk_key, ctx[j].ltk_data );
- ctx[j].ltk_key = NULL;
- ctx[j].ltk_free = NULL;
+ 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;
break;
}
}
tid = ldap_pvt_thread_self();
if ( ldap_pvt_thread_equal( tid, ldap_int_main_tid ))
- return ldap_int_main_thrctx;
+ return &ldap_int_main_thrctx;
TID_HASH( tid, hash );
for (i = hash & (LDAP_MAXTHR-1);
void ldap_pvt_thread_pool_context_reset( void *vctx )
{
- ldap_int_thread_key_t *ctx = vctx;
+ ldap_int_thread_userctx_t *ctx = vctx;
int i;
- for ( i=0; i<MAXKEYS && ctx[i].ltk_key; i++) {
- if ( ctx[i].ltk_free )
- ctx[i].ltk_free( ctx[i].ltk_key, ctx[i].ltk_data );
- ctx[i].ltk_key = NULL;
+ for ( i=0; i<MAXKEYS && ctx->ltu_key[i].ltk_key; i++) {
+ if ( ctx->ltu_key[i].ltk_free )
+ ctx->ltu_key[i].ltk_free( ctx->ltu_key[i].ltk_key,
+ ctx->ltu_key[i].ltk_data );
+ ctx->ltu_key[i].ltk_key = NULL;
}
}
+
+ldap_pvt_thread_t ldap_pvt_thread_pool_tid( void *vctx )
+{
+ ldap_int_thread_userctx_t *ctx = vctx;
+
+ return ctx->ltu_id;
+}
#endif /* LDAP_THREAD_HAVE_TPOOL */
if (tm->tm_sec < 0 || tm->tm_sec > 61) break;
/* Fractions of seconds */
- for (i = 0, fracs = 0; isdigit((unsigned char) *ptr); ) {
- i*=10; i+= *ptr++ - '0';
- fracs++;
- }
- tm->tm_usec = i;
- if (i) {
- for (i = fracs; i<6; i++)
- tm->tm_usec *= 10;
+ if ( *ptr == '.' ) {
+ ptr++;
+ for (i = 0, fracs = 0; isdigit((unsigned char) *ptr); ) {
+ i*=10; i+= *ptr++ - '0';
+ fracs++;
+ }
+ tm->tm_usec = i;
+ if (i) {
+ for (i = fracs; i<6; i++)
+ tm->tm_usec *= 10;
+ }
}
/* Must be UTC */
assert( s != NULL );
assert( v != NULL );
+ /* strtoul() has an odd interface */
+ if ( s[ 0 ] == '-' ) {
+ return -1;
+ }
+
u = strtoul( s, &next, x );
if ( next == s || next[ 0 ] != '\0' ) {
return -1;
assert( s != NULL );
assert( v != NULL );
+ /* strtoul() has an odd interface */
+ if ( s[ 0 ] == '-' ) {
+ return -1;
+ }
+
ul = strtoul( s, &next, x );
if ( next == s || next[ 0 ] != '\0' ) {
return -1;
unsigned long u;
char *what;
+ /* strtoul() has an odd interface */
+ if ( s[ 0 ] == '-' ) {
+ return -1;
+ }
+
u = strtoul( s, &next, 10 );
if ( next == s ) {
return -1;
}
/* start out with nothing granted, nothing denied */
- ACL_INIT(tgrant);
- ACL_INIT(tdeny);
+ ACL_INVALIDATE(tgrant);
+ ACL_INVALIDATE(tdeny);
for ( da = b->a_dynacl; da; da = da->da_next ) {
slap_access_t grant,
deny;
- ACL_INIT(grant);
- ACL_INIT(deny);
+ ACL_INVALIDATE(grant);
+ ACL_INVALIDATE(deny);
Debug( LDAP_DEBUG_ACL, " <= check a_dynacl: %s\n",
da->da_name, 0, 0 );
/* out of arguments or plain stop */
ACL_PRIV_ASSIGN( b->a_access_mask, ACL_PRIV_ADDITIVE );
+ ACL_PRIV_SET( b->a_access_mask, ACL_PRIV_NONE);
b->a_type = ACL_STOP;
access_append( &a->acl_access, b );
/* plain continue */
ACL_PRIV_ASSIGN( b->a_access_mask, ACL_PRIV_ADDITIVE );
+ ACL_PRIV_SET( b->a_access_mask, ACL_PRIV_NONE);
b->a_type = ACL_CONTINUE;
access_append( &a->acl_access, b );
/* plain continue */
ACL_PRIV_ASSIGN(b->a_access_mask, ACL_PRIV_ADDITIVE);
+ ACL_PRIV_SET( b->a_access_mask, ACL_PRIV_NONE);
b->a_type = ACL_BREAK;
access_append( &a->acl_access, b );
/* we've gone too far */
--i;
ACL_PRIV_ASSIGN( b->a_access_mask, ACL_PRIV_ADDITIVE );
+ ACL_PRIV_SET( b->a_access_mask, ACL_PRIV_NONE);
b->a_type = ACL_STOP;
access_append( &a->acl_access, b );
}
/* get <access> */
- if ( strncasecmp( left, "self", STRLENOF( "self" ) ) == 0 ) {
- b->a_dn_self = 1;
- ACL_PRIV_ASSIGN( b->a_access_mask, str2accessmask( &left[ STRLENOF( "self" ) ] ) );
+ {
+ char *lleft = left;
- } else if ( strncasecmp( left, "realself", STRLENOF( "realself" ) ) == 0 ) {
- b->a_realdn_self = 1;
- ACL_PRIV_ASSIGN( b->a_access_mask, str2accessmask( &left[ STRLENOF( "realself" ) ] ) );
+ if ( strncasecmp( left, "self", STRLENOF( "self" ) ) == 0 ) {
+ b->a_dn_self = 1;
+ lleft = &left[ STRLENOF( "self" ) ];
- } else {
- ACL_PRIV_ASSIGN( b->a_access_mask, str2accessmask( left ) );
+ } else if ( strncasecmp( left, "realself", STRLENOF( "realself" ) ) == 0 ) {
+ b->a_realdn_self = 1;
+ lleft = &left[ STRLENOF( "realself" ) ];
+ }
+
+ ACL_PRIV_ASSIGN( b->a_access_mask, str2accessmask( lleft ) );
}
if ( ACL_IS_INVALID( b->a_access_mask ) ) {
} else if( TOLOWER((unsigned char) str[i]) == 'd' ) {
ACL_PRIV_SET(mask, ACL_PRIV_DISCLOSE);
- } else if( str[i] != '0' ) {
+ } else if( str[i] == '0' ) {
+ ACL_PRIV_SET(mask, ACL_PRIV_NONE);
+
+ } else {
ACL_INVALIDATE(mask);
return mask;
}
{
char *access =
"<access clause> ::= access to <what> "
- "[ by <who> <access> [ <control> ] ]+ \n";
+ "[ by <who> [ <access> ] [ <control> ] ]+ \n";
char *what =
- "<what> ::= * | [dn[.<dnstyle>]=<DN>] [filter=<filter>] [attrs=<attrspec>]\n"
+ "<what> ::= * | dn[.<dnstyle>=<DN>] [filter=<filter>] [attrs=<attrspec>]\n"
"<attrspec> ::= <attrname> [val[/<matchingRule>][.<attrstyle>]=<value>] | <attrlist>\n"
"<attrlist> ::= <attr> [ , <attrlist> ]\n"
"<attr> ::= <attrname> | @<objectClass> | !<objectClass> | entry | children\n";
}
static char *strchrlen(
- const char *p,
+ const char *beg,
+ const char *end,
const char ch,
int *len )
{
- int i;
+ const char *p;
- for( i=0; p[i]; i++ ) {
- if( p[i] == ch ) {
- *len = i;
- return (char *) &p[i];
+ for( p=beg; *p && p < end; p++ ) {
+ if( *p == ch ) {
+ *len = p - beg;
+ return (char *) p;
}
}
- *len = i;
+ *len = p - beg;
return NULL;
}
{
int rtn = LDAP_UNDEFINED_TYPE;
AttributeDescription desc, *d2;
- char *name, *options;
+ char *name, *options, *optn;
char *opt, *next;
int ntags;
int tagslen;
ntags = 0;
memset( tags, 0, sizeof( tags ));
tagslen = 0;
+ optn = bv->bv_val + bv->bv_len;
for( opt=options; opt != NULL; opt=next ) {
int optlen;
opt++;
- next = strchrlen( opt, ';', &optlen );
+ next = strchrlen( opt, optn, ';', &optlen );
if( optlen == 0 ) {
*text = "zero length option is invalid";
struct berval *subtagsbv,
struct berval *suptagsbv )
{
- const char *suptags, *supp, *supdelimp;
- const char *subtags, *subp, *subdelimp;
+ const char *suptags, *supp, *supdelimp, *supn;
+ const char *subtags, *subp, *subdelimp, *subn;
int suplen, sublen;
subtags =subtagsbv->bv_val;
suptags =suptagsbv->bv_val;
+ subn = subtags + subtagsbv->bv_len;
+ supn = suptags + suptagsbv->bv_len;
for( supp=suptags ; supp; supp=supdelimp ) {
- supdelimp = strchrlen( supp, ';', &suplen );
+ supdelimp = strchrlen( supp, supn, ';', &suplen );
if( supdelimp ) supdelimp++;
for( subp=subtags ; subp; subp=subdelimp ) {
- subdelimp = strchrlen( subp, ';', &sublen );
+ subdelimp = strchrlen( subp, subn, ';', &sublen );
if( subdelimp ) subdelimp++;
if ( suplen > sublen
}
if (alock_read_iattr (slotbuf) != ALOCK_MAGIC) {
- return 1;
+ return -1;
}
slot_data->al_lock = alock_read_iattr (slotbuf+8);
slot_data->al_stamp = alock_read_iattr (slotbuf+16);
alock_write_iattr (slotbuf+16, slot_data->al_stamp);
alock_write_iattr (slotbuf+24, slot_data->al_pid);
- strncpy ((char *)slotbuf+32, slot_data->al_appname, ALOCK_MAX_APPNAME-1);
+ if (slot_data->al_appname)
+ strncpy ((char *)slotbuf+32, slot_data->al_appname, ALOCK_MAX_APPNAME-1);
slotbuf[ALOCK_SLOT_SIZE-1] = '\0';
res = lseek (info->al_fd,
}
op->o_private = NULL;
- if( postread_ctrl != NULL ) {
+ if( postread_ctrl != NULL && (*postread_ctrl) != NULL ) {
slap_sl_free( (*postread_ctrl)->ldctl_value.bv_val, op->o_tmpmemctx );
slap_sl_free( *postread_ctrl, op->o_tmpmemctx );
}
send_ldap_result( op, rs );
slap_graduate_commit_csn( op );
- if( preread_ctrl != NULL ) {
+ if( preread_ctrl != NULL && (*preread_ctrl) != NULL ) {
slap_sl_free( (*preread_ctrl)->ldctl_value.bv_val, op->o_tmpmemctx );
slap_sl_free( *preread_ctrl, op->o_tmpmemctx );
}
return 0;
}
-#if 0
+#if 1
/* Quicksort + Insertion sort for small arrays */
LDAP_CONTROL_MANAGEDSAIT,
LDAP_CONTROL_NOOP,
LDAP_CONTROL_PAGEDRESULTS,
+ LDAP_CONTROL_PRE_READ,
+ LDAP_CONTROL_POST_READ,
LDAP_CONTROL_SUBENTRIES,
LDAP_CONTROL_X_PERMISSIVE_MODIFY,
#ifdef LDAP_X_TXN
bdb_unlocked_cache_return_entry_w (&bdb->bi_cache, e);
}
- if( preread_ctrl != NULL ) {
+ if( preread_ctrl != NULL && (*preread_ctrl) != NULL ) {
slap_sl_free( (*preread_ctrl)->ldctl_value.bv_val, op->o_tmpmemctx );
slap_sl_free( *preread_ctrl, op->o_tmpmemctx );
}
- if( postread_ctrl != NULL ) {
+ if( postread_ctrl != NULL && (*postread_ctrl) != NULL ) {
slap_sl_free( (*postread_ctrl)->ldctl_value.bv_val, op->o_tmpmemctx );
slap_sl_free( *postread_ctrl, op->o_tmpmemctx );
}
}
op->o_private = NULL;
- if( preread_ctrl != NULL ) {
+ if( preread_ctrl != NULL && (*preread_ctrl) != NULL ) {
slap_sl_free( (*preread_ctrl)->ldctl_value.bv_val, op->o_tmpmemctx );
slap_sl_free( *preread_ctrl, op->o_tmpmemctx );
}
- if( postread_ctrl != NULL ) {
+ if( postread_ctrl != NULL && (*postread_ctrl) != NULL ) {
slap_sl_free( (*postread_ctrl)->ldctl_value.bv_val, op->o_tmpmemctx );
slap_sl_free( *postread_ctrl, op->o_tmpmemctx );
}
static void *bdb_tool_index_rec;
static struct bdb_info *bdb_tool_info;
static ldap_pvt_thread_mutex_t bdb_tool_index_mutex;
-static ldap_pvt_thread_cond_t bdb_tool_index_cond;
+static ldap_pvt_thread_cond_t bdb_tool_index_cond_main;
+static ldap_pvt_thread_cond_t bdb_tool_index_cond_work;
static void * bdb_tool_index_task( void *ctx, void *ptr );
if ( !bdb_tool_info ) {
int i;
ldap_pvt_thread_mutex_init( &bdb_tool_index_mutex );
- ldap_pvt_thread_cond_init( &bdb_tool_index_cond );
+ 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;
slapd_shutdown = 1;
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 );
+ ldap_pvt_thread_cond_broadcast( &bdb_tool_index_cond_work );
ldap_pvt_thread_mutex_unlock( &bdb_tool_index_mutex );
}
ldap_pvt_thread_mutex_lock( &bdb_tool_index_mutex );
/* Wait for all threads to be ready */
while ( bdb_tool_index_tcount ) {
- ldap_pvt_thread_mutex_unlock( &bdb_tool_index_mutex );
- ldap_pvt_thread_yield();
- ldap_pvt_thread_mutex_lock( &bdb_tool_index_mutex );
+ ldap_pvt_thread_cond_wait( &bdb_tool_index_cond_main,
+ &bdb_tool_index_mutex );
}
for ( i=1; i<slap_tool_thread_max; i++ )
bdb_tool_index_threads[i] = LDAP_BUSY;
bdb_tool_index_tcount = slap_tool_thread_max - 1;
- ldap_pvt_thread_cond_broadcast( &bdb_tool_index_cond );
+ ldap_pvt_thread_cond_broadcast( &bdb_tool_index_cond_work );
ldap_pvt_thread_mutex_unlock( &bdb_tool_index_mutex );
rc = bdb_index_recrun( op, bdb, ir, e->e_id, 0 );
if ( rc )
return rc;
+ ldap_pvt_thread_mutex_lock( &bdb_tool_index_mutex );
for ( i=1; i<slap_tool_thread_max; i++ ) {
if ( bdb_tool_index_threads[i] == LDAP_BUSY ) {
- ldap_pvt_thread_yield();
+ ldap_pvt_thread_cond_wait( &bdb_tool_index_cond_main,
+ &bdb_tool_index_mutex );
i--;
continue;
}
- if ( bdb_tool_index_threads[i] )
- return bdb_tool_index_threads[i];
+ if ( bdb_tool_index_threads[i] ) {
+ rc = bdb_tool_index_threads[i];
+ break;
+ }
}
- return 0;
+ ldap_pvt_thread_mutex_unlock( &bdb_tool_index_mutex );
+ return rc;
} else {
return bdb_index_entry_add( op, txn, e );
}
while ( 1 ) {
ldap_pvt_thread_mutex_lock( &bdb_tool_index_mutex );
bdb_tool_index_tcount--;
- ldap_pvt_thread_cond_wait( &bdb_tool_index_cond,
+ if ( !bdb_tool_index_tcount )
+ ldap_pvt_thread_cond_signal( &bdb_tool_index_cond_main );
+ ldap_pvt_thread_cond_wait( &bdb_tool_index_cond_work,
&bdb_tool_index_mutex );
ldap_pvt_thread_mutex_unlock( &bdb_tool_index_mutex );
if ( slapd_shutdown )
} \
} while ( 0 )
-#define LDAP_BACK_FCONN_ISBOUND (0x01)
-#define LDAP_BACK_FCONN_ISANON (0x02)
+#define LDAP_BACK_FCONN_ISBOUND (0x00000001U)
+#define LDAP_BACK_FCONN_ISANON (0x00000002U)
#define LDAP_BACK_FCONN_ISBMASK (LDAP_BACK_FCONN_ISBOUND|LDAP_BACK_FCONN_ISANON)
-#define LDAP_BACK_FCONN_ISPRIV (0x04)
-#define LDAP_BACK_FCONN_ISTLS (0x08)
-#define LDAP_BACK_FCONN_BINDING (0x10)
-#define LDAP_BACK_FCONN_TAINTED (0x20)
+#define LDAP_BACK_FCONN_ISPRIV (0x00000004U)
+#define LDAP_BACK_FCONN_ISTLS (0x00000008U)
+#define LDAP_BACK_FCONN_BINDING (0x00000010U)
+#define LDAP_BACK_FCONN_TAINTED (0x00000020U)
+
+/* 0x00FF0000 are reserved for back-meta */
#define LDAP_BACK_CONN_ISBOUND(lc) LDAP_BACK_CONN_ISSET((lc), LDAP_BACK_FCONN_ISBOUND)
#define LDAP_BACK_CONN_ISBOUND_SET(lc) LDAP_BACK_CONN_SET((lc), LDAP_BACK_FCONN_ISBOUND)
/* li_bvuri: an array of each single URI that is equivalent;
* to be checked for the presence of a certain item */
BerVarray li_bvuri;
+ ldap_pvt_thread_mutex_t li_uri_mutex;
+
+ LDAP_REBIND_PROC *li_rebind_f;
+ LDAP_URLLIST_PROC *li_urllist_f;
+ void *li_urllist_p;
slap_bindconf li_acl;
#define li_acl_authcID li_acl.sb_authcId
#define LDAP_BACK_RETRY_DEFAULT (3)
unsigned li_flags;
-#define LDAP_BACK_F_NONE 0x00U
-#define LDAP_BACK_F_SAVECRED 0x01U
-#define LDAP_BACK_F_USE_TLS 0x02U
-#define LDAP_BACK_F_PROPAGATE_TLS 0x04U
-#define LDAP_BACK_F_TLS_CRITICAL 0x08U
+#define LDAP_BACK_F_NONE 0x0000U
+#define LDAP_BACK_F_SAVECRED 0x0001U
+#define LDAP_BACK_F_USE_TLS 0x0002U
+#define LDAP_BACK_F_PROPAGATE_TLS 0x0004U
+#define LDAP_BACK_F_TLS_CRITICAL 0x0008U
#define LDAP_BACK_F_TLS_USE_MASK (LDAP_BACK_F_USE_TLS|LDAP_BACK_F_TLS_CRITICAL)
#define LDAP_BACK_F_TLS_PROPAGATE_MASK (LDAP_BACK_F_PROPAGATE_TLS|LDAP_BACK_F_TLS_CRITICAL)
#define LDAP_BACK_F_TLS_MASK (LDAP_BACK_F_TLS_USE_MASK|LDAP_BACK_F_TLS_PROPAGATE_MASK)
-#define LDAP_BACK_F_CHASE_REFERRALS 0x10U
-#define LDAP_BACK_F_PROXY_WHOAMI 0x20U
+#define LDAP_BACK_F_CHASE_REFERRALS 0x0010U
+#define LDAP_BACK_F_PROXY_WHOAMI 0x0020U
+
+#define LDAP_BACK_F_SUPPORT_T_F_DISCOVER 0x0040U
+#define LDAP_BACK_F_SUPPORT_T_F 0x0080U
+#define LDAP_BACK_F_SUPPORT_T_F_MASK (LDAP_BACK_F_SUPPORT_T_F|LDAP_BACK_F_SUPPORT_T_F_DISCOVER)
-#define LDAP_BACK_F_SUPPORT_T_F 0x80U
-#define LDAP_BACK_F_SUPPORT_T_F_DISCOVER 0x40U
-#define LDAP_BACK_F_SUPPORT_T_F_MASK (LDAP_BACK_F_SUPPORT_T_F|LDAP_BACK_F_SUPPORT_T_F_DISCOVER)
+#define LDAP_BACK_F_MONITOR 0x0100U
+#define LDAP_BACK_F_SINGLECONN 0x0200U
#define LDAP_BACK_ISSET(li,f) ( ( (li)->li_flags & (f) ) == (f) )
#define LDAP_BACK_SAVECRED(li) LDAP_BACK_ISSET( (li), LDAP_BACK_F_SAVECRED )
#define LDAP_BACK_TLS_CRITICAL(li) LDAP_BACK_ISSET( (li), LDAP_BACK_F_TLS_CRITICAL )
#define LDAP_BACK_CHASE_REFERRALS(li) LDAP_BACK_ISSET( (li), LDAP_BACK_F_CHASE_REFERRALS )
#define LDAP_BACK_PROXY_WHOAMI(li) LDAP_BACK_ISSET( (li), LDAP_BACK_F_PROXY_WHOAMI )
+#define LDAP_BACK_MONITOR(li) LDAP_BACK_ISSET( (li), LDAP_BACK_F_MONITOR )
+#define LDAP_BACK_SINGLECONN(li) LDAP_BACK_ISSET( (li), LDAP_BACK_F_SINGLECONN )
int li_version;
#define LDAP_CONTROL_OBSOLETE_PROXY_AUTHZ "2.16.840.1.113730.3.4.12"
-static LDAP_REBIND_PROC ldap_back_default_rebind;
+#if PRINT_CONNTREE > 0
+static void
+ravl_print( Avlnode *root, int depth )
+{
+ int i;
+ ldapconn_t *lc;
+
+ if ( root == 0 ) {
+ return;
+ }
+
+ ravl_print( root->avl_right, depth+1 );
+
+ for ( i = 0; i < depth; i++ ) {
+ fprintf( stderr, "-" );
+ }
+
+ lc = root->avl_data;
+ fprintf( stderr, "lc=%p local=\"%s\" conn=%p %s refcnt=%d\n",
+ (void *)lc,
+ lc->lc_local_ndn.bv_val ? lc->lc_local_ndn.bv_val : "",
+ (void *)lc->lc_conn,
+ avl_bf2str( root->avl_bf ), lc->lc_refcnt );
+
+ ravl_print( root->avl_left, depth+1 );
+}
-LDAP_REBIND_PROC *ldap_back_rebind_f = ldap_back_default_rebind;
+static void
+myprint( Avlnode *root, char *msg )
+{
+ fprintf( stderr, "========> %s\n", msg );
+
+ if ( root == 0 ) {
+ fprintf( stderr, "\tNULL\n" );
+
+ } else {
+ ravl_print( root, 0 );
+ }
+
+ fprintf( stderr, "<======== %s\n", msg );
+}
+#endif /* PRINT_CONNTREE */
static int
ldap_back_proxy_authz_bind( ldapconn_t *lc, Operation *op, SlapReply *rs, ldap_back_send_t sendok );
lc->lc_cred.bv_len );
}
ber_bvreplace( &lc->lc_cred, &op->orb_cred );
- ldap_set_rebind_proc( lc->lc_ld, ldap_back_rebind_f, lc );
+ ldap_set_rebind_proc( lc->lc_ld, li->li_rebind_f, lc );
}
}
done:;
ldap_back_conndnlc_cmp );
assert( tmplc == NULL || lc == tmplc );
+ /* delete all cached connections with the current connection */
+ if ( LDAP_BACK_SINGLECONN( li ) ) {
+ while ( ( tmplc = avl_delete( &li->li_conninfo.lai_tree, (caddr_t)lc, ldap_back_conn_cmp ) ) != NULL )
+ {
+ Debug( LDAP_DEBUG_TRACE,
+ "=>ldap_back_bind: destroying conn %ld (refcnt=%u)\n",
+ LDAP_BACK_PCONN_ID( lc->lc_conn ), lc->lc_refcnt, 0 );
+
+ if ( lc->lc_refcnt != 0 ) {
+ /* taint it */
+ LDAP_BACK_CONN_TAINTED_SET( tmplc );
+
+ } else {
+ /*
+ * Needs a test because the handler may be corrupted,
+ * and calling ldap_unbind on a corrupted header results
+ * in a segmentation fault
+ */
+ ldap_back_conn_free( tmplc );
+ }
+ }
+ }
+
if ( LDAP_BACK_CONN_ISBOUND( lc ) ) {
ber_bvreplace( &lc->lc_local_ndn, &op->o_req_ndn );
+ if ( be_isroot_dn( op->o_bd, &op->o_req_ndn ) ) {
+ lc->lc_conn = LDAP_BACK_PCONN_SET( op );
+ }
lerr = avl_insert( &li->li_conninfo.lai_tree, (caddr_t)lc,
ldap_back_conndn_cmp, ldap_back_conndn_dup );
}
+#if PRINT_CONNTREE > 0
+ myprint( li->li_conninfo.lai_tree, "ldap_back_bind" );
+#endif /* PRINT_CONNTREE */
+
ldap_pvt_thread_mutex_unlock( &li->li_conninfo.lai_mutex );
switch ( lerr ) {
case 0:
return 0;
}
-#if PRINT_CONNTREE > 0
-static void
-ravl_print( Avlnode *root, int depth )
-{
- int i;
- ldapconn_t *lc;
-
- if ( root == 0 ) {
- return;
- }
-
- ravl_print( root->avl_right, depth+1 );
-
- for ( i = 0; i < depth; i++ ) {
- fprintf( stderr, "-" );
- }
-
- lc = root->avl_data;
- fprintf( stderr, "lc=%p local=\"%s\" conn=%p %s refcnt=%d\n",
- (void *)lc, lc->lc_local_ndn.bv_val, (void *)lc->lc_conn,
- avl_bf2str( root->avl_bf ), lc->lc_refcnt );
-
- ravl_print( root->avl_left, depth+1 );
-}
-
-static void
-myprint( Avlnode *root )
-{
- fprintf( stderr, "========>\n" );
-
- if ( root == 0 ) {
- fprintf( stderr, "\tNULL\n" );
-
- } else {
- ravl_print( root, 0 );
- }
-
- fprintf( stderr, "<========\n" );
-}
-#endif /* PRINT_CONNTREE */
-
int
ldap_back_freeconn( Operation *op, ldapconn_t *lc, int dolock )
{
assert( lcp != NULL );
+ ldap_pvt_thread_mutex_lock( &li->li_uri_mutex );
rs->sr_err = ldap_initialize( &ld, li->li_uri );
+ ldap_pvt_thread_mutex_unlock( &li->li_uri_mutex );
if ( rs->sr_err != LDAP_SUCCESS ) {
goto error_return;
}
+ if ( li->li_urllist_f ) {
+ ldap_set_urllist_proc( ld, li->li_urllist_f, li->li_urllist_p );
+ }
+
/* Set LDAP version. This will always succeed: If the client
* bound with a particular version, then so can we.
*/
}
#ifdef HAVE_TLS
+ ldap_pvt_thread_mutex_lock( &li->li_uri_mutex );
rs->sr_err = ldap_back_start_tls( ld, op->o_protocol, &is_tls,
li->li_uri, li->li_flags, li->li_nretries, &rs->sr_text );
+ ldap_pvt_thread_mutex_unlock( &li->li_uri_mutex );
if ( rs->sr_err != LDAP_SUCCESS ) {
ldap_unbind_ext( ld, NULL, NULL );
goto error_return;
if ( *lcp == NULL ) {
*lcp = (ldapconn_t *)ch_calloc( 1, sizeof( ldapconn_t ) );
- (*lcp)->lc_flags= li->li_flags;
+ (*lcp)->lc_flags = li->li_flags;
}
(*lcp)->lc_ld = ld;
(*lcp)->lc_refcnt = 1;
ldap_back_conndn_cmp, ldap_back_conndn_dup );
#if PRINT_CONNTREE > 0
- myprint( li->li_conninfo.lai_tree );
+ myprint( li->li_conninfo.lai_tree, "ldap_back_getconn" );
#endif /* PRINT_CONNTREE */
ldap_pvt_thread_mutex_unlock( &li->li_conninfo.lai_mutex );
Debug( LDAP_DEBUG_TRACE,
"=>ldap_back_getconn: %s.\n", buf, 0, 0 );
}
+
}
+#ifdef HAVE_TLS
+done:;
+#endif /* HAVE_TLS */
if ( li->li_idle_timeout && lc ) {
lc->lc_time = op->o_time;
}
-done:;
return lc;
}
if ( rc != LDAP_OPT_SUCCESS ) {
Debug( LDAP_DEBUG_ANY, "Error: ldap_set_option "
- "(%s,SECPROPS,\"%s\") failed!\n",
- li->li_uri, li->li_acl_secprops, 0 );
+ "(SECPROPS,\"%s\") failed!\n",
+ li->li_acl_secprops, 0, 0 );
goto done;
}
}
}
}
+ lc->lc_binding--;
ldap_back_freeconn( op, lc, dolock );
rs->sr_err = slap_map_api2result( rs );
* This is a callback used for chasing referrals using the same
* credentials as the original user on this session.
*/
-static int
+int
ldap_back_default_rebind( LDAP *ld, LDAP_CONST char *url, ber_tag_t request,
ber_int_t msgid, void *params )
{
LDAP_SASL_SIMPLE, &lc->lc_cred, NULL, NULL, NULL );
}
+/*
+ * ldap_back_default_urllist
+ */
+int
+ldap_back_default_urllist(
+ LDAP *ld,
+ LDAPURLDesc **urllist,
+ LDAPURLDesc **url,
+ void *params )
+{
+ ldapinfo_t *li = (ldapinfo_t *)params;
+ LDAPURLDesc **urltail;
+
+ if ( urllist == url ) {
+ return LDAP_SUCCESS;
+ }
+
+ for ( urltail = &(*url)->lud_next; *urltail; urltail = &(*urltail)->lud_next )
+ /* count */ ;
+
+ *urltail = *urllist;
+ *urllist = *url;
+ *url = NULL;
+
+ ldap_pvt_thread_mutex_lock( &li->li_uri_mutex );
+ if ( li->li_uri ) {
+ ch_free( li->li_uri );
+ }
+
+ ldap_get_option( ld, LDAP_OPT_URI, (void *)&li->li_uri );
+ ldap_pvt_thread_mutex_unlock( &li->li_uri_mutex );
+
+ return LDAP_SUCCESS;
+}
+
int
ldap_back_op_result(
ldapconn_t *lc,
ldap_pvt_thread_mutex_lock( &li->li_conninfo.lai_mutex );
if ( (*lcp)->lc_refcnt == 1 ) {
+ ldap_pvt_thread_mutex_lock( &li->li_uri_mutex );
Debug( LDAP_DEBUG_ANY,
"%s ldap_back_retry: retrying URI=\"%s\" DN=\"%s\"\n",
op->o_log_prefix, li->li_uri,
BER_BVISNULL( &(*lcp)->lc_bound_ndn ) ?
"" : (*lcp)->lc_bound_ndn.bv_val );
+ ldap_pvt_thread_mutex_unlock( &li->li_uri_mutex );
ldap_unbind_ext( (*lcp)->lc_ld, NULL, NULL );
(*lcp)->lc_ld = NULL;
goto done;
}
- if ( !BER_BVISNULL( &op->o_conn->c_ndn ) ) {
+ if ( op->o_tag == LDAP_REQ_BIND ) {
+ ndn = op->o_req_ndn;
+
+ } else if ( !BER_BVISNULL( &op->o_conn->c_ndn ) ) {
ndn = op->o_conn->c_ndn;
} else {
assertedID = slap_empty_bv;
}
+ /* don't idassert the bound DN (ITS#4497) */
+ if ( dn_match( &assertedID, &lc->lc_bound_ndn ) ) {
+ goto done;
+ }
+
if ( op->o_ctrls ) {
for ( i = 0; op->o_ctrls[ i ]; i++ )
/* just count ctrls */ ;
/* parse reference and use
* proto://[host][:port]/ only */
- rc = ldap_url_parse_ext( ref->bv_val, &srv );
+ rc = ldap_url_parse_ext( ref->bv_val, &srv, LDAP_PVT_URL_PARSE_NONE );
if ( rc != LDAP_URL_SUCCESS ) {
/* try next */
rc = LDAP_OTHER;
/* parse reference and use
* proto://[host][:port]/ only */
- rc = ldap_url_parse_ext( curr[0].bv_val, &srv );
+ rc = ldap_url_parse_ext( curr[0].bv_val, &srv, LDAP_PVT_URL_PARSE_NONE );
if ( rc != LDAP_URL_SUCCESS ) {
/* try next */
rs->sr_err = LDAP_OTHER;
BackendDB *be )
{
BackendInfo *bi = be->bd_info;
+ ldapinfo_t *li;
int t;
be->bd_info = lback;
if ( t != 0 ) {
return t;
}
+ li = (ldapinfo_t *)be->be_private;
+ li->li_urllist_f = NULL;
+ li->li_urllist_p = NULL;
be->bd_info = bi;
return 0;
return t;
}
li = (ldapinfo_t *)be->be_private;
+ li->li_urllist_f = NULL;
+ li->li_urllist_p = NULL;
/* copy common data */
li->li_nretries = lc->lc_common_li->li_nretries;
LDAP_BACK_CFG_CONN_TTL,
LDAP_BACK_CFG_NETWORK_TIMEOUT,
LDAP_BACK_CFG_VERSION,
+ LDAP_BACK_CFG_SINGLECONN,
LDAP_BACK_CFG_REWRITE,
LDAP_BACK_CFG_LAST
"SYNTAX OMsInteger "
"SINGLE-VALUE )",
NULL, NULL },
+ { "single-conn", "TRUE/FALSE", 2, 0, 0,
+ ARG_MAGIC|ARG_ON_OFF|LDAP_BACK_CFG_SINGLECONN,
+ ldap_back_cf_gen, "( OLcfgDbAt:3.19 "
+ "NAME 'olcDbSingleConn' "
+ "DESC 'cache a single connection per identity' "
+ "SYNTAX OMsBoolean "
+ "SINGLE-VALUE )",
+ NULL, NULL },
{ "suffixmassage", "[virtual]> <real", 2, 3, 0,
ARG_STRING|ARG_MAGIC|LDAP_BACK_CFG_REWRITE,
ldap_back_cf_gen, NULL, NULL, NULL },
"$ olcDbProxyWhoAmI "
"$ olcDbTimeout "
"$ olcDbIdleTimeout "
+ "$ olcDbSingleConn "
") )",
Cft_Database, ldapcfg},
{ NULL, 0, NULL }
c->value_int = li->li_version;
break;
+ case LDAP_BACK_CFG_SINGLECONN:
+ c->value_int = LDAP_BACK_SINGLECONN( li );
+ break;
+
default:
/* FIXME: we need to handle all... */
assert( 0 );
li->li_version = 0;
break;
+ case LDAP_BACK_CFG_SINGLECONN:
+ li->li_flags &= ~LDAP_BACK_F_SINGLECONN;
+ break;
+
default:
/* FIXME: we need to handle all... */
assert( 0 );
}
/* PARANOID: DN and more are not required nor allowed */
- urlrc = ldap_url_parselist_ext( &lud, c->argv[ 1 ], ", \t" );
+ urlrc = ldap_url_parselist_ext( &lud, c->argv[ 1 ], ", \t", LDAP_PVT_URL_PARSE_NONE );
if ( urlrc != LDAP_URL_SUCCESS ) {
char *why;
"host and port allowed "
"in \"uri <uri>\" statement "
"for uri #%d of \"%s\"",
- i, c->value_string );
+ i, c->argv[ 1 ] );
Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
}
}
} break;
case LDAP_BACK_CFG_VERSION:
- switch ( c->value_int ) {
- case 0:
- case LDAP_VERSION2:
- case LDAP_VERSION3:
- li->li_version = c->value_int;
- break;
-
- default:
+ if ( c->value_int != 0 && ( c->value_int < LDAP_VERSION_MIN || c->value_int > LDAP_VERSION_MAX ) ) {
+ snprintf( c->msg, sizeof( c->msg ),
+ "unsupported version \"%s\" "
+ "in \"protocol-version <version>\"",
+ c->argv[ 1 ] );
+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
return 1;
}
+
+ li->li_version = c->value_int;
+ break;
+
+ case LDAP_BACK_CFG_SINGLECONN:
+ if ( c->value_int ) {
+ li->li_flags |= LDAP_BACK_F_SINGLECONN;
+
+ } else {
+ li->li_flags &= ~LDAP_BACK_F_SINGLECONN;
+ }
break;
case LDAP_BACK_CFG_REWRITE:
return -1;
}
+ li->li_rebind_f = ldap_back_default_rebind;
+ li->li_urllist_f = ldap_back_default_urllist;
+ li->li_urllist_p = li;
+ ldap_pvt_thread_mutex_init( &li->li_uri_mutex );
+
BER_BVZERO( &li->li_acl_authcID );
BER_BVZERO( &li->li_acl_authcDN );
BER_BVZERO( &li->li_acl_passwd );
ldap_pvt_thread_mutex_unlock( &li->li_conninfo.lai_mutex );
ldap_pvt_thread_mutex_destroy( &li->li_conninfo.lai_mutex );
+ ldap_pvt_thread_mutex_destroy( &li->li_uri_mutex );
}
ch_free( be->be_private );
extern int distproc_initialize( void );
#endif
-extern LDAP_REBIND_PROC *ldap_back_rebind_f;
+extern LDAP_REBIND_PROC ldap_back_default_rebind;
+extern LDAP_URLLIST_PROC ldap_back_default_urllist;
LDAP_END_DECL
struct berval li_base_path;
enumCookie li_tool_cookie;
ID li_tool_current;
- ldap_pvt_thread_mutex_t li_mutex;
+ ldap_pvt_thread_rdwr_t li_rdwr;
};
#ifdef _WIN32
writeres = write(fd, spew, len);
if(writeres == -1) {
Debug( LDAP_DEBUG_ANY, "could not spew write: %s\n",
- strerror( errno ), 0, 0 );
+ STRERROR( errno ), 0, 0 );
return -1;
}
else {
else
rs = LDAP_UNWILLING_TO_PERFORM;
Debug( LDAP_DEBUG_ANY, "could not open \"%s\": %s\n",
- path->bv_val, strerror( errno ), 0 );
+ path->bv_val, STRERROR( errno ), 0 );
}
else {
struct berval rdn;
dn2path(&op->o_req_ndn, op->o_bd->be_nsuffix, base_path, &path);
fd = open(path.bv_val, O_RDONLY);
/* error opening file (mebbe should log error) */
- if(fd == -1) {
- Debug(LDAP_DEBUG_ANY, "failed to open file \"%s\": %s\n",
- path.bv_val, strerror(errno), 0 );
+ if ( fd == -1 && ( errno != ENOENT || op->o_tag != LDAP_REQ_ADD ) ) {
+ Debug( LDAP_DEBUG_ANY, "failed to open file \"%s\": %s\n",
+ path.bv_val, STRERROR(errno), 0 );
}
if(path.bv_val != NULL)
if ( fd < 0 ) {
Debug( LDAP_DEBUG_ANY,
"=> ldif_enum_tree: failed to open %s: %s\n",
- path->bv_val, strerror(errno), 0 );
+ path->bv_val, STRERROR(errno), 0 );
return LDAP_NO_SUCH_OBJECT;
}
if ( ptr ) {
itmp.bv_len = ptr - itmp.bv_val;
ber_dupbv( &bvl->num, &itmp );
- bvl->inum = strtoul( itmp.bv_val, NULL, 0 );
+ bvl->inum = strtol( itmp.bv_val, NULL, 0 );
itmp.bv_val[0] = '\0';
bvl->off = itmp.bv_val - bvl->bv.bv_val;
}
SlapReply * rs)
{
char textbuf[SLAP_TEXT_BUFLEN];
- int rc = LDAP_UNWILLING_TO_PERFORM;
+ int rc = modlist ? LDAP_UNWILLING_TO_PERFORM : LDAP_SUCCESS;
+ int is_oc = 0;
Modification *mods = NULL;
if (!acl_check_modlist(op, entry, modlist)) {
for (; modlist != NULL; modlist = modlist->sml_next) {
mods = &modlist->sml_mod;
+ if ( mods->sm_desc == slap_schema.si_ad_objectClass ) {
+ is_oc = 1;
+ }
switch (mods->sm_op) {
case LDAP_MOD_ADD:
rc = modify_add_values(entry, mods,
}
if(rc == LDAP_SUCCESS) {
- if ( mods->sm_desc == slap_schema.si_ad_objectClass ) {
+ if ( is_oc ) {
entry->e_ocflags = 0;
}
/* check that the entry still obeys the schema */
- rc = entry_schema_check(op, entry, NULL, 0,
+ rc = entry_schema_check( op, entry, NULL, 0,
&rs->sr_text, textbuf, sizeof( textbuf ) );
}
+
return rc;
}
}
ni = (struct ldif_info *)op->o_bd->be_private;
- ldap_pvt_thread_mutex_lock( &ni->li_mutex );
+ ldap_pvt_thread_rdwr_rlock( &ni->li_rdwr );
entry = (Entry *)get_entry( op, &ni->li_base_path );
/* no object is found for them */
entry = (Entry *)get_entry( op, &ni->li_base_path );
}
- ldap_pvt_thread_mutex_unlock( &ni->li_mutex );
+ ldap_pvt_thread_rdwr_runlock( &ni->li_rdwr );
op->o_req_dn = odn;
op->o_req_ndn = ondn;
return rc;
}
- ldap_pvt_thread_mutex_unlock( &ni->li_mutex );
+ ldap_pvt_thread_rdwr_runlock( &ni->li_rdwr );
if ( is_entry_referral( entry ) ) {
/* entry is a referral */
Entry * entry = NULL;
ni = (struct ldif_info *) op->o_bd->be_private;
- ldap_pvt_thread_mutex_lock(&ni->li_mutex);
+ ldap_pvt_thread_rdwr_rlock(&ni->li_rdwr);
entry = (Entry *) get_entry(op, &ni->li_base_path);
/* no object is found for them */
goto return_result;
return_result:
- ldap_pvt_thread_mutex_unlock(&ni->li_mutex);
+ ldap_pvt_thread_rdwr_runlock(&ni->li_rdwr);
if(return_val != 0)
send_ldap_result( op, rs );
if(entry != NULL)
ck.op = op;
ck.rs = rs;
- ldap_pvt_thread_mutex_lock(&ni->li_mutex);
+ ldap_pvt_thread_rdwr_rlock(&ni->li_rdwr);
rs->sr_err = enum_tree( &ck );
- ldap_pvt_thread_mutex_unlock(&ni->li_mutex);
+ ldap_pvt_thread_rdwr_runlock(&ni->li_rdwr);
send_ldap_result(op, rs);
return rs->sr_err;
&rs->sr_text, textbuf, sizeof( textbuf ) );
if ( rs->sr_err != LDAP_SUCCESS ) goto send_res;
- ldap_pvt_thread_mutex_lock(&ni->li_mutex);
+ ldap_pvt_thread_rdwr_wlock(&ni->li_rdwr);
dn2path(&dn, &op->o_bd->be_nsuffix[0], &ni->li_base_path, &leaf_path);
rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
rs->sr_text = "Could not create parent folder";
Debug( LDAP_DEBUG_ANY, "could not create folder \"%s\": %s\n",
- base.bv_val, strerror( errno ), 0 );
+ base.bv_val, STRERROR( errno ), 0 );
}
}
else
else if ( statres == -1 ) {
rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
Debug( LDAP_DEBUG_ANY, "could not stat file \"%s\": %s\n",
- leaf_path.bv_val, strerror( errno ), 0 );
+ leaf_path.bv_val, STRERROR( errno ), 0 );
}
else /* it already exists */
rs->sr_err = LDAP_ALREADY_EXISTS;
SLAP_FREE(leaf_path.bv_val);
}
- ldap_pvt_thread_mutex_unlock(&ni->li_mutex);
+ ldap_pvt_thread_rdwr_wunlock(&ni->li_rdwr);
send_res:
Debug( LDAP_DEBUG_TRACE,
- "ldif_back_add: err: %d text: %s\n", rs->sr_err, rs->sr_text, 0);
+ "ldif_back_add: err: %d text: %s\n", rs->sr_err, rs->sr_text ?
+ rs->sr_text : "", 0);
send_ldap_result(op, rs);
slap_graduate_commit_csn( op );
return 0;
slap_mods_opattrs( op, &op->orm_modlist, 1 );
- ldap_pvt_thread_mutex_lock(&ni->li_mutex);
+ ldap_pvt_thread_rdwr_wlock(&ni->li_rdwr);
dn2path(&op->o_req_ndn, &op->o_bd->be_nsuffix[0], &ni->li_base_path,
&path);
entry = (Entry *) get_entry(op, &ni->li_base_path);
if(spew_res == -1) {
Debug( LDAP_DEBUG_ANY,
"%s ldif_back_modify: could not output entry \"%s\": %s\n",
- op->o_log_prefix, entry->e_name.bv_val, strerror( save_errno ) );
+ op->o_log_prefix, entry->e_name.bv_val, STRERROR( save_errno ) );
rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
}
}
if(path.bv_val != NULL)
SLAP_FREE(path.bv_val);
rs->sr_text = NULL;
- ldap_pvt_thread_mutex_unlock(&ni->li_mutex);
+ ldap_pvt_thread_rdwr_wunlock(&ni->li_rdwr);
send_ldap_result(op, rs);
slap_graduate_commit_csn( op );
return 0;
slap_get_csn( op, &csn, 1 );
}
- ldap_pvt_thread_mutex_lock(&ni->li_mutex);
+ ldap_pvt_thread_rdwr_wlock(&ni->li_rdwr);
dn2path(&op->o_req_ndn, &op->o_bd->be_nsuffix[0], &ni->li_base_path, &path);
path.bv_val[path.bv_len - STRLENOF(LDIF)] = '\0';
rs->sr_err = LDAP_SUCCESS;
SLAP_FREE(path.bv_val);
- ldap_pvt_thread_mutex_unlock(&ni->li_mutex);
+ ldap_pvt_thread_rdwr_wunlock(&ni->li_rdwr);
send_ldap_result(op, rs);
slap_graduate_commit_csn( op );
return 0;
else { /* do the modrdn */
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);
if(res != -1) {
/* if this fails we should log something bad */
res = LDAP_UNWILLING_TO_PERFORM;
unlink(newpath.bv_val); /* in case file was created */
}
+ ldap_pvt_thread_mutex_unlock( &entry2str_mutex );
}
else if(exists_res) {
int close_res = close(exists_res);
slap_mods_opattrs( op, &op->orr_modlist, 1 );
- ldap_pvt_thread_mutex_lock( &ni->li_mutex );
- ldap_pvt_thread_mutex_lock( &entry2str_mutex );
+ ldap_pvt_thread_rdwr_wlock( &ni->li_rdwr );
entry = (Entry *) get_entry( op, &ni->li_base_path );
/* build the mods to the entry */
if ( entry != NULL ) {
/* build new dn, and new ndn for the entry */
if ( op->oq_modrdn.rs_newSup != NULL ) {
+ struct berval op_dn = op->o_req_dn,
+ op_ndn = op->o_req_ndn;
+ Entry *np;
+
/* new superior */
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 );
+ op->o_req_dn = op_dn;
+ op->o_req_ndn = op_ndn;
+ if ( np == NULL ) {
+ goto no_such_object;
+ }
+ entry_free( np );
} else {
- p_dn = slap_empty_bv;
+ dnParent( &entry->e_name, &p_dn );
}
- dnParent( &entry->e_name, &p_dn );
build_new_dn( &new_dn, &p_dn, &op->oq_modrdn.rs_newrdn, NULL );
dnNormalize( 0, NULL, NULL, &new_dn, &new_ndn, NULL );
ber_memfree_x( entry->e_name.bv_val, NULL );
rs->sr_err = res;
}
} else {
+no_such_object:;
/* entry was null */
rs->sr_err = LDAP_NO_SUCH_OBJECT;
}
entry_free( entry );
}
rs->sr_text = "";
- ldap_pvt_thread_mutex_unlock( &ni->li_mutex );
- ldap_pvt_thread_mutex_unlock( &entry2str_mutex );
+ ldap_pvt_thread_rdwr_wunlock( &ni->li_rdwr );
send_ldap_result( op, rs );
slap_graduate_commit_csn( op );
return 0;
assert( ndn != NULL );
assert( !BER_BVISNULL( ndn ) );
- ldap_pvt_thread_mutex_lock( &ni->li_mutex );
+ ldap_pvt_thread_rdwr_rlock( &ni->li_rdwr );
op->o_req_dn = *ndn;
op->o_req_ndn = *ndn;
*ent = (Entry *) get_entry( op, &ni->li_base_path );
op->o_req_dn = op_dn;
op->o_req_ndn = op_ndn;
- ldap_pvt_thread_mutex_unlock( &ni->li_mutex );
+ ldap_pvt_thread_rdwr_runlock( &ni->li_rdwr );
if ( *ent && oc && !is_entry_objectclass_or_sub( *ent, oc ) ) {
entry_free( *ent );
ni = ch_calloc( 1, sizeof(struct ldif_info) );
be->be_private = ni;
be->be_cf_ocs = ldifocs;
- ldap_pvt_thread_mutex_init(&ni->li_mutex);
+ ldap_pvt_thread_rdwr_init(&ni->li_rdwr);
return 0;
}
struct ldif_info *ni = be->be_private;
ch_free(ni->li_base_path.bv_val);
- ldap_pvt_thread_mutex_destroy(&ni->li_mutex);
+ ldap_pvt_thread_rdwr_destroy(&ni->li_rdwr);
free( be->be_private );
return 0;
}
/*
* Rewrite the add dn, if needed
*/
- dc.target = &mi->mi_targets[ candidate ];
+ dc.target = mi->mi_targets[ candidate ];
dc.conn = op->o_conn;
dc.rs = rs;
dc.ctx = "addDN";
mapped = a->a_desc->ad_cname;
} else {
- ldap_back_map( &mi->mi_targets[ candidate ].mt_rwmap.rwm_at,
+ ldap_back_map( &mi->mi_targets[ candidate ]->mt_rwmap.rwm_at,
&a->a_desc->ad_cname, &mapped, BACKLDAP_MAP );
if ( BER_BVISNULL( &mapped ) || BER_BVISEMPTY( &mapped ) ) {
continue;
for ( j = 0; !BER_BVISNULL( &a->a_vals[ j ] ); ) {
struct ldapmapping *mapping;
- ldap_back_mapping( &mi->mi_targets[ candidate ].mt_rwmap.rwm_oc,
+ ldap_back_mapping( &mi->mi_targets[ candidate ]->mt_rwmap.rwm_oc,
&a->a_vals[ j ], &mapping, BACKLDAP_MAP );
if ( mapping == NULL ) {
- if ( mi->mi_targets[ candidate ].mt_rwmap.rwm_oc.drop_missing ) {
+ if ( mi->mi_targets[ candidate ]->mt_rwmap.rwm_oc.drop_missing ) {
continue;
}
attrs[ i ]->mod_bvalues[ j ] = &a->a_vals[ j ];
LDAPMessage *res = NULL;
int rc;
- if ( mi->mi_targets[ candidate ].mt_timeout[ LDAP_BACK_OP_ADD ] != 0 ) {
- tv.tv_sec = mi->mi_targets[ candidate ].mt_timeout[ LDAP_BACK_OP_ADD ];
+ if ( mi->mi_targets[ candidate ]->mt_timeout[ LDAP_BACK_OP_ADD ] != 0 ) {
+ tv.tv_sec = mi->mi_targets[ candidate ]->mt_timeout[ LDAP_BACK_OP_ADD ];
tv.tv_usec = 0;
tvp = &tv;
}
typedef struct metatarget_t {
char *mt_uri;
+ ldap_pvt_thread_mutex_t mt_uri_mutex;
+
+ /* TODO: we might want to enable different strategies
+ * for different targets */
+ LDAP_REBIND_PROC *mt_rebind_f;
+ LDAP_URLLIST_PROC *mt_urllist_f;
+ void *mt_urllist_p;
+
BerVarray mt_subtree_exclude;
int mt_scope;
#define META_DEFAULT_TARGET_NONE (-1)
int mi_nretries;
- metatarget_t *mi_targets;
+ metatarget_t **mi_targets;
metacandidates_t *mi_candidates;
+ LDAP_REBIND_PROC *mi_rebind_f;
+ LDAP_URLLIST_PROC *mi_urllist_f;
+
metadncache_t mi_cache;
ldap_avl_info_t mi_conninfo;
unsigned mi_flags;
#define li_flags mi_flags
/* uses flags as defined in <back-ldap/back-ldap.h> */
-#define META_BACK_F_ONERR_STOP 0x00010000U
-#define META_BACK_F_DEFER_ROOTDN_BIND 0x00020000U
+#define META_BACK_F_ONERR_STOP (0x00010000U)
+#define META_BACK_F_DEFER_ROOTDN_BIND (0x00020000U)
#define META_BACK_ONERR_STOP(mi) ( (mi)->mi_flags & META_BACK_F_ONERR_STOP )
#define META_BACK_ONERR_CONTINUE(mi) ( !META_BACK_ONERR_CONTINUE( (mi) ) )
extern void
meta_dncache_free( void *entry );
-extern LDAP_REBIND_PROC *meta_back_rebind_f;
+extern LDAP_REBIND_PROC meta_back_default_rebind;
+extern LDAP_URLLIST_PROC meta_back_default_urllist;
LDAP_END_DECL
#include "../back-ldap/back-ldap.h"
#include "back-meta.h"
-static LDAP_REBIND_PROC meta_back_default_rebind;
-
-/*
- * a module could register a replacement for this function
- */
-LDAP_REBIND_PROC *meta_back_rebind_f = meta_back_default_rebind;
-
int
meta_back_bind( Operation *op, SlapReply *rs )
{
*/
mc->mc_authz_target = META_BOUND_NONE;
for ( i = 0; i < mi->mi_ntargets; i++ ) {
+ metatarget_t *mt = mi->mi_targets[ i ];
int lerr;
Operation op2 = *op;
int massage = 1;
}
if ( isroot ) {
- if ( BER_BVISNULL( &mi->mi_targets[ i ].mt_pseudorootdn ) )
+ if ( BER_BVISNULL( &mt->mt_pseudorootdn ) )
{
metasingleconn_t *msc = &mc->mc_conns[ i ];
continue;
}
- op2.o_req_dn = mi->mi_targets[ i ].mt_pseudorootdn;
- op2.o_req_ndn = mi->mi_targets[ i ].mt_pseudorootdn;
- op2.orb_cred = mi->mi_targets[ i ].mt_pseudorootpw;
+ op2.o_req_dn = mt->mt_pseudorootdn;
+ op2.o_req_ndn = mt->mt_pseudorootdn;
+ op2.orb_cred = mt->mt_pseudorootpw;
op2.orb_method = LDAP_AUTH_SIMPLE;
massage = 0;
meta_back_conndn_cmp );
assert( tmpmc == mc );
+ /* delete all cached connections with the current connection */
+ if ( LDAP_BACK_SINGLECONN( mi ) ) {
+ while ( ( tmpmc = avl_delete( &mi->mi_conninfo.lai_tree, (caddr_t)mc, meta_back_conn_cmp ) ) != NULL )
+ {
+ Debug( LDAP_DEBUG_TRACE,
+ "=>meta_back_bind: destroying conn %ld (refcnt=%u)\n",
+ LDAP_BACK_PCONN_ID( mc->mc_conn ), mc->mc_refcnt, 0 );
+
+ if ( mc->mc_refcnt != 0 ) {
+ /* taint it */
+ LDAP_BACK_CONN_TAINTED_SET( tmpmc );
+
+ } else {
+ /*
+ * Needs a test because the handler may be corrupted,
+ * and calling ldap_unbind on a corrupted header results
+ * in a segmentation fault
+ */
+ meta_back_conn_free( tmpmc );
+ }
+ }
+ }
+
ber_bvreplace( &mc->mc_local_ndn, &op->o_req_ndn );
+ if ( be_isroot_dn( op->o_bd, &op->o_req_ndn ) ) {
+ mc->mc_conn = LDAP_BACK_PCONN_SET( op );
+ }
lerr = avl_insert( &mi->mi_conninfo.lai_tree, (caddr_t)mc,
meta_back_conndn_cmp, meta_back_conndn_dup );
ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
int massage )
{
metainfo_t *mi = ( metainfo_t * )op->o_bd->be_private;
- metatarget_t *mt = &mi->mi_targets[ candidate ];
+ metatarget_t *mt = mi->mi_targets[ candidate ];
struct berval mdn = BER_BVNULL;
metasingleconn_t *msc = &mc->mc_conns[ candidate ];
int msgid,
if ( LDAP_BACK_SAVECRED( mi ) ) {
ber_bvreplace( &msc->msc_cred, &op->orb_cred );
- ldap_set_rebind_proc( msc->msc_ld, meta_back_rebind_f, msc );
+ ldap_set_rebind_proc( msc->msc_ld, mt->mt_rebind_f, msc );
}
if ( mi->mi_cache.ttl != META_DNCACHE_DISABLED
int dolock )
{
metainfo_t *mi = ( metainfo_t * )op->o_bd->be_private;
- metatarget_t *mt = &mi->mi_targets[ candidate ];
+ metatarget_t *mt = mi->mi_targets[ candidate ];
metaconn_t *mc = *mcp;
metasingleconn_t *msc = &mc->mc_conns[ candidate ];
int rc;
* meta_back_single_dobind() calls meta_back_single_bind()
* if required.
*/
- if ( be_isroot( op ) && !BER_BVISNULL( &mi->mi_targets[ candidate ].mt_pseudorootdn ) )
+ if ( be_isroot( op ) && !BER_BVISNULL( &mt->mt_pseudorootdn ) )
{
Operation op2 = *op;
op2.o_tag = LDAP_REQ_BIND;
- op2.o_req_dn = mi->mi_targets[ candidate ].mt_pseudorootdn;
- op2.o_req_ndn = mi->mi_targets[ candidate ].mt_pseudorootdn;
- op2.orb_cred = mi->mi_targets[ candidate ].mt_pseudorootpw;
+ op2.o_req_dn = mt->mt_pseudorootdn;
+ op2.o_req_ndn = mt->mt_pseudorootdn;
+ op2.orb_cred = mt->mt_pseudorootpw;
op2.orb_method = LDAP_AUTH_SIMPLE;
rc = meta_back_single_bind( &op2, rs, *mcp, candidate, 0 );
mt, mc, candidate,
LDAP_BACK_CONN_ISPRIV( mc ),
LDAP_BACK_DONTSEND );
- LDAP_BACK_CONN_BINDING_SET( msc );
+ if ( rc == LDAP_SUCCESS ) {
+ LDAP_BACK_CONN_BINDING_SET( msc );
+ }
} else {
/* can't do anything about it */
}
for ( i = 0; i < mi->mi_ntargets; i++ ) {
- metatarget_t *mt = &mi->mi_targets[ i ];
+ metatarget_t *mt = mi->mi_targets[ i ];
metasingleconn_t *msc = &mc->mc_conns[ i ];
int rc, do_retry = 1;
if ( meta_back_retry( op, rs, &mc, i, sendok ) ) {
goto retry;
}
- ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex );
- LDAP_BACK_CONN_BINDING_CLEAR( msc );
- ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
+
+ if ( mc != NULL ) {
+ ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex );
+ LDAP_BACK_CONN_BINDING_CLEAR( msc );
+ ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
+ }
return 0;
}
* This is a callback used for chasing referrals using the same
* credentials as the original user on this session.
*/
-static int
+int
meta_back_default_rebind(
LDAP *ld,
LDAP_CONST char *url,
NULL, NULL, NULL );
}
+/*
+ * meta_back_default_urllist
+ *
+ * This is a callback used for mucking with the urllist
+ */
+int
+meta_back_default_urllist(
+ LDAP *ld,
+ LDAPURLDesc **urllist,
+ LDAPURLDesc **url,
+ void *params )
+{
+ metatarget_t *mt = (metatarget_t *)params;
+ LDAPURLDesc **urltail;
+
+ if ( urllist == url ) {
+ return LDAP_SUCCESS;
+ }
+
+ for ( urltail = &(*url)->lud_next; *urltail; urltail = &(*urltail)->lud_next )
+ /* count */ ;
+
+ *urltail = *urllist;
+ *urllist = *url;
+ *url = NULL;
+
+ ldap_pvt_thread_mutex_lock( &mt->mt_uri_mutex );
+ if ( mt->mt_uri ) {
+ ch_free( mt->mt_uri );
+ }
+
+ ldap_get_option( ld, LDAP_OPT_URI, (void *)&mt->mt_uri );
+ ldap_pvt_thread_mutex_unlock( &mt->mt_uri_mutex );
+
+ return LDAP_SUCCESS;
+}
+
/*
* FIXME: error return must be handled in a cleaner way ...
*/
*save_rmatch = NULL;
void *rmatch_ctx = NULL;
+ assert( mc != NULL );
+
if ( candidate != META_TARGET_NONE ) {
metasingleconn_t *msc = &mc->mc_conns[ candidate ];
{
int i, candidate = META_TARGET_NONE;
- for ( i = 0; i < mi->mi_ntargets; ++i ) {
- if ( meta_back_is_candidate( &mi->mi_targets[ i ].mt_nsuffix,
- mi->mi_targets[ i ].mt_scope,
- mi->mi_targets[ i ].mt_subtree_exclude,
+ for ( i = 0; i < mi->mi_ntargets; i++ ) {
+ metatarget_t *mt = mi->mi_targets[ i ];
+
+ if ( meta_back_is_candidate( &mt->mt_nsuffix,
+ mt->mt_scope,
+ mt->mt_subtree_exclude,
ndn, LDAP_SCOPE_BASE ) )
{
if ( candidate == META_TARGET_NONE ) {
/*
* Rewrite the compare dn, if needed
*/
- dc.target = &mi->mi_targets[ i ];
+ dc.target = mi->mi_targets[ i ];
switch ( ldap_back_dn_massage( &dc, &op->o_req_dn, &mdn ) ) {
case LDAP_UNWILLING_TO_PERFORM:
* if attr is objectClass, try to remap the value
*/
if ( op->orc_ava->aa_desc == slap_schema.si_ad_objectClass ) {
- ldap_back_map( &mi->mi_targets[ i ].mt_rwmap.rwm_oc,
+ ldap_back_map( &mi->mi_targets[ i ]->mt_rwmap.rwm_oc,
&op->orc_ava->aa_value,
&mapped_value, BACKLDAP_MAP );
* else try to remap the attribute
*/
} else {
- ldap_back_map( &mi->mi_targets[ i ].mt_rwmap.rwm_at,
+ ldap_back_map( &mi->mi_targets[ i ]->mt_rwmap.rwm_at,
&op->orc_ava->aa_desc->ad_cname,
&mapped_attr, BACKLDAP_MAP );
if ( BER_BVISNULL( &mapped_attr ) || mapped_attr.bv_val[0] == '\0' ) {
static int
meta_back_new_target(
- metatarget_t *mt )
+ metatarget_t **mtp )
{
struct ldapmapping *mapping;
char *rargv[ 3 ];
+ metatarget_t *mt;
- memset( mt, 0, sizeof( metatarget_t ) );
+ *mtp = NULL;
+
+ mt = ch_calloc( sizeof( metatarget_t ), 1 );
mt->mt_rwmap.rwm_rw = rewrite_info_init( REWRITE_MODE_USE_DEFAULT );
if ( mt->mt_rwmap.rwm_rw == NULL ) {
- return -1;
+ ch_free( mt );
+ return -1;
}
ldap_back_map_init( &mt->mt_rwmap.rwm_at, &mapping );
+ ldap_pvt_thread_mutex_init( &mt->mt_uri_mutex );
+
+ *mtp = mt;
+
return 0;
}
struct berval dn;
int rc;
int c;
+
+ metatarget_t *mt;
switch ( argc ) {
case 1:
++mi->mi_ntargets;
- mi->mi_targets = ( metatarget_t * )ch_realloc( mi->mi_targets,
- sizeof( metatarget_t ) * mi->mi_ntargets );
+ mi->mi_targets = ( metatarget_t ** )ch_realloc( mi->mi_targets,
+ sizeof( metatarget_t * ) * mi->mi_ntargets );
if ( mi->mi_targets == NULL ) {
Debug( LDAP_DEBUG_ANY,
"%s: line %d: out of memory while storing server name"
return 1;
}
- mi->mi_targets[ i ].mt_nretries = mi->mi_nretries;
- mi->mi_targets[ i ].mt_flags = mi->mi_flags;
- mi->mi_targets[ i ].mt_version = mi->mi_version;
- mi->mi_targets[ i ].mt_network_timeout = mi->mi_network_timeout;
- mi->mi_targets[ i ].mt_bind_timeout = mi->mi_bind_timeout;
+ mt = mi->mi_targets[ i ];
+
+ mt->mt_rebind_f = mi->mi_rebind_f;
+ mt->mt_urllist_f = mi->mi_urllist_f;
+ mt->mt_urllist_p = mt;
+
+ mt->mt_nretries = mi->mi_nretries;
+ mt->mt_flags = mi->mi_flags;
+ mt->mt_version = mi->mi_version;
+ mt->mt_network_timeout = mi->mi_network_timeout;
+ mt->mt_bind_timeout = mi->mi_bind_timeout;
for ( c = 0; c < LDAP_BACK_OP_LAST; c++ ) {
- mi->mi_targets[ i ].mt_timeout[ c ] = mi->mi_timeout[ c ];
+ mt->mt_timeout[ c ] = mi->mi_timeout[ c ];
}
/*
* uri MUST be legal!
*/
- if ( ldap_url_parselist_ext( &ludp, argv[ 1 ], "\t" ) != LDAP_SUCCESS ) {
+ if ( ldap_url_parselist_ext( &ludp, argv[ 1 ], "\t",
+ LDAP_PVT_URL_PARSE_NONE ) != LDAP_SUCCESS )
+ {
Debug( LDAP_DEBUG_ANY,
"%s: line %d: unable to parse URI"
" in \"uri <protocol>://<server>[:port]/<naming context>\" line\n",
* copies and stores uri and suffix
*/
ber_str2bv( ludp->lud_dn, 0, 0, &dn );
- rc = dnPrettyNormal( NULL, &dn, &mi->mi_targets[ i ].mt_psuffix,
- &mi->mi_targets[ i ].mt_nsuffix, NULL );
+ rc = dnPrettyNormal( NULL, &dn, &mt->mt_psuffix,
+ &mt->mt_nsuffix, NULL );
if( rc != LDAP_SUCCESS ) {
Debug( LDAP_DEBUG_ANY, "%s: line %d: "
"target \"%s\" DN is invalid\n",
switch ( ludp->lud_scope ) {
case LDAP_SCOPE_DEFAULT:
- mi->mi_targets[ i ].mt_scope = LDAP_SCOPE_SUBTREE;
+ mt->mt_scope = LDAP_SCOPE_SUBTREE;
break;
case LDAP_SCOPE_SUBTREE:
case LDAP_SCOPE_SUBORDINATE:
- mi->mi_targets[ i ].mt_scope = ludp->lud_scope;
+ mt->mt_scope = ludp->lud_scope;
break;
default:
}
}
- mi->mi_targets[ i ].mt_uri = ldap_url_list2urls( ludp );
+ mt->mt_uri = ldap_url_list2urls( ludp );
ldap_free_urllist( ludp );
- if ( mi->mi_targets[ i ].mt_uri == NULL) {
+ if ( mt->mt_uri == NULL) {
Debug( LDAP_DEBUG_ANY, "%s: line %d: no memory?\n",
fname, lineno, 0 );
return( 1 );
* uri MUST be a branch of suffix!
*/
#if 0 /* too strict a constraint */
- if ( select_backend( &mi->mi_targets[ i ].suffix, 0, 0 ) != be ) {
+ 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",
/*
* uri MUST be a branch of a suffix!
*/
- if ( select_backend( &mi->mi_targets[ i ].mt_nsuffix, 0, 0 ) == NULL ) {
+ if ( select_backend( &mt->mt_nsuffix, 0, 0 ) == NULL ) {
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",
return( 1 );
}
- if ( !dnIsSuffix( &ndn, &mi->mi_targets[ i ].mt_nsuffix ) ) {
+ if ( !dnIsSuffix( &ndn, &mi->mi_targets[ i ]->mt_nsuffix ) ) {
Debug( LDAP_DEBUG_ANY, "%s: line %d: "
"subtree-exclude DN=\"%s\" "
"must be subtree of target\n",
return( 1 );
}
- if ( mi->mi_targets[ i ].mt_subtree_exclude != NULL ) {
+ if ( mi->mi_targets[ i ]->mt_subtree_exclude != NULL ) {
int j;
- for ( j = 0; !BER_BVISNULL( &mi->mi_targets[ i ].mt_subtree_exclude[ j ] ); j++ )
+ for ( j = 0; !BER_BVISNULL( &mi->mi_targets[ i ]->mt_subtree_exclude[ j ] ); j++ )
{
- if ( dnIsSuffix( &mi->mi_targets[ i ].mt_subtree_exclude[ j ], &ndn ) ) {
+ if ( dnIsSuffix( &mi->mi_targets[ i ]->mt_subtree_exclude[ j ], &ndn ) ) {
Debug( LDAP_DEBUG_ANY, "%s: line %d: "
"subtree-exclude DN=\"%s\" "
"is suffix of another subtree-exclude\n",
ber_memfree( ndn.bv_val );
return( 1 );
- } else if ( dnIsSuffix( &ndn, &mi->mi_targets[ i ].mt_subtree_exclude[ j ] ) ) {
+ } else if ( dnIsSuffix( &ndn, &mi->mi_targets[ i ]->mt_subtree_exclude[ j ] ) ) {
Debug( LDAP_DEBUG_ANY, "%s: line %d: "
"another subtree-exclude is suffix of "
"subtree-exclude DN=\"%s\"\n",
}
}
- ber_bvarray_add( &mi->mi_targets[ i ].mt_subtree_exclude, &ndn );
+ ber_bvarray_add( &mi->mi_targets[ i ]->mt_subtree_exclude, &ndn );
/* default target directive */
} else if ( strcasecmp( argv[ 0 ], "default-target" ) == 0 ) {
} else if ( strcasecmp( argv[ 0 ], "network-timeout" ) == 0 ) {
unsigned long t;
time_t *tp = mi->mi_ntargets ?
- &mi->mi_targets[ mi->mi_ntargets - 1 ].mt_network_timeout
+ &mi->mi_targets[ mi->mi_ntargets - 1 ]->mt_network_timeout
: &mi->mi_network_timeout;
if ( argc != 2 ) {
} else if ( strcasecmp( argv[ 0 ], "bind-timeout" ) == 0 ) {
unsigned long t;
struct timeval *tp = mi->mi_ntargets ?
- &mi->mi_targets[ mi->mi_ntargets - 1 ].mt_bind_timeout
+ &mi->mi_targets[ mi->mi_ntargets - 1 ]->mt_bind_timeout
: &mi->mi_bind_timeout;
switch ( argc ) {
}
ber_str2bv( argv[ 1 ], 0, 0, &dn );
- if ( dnNormalize( 0, NULL, NULL, &dn, &mi->mi_targets[ i ].mt_binddn,
+ if ( dnNormalize( 0, NULL, NULL, &dn, &mi->mi_targets[ i ]->mt_binddn,
NULL ) != LDAP_SUCCESS )
{
Debug( LDAP_DEBUG_ANY, "%s: line %d: "
/* FIXME: some day we'll need to throw an error */
}
- ber_str2bv( argv[ 1 ], 0L, 1, &mi->mi_targets[ i ].mt_bindpw );
+ ber_str2bv( argv[ 1 ], 0L, 1, &mi->mi_targets[ i ]->mt_bindpw );
/* save bind creds for referral rebinds? */
} else if ( strcasecmp( argv[ 0 ], "rebind-as-user" ) == 0 ) {
} else if ( strcasecmp( argv[ 0 ], "chase-referrals" ) == 0 ) {
unsigned *flagsp = mi->mi_ntargets ?
- &mi->mi_targets[ mi->mi_ntargets - 1 ].mt_flags
+ &mi->mi_targets[ mi->mi_ntargets - 1 ]->mt_flags
: &mi->mi_flags;
if ( argc != 2 ) {
} else if ( strcasecmp( argv[ 0 ], "tls" ) == 0 ) {
unsigned *flagsp = mi->mi_ntargets ?
- &mi->mi_targets[ mi->mi_ntargets - 1 ].mt_flags
+ &mi->mi_targets[ mi->mi_ntargets - 1 ]->mt_flags
: &mi->mi_flags;
if ( argc != 2 ) {
} else if ( strcasecmp( argv[ 0 ], "t-f-support" ) == 0 ) {
unsigned *flagsp = mi->mi_ntargets ?
- &mi->mi_targets[ mi->mi_ntargets - 1 ].mt_flags
+ &mi->mi_targets[ mi->mi_ntargets - 1 ]->mt_flags
: &mi->mi_flags;
if ( argc != 2 ) {
return 1;
}
+ /* single-conn? */
+ } else if ( strcasecmp( argv[ 0 ], "single-conn" ) == 0 ) {
+ if ( argc != 2 ) {
+ Debug( LDAP_DEBUG_ANY,
+ "%s: line %d: \"single-conn {FALSE|true}\" takes 1 argument\n",
+ fname, lineno, 0 );
+ return( 1 );
+ }
+
+ if ( mi->mi_ntargets > 0 ) {
+ Debug( LDAP_DEBUG_ANY,
+ "%s: line %d: \"single-conn\" must appear before target definitions\n",
+ fname, lineno, 0 );
+ return( 1 );
+ }
+
+ switch ( check_true_false( argv[ 1 ] ) ) {
+ case 0:
+ mi->mi_flags &= ~LDAP_BACK_F_SINGLECONN;
+ break;
+
+ case 1:
+ mi->mi_flags |= LDAP_BACK_F_SINGLECONN;
+ break;
+
+ default:
+ Debug( LDAP_DEBUG_ANY,
+ "%s: line %d: \"single-conn {FALSE|true}\": invalid arg \"%s\".\n",
+ fname, lineno, argv[ 1 ] );
+ return 1;
+ }
+
} else if ( strcasecmp( argv[ 0 ], "timeout" ) == 0 ) {
char *sep;
time_t *tv = mi->mi_ntargets ?
- mi->mi_targets[ mi->mi_ntargets - 1 ].mt_timeout
+ mi->mi_targets[ mi->mi_ntargets - 1 ]->mt_timeout
: mi->mi_timeout;
int c;
dn.bv_val = argv[ 1 ];
dn.bv_len = strlen( argv[ 1 ] );
if ( dnNormalize( 0, NULL, NULL, &dn,
- &mi->mi_targets[ i ].mt_pseudorootdn, NULL ) != LDAP_SUCCESS )
+ &mi->mi_targets[ i ]->mt_pseudorootdn, NULL ) != LDAP_SUCCESS )
{
Debug( LDAP_DEBUG_ANY, "%s: line %d: "
"pseudoroot DN '%s' is invalid\n",
fname, lineno, 0 );
return 1;
}
- ber_str2bv( argv[ 1 ], 0L, 1, &mi->mi_targets[ i ].mt_pseudorootpw );
+ ber_str2bv( argv[ 1 ], 0L, 1, &mi->mi_targets[ i ]->mt_pseudorootpw );
/* dn massaging */
} else if ( strcasecmp( argv[ 0 ], "suffixmassage" ) == 0 ) {
* FIXME: no extra rewrite capabilities should be added
* to the database
*/
- rc = suffix_massage_config( mi->mi_targets[ i ].mt_rwmap.rwm_rw,
+ rc = suffix_massage_config( mi->mi_targets[ i ]->mt_rwmap.rwm_rw,
&pvnc, &nvnc, &prnc, &nrnc );
free( pvnc.bv_val );
return 1;
}
- return rewrite_parse( mi->mi_targets[ i ].mt_rwmap.rwm_rw,
+ return rewrite_parse( mi->mi_targets[ i ]->mt_rwmap.rwm_rw,
fname, lineno, argc, argv );
/* objectclass/attribute mapping */
return 1;
}
- return ldap_back_map_config( &mi->mi_targets[ i ].mt_rwmap.rwm_oc,
- &mi->mi_targets[ i ].mt_rwmap.rwm_at,
+ return ldap_back_map_config( &mi->mi_targets[ i ]->mt_rwmap.rwm_oc,
+ &mi->mi_targets[ i ]->mt_rwmap.rwm_at,
fname, lineno, argc, argv );
} else if ( strcasecmp( argv[ 0 ], "nretries" ) == 0 ) {
mi->mi_nretries = nretries;
} else {
- mi->mi_targets[ i ].mt_nretries = nretries;
+ mi->mi_targets[ i ]->mt_nretries = nretries;
}
} else if ( strcasecmp( argv[ 0 ], "protocol-version" ) == 0 ) {
int *version = mi->mi_ntargets ?
- &mi->mi_targets[ mi->mi_ntargets - 1 ].mt_version
+ &mi->mi_targets[ mi->mi_ntargets - 1 ]->mt_version
: &mi->mi_version;
if ( argc != 2 ) {
return 1;
}
- switch ( *version ) {
- case 0:
- case LDAP_VERSION2:
- case LDAP_VERSION3:
- break;
-
- default:
+ if ( *version != 0 && ( *version < LDAP_VERSION_MIN || *version > LDAP_VERSION_MAX ) ) {
Debug( LDAP_DEBUG_ANY,
"%s: line %d: unsupported version \"%s\" in \"protocol-version <version>\"\n",
fname, lineno, argv[ 1 ] );
/*
* Set PRINT_CONNTREE larger than 0 to dump the connection tree (debug only)
*/
+#ifndef PRINT_CONNTREE
#define PRINT_CONNTREE 0
+#endif /* !PRINT_CONNTREE */
/*
* meta_back_conndn_cmp
ravl_print( Avlnode *root, int depth )
{
int i;
- metaconn_t *mc = (metaconn_t *)root->avl_data;
+ metaconn_t *mc;
if ( root == 0 ) {
return;
ravl_print( root->avl_right, depth + 1 );
for ( i = 0; i < depth; i++ ) {
- printf( " " );
+ fprintf( stderr, "-" );
}
- printf( "c(%d%s%s) %d\n",
- LDAP_BACK_PCONN_ID( mc->mc_conn ),
- BER_BVISNULL( &mc->mc_local_ndn ) ? "" : ": ",
- BER_BVISNULL( &mc->mc_local_ndn ) ? "" : mc->mc_local_ndn.bv_val,
- root->avl_bf );
+ mc = (metaconn_t *)root->avl_data;
+ fprintf( stderr, "mc=%p local=\"%s\" conn=%p %s refcnt=%d\n",
+ (void *)mc,
+ mc->mc_local_ndn.bv_val ? mc->mc_local_ndn.bv_val : "",
+ (void *)mc->mc_conn,
+ avl_bf2str( root->avl_bf ), mc->mc_refcnt );
ravl_print( root->avl_left, depth + 1 );
}
static void
-myprint( Avlnode *root )
+myprint( Avlnode *root, char *msg )
{
- printf( "********\n" );
+ fprintf( stderr, "========> %s\n", msg );
if ( root == 0 ) {
- printf( "\tNULL\n" );
+ fprintf( stderr, "\tNULL\n" );
+
} else {
ravl_print( root, 0 );
}
- printf( "********\n" );
+ fprintf( stderr, "<======== %s\n", msg );
}
#endif /* PRINT_CONNTREE */
/*
int version;
dncookie dc;
int isauthz = ( candidate == mc->mc_authz_target );
+#ifdef HAVE_TLS
+ int is_ldaps = 0;
+#endif /* HAVE_TLS */
/*
* Already init'ed
/*
* Attempts to initialize the connection to the target ds
*/
+ ldap_pvt_thread_mutex_lock( &mt->mt_uri_mutex );
rs->sr_err = ldap_initialize( &msc->msc_ld, mt->mt_uri );
+#ifdef HAVE_TLS
+ is_ldaps = ldap_is_ldaps_url( mt->mt_uri );
+#endif /* HAVE_TLS */
+ ldap_pvt_thread_mutex_unlock( &mt->mt_uri_mutex );
if ( rs->sr_err != LDAP_SUCCESS ) {
goto error_return;
}
version = LDAP_VERSION3;
}
ldap_set_option( msc->msc_ld, LDAP_OPT_PROTOCOL_VERSION, &version );
+ ldap_set_urllist_proc( msc->msc_ld, mt->mt_urllist_f, mt->mt_urllist_p );
/* automatically chase referrals ("chase-referrals [{yes|no}]" statement) */
ldap_set_option( msc->msc_ld, LDAP_OPT_REFERRALS,
#ifdef HAVE_TLS
/* start TLS ("tls [try-]{start|propagate}" statement) */
if ( ( LDAP_BACK_USE_TLS( mi ) || ( op->o_conn->c_is_tls && LDAP_BACK_PROPAGATE_TLS( mi ) ) )
- && !ldap_is_ldaps_url( mt->mt_uri ) )
+ && !is_ldaps )
{
#ifdef SLAP_STARTTLS_ASYNCHRONOUS
/*
if ( rs->sr_err == LDAP_SERVER_DOWN
|| ( rs->sr_err != LDAP_SUCCESS && LDAP_BACK_TLS_CRITICAL( mi ) ) )
{
- ldap_unbind_ext_s( msc->msc_ld, NULL, NULL );
+ ldap_unbind_ext( msc->msc_ld, NULL, NULL );
+ msc->msc_ld = NULL;
goto error_return;
}
}
if ( ldap_back_dn_massage( &dc, &op->o_conn->c_dn,
&msc->msc_bound_ndn ) )
{
- ldap_unbind_ext_s( msc->msc_ld, NULL, NULL );
+ ldap_unbind_ext( msc->msc_ld, NULL, NULL );
+ msc->msc_ld = NULL;
goto error_return;
}
ldap_back_send_t sendok )
{
metainfo_t *mi = ( metainfo_t * )op->o_bd->be_private;
- metatarget_t *mt = &mi->mi_targets[ candidate ];
+ metatarget_t *mt = mi->mi_targets[ candidate ];
metaconn_t *mc = *mcp;
metasingleconn_t *msc = &mc->mc_conns[ candidate ];
int rc = LDAP_UNAVAILABLE,
assert( mc->mc_refcnt > 0 );
if ( mc->mc_refcnt == 1 ) {
- char buf[ SLAP_TEXT_BUFLEN ];
+ if ( LogTest( LDAP_DEBUG_ANY ) ) {
+ char buf[ SLAP_TEXT_BUFLEN ];
- snprintf( buf, sizeof( buf ),
- "retrying URI=\"%s\" DN=\"%s\"",
- mt->mt_uri,
- BER_BVISNULL( &msc->msc_bound_ndn ) ?
- "" : msc->msc_bound_ndn.bv_val );
- Debug( LDAP_DEBUG_ANY,
- "%s meta_back_retry[%d]: %s.\n",
- op->o_log_prefix, candidate, buf );
+ ldap_pvt_thread_mutex_lock( &mt->mt_uri_mutex );
+ snprintf( buf, sizeof( buf ),
+ "retrying URI=\"%s\" DN=\"%s\"",
+ mt->mt_uri,
+ BER_BVISNULL( &msc->msc_bound_ndn ) ?
+ "" : msc->msc_bound_ndn.bv_val );
+ ldap_pvt_thread_mutex_unlock( &mt->mt_uri_mutex );
+
+ Debug( LDAP_DEBUG_ANY,
+ "%s meta_back_retry[%d]: %s.\n",
+ op->o_log_prefix, candidate, buf );
+ }
meta_clear_one_candidate( msc );
LDAP_BACK_CONN_ISBOUND_CLEAR( msc );
if ( rc == LDAP_SUCCESS ) {
rc = meta_back_single_dobind( op, rs, mcp, candidate,
sendok, mt->mt_nretries, 0 );
+
+ Debug( LDAP_DEBUG_ANY,
+ "%s meta_back_retry[%d]: "
+ "meta_back_single_dobind=%d\n",
+ op->o_log_prefix, candidate, rc );
+ if ( rc == LDAP_SUCCESS ) {
+ if ( be_isroot( op ) ) {
+ LDAP_BACK_CONN_ISBOUND_SET( msc );
+ } else {
+ LDAP_BACK_CONN_ISANON_SET( msc );
+ }
+ }
}
}
if ( rc != LDAP_SUCCESS ) {
+ SlapReply *candidates = meta_back_candidates_get( op );
+
+ candidates[ candidate ].sr_err = rc;
+
if ( *mcp != NULL ) {
if ( binding ) {
LDAP_BACK_CONN_BINDING_CLEAR( msc );
}
LDAP_BACK_CONN_TAINTED_SET( mc );
- meta_back_release_conn_lock( op, mc, 0 );
- *mcp = NULL;
+ /* only release if mandatory; otherwise
+ * let the caller do what's best before
+ * releasing */
+ if ( META_BACK_ONERR_STOP( mi ) ) {
+ meta_back_release_conn_lock( op, mc, 0 );
+ *mcp = NULL;
+ }
}
if ( sendok ) {
- rs->sr_err = LDAP_UNAVAILABLE;
+ rs->sr_err = rc;
rs->sr_text = NULL;
send_ldap_result( op, rs );
}
* and a default target is defined, and it is
* a candidate, try using it (FIXME: YMMV) */
if ( mi->mi_defaulttarget != META_DEFAULT_TARGET_NONE
- && meta_back_is_candidate( &mi->mi_targets[ mi->mi_defaulttarget ].mt_nsuffix,
- mi->mi_targets[ mi->mi_defaulttarget ].mt_scope,
- mi->mi_targets[ mi->mi_defaulttarget ].mt_subtree_exclude,
+ && meta_back_is_candidate( &mi->mi_targets[ mi->mi_defaulttarget ]->mt_nsuffix,
+ mi->mi_targets[ mi->mi_defaulttarget ]->mt_scope,
+ mi->mi_targets[ mi->mi_defaulttarget ]->mt_subtree_exclude,
ndn, op->o_tag == LDAP_REQ_SEARCH ? op->ors_scope : LDAP_SCOPE_BASE ) )
{
candidate = mi->mi_defaulttarget;
} else if ( mc->mc_ntargets < mi->mi_ntargets ) {
/* NOTE: in the future, may want to allow back-config
* to add/remove targets from back-meta... */
- mc->mc_ntargets = mi->mi_ntargets;
mc->mc_candidates = ch_realloc( mc->mc_candidates,
- sizeof( SlapReply ) * mc->mc_ntargets );
+ sizeof( SlapReply ) * mi->mi_ntargets );
+ memset( &mc->mc_candidates[ mc->mc_ntargets ], 0,
+ sizeof( SlapReply ) * ( mi->mi_ntargets - mc->mc_ntargets ) );
+ mc->mc_ntargets = mi->mi_ntargets;
}
return mc->mc_candidates;
}
for ( i = 0; i < mi->mi_ntargets; i++ ) {
- metatarget_t *mt = &mi->mi_targets[ i ];
+ metatarget_t *mt = mi->mi_targets[ i ];
/*
* The target is activated; if needed, it is
*/
( void )meta_clear_unused_candidates( op, i );
- mt = &mi->mi_targets[ i ];
+ mt = mi->mi_targets[ i ];
msc = &mc->mc_conns[ i ];
/*
}
for ( i = 0; i < mi->mi_ntargets; i++ ) {
- metatarget_t *mt = &mi->mi_targets[ i ];
+ metatarget_t *mt = mi->mi_targets[ i ];
metasingleconn_t *msc = &mc->mc_conns[ i ];
if ( i == cached
meta_back_conndn_cmp, meta_back_conndn_dup );
#if PRINT_CONNTREE > 0
- myprint( mi->mi_conninfo.lai_tree );
+ myprint( mi->mi_conninfo.lai_tree, "meta_back_getconn" );
#endif /* PRINT_CONNTREE */
ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
/*
* Rewrite the compare dn, if needed
*/
- dc.target = &mi->mi_targets[ candidate ];
+ dc.target = mi->mi_targets[ candidate ];
dc.conn = op->o_conn;
dc.rs = rs;
dc.ctx = "deleteDN";
LDAPMessage *res = NULL;
int rc;
- if ( mi->mi_targets[ candidate ].mt_timeout[ LDAP_BACK_OP_DELETE ] != 0 ) {
- tv.tv_sec = mi->mi_targets[ candidate ].mt_timeout[ LDAP_BACK_OP_DELETE ];
+ if ( mi->mi_targets[ candidate ]->mt_timeout[ LDAP_BACK_OP_DELETE ] != 0 ) {
+ tv.tv_sec = mi->mi_targets[ candidate ]->mt_timeout[ LDAP_BACK_OP_DELETE ];
tv.tv_usec = 0;
tvp = &tv;
}
mi->mi_bind_timeout.tv_sec = 0;
mi->mi_bind_timeout.tv_usec = META_BIND_TIMEOUT;
+ mi->mi_rebind_f = meta_back_default_rebind;
+ mi->mi_urllist_f = meta_back_default_urllist;
+
ldap_pvt_thread_mutex_init( &mi->mi_conninfo.lai_mutex );
ldap_pvt_thread_mutex_init( &mi->mi_cache.mutex );
int i, rc;
for ( i = 0; i < mi->mi_ntargets; i++ ) {
- if ( mi->mi_targets[ i ].mt_flags & LDAP_BACK_F_SUPPORT_T_F_DISCOVER )
+ metatarget_t *mt = mi->mi_targets[ i ];
+
+ if ( mt->mt_flags & LDAP_BACK_F_SUPPORT_T_F_DISCOVER )
{
- mi->mi_targets[ i ].mt_flags &= ~LDAP_BACK_F_SUPPORT_T_F_DISCOVER;
- rc = slap_discover_feature( mi->mi_targets[ i ].mt_uri,
- mi->mi_targets[ i ].mt_version,
+ mt->mt_flags &= ~LDAP_BACK_F_SUPPORT_T_F_DISCOVER;
+ rc = slap_discover_feature( mt->mt_uri,
+ mt->mt_version,
slap_schema.si_ad_supportedFeatures->ad_cname.bv_val,
LDAP_FEATURE_ABSOLUTE_FILTERS );
if ( rc == LDAP_COMPARE_TRUE ) {
- mi->mi_targets[ i ].mt_flags |= LDAP_BACK_F_SUPPORT_T_F;
+ mt->mt_flags |= LDAP_BACK_F_SUPPORT_T_F;
}
}
}
{
if ( mt->mt_uri ) {
free( mt->mt_uri );
+ ldap_pvt_thread_mutex_destroy( &mt->mt_uri_mutex );
}
if ( mt->mt_subtree_exclude ) {
ber_bvarray_free( mt->mt_subtree_exclude );
avl_free( mt->mt_rwmap.rwm_oc.map, mapping_free );
avl_free( mt->mt_rwmap.rwm_at.remap, mapping_dst_free );
avl_free( mt->mt_rwmap.rwm_at.map, mapping_free );
+
+ free( mt );
}
int
*/
if ( mi->mi_targets != NULL ) {
for ( i = 0; i < mi->mi_ntargets; i++ ) {
- target_free( &mi->mi_targets[ i ] );
+ target_free( mi->mi_targets[ i ] );
}
free( mi->mi_targets );
/*
* Rewrite the modify dn, if needed
*/
- dc.target = &mi->mi_targets[ candidate ];
+ dc.target = mi->mi_targets[ candidate ];
dc.conn = op->o_conn;
dc.rs = rs;
dc.ctx = "modifyDN";
mapped = ml->sml_desc->ad_cname;
} else {
- ldap_back_map( &mi->mi_targets[ candidate ].mt_rwmap.rwm_at,
+ ldap_back_map( &mi->mi_targets[ candidate ]->mt_rwmap.rwm_at,
&ml->sml_desc->ad_cname, &mapped,
BACKLDAP_MAP );
if ( BER_BVISNULL( &mapped ) || BER_BVISEMPTY( &mapped ) ) {
for ( j = 0; !BER_BVISNULL( &ml->sml_values[ j ] ); ) {
struct ldapmapping *mapping;
- ldap_back_mapping( &mi->mi_targets[ candidate ].mt_rwmap.rwm_oc,
+ ldap_back_mapping( &mi->mi_targets[ candidate ]->mt_rwmap.rwm_oc,
&ml->sml_values[ j ], &mapping, BACKLDAP_MAP );
if ( mapping == NULL ) {
- if ( mi->mi_targets[ candidate ].mt_rwmap.rwm_oc.drop_missing ) {
+ if ( mi->mi_targets[ candidate ]->mt_rwmap.rwm_oc.drop_missing ) {
continue;
}
mods[ i ].mod_bvalues[ j ] = &ml->sml_values[ j ];
struct timeval tv, *tvp = NULL;
LDAPMessage *res = NULL;
- if ( mi->mi_targets[ candidate ].mt_timeout[ LDAP_BACK_OP_MODIFY ] != 0 ) {
- tv.tv_sec = mi->mi_targets[ candidate ].mt_timeout[ LDAP_BACK_OP_MODIFY ];
+ if ( mi->mi_targets[ candidate ]->mt_timeout[ LDAP_BACK_OP_MODIFY ] != 0 ) {
+ tv.tv_sec = mi->mi_targets[ candidate ]->mt_timeout[ LDAP_BACK_OP_MODIFY ];
tv.tv_usec = 0;
tvp = &tv;
}
*/
/* needs LDAPv3 */
- switch ( mi->mi_targets[ candidate ].mt_version ) {
+ switch ( mi->mi_targets[ candidate ]->mt_version ) {
case LDAP_VERSION3:
break;
/*
* Rewrite the new superior, if defined and required
*/
- dc.target = &mi->mi_targets[ candidate ];
+ dc.target = mi->mi_targets[ candidate ];
dc.ctx = "newSuperiorDN";
if ( ldap_back_dn_massage( &dc, op->orr_newSup, &mnewSuperior ) ) {
rs->sr_err = LDAP_OTHER;
/*
* Rewrite the modrdn dn, if required
*/
- dc.target = &mi->mi_targets[ candidate ];
+ dc.target = mi->mi_targets[ candidate ];
dc.ctx = "modrDN";
if ( ldap_back_dn_massage( &dc, &op->o_req_dn, &mdn ) ) {
rs->sr_err = LDAP_OTHER;
LDAPMessage *res = NULL;
int rc;
- if ( mi->mi_targets[ candidate ].mt_timeout[ LDAP_BACK_OP_MODRDN ] != 0 ) {
- tv.tv_sec = mi->mi_targets[ candidate ].mt_timeout[ LDAP_BACK_OP_MODRDN ];
+ if ( mi->mi_targets[ candidate ]->mt_timeout[ LDAP_BACK_OP_MODRDN ] != 0 ) {
+ tv.tv_sec = mi->mi_targets[ candidate ]->mt_timeout[ LDAP_BACK_OP_MODRDN ];
tv.tv_usec = 0;
tvp = &tv;
}
#include "ldap_log.h"
#include "../../../libraries/libldap/ldap-int.h"
+/* IGNORE means that target does not (no longer) participate
+ * in the search;
+ * NOTREADY means the search on that target has not been initialized yet
+ */
+#define META_MSGID_IGNORE (-1)
+#define META_MSGID_NEED_BIND (-2)
+
static int
meta_send_entry(
Operation *op,
typedef enum meta_search_candidate_t {
META_SEARCH_ERR = -1,
META_SEARCH_NOT_CANDIDATE,
- META_SEARCH_CANDIDATE
+ META_SEARCH_CANDIDATE,
+ META_SEARCH_BINDING,
+ META_SEARCH_NEED_BIND
} meta_search_candidate_t;
+/*
+ * meta_search_dobind_init()
+ *
+ * initiates bind for a candidate target of a search.
+ */
+static meta_search_candidate_t
+meta_search_dobind_init(
+ Operation *op,
+ SlapReply *rs,
+ metaconn_t **mcp,
+ int candidate,
+ SlapReply *candidates )
+{
+ metaconn_t *mc = *mcp;
+ metainfo_t *mi = ( metainfo_t * )op->o_bd->be_private;
+ metatarget_t *mt = mi->mi_targets[ candidate ];
+ metasingleconn_t *msc = &mc->mc_conns[ candidate ];
+
+ char *binddn = "";
+ struct berval cred = BER_BVC( "" );
+
+ int rc;
+ int nretries = 1;
+
+ meta_search_candidate_t retcode;
+
+ Debug( LDAP_DEBUG_TRACE, "%s >>> meta_search_dobind_init[%d]\n", op->o_log_prefix, candidate, 0 );
+
+ /*
+ * all the targets are already bound as pseudoroot
+ */
+ if ( mc->mc_authz_target == META_BOUND_ALL ) {
+ return META_SEARCH_CANDIDATE;
+ }
+
+ ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex );
+ if ( LDAP_BACK_CONN_ISBOUND( msc ) || LDAP_BACK_CONN_ISANON( msc ) ) {
+ ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
+ return META_SEARCH_CANDIDATE;
+ }
+
+ if ( LDAP_BACK_CONN_BINDING( msc ) ) {
+ ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
+ candidates[ candidate ].sr_msgid = META_MSGID_NEED_BIND;
+ return META_SEARCH_NEED_BIND;
+ }
+
+ LDAP_BACK_CONN_BINDING_SET( msc );
+ ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
+
+ if ( be_isroot( op ) && !BER_BVISNULL( &mt->mt_pseudorootdn ) ) {
+ binddn = mt->mt_pseudorootdn.bv_val;
+ cred = mt->mt_pseudorootpw;
+ }
+
+ /*
+ * Otherwise an anonymous bind is performed
+ * (note: if the target was already bound, the anonymous
+ * bind clears the previous bind).
+ */
+ if ( !BER_BVISNULL( &msc->msc_bound_ndn ) ) {
+ ber_memfree( msc->msc_bound_ndn.bv_val );
+ BER_BVZERO( &msc->msc_bound_ndn );
+ }
+
+ if ( LDAP_BACK_SAVECRED( mi ) && !BER_BVISNULL( &msc->msc_cred ) ) {
+ /* destroy sensitive data */
+ memset( msc->msc_cred.bv_val, 0, msc->msc_cred.bv_len );
+ ber_memfree( msc->msc_cred.bv_val );
+ BER_BVZERO( &msc->msc_cred );
+ }
+
+retry:;
+ assert( msc->msc_ld != NULL );
+
+ rc = ldap_sasl_bind( msc->msc_ld, binddn, LDAP_SASL_SIMPLE, &cred,
+ NULL, NULL, &candidates[ candidate ].sr_msgid );
+ switch ( rc ) {
+ case LDAP_SUCCESS:
+ return META_SEARCH_BINDING;
+
+ case LDAP_SERVER_DOWN:
+ if ( nretries && meta_back_retry( op, rs, mcp, candidate, LDAP_BACK_DONTSEND ) ) {
+ nretries = 0;
+ goto retry;
+ }
+
+ if ( *mcp == NULL ) {
+ retcode = META_SEARCH_ERR;
+ rs->sr_err = LDAP_UNAVAILABLE;
+ break;
+ }
+ /* fall thru */
+
+ default:
+ rs->sr_err = rc;
+ rc = slap_map_api2result( rs );
+
+ ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex );
+ LDAP_BACK_CONN_BINDING_CLEAR( msc );
+ if ( META_BACK_ONERR_STOP( mi ) ) {
+ LDAP_BACK_CONN_TAINTED_SET( mc );
+ meta_back_release_conn( op, mc );
+ *mcp = NULL;
+
+ retcode = META_SEARCH_ERR;
+
+ } else {
+ candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;
+ retcode = META_SEARCH_NOT_CANDIDATE;
+ }
+ ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
+ break;
+ }
+
+ return retcode;
+}
+
+static meta_search_candidate_t
+meta_search_dobind_result(
+ Operation *op,
+ SlapReply *rs,
+ metaconn_t **mcp,
+ int candidate,
+ SlapReply *candidates,
+ LDAPMessage *res )
+{
+ metainfo_t *mi = ( metainfo_t * )op->o_bd->be_private;
+ metaconn_t *mc = *mcp;
+ metasingleconn_t *msc = &mc->mc_conns[ candidate ];
+
+ meta_search_candidate_t retcode = META_SEARCH_NOT_CANDIDATE;
+ int rc;
+
+ assert( msc->msc_ld != NULL );
+
+ rc = ldap_parse_result( msc->msc_ld, res,
+ &candidates[ candidate ].sr_err,
+ NULL, NULL, NULL, NULL, 1 );
+ if ( rc == LDAP_SUCCESS ) {
+ rc = slap_map_api2result( &candidates[ candidate ] );
+ }
+
+ ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex );
+ LDAP_BACK_CONN_BINDING_CLEAR( msc );
+ if ( rc != LDAP_SUCCESS ) {
+ if ( META_BACK_ONERR_STOP( mi ) ) {
+ LDAP_BACK_CONN_TAINTED_SET( mc );
+ meta_back_release_conn( op, mc );
+ *mcp = NULL;
+ retcode = META_SEARCH_ERR;
+ }
+
+ } else {
+ if ( be_isroot( op ) ) {
+ LDAP_BACK_CONN_ISBOUND_SET( msc );
+ } else {
+ LDAP_BACK_CONN_ISANON_SET( msc );
+ }
+ retcode = META_SEARCH_CANDIDATE;
+ }
+ ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
+
+ return retcode;
+}
+
static meta_search_candidate_t
meta_back_search_start(
Operation *op,
SlapReply *rs,
dncookie *dc,
- metasingleconn_t *msc,
+ metaconn_t **mcp,
int candidate,
- SlapReply *candidates
-)
+ SlapReply *candidates )
{
- metainfo_t *mi = ( metainfo_t * )op->o_bd->be_private;
- struct berval realbase = op->o_req_dn;
- int realscope = op->ors_scope;
- ber_len_t suffixlen = 0;
- struct berval mbase = BER_BVNULL;
- struct berval mfilter = BER_BVNULL;
- char **mapped_attrs = NULL;
- int rc;
+ metainfo_t *mi = ( metainfo_t * )op->o_bd->be_private;
+ metatarget_t *mt = mi->mi_targets[ candidate ];
+ metaconn_t *mc = *mcp;
+ metasingleconn_t *msc = &mc->mc_conns[ candidate ];
+ struct berval realbase = op->o_req_dn;
+ int realscope = op->ors_scope;
+ ber_len_t suffixlen = 0;
+ struct berval mbase = BER_BVNULL;
+ struct berval mfilter = BER_BVNULL;
+ char **mapped_attrs = NULL;
+ int rc;
meta_search_candidate_t retcode;
- struct timeval tv, *tvp = NULL;
+ struct timeval tv, *tvp = NULL;
+ int nretries = 1;
+
+ Debug( LDAP_DEBUG_TRACE, "%s >>> meta_back_search_start[%d]\n", op->o_log_prefix, candidate, 0 );
/* should we check return values? */
if ( op->ors_deref != -1 ) {
- ldap_set_option( msc->msc_ld, LDAP_OPT_DEREF,
+ assert( msc->msc_ld != NULL );
+ (void)ldap_set_option( msc->msc_ld, LDAP_OPT_DEREF,
( void * )&op->ors_deref );
}
if ( op->ors_tlimit != SLAP_NO_LIMIT ) {
tv.tv_sec = op->ors_tlimit > 0 ? op->ors_tlimit : 1;
+ tv.tv_usec = 0;
tvp = &tv;
}
- dc->target = &mi->mi_targets[ candidate ];
+ dc->target = mt;
/*
* modifies the base according to the scope, if required
*/
- suffixlen = mi->mi_targets[ candidate ].mt_nsuffix.bv_len;
+ suffixlen = mt->mt_nsuffix.bv_len;
if ( suffixlen > op->o_req_ndn.bv_len ) {
switch ( op->ors_scope ) {
case LDAP_SCOPE_SUBTREE:
* the requested searchBase already passed
* thru the candidate analyzer...
*/
- if ( dnIsSuffix( &mi->mi_targets[ candidate ].mt_nsuffix,
- &op->o_req_ndn ) )
- {
- realbase = mi->mi_targets[ candidate ].mt_nsuffix;
- if ( mi->mi_targets[ candidate ].mt_scope == LDAP_SCOPE_SUBORDINATE ) {
+ if ( dnIsSuffix( &mt->mt_nsuffix, &op->o_req_ndn ) ) {
+ realbase = mt->mt_nsuffix;
+ if ( mt->mt_scope == LDAP_SCOPE_SUBORDINATE ) {
realscope = LDAP_SCOPE_SUBORDINATE;
}
case LDAP_SCOPE_SUBORDINATE:
case LDAP_SCOPE_ONELEVEL:
{
- struct berval rdn = mi->mi_targets[ candidate ].mt_nsuffix;
+ struct berval rdn = mt->mt_nsuffix;
rdn.bv_len -= op->o_req_ndn.bv_len + STRLENOF( "," );
if ( dnIsOneLevelRDN( &rdn )
- && dnIsSuffix( &mi->mi_targets[ candidate ].mt_nsuffix, &op->o_req_ndn ) )
+ && dnIsSuffix( &mt->mt_nsuffix, &op->o_req_ndn ) )
{
/*
* if there is exactly one level,
* make the target suffix the new
* base, and make scope "base"
*/
- realbase = mi->mi_targets[ candidate ].mt_nsuffix;
+ realbase = mt->mt_nsuffix;
if ( op->ors_scope == LDAP_SCOPE_SUBORDINATE ) {
- if ( mi->mi_targets[ candidate ].mt_scope == LDAP_SCOPE_SUBORDINATE ) {
+ if ( mt->mt_scope == LDAP_SCOPE_SUBORDINATE ) {
realscope = LDAP_SCOPE_SUBORDINATE;
} else {
realscope = LDAP_SCOPE_SUBTREE;
}
}
+ /* initiate dobind */
+ retcode = meta_search_dobind_init( op, rs, mcp, candidate, candidates );
+
+ Debug( LDAP_DEBUG_TRACE, "%s <<< meta_search_dobind_init[%d]=%d\n", op->o_log_prefix, candidate, retcode );
+
+ if ( retcode != META_SEARCH_CANDIDATE ) {
+ return retcode;
+ }
+
/*
* Rewrite the search base, if required
*/
/*
* Maps required attributes
*/
- rc = ldap_back_map_attrs( &mi->mi_targets[ candidate ].mt_rwmap.rwm_at,
+ rc = ldap_back_map_attrs( &mt->mt_rwmap.rwm_at,
op->ors_attrs, BACKLDAP_MAP, &mapped_attrs );
if ( rc != LDAP_SUCCESS ) {
/*
/*
* Starts the search
*/
+retry:;
+ assert( msc->msc_ld != NULL );
rc = ldap_search_ext( msc->msc_ld,
mbase.bv_val, realscope, mfilter.bv_val,
mapped_attrs, op->ors_attrsonly,
op->o_ctrls, NULL, tvp, op->ors_slimit,
&candidates[ candidate ].sr_msgid );
- if ( rc == LDAP_SUCCESS ) {
+ switch ( rc ) {
+ case LDAP_SUCCESS:
retcode = META_SEARCH_CANDIDATE;
+ break;
+
+ case LDAP_SERVER_DOWN:
+ if ( nretries && meta_back_retry( op, rs, mcp, candidate, LDAP_BACK_DONTSEND ) ) {
+ nretries = 0;
+ goto retry;
+ }
- } else {
- candidates[ candidate ].sr_msgid = -1;
+ if ( *mcp == NULL ) {
+ retcode = META_SEARCH_ERR;
+ break;
+ }
+ /* fall thru */
+
+ default:
+ candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;
retcode = META_SEARCH_NOT_CANDIDATE;
}
* to map attrs and maybe rewrite value
*/
mc = meta_back_getconn( op, rs, NULL, LDAP_BACK_SENDERR );
- if ( !mc || !meta_back_dobind( op, rs, mc, LDAP_BACK_SENDERR ) ) {
+ if ( !mc ) {
return rs->sr_err;
}
* Inits searches
*/
for ( i = 0; i < mi->mi_ntargets; i++ ) {
- metasingleconn_t *msc = &mc->mc_conns[ i ];
+ candidates[ i ].sr_msgid = META_MSGID_IGNORE;
+
+ if ( candidates[ i ].sr_tag != META_CANDIDATE ) {
+ continue;
+ }
- candidates[ i ].sr_msgid = -1;
candidates[ i ].sr_matched = NULL;
candidates[ i ].sr_text = NULL;
candidates[ i ].sr_ref = NULL;
candidates[ i ].sr_ctrls = NULL;
+ }
+ for ( i = 0; i < mi->mi_ntargets; i++ ) {
if ( candidates[ i ].sr_tag != META_CANDIDATE
|| candidates[ i ].sr_err != LDAP_SUCCESS )
{
continue;
}
- switch ( meta_back_search_start( op, rs, &dc, msc, i, candidates ) )
+ switch ( meta_back_search_start( op, rs, &dc, &mc, i, candidates ) )
{
case META_SEARCH_NOT_CANDIDATE:
break;
case META_SEARCH_CANDIDATE:
+ case META_SEARCH_BINDING:
+ case META_SEARCH_NEED_BIND:
candidates[ i ].sr_type = REP_INTERMEDIATE;
++ncandidates;
break;
case META_SEARCH_ERR:
+ savepriv = op->o_private;
+ op->o_private = (void *)i;
+ send_ldap_result( op, rs );
+ op->o_private = savepriv;
rc = -1;
goto finish;
}
for ( rc = 0; ncandidates > 0; ) {
int gotit = 0, doabandon = 0;
+ /* check time limit */
+ if ( op->ors_tlimit != SLAP_NO_LIMIT
+ && slap_get_time() > stoptime )
+ {
+ doabandon = 1;
+ rc = rs->sr_err = LDAP_TIMELIMIT_EXCEEDED;
+ savepriv = op->o_private;
+ op->o_private = (void *)i;
+ send_ldap_result( op, rs );
+ op->o_private = savepriv;
+ goto finish;
+ }
+
for ( i = 0; i < mi->mi_ntargets; i++ ) {
metasingleconn_t *msc = &mc->mc_conns[ i ];
- if ( candidates[ i ].sr_msgid == -1 ) {
+ if ( candidates[ i ].sr_msgid == META_MSGID_IGNORE ) {
+ continue;
+ }
+
+ if ( candidates[ i ].sr_msgid == META_MSGID_NEED_BIND ) {
+ /* initiate dobind */
+ switch ( meta_search_dobind_init( op, rs, &mc, i, candidates ) )
+ {
+ case META_SEARCH_BINDING:
+ case META_SEARCH_NEED_BIND:
+ break;
+
+ case META_SEARCH_NOT_CANDIDATE:
+ /*
+ * When no candidates are left,
+ * the outer cycle finishes
+ */
+ candidates[ i ].sr_msgid = META_MSGID_IGNORE;
+ --ncandidates;
+ break;
+
+ case META_SEARCH_ERR:
+ if ( META_BACK_ONERR_STOP( mi ) ) {
+ savepriv = op->o_private;
+ op->o_private = (void *)i;
+ send_ldap_result( op, rs );
+ op->o_private = savepriv;
+ goto finish;
+ }
+ break;
+
+ case META_SEARCH_CANDIDATE:
+ switch ( meta_back_search_start( op, rs, &dc, &mc, i, candidates ) )
+ {
+ case META_SEARCH_CANDIDATE:
+ goto get_result;
+
+ /* means that failed but onerr == continue */
+ case META_SEARCH_NOT_CANDIDATE:
+ case META_SEARCH_ERR:
+ candidates[ i ].sr_msgid = META_MSGID_IGNORE;
+ --ncandidates;
+
+ if ( META_BACK_ONERR_STOP( mi ) ) {
+ savepriv = op->o_private;
+ op->o_private = (void *)i;
+ send_ldap_result( op, rs );
+ op->o_private = savepriv;
+ goto finish;
+ }
+ break;
+
+ default:
+ /* impossible */
+ assert( 0 );
+ break;
+ }
+
+ default:
+ /* impossible */
+ assert( 0 );
+ break;
+ }
continue;
}
/* FIXME: res should not need to be freed */
assert( res == NULL );
- /* check time limit */
- if ( op->ors_tlimit != SLAP_NO_LIMIT
- && slap_get_time() > stoptime )
- {
- doabandon = 1;
- rc = rs->sr_err = LDAP_TIMELIMIT_EXCEEDED;
- savepriv = op->o_private;
- op->o_private = (void *)i;
- send_ldap_result( op, rs );
- op->o_private = savepriv;
- goto finish;
- }
-
continue;
} else if ( rc == -1 ) {
candidates[ i ].sr_type = REP_RESULT;
if ( meta_back_retry( op, rs, &mc, i, LDAP_BACK_DONTSEND ) ) {
- switch ( meta_back_search_start( op, rs, &dc, msc, i, candidates ) )
+ switch ( meta_back_search_start( op, rs, &dc, &mc, i, candidates ) )
{
case META_SEARCH_CANDIDATE:
goto get_result;
+ /* means that failed but onerr == continue */
case META_SEARCH_NOT_CANDIDATE:
+ candidates[ i ].sr_msgid = META_MSGID_IGNORE;
+ --ncandidates;
+
+ if ( META_BACK_ONERR_STOP( mi ) ) {
+ savepriv = op->o_private;
+ op->o_private = (void *)i;
+ send_ldap_result( op, rs );
+ op->o_private = savepriv;
+ goto finish;
+ }
+ break;
+
+ case META_SEARCH_BINDING:
+ case META_SEARCH_NEED_BIND:
assert( 0 );
default:
}
}
- savepriv = op->o_private;
- op->o_private = (void *)i;
- send_ldap_result( op, rs );
- op->o_private = savepriv;
- goto finish;
+ if ( META_BACK_ONERR_STOP( mi ) ) {
+ savepriv = op->o_private;
+ op->o_private = (void *)i;
+ send_ldap_result( op, rs );
+ op->o_private = savepriv;
+ goto finish;
+ }
}
/*
* When no candidates are left,
* the outer cycle finishes
*/
- candidates[ i ].sr_msgid = -1;
+ candidates[ i ].sr_msgid = META_MSGID_IGNORE;
--ncandidates;
rs->sr_err = candidates[ i ].sr_err = LDAP_OTHER;
rs->sr_text = "remote server unavailable";
candidates[ i ].sr_matched = NULL;
dc.ctx = "matchedDN";
- dc.target = &mi->mi_targets[ i ];
+ dc.target = mi->mi_targets[ i ];
if ( !ldap_back_dn_massage( &dc, &match, &mmatch ) ) {
if ( mmatch.bv_val == match.bv_val ) {
candidates[ i ].sr_matched = ch_strdup( mmatch.bv_val );
* When no candidates are left,
* the outer cycle finishes
*/
- candidates[ i ].sr_msgid = -1;
+ candidates[ i ].sr_msgid = META_MSGID_IGNORE;
--ncandidates;
+ } else if ( rc == LDAP_RES_BIND ) {
+ meta_search_candidate_t retcode;
+
+ retcode = meta_search_dobind_result( op, rs, &mc, i, candidates, res );
+ if ( retcode == META_SEARCH_CANDIDATE ) {
+ retcode = meta_back_search_start( op, rs, &dc, &mc, i, candidates );
+ }
+
+ switch ( retcode ) {
+ case META_SEARCH_CANDIDATE:
+ goto get_result;
+
+ /* means that failed but onerr == continue */
+ case META_SEARCH_NOT_CANDIDATE:
+ case META_SEARCH_ERR:
+ candidates[ i ].sr_msgid = META_MSGID_IGNORE;
+ --ncandidates;
+
+ if ( META_BACK_ONERR_STOP( mi ) ) {
+ savepriv = op->o_private;
+ op->o_private = (void *)i;
+ send_ldap_result( op, rs );
+ op->o_private = savepriv;
+ goto finish;
+ }
+ break;
+
+ default:
+ assert( 0 );
+ break;
+ }
+
} else {
assert( 0 );
goto really_bad;
for ( i = 0; i < mi->mi_ntargets; i++ ) {
metasingleconn_t *msc = &mc->mc_conns[ i ];
- if ( candidates[ i ].sr_msgid != -1 ) {
+ if ( candidates[ i ].sr_msgid != META_MSGID_IGNORE )
+ {
ldap_abandon_ext( msc->msc_ld,
candidates[ i ].sr_msgid,
NULL, NULL );
- candidates[ i ].sr_msgid = -1;
+ candidates[ i ].sr_msgid = META_MSGID_IGNORE;
}
}
/* if no entry was found during this loop,
* set a minimal timeout */
if ( gotit == 0 ) {
- LDAP_BACK_TV_SET( &tv );
+ /* make the entire wait last
+ * LDAP_BACK_RESULT_UTIMEOUT at worst */
+ tv.tv_sec = 0;
+ tv.tv_usec = LDAP_BACK_RESULT_UTIMEOUT/initial_candidates;
ldap_pvt_thread_yield();
}
}
/*
* FIXME: need a better strategy to handle errors
*/
- rc = meta_back_op_result( mc, op, rs, META_TARGET_NONE );
+ if ( mc ) {
+ rc = meta_back_op_result( mc, op, rs, META_TARGET_NONE );
+ } else {
+ rc = rs->sr_err;
+ }
goto finish;
}
* ignore the matchedDN */
if ( sres == LDAP_SUCCESS
&& candidates[ i ].sr_err == LDAP_NO_SUCH_OBJECT
- && op->o_req_ndn.bv_len > mi->mi_targets[ i ].mt_nsuffix.bv_len )
+ && op->o_req_ndn.bv_len > mi->mi_targets[ i ]->mt_nsuffix.bv_len )
{
free( (char *)candidates[ i ].sr_matched );
candidates[ i ].sr_matched = NULL;
continue;
}
+ if ( mc && candidates[ i ].sr_msgid >= 0 ) {
+ ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex );
+ if ( LDAP_BACK_CONN_BINDING( &mc->mc_conns[ i ] ) ) {
+ LDAP_BACK_CONN_BINDING_CLEAR( &mc->mc_conns[ i ] );
+ }
+ ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
+ }
+
if ( candidates[ i ].sr_matched ) {
free( (char *)candidates[ i ].sr_matched );
candidates[ i ].sr_matched = NULL;
/*
* Rewrite the dn of the result, if needed
*/
- dc.target = &mi->mi_targets[ target ];
+ dc.target = mi->mi_targets[ target ];
dc.conn = op->o_conn;
dc.rs = rs;
dc.ctx = "searchResult";
slap_syntax_validate_func *validate;
slap_syntax_transform_func *pretty;
- ldap_back_map( &mi->mi_targets[ target ].mt_rwmap.rwm_at,
+ ldap_back_map( &mi->mi_targets[ target ]->mt_rwmap.rwm_at,
&a, &mapped, BACKLDAP_REMAP );
if ( BER_BVISNULL( &mapped ) || mapped.bv_val[0] == '\0' ) {
( void )ber_scanf( &ber, "x" /* [W] */ );
struct berval *bv;
for ( bv = attr->a_vals; !BER_BVISNULL( bv ); bv++ ) {
- ldap_back_map( &mi->mi_targets[ target ].mt_rwmap.rwm_oc,
+ ldap_back_map( &mi->mi_targets[ target ]->mt_rwmap.rwm_oc,
bv, &mapped, BACKLDAP_REMAP );
if ( BER_BVISNULL( &mapped ) || mapped.bv_val[0] == '\0') {
free( bv->bv_val );
* Cleanup rewrite session
*/
for ( i = 0; i < mi->mi_ntargets; ++i ) {
- rewrite_session_delete( mi->mi_targets[ i ].mt_rwmap.rwm_rw, conn );
+ rewrite_session_delete( mi->mi_targets[ i ]->mt_rwmap.rwm_rw, conn );
}
return 0;
int t;
for ( t = 0; t < mi->mi_ntargets; t++ ) {
- char **urls = ldap_str2charray( mi->mi_targets[ t ].mt_uri, " " );
+ char **urls = ldap_str2charray( mi->mi_targets[ t ]->mt_uri, " " );
if ( urls != NULL ) {
int u;
{
struct null_info *ni = (struct null_info *) op->o_bd->be_private;
- if ( ni->ni_bind_allowed ) {
+ if ( ni->ni_bind_allowed || be_isroot_pw( op ) ) {
/* front end will send result on success (0) */
return LDAP_SUCCESS;
}
const char *text = NULL;
struct berval bv;
struct berbuf bb = BB_NULL;
+ AttributeDescription *ad = NULL;
Debug( LDAP_DEBUG_TRACE,
"attributeType:\n"
/* TimesTen */
Debug( LDAP_DEBUG_TRACE, "\tsel_expr_u=\"%s\"\n",
at_row.cols[ 8 ], 0, 0 );
- at_map = (backsql_at_map_rec *)ch_calloc( 1,
- sizeof( backsql_at_map_rec ) );
- rc = slap_str2ad( at_row.cols[ 0 ],
- &at_map->bam_ad, &text );
+ rc = slap_str2ad( at_row.cols[ 0 ], &ad, &text );
if ( rc != LDAP_SUCCESS ) {
Debug( LDAP_DEBUG_TRACE, "backsql_oc_get_attr_mapping(): "
"attribute \"%s\" for objectClass \"%s\" "
bas->bas_rc = LDAP_CONSTRAINT_VIOLATION;
return BACKSQL_AVL_STOP;
}
+ at_map = (backsql_at_map_rec *)ch_calloc( 1,
+ sizeof( backsql_at_map_rec ) );
+ at_map->bam_ad = ad;
ber_str2bv( at_row.cols[ 1 ], 0, 1, &at_map->bam_sel_expr );
if ( at_row.value_len[ 8 ] < 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;
row->col_prec = (UDWORD *)ber_memcalloc_x( row->ncols,
sizeof( UDWORD ), ctx );
+ if ( !row->col_prec ) goto nomem1;
row->value_len = (SQLINTEGER *)ber_memcalloc_x( row->ncols,
sizeof( SQLINTEGER ), ctx );
+ if ( !row->value_len ) {
+ ber_memfree_x( row->col_prec, ctx );
+ row->col_prec = NULL;
+nomem1: 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: "
+ "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 ],
(SQLUINTEGER)( sizeof( colname ) - 1 ),
int
be_shadow_update( Operation *op )
{
- return ( SLAP_SYNC_SHADOW( op->o_bd ) ||
+ /* This assumes that all internal ops (connid == -1) on a syncrepl
+ * database are syncrepl operations.
+ */
+ return (( SLAP_SYNC_SHADOW( op->o_bd ) && op->o_connid == -1 ) ||
( SLAP_SHADOW( op->o_bd ) && be_isupdate_dn( op->o_bd, &op->o_ndn ) ) );
}
BackendDB *b1 = NULL, *btmp;
BackendInfo *bi0 = op->o_bd->bd_info;
int i;
- long stoptime = 0;
+ long stoptime = 0, starttime;
glue_state gs = {NULL, NULL, NULL, 0, 0, 0, 0};
slap_callback cb = { NULL, glue_op_response, NULL, NULL };
int scope0, tlimit0;
cb.sc_next = op->o_callback;
+ starttime = op->o_time;
stoptime = slap_get_time () + op->ors_tlimit;
op->o_bd = glue_back_select (b0, &op->o_req_ndn);
if (!dnIsSuffix(&btmp->be_nsuffix[0], &b1->be_nsuffix[0]))
continue;
if (tlimit0 != SLAP_NO_LIMIT) {
- op->ors_tlimit = stoptime - slap_get_time ();
+ op->o_time = slap_get_time();
+ op->ors_tlimit = stoptime - op->o_time;
if (op->ors_tlimit <= 0) {
rs->sr_err = gs.err = LDAP_TIMELIMIT_EXCEEDED;
break;
end_of_loop:;
op->ors_scope = scope0;
op->ors_tlimit = tlimit0;
+ op->o_time = starttime;
op->o_req_dn = dn;
op->o_req_ndn = ndn;
static struct berval config_rdn = BER_BVC("cn=config");
static struct berval schema_rdn = BER_BVC("cn=schema");
+extern int slap_DN_strict; /* dn.c */
+
#ifdef SLAPD_MODULES
typedef struct modpath_s {
struct modpath_s *mp_next;
static Avlnode *CfOcTree;
static int config_add_internal( CfBackInfo *cfb, Entry *e, ConfigArgs *ca,
- SlapReply *rs, int *renumber );
+ SlapReply *rs, int *renumber, Operation *op );
static ConfigDriver config_fname;
static ConfigDriver config_cfdir;
* 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
*/
/* alphabetical ordering */
"SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL },
{ "limits", "limits", 2, 0, 0, ARG_DB|ARG_MAGIC|CFG_LIMITS,
&config_generic, "( OLcfgDbAt:0.5 NAME 'olcLimits' "
+ "EQUALITY caseIgnoreMatch "
"SYNTAX OMsDirectoryString X-ORDERED 'VALUES' )", NULL, NULL },
{ "localSSF", "ssf", 2, 2, 0, ARG_INT,
&local_ssf, "( OLcfgGlAt:26 NAME 'olcLocalSSF' "
"SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
{ "loglevel", "level", 2, 0, 0, ARG_MAGIC,
&config_loglevel, "( OLcfgGlAt:28 NAME 'olcLogLevel' "
+ "EQUALITY caseIgnoreMatch "
"SYNTAX OMsDirectoryString )", NULL, NULL },
{ "maxDerefDepth", "depth", 2, 2, 0, ARG_DB|ARG_INT|ARG_MAGIC|CFG_DEPTH,
&config_generic, "( OLcfgDbAt:0.6 NAME 'olcMaxDerefDepth' "
ARG_IGNORED, NULL,
#endif
"( OLcfgGlAt:30 NAME 'olcModuleLoad' "
+ "EQUALITY caseIgnoreMatch "
"SYNTAX OMsDirectoryString X-ORDERED 'VALUES' )", NULL, NULL },
{ "modulepath", "path", 2, 2, 0,
#ifdef SLAPD_MODULES
NULL, NULL },
{ "objectidentifier", NULL, 0, 0, 0, ARG_MAGIC|CFG_OID,
&config_generic, "( OLcfgGlAt:33 NAME 'olcObjectIdentifier' "
+ "EQUALITY caseIgnoreMatch "
"SYNTAX OMsDirectoryString X-ORDERED 'VALUES' )", NULL, NULL },
{ "overlay", "overlay", 2, 2, 0, ARG_MAGIC,
&config_overlay, "( OLcfgGlAt:34 NAME 'olcOverlay' "
"SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
{ "password-hash", "hash", 2, 2, 0, ARG_MAGIC,
&config_passwd_hash, "( OLcfgGlAt:36 NAME 'olcPasswordHash' "
+ "EQUALITY caseIgnoreMatch "
"SYNTAX OMsDirectoryString )", NULL, NULL },
{ "pidfile", "file", 2, 2, 0, ARG_STRING,
&slapd_pid_file, "( OLcfgGlAt:37 NAME 'olcPidFile' "
ARG_IGNORED, NULL,
#endif
"( OLcfgGlAt:38 NAME 'olcPlugin' "
+ "EQUALITY caseIgnoreMatch "
"SYNTAX OMsDirectoryString )", NULL, NULL },
{ "pluginlog", "filename", 2, 2, 0,
#ifdef LDAP_SLAPI
"SUP labeledURI SINGLE-VALUE )", NULL, NULL },
{ "replica", "host or uri", 2, 0, 0, ARG_DB|ARG_MAGIC,
&config_replica, "( 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' "
"SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
{ "require", "features", 2, 0, 7, ARG_MAY_DB|ARG_MAGIC,
&config_requires, "( OLcfgGlAt:47 NAME 'olcRequires' "
+ "EQUALITY caseIgnoreMatch "
"SYNTAX OMsDirectoryString )", NULL, NULL },
{ "restrict", "op_list", 2, 0, 0, ARG_MAY_DB|ARG_MAGIC,
&config_restrict, "( OLcfgGlAt:48 NAME 'olcRestrict' "
+ "EQUALITY caseIgnoreMatch "
"SYNTAX OMsDirectoryString )", NULL, NULL },
{ "reverse-lookup", "on|off", 2, 2, 0,
#ifdef SLAPD_RLOOKUPS
"SYNTAX OMsDN SINGLE-VALUE )", NULL, NULL },
{ "rootDSE", "file", 2, 2, 0, ARG_MAGIC|CFG_ROOTDSE,
&config_generic, "( OLcfgGlAt:51 NAME 'olcRootDSE' "
+ "EQUALITY caseIgnoreMatch "
"SYNTAX OMsDirectoryString )", NULL, NULL },
{ "rootpw", "password", 2, 2, 0, ARG_BERVAL|ARG_DB|ARG_MAGIC,
&config_rootpw, "( OLcfgDbAt:0.9 NAME 'olcRootPW' "
"SYNTAX OMsDN SINGLE-VALUE )", NULL, NULL },
{ "security", "factors", 2, 0, 0, ARG_MAY_DB|ARG_MAGIC,
&config_security, "( OLcfgGlAt:59 NAME 'olcSecurity' "
+ "EQUALITY caseIgnoreMatch "
"SYNTAX OMsDirectoryString )", NULL, NULL },
{ "sizelimit", "limit", 2, 0, 0, ARG_MAY_DB|ARG_MAGIC,
&config_sizelimit, "( OLcfgGlAt:60 NAME 'olcSizeLimit' "
"SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
{ "subordinate", "[advertise]", 1, 2, 0, ARG_DB|ARG_MAGIC,
&config_subordinate, "( OLcfgDbAt:0.15 NAME 'olcSubordinate' "
- "SYNTAX OMsDirectoryString )", NULL, NULL },
+ "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
{ "suffix", "suffix", 2, 2, 0, ARG_DB|ARG_DN|ARG_QUOTE|ARG_MAGIC,
&config_suffix, "( OLcfgDbAt:0.10 NAME 'olcSuffix' "
+ "EQUALITY distinguishedNameMatch "
"SYNTAX OMsDN )", NULL, NULL },
{ "syncrepl", NULL, 0, 0, 0, ARG_DB|ARG_MAGIC,
&syncrepl_config, "( OLcfgDbAt:0.11 NAME 'olcSyncrepl' "
"SYNTAX OMsDN SINGLE-VALUE )", NULL, NULL },
{ "updateref", "url", 2, 2, 0, ARG_DB|ARG_MAGIC,
&config_updateref, "( OLcfgDbAt:0.13 NAME 'olcUpdateRef' "
+ "EQUALITY caseIgnoreMatch "
"SUP labeledURI )", NULL, NULL },
{ NULL, NULL, 0, 0, 0, ARG_IGNORED,
NULL, NULL, NULL, NULL }
break;
case CFG_ACL:
- if ( parse_acl(c->be, c->fname, c->lineno, c->argc, c->argv, c->valx ) ) {
+ /* Don't append to the global ACL if we're on a specific DB */
+ i = c->valx;
+ if ( c->be != frontendDB && frontendDB->be_acl && c->valx == -1 ) {
+ AccessControl *a;
+ i = 0;
+ for ( a=c->be->be_acl; a && a != frontendDB->be_acl;
+ a = a->acl_next )
+ i++;
+ }
+ if ( parse_acl(c->be, c->fname, c->lineno, c->argc, c->argv, i ) ) {
return 1;
}
break;
/* 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:
setup_cookie *sc = op->o_callback->sc_private;
sc->cfb->cb_got_ldif = 1;
- rs->sr_err = config_add_internal( sc->cfb, rs->sr_entry, sc->ca, NULL, NULL );
+ 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 );
if ( readit ) {
void *thrctx = ldap_pvt_thread_pool_context();
+ int prev_DN_strict;
op = (Operation *) &opbuf;
connection_fake_init( &conn, op, thrctx );
cb.sc_private = ≻
op->o_bd = &cfb->cb_db;
+
+ /* Allow unknown attrs in DNs */
+ prev_DN_strict = slap_DN_strict;
+ slap_DN_strict = 0;
+
rc = op->o_bd->be_search( op, &rs );
+ /* Restore normal DN validation */
+ slap_DN_strict = prev_DN_strict;
+
ldap_pvt_thread_pool_context_reset( thrctx );
}
return 1;
cfb = be->be_private;
+ be->be_dfltaccess = ACL_NONE;
/* If no .conf, or a dir was specified, setup the dir */
if ( !fname || dir ) {
if ( rc != LDAP_NO_SUCH_OBJECT )
return 1;
/* ITS#4194: But if dir was specified and no fname,
- * then we were supposed to read the dir.
+ * then we were supposed to read the dir. Unless we're
+ * trying to slapadd the dir...
*/
- if ( dir && !fname )
- return 1;
+ if ( dir && !fname ) {
+ if ( slapMode & (SLAP_SERVER_MODE|SLAP_TOOL_READMAIN|SLAP_TOOL_READONLY))
+ return 1;
+ /* Assume it's slapadd with a config dir, let it continue */
+ rc = 0;
+ cfb->cb_got_ldif = 1;
+ cfb->cb_use_ldif = 1;
+ goto done;
+ }
}
/* If we read the config from back-ldif, nothing to do here */
if ( rc == 0 )
ber_str2bv( cfname, 0, 1, &cfb->cb_config->c_file );
- /* If we got this far and failed, it may be a serious problem. In server
- * mode, we should never come to this. However, it may be alright if we're
- * using slapadd to create the conf dir.
- */
- while ( rc ) {
- if ( slapMode & (SLAP_SERVER_MODE|SLAP_TOOL_READMAIN|SLAP_TOOL_READONLY))
- break;
- /* If a config file was explicitly given, fail */
- if ( fname )
- break;
-
- /* Seems to be slapadd with a config dir, let it continue */
- if ( cfb->cb_use_ldif ) {
- rc = 0;
- cfb->cb_got_ldif = 1;
- }
- break;
- }
-
done:
if ( rc == 0 && BER_BVISNULL( &frontendDB->be_schemadn ) ) {
ber_str2bv( SLAPD_SCHEMA_DN, STRLENOF( SLAPD_SCHEMA_DN ), 1,
/* Parse an LDAP entry into config directives */
static int
-config_add_internal( CfBackInfo *cfb, Entry *e, ConfigArgs *ca, SlapReply *rs, int *renum )
+config_add_internal( CfBackInfo *cfb, Entry *e, ConfigArgs *ca, SlapReply *rs,
+ int *renum, Operation *op )
{
CfEntryInfo *ce, *last;
ConfigOCs **colst;
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 ))
+ return LDAP_NO_SUCH_OBJECT;
+ if ( last && !access_allowed( op, last->ce_entry,
+ slap_schema.si_ad_children, NULL, ACL_WADD, NULL ))
+ return LDAP_INSUFFICIENT_ACCESS;
+ }
+
oc_at = attr_find( e->e_attrs, slap_schema.si_ad_objectClass );
if ( !oc_at ) return LDAP_OBJECT_CLASS_VIOLATION;
int renumber;
ConfigArgs ca;
- if ( !be_isroot( op ) ) {
+ if ( !access_allowed( op, op->ora_e, slap_schema.si_ad_entry,
+ NULL, ACL_WADD, NULL )) {
rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
goto out;
}
*/
/* NOTE: by now we do not accept adds that require renumbering */
renumber = -1;
- rs->sr_err = config_add_internal( cfb, op->ora_e, &ca, rs, &renumber );
+ 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;
goto out2;
char *ptr;
AttributeDescription *rad = NULL;
- if ( !be_isroot( op ) ) {
- rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
- goto out;
- }
-
cfb = (CfBackInfo *)op->o_bd->be_private;
ce = config_find_base( cfb->cb_root, &op->o_req_ndn, &last );
goto out;
}
+ if ( !acl_check_modlist( op, ce->ce_entry, op->orm_modlist )) {
+ rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
+ goto out;
+ }
+
/* Get type of RDN */
rdn = ce->ce_entry->e_nname;
ptr = strchr( rdn.bv_val, '=' );
CfBackInfo *cfb;
CfEntryInfo *ce, *last;
- if ( !be_isroot( op ) ) {
- rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
- goto out;
- }
-
cfb = (CfBackInfo *)op->o_bd->be_private;
ce = config_find_base( cfb->cb_root, &op->o_req_ndn, &last );
rs->sr_err = LDAP_NO_SUCH_OBJECT;
goto out;
}
+ if ( !access_allowed( op, ce->ce_entry, slap_schema.si_ad_entry,
+ NULL, ACL_WRITE, NULL )) {
+ rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
+ goto out;
+ }
+ { Entry *parent;
+ if ( ce->ce_parent )
+ parent = ce->ce_parent->ce_entry;
+ else
+ parent = (Entry *)&slap_entry_root;
+ if ( !access_allowed( op, parent, slap_schema.si_ad_children,
+ NULL, ACL_WRITE, NULL )) {
+ rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
+ goto out;
+ }
+ }
/* We don't allow moving objects to new parents.
* Generally we only allow reordering a set of ordered entries.
{
CfBackInfo *cfb;
CfEntryInfo *ce, *last;
-
- if ( !be_isroot( op ) ) {
- rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
- goto out;
- }
+ slap_mask_t mask;
cfb = (CfBackInfo *)op->o_bd->be_private;
rs->sr_err = LDAP_NO_SUCH_OBJECT;
goto out;
}
+ if ( !access_allowed_mask( op, ce->ce_entry, slap_schema.si_ad_entry, NULL,
+ ACL_SEARCH, NULL, &mask ))
+ {
+ if ( !ACL_GRANT( mask, ACL_DISCLOSE )) {
+ rs->sr_err = LDAP_NO_SUCH_OBJECT;
+ } else {
+ rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
+ }
+ goto out;
+ }
switch ( op->ors_scope ) {
case LDAP_SCOPE_BASE:
case LDAP_SCOPE_SUBTREE:
}
#endif
+static const char *defacl[] = {
+ NULL, "to", "*", "by", "*", "none", NULL
+};
+
static int
config_back_db_open( BackendDB *be )
{
void *thrctx = NULL;
Debug( LDAP_DEBUG_TRACE, "config_back_db_open\n", 0, 0, 0);
+
+ /* If we have no explicitly configured ACLs, don't just use
+ * the global ACLs. Explicitly deny access to everything.
+ */
+ if ( frontendDB->be_acl && be->be_acl == frontendDB->be_acl ) {
+ parse_acl(be, "config_back_db_open", 0, 6, (char **)defacl, 0 );
+ }
+
/* If we read the config from back-ldif, nothing to do here */
if ( cfb->cb_got_ldif )
return 0;
ConfigArgs ca;
if ( bi && bi->bi_tool_entry_put &&
- config_add_internal( cfb, e, &ca, NULL, NULL ) == 0 )
+ config_add_internal( cfb, e, &ca, NULL, NULL, NULL ) == 0 )
return bi->bi_tool_entry_put( &cfb->cb_db, e, text );
else
return NOID;
bi->bi_chk_referrals = 0;
- bi->bi_access_allowed = slap_access_always_allowed;
+ bi->bi_access_allowed = slap_access_allowed;
bi->bi_connection_init = 0;
bi->bi_connection_destroy = 0;
}
int config_check_vals(ConfigTable *Conf, ConfigArgs *c, int check_only ) {
- int rc, arg_user, arg_type, iarg;
+ int rc, arg_user, arg_type, arg_syn, iarg;
long larg;
ber_len_t barg;
- arg_type = Conf->arg_type;
- if(arg_type == ARG_IGNORED) {
+ if(Conf->arg_type == ARG_IGNORED) {
Debug(LDAP_DEBUG_CONFIG, "%s: keyword <%s> ignored\n",
c->log, Conf->name, 0);
return(0);
}
- if((arg_type & ARG_DN) && c->argc == 1) {
+ arg_type = Conf->arg_type & ARGS_TYPES;
+ arg_user = Conf->arg_type & ARGS_USERLAND;
+ arg_syn = Conf->arg_type & ARGS_SYNTAX;
+
+ if((arg_type == ARG_DN) && c->argc == 1) {
c->argc = 2;
c->argv[1] = "";
}
return(ARG_BAD_CONF);
#endif /* LDAP_DEVEL */
}
- if((arg_type & ARG_DB) && !c->be) {
+ if((arg_syn & ARG_DB) && !c->be) {
snprintf( c->msg, sizeof( c->msg ), "<%s> only allowed within database declaration",
c->argv[0] );
Debug(LDAP_DEBUG_CONFIG, "%s: keyword %s\n",
c->log, c->msg, 0);
return(ARG_BAD_CONF);
}
- if((arg_type & ARG_PRE_BI) && c->bi) {
+ if((arg_syn & ARG_PRE_BI) && c->bi) {
snprintf( c->msg, sizeof( c->msg ), "<%s> must occur before any backend %sdeclaration",
- c->argv[0], (arg_type & ARG_PRE_DB) ? "or database " : "" );
+ c->argv[0], (arg_syn & ARG_PRE_DB) ? "or database " : "" );
Debug(LDAP_DEBUG_CONFIG, "%s: keyword %s\n",
c->log, c->msg, 0 );
return(ARG_BAD_CONF);
}
- if((arg_type & ARG_PRE_DB) && c->be && c->be != frontendDB) {
+ if((arg_syn & ARG_PRE_DB) && c->be && c->be != frontendDB) {
snprintf( c->msg, sizeof( c->msg ), "<%s> must occur before any database declaration",
c->argv[0] );
Debug(LDAP_DEBUG_CONFIG, "%s: keyword %s\n",
c->log, c->msg, 0);
return(ARG_BAD_CONF);
}
- if((arg_type & ARG_PAREN) && *c->argv[1] != '(' /*')'*/) {
+ if((arg_syn & ARG_PAREN) && *c->argv[1] != '(' /*')'*/) {
snprintf( c->msg, sizeof( c->msg ), "<%s> old format not supported", c->argv[0] );
Debug(LDAP_DEBUG_CONFIG, "%s: %s\n",
c->log, c->msg, 0);
return(ARG_BAD_CONF);
}
- if((arg_type & ARGS_POINTER) && !Conf->arg_item && !(arg_type & ARG_OFFSET)) {
+ if(arg_type && !Conf->arg_item && !(arg_syn & ARG_OFFSET)) {
snprintf( c->msg, sizeof( c->msg ), "<%s> invalid config_table, arg_item is NULL",
c->argv[0] );
Debug(LDAP_DEBUG_CONFIG, "%s: %s\n",
c->log, c->msg, 0);
return(ARG_BAD_CONF);
}
- c->type = arg_user = (arg_type & ARGS_USERLAND);
+ c->type = arg_user;
memset(&c->values, 0, sizeof(c->values));
- if(arg_type & ARGS_NUMERIC) {
+ if(arg_type == ARG_STRING) {
+ if ( !check_only )
+ c->value_string = ch_strdup(c->argv[1]);
+ } else if(arg_type == ARG_BERVAL) {
+ if ( !check_only )
+ ber_str2bv( c->argv[1], 0, 1, &c->value_bv );
+ } else if(arg_type == ARG_DN) {
+ struct berval bv;
+ 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)",
+ c->argv[0], rc, ldap_err2string( rc ));
+ Debug(LDAP_DEBUG_CONFIG, "%s: %s\n" , c->log, c->msg, 0);
+ return(ARG_BAD_CONF);
+ }
+ if ( check_only ) {
+ ch_free( c->value_ndn.bv_val );
+ ch_free( c->value_dn.bv_val );
+ }
+ } else { /* all numeric */
int j;
iarg = 0; larg = 0; barg = 0;
- switch(arg_type & ARGS_NUMERIC) {
+ switch(arg_type) {
case ARG_INT:
if ( lutil_atoix( &iarg, c->argv[1], 0 ) != 0 ) {
snprintf( c->msg, sizeof( c->msg ),
c->log, c->msg, 0 );
return(ARG_BAD_CONF);
}
- switch(arg_type & ARGS_NUMERIC) {
+ switch(arg_type) {
case ARG_ON_OFF:
case ARG_INT: c->value_int = iarg; break;
case ARG_LONG: c->value_long = larg; break;
case ARG_BER_LEN_T: c->value_ber_t = barg; break;
}
- } else if(arg_type & ARG_STRING) {
- if ( !check_only )
- c->value_string = ch_strdup(c->argv[1]);
- } else if(arg_type & ARG_BERVAL) {
- if ( !check_only )
- ber_str2bv( c->argv[1], 0, 1, &c->value_bv );
- } else if(arg_type & ARG_DN) {
- struct berval bv;
- 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)",
- c->argv[0], rc, ldap_err2string( rc ));
- Debug(LDAP_DEBUG_CONFIG, "%s: %s\n" , c->log, c->msg, 0);
- return(ARG_BAD_CONF);
- }
- if ( check_only ) {
- ch_free( c->value_ndn.bv_val );
- ch_free( c->value_dn.bv_val );
- }
}
return 0;
}
return(ARG_BAD_CONF);
}
ptr = (void *)((char *)ptr + (long)Conf->arg_item);
- } else if (arg_type & ARGS_POINTER) {
+ } else if (arg_type & ARGS_TYPES) {
ptr = Conf->arg_item;
}
- if(arg_type & ARGS_POINTER)
- switch(arg_type & ARGS_POINTER) {
+ if(arg_type & ARGS_TYPES)
+ switch(arg_type & ARGS_TYPES) {
case ARG_ON_OFF:
case ARG_INT: *(int*)ptr = c->value_int; break;
case ARG_LONG: *(long*)ptr = c->value_long; break;
ptr = cf->arg_item;
}
- switch(cf->arg_type & ARGS_POINTER) {
+ switch(cf->arg_type & ARGS_TYPES) {
case ARG_ON_OFF:
case ARG_INT: c->value_int = *(int *)ptr; break;
case ARG_LONG: c->value_long = *(long *)ptr; break;
ber_dupbv( &c->value_bv, (struct berval *)ptr ); break;
}
}
- if ( cf->arg_type & ARGS_POINTER) {
+ if ( cf->arg_type & ARGS_TYPES) {
bv.bv_val = c->log;
- switch(cf->arg_type & ARGS_POINTER) {
+ switch(cf->arg_type & ARGS_TYPES) {
case ARG_INT: bv.bv_len = snprintf(bv.bv_val, sizeof( c->log ), "%d", c->value_int); break;
case ARG_LONG: bv.bv_len = snprintf(bv.bv_val, sizeof( c->log ), "%ld", c->value_long); break;
case ARG_BER_LEN_T: bv.bv_len = snprintf(bv.bv_val, sizeof( c->log ), "%ld", c->value_ber_t); break;
if (bv.bv_val == c->log && bv.bv_len >= sizeof( c->log ) ) {
return 1;
}
- if (( cf->arg_type & ARGS_POINTER ) == ARG_STRING )
+ if (( cf->arg_type & ARGS_TYPES ) == ARG_STRING )
ber_bvarray_add(&c->rvalue_vals, &bv);
else
value_add_one(&c->rvalue_vals, &bv);
return -1;
}
+#ifdef HAVE_TLS
static slap_verbmasks tlskey[] = {
{ BER_BVC("no"), SB_TLS_OFF },
{ BER_BVC("yes"), SB_TLS_ON },
{ BER_BVC("critical"), SB_TLS_CRITICAL },
{ BER_BVNULL, 0 }
};
+#endif
static slap_verbmasks methkey[] = {
{ BER_BVC("none"), LDAP_AUTH_NONE },
static slap_cf_aux_table bindkey[] = {
{ BER_BVC("uri="), offsetof(slap_bindconf, sb_uri), 'b', 1, NULL },
- { BER_BVC("starttls="), offsetof(slap_bindconf, sb_tls), 'd', 0, tlskey },
{ BER_BVC("bindmethod="), offsetof(slap_bindconf, sb_method), 'd', 0, methkey },
{ BER_BVC("binddn="), offsetof(slap_bindconf, sb_binddn), 'b', 1, NULL },
{ BER_BVC("credentials="), offsetof(slap_bindconf, sb_cred), 'b', 1, NULL },
{ BER_BVC("authcID="), offsetof(slap_bindconf, sb_authcId), 'b', 0, NULL },
{ BER_BVC("authzID="), offsetof(slap_bindconf, sb_authzId), 'b', 1, NULL },
#ifdef HAVE_TLS
+ { BER_BVC("starttls="), offsetof(slap_bindconf, sb_tls), 'd', 0, tlskey },
+
+#define aux_TLS (bindkey+10) /* beginning of TLS keywords */
+
{ BER_BVC("tls_cert="), offsetof(slap_bindconf, sb_tls_cert), 's', 1, NULL },
{ BER_BVC("tls_key="), offsetof(slap_bindconf, sb_tls_key), 's', 1, NULL },
{ BER_BVC("tls_cacert="), offsetof(slap_bindconf, sb_tls_cacert), 's', 1, NULL },
int
slap_cf_aux_table_parse( const char *word, void *dst, slap_cf_aux_table *tab0, LDAP_CONST char *tabmsg )
{
- int rc = 0;
+ int rc = SLAP_CONF_UNKNOWN;
slap_cf_aux_table *tab;
for (tab = tab0; !BER_BVISNULL(&tab->key); tab++ ) {
case 's':
cptr = (char **)((char *)dst + tab->off);
*cptr = ch_strdup( val );
+ rc = 0;
break;
case 'b':
bptr = (struct berval *)((char *)dst + tab->off);
ber_str2bv( val, 0, 1, bptr );
+ rc = 0;
break;
case 'd':
int
bindconf_parse( const char *word, slap_bindconf *bc )
{
+#ifdef HAVE_TLS
+ /* Detect TLS config changes explicitly */
+ if ( slap_cf_aux_table_parse( word, bc, aux_TLS, "tls config" ) == 0 ) {
+ bc->sb_tls_do_init = 1;
+ return 0;
+ }
+#endif
return slap_cf_aux_table_parse( word, bc, bindkey, "bind config" );
}
int i, rc, newctx = 0, res = 0;
char *ptr = (char *)bc, **word;
+ bc->sb_tls_do_init = 0;
+
for (i=0; bindtlsopts[i].opt; i++) {
word = (char **)(ptr + bindtlsopts[i].offset);
if ( *word ) {
#endif
if ( newctx ) {
int opt = 0;
+
+ if ( bc->sb_tls_ctx ) {
+ SSL_CTX_free( bc->sb_tls_ctx );
+ bc->sb_tls_ctx = NULL;
+ }
rc = ldap_set_option( ld, LDAP_OPT_X_TLS_NEWCTX, &opt );
if ( rc )
res = rc;
} ConfigType;
#define ARGS_USERLAND 0x00000fff
-#define ARGS_TYPES 0x000ff000
-#define ARGS_POINTER 0x0003f000
-#define ARGS_NUMERIC 0x0000f000
+
+/* types are enumerated, not a bitmask */
+#define ARGS_TYPES 0x0000f000
#define ARG_INT 0x00001000
#define ARG_LONG 0x00002000
-#define ARG_BER_LEN_T 0x00004000
-#define ARG_ON_OFF 0x00008000
-#define ARG_STRING 0x00010000
-#define ARG_BERVAL 0x00020000
-#define ARG_DN 0x00040000
-#define ARG_IGNORED 0x00080000
+#define ARG_BER_LEN_T 0x00003000
+#define ARG_ON_OFF 0x00004000
+#define ARG_STRING 0x00005000
+#define ARG_BERVAL 0x00006000
+#define ARG_DN 0x00007000
-#define ARGS_SYNTAX 0xfff00000
+#define ARGS_SYNTAX 0xffff0000
+#define ARG_IGNORED 0x00080000
#define ARG_PRE_BI 0x00100000
#define ARG_PRE_DB 0x00200000
#define ARG_DB 0x00400000 /* Only applies to DB */
#include "slapi/slapi.h"
#endif
-#ifdef SLAP_MULTI_CONN_ARRAY
-/* for Multiple Connection Arrary (MCA) Support */
-static ldap_pvt_thread_mutex_t* connections_mutex;
-static Connection **connections = NULL;
-
-/* set to the number of processors (round up to a power of 2) */
-# define NUM_CONNECTION_ARRAY 4
-
-/* partition the array in a modulo manner */
-# define MCA_conn_array_id(fd) ((int)(fd)%NUM_CONNECTION_ARRAY)
-# define MCA_conn_array_element_id(fd) ((int)(fd)/NUM_CONNECTION_ARRAY)
-# define MCA_ARRAY_SIZE ((int)(MCA_conn_array_element_id(dtblsize) + (MCA_conn_array_id(dtblsize) ? 1 : 0)))
-# define MCA_conn_check(fd) (dtblsize > 0 && (fd) >= 0 && (fd) < (MCA_ARRAY_SIZE*NUM_CONNECTION_ARRAY))
-# define MCA_GET_CONNECTION(fd) (&(connections[MCA_conn_array_id(fd)]) \
- [MCA_conn_array_element_id(fd)])
-# define MCA_GET_CONN_MUTEX(fd) (&connections_mutex[MCA_conn_array_id(fd)])
-
-#else
/* protected by connections_mutex */
static ldap_pvt_thread_mutex_t connections_mutex;
static Connection *connections = NULL;
-# define MCA_conn_check(fd) (dtblsize > 0 && (fd) < dtblsize)
-# define MCA_GET_CONNECTION(fd) (&connections[s])
-# define MCA_GET_CONN_MUTEX(fd) (&connections_mutex)
-#endif
-
static ldap_pvt_thread_mutex_t conn_nextid_mutex;
static unsigned long conn_nextid = 0;
#define SLAP_C_UNINITIALIZED 0x00 /* MUST BE ZERO (0) */
#define SLAP_C_UNUSED 0x01
#define SLAP_C_USED 0x02
+#define SLAP_C_PENDING 0x03
/* connection state (protected by c_mutex ) */
#define SLAP_C_INVALID 0x00 /* MUST BE ZERO (0) */
* Initialize connection management infrastructure.
*/
int connections_init(void)
-#ifdef SLAP_MULTI_CONN_ARRAY
-{
- int i, j;
- Connection* conn;
-
- assert( connections == NULL );
-
- if( connections != NULL) {
- Debug( LDAP_DEBUG_ANY, "connections_init: already initialized.\n",
- 0, 0, 0 );
- return -1;
- }
-
- connections_mutex = (ldap_pvt_thread_mutex_t*) ch_calloc(
- NUM_CONNECTION_ARRAY, sizeof(ldap_pvt_thread_mutex_t) );
- if( connections_mutex == NULL ) {
- Debug( LDAP_DEBUG_ANY, "connections_init: "
- "allocation of connection mutexes failed\n", 0, 0, 0 );
- return -1;
- }
-
- connections = (Connection**) ch_calloc(
- NUM_CONNECTION_ARRAY, sizeof(Connection*));
- if( connections == NULL ) {
- Debug( LDAP_DEBUG_ANY, "connections_init: "
- "allocation of connection[%d] failed\n", 0, 0, 0 );
- return -1;
- }
-
- for ( i = 0; i < NUM_CONNECTION_ARRAY; i++ ) {
- ldap_pvt_thread_mutex_init( connections_mutex+i );
- connections[i] = (Connection*) ch_calloc(
- MCA_ARRAY_SIZE, sizeof(Connection) );
- if( connections[i] == NULL ) {
- Debug( LDAP_DEBUG_ANY, "connections_init: "
- "allocation (%d*%ld) of connection array[%d] failed\n",
- dtblsize, (long) sizeof(Connection), i );
- return -1;
- }
- }
-
- /* should check return of every call */
- ldap_pvt_thread_mutex_init( &conn_nextid_mutex );
-
- assert( connections[0]->c_struct_state == SLAP_C_UNINITIALIZED );
- assert( connections[NUM_CONNECTION_ARRAY-1]->c_struct_state ==
- SLAP_C_UNINITIALIZED );
-
- for ( i = 0; i < NUM_CONNECTION_ARRAY; i++ ) {
- conn = connections[i];
- for ( j = 0; j < MCA_ARRAY_SIZE; j++ ) {
- conn[j].c_conn_idx = j;
- }
- }
-
- /*
- * per entry initialization of the Connection array initialization
- * will be done by connection_init()
- */
-
- return 0;
-}
-#else
{
int i;
return 0;
}
-#endif
/*
* Destroy connection management infrastructure.
*/
int connections_destroy(void)
-#ifdef SLAP_MULTI_CONN_ARRAY
-{
- int i;
- ber_socket_t j;
-
- if( connections == NULL) {
- Debug( LDAP_DEBUG_ANY, "connections_destroy: nothing to destroy.\n",
- 0, 0, 0 );
- return -1;
- }
-
- for ( i = 0; i < NUM_CONNECTION_ARRAY; i++ ) {
- Connection* conn = connections[i];
- for ( j = 0; j < MCA_ARRAY_SIZE; j++ ) {
- if( conn[j].c_struct_state != SLAP_C_UNINITIALIZED ) {
- ber_sockbuf_free( conn[j].c_sb );
- ldap_pvt_thread_mutex_destroy( &conn[j].c_mutex );
- ldap_pvt_thread_mutex_destroy( &conn[j].c_write_mutex );
- ldap_pvt_thread_cond_destroy( &conn[j].c_write_cv );
-#ifdef LDAP_SLAPI
- /* FIX ME!! */
- if ( slapi_plugins_used ) {
- slapi_int_free_object_extensions( SLAPI_X_EXT_CONNECTION,
- &connections[i] );
- }
-#endif
- }
- }
- }
-
- for ( i = 0; i < NUM_CONNECTION_ARRAY; i++ ) {
- free( connections[i] );
- connections[i] = NULL;
- ldap_pvt_thread_mutex_destroy( &connections_mutex[i] );
- }
-
- free( connections );
- free( connections_mutex );
-
- ldap_pvt_thread_mutex_destroy( &conn_nextid_mutex );
-
- return 0;
-
-}
-#else
{
ber_socket_t i;
ldap_pvt_thread_mutex_destroy( &conn_nextid_mutex );
return 0;
}
-#endif
/*
* shutdown all connections
*/
int connections_shutdown(void)
-#ifdef SLAP_MULTI_CONN_ARRAY
-{
- int i;
- ber_socket_t j;
-
- for ( i = 0; i < NUM_CONNECTION_ARRAY; i++ ) {
- Connection* conn = connections[i];
- ldap_pvt_thread_mutex_lock( &connections_mutex[i] );
- for ( j = 0; j < MCA_ARRAY_SIZE; j++ ) {
- if( conn[j].c_struct_state != SLAP_C_USED ) {
- continue;
- }
- /* give persistent clients a chance to cleanup */
- if( conn[j].c_conn_state == SLAP_C_CLIENT ) {
- ldap_pvt_thread_pool_submit( &connection_pool,
- conn[j].c_clientfunc, conn[j].c_clientarg );
- continue;
- }
-
- ldap_pvt_thread_mutex_lock( &conn[j].c_mutex );
- /* connections_mutex and c_mutex are locked */
- connection_closing( &conn[j], "connection shutdown" );
- connection_close( &conn[j] );
- ldap_pvt_thread_mutex_unlock( &conn[j].c_mutex );
- }
-
- ldap_pvt_thread_mutex_unlock( &connections_mutex[i] );
- }
-
- return 0;
-
-}
-#else
{
ber_socket_t i;
- ldap_pvt_thread_mutex_lock( &connections_mutex );
-
for ( i = 0; i < dtblsize; i++ ) {
if( connections[i].c_struct_state != SLAP_C_USED ) {
continue;
ldap_pvt_thread_mutex_lock( &connections[i].c_mutex );
- /* connections_mutex and c_mutex are locked */
+ /* c_mutex is locked */
connection_closing( &connections[i], "slapd shutdown" );
connection_close( &connections[i] );
ldap_pvt_thread_mutex_unlock( &connections[i].c_mutex );
}
- ldap_pvt_thread_mutex_unlock( &connections_mutex );
-
return 0;
}
-#endif
/*
* Timeout idle connections.
static Connection* connection_get( ber_socket_t s )
{
- /* connections_mutex should be locked by caller */
-
Connection *c;
Debug( LDAP_DEBUG_ARGS,
if(s == AC_SOCKET_INVALID) return NULL;
#ifndef HAVE_WINSOCK
- assert( MCA_conn_check( s ) );
- c = MCA_GET_CONNECTION(s);
+ assert( s < dtblsize );
+ c = &connections[s];
#else
c = NULL;
{
ber_socket_t i, sd;
+ ldap_pvt_thread_mutex_lock( &connections_mutex );
for(i=0; i<dtblsize; i++) {
+ if( connections[i].c_struct_state == SLAP_C_PENDING )
+ continue;
+
if( connections[i].c_struct_state == SLAP_C_UNINITIALIZED ) {
assert( connections[i].c_conn_state == SLAP_C_INVALID );
assert( connections[i].c_sb == 0 );
break;
}
}
+ ldap_pvt_thread_mutex_unlock( &connections_mutex );
}
#endif
{
unsigned long id;
Connection *c;
+ int doinit = 0;
assert( connections != NULL );
assert( s >= 0 );
#ifndef HAVE_WINSOCK
assert( s < dtblsize );
-#endif
-
- ldap_pvt_thread_mutex_lock( MCA_GET_CONN_MUTEX(s) );
-
-#ifndef HAVE_WINSOCK
- assert( MCA_conn_check( s ) );
- c = MCA_GET_CONNECTION(s);
+ c = &connections[s];
+ if( c->c_struct_state == SLAP_C_UNINITIALIZED ) {
+ doinit = 1;
+ } else {
+ assert( c->c_struct_state == SLAP_C_UNUSED );
+ }
#else
{
ber_socket_t i;
c = NULL;
+ ldap_pvt_thread_mutex_lock( &connections_mutex );
for( i=0; i < dtblsize; i++) {
ber_socket_t sd;
+ if ( connections[i].c_struct_state == SLAP_C_PENDING )
+ continue;
+
if( connections[i].c_struct_state == SLAP_C_UNINITIALIZED ) {
assert( connections[i].c_sb == 0 );
c = &connections[i];
+ c->c_struct_state = SLAP_C_PENDING;
+ doinit = 1;
break;
}
if( connections[i].c_struct_state == SLAP_C_UNUSED ) {
assert( sd == AC_SOCKET_INVALID );
c = &connections[i];
+ c->c_struct_state = SLAP_C_PENDING;
break;
}
assert( connections[i].c_conn_state != SLAP_C_INVALID );
assert( sd != AC_SOCKET_INVALID );
}
+ ldap_pvt_thread_mutex_unlock( &connections_mutex );
if( c == NULL ) {
Debug( LDAP_DEBUG_ANY,
"connection_init(%d): connection table full "
"(%d/%d)\n", s, i, dtblsize);
- ldap_pvt_thread_mutex_unlock( &connections_mutex );
return -1;
}
}
#endif
- assert( c != NULL );
-
- if( c->c_struct_state == SLAP_C_UNINITIALIZED ) {
+ if( doinit ) {
c->c_send_ldap_result = slap_send_ldap_result;
c->c_send_search_entry = slap_send_search_entry;
c->c_send_search_reference = slap_send_search_reference;
slapi_int_create_object_extensions( SLAPI_X_EXT_CONNECTION, c );
}
#endif
-
- c->c_struct_state = SLAP_C_UNUSED;
}
ldap_pvt_thread_mutex_lock( &c->c_mutex );
- assert( c->c_struct_state == SLAP_C_UNUSED );
assert( BER_BVISNULL( &c->c_authmech ) );
assert( BER_BVISNULL( &c->c_dn ) );
assert( BER_BVISNULL( &c->c_ndn ) );
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 );
- ldap_pvt_thread_mutex_unlock( MCA_GET_CONN_MUTEX(s) );
return 0;
}
slapd_add_internal( s, 1 );
ldap_pvt_thread_mutex_unlock( &c->c_mutex );
- ldap_pvt_thread_mutex_unlock( MCA_GET_CONN_MUTEX(s) );
backend_connection_init(c);
static void
connection_destroy( Connection *c )
{
- /* note: connections_mutex should be locked by caller */
ber_socket_t sd;
unsigned long connid;
const char *close_reason;
+ Sockbuf *sb;
assert( connections != NULL );
assert( c != NULL );
connid = c->c_connid;
close_reason = c->c_close_reason;
+ ldap_pvt_thread_mutex_lock( &connections_mutex );
+ c->c_struct_state = SLAP_C_PENDING;
+ ldap_pvt_thread_mutex_unlock( &connections_mutex );
+
backend_connection_destroy(c);
c->c_protocol = 0;
c->c_currentber = NULL;
}
- ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_GET_FD, &sd );
- slapd_sd_lock();
- ber_sockbuf_free( c->c_sb );
- if ( sd != AC_SOCKET_INVALID ) {
- slapd_remove( sd, 1, 0, 1 );
- Statslog( LDAP_DEBUG_STATS, (close_reason
- ? "conn=%lu fd=%ld closed (%s)\n"
- : "conn=%lu fd=%ld closed\n"),
- connid, (long) sd, close_reason, 0, 0 );
- } else {
- slapd_sd_unlock();
+#ifdef LDAP_SLAPI
+ /* call destructors, then constructors; avoids unnecessary allocation */
+ if ( slapi_plugins_used ) {
+ slapi_int_clear_object_extensions( SLAPI_X_EXT_CONNECTION, c );
}
+#endif
- c->c_sb = ber_sockbuf_alloc( );
+ c->c_conn_state = SLAP_C_INVALID;
+ c->c_struct_state = SLAP_C_UNUSED;
+ c->c_close_reason = "?"; /* should never be needed */
+ sb = c->c_sb;
+ c->c_sb = ber_sockbuf_alloc( );
{
ber_len_t max = sockbuf_max_incoming;
ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_SET_MAX_INCOMING, &max );
}
- c->c_conn_state = SLAP_C_INVALID;
- c->c_struct_state = SLAP_C_UNUSED;
- c->c_close_reason = "?"; /* should never be needed */
+ ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, &sd );
+ slapd_sd_lock();
-#ifdef LDAP_SLAPI
- /* call destructors, then constructors; avoids unnecessary allocation */
- if ( slapi_plugins_used ) {
- slapi_int_clear_object_extensions( SLAPI_X_EXT_CONNECTION, c );
+ ber_sockbuf_free( sb );
+
+ /* c must be fully reset by this point; when we call slapd_remove
+ * it may get immediately reused by a new connection.
+ */
+ if ( sd != AC_SOCKET_INVALID ) {
+ slapd_remove( sd, 1, 0, 1 );
+
+ Statslog( LDAP_DEBUG_STATS, (close_reason
+ ? "conn=%lu fd=%ld closed (%s)\n"
+ : "conn=%lu fd=%ld closed\n"),
+ connid, (long) sd, close_reason, 0, 0 );
+ } else {
+ slapd_sd_unlock();
}
-#endif
}
int connection_state_closing( Connection *c )
c->c_close_reason = why;
/* don't listen on this port anymore */
- slapd_clr_read( sd, 1 );
+ slapd_clr_read( sd, 0 );
/* abandon active operations */
connection_abandon( c );
slapd_clr_write( sd, 1 );
if ( c->c_writewaiter ) {
ldap_pvt_thread_cond_signal( &c->c_write_cv );
- ldap_pvt_thread_mutex_unlock( &c->c_mutex );
- ldap_pvt_thread_yield();
- ldap_pvt_thread_mutex_lock( &c->c_mutex );
}
} else if( why == NULL && c->c_close_reason == conn_lost_str ) {
assert( c->c_struct_state == SLAP_C_USED );
assert( c->c_conn_state == SLAP_C_CLOSING );
- /* note: connections_mutex and c_mutex should be locked by caller */
+ /* note: c_mutex should be locked by caller */
ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_GET_FD, &sd );
if( !LDAP_STAILQ_EMPTY(&c->c_ops) ) {
Connection* connection_first( ber_socket_t *index )
{
-#ifdef SLAP_MULTI_CONN_ARRAY
- int conn_array_id;
-#endif
-
assert( connections != NULL );
assert( index != NULL );
-#ifdef SLAP_MULTI_CONN_ARRAY
- for ( conn_array_id = 0;
- conn_array_id < NUM_CONNECTION_ARRAY;
- conn_array_id++ )
- {
- ldap_pvt_thread_mutex_lock( &connections_mutex[ conn_array_id ] );
- }
-#else
ldap_pvt_thread_mutex_lock( &connections_mutex );
-#endif
-
- *index = 0;
-
- return connection_next(NULL, index);
-}
-
-Connection* connection_next( Connection *c, ber_socket_t *index )
-#ifdef SLAP_MULTI_CONN_ARRAY
-{
- Connection* conn;
-
- assert( connections != NULL );
- assert( index != NULL );
- assert( *index >= 0 && *index <= dtblsize );
-
- if( c != NULL ) ldap_pvt_thread_mutex_unlock( &c->c_mutex );
-
- c = NULL;
-
- for(; *index < dtblsize; (*index)++) {
- assert( MCA_conn_check( *index ) );
- conn = MCA_GET_CONNECTION(*index);
- if( conn->c_struct_state == SLAP_C_UNINITIALIZED ) {
- assert( conn->c_conn_state == SLAP_C_INVALID );
-#ifndef HAVE_WINSOCK
- continue;
-#else
+ for( *index = 0; *index < dtblsize; (*index)++) {
+ if( connections[*index].c_struct_state != SLAP_C_UNINITIALIZED ) {
break;
-#endif
}
-
- if( conn->c_struct_state == SLAP_C_USED ) {
- assert( conn->c_conn_state != SLAP_C_INVALID );
- c = conn;
- (*index)++;
- break;
- }
-
- assert( conn->c_struct_state == SLAP_C_UNUSED );
- assert( conn->c_conn_state == SLAP_C_INVALID );
}
+ ldap_pvt_thread_mutex_unlock( &connections_mutex );
- if( c != NULL ) ldap_pvt_thread_mutex_lock( &c->c_mutex );
-
- return c;
-
+ return connection_next(NULL, index);
}
-#else
+
+Connection* connection_next( Connection *c, ber_socket_t *index )
{
assert( connections != NULL );
assert( index != NULL );
c = NULL;
+ ldap_pvt_thread_mutex_lock( &connections_mutex );
for(; *index < dtblsize; (*index)++) {
if( connections[*index].c_struct_state == SLAP_C_UNINITIALIZED ) {
assert( connections[*index].c_conn_state == SLAP_C_INVALID );
-#ifndef HAVE_WINSOCK
- continue;
-#else
break;
-#endif
}
if( connections[*index].c_struct_state == SLAP_C_USED ) {
}
if( c != NULL ) ldap_pvt_thread_mutex_lock( &c->c_mutex );
+ ldap_pvt_thread_mutex_unlock( &connections_mutex );
return c;
}
-#endif
void connection_done( Connection *c )
{
-#ifdef SLAP_MULTI_CONN_ARRAY
- int conn_array_id;
-#endif
-
assert( connections != NULL );
if( c != NULL ) ldap_pvt_thread_mutex_unlock( &c->c_mutex );
-
-#ifdef SLAP_MULTI_CONN_ARRAY
- for ( conn_array_id = 0;
- conn_array_id < NUM_CONNECTION_ARRAY;
- conn_array_id++ )
- {
- ldap_pvt_thread_mutex_unlock( &connections_mutex[ conn_array_id ] );
- }
-#else
- ldap_pvt_thread_mutex_unlock( &connections_mutex );
-#endif
}
/*
ldap_pvt_thread_mutex_unlock( &slap_counters.sc_ops_mutex );
op->o_threadctx = ctx;
+ op->o_tid = ldap_pvt_thread_pool_tid( ctx );
switch ( tag ) {
case LDAP_REQ_BIND:
assert( connections != NULL );
- ldap_pvt_thread_mutex_lock( MCA_GET_CONN_MUTEX(s) );
-
/* get (locked) connection */
c = connection_get( s );
"connection_read(%ld): no connection!\n",
(long) s, 0, 0 );
- ldap_pvt_thread_mutex_unlock( MCA_GET_CONN_MUTEX(s) );
return -1;
}
Debug( LDAP_DEBUG_TRACE,
"connection_read(%d): closing, ignoring input for id=%lu\n",
s, c->c_connid, 0 );
-
-#ifdef SLAP_LIGHTWEIGHT_DISPATCHER
- slapd_set_read( s, 1 );
-#endif
connection_return( c );
- ldap_pvt_thread_mutex_unlock( MCA_GET_CONN_MUTEX(s) );
return 0;
}
c->c_clientfunc, c->c_clientarg );
#endif
connection_return( c );
- ldap_pvt_thread_mutex_unlock( MCA_GET_CONN_MUTEX(s) );
return 0;
}
s, rc, c->c_connid );
c->c_needs_tls_accept = 0;
- /* connections_mutex and c_mutex are locked */
+ /* c_mutex is locked */
connection_closing( c, "TLS negotiation failure" );
-
-#if 0
- {
- struct timeval tv;
- fd_set rfd;
- /* Drain input before close, to allow SSL error codes
- * to propagate to client. */
- FD_ZERO(&rfd);
- FD_SET(s, &rfd);
- for (rc=1; rc>0;) {
- tv.tv_sec = 1;
- tv.tv_usec = 0;
- rc = select(s+1, &rfd, NULL, NULL, &tv);
- if (rc == 1) {
- ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_DRAIN, NULL);
- }
- }
- }
-#endif
-
connection_close( c );
connection_return( c );
- ldap_pvt_thread_mutex_unlock( MCA_GET_CONN_MUTEX(s) );
return 0;
} else if ( rc == 0 ) {
}
/* if success and data is ready, fall thru to data input loop */
- if( rc != 0 ||
- !ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_DATA_READY, NULL ) )
+ if( !ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_DATA_READY, NULL ) )
{
#ifdef SLAP_LIGHTWEIGHT_DISPATCHER
slapd_set_read( s, 1 );
#endif
connection_return( c );
- ldap_pvt_thread_mutex_unlock( MCA_GET_CONN_MUTEX(s) );
return 0;
}
}
#endif
connection_return( c );
- ldap_pvt_thread_mutex_unlock( MCA_GET_CONN_MUTEX(s) );
return 0;
}
"error=%d id=%lu, closing\n",
s, rc, c->c_connid );
- /* connections_mutex and c_mutex are locked */
+ /* c_mutex is locked */
connection_closing( c, "SASL layer install failure" );
connection_close( c );
connection_return( c );
- ldap_pvt_thread_mutex_unlock( MCA_GET_CONN_MUTEX(s) );
return 0;
}
}
#endif
if( rc < 0 ) {
- Debug( LDAP_DEBUG_TRACE,
+ Debug( LDAP_DEBUG_CONNS,
"connection_read(%d): input error=%d id=%lu, closing.\n",
s, rc, c->c_connid );
- /* connections_mutex and c_mutex are locked */
+ /* c_mutex is locked */
connection_closing( c, conn_lost_str );
connection_close( c );
connection_return( c );
- ldap_pvt_thread_mutex_unlock( MCA_GET_CONN_MUTEX(s) );
return 0;
}
#endif
connection_return( c );
- ldap_pvt_thread_mutex_unlock( MCA_GET_CONN_MUTEX(s) );
return 0;
}
Operation *op;
if( conn->c_conn_state == SLAP_C_CLOSING ) {
- int rc;
ber_socket_t sd;
ber_sockbuf_ctrl( conn->c_sb, LBER_SB_OPT_GET_FD, &sd );
- /* use trylock to avoid possible deadlock */
- rc = ldap_pvt_thread_mutex_trylock( MCA_GET_CONN_MUTEX( sd ) );
-
- if( rc ) {
- Debug( LDAP_DEBUG_TRACE,
- "connection_resched: reaquiring locks conn=%lu sd=%d\n",
- conn->c_connid, sd, 0 );
- /*
- * reaquire locks in the right order...
- * this may allow another thread to close this connection,
- * so recheck state below.
- */
- ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
- ldap_pvt_thread_mutex_lock( MCA_GET_CONN_MUTEX ( sd ) );
- ldap_pvt_thread_mutex_lock( &conn->c_mutex );
- }
-
- if( conn->c_conn_state != SLAP_C_CLOSING ) {
- Debug( LDAP_DEBUG_TRACE, "connection_resched: "
- "closed by other thread conn=%lu sd=%d\n",
- conn->c_connid, sd, 0 );
- } else {
- Debug( LDAP_DEBUG_TRACE, "connection_resched: "
- "attempting closing conn=%lu sd=%d\n",
- conn->c_connid, sd, 0 );
- connection_close( conn );
- }
-
- ldap_pvt_thread_mutex_unlock( MCA_GET_CONN_MUTEX( sd ) );
+ Debug( LDAP_DEBUG_TRACE, "connection_resched: "
+ "attempting closing conn=%lu sd=%d\n",
+ conn->c_connid, sd, 0 );
+ connection_close( conn );
return 0;
}
slapd_clr_write( s, 0 );
- ldap_pvt_thread_mutex_lock( MCA_GET_CONN_MUTEX( s ) );
-
c = connection_get( s );
if( c == NULL ) {
Debug( LDAP_DEBUG_ANY,
"connection_write(%ld): no connection!\n",
(long)s, 0, 0 );
- ldap_pvt_thread_mutex_unlock( MCA_GET_CONN_MUTEX( s ) );
return -1;
}
}
connection_return( c );
- ldap_pvt_thread_mutex_unlock( MCA_GET_CONN_MUTEX(s) );
return 0;
}
op->o_tmpmemctx = slap_sl_mem_create(SLAP_SLAB_SIZE, SLAP_SLAB_STACK, ctx);
op->o_tmpmfuncs = &slap_sl_mfuncs;
op->o_threadctx = ctx;
+ op->o_tid = ldap_pvt_thread_pool_tid( ctx );
op->o_conn = conn;
op->o_connid = op->o_conn->c_connid;
rs->sr_err = get_filter( op, ber, (Filter **)&(op->o_assertion),
&rs->sr_text);
+ (void) ber_free( ber, 1 );
if( rs->sr_err != LDAP_SUCCESS ) {
if( rs->sr_err == SLAPD_DISCONNECT ) {
rs->sr_err = LDAP_PROTOCOL_ERROR;
return LDAP_OTHER;
}
+ rs->sr_err = LDAP_SUCCESS;
+
siz = sizeof( AttributeName );
off = offsetof( AttributeName, an_name );
if ( ber_scanf( ber, "{M}", &an, &siz, off ) == LBER_ERROR ) {
rs->sr_text = "preread control: decoding error";
- return LDAP_PROTOCOL_ERROR;
+ rs->sr_err = LDAP_PROTOCOL_ERROR;
+ goto done;
}
for( i=0; i<siz; i++ ) {
- int rc = LDAP_SUCCESS;
const char *dummy = NULL;
an[i].an_desc = NULL;
an[i].an_oc = NULL;
an[i].an_oc_exclude = 0;
- rc = slap_bv2ad( &an[i].an_name, &an[i].an_desc, &dummy );
- if ( rc != LDAP_SUCCESS && ctrl->ldctl_iscritical ) {
+ rs->sr_err = slap_bv2ad( &an[i].an_name, &an[i].an_desc, &dummy );
+ if ( rs->sr_err != LDAP_SUCCESS && ctrl->ldctl_iscritical ) {
rs->sr_text = dummy
? dummy
: "postread control: unknown attributeType";
- return rc;
+ goto done;
}
}
op->o_preread_attrs = an;
- rs->sr_err = LDAP_SUCCESS;
- return LDAP_SUCCESS;
+done:
+ (void) ber_free( ber, 1 );
+ return rs->sr_err;
}
static int parsePostRead (
return LDAP_OTHER;
}
+ rs->sr_err = LDAP_SUCCESS;
siz = sizeof( AttributeName );
off = offsetof( AttributeName, an_name );
if ( ber_scanf( ber, "{M}", &an, &siz, off ) == LBER_ERROR ) {
rs->sr_text = "postread control: decoding error";
- return LDAP_PROTOCOL_ERROR;
+ rs->sr_err = LDAP_PROTOCOL_ERROR;
+ goto done;
}
for( i=0; i<siz; i++ ) {
- int rc = LDAP_SUCCESS;
const char *dummy = NULL;
an[i].an_desc = NULL;
an[i].an_oc = NULL;
an[i].an_oc_exclude = 0;
- rc = slap_bv2ad( &an[i].an_name, &an[i].an_desc, &dummy );
- if ( rc != LDAP_SUCCESS && ctrl->ldctl_iscritical ) {
+ rs->sr_err = slap_bv2ad( &an[i].an_name, &an[i].an_desc, &dummy );
+ if ( rs->sr_err != LDAP_SUCCESS && ctrl->ldctl_iscritical ) {
rs->sr_text = dummy
? dummy
: "postread control: unknown attributeType";
- return rc;
+ goto done;
}
}
op->o_postread_attrs = an;
- rs->sr_err = LDAP_SUCCESS;
- return LDAP_SUCCESS;
+done:
+ (void) ber_free( ber, 1 );
+ return rs->sr_err;
}
static int parseValuesReturnFilter (
rs->sr_err = get_vrFilter( op, ber,
(ValuesReturnFilter **)&(op->o_vrFilter), &rs->sr_text);
+ (void) ber_free( ber, 1 );
+
if( rs->sr_err != LDAP_SUCCESS ) {
if( rs->sr_err == SLAPD_DISCONNECT ) {
rs->sr_err = LDAP_PROTOCOL_ERROR;
return LDAP_OTHER;
}
- if ( (tag = ber_scanf( ber, "{i}", &search_flags )) == LBER_ERROR ) {
+ tag = ber_scanf( ber, "{i}", &search_flags );
+ (void) ber_free( ber, 1 );
+
+ if ( tag == LBER_ERROR ) {
rs->sr_text = "searchOptions control decoding error";
return LDAP_PROTOCOL_ERROR;
}
- (void) ber_free( ber, 1 );
-
if ( search_flags & LDAP_SEARCH_FLAG_DOMAIN_SCOPE ) {
if ( op->o_domain_scope != SLAP_CONTROL_NONE ) {
rs->sr_text = "searchOptions control specified multiple times "
static char** slapd_srvurls = NULL;
static SLPHandle slapd_hslp = 0;
int slapd_register_slp = 0;
+char *slapd_slp_attrs = NULL;
+
+static SLPError slapd_slp_cookie;
void slapd_slp_init( const char* urls ) {
int i;
+ SLPError err;
slapd_srvurls = ldap_str2charray( urls, " " );
}
/* open the SLP handle */
- SLPOpen( "en", 0, &slapd_hslp );
+ err = SLPOpen( "en", 0, &slapd_hslp );
+
+ if (err != SLP_OK) {
+ Debug( LDAP_DEBUG_CONNS, "daemon: SLPOpen() failed with %ld\n",
+ (long)err, 0, 0 );
+ }
}
void slapd_slp_deinit() {
SLPError errcode,
void* cookie )
{
- /* empty report */
+ /* return the error code in the cookie */
+ *(SLPError*)cookie = errcode;
}
void slapd_slp_reg() {
int i;
+ SLPError err;
if( slapd_srvurls == NULL ) return;
strncmp( slapd_srvurls[i], LDAPS_SRVTYPE_PREFIX,
sizeof( LDAPS_SRVTYPE_PREFIX ) - 1 ) == 0 )
{
- SLPReg( slapd_hslp,
+ err = SLPReg( slapd_hslp,
slapd_srvurls[i],
SLP_LIFETIME_MAXIMUM,
"ldap",
- "",
- 1,
+ (slapd_slp_attrs) ? slapd_slp_attrs : "",
+ SLP_TRUE,
slapd_slp_regreport,
- NULL );
+ &slapd_slp_cookie );
+
+ if (err != SLP_OK || slapd_slp_cookie != SLP_OK) {
+ Debug( LDAP_DEBUG_CONNS,
+ "daemon: SLPReg(%s) failed with %ld, cookie = %ld\n",
+ slapd_srvurls[i], (long)err, (long)slapd_slp_cookie );
+ }
}
}
}
void slapd_slp_dereg() {
int i;
+ SLPError err;
if( slapd_srvurls == NULL ) return;
for( i=0; slapd_srvurls[i] != NULL; i++ ) {
- SLPDereg( slapd_hslp,
+ err = SLPDereg( slapd_hslp,
slapd_srvurls[i],
slapd_slp_regreport,
- NULL );
+ &slapd_slp_cookie );
+
+ if (err != SLP_OK || slapd_slp_cookie != SLP_OK) {
+ Debug( LDAP_DEBUG_CONNS,
+ "daemon: SLPDereg(%s) failed with %ld, cookie = %ld\n",
+ slapd_srvurls[i], (long)err, (long)slapd_slp_cookie );
+ }
}
}
#endif /* HAVE_SLP */
sap[i]->sa_family = AF_INET;
((struct sockaddr_in *)sap[i])->sin_port = htons(port);
AC_MEMCPY( &((struct sockaddr_in *)sap[i])->sin_addr,
- he ? he->h_addr_list[i] : &in, sizeof(struct in_addr) );
+ he ? (struct in_addr *)he->h_addr_list[i] : &in,
+ sizeof(struct in_addr) );
}
sap[i] = NULL;
#endif
struct timeval tv;
struct timeval *tvp;
- struct timeval *cat;
+ struct timeval cat;
time_t tdelta = 1;
struct re_s* rtask;
now = slap_get_time();
ldap_pvt_thread_mutex_lock( &slapd_rq.rq_mutex );
rtask = ldap_pvt_runqueue_next_sched( &slapd_rq, &cat );
- while ( cat && cat->tv_sec && cat->tv_sec <= now ) {
+ while ( rtask && cat.tv_sec && cat.tv_sec <= now ) {
if ( ldap_pvt_runqueue_isrunning( &slapd_rq, rtask )) {
ldap_pvt_runqueue_resched( &slapd_rq, rtask, 0 );
} else {
ldap_pvt_runqueue_resched( &slapd_rq, rtask, 0 );
ldap_pvt_thread_mutex_unlock( &slapd_rq.rq_mutex );
ldap_pvt_thread_pool_submit( &connection_pool,
- rtask->routine, (void *) rtask );
+ rtask->routine, (void *) rtask );
ldap_pvt_thread_mutex_lock( &slapd_rq.rq_mutex );
}
rtask = ldap_pvt_runqueue_next_sched( &slapd_rq, &cat );
}
ldap_pvt_thread_mutex_unlock( &slapd_rq.rq_mutex );
- if ( cat && cat->tv_sec ) {
- time_t diff = difftime( cat->tv_sec, now );
+ if ( rtask && cat.tv_sec ) {
+ time_t diff = difftime( cat.tv_sec, now );
if ( diff == 0 ) diff = tdelta;
if ( tvp == NULL || diff < tv.tv_sec ) {
tv.tv_sec = diff;
#endif
for (i=0; i<ns; i++) {
- int rc = 1, fd, waswrite = 0;
+ int rc = 1, fd;
if ( SLAP_EVENT_IS_LISTENER(i) ) {
#ifdef SLAP_LIGHTWEIGHT_DISPATCHER
"daemon: write active on %d\n",
fd, 0, 0 );
- waswrite = 1;
+ SLAP_EVENT_CLR_WRITE( i );
/*
* NOTE: it is possible that the connection was closed
continue;
}
}
- /* If event is a read or an error */
- if( SLAP_EVENT_IS_READ( i ) || !waswrite ) {
+ /* If event is a read */
+ if( SLAP_EVENT_IS_READ( i )) {
Debug( LDAP_DEBUG_CONNS,
"daemon: read active on %d\n",
fd, 0, 0 );
+ SLAP_EVENT_CLR_READ( i );
#ifdef SLAP_LIGHTWEIGHT_DISPATCHER
connection_read_activate( fd );
#else
*/
connection_read( fd );
#endif
+ } else {
+ Debug( LDAP_DEBUG_CONNS,
+ "daemon: hangup on %d\n", fd, 0, 0 );
}
}
}
#define AVA_PRIVATE( ava ) ( ( AttributeDescription * )(ava)->la_private )
+int slap_DN_strict = SLAP_AD_NOINSERT;
+
static int
LDAPRDN_validate( LDAPRDN rdn )
{
if ( rc != LDAP_SUCCESS ) {
rc = slap_bv2undef_ad( &ava->la_attr,
&ad, &text,
- SLAP_AD_PROXIED|SLAP_AD_NOINSERT );
+ SLAP_AD_PROXIED|slap_DN_strict );
if ( rc != LDAP_SUCCESS ) {
return LDAP_INVALID_SYNTAX;
}
if ( rc != LDAP_SUCCESS ) {
rc = slap_bv2undef_ad( &ava->la_attr,
&ad, &text,
- SLAP_AD_PROXIED|SLAP_AD_NOINSERT );
+ SLAP_AD_PROXIED|slap_DN_strict );
if ( rc != LDAP_SUCCESS ) {
return LDAP_INVALID_SYNTAX;
}
if ( rc != LDAP_SUCCESS ) {
rc = slap_bv2undef_ad( &ava->la_attr,
&ad, &text,
- SLAP_AD_PROXIED|SLAP_AD_NOINSERT );
+ SLAP_AD_PROXIED|slap_DN_strict );
if ( rc != LDAP_SUCCESS ) {
return LDAP_INVALID_SYNTAX;
}
if ( rc != LDAP_SUCCESS ) {
rc = slap_bv2undef_ad( &ava->la_attr,
&ad, &text,
- SLAP_AD_PROXIED|SLAP_AD_NOINSERT );
+ SLAP_AD_PROXIED|slap_DN_strict );
if ( rc != LDAP_SUCCESS ) {
return LDAP_INVALID_SYNTAX;
}
switch ( slapMode & SLAP_MODE ) {
case SLAP_SERVER_MODE:
- ldap_pvt_thread_pool_init( &connection_pool,
- connection_pool_max, 0);
/* FALLTHRU */
case SLAP_TOOL_MODE:
slap_name = name;
+ ldap_pvt_thread_pool_init( &connection_pool,
+ connection_pool_max, 0);
ldap_pvt_thread_mutex_init( &entry2str_mutex );
ldap_pvt_thread_mutex_init( &replog_mutex );
return -1;
}
+ if ( rid_ptr[ STRLENOF( "rid=" ) ] == '-' ) {
+ return -1;
+ }
cookie->rid = strtoul( &rid_ptr[ STRLENOF( "rid=" ) ], &next, 10 );
if ( next == &rid_ptr[ STRLENOF( "rid=" ) ] || ( next[ 0 ] != ',' && next[ 0 ] != '\0' ) ) {
return -1;
{
#ifdef HAVE_SLP
/* NULL is default */
- if ( val == NULL || strcasecmp( val, "on" ) == 0 ) {
+ if ( val == NULL || *val == '(' || strcasecmp( val, "on" ) == 0 ) {
slapd_register_slp = 1;
+ slapd_slp_attrs = (val != NULL && *val == '(') ? val : NULL;
} else if ( strcasecmp( val, "off" ) == 0 ) {
slapd_register_slp = 0;
void *oh_arg;
const char *oh_usage;
} option_helpers[] = {
- { BER_BVC("slp"), slapd_opt_slp, NULL, "slp[={on|off}] enable/disable SLP" },
+ { BER_BVC("slp"), slapd_opt_slp, NULL, "slp[={on|off|(attrs)}] enable/disable SLP using (attrs)" },
{ BER_BVNULL, 0, NULL, NULL }
};
+#if defined(LDAP_DEBUG) && defined(LDAP_SYSLOG)
#ifdef LOG_LOCAL4
static int
parse_syslog_user( const char *arg, int *syslogUser )
return 0;
}
+#endif /* LDAP_DEBUG && LDAP_SYSLOG */
int
parse_debug_unknowns( char **unknowns, int *levelp )
#ifdef HAVE_CHROOT
"r:"
#endif
-#ifdef LDAP_SYSLOG
+#if defined(LDAP_DEBUG) && defined(LDAP_SYSLOG)
"S:"
-#endif
#ifdef LOG_LOCAL4
"l:"
#endif
+#endif
#if defined(HAVE_SETUID) && defined(HAVE_SETGID)
"u:g:"
#endif
goto destroy;
}
break;
-#endif /* LDAP_DEBUG && LDAP_SYSLOG */
#ifdef LOG_LOCAL4
case 'l': /* set syslog local user */
}
break;
#endif
+#endif /* LDAP_DEBUG && LDAP_SYSLOG */
#ifdef HAVE_CHROOT
case 'r':
SRCS = overlays.c \
accesslog.c \
auditlog.c \
+ constraint.c \
dds.c \
denyop.c \
dyngroup.c \
auditlog.la : auditlog.lo
$(LTLINK_MOD) -module -o $@ auditlog.lo version.lo $(LINK_LIBS)
+constraint.la : constraint.lo
+ $(LTLINK_MOD) -module -o $@ constraint.lo version.lo $(LINK_LIBS)
+
dds.la : dds.lo
$(LTLINK_MOD) -module -o $@ dds.lo version.lo $(LINK_LIBS)
#define LOG_OP_ALL (LOG_OP_READS|LOG_OP_WRITES|LOG_OP_SESSION| \
LOG_OP_EXTENDED|LOG_OP_UNKNOWN)
+typedef struct log_attr {
+ struct log_attr *next;
+ AttributeDescription *attr;
+} log_attr;
+
typedef struct log_info {
BackendDB *li_db;
slap_mask_t li_ops;
int li_age;
int li_cycle;
struct re_s *li_task;
+ Filter *li_oldf;
+ Entry *li_old;
+ log_attr *li_oldattrs;
int li_success;
- ldap_pvt_thread_mutex_t li_op_mutex;
+ ldap_pvt_thread_rmutex_t li_op_rmutex;
ldap_pvt_thread_mutex_t li_log_mutex;
} log_info;
LOG_DB = 1,
LOG_OPS,
LOG_PURGE,
- LOG_SUCCESS
+ LOG_SUCCESS,
+ LOG_OLD,
+ LOG_OLDATTR
};
static ConfigTable log_cfats[] = {
log_cf_gen, "( OLcfgOvAt:4.4 NAME 'olcAccessLogSuccess' "
"DESC 'Log successful ops only' "
"SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL },
+ { "logold", "filter", 2, 2, 0, ARG_MAGIC|LOG_OLD,
+ log_cf_gen, "( OLcfgOvAt:4.5 NAME 'olcAccessLogOld' "
+ "DESC 'Log old values when modifying entries matching the filter' "
+ "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
+ { "logoldattr", "attrs", 2, 0, 0, ARG_MAGIC|LOG_OLDATTR,
+ log_cf_gen, "( OLcfgOvAt:4.6 NAME 'olcAccessLogOldAttr' "
+ "DESC 'Log old values of these attributes even if unmodified' "
+ "SYNTAX OMsDirectoryString )", NULL, NULL },
{ NULL }
};
"DESC 'Access log configuration' "
"SUP olcOverlayConfig "
"MUST olcAccessLogDB "
- "MAY ( olcAccessLogOps $ olcAccessLogPurge $ olcAccessLogSuccess ) )",
+ "MAY ( olcAccessLogOps $ olcAccessLogPurge $ olcAccessLogSuccess $ "
+ "olcAccessLogOld $ olcAccessLogOldAttr ) )",
Cft_Overlay, log_cfats },
{ NULL }
};
"DESC 'ModRDN operation' "
"SUP auditWriteObject STRUCTURAL "
"MUST ( reqNewRDN $ reqDeleteOldRDN ) "
- "MAY reqNewSuperior )", &log_ocs[LOG_EN_MODRDN] },
+ "MAY ( reqNewSuperior $ reqOld ) )", &log_ocs[LOG_EN_MODRDN] },
{ "( " LOG_SCHEMA_OC ".11 NAME 'auditSearch' "
"DESC 'Search operation' "
"SUP auditReadObject STRUCTURAL "
return -1;
t1 *= 24;
gotdays = 1;
- } else if ( *endptr != ':' ) {
- /* No valid delimiter found, fail */
- return -1;
+ agestr = endptr + 1;
+ } else {
+ if ( agestr[2] != ':' ) {
+ /* No valid delimiter found, fail */
+ return -1;
+ }
+ t1 *= 60;
+ agestr += 3;
}
- agestr += 3;
t2 = atoi( agestr );
-
- /* if there's a delimiter, it can only be a colon */
- if ( agestr[2] && agestr[2] != ':' )
- return -1;
-
- /* If we're at the end of the string, and we started with days,
- * fail because we expected to find minutes too.
- */
- if ( gotdays && !agestr[2] )
- return -1;
-
- t1 *= 60;
t1 += t2;
- if ( !agestr[2] )
- return t1 * 60;
+ if ( agestr[2] ) {
+ /* if there's a delimiter, it can only be a colon */
+ if ( agestr[2] != ':' )
+ return -1;
+ } else {
+ /* If we're at the end of the string, and we started with days,
+ * fail because we expected to find minutes too.
+ */
+ return gotdays ? -1 : t1 * 60;
+ }
agestr += 3;
t2 = atoi( agestr );
t1 *= 60;
t1 += t2;
- t1 *= 60;
if ( agestr[2] ) {
agestr += 3;
if ( agestr[2] )
return -1;
+ t1 *= 60;
t1 += atoi( agestr );
+ } else if ( gotdays ) {
+ /* only got days+hh:mm */
+ t1 *= 60;
}
return t1;
}
age /= 60;
mm = age % 60;
age /= 60;
- hh = age % 60;
+ hh = age % 24;
age /= 24;
dd = age;
else
rc = 1;
break;
+ case LOG_OLD:
+ if ( li->li_oldf ) {
+ filter2bv( li->li_oldf, &agebv );
+ value_add_one( &c->rvalue_vals, &agebv );
+ }
+ else
+ rc = 1;
+ break;
+ case LOG_OLDATTR:
+ if ( li->li_oldattrs ) {
+ log_attr *la;
+
+ for ( la = li->li_oldattrs; la; la=la->next )
+ value_add_one( &c->rvalue_vals, &la->attr->ad_cname );
+ }
+ else
+ rc = 1;
+ break;
}
break;
case LDAP_MOD_DELETE:
case LOG_SUCCESS:
li->li_success = 0;
break;
+ case LOG_OLD:
+ if ( li->li_oldf ) {
+ filter_free( li->li_oldf );
+ li->li_oldf = NULL;
+ }
+ break;
+ case LOG_OLDATTR:
+ if ( c->valx < 0 ) {
+ log_attr *la, *ln;
+
+ for ( la = li->li_oldattrs; la; la = ln ) {
+ ln = la->next;
+ ch_free( la );
+ }
+ } else {
+ log_attr *la, **lp;
+ int i;
+
+ for ( lp = &li->li_oldattrs, i=0; i < c->valx; i++ ) {
+ la = *lp;
+ lp = &la->next;
+ }
+ *lp = la->next;
+ ch_free( la );
+ }
+ break;
}
break;
default:
case LOG_SUCCESS:
li->li_success = c->value_int;
break;
+ case LOG_OLD:
+ li->li_oldf = str2filter( c->argv[1] );
+ if ( !li->li_oldf ) {
+ sprintf( c->msg, "bad filter!" );
+ rc = 1;
+ }
+ break;
+ case LOG_OLDATTR: {
+ int i;
+ AttributeDescription *ad;
+ const char *text;
+
+ for ( i=1; i< c->argc; i++ ) {
+ ad = NULL;
+ if ( slap_str2ad( c->argv[i], &ad, &text ) == LDAP_SUCCESS ) {
+ log_attr *la = ch_malloc( sizeof( log_attr ));
+ la->attr = ad;
+ la->next = li->li_oldattrs;
+ li->li_oldattrs = la;
+ } else {
+ sprintf( c->msg, "%s: %s", c->argv[i], text );
+ rc = ARG_BAD_CONF;
+ break;
+ }
+ }
+ }
+ break;
}
break;
}
static struct berval simple = BER_BVC("SIMPLE");
+static void accesslog_val2val(AttributeDescription *ad, struct berval *val,
+ char c_op, struct berval *dst) {
+ char *ptr;
+
+ dst->bv_len = ad->ad_cname.bv_len + val->bv_len + 2;
+ if ( c_op ) dst->bv_len++;
+
+ dst->bv_val = ch_malloc( dst->bv_len+1 );
+
+ ptr = lutil_strcopy( dst->bv_val, ad->ad_cname.bv_val );
+ *ptr++ = ':';
+ if ( c_op )
+ *ptr++ = c_op;
+ *ptr++ = ' ';
+ AC_MEMCPY( ptr, val->bv_val, val->bv_len );
+ dst->bv_val[dst->bv_len] = '\0';
+}
+
static int accesslog_response(Operation *op, SlapReply *rs) {
slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
log_info *li = on->on_bi.bi_private;
int i;
int logop;
slap_verbmasks *lo;
- Entry *e;
+ Entry *e = NULL, *old = NULL;
char timebuf[LDAP_LUTIL_GENTIME_BUFSIZE+8];
struct berval bv;
char *ptr;
if ( lo->mask & LOG_OP_WRITES ) {
ldap_pvt_thread_mutex_lock( &li->li_log_mutex );
- ldap_pvt_thread_mutex_unlock( &li->li_op_mutex );
+ old = li->li_old;
+ li->li_old = NULL;
+ ldap_pvt_thread_rmutex_unlock( &li->li_op_rmutex, op->o_tid );
}
if ( li->li_success && rs->sr_err != LDAP_SUCCESS )
switch( logop ) {
case LOG_EN_ADD:
+ case LOG_EN_DELETE: {
+ char c_op;
+ Entry *e2;
+
+ if ( logop == LOG_EN_ADD ) {
+ e2 = op->ora_e;
+ c_op = '+';
+ } else {
+ if ( !old )
+ break;
+ e2 = old;
+ c_op = 0;
+ }
/* count all the vals */
i = 0;
- for ( a=op->ora_e->e_attrs; a; a=a->a_next ) {
+ for ( a=e2->e_attrs; a; a=a->a_next ) {
if ( a->a_vals ) {
for (b=a->a_vals; !BER_BVISNULL( b ); b++) {
i++;
}
vals = ch_malloc( (i+1) * sizeof( struct berval ));
i = 0;
- for ( a=op->ora_e->e_attrs; a; a=a->a_next ) {
+ for ( a=e2->e_attrs; a; a=a->a_next ) {
if ( a->a_vals ) {
for (b=a->a_vals; !BER_BVISNULL( b ); b++,i++) {
- vals[i].bv_len = a->a_desc->ad_cname.bv_len + b->bv_len +3;
- vals[i].bv_val = ch_malloc( vals[i].bv_len+1 );
- ptr = lutil_strcopy( vals[i].bv_val,
- a->a_desc->ad_cname.bv_val );
- *ptr++ = ':';
- *ptr++ = '+';
- *ptr++ = ' ';
- AC_MEMCPY( ptr, b->bv_val, b->bv_len );
- vals[i].bv_val[vals[i].bv_len] = '\0';
+ accesslog_val2val( a->a_desc, b, c_op, &vals[i] );
}
}
}
vals[i].bv_val = NULL;
vals[i].bv_len = 0;
- a = attr_alloc( ad_reqMod );
+ a = attr_alloc( logop == LOG_EN_ADD ? ad_reqMod : ad_reqOld );
a->a_vals = vals;
a->a_nvals = vals;
last_attr->a_next = a;
break;
-
- case LOG_EN_DELETE:
- /* needs nothing else */
- break;
+ }
case LOG_EN_MODIFY:
/* count all the mods */
}
vals = ch_malloc( (i+1) * sizeof( struct berval ));
i = 0;
+
+ /* init flags on old entry */
+ if ( old ) {
+ for ( a=old->e_attrs; a; a=a->a_next ) {
+ log_attr *la;
+ a->a_flags = 0;
+
+ /* look for attrs that are always logged */
+ for ( la=li->li_oldattrs; la; la=la->next )
+ if ( a->a_desc == la->attr )
+ a->a_flags = 1;
+ }
+ }
+
for ( m=op->orm_modlist; m; m=m->sml_next ) {
+ /* Mark this attribute as modified */
+ if ( old ) {
+ a = attr_find( old->e_attrs, m->sml_desc );
+ if ( a )
+ a->a_flags = 1;
+ }
if ( m->sml_values ) {
for (b=m->sml_values; !BER_BVISNULL( b ); b++,i++) {
char c_op;
- vals[i].bv_len = m->sml_desc->ad_cname.bv_len + b->bv_len +3;
- vals[i].bv_val = ch_malloc( vals[i].bv_len+1 );
- ptr = lutil_strcopy( vals[i].bv_val,
- m->sml_desc->ad_cname.bv_val );
- *ptr++ = ':';
+
switch( m->sml_op ) {
case LDAP_MOD_ADD: c_op = '+'; break;
case LDAP_MOD_DELETE: c_op = '-'; break;
*/
default: c_op = '?'; break;
}
- *ptr++ = c_op;
- *ptr++ = ' ';
- AC_MEMCPY( ptr, b->bv_val, b->bv_len );
- vals[i].bv_val[vals[i].bv_len] = '\0';
+ accesslog_val2val( m->sml_desc, b, c_op, &vals[i] );
}
} else if ( m->sml_op == LDAP_MOD_DELETE ) {
vals[i].bv_len = m->sml_desc->ad_cname.bv_len + 2;
a->a_vals = vals;
a->a_nvals = vals;
last_attr->a_next = a;
+
+ if ( old ) {
+ last_attr = a;
+ /* count all the vals */
+ i = 0;
+ for ( a=old->e_attrs; a; a=a->a_next ) {
+ if ( a->a_vals && a->a_flags ) {
+ for (b=a->a_vals; !BER_BVISNULL( b ); b++) {
+ i++;
+ }
+ }
+ }
+ vals = ch_malloc( (i+1) * sizeof( struct berval ));
+ i = 0;
+ for ( a=old->e_attrs; a; a=a->a_next ) {
+ if ( a->a_vals && a->a_flags ) {
+ for (b=a->a_vals; !BER_BVISNULL( b ); b++,i++) {
+ accesslog_val2val( a->a_desc, b, 0, &vals[i] );
+ }
+ }
+ }
+ vals[i].bv_val = NULL;
+ vals[i].bv_len = 0;
+ a = attr_alloc( ad_reqOld );
+ a->a_vals = vals;
+ a->a_nvals = vals;
+ last_attr->a_next = a;
+ }
break;
case LOG_EN_MODRDN:
+ if ( old ) {
+ /* count all the vals */
+ i = 0;
+ for ( a=old->e_attrs; a; a=a->a_next ) {
+ log_attr *la;
+
+ /* look for attrs that are always logged */
+ for ( la=li->li_oldattrs; la; la=la->next ) {
+ if ( a->a_desc == la->attr ) {
+ for (b=a->a_vals; !BER_BVISNULL( b ); b++) {
+ i++;
+ }
+ }
+ }
+ }
+ vals = ch_malloc( (i+1) * sizeof( struct berval ));
+ i = 0;
+ for ( a=old->e_attrs; a; a=a->a_next ) {
+ log_attr *la;
+ for ( la=li->li_oldattrs; la; la=la->next ) {
+ if ( a->a_desc == la->attr ) {
+ for (b=a->a_vals; !BER_BVISNULL( b ); b++,i++) {
+ accesslog_val2val( a->a_desc, b, 0, &vals[i] );
+ }
+ }
+ }
+ }
+ vals[i].bv_val = NULL;
+ vals[i].bv_len = 0;
+ a = attr_alloc( ad_reqOld );
+ a->a_vals = vals;
+ a->a_nvals = vals;
+ last_attr->a_next = a;
+ }
attr_merge_one( e, ad_reqNewRDN, &op->orr_newrdn, &op->orr_nnewrdn );
attr_merge_one( e, ad_reqDeleteOldRDN, op->orr_deleteoldrdn ?
(struct berval *)&slap_true_bv : (struct berval *)&slap_false_bv,
}
op2.o_bd->be_add( &op2, &rs2 );
- entry_free( e );
done:
- ldap_pvt_thread_mutex_unlock( &li->li_log_mutex );
+ if ( lo->mask & LOG_OP_WRITES )
+ ldap_pvt_thread_mutex_unlock( &li->li_log_mutex );
+ if ( e ) entry_free( e );
+ if ( old ) entry_free( old );
return SLAP_CB_CONTINUE;
}
log_info *li = on->on_bi.bi_private;
if ( li->li_ops & LOG_OP_WRITES ) {
- /* FIXME: this needs to be a recursive mutex to allow
- * overlays like refint to keep working.
- */
- ldap_pvt_thread_mutex_lock( &li->li_op_mutex );
+ ldap_pvt_thread_rmutex_lock( &li->li_op_rmutex, op->o_tid );
+ if ( li->li_oldf && ( op->o_tag == LDAP_REQ_DELETE ||
+ op->o_tag == LDAP_REQ_MODIFY ||
+ ( op->o_tag == LDAP_REQ_MODRDN && li->li_oldattrs ))) {
+ int rc;
+ Entry *e;
+
+ op->o_bd->bd_info = on->on_info->oi_orig;
+ rc = be_entry_get_rw( op, &op->o_req_ndn, NULL, NULL, 0, &e );
+ if ( e ) {
+ if ( test_filter( op, e, li->li_oldf ) == LDAP_COMPARE_TRUE )
+ li->li_old = entry_dup( e );
+ be_entry_release_rw( op, e, 0 );
+ }
+ op->o_bd->bd_info = (BackendInfo *)on;
+ }
}
return SLAP_CB_CONTINUE;
}
log_info *li = ch_calloc(1, sizeof(log_info));
on->on_bi.bi_private = li;
- ldap_pvt_thread_mutex_init( &li->li_op_mutex );
+ ldap_pvt_thread_rmutex_init( &li->li_op_rmutex );
ldap_pvt_thread_mutex_init( &li->li_log_mutex );
return 0;
}
log_info *li = on->on_bi.bi_private;
ldap_pvt_thread_mutex_destroy( &li->li_log_mutex );
- ldap_pvt_thread_mutex_destroy( &li->li_op_mutex );
+ ldap_pvt_thread_rmutex_destroy( &li->li_op_rmutex );
free( li );
return LDAP_SUCCESS;
}
FILE *f;
Attribute *a;
Modifications *m;
- struct berval *b;
- char *what, *suffix, *who = NULL;
+ struct berval *b, *who = NULL;
+ char *what, *suffix;
long stamp = slap_get_time();
int i;
what = "add";
for(a = op->ora_e->e_attrs; a; a = a->a_next)
if( a->a_desc == slap_schema.si_ad_modifiersName ) {
- who = a->a_vals[0].bv_val;
+ who = &a->a_vals[0];
break;
}
break;
if( m->sml_desc == slap_schema.si_ad_modifiersName &&
( m->sml_op == LDAP_MOD_ADD ||
m->sml_op == LDAP_MOD_REPLACE )) {
- who = m->sml_values[0].bv_val;
+ who = &m->sml_values[0];
break;
}
break;
** note: this means requestor's dn when modifiersName is null
*/
if ( !who )
- who = op->o_dn.bv_val;
+ who = &op->o_dn;
ldap_pvt_thread_mutex_lock(&ad->ad_mutex);
if((f = fopen(ad->ad_logfile, "a")) == NULL) {
return SLAP_CB_CONTINUE;
}
- fprintf(f, "# %s %ld %s%s%s\ndn: %s\nchangetype: %s\n",
- what, stamp, suffix, who ? " " : "", who ? who : "",
+ fprintf(f, "# %s %ld %s%s%s\n",
+ what, stamp, suffix, who ? " " : "", who ? who->bv_val : "");
+
+ if ( !who || !dn_match( who, &op->o_conn->c_dn ))
+ fprintf(f, "# realdn: %s\n", op->o_conn->c_dn.bv_val ? op->o_conn->c_dn.bv_val :
+ "<empty>" );
+
+ fprintf(f, "dn: %s\nchangetype: %s\n",
op->o_req_dn.bv_val, what);
switch(op->o_tag) {
--- /dev/null
+/* constraint.c - Overlay to constrain attributes to certain values */
+/*
+ *
+ * Copyright 2003-2004 Hewlett-Packard Company
+ * 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>.
+ */
+/*
+ * Author: Neil Dunbar <neil.dunbar@hp.com>
+ */
+#include "portable.h"
+
+#ifdef SLAPD_OVER_CONSTRAINT
+
+#include <stdio.h>
+
+#include <ac/string.h>
+#include <ac/socket.h>
+#include <ac/regex.h>
+
+#include "slap.h"
+
+/*
+ * This overlay limits the values which can be placed into an
+ * attribute, over and above the limits placed by the schema.
+ *
+ * It traps only LDAP adds and modify commands (and only seeks to
+ * control the add and modify value mods of a modify)
+ */
+
+/*
+ * Linked list of attribute constraints which we should enforce.
+ * This is probably a sub optimal structure - some form of sorted
+ * array would be better if the number of attributes contrained is
+ * likely to be much bigger than 4 or 5. We stick with a list for
+ * the moment.
+ */
+typedef struct constraint {
+ struct constraint *ap_next;
+ AttributeDescription *ap;
+ regex_t *re;
+} constraint;
+
+static int
+constraint_violation( constraint *c, struct berval *bv )
+{
+ if ((!c) || (!bv)) return 0;
+
+ if ((c->re) &&
+ (regexec(c->re, bv->bv_val, 0, NULL, 0) == REG_NOMATCH))
+
+ return 1; /* regular expression violation */
+
+ return 0;
+}
+
+static char *
+print_message( const char *fmt, AttributeDescription *a )
+{
+ char *ret;
+ int sz;
+
+ sz = strlen(fmt) + a->ad_cname.bv_len + 1;
+ ret = ch_malloc(sz);
+ snprintf( ret, sz, fmt, a->ad_cname.bv_val );
+ return ret;
+}
+
+static int
+constraint_add( Operation *op, SlapReply *rs )
+{
+ slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
+ Attribute *a;
+ constraint *c = on->on_bi.bi_private, *cp;
+ BerVarray b = NULL;
+ int i;
+ const char *rsv = "add breaks regular expression constraint on %s";
+ char *msg;
+
+ if ((a = op->ora_e->e_attrs) == NULL) {
+ op->o_bd->bd_info = (BackendInfo *)(on->on_info);
+ send_ldap_error(op, rs, LDAP_INVALID_SYNTAX,
+ "constraint_add() got null op.ora_e.e_attrs");
+ return(rs->sr_err);
+ }
+
+ for(; a; a = a->a_next ) {
+ /* we don't constrain operational attributes */
+
+ if (is_at_operational(a->a_desc->ad_type)) continue;
+
+ for(cp = c; cp; cp = cp->ap_next) {
+ if (cp->ap != a->a_desc) continue;
+ if ((b = a->a_vals) == NULL) continue;
+
+ for(i=0; b[i].bv_val; i++) {
+ int cv = constraint_violation( cp, &b[i]);
+
+ if (cv) {
+ /* regex violation */
+ op->o_bd->bd_info = (BackendInfo *)(on->on_info);
+ msg = print_message( rsv, a->a_desc );
+ send_ldap_error(op, rs, LDAP_CONSTRAINT_VIOLATION, msg );
+ ch_free(msg);
+ return (rs->sr_err);
+ }
+ }
+ }
+ }
+ /* Default is to just fall through to the normal processing */
+ return SLAP_CB_CONTINUE;
+}
+
+static int
+constraint_modify( Operation *op, SlapReply *rs )
+{
+ slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
+ constraint *c = on->on_bi.bi_private, *cp;
+ Modifications *m;
+ BerVarray b = NULL;
+ int i;
+ const char *rsv = "modify breaks regular expression constraint on %s";
+ char *msg;
+
+ if ((m = op->orm_modlist) == NULL) {
+ op->o_bd->bd_info = (BackendInfo *)(on->on_info);
+ send_ldap_error(op, rs, LDAP_INVALID_SYNTAX,
+ "constraint_modify() got null orm_modlist");
+ return(rs->sr_err);
+ }
+
+ for(;m; m = m->sml_next) {
+ if (is_at_operational( m->sml_desc->ad_type )) continue;
+ if ((( m->sml_op & LDAP_MOD_OP ) != LDAP_MOD_ADD) &&
+ (( m->sml_op & LDAP_MOD_OP ) != LDAP_MOD_REPLACE))
+ continue;
+ /* we only care about ADD and REPLACE modifications */
+ if ((( b = m->sml_values ) == NULL ) || (b[0].bv_val == NULL))
+ continue;
+
+ for(cp = c; cp; cp = cp->ap_next) {
+ if (cp->ap != m->sml_desc) continue;
+
+ for(i=0; b[i].bv_val; i++) {
+ int cv = constraint_violation( cp, &b[i]);
+
+ if (cv) {
+ /* regex violation */
+ op->o_bd->bd_info = (BackendInfo *)(on->on_info);
+ msg = print_message( rsv, m->sml_desc );
+ send_ldap_error(op, rs, LDAP_CONSTRAINT_VIOLATION, msg );
+ ch_free(msg);
+ return (rs->sr_err);
+ }
+ }
+ }
+ }
+
+ return SLAP_CB_CONTINUE;
+}
+
+static int constraint_config(
+ BackendDB *be,
+ const char *fname,
+ int lineno,
+ int argc,
+ char **argv
+ )
+{
+ slap_overinst *on = (slap_overinst *) be->bd_info;
+ constraint ap = { NULL, NULL, NULL }, *a2 = NULL;
+ regmatch_t rm[2];
+
+ if ( strcasecmp( argv[0], "constraint_attribute" ) == 0 ) {
+ const char *text;
+
+ if ( argc != 4 ) {
+ Debug( LDAP_DEBUG_ANY, "%s: line %d: "
+ "wrong number of parameters in"
+ "\"constraint_attribute <attribute> <constraint> <constraint_value>\" line.\n",
+ fname, lineno, 0 );
+ return( 1 );
+ }
+ if ( slap_str2ad( argv[1], &ap.ap, &text ) ) {
+ Debug( LDAP_DEBUG_ANY, "%s: line %d: "
+ "attribute description unknown \"constraint_attribute\" line: %s.\n",
+ fname, lineno, text );
+ return( 1 );
+ }
+
+ if ( strcasecmp( argv[2], "regex" ) == 0) {
+ int err;
+
+ ap.re = ch_malloc( sizeof(regex_t) );
+ if ((err = regcomp( ap.re, argv[3], REG_EXTENDED )) != 0) {
+ const char *fmt = "%s: line %d: Illegal regular expression \"%s\": Error %s\n";
+ char errmsg[1024], *msg;
+ int i, l, msgsize;
+
+ msgsize = regerror( err, ap.re, errmsg, sizeof(errmsg) );
+ msgsize += strlen(fmt) + strlen(argv[3]) + strlen(fname);
+ for(l=lineno; l>0; l/=10, msgsize++);
+ msgsize++;
+
+ msg = ch_malloc( msgsize + 1 );
+ snprintf( msg, msgsize, fmt, fname, lineno, argv[3], errmsg );
+ ch_free(ap.re);
+ Debug( LDAP_DEBUG_ANY, msg, 0, 0, 0);
+ ch_free(msg);
+ ap.re = NULL;
+ return(1);
+ }
+ } else
+ Debug( LDAP_DEBUG_ANY, "%s: line %d: "
+ "Unknown constraint type: %s",
+ fname, lineno, argv[2] );
+
+
+ a2 = ch_malloc( sizeof(constraint) );
+ a2->ap_next = on->on_bi.bi_private;
+ a2->ap = ap.ap;
+ a2->re = ap.re;
+ on->on_bi.bi_private = a2;
+ } else {
+ return SLAP_CONF_UNKNOWN;
+ }
+
+ return 0;
+}
+
+static int
+constraint_close(
+ BackendDB *be
+ )
+{
+ slap_overinst *on = (slap_overinst *) be->bd_info;
+ constraint *ap, *a2;
+
+ for ( ap = on->on_bi.bi_private; ap; ap = a2 ) {
+ a2 = ap->ap_next;
+ if (ap->re) {
+ regfree( ap->re );
+ ch_free( ap->re );
+ }
+
+ ch_free( ap );
+ }
+
+ return 0;
+}
+
+static slap_overinst constraint_ovl;
+
+/* This overlay is set up for dynamic loading via moduleload. For static
+ * configuration, you'll need to arrange for the slap_overinst to be
+ * initialized and registered by some other function inside slapd.
+ */
+
+#if SLAPD_OVER_CONSTRAINT == SLAPD_MOD_DYNAMIC
+static
+#endif
+int
+constraint_initialize( void ) {
+ constraint_ovl.on_bi.bi_type = "constraint";
+ constraint_ovl.on_bi.bi_db_config = constraint_config;
+ constraint_ovl.on_bi.bi_db_close = constraint_close;
+ constraint_ovl.on_bi.bi_op_add = constraint_add;
+ constraint_ovl.on_bi.bi_op_modify = constraint_modify;
+
+ return overlay_register( &constraint_ovl );
+}
+
+#if SLAPD_OVER_CONSTRAINT == SLAPD_MOD_DYNAMIC
+int init_module(int argc, char *argv[]) {
+ return constraint_initialize();
+}
+#endif
+
+#endif /* defined(SLAPD_OVER_CONSTRAINT) */
+
op->o_tmpfree( o.ors_filterstr.bv_val, op->o_tmpmemctx );
lud->lud_filter = NULL;
}
- if ( lud ) {
- ldap_free_urldesc( lud );
- }
+ ldap_free_urldesc( lud );
}
rs->sr_entry = e;
* used by all instances
*/
typedef struct pw_conn {
- int restricted; /* TRUE if connection is restricted */
+ struct berval dn; /* DN of restricted user */
} pw_conn;
static pw_conn *pwcons;
return 0;
}
-#define PPOLICY_WARNING 0xa0L
-#define PPOLICY_ERROR 0xa1L
+/* IMPLICIT TAGS, all context-specific */
+#define PPOLICY_WARNING 0xa0L /* constructed + 0 */
+#define PPOLICY_ERROR 0x81L /* primitive + 1 */
-#define PPOLICY_EXPIRE 0xa0L
-#define PPOLICY_GRACE 0xa1L
+#define PPOLICY_EXPIRE 0x80L /* primitive + 0 */
+#define PPOLICY_GRACE 0x81L /* primitive + 1 */
static LDAPControl *
create_passcontrol( int exptime, int grace, LDAPPasswordPolicyError err )
* that we are disallowed from doing anything
* other than change password.
*/
- pwcons[op->o_conn->c_conn_idx].restricted = 1;
+ ber_dupbv( &pwcons[op->o_conn->c_conn_idx].dn,
+ &op->o_conn->c_ndn );
ppb->pErr = PP_changeAfterReset;
slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
/* Reset lockout status on all Bind requests */
- pwcons[op->o_conn->c_conn_idx].restricted = 0;
+ if ( !BER_BVISEMPTY( &pwcons[op->o_conn->c_conn_idx].dn )) {
+ ch_free( pwcons[op->o_conn->c_conn_idx].dn.bv_val );
+ BER_BVZERO( &pwcons[op->o_conn->c_conn_idx].dn );
+ }
/* Root bypasses policy */
if ( !be_isroot_dn( op->o_bd, &op->o_req_ndn )) {
return SLAP_CB_CONTINUE;
}
-/* Reset the restricted flag for the next session on this connection */
+/* Reset the restricted info for the next session on this connection */
static int
ppolicy_connection_destroy( BackendDB *bd, Connection *conn )
{
- pwcons[conn->c_conn_idx].restricted = 0;
+ if ( !BER_BVISEMPTY( &pwcons[conn->c_conn_idx].dn )) {
+ ch_free( pwcons[conn->c_conn_idx].dn.bv_val );
+ BER_BVZERO( &pwcons[conn->c_conn_idx].dn );
+ }
return SLAP_CB_CONTINUE;
}
send_ctrl = 1;
}
- if ( op->o_conn && pwcons[op->o_conn->c_conn_idx].restricted ) {
+ if ( op->o_conn && !BER_BVISEMPTY( &pwcons[op->o_conn->c_conn_idx].dn )) {
+ /* if the current authcDN doesn't match the one we recorded,
+ * then an intervening Bind has succeeded and the restriction
+ * no longer applies. (ITS#4516)
+ */
+ if ( !dn_match( &op->o_conn->c_ndn,
+ &pwcons[op->o_conn->c_conn_idx].dn )) {
+ ch_free( pwcons[op->o_conn->c_conn_idx].dn.bv_val );
+ BER_BVZERO( &pwcons[op->o_conn->c_conn_idx].dn );
+ return SLAP_CB_CONTINUE;
+ }
+
Debug( LDAP_DEBUG_TRACE,
"connection restricted to password changing only\n", 0, 0, 0);
if ( send_ctrl ) {
}
}
- if (pwcons[op->o_conn->c_conn_idx].restricted && !mod_pw_only) {
- Debug( LDAP_DEBUG_TRACE,
- "connection restricted to password changing only\n", 0, 0, 0 );
- rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
- rs->sr_text = "Operations are restricted to bind/unbind/abandon/StartTLS/modify password";
- pErr = PP_changeAfterReset;
- goto return_results;
+ if (!BER_BVISEMPTY( &pwcons[op->o_conn->c_conn_idx].dn ) && !mod_pw_only ) {
+ if ( dn_match( &op->o_conn->c_ndn,
+ &pwcons[op->o_conn->c_conn_idx].dn )) {
+ Debug( LDAP_DEBUG_TRACE,
+ "connection restricted to password changing only\n", 0, 0, 0 );
+ rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
+ rs->sr_text = "Operations are restricted to bind/unbind/abandon/StartTLS/modify password";
+ pErr = PP_changeAfterReset;
+ goto return_results;
+ } else {
+ ch_free( pwcons[op->o_conn->c_conn_idx].dn.bv_val );
+ BER_BVZERO( &pwcons[op->o_conn->c_conn_idx].dn );
+ }
}
/*
#include <ac/socket.h>
#include "slap.h"
+#include "config.h"
static slap_overinst refint;
BerValue nnothing; /* normalized nothingness */
} refint_data;
+enum {
+ REFINT_ATTRS = 1,
+ REFINT_NOTHING
+};
+
+static ConfigDriver refint_cf_gen;
+
+static ConfigTable refintcfg[] = {
+ { "refint_attributes", "attribute...", 2, 0, 0,
+ ARG_MAGIC|REFINT_ATTRS, refint_cf_gen,
+ "( OLcfgOvAt:11.1 NAME 'olcRefintAttribute' "
+ "DESC 'Attributes for referential integrity' "
+ "SYNTAX OMsDirectoryString )", NULL, NULL },
+ { "refint_nothing", "string", 2, 2, 0,
+ ARG_DN|ARG_MAGIC|REFINT_NOTHING, refint_cf_gen,
+ "( OLcfgOvAt:11.2 NAME 'olcRefintNothing' "
+ "DESC 'Replacement DN to supply when needed' "
+ "SYNTAX OMsDN SINGLE-VALUE )", NULL, NULL },
+ { NULL, NULL, 0, 0, 0, ARG_IGNORED }
+};
+
+static ConfigOCs refintocs[] = {
+ { "( OLcfgOvOc:11.1 "
+ "NAME 'olcRefintConfig' "
+ "DESC 'Referential integrity configuration' "
+ "SUP olcOverlayConfig "
+ "MAY ( olcRefintAttribute $ olcRefintNothing ) )",
+ Cft_Overlay, refintcfg },
+ { NULL, 0, NULL }
+};
+
+static int
+refint_cf_gen(ConfigArgs *c)
+{
+ slap_overinst *on = (slap_overinst *)c->bi;
+ refint_data *dd = (refint_data *)on->on_bi.bi_private;
+ refint_attrs *ip, *pip, **pipp = NULL;
+ AttributeDescription *ad;
+ const char *text;
+ int rc = ARG_BAD_CONF;
+ int i;
+
+ switch ( c->op ) {
+ case SLAP_CONFIG_EMIT:
+ switch ( c->type ) {
+ case REFINT_ATTRS:
+ ip = dd->attrs;
+ while ( ip ) {
+ value_add_one( &c->rvalue_vals,
+ &ip->attr->ad_cname );
+ ip = ip->next;
+ }
+ rc = 0;
+ break;
+ case REFINT_NOTHING:
+ if ( !BER_BVISEMPTY( &dd->nothing )) {
+ rc = value_add_one( &c->rvalue_vals,
+ &dd->nothing );
+ if ( rc ) return rc;
+ rc = value_add_one( &c->rvalue_nvals,
+ &dd->nnothing );
+ return rc;
+ }
+ rc = 0;
+ break;
+ default:
+ abort ();
+ }
+ break;
+ case LDAP_MOD_DELETE:
+ switch ( c->type ) {
+ case REFINT_ATTRS:
+ pipp = &dd->attrs;
+ if ( c->valx < 0 ) {
+ ip = *pipp;
+ *pipp = NULL;
+ while ( ip ) {
+ pip = ip;
+ ip = ip->next;
+ ch_free ( pip );
+ }
+ } else {
+ /* delete from linked list */
+ for ( i=0; i < c->valx; ++i ) {
+ pipp = &(*pipp)->next;
+ }
+ ip = *pipp;
+ *pipp = (*pipp)->next;
+
+ /* AttributeDescriptions are global so
+ * shouldn't be freed here... */
+ ch_free ( ip );
+ }
+ rc = 0;
+ break;
+ case REFINT_NOTHING:
+ if ( dd->nothing.bv_val )
+ ber_memfree ( dd->nothing.bv_val );
+ if ( dd->nnothing.bv_val )
+ ber_memfree ( dd->nnothing.bv_val );
+ dd->nothing.bv_len = 0;
+ dd->nnothing.bv_len = 0;
+ rc = 0;
+ break;
+ default:
+ abort ();
+ }
+ break;
+ case SLAP_CONFIG_ADD:
+ /* fallthrough to LDAP_MOD_ADD */
+ case LDAP_MOD_ADD:
+ switch ( c->type ) {
+ case REFINT_ATTRS:
+ rc = 0;
+ for ( i=1; i < c->argc; ++i ) {
+ ad = NULL;
+ if ( slap_str2ad ( c->argv[i], &ad, &text )
+ == LDAP_SUCCESS) {
+ ip = ch_malloc (
+ sizeof ( refint_attrs ) );
+ ip->attr = ad;
+ ip->next = dd->attrs;
+ dd->attrs = ip;
+ } else {
+ Debug ( LDAP_DEBUG_CONFIG,
+ "refint add: <%s>: %s\n",
+ c->argv[i], text, NULL );
+ strncpy ( c->msg,
+ text,
+ SLAP_TEXT_BUFLEN-1 );
+ c->msg[SLAP_TEXT_BUFLEN-1] = '\0';
+ rc = ARG_BAD_CONF;
+ }
+ }
+ break;
+ case REFINT_NOTHING:
+ if ( dd->nothing.bv_val )
+ ber_memfree ( dd->nothing.bv_val );
+ if ( dd->nnothing.bv_val )
+ ber_memfree ( dd->nnothing.bv_val );
+ dd->nothing = c->value_dn;
+ dd->nnothing = c->value_ndn;
+ rc = 0;
+ break;
+ default:
+ abort ();
+ }
+ break;
+ default:
+ abort ();
+ }
+
+ return rc;
+}
+
/*
** allocate new refint_data;
-** initialize, copy basedn;
** store in on_bi.bi_private;
**
*/
)
{
slap_overinst *on = (slap_overinst *)be->bd_info;
- refint_data *id = ch_malloc(sizeof(refint_data));
+ refint_data *id = ch_calloc(1,sizeof(refint_data));
id->message = "_init";
- id->attrs = NULL;
- id->newdn.bv_val = NULL;
- id->nothing.bv_val = NULL;
- id->nnothing.bv_val = NULL;
- ber_dupbv( &id->dn, &be->be_nsuffix[0] );
on->on_bi.bi_private = id;
return(0);
}
-
-/*
-** if command = attributes:
-** foreach argument:
-** convert to attribute;
-** add to configured attribute list;
-** elseif command = basedn:
-** set our basedn to argument;
-**
-*/
-
static int
-refint_config(
- BackendDB *be,
- const char *fname,
- int lineno,
- int argc,
- char **argv
+refint_db_destroy(
+ BackendDB *be
)
{
- slap_overinst *on = (slap_overinst *) be->bd_info;
- refint_data *id = on->on_bi.bi_private;
- refint_attrs *ip;
- const char *text;
- AttributeDescription *ad;
- BerValue dn;
- int i;
+ slap_overinst *on = (slap_overinst *)be->bd_info;
- if(!strcasecmp(*argv, "refint_attributes")) {
- for(i = 1; i < argc; i++) {
- for(ip = id->attrs; ip; ip = ip->next)
- if(!strcmp(argv[i], ip->attr->ad_cname.bv_val)) {
- Debug(LDAP_DEBUG_ANY,
- "%s: line %d: duplicate attribute <s>, ignored\n",
- fname, lineno, argv[i]);
- continue;
- }
- ad = NULL;
- if(slap_str2ad(argv[i], &ad, &text) != LDAP_SUCCESS) {
- Debug(LDAP_DEBUG_ANY,
- "%s: line %d: bad attribute <%s>, ignored\n",
- fname, lineno, text);
- continue; /* XXX */
- } else if(ad->ad_next) {
- Debug(LDAP_DEBUG_ANY,
- "%s: line %d: multiple attributes match <%s>, ignored\n",
- fname, lineno, argv[i]);
- continue;
- }
- ip = ch_malloc(sizeof(refint_attrs));
- ip->attr = ad;
- ip->next = id->attrs;
- id->attrs = ip;
- Debug(LDAP_DEBUG_ANY, "%s: line %d: new attribute <%s>\n",
- fname, lineno, argv[i]);
- }
- } else if(!strcasecmp(*argv, "refint_base")) {
- /* XXX only one basedn (yet) - need validate argument! */
- if(id->dn.bv_val) ch_free(id->dn.bv_val);
- ber_str2bv( argv[1], 0, 0, &dn );
- Debug(LDAP_DEBUG_ANY, "%s: line %d: new baseDN <%s>\n",
- fname, lineno, argv[1]);
- if(dnNormalize(0, NULL, NULL, &dn, &id->dn, NULL)) {
- Debug(LDAP_DEBUG_ANY, "%s: line %d: bad baseDN!\n", fname, lineno, 0);
- return(1);
- }
- } else if(!strcasecmp(*argv, "refint_nothing")) {
- if(id->nothing.bv_val) ch_free(id->nothing.bv_val);
- if(id->nnothing.bv_val) ch_free(id->nnothing.bv_val);
- ber_str2bv( argv[1], 0, 1, &id->nothing );
- if(dnNormalize(0, NULL, NULL, &id->nothing, &id->nnothing, NULL)) {
- Debug(LDAP_DEBUG_ANY, "%s: line %d: bad nothingDN!\n", fname, lineno, 0);
- return(1);
- }
- Debug(LDAP_DEBUG_ANY, "%s: line %d: new nothingDN<%s>\n",
- fname, lineno, argv[1]);
- } else {
- return(SLAP_CONF_UNKNOWN);
+ if ( on->on_bi.bi_private ) {
+ ch_free( on->on_bi.bi_private );
+ on->on_bi.bi_private = NULL;
}
-
- id->message = "_config";
return(0);
}
-
/*
-** nothing really happens here;
+** initialize, copy basedn if not already set
**
*/
slap_overinst *on = (slap_overinst *)be->bd_info;
refint_data *id = on->on_bi.bi_private;
id->message = "_open";
+
+ if ( BER_BVISNULL( &id->dn )) {
+ if ( BER_BVISNULL( &be->be_nsuffix[0] ))
+ return -1;
+ ber_dupbv( &id->dn, &be->be_nsuffix[0] );
+ }
return(0);
}
ch_free(id->nothing.bv_val);
ch_free(id->nnothing.bv_val);
- on->on_bi.bi_private = NULL; /* XXX */
-
- ch_free(id);
+ memset( id, 0, sizeof(*id));
return(0);
}
*/
int refint_initialize() {
+ int rc;
/* statically declared just after the #includes at top */
refint.on_bi.bi_type = "refint";
refint.on_bi.bi_db_init = refint_db_init;
- refint.on_bi.bi_db_config = refint_config;
+ refint.on_bi.bi_db_destroy = refint_db_destroy;
refint.on_bi.bi_db_open = refint_open;
refint.on_bi.bi_db_close = refint_close;
refint.on_response = refint_response;
+ refint.on_bi.bi_cf_ocs = refintocs;
+ rc = config_register_schema ( refintcfg, refintocs );
+ if ( rc ) return rc;
+
return(overlay_register(&refint));
}
/* sleep time */
a = attr_find( e->e_attrs, ad_errSleepTime );
- if ( a != NULL ) {
+ if ( a != NULL && a->a_nvals[ 0 ].bv_val[ 0 ] != '-' ) {
int sleepTime;
sleepTime = strtoul( a->a_nvals[ 0 ].bv_val, &next, 0 );
}
+static int
+rwm_exop_passwd( Operation *op, SlapReply *rs )
+{
+ slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
+ int rc;
+
+ struct berval id = BER_BVNULL,
+ pwold = BER_BVNULL,
+ pwnew = BER_BVNULL;
+
+ if ( !BER_BVISNULL( &op->o_req_ndn ) ) {
+ return LDAP_SUCCESS;
+ }
+
+ if ( !SLAP_ISGLOBALOVERLAY( op->o_bd ) ) {
+ rs->sr_err = LDAP_OTHER;
+ return rs->sr_err;
+ }
+
+ rs->sr_err = slap_passwd_parse( op->ore_reqdata, &id,
+ &pwold, &pwnew, &rs->sr_text );
+ if ( rs->sr_err != LDAP_SUCCESS ) {
+ return rs->sr_err;
+ }
+
+ if ( !BER_BVISNULL( &id ) ) {
+ rs->sr_err = dnPrettyNormal( NULL, &id, &op->o_req_dn,
+ &op->o_req_ndn, op->o_tmpmemctx );
+ if ( rs->sr_err != LDAP_SUCCESS ) {
+ rs->sr_text = "Invalid DN";
+ return rs->sr_err;
+ }
+
+ } else {
+ ber_dupbv_x( &op->o_req_dn, &op->o_dn, op->o_tmpmemctx );
+ ber_dupbv_x( &op->o_req_ndn, &op->o_ndn, op->o_tmpmemctx );
+ }
+
+#ifdef ENABLE_REWRITE
+ rc = rwm_op_dn_massage( op, rs, "extendedDN" );
+#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, "extendedDN massage error" );
+ return -1;
+ }
+
+ /* TODO: re-encode the request */
+
+ return SLAP_CB_CONTINUE;
+}
+
+static struct exop {
+ struct berval oid;
+ BI_op_extended *extended;
+} exop_table[] = {
+ { BER_BVC(LDAP_EXOP_MODIFY_PASSWD), rwm_exop_passwd },
+ { BER_BVNULL, NULL }
+};
+
static int
rwm_extended( Operation *op, SlapReply *rs )
{
slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
int rc;
+ int i;
+
+ for ( i = 0; exop_table[i].extended != NULL; i++ ) {
+ if ( bvmatch( &exop_table[i].oid, &op->oq_extended.rs_reqoid ) )
+ {
+ rc = exop_table[i].extended( op, rs );
+ switch ( rc ) {
+ case LDAP_SUCCESS:
+ break;
+
+ case SLAP_CB_CONTINUE:
+ case SLAPD_ABANDON:
+ return rc;
+
+ default:
+ send_ldap_result( op, rs );
+ return rc;
+ }
+ break;
+ }
+ }
+
#ifdef ENABLE_REWRITE
rc = rwm_op_dn_massage( op, rs, "extendedDN" );
#else /* ! ENABLE_REWRITE */
/* enter with sl->sl_mutex locked, release before returning */
static void
syncprov_playlog( Operation *op, SlapReply *rs, sessionlog *sl,
- struct berval *oldcsn, struct berval *ctxcsn )
+ sync_control *srs, struct berval *ctxcsn )
{
slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
slog_entry *se;
int i, j, ndel, num, nmods, mmods;
+ char cbuf[LDAP_LUTIL_CSNSTR_BUFSIZE];
BerVarray uuids;
+ struct berval delcsn;
if ( !sl->sl_num ) {
ldap_pvt_thread_mutex_unlock( &sl->sl_mutex );
uuids = op->o_tmpalloc( (num+1) * sizeof( struct berval ) +
num * UUID_LEN, op->o_tmpmemctx );
-
uuids[0].bv_val = (char *)(uuids + num + 1);
+ delcsn.bv_len = 0;
+ delcsn.bv_val = cbuf;
+
/* Make a copy of the relevant UUIDs. Put the Deletes up front
* and everything else at the end. Do this first so we can
* unlock the list mutex.
*/
for ( se=sl->sl_head; se; se=se->se_next ) {
- if ( ber_bvcmp( &se->se_csn, oldcsn ) < 0 ) continue;
+ if ( ber_bvcmp( &se->se_csn, &srs->sr_state.ctxcsn ) <= 0 ) continue;
if ( ber_bvcmp( &se->se_csn, ctxcsn ) > 0 ) break;
if ( se->se_tag == LDAP_REQ_DELETE ) {
j = i;
i++;
+ AC_MEMCPY( cbuf, se->se_csn.bv_val, se->se_csn.bv_len );
+ delcsn.bv_len = se->se_csn.bv_len;
} else {
nmods++;
j = num - nmods;
fop.o_bd->bd_info = (BackendInfo *)on;
}
if ( ndel ) {
+ struct berval cookie;
+
+ slap_compose_sync_cookie( op, &cookie, &delcsn, srs->sr_state.rid );
uuids[ndel].bv_val = NULL;
- syncprov_sendinfo( op, rs, LDAP_TAG_SYNC_ID_SET, NULL, 0, uuids, 1 );
+ syncprov_sendinfo( op, rs, LDAP_TAG_SYNC_ID_SET, &cookie, 0, uuids, 1 );
+ op->o_tmpfree( cookie.bv_val, op->o_tmpmemctx );
}
+ op->o_tmpfree( uuids, op->o_tmpmemctx );
}
static int
}
if ( a ) {
/* Make sure entry is less than the snapshot'd contextCSN */
- if ( ber_bvcmp( &a->a_nvals[0], &ss->ss_ctxcsn ) > 0 )
+ if ( ber_bvcmp( &a->a_nvals[0], &ss->ss_ctxcsn ) > 0 ) {
+ Debug( LDAP_DEBUG_SYNC, "Entry %s CSN %s greater than snapshot %s\n",
+ rs->sr_entry->e_name.bv_val,
+ a->a_nvals[0].bv_val,
+ ss->ss_ctxcsn.bv_val );
return LDAP_SUCCESS;
+ }
/* Don't send the ctx entry twice */
if ( !BER_BVISNULL( &srs->sr_state.ctxcsn ) &&
- bvmatch( &a->a_nvals[0], &srs->sr_state.ctxcsn ) )
+ bvmatch( &a->a_nvals[0], &srs->sr_state.ctxcsn ) ) {
+ Debug( LDAP_DEBUG_SYNC, "Entry %s CSN %s matches ctx %s\n",
+ rs->sr_entry->e_name.bv_val,
+ a->a_nvals[0].bv_val,
+ srs->sr_state.ctxcsn.bv_val );
return LDAP_SUCCESS;
+ }
}
rs->sr_ctrls = op->o_tmpalloc( sizeof(LDAPControl *)*2,
op->o_tmpmemctx );
if ( ber_bvcmp( &srs->sr_state.ctxcsn, &sl->sl_mincsn ) >= 0 ) {
do_present = 0;
/* mutex is unlocked in playlog */
- syncprov_playlog( op, rs, sl, &srs->sr_state.ctxcsn, &ctxcsn );
+ syncprov_playlog( op, rs, sl, srs, &ctxcsn );
} else {
ldap_pvt_thread_mutex_unlock( &sl->sl_mutex );
}
#include <ac/socket.h>
#include "slap.h"
+#include "config.h"
static slap_overinst unique;
int count;
} unique_counter;
+enum {
+ UNIQUE_BASE = 1,
+ UNIQUE_IGNORE,
+ UNIQUE_ATTR,
+ UNIQUE_STRICT
+};
+
+static ConfigDriver unique_cf_gen;
+
+static ConfigTable uniquecfg[] = {
+ { "unique_base", "basedn", 2, 2, 0, ARG_DN|ARG_MAGIC|UNIQUE_BASE,
+ unique_cf_gen, "( OLcfgOvAt:10.1 NAME 'olcUniqueBase' "
+ "DESC 'Subtree for uniqueness searches' "
+ "SYNTAX OMsDN SINGLE-VALUE )", NULL, NULL },
+ { "unique_ignore", "attribute...", 2, 0, 0, ARG_MAGIC|UNIQUE_IGNORE,
+ unique_cf_gen, "( OLcfgOvAt:10.2 NAME 'olcUniqueIgnore' "
+ "DESC 'Attributes for which uniqueness shall not be enforced' "
+ "SYNTAX OMsDirectoryString )", NULL, NULL },
+ { "unique_attributes", "attribute...", 2, 0, 0, ARG_MAGIC|UNIQUE_ATTR,
+ unique_cf_gen, "( OLcfgOvAt:10.3 NAME 'olcUniqueAttribute' "
+ "DESC 'Attributes for which uniqueness shall be enforced' "
+ "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' "
+ "DESC 'Enforce uniqueness of null values' "
+ "SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL },
+ { NULL, NULL, 0, 0, 0, ARG_IGNORED }
+};
+
+static ConfigOCs uniqueocs[] = {
+ { "( OLcfgOvOc:10.1 "
+ "NAME 'olcUniqueConfig' "
+ "DESC 'Attribute value uniqueness configuration' "
+ "SUP olcOverlayConfig "
+ "MAY ( olcUniqueBase $ olcUniqueIgnore $ "
+ "olcUniqueAttribute $ olcUniqueStrict ) )",
+ Cft_Overlay, uniquecfg },
+ { NULL, 0, NULL }
+};
+
+static int
+unique_cf_gen( ConfigArgs *c )
+{
+ slap_overinst *on = (slap_overinst *)c->bi;
+ unique_data *ud = (unique_data *)on->on_bi.bi_private;
+ BackendDB *be = (BackendDB *)c->be;
+ unique_attrs *up, *pup, **pupp = NULL;
+ AttributeDescription *ad;
+ const char *text;
+ 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;
+ }
+ 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;
+ break;
+ case UNIQUE_STRICT:
+ /* handled via ARG_OFFSET */
+ /* fallthrough to default */
+ default:
+ abort ();
+ }
+ 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;
+ 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 );
+ }
+
+ } else {
+
+ /* delete from linked list */
+ for ( i=0; i < c->valx; ++i ) {
+ pupp = &(*pupp)->next;
+ }
+ up = *pupp;
+ *pupp = (*pupp)->next;
+
+ /* AttributeDescriptions are global so
+ * shouldn't be freed here... */
+ ch_free ( up );
+ }
+ rc = 0;
+ break;
+ case UNIQUE_STRICT:
+ /* handled via ARG_OFFSET */
+ /* fallthrough to default */
+ default:
+ abort ();
+ }
+ 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, "dn is not a suffix of backend base" );
+ Debug ( LDAP_DEBUG_CONFIG, "unique add: %s\n",
+ c->msg, NULL, NULL );
+ rc = ARG_BAD_CONF;
+ }
+ if ( ud->dn.bv_val ) ber_memfree ( ud->dn.bv_val );
+ ud->dn = c->value_ndn;
+ rc = 0;
+ 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 {
+ Debug ( LDAP_DEBUG_CONFIG,
+ "unique add: <%s>: %s\n",
+ c->argv[i], text, NULL );
+ strncpy ( c->msg,
+ text,
+ SLAP_TEXT_BUFLEN-1 );
+ c->msg[SLAP_TEXT_BUFLEN-1] = '\0';
+ rc = ARG_BAD_CONF;
+ }
+ }
+ break;
+ case UNIQUE_STRICT:
+ /* handled via ARG_OFFSET */
+ /* fallthrough to default */
+ default:
+ abort ();
+ }
+ break;
+ default:
+ abort ();
+ }
+
+ return rc;
+}
+
/*
** allocate new unique_data;
** initialize, copy basedn;
)
{
slap_overinst *on = (slap_overinst *)be->bd_info;
- unique_data *ud = ch_malloc(sizeof(unique_data));
+ unique_data *ud = ch_calloc(1,sizeof(unique_data));
/* Debug(LDAP_DEBUG_TRACE, "==> unique_init\n", 0, 0, 0); */
ud->message = "_init";
- ud->attrs = NULL;
- ud->ignore = NULL;
- ud->strict = 0;
-
- /* default to the base of our configured database */
- ber_dupbv(&ud->dn, &be->be_nsuffix[0]);
on->on_bi.bi_private = ud;
-
return 0;
}
-
-/*
-** if command = attributes:
-** foreach argument:
-** convert to attribute;
-** add to configured attribute list;
-** elseif command = base:
-** set our basedn to argument;
-** else complain about invalid directive;
-**
-*/
-
-static int unique_config(
- BackendDB *be,
- const char *fname,
- int lineno,
- int argc,
- char **argv
+static int unique_db_destroy(
+ BackendDB *be
)
{
- slap_overinst *on = (slap_overinst *) be->bd_info;
- unique_data *ud = on->on_bi.bi_private;
- unique_attrs *up;
- const char *text;
- AttributeDescription *ad;
- int i;
+ slap_overinst *on = (slap_overinst *)be->bd_info;
- ud->message = "_config";
- Debug(LDAP_DEBUG_TRACE, "==> unique_config\n", 0, 0, 0);
-
- if(!strcasecmp(*argv, "unique_attributes") ||
- !strcasecmp(*argv, "unique_ignore")) {
- for(i = 1; i < argc; i++) {
- for(up = ud->attrs; up; up = up->next)
- if(!strcmp(argv[i], up->attr->ad_cname.bv_val)) {
- Debug(LDAP_DEBUG_ANY,
- "%s: line %d: duplicate attribute <%s>, ignored\n",
- fname, lineno, argv[i]);
- continue;
- }
- ad = NULL;
- if(slap_str2ad(argv[i], &ad, &text) != LDAP_SUCCESS) {
- Debug(LDAP_DEBUG_ANY,
- "%s: line %d: bad attribute <%s>, ignored\n",
- fname, lineno, text);
- continue; /* XXX */
- } else if(ad->ad_next) {
- Debug(LDAP_DEBUG_ANY,
- "%s: line %d: multiple attributes match <%s>, ignored\n",
- fname, lineno, argv[i]);
- continue;
- }
- up = ch_malloc(sizeof(unique_attrs));
- up->attr = ad;
- if(!strcasecmp(*argv, "unique_ignore")) {
- up->next = ud->ignore;
- ud->ignore = up;
- } else {
- up->next = ud->attrs;
- ud->attrs = up;
- }
- Debug(LDAP_DEBUG_CONFIG, "%s: line %d: new attribute <%s>\n",
- fname, lineno, argv[i]);
- }
- } else if(!strcasecmp(*argv, "unique_strict")) {
- ud->strict = 1;
- } else if(!strcasecmp(*argv, "unique_base")) {
- struct berval bv;
- ber_str2bv( argv[1], 0, 0, &bv );
- ch_free(ud->dn.bv_val);
- dnNormalize(0, NULL, NULL, &bv, &ud->dn, NULL);
- Debug(LDAP_DEBUG_CONFIG, "%s: line %d: new base dn <%s>\n",
- fname, lineno, argv[1]);
- } else {
- return(SLAP_CONF_UNKNOWN);
+ if ( on->on_bi.bi_private ) {
+ ch_free( on->on_bi.bi_private );
+ on->on_bi.bi_private = NULL;
}
-
- return(0);
+ return 0;
}
-
/*
** mostly, just print the init message;
**
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);
}
** foreach configured attribute:
** free it;
** free our basedn;
-** (do not) free ud->message;
-** reset on_bi.bi_private;
-** free our config data;
**
*/
ch_free(ud->dn.bv_val);
- on->on_bi.bi_private = NULL; /* XXX */
-
- ch_free(ud);
+ memset( ud, 0, sizeof(*ud));
return(0);
}
*/
int unique_initialize() {
+ int rc;
/* statically declared just after the #includes at top */
unique.on_bi.bi_type = "unique";
unique.on_bi.bi_db_init = unique_db_init;
- unique.on_bi.bi_db_config = unique_config;
+ unique.on_bi.bi_db_destroy = unique_db_destroy;
unique.on_bi.bi_db_open = unique_open;
unique.on_bi.bi_db_close = unique_close;
unique.on_bi.bi_op_add = unique_add;
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 );
+ if ( rc ) return rc;
+
return(overlay_register(&unique));
}
slap_passwd_generate( struct berval *pass )
{
Debug( LDAP_DEBUG_TRACE, "slap_passwd_generate\n", 0, 0, 0 );
- pass->bv_val = NULL;
- pass->bv_len = 0;
+ BER_BVZERO( pass );
/*
* generate passwords of only 8 characters as some getpass(3)
LDAP_SLAPD_V (volatile sig_atomic_t) slapd_abrupt_shutdown;
LDAP_SLAPD_V (volatile sig_atomic_t) slapd_shutdown;
LDAP_SLAPD_V (int) slapd_register_slp;
+LDAP_SLAPD_V (char *) slapd_slp_attrs;
LDAP_SLAPD_V (slap_ssf_t) local_ssf;
LDAP_SLAPD_V (struct runqueue_s) slapd_rq;
int rc;
LDAPURLDesc *lurl;
- rc = ldap_url_parse_ext( url, &lurl );
+ rc = ldap_url_parse_ext( url, &lurl, LDAP_PVT_URL_PARSE_NONE );
switch( rc ) {
case LDAP_URL_SUCCESS:
char *dn;
int rc;
- rc = ldap_url_parse_ext( iv->bv_val, &url );
+ rc = ldap_url_parse_ext( iv->bv_val, &url, LDAP_PVT_URL_PARSE_NONE );
if ( rc == LDAP_URL_ERR_BADSCHEME ) {
ber_dupbv( jv++, iv );
continue;
#include <ac/unistd.h>
#include "slap.h"
-#include "lutil.h"
const struct berval slap_dummy_bv = BER_BVNULL;
}
if ( strncasecmp( s, "code", STRLENOF( "code" ) ) == 0 ) {
- if ( c != NULL && lutil_atoi( code, c ) != 0 ) {
- goto bailout;
+ char *next = NULL;
+ long retcode;
+
+ if ( c == NULL ) {
+ Debug( LDAP_DEBUG_ANY, "str2result (%s) missing value\n",
+ s, 0, 0 );
+ rc = -1;
+ continue;
}
+
+ while ( isspace( (unsigned char) c[ 0 ] ) ) c++;
+ if ( c[ 0 ] == '\0' ) {
+ Debug( LDAP_DEBUG_ANY, "str2result (%s) missing or empty value\n",
+ s, 0, 0 );
+ rc = -1;
+ continue;
+ }
+
+ retcode = strtol( c, &next, 10 );
+ if ( next == NULL || next == c ) {
+ Debug( LDAP_DEBUG_ANY, "str2result (%s) unable to parse value\n",
+ s, 0, 0 );
+ rc = -1;
+ continue;
+ }
+
+ while ( isspace( (unsigned char) next[ 0 ] ) ) next++;
+ if ( next[ 0 ] != '\0' ) {
+ Debug( LDAP_DEBUG_ANY, "str2result (%s) extra cruft after value\n",
+ s, 0, 0 );
+ rc = -1;
+ continue;
+ }
+
+ /* FIXME: what if it's larger that max int? */
+ *code = (int)retcode;
+
} else if ( strncasecmp( s, "matched", STRLENOF( "matched" ) ) == 0 ) {
if ( c != NULL ) {
*matched = c;
*info = c;
}
} else {
-bailout:;
Debug( LDAP_DEBUG_ANY, "str2result (%s) unknown\n",
s, 0, 0 );
/* FIXME: is this really needed? */
BER_BVSTR( &val, "top" );
if( attr_merge_one( e, ad_objectClass, &val, NULL ) ) {
+fail:
+ entry_free( e );
return LDAP_OTHER;
}
BER_BVSTR( &val, "OpenLDAProotDSE" );
if( attr_merge_one( e, ad_objectClass, &val, NULL ) ) {
- return LDAP_OTHER;
+ goto fail;
}
if( attr_merge_one( e, ad_structuralObjectClass, &val, NULL ) ) {
- return LDAP_OTHER;
+ goto fail;
}
LDAP_STAILQ_FOREACH( be, &backendDB, be_next ) {
&be->be_suffix[0],
&be->be_nsuffix[0] ) )
{
- return LDAP_OTHER;
+ goto fail;
}
continue;
}
&be->be_suffix[0],
& be->be_nsuffix[0] ) )
{
- return LDAP_OTHER;
+ goto fail;
}
continue;
}
&be->be_suffix[j],
&be->be_nsuffix[0] ) )
{
- return LDAP_OTHER;
+ goto fail;
}
}
}
/* supportedControl */
if ( controls_root_dse_info( e ) != 0 ) {
- return LDAP_OTHER;
+ goto fail;
}
/* supportedExtension */
if ( exop_root_dse_info( e ) != 0 ) {
- return LDAP_OTHER;
+ goto fail;
}
#ifdef LDAP_SLAPI
/* netscape supportedExtension */
for ( i = 0; (bv = slapi_int_get_supported_extop(i)) != NULL; i++ ) {
if( attr_merge_one( e, ad_supportedExtension, bv, NULL ) ) {
- return LDAP_OTHER;
+ goto fail;
}
}
#endif /* LDAP_SLAPI */
}
if( attr_merge( e, ad_supportedFeatures, supportedFeatures, NULL ) ) {
- return LDAP_OTHER;
+ goto fail;
}
/* supportedLDAPVersion */
val.bv_val = buf;
val.bv_len = strlen( val.bv_val );
if( attr_merge_one( e, ad_supportedLDAPVersion, &val, NULL ) ) {
- return LDAP_OTHER;
+ goto fail;
}
}
val.bv_val = supportedSASLMechanisms[i];
val.bv_len = strlen( val.bv_val );
if( attr_merge_one( e, ad_supportedSASLMechanisms, &val, NULL ) ) {
- return LDAP_OTHER;
+ ldap_charray_free( supportedSASLMechanisms );
+ goto fail;
}
}
ldap_charray_free( supportedSASLMechanisms );
if ( default_referral != NULL ) {
if( attr_merge( e, ad_ref, default_referral, NULL /* FIXME */ ) ) {
- return LDAP_OTHER;
+ goto fail;
}
}
if( attr_merge( e, a->a_desc, a->a_vals,
(a->a_nvals == a->a_vals) ? NULL : a->a_nvals ) )
{
- return LDAP_OTHER;
+ goto fail;
}
}
}
}
/* This callback actually does some work...*/
-static int sasl_sc_sasl2dn( Operation *o, SlapReply *rs )
+static int sasl_sc_sasl2dn( Operation *op, SlapReply *rs )
{
- struct berval *ndn = o->o_callback->sc_private;
+ struct berval *ndn = op->o_callback->sc_private;
- if (rs->sr_type != REP_SEARCH) return 0;
+ if ( rs->sr_type != REP_SEARCH ) return LDAP_SUCCESS;
/* We only want to be called once */
if ( !BER_BVISNULL( ndn ) ) {
- o->o_tmpfree(ndn->bv_val, o->o_tmpmemctx);
+ op->o_tmpfree( ndn->bv_val, op->o_tmpmemctx );
BER_BVZERO( ndn );
Debug( LDAP_DEBUG_TRACE,
- "slap_sc_sasl2dn: search DN returned more than 1 entry\n", 0, 0, 0 );
- return -1;
+ "%s: slap_sc_sasl2dn: search DN returned more than 1 entry\n",
+ op->o_log_prefix, 0, 0 );
+ return LDAP_OTHER;
}
- ber_dupbv_x(ndn, &rs->sr_entry->e_nname, o->o_tmpmemctx);
- return 0;
+ ber_dupbv_x( ndn, &rs->sr_entry->e_nname, op->o_tmpmemctx );
+ return LDAP_SUCCESS;
}
#ifdef HAVE_OPENSSL_CRL
char *sb_tls_crlcheck;
#endif
+ int sb_tls_do_init;
#endif
} slap_bindconf;
accessstr = strchr( attr, '/' );
if ( accessstr != NULL ) {
+ int invalid = 0;
+
accessstr[0] = '\0';
accessstr++;
access = str2access( accessstr );
- if ( access == ACL_INVALID_ACCESS ) {
+ switch ( access ) {
+ case ACL_INVALID_ACCESS:
fprintf( stderr, "unknown access \"%s\" for attribute \"%s\"\n",
accessstr, attr );
+ invalid = 1;
+ break;
+
+ case ACL_NONE:
+ fprintf( stderr, "\"none\" not allowed for attribute \"%s\"\n",
+ attr );
+ invalid = 1;
+ break;
+ }
+
+ if ( invalid ) {
if ( continuemode ) {
continue;
}
{
Slapi_PBlock *pb = SLAPI_OPERATION_PBLOCK( op );
- assert( rs->sr_type == REP_RESULT );
+ assert( rs->sr_type == REP_RESULT || rs->sr_type == REP_SASL || rs->sr_type == REP_EXTENDED );
slapi_over_call_plugins( pb, type );
if ( pb->pb_intop == 0 ) {
switch ( rs->sr_type ) {
case REP_RESULT:
+ case REP_SASL:
+ case REP_EXTENDED:
rc = slapi_over_result( op, rs, SLAPI_PLUGIN_PRE_RESULT_FN );
break;
case REP_SEARCH:
if ( pb->pb_intop == 0 ) {
switch ( rs->sr_type ) {
case REP_RESULT:
+ case REP_SASL:
+ case REP_EXTENDED:
rc = slapi_over_result( op, rs, SLAPI_PLUGIN_POST_RESULT_FN );
break;
case REP_SEARCH:
#include <ac/unistd.h>
#include <ldap.h>
+#include <lber_pvt.h>
#include <lutil.h>
#include <lutil_sha1.h>
{
fprintf(stderr,
"Usage: %s [options]\n"
+ " -c format\tcrypt(3) salt format\n"
+ " -g\t\tgenerate random password\n"
" -h hash\tpassword scheme\n"
+ " -n\t\tomit trailing newline\n"
" -s secret\tnew password\n"
- " -c format\tcrypt(3) salt format\n"
" -u\t\tgenerate RFC2307 values (default)\n"
" -v\t\tincrease verbosity\n"
" -T file\tread file for new password\n"
slappasswd( int argc, char *argv[] )
{
#ifdef LUTIL_SHA1_BYTES
- char *scheme = "{SSHA}";
+ char *default_scheme = "{SSHA}";
#else
- char *scheme = "{SMD5}";
+ char *default_scheme = "{SMD5}";
#endif
+ char *scheme = default_scheme;
char *newpw = NULL;
char *pwfile = NULL;
const char *progname = "slappasswd";
int i;
- struct berval passwd;
+ char *newline = "\n";
+ struct berval passwd = BER_BVNULL;
struct berval hash;
while( (i = getopt( argc, argv,
- "c:d:h:s:T:vu" )) != EOF )
+ "c:d:gh:ns:T:vu" )) != EOF )
{
switch (i) {
case 'c': /* crypt salt format */
lutil_salt_format( optarg );
break;
+ case 'g': /* new password (generate) */
+ if ( pwfile != NULL ) {
+ fprintf( stderr, "Option -g incompatible with -T\n" );
+ return EXIT_FAILURE;
+
+ } else if ( newpw != NULL ) {
+ fprintf( stderr, "New password already provided\n" );
+ return EXIT_FAILURE;
+
+ } else if ( lutil_passwd_generate( &passwd, 8 )) {
+ fprintf( stderr, "Password generation failed\n" );
+ return EXIT_FAILURE;
+ }
+ break;
+
case 'h': /* scheme */
- scheme = strdup( optarg );
+ if ( scheme != default_scheme ) {
+ fprintf( stderr, "Scheme already provided\n" );
+ return EXIT_FAILURE;
+
+ } else {
+ scheme = strdup( optarg );
+ }
+ break;
+
+ case 'n':
+ newline = "";
break;
case 's': /* new password (secret) */
- {
+ if ( pwfile != NULL ) {
+ fprintf( stderr, "Option -s incompatible with -T\n" );
+ return EXIT_FAILURE;
+
+ } else if ( newpw != NULL ) {
+ fprintf( stderr, "New password already provided\n" );
+ return EXIT_FAILURE;
+
+ } else {
char* p;
newpw = strdup( optarg );
for( p = optarg; *p != '\0'; p++ ) {
*p = '\0';
}
- } break;
+ }
+ break;
case 'T': /* password file */
+ if ( pwfile != NULL ) {
+ fprintf( stderr, "Password file already provided\n" );
+ return EXIT_FAILURE;
+
+ } else if ( newpw != NULL ) {
+ fprintf( stderr, "Option -T incompatible with -s/-g\n" );
+ return EXIT_FAILURE;
+
+ }
pwfile = optarg;
break;
if( lutil_get_filed_password( pwfile, &passwd )) {
return EXIT_FAILURE;
}
- } else {
+ } else if ( BER_BVISEMPTY( &passwd )) {
if( newpw == NULL ) {
/* prompt for new password */
char *cknewpw;
passwd.bv_val = newpw;
passwd.bv_len = strlen(passwd.bv_val);
+ } else {
+ hash = passwd;
+ goto print_pw;
}
lutil_passwd_hash( &passwd, scheme, &hash, &text );
return EXIT_FAILURE;
}
- printf( "%s\n" , hash.bv_val );
+print_pw:;
+ printf( "%s%s" , hash.bv_val, newline );
return EXIT_SUCCESS;
}
int si_syncdata;
int si_logstate;
int si_conn_setup;
-#ifdef HAVE_TLS
- int si_check_tls;
-#endif
Avlnode *si_presentlist;
LDAP *si_ld;
LDAP_LIST_HEAD(np, nonpresent_entry) si_nonpresentlist;
static int syncuuid_cmp( const void *, const void * );
static void avl_ber_bvfree( void * );
-static void syncrepl_del_nonpresent( Operation *, syncinfo_t *, BerVarray );
+static void syncrepl_del_nonpresent( Operation *, syncinfo_t *, BerVarray, struct berval * );
static int syncrepl_message_to_op(
syncinfo_t *, Operation *, LDAPMessage * );
static int syncrepl_message_to_entry(
(const void *)&op->o_protocol );
#ifdef HAVE_TLS
- if ( si->si_check_tls ) {
- si->si_check_tls = 0;
+ if ( si->si_bindconf.sb_tls_do_init ) {
rc = bindconf_tls_set( &si->si_bindconf, si->si_ld );
} else if ( si->si_bindconf.sb_tls_ctx ) {
rc = ldap_set_option( si->si_ld, LDAP_OPT_X_TLS_CTX,
if ( refreshDeletes == 0 && match < 0 &&
err == LDAP_SUCCESS )
{
- syncrepl_del_nonpresent( op, si, NULL );
+ syncrepl_del_nonpresent( op, si, NULL, NULL );
} else {
avl_free( si->si_presentlist, avl_ber_bvfree );
si->si_presentlist = NULL;
ber_scanf( ber, "[W]", &syncUUIDs );
ber_scanf( ber, /*"{"*/ "}" );
if ( refreshDeletes ) {
- syncrepl_del_nonpresent( op, si, syncUUIDs );
+ syncrepl_del_nonpresent( op, si, syncUUIDs,
+ &syncCookie.ctxcsn );
ber_bvarray_free_x( syncUUIDs, op->o_tmpmemctx );
} else {
for ( i = 0; !BER_BVISNULL( &syncUUIDs[i] ); i++ ) {
if ( si->si_refreshPresent == 1 ) {
if ( match < 0 ) {
- syncrepl_del_nonpresent( op, si, NULL );
+ syncrepl_del_nonpresent( op, si, NULL, NULL );
}
}
f.f_choice = LDAP_FILTER_EQUALITY;
f.f_ava = &ava;
ava.aa_desc = slap_schema.si_ad_entryUUID;
- (void)slap_uuidstr_from_normalized( &syncUUID_strrep, syncUUID, op->o_tmpmemctx );
ava.aa_value = *syncUUID;
+
+ (void)slap_uuidstr_from_normalized( &syncUUID_strrep, syncUUID, op->o_tmpmemctx );
+ if ( syncuuid_bv ) {
+ Debug( LDAP_DEBUG_SYNC, "syncrepl_entry: inserted UUID %s\n",
+ syncUUID_strrep.bv_val, 0, 0 );
+ }
op->ors_filter = &f;
op->ors_filterstr.bv_len = STRLENOF( "(entryUUID=)" ) + syncUUID_strrep.bv_len;
syncrepl_del_nonpresent(
Operation *op,
syncinfo_t *si,
- BerVarray uuids )
+ BerVarray uuids,
+ struct berval *cookiecsn )
{
Backend* be = op->o_bd;
slap_callback cb = { NULL };
AttributeName an[2];
struct berval pdn = BER_BVNULL;
+ struct berval csn;
op->o_req_dn = si->si_base;
op->o_req_ndn = si->si_base;
if ( !LDAP_LIST_EMPTY( &si->si_nonpresentlist ) ) {
- slap_queue_csn( op, &si->si_syncCookie.ctxcsn );
+ if ( cookiecsn && !BER_BVISNULL( cookiecsn ))
+ csn = *cookiecsn;
+ else
+ csn = si->si_syncCookie.ctxcsn;
+
+ slap_queue_csn( op, &csn );
np_list = LDAP_LIST_FIRST( &si->si_nonpresentlist );
while ( np_list != NULL ) {
if ( !(si->si_refreshDelete & NP_DELETE_ONE )) {
a = attr_find( rs->sr_entry->e_attrs, slap_schema.si_ad_entryUUID );
- if ( a == NULL ) return 0;
+ if ( a )
+ present_uuid = avl_find( si->si_presentlist, &a->a_nvals[0],
+ syncuuid_cmp );
+
+ Debug( LDAP_DEBUG_SYNC, "nonpresent_callback: UUID %s, dn %s, %sfound\n",
+ a ? a->a_vals[0].bv_val : "<missing>", rs->sr_entry->e_name.bv_val, present_uuid ? "" : "not " );
- present_uuid = avl_find( si->si_presentlist, &a->a_nvals[0],
- syncuuid_cmp );
+ if ( a == NULL ) return 0;
}
if ( present_uuid == NULL ) {
/* mandatory */
#define GOT_ID 0x0001
-#define GOT_PROVIDER 0x0002
+#define GOT_PROVIDER 0x0002
+#define GOT_BASE 0x0004
/* check */
-#define GOT_ALL (GOT_ID|GOT_PROVIDER)
+#define GOT_ALL (GOT_ID|GOT_PROVIDER|GOT_BASE)
static struct {
struct berval key;
Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
return -1;
}
+ gots |= GOT_BASE;
} else if ( !strncasecmp( c->argv[ i ], LOGBASESTR "=",
STRLENOF( LOGBASESTR "=" ) ) )
{
} else if ( strchr( val, ':' ) != NULL ) {
char *next, *ptr = val;
unsigned dd, hh, mm, ss;
+
+ /* NOTE: the test for ptr[ 0 ] == '-'
+ * should go before the call to strtoul() */
dd = strtoul( ptr, &next, 10 );
- if ( next == ptr || next[0] != ':' ) {
+ if ( ptr[ 0 ] == '-' || next == ptr || next[0] != ':' ) {
snprintf( c->msg, sizeof( c->msg ),
"Error: parse_syncrepl_line: "
"invalid interval \"%s\", unable to parse days", val );
}
ptr = next + 1;
hh = strtoul( ptr, &next, 10 );
- if ( next == ptr || next[0] != ':' || hh > 24 ) {
+ if ( ptr[ 0 ] == '-' || next == ptr || next[0] != ':' || hh > 24 ) {
snprintf( c->msg, sizeof( c->msg ),
"Error: parse_syncrepl_line: "
"invalid interval \"%s\", unable to parse hours", val );
}
ptr = next + 1;
mm = strtoul( ptr, &next, 10 );
- if ( next == ptr || next[0] != ':' || mm > 60 ) {
+ if ( ptr[ 0 ] == '-' || next == ptr || next[0] != ':' || mm > 60 ) {
snprintf( c->msg, sizeof( c->msg ),
"Error: parse_syncrepl_line: "
"invalid interval \"%s\", unable to parse minutes", val );
}
ptr = next + 1;
ss = strtoul( ptr, &next, 10 );
- if ( next == ptr || next[0] != '\0' || ss > 60 ) {
+ if ( ptr[ 0 ] == '-' || next == ptr || next[0] != '\0' || ss > 60 ) {
snprintf( c->msg, sizeof( c->msg ),
"Error: parse_syncrepl_line: "
"invalid interval \"%s\", unable to parse seconds", val );
if ( gots != GOT_ALL ) {
snprintf( c->msg, sizeof( c->msg ),
- "Error: Malformed \"syncrepl\" line in slapd config file" );
+ "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 );
return -1;
}
si->si_slimit = 0;
si->si_conn_setup = 0;
-#ifdef HAVE_TLS
- si->si_check_tls = 1;
-#endif
-
si->si_presentlist = NULL;
LDAP_LIST_INIT( &si->si_nonpresentlist );
ldap_pvt_thread_mutex_init( &si->si_mutex );
# cn=monitor, cn=schema, and cn=config
#
-access to attr=userpassword
+access to attrs=userpassword
by self =wx
by anonymous =x
# cn=monitor, cn=schema, and cn=config
#
-access to attr=userpassword
+access to attrs=userpassword
by self =wx
by anonymous =x
# cn=monitor, cn=schema, and cn=config
#
-access to attr=userpassword
+access to attrs=userpassword
by dn.exact="uid=proxy,ou=People,dc=example,dc=com" read
by self =wx
by anonymous =x
ppolicy_default "cn=Standard Policy,ou=Policies,dc=example,dc=com"
ppolicy_use_lockout
-access to attr=userpassword
+access to attrs=userpassword
by self write
by * auth
# cn=monitor, cn=schema, and cn=config
#
-access to attr=userpassword
+access to attrs=userpassword
by anonymous auth
by self write
#database @BACKEND@
#suffix "dc=example,dc=com"
#directory @TESTDIR@/db.1.b
-#index objectClass eq
+##bdb#index objectClass eq
+##hdb#index objectClass eq
#monitor#database monitor
valsort-attr employeeType ou=users,o=valsort weighted alpha-ascend
database config
-rootpw secret
+rootpw @CONFIGPW@
#monitor#database monitor
# cn=monitor, cn=schema, and cn=config
#
-access to attr=authzFrom,authzTo
+access to attrs=authzFrom,authzTo
by * auth
-access to attr=userpassword
+access to attrs=userpassword
by anonymous auth
by self write
directory @TESTDIR@/db.2.a
rootdn "cn=Manager,dc=example,dc=com"
rootpw secret
-index objectClass eq
-index cn,sn,uid pres,eq,sub
+#bdb#index objectClass eq
+#bdb#index cn,sn,uid pres,eq,sub
+#hdb#index objectClass eq
+#hdb#index cn,sn,uid pres,eq,sub
#monitor#database monitor
#include <ldap.h>
#include <lutil.h>
+#include <lber_pvt.h>
#include "slapd-common.h"
int force, int chaserefs, int noinit, LDAP **ldp );
static int
-do_base( char *uri, struct berval *base, struct berval *pass, int maxloop,
- int force, int chaserefs, int noinit, int delay );
+do_base( char *uri, struct berval *base, struct berval *pass, char *pwattr,
+ int maxloop, int force, int chaserefs, int noinit, int delay );
/* This program can be invoked two ways: if -D is used to specify a Bind DN,
* that DN will be used repeatedly for all of the Binds. If instead -b is used
usage( char *name )
{
fprintf( stderr, "usage: %s "
- "[-h <host>] "
- "-p port "
- "(-D <dn>|-b <baseDN> [-f <searchfilter>]) "
- "-w <passwd> "
+ "[-H uri | -h <host> [-p port]] "
+ "[-D <dn> [-w <passwd>]] "
+ "[-b <baseDN> [-f <searchfilter>] [-a pwattr]] "
"[-l <loops>] "
"[-L <outerloops>] "
"[-F] "
char *dn = NULL;
struct berval base = { 0, NULL };
struct berval pass = { 0, NULL };
+ char *pwattr = NULL;
int port = -1;
int loops = LOOPS;
int outerloops = 1;
tester_init( "slapd-bind" );
- while ( (i = getopt( argc, argv, "b:H:h:p:D:w:l:L:f:FIt:" )) != EOF ) {
+ while ( (i = getopt( argc, argv, "a:b:H:h:p:D:w:l:L:f:FIt:" )) != EOF ) {
switch( i ) {
+ case 'a':
+ pwattr = optarg;
+ break;
+
case 'b': /* base DN of a tree of user DNs */
ber_str2bv( optarg, 0, 0, &base );
break;
break;
case 'H': /* the server uri */
- uri = strdup( optarg );
+ uri = optarg;
break;
case 'h': /* the servers host */
- host = strdup( optarg );
+ host = optarg;
break;
case 'p': /* the servers port */
break;
case 'D':
- dn = strdup( optarg );
+ dn = optarg;
break;
case 'w':
- pass.bv_val = strdup( optarg );
- pass.bv_len = strlen( optarg );
+ ber_str2bv( optarg, 0, 0, &pass );
break;
case 'l': /* the number of loops */
for ( i = 0; i < outerloops; i++ ) {
if ( base.bv_val != NULL ) {
- do_base( uri, &base, &pass, loops,
+ do_base( uri, &base, &pass, pwattr, loops,
force, chaserefs, noinit, delay );
} else {
do_bind( uri, dn, &pass, loops,
fprintf( stderr, " PID=%ld - Bind done (%d).\n", (long) pid, rc );
}
- if ( ldp ) {
+ if ( ldp && noinit ) {
*ldp = ld;
} else if ( ld != NULL ) {
static int
-do_base( char *uri, struct berval *base, struct berval *pass, int maxloop,
- int force, int chaserefs, int noinit, int delay )
+do_base( char *uri, struct berval *base, struct berval *pass, char *pwattr,
+ int maxloop, int force, int chaserefs, int noinit, int delay )
{
LDAP *ld = NULL;
int i = 0;
int rc = LDAP_SUCCESS;
ber_int_t msgid;
LDAPMessage *res, *msg;
- struct berval *rdns = NULL;
+ char **dns = NULL;
+ struct berval *creds = NULL;
char *attrs[] = { LDAP_NO_ATTRS, NULL };
- int nrdns = 0;
+ int ndns = 0;
#ifdef _WIN32
DWORD beg, end;
#else
#endif
int version = LDAP_VERSION3;
struct berval pw = { 0, NULL };
+ char *nullstr = "";
srand(pid);
exit( EXIT_FAILURE );
}
- rc = ldap_search_ext( ld, base->bv_val, LDAP_SCOPE_ONE,
+ fprintf( stderr, "PID=%ld - Bind(%d): base=\"%s\", filter=\"%s\" attr=\"%s\".\n",
+ (long) pid, maxloop, base->bv_val, filter, pwattr );
+
+ if ( pwattr != NULL ) {
+ attrs[ 0 ] = pwattr;
+ }
+ rc = ldap_search_ext( ld, base->bv_val, LDAP_SCOPE_SUBTREE,
filter, attrs, 0, NULL, NULL, 0, 0, &msgid );
if ( rc != LDAP_SUCCESS ) {
tester_ldap_error( ld, "ldap_search_ext", NULL );
exit( EXIT_FAILURE );
}
- while (( rc=ldap_result( ld, LDAP_RES_ANY, LDAP_MSG_ONE, NULL, &res )) >0){
+ while ( ( rc = ldap_result( ld, LDAP_RES_ANY, LDAP_MSG_ONE, NULL, &res ) ) > 0 )
+ {
BerElement *ber;
struct berval bv;
- char *ptr;
int done = 0;
- for (msg = ldap_first_message( ld, res ); msg;
- msg = ldap_next_message( ld, msg )) {
- switch ( ldap_msgtype( msg )) {
+ for ( msg = ldap_first_message( ld, res ); msg;
+ msg = ldap_next_message( ld, msg ) )
+ {
+ switch ( ldap_msgtype( msg ) ) {
case LDAP_RES_SEARCH_ENTRY:
rc = ldap_get_dn_ber( ld, msg, &ber, &bv );
- ptr = strchr( bv.bv_val, ',');
- assert( ptr != NULL );
- bv.bv_len = ptr - bv.bv_val + 1;
- rdns = realloc( rdns, (nrdns+1)*sizeof(struct berval));
- ber_dupbv( &rdns[nrdns], &bv );
- nrdns++;
+ dns = realloc( dns, (ndns + 1)*sizeof(char *) );
+ dns[ndns] = ber_strdup( bv.bv_val );
+ if ( pwattr != NULL ) {
+ struct berval **values = ldap_get_values_len( ld, msg, pwattr );
+
+ creds = realloc( creds, (ndns + 1)*sizeof(struct berval) );
+ if ( values == NULL ) {
+novals:;
+ if ( pass != NULL ) {
+ ber_dupbv( &creds[ndns], pass );
+
+ } else {
+ creds[ndns].bv_len = 0;
+ creds[ndns].bv_val = nullstr;
+ }
+
+ } else {
+ static struct berval cleartext = BER_BVC( "{CLEARTEXT} " );
+ struct berval value = *values[ 0 ];
+
+ if ( value.bv_val[ 0 ] == '{' ) {
+ char *end = ber_bvchr( &value, '}' );
+
+ if ( end ) {
+ if ( ber_bvcmp( &value, &cleartext ) == 0 ) {
+ value.bv_val += cleartext.bv_len;
+ value.bv_len -= cleartext.bv_len;
+
+ } else {
+ ldap_value_free_len( values );
+ goto novals;
+ }
+ }
+
+ }
+
+ ber_dupbv( &creds[ndns], &value );
+ ldap_value_free_len( values );
+ }
+ }
+ ndns++;
ber_free( ber, 0 );
break;
+
case LDAP_RES_SEARCH_RESULT:
done = 1;
break;
gettimeofday( &beg, NULL );
#endif
- if ( nrdns == 0 ) {
+ if ( ndns == 0 ) {
tester_error( "No RDNs" );
return 1;
}
+ fprintf( stderr, "PID=%ld - got %d values.\n", (long) pid, ndns );
+
/* Ok, got list of RDNs, now start binding to each */
for ( i = 0; i < maxloop; i++ ) {
- char dn[BUFSIZ], *ptr;
int j, k;
+ struct berval *cred = pass;
- for ( j = 0, k = 0; k < nrdns; k++) {
- j = rand() % nrdns;
- if ( base->bv_len + rdns[j].bv_len < sizeof( dn ) ) {
- break;
- }
+ for ( j = 0, k = 0; k < ndns; k++) {
+ j = rand() % ndns;
}
- if ( k == nrdns ) {
-
+ if ( creds && !BER_BVISEMPTY( &creds[j] ) ) {
+ cred = &creds[j];
}
-
- ptr = lutil_strcopy(dn, rdns[j].bv_val);
- strcpy(ptr, base->bv_val);
- if ( do_bind( uri, dn, pass, 1, force, chaserefs, noinit, &ld )
+ if ( do_bind( uri, dns[j], cred, 1, force, chaserefs, noinit, &ld )
&& !force )
{
break;
(long) end.tv_sec, (long) end.tv_usec );
#endif
- if ( rdns ) {
- for ( i = 0; i < nrdns; i++ ) {
- free( rdns[i].bv_val );
+ if ( dns ) {
+ for ( i = 0; i < ndns; i++ ) {
+ free( dns[i] );
+ }
+ free( dns );
+ }
+
+ if ( creds ) {
+ for ( i = 0; i < ndns; i++ ) {
+ if ( creds[i].bv_val != nullstr ) {
+ free( creds[i].bv_val );
+ }
}
- free( rdns );
+ free( creds );
}
return 0;
char *bfile = NULL;
char *breqs[MAXREQS];
char *bcreds[MAXREQS];
+ char *battrs[MAXREQS];
int bnum = 0;
char *bargs[MAXARGS];
int banum;
/* look for bind requests */
if ( bfile ) {
- bnum = get_search_filters( bfile, bcreds, NULL, breqs );
+ bnum = get_search_filters( bfile, bcreds, battrs, breqs );
}
/* setup friendly option */
bargs[banum - 4] = breqs[jj];
bargs[banum - 2] = bcreds[jj];
+ if ( battrs[jj] != NULL ) {
+ bargs[banum - 1] = "-a";
+ bargs[banum] = battrs[jj];
+
+ } else {
+ sargs[sanum - 1] = NULL;
+ }
fork_child( bcmd, bargs );
}
}
-e "s;@PORT4@;${PORT4};" \
-e "s;@PORT5@;${PORT5};" \
-e "s;@PORT6@;${PORT6};" \
+ -e "s/@CONFIGPW@/${CONFIGPW}/" \
-e "s/@SASL_MECH@/${SASL_MECH}/" \
-e "s/@CACHETTL@/${CACHETTL}/" \
-e "s/@ENTRY_LIMIT@/${CACHE_ENTRY_LIMIT}/" \
## top-level directory of the distribution or, alternatively, at
## <http://www.OpenLDAP.org/license.html>.
+umask 077
+
MONITORDB=${AC_monitor-no}
BACKLDAP=${AC_ldap-ldapno}
BACKMETA=${AC_meta-metano}
SLAPADD="../servers/slapd/slapd -Ta -d 0 $LDAP_VERBOSE"
SLAPCAT="../servers/slapd/slapd -Tc -d 0 $LDAP_VERBOSE"
SLAPINDEX="../servers/slapd/slapd -Ti -d 0 $LDAP_VERBOSE"
+SLAPPASSWD="../servers/slapd/slapd -Tpasswd"
+
+CONFIGPWF=$TESTDIR/configpw
unset DIFF_OPTIONS
# NOTE: -u/-c is not that portable...
if test $? != 0 ; then
echo "comparison failed - modrdn operations did not complete correctly"
test $KILLSERVERS != no && kill -HUP $KILLPIDS
- exit 1
+ exit -1
fi
if test $? != 0 ; then
echo "comparison failed - modrdn operations did not complete correctly"
test $KILLSERVERS != no && kill -HUP $KILLPIDS
- exit 1
+ exit -1
fi
# Ensure that you cannot find the entry for which the rdn was deleted as
if test $? != 0 ; then
echo "failure: ldapsearch found attribute that was to be removed!"
test $KILLSERVERS != no && kill -HUP $KILLPIDS
- exit 1
+ exit -1
fi
echo "Using ldapsearch to retrieve all the entries..."
if test $? != 0 ; then
echo "comparison failed - modrdn operations did not complete correctly"
test $KILLSERVERS != no && kill -HUP $KILLPIDS
- exit 1
+ exit -1
fi
# Test that you can use modrdn with an attribute value which was previously
if test $? != 0 ; then
echo "comparison failed - modrdn operations did not complete correctly"
test $KILLSERVERS != no && kill -HUP $KILLPIDS
- exit 1
+ exit -1
fi
echo "Testing modrdn with newSuperior as child of target "
'cn=James A Jones 1, ou=Alumni Association, ou=People, dc=example, dc=com' 'cn=James A Jones 1'
RC=$?
-if test $RC -eq 0 ; then
+case $RC in
+0)
echo "ldapmodrdn succeeded, should have failed!"
test $KILLSERVERS != no && kill -HUP $KILLPIDS
- exit 1
-fi
+ exit -1
+ ;;
+32)
+ echo "ldapmodrdn failed (noSuchObject)"
+ ;;
+*)
+ echo "ldapmodrdn failed ($RC)!"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit $RC
+ ;;
+esac
test $KILLSERVERS != no && kill -HUP $KILLPIDS
exit $RC
fi
+# ITS#4491, if debug messages are unavailable, we can't verify the tests.
+grep "query template" $LOG2 > /dev/null
+RC=$?
+if test $RC != 0 ; then
+ echo "Debug messages unavailable, test aborted..."
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS && wait
+ exit 0
+fi
+
echo "Query 2: filter:(|(cn=*Jon*)(sn=Jon*)) attrs:cn sn title uid"
echo "# Query 2: filter:(|(cn=*Jon*)(sn=Jon*)) attrs:cn sn title uid" >> $SLAVEOUT
$LDAPSEARCH -x -S "" -b "$BASEDN" -h $LOCALHOST -p $PORT2 \
echo "running defines.sh"
. $SRCDIR/scripts/defines.sh
+if test $SYNCPROV = syncprovno; then
+ echo "Syncrepl provider overlay not available, test skipped"
+ exit 0
+fi
+
mkdir -p $TESTDIR $DBDIR1A $DBDIR1B $DBDIR1C $DBDIR2A $DBDIR2B
echo "Running slapadd to build glued slapd databases..."
mkdir -p $TESTDIR $DBDIR1
+$SLAPPASSWD -g -n > $CONFIGPWF
+RC=$?
+if test $RC != 0 ; then
+ echo "slappasswd failed ($RC)!"
+ exit $RC
+fi
+read CONFIGPW < $CONFIGPWF
+
echo "Running slapadd to build slapd database..."
. $CONFFILTER $BACKEND $MONITORDB < $VALSORTCONF > $CONF1
$SLAPADD -f $CONF1 -l $LDIFVALSORT
exit 1
fi
-echo ">>>>> Test succeeded"
-
echo "Reconfiguring slapd to test valsort descending"
-$LDAPMODIFY -x -D cn=config -h $LOCALHOST -p $PORT1 -w $PASSWD > \
+$LDAPMODIFY -x -D cn=config -h $LOCALHOST -p $PORT1 -y $CONFIGPWF > \
$TESTOUT 2>&1 << EOMODS
version: 1
dn: olcOverlay={0}valsort,olcDatabase={1}$BACKEND,cn=config
exit 1
fi
-echo ">>>>> Test succeeded"
-
echo "Adding a valsort record with weighted ou..."
$LDAPADD -D "$VALSORTDN" -h $LOCALHOST -p $PORT1 -w $PASSWD \
test $KILLSERVERS != no && kill -HUP $KILLPIDS
-echo ">>>>> Test succeeded"
-
test $KILLSERVERS != no && wait
+echo ">>>>> Test succeeded"
+
exit 0