From c7686180b5fd75ed90e028b4f99ad86d9a3d0880 Mon Sep 17 00:00:00 2001 From: Kurt Zeilenga Date: Thu, 3 Nov 2005 19:02:53 +0000 Subject: [PATCH] Sync with HEAD --- CHANGES | 7 + aclocal.m4 | 172 +-- build/BerkeleyDB42.patch | 68 -- build/ltmain.sh | 205 ++-- clients/tools/ldapmodrdn.c | 2 +- clients/tools/ldappasswd.c | 4 +- configure.in | 40 +- contrib/slapd-modules/smbk5pwd/smbk5pwd.c | 32 +- doc/devel/todo | 1 + doc/guide/admin/tls.sdf | 12 +- doc/man/man3/ldap.3 | 17 +- doc/man/man5/slapd.conf.5 | 46 +- doc/man/man5/slapo-accesslog.5 | 119 +- doc/man/man5/slapo-retcode.5 | 15 +- doc/man/man5/slapo-syncprov.5 | 17 +- doc/man/man8/slapadd.8 | 7 +- doc/man/man8/slapauth.8 | 14 + doc/man/man8/slapcat.8 | 21 +- doc/man/man8/slapdn.8 | 13 + doc/man/man8/slapindex.8 | 7 +- include/ldap.h | 120 +- include/portable.hin | 16 +- libraries/libldap/cyrus.c | 62 +- libraries/libldap/error.c | 23 +- libraries/libldap/init.c | 17 +- libraries/libldap/os-ip.c | 10 + libraries/libldap/search.c | 50 + libraries/libldap/tls.c | 167 ++- libraries/libldap/utf-8-conv.c | 45 +- libraries/libldap/util-int.c | 2 +- libraries/libldap_r/tpool.c | 10 +- libraries/librewrite/info.c | 5 +- libraries/librewrite/session.c | 47 +- servers/slapd/aci.c | 28 +- servers/slapd/acl.c | 2 +- servers/slapd/aclparse.c | 233 ++-- servers/slapd/add.c | 127 ++- servers/slapd/back-bdb/add.c | 48 +- servers/slapd/back-bdb/attr.c | 143 +-- servers/slapd/back-bdb/back-bdb.h | 16 +- servers/slapd/back-bdb/cache.c | 129 +-- servers/slapd/back-bdb/delete.c | 63 +- servers/slapd/back-bdb/dn2id.c | 16 +- servers/slapd/back-bdb/id2entry.c | 16 +- servers/slapd/back-bdb/index.c | 78 +- servers/slapd/back-bdb/init.c | 13 +- servers/slapd/back-bdb/key.c | 8 +- servers/slapd/back-bdb/modify.c | 10 +- servers/slapd/back-bdb/modrdn.c | 5 +- servers/slapd/back-bdb/proto-bdb.h | 41 +- servers/slapd/back-bdb/tools.c | 493 ++++++++- servers/slapd/back-ldap/bind.c | 4 + servers/slapd/back-ldap/chain.c | 5 +- servers/slapd/back-ldap/extended.c | 24 +- servers/slapd/back-ldap/search.c | 1 + servers/slapd/back-ldbm/add.c | 17 + servers/slapd/back-ldbm/delete.c | 79 +- servers/slapd/back-ldbm/modify.c | 56 +- servers/slapd/back-ldif/ldif.c | 22 + servers/slapd/back-meta/bind.c | 14 +- servers/slapd/back-meta/candidates.c | 6 +- servers/slapd/back-meta/config.c | 45 +- servers/slapd/back-meta/conn.c | 3 +- servers/slapd/back-meta/init.c | 41 +- servers/slapd/back-meta/map.c | 82 +- servers/slapd/back-meta/search.c | 23 +- servers/slapd/back-meta/unbind.c | 7 +- servers/slapd/back-monitor/init.c | 8 + servers/slapd/back-monitor/log.c | 236 ++-- servers/slapd/back-monitor/modify.c | 3 + servers/slapd/back-monitor/rww.c | 25 +- servers/slapd/back-sql/add.c | 6 +- servers/slapd/back-sql/modrdn.c | 1 + servers/slapd/back-sql/operational.c | 4 +- servers/slapd/backglue.c | 2 +- servers/slapd/bconfig.c | 291 +++-- servers/slapd/config.c | 59 +- servers/slapd/connection.c | 667 ++++++++--- servers/slapd/ctxcsn.c | 9 +- servers/slapd/daemon.c | 1104 +++++++++++-------- servers/slapd/delete.c | 8 - servers/slapd/extended.c | 2 +- servers/slapd/init.c | 6 +- servers/slapd/main.c | 52 +- servers/slapd/modify.c | 222 +--- servers/slapd/modrdn.c | 16 +- servers/slapd/mods.c | 10 +- servers/slapd/operation.c | 23 +- servers/slapd/overlays/accesslog.c | 337 ++++-- servers/slapd/overlays/lastmod.c | 8 +- servers/slapd/overlays/ppolicy.c | 38 +- servers/slapd/overlays/refint.c | 6 - servers/slapd/overlays/rwm.c | 22 +- servers/slapd/overlays/rwm.h | 3 + servers/slapd/overlays/rwmconf.c | 6 +- servers/slapd/overlays/rwmmap.c | 72 +- servers/slapd/overlays/syncprov.c | 44 +- servers/slapd/passwd.c | 7 +- servers/slapd/proto-slap.h | 34 +- servers/slapd/result.c | 66 +- servers/slapd/sasl.c | 29 +- servers/slapd/saslauthz.c | 4 +- servers/slapd/schema/core.schema | 6 + servers/slapd/schema_init.c | 84 +- servers/slapd/slap.h | 12 +- servers/slapd/slapcommon.c | 61 +- servers/slapd/slapi/slapi_ops.c | 4 - servers/slapd/slaptest.c | 59 + servers/slapd/syncrepl.c | 247 ++++- tests/progs/Makefile.in | 7 +- tests/progs/slapd-bind.c | 261 +++++ tests/run.in | 3 +- tests/scripts/conf.sh | 1 + tests/scripts/defines.sh | 3 + tests/scripts/test031-component-filter | 9 +- tests/scripts/test035-meta | 23 + tests/scripts/test039-glue-ldap-concurrency | 2 +- 117 files changed, 4959 insertions(+), 2544 deletions(-) delete mode 100644 build/BerkeleyDB42.patch create mode 100644 tests/progs/slapd-bind.c diff --git a/CHANGES b/CHANGES index 9d73a2561d..649b3115fc 100644 --- a/CHANGES +++ b/CHANGES @@ -1,6 +1,13 @@ OpenLDAP 2.3 Change Log OpenLDAP 2.3.12 Engineering + Fixed libldap ldapi:// authdn construction + Added libldap ldap_bv2escaped_filter_value + Updated contrib smbk5pwd module + Build environment + Added slapd-bind test program + Added inet_ntoa_b support for VxWorks + Dropped SSLeay support OpenLDAP 2.3.11 Release Fixed libldap reentrancy issue (ITS#3988) diff --git a/aclocal.m4 b/aclocal.m4 index 22cdcb9365..d5ecbecab1 100644 --- a/aclocal.m4 +++ b/aclocal.m4 @@ -621,7 +621,7 @@ rm="rm -f" default_ofile=libtool can_build_shared=yes -# All known linkers require a `.a' archive for static linking (except M$VC, +# All known linkers require a `.a' archive for static linking (except MSVC, # which needs '.lib'). libext=a ltmain="$ac_aux_dir/ltmain.sh" @@ -837,8 +837,8 @@ if test "X${echo_test_string+set}" != Xset; then # find a string as large as possible, as long as the shell can cope with it for cmd in 'sed 50q "[$]0"' 'sed 20q "[$]0"' 'sed 10q "[$]0"' 'sed 2q "[$]0"' 'echo test'; do # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ... - if (echo_test_string="`eval $cmd`") 2>/dev/null && - echo_test_string="`eval $cmd`" && + if (echo_test_string=`eval $cmd`) 2>/dev/null && + echo_test_string=`eval $cmd` && (test "X$echo_test_string" = "X$echo_test_string") 2>/dev/null then break @@ -1007,7 +1007,7 @@ x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*|s390*-*linux*|sparc*-*linux*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then - case "`/usr/bin/file conftest.o`" in + case `/usr/bin/file conftest.o` in *32-bit*) case $host in x86_64-*linux*) @@ -1089,7 +1089,7 @@ AC_CACHE_CHECK([$1], [$2], # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ - -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \ + -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:__oline__: $lt_compile\"" >&AS_MESSAGE_LOG_FD) @@ -1128,7 +1128,7 @@ AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], LDFLAGS="$LDFLAGS $3" printf "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then - # The compiler can only warn and ignore the option if not recognized + # The linker can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then # Append any errors to the config.log. @@ -1203,7 +1203,7 @@ AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl elif test -x /usr/sbin/sysctl; then lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` else - lt_cv_sys_max_cmd_len=65536 # usable default for *BSD + lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs fi # And add a safety zone lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` @@ -1215,7 +1215,7 @@ AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl # nice to cause kernel panics so lets avoid the loop below. # First set a reasonable default. lt_cv_sys_max_cmd_len=16384 - # + # if test -x /sbin/sysconfig; then case `/sbin/sysconfig -q proc exec_disable_arg_limit` in *1*) lt_cv_sys_max_cmd_len=-1 ;; @@ -1332,7 +1332,7 @@ int main () }] EOF if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext} 2>/dev/null; then - (./conftest; exit; ) 2>/dev/null + (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) $1 ;; @@ -1481,7 +1481,7 @@ AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext], # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ - -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \ + -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:__oline__: $lt_compile\"" >&AS_MESSAGE_LOG_FD) @@ -1499,7 +1499,7 @@ AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext], _LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes fi fi - chmod u+w . + chmod u+w . 2>&AS_MESSAGE_LOG_FD $rm conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation @@ -1759,7 +1759,8 @@ cygwin* | mingw* | pw32*) dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ - $install_prog $dir/$dlname \$dldir/$dlname' + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $rm \$dlpath' @@ -1812,7 +1813,7 @@ darwin* | rhapsody*) soname_spec='${libname}${release}${major}$shared_ext' shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH - shrext_cmds='$(test .$module = .yes && echo .so || echo .dylib)' + shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same. if test "$GCC" = yes; then sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"` @@ -1850,7 +1851,14 @@ kfreebsd*-gnu) freebsd* | dragonfly*) # DragonFly does not have aout. When/if they implement a new # versioning mechanism, adjust this. - objformat=`test -x /usr/bin/objformat && /usr/bin/objformat || echo aout` + if test -x /usr/bin/objformat; then + objformat=`/usr/bin/objformat` + else + case $host_os in + freebsd[[123]]*) objformat=aout ;; + *) objformat=elf ;; + esac + fi version_type=freebsd-$objformat case $version_type in freebsd-elf*) @@ -1895,7 +1903,7 @@ hpux9* | hpux10* | hpux11*) version_type=sunos need_lib_prefix=no need_version=no - case "$host_cpu" in + case $host_cpu in ia64*) shrext_cmds='.so' hardcode_into_libs=yes @@ -2291,7 +2299,7 @@ AC_DEFUN([AC_LIBTOOL_DLOPEN], # AC_LIBTOOL_WIN32_DLL # -------------------- -# declare package support for building win32 dll's +# declare package support for building win32 DLLs AC_DEFUN([AC_LIBTOOL_WIN32_DLL], [AC_BEFORE([$0], [AC_LIBTOOL_SETUP]) ])# AC_LIBTOOL_WIN32_DLL @@ -2465,7 +2473,7 @@ dnl not every word. This closes a longstanding sh security hole. if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) - file_magic_regex="`expr \"$deplibs_check_method\" : \"file_magic \(.*\)\"`" + file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then @@ -2575,7 +2583,7 @@ AC_CACHE_VAL(lt_cv_path_LD, if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then lt_cv_path_LD="$ac_dir/$ac_prog" # Check to see if the program is GNU ld. I'd rather use --version, - # but apparently some GNU ld's only accept -v. + # but apparently some variants of GNU ld only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. case `"$lt_cv_path_LD" -v 2>&1 &1 \?\'\ \ ]*|*]*|"") arg="\"$arg\"" ;; esac @@ -228,7 +228,7 @@ func_infer_tag () for arg in $CC; do # Double-quote args containing other shell metacharacters. case $arg in - *$quote_scanset* | *]* | *\|* | *\&* | *\(* | *\)* | "") + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") arg="\"$arg\"" ;; esac @@ -352,7 +352,7 @@ func_extract_archives () func_extract_an_archive "$my_xdir" "$my_xabs" fi # $darwin_arches fi # $run - ;; + ;; *) func_extract_an_archive "$my_xdir" "$my_xabs" ;; @@ -591,7 +591,7 @@ if test -z "$show_help"; then for arg do - case "$arg_mode" in + case $arg_mode in arg ) # do not "continue". Instead, add this to base_compile lastarg="$arg" @@ -642,7 +642,7 @@ if test -z "$show_help"; then # Many Bourne shells cannot handle close brackets correctly # in scan sets, so we specify it separately. case $arg in - *$quote_scanset* | *]* | *\|* | *\&* | *\(* | *\)* | "") + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") arg="\"$arg\"" ;; esac @@ -677,7 +677,7 @@ if test -z "$show_help"; then # in scan sets (worked around with variable expansion), # and furthermore cannot handle '|' '&' '(' ')' in scan sets # at all, so we specify them separately. - *$quote_scanset* | *]* | *\|* | *\&* | *\(* | *\)* | "") + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") lastarg="\"$lastarg\"" ;; esac @@ -752,13 +752,12 @@ if test -z "$show_help"; then qlibobj=`$echo "X$libobj" | $Xsed -e "$sed_quote_subst"` case $qlibobj in - *$quote_scanset* | *]* | *\|* | *\&* | *\(* | *\)* | "") + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") qlibobj="\"$qlibobj\"" ;; esac - if test "X$libobj" != "X$qlibobj"; then - $echo "$modename: libobj name \`$libobj' may not contain shell special characters." - exit $EXIT_FAILURE - fi + test "X$libobj" != "X$qlibobj" \ + && $echo "X$libobj" | grep '[]~#^*{};<>?"'"'"' &()|`$[]' \ + && $echo "$modename: libobj name \`$libobj' may not contain shell special characters." objname=`$echo "X$obj" | $Xsed -e 's%^.*/%%'` xdir=`$echo "X$obj" | $Xsed -e 's%/[^/]*$%%'` if test "X$xdir" = "X$obj"; then @@ -839,7 +838,7 @@ compiler." fi qsrcfile=`$echo "X$srcfile" | $Xsed -e "$sed_quote_subst"` case $qsrcfile in - *$quote_scanset* | *]* | *\|* | *\&* | *\(* | *\)* | "") + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") qsrcfile="\"$qsrcfile\"" ;; esac @@ -1105,15 +1104,14 @@ EOF if test -n "$link_static_flag"; then dlopen_self=$dlopen_self_static fi - prefer_static_libs=yes else if test -z "$pic_flag" && test -n "$link_static_flag"; then dlopen_self=$dlopen_self_static fi - prefer_static_libs=built fi build_libtool_libs=no build_old_libs=yes + prefer_static_libs=yes break ;; esac @@ -1127,7 +1125,7 @@ EOF arg="$1" shift case $arg in - *$quote_scanset* | *]* | *\|* | *\&* | *\(* | *\)* | "") + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") qarg=\"`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`\" ### testsuite: skip nested quoting test ;; *) qarg=$arg ;; @@ -1436,7 +1434,7 @@ EOF continue ;; - -framework) + -framework|-arch) prev=darwin_framework compiler_flags="$compiler_flags $arg" compile_command="$compile_command $arg" @@ -1566,7 +1564,7 @@ EOF # to be aesthetically quoted because they are evaled later. arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` case $arg in - *$quote_scanset* | *]* | *\|* | *\&* | *\(* | *\)* | "") + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") arg="\"$arg\"" ;; esac @@ -1682,7 +1680,7 @@ EOF for flag in $args; do IFS="$save_ifs" case $flag in - *$quote_scanset* | *]* | *\|* | *\&* | *\(* | *\)* | "") + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") flag="\"$flag\"" ;; esac @@ -1700,7 +1698,7 @@ EOF for flag in $args; do IFS="$save_ifs" case $flag in - *$quote_scanset* | *]* | *\|* | *\&* | *\(* | *\)* | "") + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") flag="\"$flag\"" ;; esac @@ -1733,7 +1731,7 @@ EOF # to be aesthetically quoted because they are evaled later. arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` case $arg in - *$quote_scanset* | *]* | *\|* | *\&* | *\(* | *\)* | "") + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") arg="\"$arg\"" ;; esac @@ -1867,7 +1865,7 @@ EOF # to be aesthetically quoted because they are evaled later. arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` case $arg in - *$quote_scanset* | *]* | *\|* | *\&* | *\(* | *\)* | "") + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") arg="\"$arg\"" ;; esac @@ -2455,7 +2453,7 @@ EOF case "$temp_rpath " in *" $dir "*) ;; *" $absdir "*) ;; - *) temp_rpath="$temp_rpath $dir" ;; + *) temp_rpath="$temp_rpath $absdir" ;; esac fi @@ -2492,12 +2490,8 @@ EOF fi link_static=no # Whether the deplib will be linked statically - use_static_libs="$prefer_static_libs" - if test "$use_static_libs" = built && test "$installed" = yes ; then - use_static_libs=no - fi if test -n "$library_names" && - { test "$use_static_libs" = no || test -z "$old_library"; }; then + { test "$prefer_static_libs" = no || test -z "$old_library"; }; then if test "$installed" = no; then notinst_deplibs="$notinst_deplibs $lib" need_relink=yes @@ -2645,7 +2639,7 @@ EOF add_dir="-L$dir" # Try looking first in the location we're being installed to. if test -n "$inst_prefix_dir"; then - case "$libdir" in + case $libdir in [\\/]*) add_dir="$add_dir -L$inst_prefix_dir$libdir" ;; @@ -2718,7 +2712,7 @@ EOF add_dir="-L$libdir" # Try looking first in the location we're being installed to. if test -n "$inst_prefix_dir"; then - case "$libdir" in + case $libdir in [\\/]*) add_dir="$add_dir -L$inst_prefix_dir$libdir" ;; @@ -2779,8 +2773,6 @@ EOF fi fi else - convenience="$convenience $dir/$old_library" - old_convenience="$old_convenience $dir/$old_library" deplibs="$dir/$old_library $deplibs" link_static=yes fi @@ -3470,7 +3462,7 @@ EOF if test "$?" -eq 0 ; then ldd_output=`ldd conftest` for i in $deplibs; do - name="`expr $i : '-l\(.*\)'`" + name=`expr $i : '-l\(.*\)'` # If $name is empty we are operating on a -L argument. if test "$name" != "" && test "$name" -ne "0"; then if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then @@ -3507,7 +3499,7 @@ EOF # Error occurred in the first compile. Let's try to salvage # the situation: Compile a separate program for each library. for i in $deplibs; do - name="`expr $i : '-l\(.*\)'`" + name=`expr $i : '-l\(.*\)'` # If $name is empty we are operating on a -L argument. if test "$name" != "" && test "$name" != "0"; then $rm conftest @@ -3559,7 +3551,7 @@ EOF set dummy $deplibs_check_method file_magic_regex=`expr "$deplibs_check_method" : "$2 \(.*\)"` for a_deplib in $deplibs; do - name="`expr $a_deplib : '-l\(.*\)'`" + name=`expr $a_deplib : '-l\(.*\)'` # If $name is empty we are operating on a -L argument. if test "$name" != "" && test "$name" != "0"; then if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then @@ -3628,7 +3620,7 @@ EOF set dummy $deplibs_check_method match_pattern_regex=`expr "$deplibs_check_method" : "$2 \(.*\)"` for a_deplib in $deplibs; do - name="`expr $a_deplib : '-l\(.*\)'`" + name=`expr $a_deplib : '-l\(.*\)'` # If $name is empty we are operating on a -L argument. if test -n "$name" && test "$name" != "0"; then if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then @@ -3869,6 +3861,9 @@ EOF # The command line is too long to execute in one step. $show "using reloadable object file for export list..." skipped_export=: + # Break out early, otherwise skipped_export may be + # set to false by a later but shorter cmd. + break fi done IFS="$save_ifs" @@ -3938,7 +3933,8 @@ EOF fi fi - if test "X$skipped_export" != "X:" && len=`expr "X$test_cmds" : ".*"` && + if test "X$skipped_export" != "X:" && + len=`expr "X$test_cmds" : ".*" 2>/dev/null` && test "$len" -le "$max_cmd_len" || test "$max_cmd_len" -le -1; then : else @@ -3973,7 +3969,7 @@ EOF do eval test_cmds=\"$reload_cmds $objlist $last_robj\" if test "X$objlist" = X || - { len=`expr "X$test_cmds" : ".*"` && + { len=`expr "X$test_cmds" : ".*" 2>/dev/null` && test "$len" -le "$max_cmd_len"; }; then objlist="$objlist $obj" else @@ -4063,13 +4059,30 @@ EOF IFS="$save_ifs" eval cmd=\"$cmd\" $show "$cmd" - $run eval "$cmd" || exit $? + $run eval "$cmd" || { + lt_exit=$? + + # Restore the uninstalled library and exit + if test "$mode" = relink; then + $run eval '(cd $output_objdir && $rm ${realname}T && $mv ${realname}U $realname)' + fi + + exit $lt_exit + } done IFS="$save_ifs" # Restore the uninstalled library and exit if test "$mode" = relink; then $run eval '(cd $output_objdir && $rm ${realname}T && $mv $realname ${realname}T && $mv "$realname"U $realname)' || exit $? + + if test -n "$convenience"; then + if test -z "$whole_archive_flag_spec"; then + $show "${rm}r $gentop" + $run ${rm}r "$gentop" + fi + fi + exit $EXIT_SUCCESS fi @@ -4414,7 +4427,7 @@ extern \"C\" { if test -z "$export_symbols"; then export_symbols="$output_objdir/$outputname.exp" $run $rm $export_symbols - $run eval "${SED} -n -e '/^: @PROGRAM@$/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"' + $run eval "${SED} -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"' else $run eval "${SED} -e 's/\([ ][.*^$]\)/\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"' $run eval 'grep -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T' @@ -4819,6 +4832,7 @@ EOF EOF cat >> $cwrappersource <<"EOF" + return 127; } void * @@ -5082,13 +5096,13 @@ else # Backslashes separate directories on plain windows *-*-mingw | *-*-os2*) $echo >> $output "\ - exec \$progdir\\\\\$program \${1+\"\$@\"} + exec \"\$progdir\\\\\$program\" \${1+\"\$@\"} " ;; *) $echo >> $output "\ - exec \$progdir/\$program \${1+\"\$@\"} + exec \"\$progdir/\$program\" \${1+\"\$@\"} " ;; esac @@ -5098,7 +5112,7 @@ else fi else # The program doesn't exist. - \$echo \"\$0: error: \$progdir/\$program does not exist\" 1>&2 + \$echo \"\$0: error: \\\`\$progdir/\$program' does not exist\" 1>&2 \$echo \"This script is just a wrapper for \$program.\" 1>&2 $echo \"See the $PACKAGE documentation for more information.\" 1>&2 exit $EXIT_FAILURE @@ -5221,7 +5235,7 @@ fi\ oldobjs="$objlist $obj" objlist="$objlist $obj" eval test_cmds=\"$old_archive_cmds\" - if len=`expr "X$test_cmds" : ".*"` && + if len=`expr "X$test_cmds" : ".*" 2>/dev/null` && test "$len" -le "$max_cmd_len"; then : else @@ -5418,11 +5432,11 @@ relink_command=\"$relink_command\"" # install_prog (especially on Windows NT). if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh || # Allow the use of GNU shtool's install command. - $echo "X$nonopt" | $Xsed | grep shtool > /dev/null; then + $echo "X$nonopt" | grep shtool > /dev/null; then # Aesthetically quote it. arg=`$echo "X$nonopt" | $Xsed -e "$sed_quote_subst"` case $arg in - *$quote_scanset* | *]* | *\|* | *\&* | *\(* | *\)* | "") + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") arg="\"$arg\"" ;; esac @@ -5431,14 +5445,14 @@ relink_command=\"$relink_command\"" shift else install_prog= - arg="$nonopt" + arg=$nonopt fi # The real first argument should be the name of the installation program. # Aesthetically quote it. arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` case $arg in - *$quote_scanset* | *]* | *\|* | *\&* | *\(* | *\)* | "") + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") arg="\"$arg\"" ;; esac @@ -5456,28 +5470,31 @@ relink_command=\"$relink_command\"" do if test -n "$dest"; then files="$files $dest" - dest="$arg" + dest=$arg continue fi case $arg in -d) isdir=yes ;; - -f) prev="-f" ;; - -g) prev="-g" ;; - -m) prev="-m" ;; - -o) prev="-o" ;; + -f) + case " $install_prog " in + *[\\\ /]cp\ *) ;; + *) prev=$arg ;; + esac + ;; + -g | -m | -o) prev=$arg ;; -s) stripme=" -s" continue ;; - -*) ;; - + -*) + ;; *) # If the previous option needed an argument, then skip it. if test -n "$prev"; then prev= else - dest="$arg" + dest=$arg continue fi ;; @@ -5486,7 +5503,7 @@ relink_command=\"$relink_command\"" # Aesthetically quote the argument. arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` case $arg in - *$quote_scanset* | *]* | *\|* | *\&* | *\(* | *\)* | "") + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") arg="\"$arg\"" ;; esac @@ -5655,11 +5672,14 @@ relink_command=\"$relink_command\"" if test "$#" -gt 0; then # Delete the old symlinks, and create new ones. + # Try `ln -sf' first, because the `ln' binary might depend on + # the symlink we replace! Solaris /bin/ln does not understand -f, + # so we also need to try rm && ln -s. for linkname do if test "$linkname" != "$realname"; then - $show "(cd $destdir && $rm $linkname && $LN_S $realname $linkname)" - $run eval "(cd $destdir && $rm $linkname && $LN_S $realname $linkname)" + $show "(cd $destdir && { $LN_S -f $realname $linkname || { $rm $linkname && $LN_S $realname $linkname; }; })" + $run eval "(cd $destdir && { $LN_S -f $realname $linkname || { $rm $linkname && $LN_S $realname $linkname; }; })" fi done fi @@ -5672,7 +5692,16 @@ relink_command=\"$relink_command\"" IFS="$save_ifs" eval cmd=\"$cmd\" $show "$cmd" - $run eval "$cmd" || exit $? + $run eval "$cmd" || { + lt_exit=$? + + # Restore the uninstalled library and exit + if test "$mode" = relink; then + $run eval '(cd $output_objdir && $rm ${realname}T && $mv ${realname}U $realname)' + fi + + exit $lt_exit + } done IFS="$save_ifs" fi @@ -5773,17 +5802,15 @@ relink_command=\"$relink_command\"" notinst_deplibs= relink_command= - # To insure that "foo" is sourced, and not "foo.exe", - # finese the cygwin/MSYS system by explicitly sourcing "foo." - # which disallows the automatic-append-.exe behavior. - case $build in - *cygwin* | *mingw*) wrapperdot=${wrapper}. ;; - *) wrapperdot=${wrapper} ;; - esac + # Note that it is not necessary on cygwin/mingw to append a dot to + # foo even if both foo and FILE.exe exist: automatic-append-.exe + # behavior happens only for exec(3), not for open(2)! Also, sourcing + # `FILE.' does not work on cygwin managed mounts. + # # If there is no directory component, then add one. - case $file in - */* | *\\*) . ${wrapperdot} ;; - *) . ./${wrapperdot} ;; + case $wrapper in + */* | *\\*) . ${wrapper} ;; + *) . ./${wrapper} ;; esac # Check the variables that should have been set. @@ -5811,17 +5838,15 @@ relink_command=\"$relink_command\"" done relink_command= - # To insure that "foo" is sourced, and not "foo.exe", - # finese the cygwin/MSYS system by explicitly sourcing "foo." - # which disallows the automatic-append-.exe behavior. - case $build in - *cygwin* | *mingw*) wrapperdot=${wrapper}. ;; - *) wrapperdot=${wrapper} ;; - esac + # Note that it is not necessary on cygwin/mingw to append a dot to + # foo even if both foo and FILE.exe exist: automatic-append-.exe + # behavior happens only for exec(3), not for open(2)! Also, sourcing + # `FILE.' does not work on cygwin managed mounts. + # # If there is no directory component, then add one. - case $file in - */* | *\\*) . ${wrapperdot} ;; - *) . ./${wrapperdot} ;; + case $wrapper in + */* | *\\*) . ${wrapper} ;; + *) . ./${wrapper} ;; esac outputname= @@ -5862,7 +5887,7 @@ relink_command=\"$relink_command\"" fi # remove .exe since cygwin /usr/bin/install will append another - # one anyways + # one anyway case $install_prog,$host in */usr/bin/install*,*cygwin*) case $file:$destfile in diff --git a/clients/tools/ldapmodrdn.c b/clients/tools/ldapmodrdn.c index e87e13d7d7..d921fe736d 100644 --- a/clients/tools/ldapmodrdn.c +++ b/clients/tools/ldapmodrdn.c @@ -206,7 +206,7 @@ main(int argc, char **argv) if (havedn) retval = domodrdn( ld, entrydn, rdn, newSuperior, remove_old_RDN ); else while ((rc == 0 || contoper) && fgets(buf, sizeof(buf), fp) != NULL) { - if ( *buf != '\0' ) { /* blank lines optional, skip */ + if ( *buf != '\n' ) { /* blank lines optional, skip */ buf[ strlen( buf ) - 1 ] = '\0'; /* remove nl */ if ( havedn ) { /* have DN, get RDN */ diff --git a/clients/tools/ldappasswd.c b/clients/tools/ldappasswd.c index 31556695c0..0acd9cdc13 100644 --- a/clients/tools/ldappasswd.c +++ b/clients/tools/ldappasswd.c @@ -345,7 +345,6 @@ main( int argc, char *argv[] ) rc = ldap_parse_result( ld, res, &code, &matcheddn, &text, &refs, NULL, 0 ); - if( rc != LDAP_SUCCESS ) { ldap_perror( ld, "ldap_parse_result" ); rc = EXIT_FAILURE; @@ -353,9 +352,8 @@ main( int argc, char *argv[] ) } rc = ldap_parse_extended_result( ld, res, &retoid, &retdata, 1 ); - if( rc != LDAP_SUCCESS ) { - ldap_perror( ld, "ldap_parse_result" ); + ldap_perror( ld, "ldap_parse_extended_result" ); rc = EXIT_FAILURE; goto done; } diff --git a/configure.in b/configure.in index 44b15b56d7..ec8f749343 100644 --- a/configure.in +++ b/configure.in @@ -245,7 +245,7 @@ ol_with_kerberos=${ol_with_kerberos-auto} OL_ARG_WITH(threads,[ --with-threads with threads], auto, [auto nt posix mach pth lwp yes no manual] ) OL_ARG_WITH(tls,[ --with-tls with TLS/SSL support], - auto, [auto ssleay openssl yes no] ) + auto, [auto openssl yes no] ) OL_ARG_WITH(yielding_select,[ --with-yielding-select with implicitly yielding select], auto, [auto yes no manual] ) OL_ARG_WITH(multiple_precision,[ --with-multiple-precision @@ -1312,40 +1312,31 @@ dnl TLS/SSL ol_link_tls=no if test $ol_with_tls != no ; then - AC_CHECK_HEADERS(openssl/ssl.h ssl.h) - - if test $ac_cv_header_openssl_ssl_h = yes || - test $ac_cv_header_ssl_h = yes ; then - AC_CHECK_LIB(ssl, SSLeay_add_ssl_algorithms, - [have_ssleay=yes - need_rsaref=no], - [have_ssleay=no], + AC_CHECK_HEADERS(openssl/ssl.h) + + if test $ac_cv_header_openssl_ssl_h = yes ; then + AC_CHECK_LIB(ssl, SSL_library_init, + [have_openssl=yes + need_rsaref=no], [have_openssl=no], [-lcrypto]) - - if test $have_ssleay = no ; then - AC_CHECK_LIB(ssl, SSL_library_init, - [have_ssleay=yes - need_rsaref=no], [have_ssleay=no], - [-lcrypto]) - fi - if test $have_ssleay = no ; then + if test $have_openssl = no ; then AC_CHECK_LIB(ssl, ssl3_accept, - [have_ssleay=yes - need_rsaref=yes], [have_ssleay=no], + [have_openssl=yes + need_rsaref=yes], [have_openssl=no], [-lcrypto -lRSAglue -lrsaref]) fi - if test $have_ssleay = yes ; then + if test $have_openssl = yes ; then ol_with_tls=found ol_link_tls=yes - AC_DEFINE(HAVE_SSLEAY, 1, - [define if you have SSLeay or OpenSSL]) + AC_DEFINE(HAVE_OPENSSL, 1, + [define if you have OpenSSL]) if test $need_rsaref = yes; then AC_DEFINE(HAVE_RSAREF, 1, - [define if you have RSAref]) + [define if OpenSSL needs RSAref]) TLS_LIBS="-lssl -lcrypto -lRSAglue -lrsaref" else @@ -2408,7 +2399,7 @@ if test "$ol_with_multiple_precision" != "no" ; then case "$ol_mp_support" in bignum) AC_DEFINE(HAVE_BIGNUM, 1, - [define if you have SSLeay or OpenSSL's BIGNUM]) + [define if you have OpenSSL's BIGNUM]) ;; gmp) AC_DEFINE(HAVE_GMP, 1, [define if you have -lgmp]) @@ -2540,6 +2531,7 @@ AC_CHECK_FUNCS( \ getspnam \ gettimeofday \ initgroups \ + inet_ntoa_b \ lockf \ memcpy \ memmove \ diff --git a/contrib/slapd-modules/smbk5pwd/smbk5pwd.c b/contrib/slapd-modules/smbk5pwd/smbk5pwd.c index 3bac38736d..9e8f27c7df 100644 --- a/contrib/slapd-modules/smbk5pwd/smbk5pwd.c +++ b/contrib/slapd-modules/smbk5pwd/smbk5pwd.c @@ -23,9 +23,9 @@ #include #include +#include #ifdef DO_KRB5 -#include #include #include #include @@ -57,6 +57,7 @@ static ObjectClass *oc_krb5KDCEntry; #ifdef DO_SAMBA #include #include +#include "ldap_utf8.h" static AttributeDescription *ad_sambaLMPassword; static AttributeDescription *ad_sambaNTPassword; @@ -155,7 +156,6 @@ static void nthash( * 256 UCS2 characters, not 256 bytes... */ char hbuf[HASHLEN]; - int i; MD4_CTX ctx; if (passwd->bv_len > MAX_PWLEN*2) @@ -307,10 +307,9 @@ static int smbk5pwd_exop_passwd( Operation *op, SlapReply *rs ) { - int i, rc; + int rc; req_pwdexop_s *qpw = &op->oq_pwdexop; Entry *e; - Attribute *a; Modifications *ml; slap_overinst *on = (slap_overinst *)op->o_bd->bd_info; @@ -329,7 +328,8 @@ static int smbk5pwd_exop_passwd( krb5_error_code ret; hdb_entry ent; struct berval *keys; - int kvno; + int kvno, i; + Attribute *a; if ( !is_entry_objectclass(e, oc_krb5KDCEntry, 0 ) ) break; @@ -365,8 +365,7 @@ static int smbk5pwd_exop_passwd( keys[i].bv_val = (char *)buf; keys[i].bv_len = len; } - keys[i].bv_val = NULL; - keys[i].bv_len = 0; + BER_BVZERO( &keys[i] ); _kadm5_free_keys(kadm_context, ent.keys.len, ent.keys.val); @@ -401,8 +400,7 @@ static int smbk5pwd_exop_passwd( ml->sml_values[0].bv_val = ch_malloc( 64 ); ml->sml_values[0].bv_len = sprintf(ml->sml_values[0].bv_val, "%d", kvno+1 ); - ml->sml_values[1].bv_val = NULL; - ml->sml_values[1].bv_len = 0; + BER_BVZERO( &ml->sml_values[1] ); ml->sml_nvalues = NULL; } while(0); #endif /* DO_KRB5 */ @@ -439,8 +437,7 @@ static int smbk5pwd_exop_passwd( qpw->rs_mods = ml; keys = ch_malloc( 2 * sizeof(struct berval) ); - keys[1].bv_val = NULL; - keys[1].bv_len = 0; + BER_BVZERO( &keys[1] ); nthash( &pwd, keys ); ml->sml_desc = ad_sambaNTPassword; @@ -466,8 +463,7 @@ static int smbk5pwd_exop_passwd( qpw->rs_mods = ml; keys = ch_malloc( 2 * sizeof(struct berval) ); - keys[1].bv_val = NULL; - keys[1].bv_len = 0; + BER_BVZERO( &keys[1] ); lmhash( &pwd, keys ); ml->sml_desc = ad_sambaLMPassword; @@ -485,11 +481,11 @@ static int smbk5pwd_exop_passwd( qpw->rs_mods = ml; keys = ch_malloc( 2 * sizeof(struct berval) ); - keys[1].bv_val = NULL; - keys[1].bv_len = 0; - keys[0].bv_val = ch_malloc(16); - keys[0].bv_len = sprintf(keys[0].bv_val, "%d", - slap_get_time()); + keys[0].bv_val = ch_malloc( STRLENOF( "9223372036854775807L" ) + 1 ); + keys[0].bv_len = snprintf(keys[0].bv_val, + STRLENOF( "9223372036854775807L" ) + 1, + "%ld", slap_get_time()); + BER_BVZERO( &keys[1] ); ml->sml_desc = ad_sambaPwdLastSet; ml->sml_op = LDAP_MOD_REPLACE; diff --git a/doc/devel/todo b/doc/devel/todo index b7e6bca018..a1bba31b4a 100644 --- a/doc/devel/todo +++ b/doc/devel/todo @@ -48,6 +48,7 @@ Localize tools Small projects -------------- +Add BSD kqueue(2) support to slapd(8) Add DSML capabilities to command line tools Add LDIFv2 (XML) support to command line tools Implement authPassword (RFC 3112) diff --git a/doc/guide/admin/tls.sdf b/doc/guide/admin/tls.sdf index 182aa1dd8d..fcbdd68a85 100644 --- a/doc/guide/admin/tls.sdf +++ b/doc/guide/admin/tls.sdf @@ -1,4 +1,4 @@ -# Copyright 1999-2003, The OpenLDAP Foundation, All Rights Reserved. +# Copyright 1999-2005, The OpenLDAP Foundation, All Rights Reserved. # COPYING RESTRICTIONS APPLY, see COPYRIGHT. H1: Using TLS @@ -132,6 +132,16 @@ bytes of arbitrary data into the file. The file is only used to provide a seed for the pseudo-random number generator, and it doesn't need very much data to work. +H4: TLSEphemeralDHParamFile + +This directive specifies the file that contains parameters for Diffie-Hellman +ephemeral key exchange. This is required in order to use a DSA certificate on +the server side (i.e. {{EX:TLSCertificateKeyFile}} points to a DSA key). +Multiple sets of parameters can be included in the file; all of them will +be processed. Parameters can be generated using the following command + +> openssl dhparam [-dsaparam] -out + H4: TLSVerifyClient { never | allow | try | demand } This directive specifies what checks to perform on client certificates diff --git a/doc/man/man3/ldap.3 b/doc/man/man3/ldap.3 index c9cd6f8b9a..9e85767a00 100644 --- a/doc/man/man3/ldap.3 +++ b/doc/man/man3/ldap.3 @@ -76,16 +76,15 @@ All character string input/output is expected to be/is UTF\-8 encoded Unicode (version 3.2). .LP Distinguished names (DN) (and relative distinguished names (RDN) to -be passed to the LDAP routines should conform to RFC 2253. The -.BR ldap_explode_dn (3) -routines can be used to work with DNs. +be passed to the LDAP routines should conform to RFC 2253 UTF\-8 +string representation. .LP Search filters to be passed to the search routines are to be -constructed by hand and should conform to RFC 2254. +constructed by hand and should conform to RFC 2254 UTF\-8 +string representation. .LP LDAP URL are to be passed to routines are expected to conform -to RFC 2255. -The +to RFC 2255 syntax. The .BR ldap_url (3) routines can be used to work with LDAP URLs. .SH DISPLAYING RESULTS @@ -194,12 +193,6 @@ return number of entries in a search result .SM ldap_get_dn(3) extract the DN from an entry .TP -.SM ldap_explode_dn(3) -convert a DN into its component parts (deprecated) -.TP -.SM ldap_explode_rdn(3) -convert an RDN into its component parts (deprecated) -.TP .SM ldap_get_values_len(3) return an attribute's values with lengths .TP diff --git a/doc/man/man5/slapd.conf.5 b/doc/man/man5/slapd.conf.5 index 924b00a431..2ff81bbcbc 100644 --- a/doc/man/man5/slapd.conf.5 +++ b/doc/man/man5/slapd.conf.5 @@ -859,9 +859,15 @@ See .BR limits for an explanation of the different flags. .TP -.B ucdata-path -Specify the path to the directory containing the Unicode character -tables. The default path is DATADIR/ucdata. +.B tool-threads +Specify the maximum number of threads to use in tool mode. +This should not be greater than the number of CPUs in the system. +The default is 1. +.\"ucdata-path is obsolete / ignored... +.\".TP +.\".B ucdata-path +.\"Specify the path to the directory containing the Unicode character +.\"tables. The default path is DATADIR/ucdata. .SH TLS OPTIONS If .B slapd @@ -902,6 +908,12 @@ server private key that matches the certificate stored in the file. Currently, the private key must not be protected with a password, so it is of critical importance that it is protected carefully. .TP +.B TLSDHParamFile +This directive specifies the file that contains parameters for Diffie-Hellman +ephemeral key exchange. This is required in order to use a DSA certificate on +the server. If multiple sets of parameters are present in the file, all of +them will be processed. +.TP .B TLSRandFile Specifies the file to obtain random bits from when /dev/[u]random is not available. Generally set to the name of the EGD/PRNGD socket. @@ -1464,6 +1476,9 @@ in order to work over all of the glued databases. E.g. .B [credentials=] .B [realm=] .B [secprops=] +.B [logbase=] +.B [logfilter=] +.B [syncdata=default|accesslog|changelog] .RS Specify the current database as a replica which is kept up-to-date with the master content by establishing the current @@ -1568,6 +1583,22 @@ keyword above) for a SASL bind can be set with the option. A non default SASL realm can be set with the .B realm option. + +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 +.B logbase +and +.B logfilter +parameters must be set appropriately for the log that will be used. The +.B syncdata +parameter must be set to either "accesslog" if the log conforms to the +.BR slapo-accesslog (5) +log format, or "changelog" if the log conforms +to the obsolete \fIchangelog\fP format. If the +.B syncdata +parameter is omitted or set to "default" then the log parameters are +ignored. .RE .TP .B updatedn @@ -1629,14 +1660,12 @@ It uses Berkeley DB or GDBM to store data. .B ldif This database uses the filesystem to build the tree structure of the database, using plain ascii files to store data. -Its usage should be limited to very simple databases, where performances -are not a requirement. +Its usage should be limited to very simple databases, where performance +is not a requirement. .TP .B meta This backend performs basic LDAP proxying with respect to a set of -remote LDAP servers. It is an enhancement of the ldap backend. The -proxy cache extension of meta backend provides answering of search -requests from the proxy using results of previously cached requests. +remote LDAP servers. It is an enhancement of the ldap backend. .TP .B monitor This backend provides information about the running status of the slapd @@ -1722,6 +1751,7 @@ operation performed on that database. .B pcache Proxycache. This overlay allows caching of LDAP search requests in a local database. +It is most often used with the ldap or meta backends. .TP .B ppolicy Password Policy. diff --git a/doc/man/man5/slapo-accesslog.5 b/doc/man/man5/slapo-accesslog.5 index 0b1cf78c28..9e869a2cc5 100644 --- a/doc/man/man5/slapo-accesslog.5 +++ b/doc/man/man5/slapo-accesslog.5 @@ -12,9 +12,9 @@ backend database on another database. This allows all of the activity on a given database to be reviewed using arbitrary LDAP queries, instead of just logging to local flat text files. Configuration options are available for selecting a subset of operation types to log, and to automatically -prune older log records from the logging database. Log records are stored -with a custom schema to assure their readability whether viewed as LDIF -or in raw form. +prune older log records from the logging database. Log records are stored +with audit schema (see below) to assure their readability whether viewed +as LDIF or in raw form. .SH CONFIGURATION These .B slapd.conf @@ -58,14 +58,14 @@ and how often to scan the database for old entries. Both the and .B interval are specified as a time span in days, hours, minutes, and seconds. The -time format is [dd+]hh:mm[:ss] i.e., the days and seconds components are -optional but hours and minutes are required. Each numeric field must be -exactly two digits. For example +time format is [ddd+]hh:mm[:ss] i.e., the days and seconds components are +optional but hours and minutes are required. Except for days, which can +be up to 5 digits, each numeric field must be exactly two digits. For example .RS .RS .PD 0 .TP -logpurge 02+00:00 01+00:00 +logpurge 2+00:00 1+00:00 .RE .PD would specify that the log database should be scanned every day for old @@ -74,6 +74,13 @@ log database that supports ordered indexing on generalizedTime attributes, specifying an eq index on the .B reqStart attribute will greatly benefit the performance of the purge operation. +.RE +.TP +.B logsuccess TRUE | FALSE +If set to TRUE then log records will only be generated for successful +requests, i.e., requests that produce a result code of 0 (LDAP_SUCCESS). +If FALSE, log records are generated for all requests whether they +succeed or not. The default is FALSE. .SH EXAMPLES .LP @@ -91,10 +98,23 @@ attribute will greatly benefit the performance of the purge operation. logops writes reads .fi -.SH OBJECT CLASSES +.SH SCHEMA The .B accesslog -overlay defines a number of object classes for use in the logs. There is +overlay utilizes the "audit" schema described herein. +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 +.I a work in +.IR progress , +and hence subject to change without notice. +The schema is loaded automatically by the overlay. + +The schema includes a number of object classes and associated +attribute types as described below. + +There is a basic .B auditObject class from which two additional classes, @@ -116,7 +136,7 @@ class is as follows: SUP top STRUCTURAL MUST ( reqStart $ reqType $ reqSession ) MAY ( reqDN $ reqAuthzID $ reqControls $ reqRespControls $ - reqEnd $ reqResult $ reqMessage ) ) + reqEnd $ reqResult $ reqMessage $ reqReferral ) ) .RE .P Note that all of the OIDs used in the logging schema currently reside @@ -141,7 +161,7 @@ being logged, e.g. .BR search , etc. For extended operations, the type also includes the OID of the extended operation, e.g. -.B extended(1.2.3.4.1) +.B extended(1.1.1.1) The .B reqSession @@ -179,6 +199,11 @@ accompanied by a text error message which will be recorded in the .B reqMessage attribute. +The +.B reqReferral +attribute carries any referrals that were returned with the result of the +request. + Operation-specific classes are defined with additional attributes to carry all of the relevant parameters associated with the operation: @@ -210,36 +235,37 @@ The .B Add class inherits from the .B auditWriteObject -class. The Add and Modify classes are essentially the same. The +class. The Add and Modify classes are very similar. The .B reqMod attribute carries all of the attributes of the original entry being added. (Or in the case of a Modify operation, all of the modifications being performed.) The values are formatted as .RS -.RS .PD 0 .TP attribute:<+|-|=|#> [ value] .RE +.RE .PD Where '+' indicates an Add of a value, '-' for Delete, '=' for Replace, and '#' for Increment. In an Add operation, all of the reqMod values will have the '+' designator. -.RE .P - .LP .RS 4 ( 1.3.6.1.4.1.4203.666.11.5.2.6 NAME 'auditBind' DESC 'Bind operation' SUP auditObject STRUCTURAL - MUST reqMethod ) + MUST ( reqVersion $ reqMethod ) ) .RE .P The .B Bind -class just adds the +class includes the +.B reqVersion +attribute which contains the LDAP protocol version specified in the Bind +as well as the .B reqMethod attribute which contains the Bind Method used in the Bind. This will be the string @@ -268,19 +294,48 @@ attribute carries the Attribute Value Assertion used in the compare request. .LP .RS 4 ( 1.3.6.1.4.1.4203.666.11.5.2.8 + NAME 'auditDelete' + DESC 'Delete operation' + SUP auditWriteObject STRUCTURAL + MAY reqOld ) +.RE +.P +The +.B Delete +operation needs no further parameters. However, the +.B reqOld +attribute may optionally be used to record the contents of the entry prior +to its deletion. The values are formatted as +.RS +.PD 0 +.TP +attribute: value +.RE +.PD +This option is not yet implemented. + +.LP +.RS 4 +( 1.3.6.1.4.1.4203.666.11.5.2.9 NAME 'auditModify' DESC 'Modify operation' SUP auditWriteObject STRUCTURAL - MUST reqMod ) + MAY reqOld MUST reqMod ) .RE .P The .B Modify -operation has already been described. +operation contains a description of modifications in the +.B reqMod +attribute, which was already described above in the Add operation. It may +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. .LP .RS 4 -( 1.3.6.1.4.1.4203.666.11.5.2.9 +( 1.3.6.1.4.1.4203.666.11.5.2.10 NAME 'auditModRDN' DESC 'ModRDN operation' SUP auditWriteObject STRUCTURAL @@ -307,11 +362,11 @@ the new parent. .LP .RS 4 -( 1.3.6.1.4.1.4203.666.11.5.2.10 +( 1.3.6.1.4.1.4203.666.11.5.2.11 NAME 'auditSearch' DESC 'Search operation' SUP auditReadObject STRUCTURAL - MUST ( reqScope $ reqAttrsOnly ) + MUST ( reqScope $ reqDerefAliases $ reqAttrsOnly ) MAY ( reqFilter $ reqAttr $ reqEntries $ reqSizeLimit $ reqTimeLimit ) ) .RE @@ -320,12 +375,22 @@ For the .B Search class the .B reqScope -attribute contains the scope of the original search request, i.e. +attribute contains the scope of the original search request, using the +values specified for the LDAP URL format. I.e. .BR base , -.BR onelevel , -.BR subtree , +.BR one , +.BR sub , +or +.BR subord . +The +.B reqDerefAliases +attribute is one of +.BR never , +.BR finding , +.BR searching , or -.BR subordinate . +.BR always , +denoting how aliases will be processed during the search. The .B reqAttrsOnly attribute is a Boolean value showing @@ -352,7 +417,7 @@ attributes indicate what limits were requested on the search operation. .LP .RS 4 -( 1.3.6.1.4.1.4203.666.11.5.2.11 +( 1.3.6.1.4.1.4203.666.11.5.2.12 NAME 'auditExtended' DESC 'Extended operation' SUP auditObject STRUCTURAL diff --git a/doc/man/man5/slapo-retcode.5 b/doc/man/man5/slapo-retcode.5 index be612cd306..78cef21866 100644 --- a/doc/man/man5/slapo-retcode.5 +++ b/doc/man/man5/slapo-retcode.5 @@ -73,7 +73,20 @@ Enables exploitation of in-directory stored errAbsObject. May result in a lot of unnecessary overhead. .SH SCHEMA -The following schema items are created and used by the overlay: +The +.B retcode +overlay utilizes the "return code" schema described herein. +This schema is specifically designed for use with this +overlay and is not intended to be used otherwise. +It is also noted that the schema describe here is +.I a work in +.IR progress , +and hence subject to change without notice. +The schema is loaded automatically by the overlay. + +The schema includes a number of object classes and associated +attribute types as described below. + .LP The error code: .RS 4 diff --git a/doc/man/man5/slapo-syncprov.5 b/doc/man/man5/slapo-syncprov.5 index 02cf233740..884ceeff53 100644 --- a/doc/man/man5/slapo-syncprov.5 +++ b/doc/man/man5/slapo-syncprov.5 @@ -52,10 +52,25 @@ specifies the number of operations that are recorded in the log. All write operations (except Adds) are recorded in the log. When using the session log, it is helpful to set an eq index on the entryUUID attribute in the underlying database. +.TP +.B syncprov-nopresent TRUE | FALSE +Specify that the Present phase of refreshing should be skipped. This value +should only be set TRUE for a syncprov instance on top of a log database +(such as one managed by the accesslog overlay). +The default is FALSE. +.TP +.B syncprov-reloadhint TRUE | FALSE +Specify that the overlay should honor the reloadHint flag in the Syncrepl +Control. In OpenLDAP releases 2.3.11 and earlier the Syncrepl consumer did +not properly set this flag, so the overlay must ignore it. This option +should be set TRUE when working with newer releases that properly support +this flag. It must be set TRUE when using the accesslog overlay for +delta-based Syncrepl support. The default is FALSE. .SH FILES .TP ETCDIR/slapd.conf default slapd configuration file .SH SEE ALSO -.BR slapd.conf (5). +.BR slapd.conf (5), +.BR slapo-accesslog (5). OpenLDAP Administrator's Guide. diff --git a/doc/man/man8/slapadd.8 b/doc/man/man8/slapadd.8 index 6235288905..d6ba8c7174 100644 --- a/doc/man/man8/slapadd.8 +++ b/doc/man/man8/slapadd.8 @@ -8,6 +8,7 @@ slapadd \- Add entries to a SLAPD database .B SBINDIR/slapadd .B [\-v] .B [\-c] +.B [\-g] .B [\-u] .B [\-q] .B [\-w] @@ -29,7 +30,7 @@ suffix and adds entries corresponding to the provided LDIF to the database. Databases configured as .B subordinate -of this one are also updated. +of this one are also updated, unless \fB-g\fP is specified. The LDIF input is read from standard input or the specified file. .LP As @@ -48,6 +49,10 @@ enable verbose mode. .B \-c enable continue (ignore errors) mode. .TP +.B \-g +disable subordinate gluing. Only the specified database will be +processed, and not its glued subordinates (if any). +.TP .B \-u enable dry-run (don't write to backend) mode. .TP diff --git a/doc/man/man8/slapauth.8 b/doc/man/man8/slapauth.8 index 6b8242c610..eb91acf850 100644 --- a/doc/man/man8/slapauth.8 +++ b/doc/man/man8/slapauth.8 @@ -8,6 +8,7 @@ slapauth \- Check a list of string-represented IDs for authc/authz. .B [\-v] .B [\-d level] .B [\-f slapd.conf] +.B [\-F confdir] .B [\-M mech] .B [\-R realm] .B [\-U authcID] @@ -44,6 +45,19 @@ specify an alternative .BR slapd.conf (5) file. .TP +.BI \-F " confdir" +specify a config directory. +If both +.B -f +and +.B -F +are specified, the config file will be read and converted to +config directory format and written to the specified directory. +If neither option is specified, an attempt to read the +default config directory wll be made before trying to use the default +config file. If a valid config directory exists then the +default config file is ignored. +.TP .BI \-M " mech" specify a mechanism. .TP diff --git a/doc/man/man8/slapcat.8 b/doc/man/man8/slapcat.8 index 03a0aa5d4a..62092b4b9c 100644 --- a/doc/man/man8/slapcat.8 +++ b/doc/man/man8/slapcat.8 @@ -8,12 +8,14 @@ slapcat \- SLAPD database to LDIF utility .B SBINDIR/slapcat .B [\-v] .B [\-c] +.B [\-g] .B [\-d level] .B [\-b suffix] .B [\-n dbnum] .B [\-a filter] .B [\-s subtree-dn] .B [\-f slapd.conf] +.B [\-F confdir] .B [\-l ldif-file] .B .LP @@ -29,7 +31,7 @@ suffix and writes the corresponding LDIF to standard output or the specified file. Databases configured as .B subordinate -of this one are also output. +of this one are also output, unless \fB-g\fP is specified. .LP The LDIF generated by this tool is suitable for use with .BR slapadd (8). @@ -45,6 +47,10 @@ Enable verbose mode. .B \-c Enable continue (ignore errors) mode. .TP +.B \-g +disable subordinate gluing. Only the specified database will be +processed, and not its glued subordinates (if any). +.TP .BI \-d " level" Enable debugging messages as defined by the specified .IR level . @@ -87,6 +93,19 @@ Specify an alternative .BR slapd.conf (5) file. .TP +.BI \-F " confdir" +specify a config directory. +If both +.B -f +and +.B -F +are specified, the config file will be read and converted to +config directory format and written to the specified directory. +If neither option is specified, an attempt to read the +default config directory wll be made before trying to use the default +config file. If a valid config directory exists then the +default config file is ignored. +.TP .BI \-l " ldif-file" Write LDIF to specified file instead of standard output. .SH LIMITATIONS diff --git a/doc/man/man8/slapdn.8 b/doc/man/man8/slapdn.8 index c2a54649ca..9099256db9 100644 --- a/doc/man/man8/slapdn.8 +++ b/doc/man/man8/slapdn.8 @@ -41,6 +41,19 @@ specify an alternative .BR slapd.conf (5) file. .TP +.BI \-F " confdir" +specify a config directory. +If both +.B -f +and +.B -F +are specified, the config file will be read and converted to +config directory format and written to the specified directory. +If neither option is specified, an attempt to read the +default config directory wll be made before trying to use the default +config file. If a valid config directory exists then the +default config file is ignored. +.TP .BI \-N only output a normalized form of the DN, suitable to be used in a normalization tool; incompatible with diff --git a/doc/man/man8/slapindex.8 b/doc/man/man8/slapindex.8 index 57a0391efa..2295301de8 100644 --- a/doc/man/man8/slapindex.8 +++ b/doc/man/man8/slapindex.8 @@ -8,6 +8,7 @@ slapindex \- SLAPD index to LDIF utility .B SBINDIR/slapindex .B [\-v] .B [\-c] +.B [\-g] .B [\-q] .B [\-d level] .B [\-b suffix] @@ -27,7 +28,7 @@ suffix and updates the indices for all values of all attributes of all entries. Databases configured as .B subordinate -of this one are also re-indexed. +of this one are also re-indexed, unless \fB-g\fP is specified. .SH OPTIONS .TP .B \-v @@ -36,6 +37,10 @@ enable verbose mode. .B \-c enable continue (ignore errors) mode. .TP +.B \-g +disable subordinate gluing. Only the specified database will be +processed, and not its glued subordinates (if any). +.TP .B \-q enable quick (fewer integrity checks) mode. Performs no consistency checks when writing the database. Improves indexing time, but if any errors or diff --git a/include/ldap.h b/include/ldap.h index 201db1e836..7cfba13cf0 100644 --- a/include/ldap.h +++ b/include/ldap.h @@ -136,6 +136,7 @@ LDAP_BEGIN_DECL #define LDAP_OPT_X_TLS_CRLCHECK 0x600b #define LDAP_OPT_X_TLS_CONNECT_CB 0x600c #define LDAP_OPT_X_TLS_CONNECT_ARG 0x600d +#define LDAP_OPT_X_TLS_DHFILE 0x600e #define LDAP_OPT_X_TLS_NEVER 0 #define LDAP_OPT_X_TLS_HARD 1 @@ -203,20 +204,26 @@ typedef struct ldapcontrol { /* LDAP Controls */ /* standard track controls */ -#define LDAP_CONTROL_MANAGEDSAIT "2.16.840.1.113730.3.4.2" /* RFC 3296 */ -#define LDAP_CONTROL_SUBENTRIES "1.3.6.1.4.1.4203.1.10.1" /* RFC 3672 */ -#define LDAP_CONTROL_PAGEDRESULTS "1.2.840.113556.1.4.319" /* RFC 2696 */ -#define LDAP_CONTROL_VALUESRETURNFILTER "1.2.826.0.1.334810.2.3" /* RFC 3876 */ -#define LDAP_CONTROL_ASSERT "1.3.6.1.1.12" -#define LDAP_CONTROL_PRE_READ "1.3.6.1.1.13.1" -#define LDAP_CONTROL_POST_READ "1.3.6.1.1.13.2" +#define LDAP_CONTROL_MANAGEDSAIT "2.16.840.1.113730.3.4.2" /* RFC 3296 */ +#define LDAP_CONTROL_PROXY_AUTHZ "2.16.840.1.113730.3.4.18" /* RFC TBD */ +#define LDAP_CONTROL_SUBENTRIES "1.3.6.1.4.1.4203.1.10.1" /* RFC 3672 */ + +#define LDAP_CONTROL_VALUESRETURNFILTER "1.2.826.0.1.334810.2.3"/* RFC 3876 */ +#define LDAP_CONTROL_ASSERT "1.3.6.1.1.12" /* RFC TBD */ +#define LDAP_CONTROL_PRE_READ "1.3.6.1.1.13.1" /* RFC TBD */ +#define LDAP_CONTROL_POST_READ "1.3.6.1.1.13.2" /* RFC TBD */ /* standard track - not implemented in slapd(8) */ #define LDAP_CONTROL_SORTREQUEST "1.2.840.113556.1.4.473" /* RFC 2891 */ #define LDAP_CONTROL_SORTRESPONSE "1.2.840.113556.1.4.474" /* RFC 2891 */ -/* but not yet formalized controls */ -#define LDAP_CONTROL_PROXY_AUTHZ "2.16.840.1.113730.3.4.18" +/* non-standard track controls */ +#define LDAP_CONTROL_PAGEDRESULTS "1.2.840.113556.1.4.319" /* RFC 2696 */ + +/* Password policy Controls *//* work in progress */ +/* ITS#3458: released; disabled by default */ +#define LDAP_CONTROL_PASSWORDPOLICYREQUEST "1.3.6.1.4.1.42.2.27.8.5.1" +#define LDAP_CONTROL_PASSWORDPOLICYRESPONSE "1.3.6.1.4.1.42.2.27.8.5.1" /* various works in progress */ #define LDAP_CONTROL_NOOP "1.3.6.1.4.1.4203.666.5.2" @@ -225,30 +232,6 @@ typedef struct ldapcontrol { #define LDAP_CONTROL_SLURP "1.3.6.1.4.1.4203.666.5.13" #define LDAP_CONTROL_VALSORT "1.3.6.1.4.1.4203.666.5.14" -/* LDAP Duplicated Entry Control Extension *//* not implemented in slapd(8) */ -#define LDAP_CONTROL_DUPENT_REQUEST "2.16.840.1.113719.1.27.101.1" -#define LDAP_CONTROL_DUPENT_RESPONSE "2.16.840.1.113719.1.27.101.2" -#define LDAP_CONTROL_DUPENT_ENTRY "2.16.840.1.113719.1.27.101.3" -#define LDAP_CONTROL_DUPENT LDAP_CONTROL_DUPENT_REQUEST - -/* LDAP Persistent Search Control *//* not implemented in slapd(8) */ -/* draft-ietf-ldapext-psearch-03.txt (expired) */ -#define LDAP_CONTROL_PERSIST_REQUEST "2.16.840.1.113730.3.4.3" -#define LDAP_CONTROL_PERSIST_ENTRY_CHANGE_NOTICE "2.16.840.1.113730.3.4.7" -#define LDAP_CONTROL_PERSSIT_ENTRY_CHANGE_ADD 0x1 -#define LDAP_CONTROL_PERSSIT_ENTRY_CHANGE_DELETE 0x2 -#define LDAP_CONTROL_PERSSIT_ENTRY_CHANGE_MODIFY 0x4 -#define LDAP_CONTROL_PERSSIT_ENTRY_CHANGE_RENAME 0x8 - -/* LDAP VLV *//* not implemented in slapd(8) */ -#define LDAP_CONTROL_VLVREQUEST "2.16.840.1.113730.3.4.9" -#define LDAP_CONTROL_VLVRESPONSE "2.16.840.1.113730.3.4.10" - -/* Password policy Controls *//* work in progress */ -/* ITS#3458: released; disabled by default */ -#define LDAP_CONTROL_PASSWORDPOLICYREQUEST "1.3.6.1.4.1.42.2.27.8.5.1" -#define LDAP_CONTROL_PASSWORDPOLICYRESPONSE "1.3.6.1.4.1.42.2.27.8.5.1" - /* LDAP Sync -- draft-zeilenga-ldup-sync *//* submitted for publication */ #define LDAP_SYNC_OID "1.3.6.1.4.1.4203.1.9.1" #define LDAP_CONTROL_SYNC LDAP_SYNC_OID ".1" @@ -291,16 +274,38 @@ typedef struct ldapcontrol { #define LDAP_REFERRALS_REQUIRED 3 #endif -/* MS ActiveDirectory controls (for compatibility) */ -#define LDAP_CONTROL_X_DOMAIN_SCOPE "1.2.840.113556.1.4.1339" -#define LDAP_CONTROL_X_PERMISSIVE_MODIFY "1.2.840.113556.1.4.1413" +/* MS Active Directory controls (for compatibility) */ #define LDAP_CONTROL_X_INCREMENTAL_VALUES "1.2.840.113556.1.4.802" -#define LDAP_CONTROL_X_TREE_DELETE "1.2.840.113556.1.4.805" +#define LDAP_CONTROL_X_DOMAIN_SCOPE "1.2.840.113556.1.4.1339" +#define LDAP_CONTROL_X_PERMISSIVE_MODIFY "1.2.840.113556.1.4.1413" #define LDAP_CONTROL_X_SEARCH_OPTIONS "1.2.840.113556.1.4.1340" -#define LDAP_SEARCH_FLAG_DOMAIN_SCOPE 1 /* do not generate referrals */ -#define LDAP_SEARCH_FLAG_PHANTOM_ROOT 2 /* search all NCs subordinate to base */ +#define LDAP_SEARCH_FLAG_DOMAIN_SCOPE 1 /* do not generate referrals */ +#define LDAP_SEARCH_FLAG_PHANTOM_ROOT 2 /* search all subordinate NCs */ + +/* MS Active Directory controls - not implemented in slapd(8) */ +#define LDAP_CONTROL_X_TREE_DELETE "1.2.840.113556.1.4.805" #define LDAP_CONTROL_X_EXTENDED_DN "1.2.840.113556.1.4.529" +/* various expired works */ +/* LDAP Duplicated Entry Control Extension *//* not implemented in slapd(8) */ +#define LDAP_CONTROL_DUPENT_REQUEST "2.16.840.1.113719.1.27.101.1" +#define LDAP_CONTROL_DUPENT_RESPONSE "2.16.840.1.113719.1.27.101.2" +#define LDAP_CONTROL_DUPENT_ENTRY "2.16.840.1.113719.1.27.101.3" +#define LDAP_CONTROL_DUPENT LDAP_CONTROL_DUPENT_REQUEST + +/* LDAP Persistent Search Control *//* not implemented in slapd(8) */ +#define LDAP_CONTROL_PERSIST_REQUEST "2.16.840.1.113730.3.4.3" +#define LDAP_CONTROL_PERSIST_ENTRY_CHANGE_NOTICE "2.16.840.1.113730.3.4.7" +#define LDAP_CONTROL_PERSSIT_ENTRY_CHANGE_ADD 0x1 +#define LDAP_CONTROL_PERSSIT_ENTRY_CHANGE_DELETE 0x2 +#define LDAP_CONTROL_PERSSIT_ENTRY_CHANGE_MODIFY 0x4 +#define LDAP_CONTROL_PERSSIT_ENTRY_CHANGE_RENAME 0x8 + +/* LDAP VLV *//* not implemented in slapd(8) */ +#define LDAP_CONTROL_VLVREQUEST "2.16.840.1.113730.3.4.9" +#define LDAP_CONTROL_VLVRESPONSE "2.16.840.1.113730.3.4.10" + + /* LDAP Unsolicited Notifications */ #define LDAP_NOTICE_OF_DISCONNECTION "1.3.6.1.4.1.1466.20036" /* RFC 2251 */ #define LDAP_NOTICE_DISCONNECT LDAP_NOTICE_OF_DISCONNECTION @@ -318,7 +323,6 @@ typedef struct ldapcontrol { #define LDAP_EXOP_X_CANCEL LDAP_EXOP_CANCEL /* various works in progress */ - #define LDAP_EXOP_WHO_AM_I "1.3.6.1.4.1.4203.1.11.3" #define LDAP_EXOP_X_WHO_AM_I LDAP_EXOP_WHO_AM_I @@ -470,7 +474,6 @@ typedef struct ldapcontrol { #define LDAP_SUBSTRING_FINAL ((ber_tag_t) 0x82U) /* context specific */ /* search scopes */ -#define LDAP_SCOPE_DEFAULT ((ber_int_t) -1) /* OpenLDAP extension */ #define LDAP_SCOPE_BASE ((ber_int_t) 0x0000) #define LDAP_SCOPE_BASEOBJECT LDAP_SCOPE_BASE #define LDAP_SCOPE_ONELEVEL ((ber_int_t) 0x0001) @@ -479,6 +482,7 @@ typedef struct ldapcontrol { #define LDAP_SCOPE_SUB LDAP_SCOPE_SUBTREE #define LDAP_SCOPE_SUBORDINATE ((ber_int_t) 0x0003) /* OpenLDAP extension */ #define LDAP_SCOPE_CHILDREN LDAP_SCOPE_SUBORDINATE +#define LDAP_SCOPE_DEFAULT ((ber_int_t) -1) /* OpenLDAP extension */ /* substring filter component types */ #define LDAP_SUBSTRING_INITIAL ((ber_tag_t) 0x80U) /* context specific */ @@ -550,7 +554,7 @@ typedef struct ldapcontrol { #define LDAP_ALREADY_EXISTS 0x44 #define LDAP_NO_OBJECT_CLASS_MODS 0x45 #define LDAP_RESULTS_TOO_LARGE 0x46 /* CLDAP */ -#define LDAP_AFFECTS_MULTIPLE_DSAS 0x47 /* LDAPv3 */ +#define LDAP_AFFECTS_MULTIPLE_DSAS 0x47 #define LDAP_OTHER 0x50 @@ -567,27 +571,34 @@ typedef struct ldapcontrol { #define LDAP_TOO_LATE 0x78 #define LDAP_CANNOT_CANCEL 0x79 +/* Assertion control (122) */ +#define LDAP_ASSERTION_FAILED 0x7A + /* Experimental result codes */ -#define LDAP_E_ERROR(n) LDAP_RANGE((n),0x1000,0x3FFF) /* experimental */ -#define LDAP_X_ERROR(n) LDAP_RANGE((n),0x4000,0xFFFF) /* private use */ +#define LDAP_E_ERROR(n) LDAP_RANGE((n),0x1000,0x3FFF) -/* for the LDAP Sync operation */ -#define LDAP_SYNC_REFRESH_REQUIRED 0x4100 +/* LDAP Sync (4096) */ +#define LDAP_SYNC_REFRESH_REQUIRED 0x1000 -/* for the LDAP No-Op control */ -#define LDAP_NO_OPERATION 0x410e -/* for the Assertion control */ -#define LDAP_ASSERTION_FAILED 0x410f +/* Private Use result codes */ +#define LDAP_X_ERROR(n) LDAP_RANGE((n),0x4000,0xFFFF) + +#define LDAP_X_SYNC_REFRESH_REQUIRED 0x4100 /* defunct */ +#define LDAP_X_ASSERTION_FAILED 0x410f /* defunct */ + +/* for the LDAP No-Op control */ +#define LDAP_X_NO_OPERATION 0x410e /* for the Chaining Behavior control (consecutive result codes requested; * see ) */ #ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR -#define LDAP_NO_REFERRALS_FOUND 0x4110 -#define LDAP_CANNOT_CHAIN 0x4111 +#define LDAP_X_NO_REFERRALS_FOUND 0x4110 +#define LDAP_X_CANNOT_CHAIN 0x4111 #endif + /* API Error Codes * * Based on draft-ietf-ldap-c-api-xx @@ -1664,6 +1675,11 @@ ldap_msgdelete LDAP_P(( * in search.c: */ LDAP_F( int ) +ldap_bv2escaped_filter_value LDAP_P(( + struct berval *in, + struct berval *out )); + +LDAP_F( int ) ldap_search_ext LDAP_P(( LDAP *ld, LDAP_CONST char *base, diff --git a/include/portable.hin b/include/portable.hin index e339b15d12..10425199a3 100644 --- a/include/portable.hin +++ b/include/portable.hin @@ -102,7 +102,7 @@ /* define if Berkeley DB has DB_THREAD support */ #undef HAVE_BERKELEY_DB_THREAD -/* define if you have SSLeay or OpenSSL's BIGNUM */ +/* define if you have OpenSSL's BIGNUM */ #undef HAVE_BIGNUM /* Define to 1 if you have the header file. */ @@ -277,6 +277,9 @@ /* define to you inet_aton(3) is available */ #undef HAVE_INET_ATON +/* Define to 1 if you have the `inet_ntoa_b' function. */ +#undef HAVE_INET_NTOA_B + /* Define to 1 if you have the `inet_ntop' function. */ #undef HAVE_INET_NTOP @@ -427,6 +430,9 @@ /* if you have NT Threads */ #undef HAVE_NT_THREADS +/* define if you have OpenSSL */ +#undef HAVE_OPENSSL + /* Define to 1 if you have the header file. */ #undef HAVE_OPENSSL_BN_H @@ -508,7 +514,7 @@ /* define if you have res_query() */ #undef HAVE_RES_QUERY -/* define if you have RSAref */ +/* define if OpenSSL needs RSAref */ #undef HAVE_RSAREF /* Define to 1 if you have the header file. */ @@ -589,12 +595,6 @@ /* Define to 1 if you have the header file. */ #undef HAVE_SQL_H -/* define if you have SSLeay or OpenSSL */ -#undef HAVE_SSLEAY - -/* Define to 1 if you have the header file. */ -#undef HAVE_SSL_H - /* Define to 1 if you have the header file. */ #undef HAVE_STDDEF_H diff --git a/libraries/libldap/cyrus.c b/libraries/libldap/cyrus.c index 99893b285d..ebaa7a3391 100644 --- a/libraries/libldap/cyrus.c +++ b/libraries/libldap/cyrus.c @@ -594,7 +594,8 @@ ldap_int_sasl_bind( 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 ); + 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; @@ -612,9 +613,11 @@ ldap_int_sasl_bind( ld->ld_defconn->lconn_sasl_authctx = NULL; } - { char *saslhost = ldap_host_connected_to( ld->ld_defconn->lconn_sb, "localhost" ); - rc = ldap_int_sasl_open( ld, ld->ld_defconn, saslhost ); - LDAP_FREE( saslhost ); + { + char *saslhost = ldap_host_connected_to( ld->ld_defconn->lconn_sb, + "localhost" ); + rc = ldap_int_sasl_open( ld, ld->ld_defconn, saslhost ); + LDAP_FREE( saslhost ); } if ( rc != LDAP_SUCCESS ) return rc; @@ -637,13 +640,16 @@ ldap_int_sasl_bind( #if !defined(_WIN32) /* Check for local */ - if ( ldap_pvt_url_scheme2proto( ld->ld_defconn->lconn_server->lud_scheme ) == LDAP_PROTO_IPC ) { - char authid[sizeof("uidNumber=4294967295+gidNumber=4294967295," + if ( ldap_pvt_url_scheme2proto( + ld->ld_defconn->lconn_server->lud_scheme ) == LDAP_PROTO_IPC ) + { + char authid[sizeof("gidNumber=4294967295+uidNumber=4294967295," "cn=peercred,cn=external,cn=auth")]; - sprintf( authid, "uidNumber=%d+gidNumber=%d," + sprintf( authid, "gidNumber=%d+uidNumber=%d," "cn=peercred,cn=external,cn=auth", - (int) geteuid(), (int) getegid() ); - (void) ldap_int_sasl_external( ld, ld->ld_defconn, authid, LDAP_PVT_SASL_LOCAL_SSF ); + (int) getegid(), (int) geteuid() ); + (void) ldap_int_sasl_external( ld, ld->ld_defconn, authid, + LDAP_PVT_SASL_LOCAL_SSF ); } #endif @@ -703,7 +709,8 @@ ldap_int_sasl_bind( scred = NULL; - rc = ldap_sasl_bind_s( ld, dn, mech, &ccred, sctrls, cctrls, &scred ); + rc = ldap_sasl_bind_s( ld, dn, mech, &ccred, sctrls, cctrls, + &scred ); if ( ccred.bv_val != NULL ) { #if SASL_VERSION_MAJOR < 2 @@ -714,13 +721,12 @@ ldap_int_sasl_bind( if ( rc != LDAP_SUCCESS && rc != LDAP_SASL_BIND_IN_PROGRESS ) { if( scred ) { - if ( scred->bv_len ) { - /* and server provided us with data? */ - Debug( LDAP_DEBUG_TRACE, - "ldap_int_sasl_bind: rc=%d sasl=%d len=%ld\n", - rc, saslrc, scred->bv_len ); - } + /* and server provided us with data? */ + Debug( LDAP_DEBUG_TRACE, + "ldap_int_sasl_bind: rc=%d sasl=%d len=%ld\n", + rc, saslrc, scred ? scred->bv_len : -1 ); ber_bvfree( scred ); + scred = NULL; } rc = ld->ld_errno; goto done; @@ -729,12 +735,11 @@ ldap_int_sasl_bind( if( rc == LDAP_SUCCESS && saslrc == SASL_OK ) { /* we're done, no need to step */ if( scred ) { - if ( scred->bv_len ) { - /* but server provided us with data! */ - Debug( LDAP_DEBUG_TRACE, - "ldap_int_sasl_bind: rc=%d sasl=%d len=%ld\n", - rc, saslrc, scred->bv_len ); - } + /* but we got additional data? */ + Debug( LDAP_DEBUG_TRACE, + "ldap_int_sasl_bind: rc=%d sasl=%d len=%ld\n", + rc, saslrc, scred ? scred->bv_len : -1 ); + ber_bvfree( scred ); rc = ld->ld_errno = LDAP_LOCAL_ERROR; goto done; @@ -743,6 +748,13 @@ ldap_int_sasl_bind( } do { + if( ! scred ) { + /* no data! */ + Debug( LDAP_DEBUG_TRACE, + "ldap_int_sasl_bind: no data in step!\n", + 0, 0, 0 ); + } + saslrc = sasl_client_step( ctx, (scred == NULL) ? NULL : scred->bv_val, (scred == NULL) ? 0 : scred->bv_len, @@ -791,13 +803,15 @@ ldap_int_sasl_bind( } if( flags != LDAP_SASL_QUIET ) { - saslrc = sasl_getprop( ctx, SASL_USERNAME, (SASL_CONST void **) &data ); + saslrc = sasl_getprop( ctx, SASL_USERNAME, + (SASL_CONST void **) &data ); if( saslrc == SASL_OK && data && *data ) { fprintf( stderr, "SASL username: %s\n", data ); } #if SASL_VERSION_MAJOR < 2 - saslrc = sasl_getprop( ctx, SASL_REALM, (SASL_CONST void **) &data ); + saslrc = sasl_getprop( ctx, SASL_REALM, + (SASL_CONST void **) &data ); if( saslrc == SASL_OK && data && *data ) { fprintf( stderr, "SASL realm: %s\n", data ); } diff --git a/libraries/libldap/error.c b/libraries/libldap/error.c index db26ae97ce..529a3e2eea 100644 --- a/libraries/libldap/error.c +++ b/libraries/libldap/error.c @@ -85,6 +85,19 @@ static struct ldaperror ldap_builtin_errlist[] = { {LDAP_OTHER, N_("Internal (implementation specific) error")}, + {LDAP_CANCELLED, N_("Cancelled")}, + {LDAP_NO_SUCH_OPERATION, N_("No Operation to Cancel")}, + {LDAP_TOO_LATE, N_("Too Late to Cancel")}, + {LDAP_CANNOT_CANCEL, N_("Cannot Cancel")}, + + {LDAP_ASSERTION_FAILED, N_("Assertion Failed")}, + {LDAP_X_ASSERTION_FAILED, N_("Assertion Failed (X)")}, + + {LDAP_SYNC_REFRESH_REQUIRED, N_("Content Sync Refresh Required")}, + {LDAP_X_SYNC_REFRESH_REQUIRED, N_("Content Sync Refresh Required (X)")}, + + {LDAP_X_NO_OPERATION, N_("No Operation (X)")}, + /* API ResultCodes */ {LDAP_SERVER_DOWN, N_("Can't contact LDAP server")}, {LDAP_LOCAL_ERROR, N_("Local error")}, @@ -105,22 +118,12 @@ static struct ldaperror ldap_builtin_errlist[] = { {LDAP_CLIENT_LOOP, N_("Client Loop")}, {LDAP_REFERRAL_LIMIT_EXCEEDED, N_("Referral Limit Exceeded")}, - {LDAP_SYNC_REFRESH_REQUIRED, N_("Content Sync Refresh Required")}, - - {LDAP_NO_OPERATION, N_("No Operation")}, - {LDAP_ASSERTION_FAILED, N_("Assertion Failed")}, - {LDAP_CUP_RESOURCES_EXHAUSTED, N_("LCUP Resources Exhausted")}, {LDAP_CUP_SECURITY_VIOLATION, N_("LCUP Security Violation")}, {LDAP_CUP_INVALID_DATA, N_("LCUP Invalid Data")}, {LDAP_CUP_UNSUPPORTED_SCHEME, N_("LCUP Unsupported Scheme")}, {LDAP_CUP_RELOAD_REQUIRED, N_("LCUP Reload Required")}, - {LDAP_CANCELLED, N_("Cancelled")}, - {LDAP_NO_SUCH_OPERATION, N_("No Operation to Cancel")}, - {LDAP_TOO_LATE, N_("Too Late to Cancel")}, - {LDAP_CANNOT_CANCEL, N_("Cannot Cancel")}, - {0, NULL} }; diff --git a/libraries/libldap/init.c b/libraries/libldap/init.c index fe47f8dc39..cb0fc14e9a 100644 --- a/libraries/libldap/init.c +++ b/libraries/libldap/init.c @@ -110,7 +110,7 @@ static const struct ol_attribute { {0, ATTR_NONE, NULL, NULL, 0} }; -#define MAX_LDAP_ATTR_LEN sizeof("TLS_CACERTDIR") +#define MAX_LDAP_ATTR_LEN sizeof("TLS_CIPHER_SUITE") #define MAX_LDAP_ENV_PREFIX_LEN 8 static void openldap_ldap_init_w_conf( @@ -409,6 +409,11 @@ ldap_int_destroy_global_options(void) #if defined(HAVE_WINSOCK) || defined(HAVE_WINSOCK2) WSACleanup( ); #endif + + if ( ldap_int_hostname ) { + LDAP_FREE( ldap_int_hostname ); + ldap_int_hostname = NULL; + } } /* @@ -529,7 +534,15 @@ void ldap_int_initialize( struct ldapoptions *gopts, int *dbglvl ) #if defined(LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND) \ || defined(HAVE_TLS) || defined(HAVE_CYRUS_SASL) - ldap_int_hostname = ldap_pvt_get_fqdn( ldap_int_hostname ); + { + char *name = ldap_int_hostname; + + ldap_int_hostname = ldap_pvt_get_fqdn( name ); + + if ( name != NULL && name != ldap_int_hostname ) { + LDAP_FREE( name ); + } + } #endif #ifndef HAVE_POLL diff --git a/libraries/libldap/os-ip.c b/libraries/libldap/os-ip.c index 65341b5e84..0c5fb36b8b 100644 --- a/libraries/libldap/os-ip.c +++ b/libraries/libldap/os-ip.c @@ -529,8 +529,18 @@ ldap_connect_to_host(LDAP *ld, Sockbuf *sb, sizeof(sin.sin_addr) ); } +#ifdef HAVE_INET_NTOA_B + { + /* for VxWorks */ + char address[INET_ADDR_LEN]; + inet_ntoa_b(sin.sin_address, address); + osip_debug(ld, "ldap_connect_to_host: Trying %s:%d\n", + address, port, 0); + } +#else osip_debug(ld, "ldap_connect_to_host: Trying %s:%d\n", inet_ntoa(sin.sin_addr), port, 0); +#endif rc = ldap_pvt_connect(ld, s, (struct sockaddr *)&sin, sizeof(sin), diff --git a/libraries/libldap/search.c b/libraries/libldap/search.c index a2d97a3e01..d78eeb84ad 100644 --- a/libraries/libldap/search.c +++ b/libraries/libldap/search.c @@ -365,3 +365,53 @@ ldap_search_s( return( ldap_result2error( ld, *res, 0 ) ); } +int +ldap_bv2escaped_filter_value( struct berval *in, struct berval *out ) +{ + char c; + ber_len_t i; + static char escape[128] = { + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + + 1, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1 + }; + + out->bv_len = 0; + out->bv_val = NULL; + + if( in->bv_len == 0 ) return 0; + + /* assume we'll escape everything */ + out->bv_val = LDAP_MALLOC( 3 * in->bv_len + 1 ); + if( out->bv_val == NULL ) return -1; + + for( i=0; ibv_len; i++ ) { + if (c & 0x80 || escape[in->bv_val[i]]) { + out->bv_val[out->bv_len++] = '\\'; + out->bv_val[out->bv_len++] = "0123456789ABCDEF"[0x0f & (c>>4)]; + out->bv_val[out->bv_len++] = "0123456789ABCDEF"[0x0f & c]; + } else { + out->bv_val[out->bv_len++] = c; + } + } + + out->bv_val[out->bv_len] = '\0'; + return 0; +} + diff --git a/libraries/libldap/tls.c b/libraries/libldap/tls.c index 2b8cafb52a..c03c8446a8 100644 --- a/libraries/libldap/tls.c +++ b/libraries/libldap/tls.c @@ -50,6 +50,7 @@ static int tls_opt_trace = 1; static char *tls_opt_certfile = NULL; static char *tls_opt_keyfile = NULL; +static char *tls_opt_dhfile = NULL; static char *tls_opt_cacertfile = NULL; static char *tls_opt_cacertdir = NULL; static int tls_opt_require_cert = LDAP_OPT_X_TLS_DEMAND; @@ -70,12 +71,18 @@ static int tls_verify_ok( int ok, X509_STORE_CTX *ctx ); static RSA * tls_tmp_rsa_cb( SSL *ssl, int is_export, int key_length ); static STACK_OF(X509_NAME) * get_ca_list( char * bundle, char * dir ); -#if 0 /* Currently this is not used by anyone */ static DH * tls_tmp_dh_cb( SSL *ssl, int is_export, int key_length ); -#endif static SSL_CTX *tls_def_ctx = NULL; +typedef struct dhplist { + struct dhplist *next; + int keylength; + DH *param; +} dhplist; + +static dhplist *dhparams; + static int tls_seed_PRNG( const char *randfile ); #ifdef LDAP_R_COMPILE @@ -134,6 +141,10 @@ ldap_pvt_tls_destroy( void ) LDAP_FREE( tls_opt_keyfile ); tls_opt_keyfile = NULL; } + if ( tls_opt_dhfile ) { + LDAP_FREE( tls_opt_dhfile ); + tls_opt_dhfile = NULL; + } if ( tls_opt_cacertfile ) { LDAP_FREE( tls_opt_cacertfile ); tls_opt_cacertfile = NULL; @@ -198,6 +209,7 @@ ldap_pvt_tls_init_def_ctx( void ) char *cacertdir = tls_opt_cacertdir; char *certfile = tls_opt_certfile; char *keyfile = tls_opt_keyfile; + char *dhfile = tls_opt_dhfile; #ifdef LDAP_R_COMPILE ldap_pvt_thread_mutex_lock( &tls_def_ctx_mutex ); @@ -205,6 +217,9 @@ ldap_pvt_tls_init_def_ctx( void ) if ( !certfile && !keyfile && !cacertfile && !cacertdir ) { /* minimum configuration not provided */ +#ifdef LDAP_R_COMPILE + ldap_pvt_thread_mutex_unlock( &tls_def_ctx_mutex ); +#endif return LDAP_NOT_SUPPORTED; } @@ -230,6 +245,10 @@ ldap_pvt_tls_init_def_ctx( void ) keyfile = LDAP_STRDUP( keyfile ); __atoe( keyfile ); } + if ( dhfile ) { + dhfile = LDAP_STRDUP( dhfile ); + __atoe( dhfile ); + } #endif if ( tls_def_ctx == NULL ) { int i; @@ -321,6 +340,31 @@ ldap_pvt_tls_init_def_ctx( void ) goto error_exit; } + if ( tls_opt_dhfile ) { + DH *dh = NULL; + BIO *bio; + dhplist *p; + + if (( bio=BIO_new_file( dhfile,"r" )) == NULL ) { + Debug( LDAP_DEBUG_ANY, + "TLS: could not use DH parameters file `%s'.\n", + tls_opt_dhfile,0,0); + tls_report_error(); + rc = -1; + goto error_exit; + } + while (( dh=PEM_read_bio_DHparams( bio, NULL, NULL, NULL ))) { + p = LDAP_MALLOC( sizeof(dhplist) ); + if ( p != NULL ) { + p->keylength = DH_size( dh ) * 8; + p->param = dh; + p->next = dhparams; + dhparams = p; + } + } + BIO_free( bio ); + } + if ( tls_opt_trace ) { SSL_CTX_set_info_callback( tls_def_ctx, tls_info_cb ); } @@ -338,7 +382,7 @@ ldap_pvt_tls_init_def_ctx( void ) tls_opt_require_cert == LDAP_OPT_X_TLS_ALLOW ? tls_verify_ok : tls_verify_cb ); SSL_CTX_set_tmp_rsa_callback( tls_def_ctx, tls_tmp_rsa_cb ); - /* SSL_CTX_set_tmp_dh_callback( tls_def_ctx, tls_tmp_dh_cb ); */ + SSL_CTX_set_tmp_dh_callback( tls_def_ctx, tls_tmp_dh_cb ); #ifdef HAVE_OPENSSL_CRL if ( tls_opt_crlcheck ) { X509_STORE *x509_s = SSL_CTX_get_cert_store( tls_def_ctx ); @@ -362,6 +406,7 @@ error_exit: LDAP_FREE( cacertdir ); LDAP_FREE( certfile ); LDAP_FREE( keyfile ); + LDAP_FREE( dhfile ); #endif #ifdef LDAP_R_COMPILE ldap_pvt_thread_mutex_unlock( &tls_def_ctx_mutex ); @@ -1121,6 +1166,7 @@ ldap_int_tls_config( LDAP *ld, int option, const char *arg ) case LDAP_OPT_X_TLS_KEYFILE: case LDAP_OPT_X_TLS_RANDOM_FILE: case LDAP_OPT_X_TLS_CIPHER_SUITE: + case LDAP_OPT_X_TLS_DHFILE: return ldap_pvt_tls_set_option( ld, option, (void *) arg ); case LDAP_OPT_X_TLS_REQUIRE_CERT: @@ -1218,6 +1264,10 @@ ldap_pvt_tls_get_option( LDAP *ld, int option, void *arg ) *(char **)arg = tls_opt_keyfile ? LDAP_STRDUP( tls_opt_keyfile ) : NULL; break; + case LDAP_OPT_X_TLS_DHFILE: + *(char **)arg = tls_opt_dhfile ? + LDAP_STRDUP( tls_opt_dhfile ) : NULL; + break; case LDAP_OPT_X_TLS_REQUIRE_CERT: *(int *)arg = tls_opt_require_cert; break; @@ -1329,6 +1379,10 @@ ldap_pvt_tls_set_option( LDAP *ld, int option, void *arg ) if ( tls_opt_keyfile ) LDAP_FREE( tls_opt_keyfile ); tls_opt_keyfile = arg ? LDAP_STRDUP( (char *) arg ) : NULL; break; + case LDAP_OPT_X_TLS_DHFILE: + if ( tls_opt_dhfile ) LDAP_FREE( tls_opt_dhfile ); + tls_opt_dhfile = arg ? LDAP_STRDUP( (char *) arg ) : NULL; + break; case LDAP_OPT_X_TLS_REQUIRE_CERT: switch( *(int *) arg ) { case LDAP_OPT_X_TLS_NEVER: @@ -1626,13 +1680,114 @@ tls_seed_PRNG( const char *randfile ) return 0; } -#if 0 +struct dhinfo { + int keylength; + const char *pem; + size_t size; +}; + + +/* From the OpenSSL 0.9.7 distro */ +static const char dhpem512[] = +"-----BEGIN DH PARAMETERS-----\n\ +MEYCQQDaWDwW2YUiidDkr3VvTMqS3UvlM7gE+w/tlO+cikQD7VdGUNNpmdsp13Yn\n\ +a6LT1BLiGPTdHghM9tgAPnxHdOgzAgEC\n\ +-----END DH PARAMETERS-----\n"; + +static const char dhpem1024[] = +"-----BEGIN DH PARAMETERS-----\n\ +MIGHAoGBAJf2QmHKtQXdKCjhPx1ottPb0PMTBH9A6FbaWMsTuKG/K3g6TG1Z1fkq\n\ +/Gz/PWk/eLI9TzFgqVAuPvr3q14a1aZeVUMTgo2oO5/y2UHe6VaJ+trqCTat3xlx\n\ +/mNbIK9HA2RgPC3gWfVLZQrY+gz3ASHHR5nXWHEyvpuZm7m3h+irAgEC\n\ +-----END DH PARAMETERS-----\n"; + +static const char dhpem2048[] = +"-----BEGIN DH PARAMETERS-----\n\ +MIIBCAKCAQEA7ZKJNYJFVcs7+6J2WmkEYb8h86tT0s0h2v94GRFS8Q7B4lW9aG9o\n\ +AFO5Imov5Jo0H2XMWTKKvbHbSe3fpxJmw/0hBHAY8H/W91hRGXKCeyKpNBgdL8sh\n\ +z22SrkO2qCnHJ6PLAMXy5fsKpFmFor2tRfCzrfnggTXu2YOzzK7q62bmqVdmufEo\n\ +pT8igNcLpvZxk5uBDvhakObMym9mX3rAEBoe8PwttggMYiiw7NuJKO4MqD1llGkW\n\ +aVM8U2ATsCun1IKHrRxynkE1/MJ86VHeYYX8GZt2YA8z+GuzylIOKcMH6JAWzMwA\n\ +Gbatw6QwizOhr9iMjZ0B26TE3X8LvW84wwIBAg==\n\ +-----END DH PARAMETERS-----\n"; + +static const char dhpem4096[] = +"-----BEGIN DH PARAMETERS-----\n\ +MIICCAKCAgEA/urRnb6vkPYc/KEGXWnbCIOaKitq7ySIq9dTH7s+Ri59zs77zty7\n\ +vfVlSe6VFTBWgYjD2XKUFmtqq6CqXMhVX5ElUDoYDpAyTH85xqNFLzFC7nKrff/H\n\ +TFKNttp22cZE9V0IPpzedPfnQkE7aUdmF9JnDyv21Z/818O93u1B4r0szdnmEvEF\n\ +bKuIxEHX+bp0ZR7RqE1AeifXGJX3d6tsd2PMAObxwwsv55RGkn50vHO4QxtTARr1\n\ +rRUV5j3B3oPMgC7Offxx+98Xn45B1/G0Prp11anDsR1PGwtaCYipqsvMwQUSJtyE\n\ +EOQWk+yFkeMe4vWv367eEi0Sd/wnC+TSXBE3pYvpYerJ8n1MceI5GQTdarJ77OW9\n\ +bGTHmxRsLSCM1jpLdPja5jjb4siAa6EHc4qN9c/iFKS3PQPJEnX7pXKBRs5f7AF3\n\ +W3RIGt+G9IVNZfXaS7Z/iCpgzgvKCs0VeqN38QsJGtC1aIkwOeyjPNy2G6jJ4yqH\n\ +ovXYt/0mc00vCWeSNS1wren0pR2EiLxX0ypjjgsU1mk/Z3b/+zVf7fZSIB+nDLjb\n\ +NPtUlJCVGnAeBK1J1nG3TQicqowOXoM6ISkdaXj5GPJdXHab2+S7cqhKGv5qC7rR\n\ +jT6sx7RUr0CNTxzLI7muV2/a4tGmj0PSdXQdsZ7tw7gbXlaWT1+MM2MCAQI=\n\ +-----END DH PARAMETERS-----\n"; + +static const struct dhinfo dhpem[] = { + { 512, dhpem512, sizeof(dhpem512) }, + { 1024, dhpem1024, sizeof(dhpem1024) }, + { 2048, dhpem2048, sizeof(dhpem2048) }, + { 4096, dhpem4096, sizeof(dhpem4096) }, + { 0, NULL, 0 } +}; + static DH * tls_tmp_dh_cb( SSL *ssl, int is_export, int key_length ) { - return NULL; -} + struct dhplist *p = NULL; + BIO *b = NULL; + DH *dh = NULL; + int i; + + /* Do we have params of this length already? */ +#ifdef LDAP_R_COMPILE + ldap_pvt_thread_mutex_lock( &tls_def_ctx_mutex ); +#endif + for ( p = dhparams; p; p=p->next ) { + if ( p->keylength == key_length ) { +#ifdef LDAP_R_COMPILE + ldap_pvt_thread_mutex_unlock( &tls_def_ctx_mutex ); #endif + return p->param; + } + } + + /* No - check for hardcoded params */ + + for (i=0; dhpem[i].keylength; i++) { + if ( dhpem[i].keylength == key_length ) { + b = BIO_new_mem_buf( (char *)dhpem[i].pem, dhpem[i].size ); + break; + } + } + + if ( b ) { + dh = PEM_read_bio_DHparams( b, NULL, NULL, NULL ); + BIO_free( b ); + } + + /* Generating on the fly is expensive/slow... */ + if ( !dh ) { + dh = DH_generate_parameters( key_length, DH_GENERATOR_2, NULL, NULL ); + } + if ( dh ) { + p = LDAP_MALLOC( sizeof(struct dhplist) ); + if ( p != NULL ) { + p->keylength = key_length; + p->param = dh; + p->next = dhparams; + dhparams = p; + } + } +done: +#ifdef LDAP_R_COMPILE + ldap_pvt_thread_mutex_unlock( &tls_def_ctx_mutex ); +#endif + return dh; +} #endif void * diff --git a/libraries/libldap/utf-8-conv.c b/libraries/libldap/utf-8-conv.c index df477822f7..b35941db3a 100644 --- a/libraries/libldap/utf-8-conv.c +++ b/libraries/libldap/utf-8-conv.c @@ -79,8 +79,8 @@ ASCII chars 7 bits Unicode address space (0 - 0x10FFFF) 21 bits ISO-10646 address space (0 - 0x7FFFFFFF) 31 bits -Note: This code does not prevent UTF-8 sequences which are longer than - necessary from being decoded. +Note: This code does not prevent UTF-8 sequences which are longer than + necessary from being decoded. */ /*----------------------------------------------------------------------------- @@ -93,31 +93,25 @@ ldap_x_utf8_to_wc ( wchar_t *wchar, const char *utf8char ) int utflen, i; wchar_t ch; - /* If input ptr is NULL, treat it as empty string. */ - if (utf8char == NULL) - utf8char = ""; + if (utf8char == NULL) return -1; /* Get UTF-8 sequence length from 1st byte */ utflen = LDAP_UTF8_CHARLEN2(utf8char, utflen); - if( utflen==0 || utflen > (int)LDAP_MAX_UTF8_LEN ) - return -1; /* Invalid input */ + if( utflen==0 || utflen > (int)LDAP_MAX_UTF8_LEN ) return -1; /* First byte minus length tag */ ch = (wchar_t)(utf8char[0] & mask[utflen]); - for(i=1; i < utflen; i++) - { + for(i=1; i < utflen; i++) { /* Subsequent bytes must start with 10 */ - if ((utf8char[i] & 0xc0) != 0x80) - return -1; + if ((utf8char[i] & 0xc0) != 0x80) return -1; ch <<= 6; /* 6 bits of data in each subsequent byte */ ch |= (wchar_t)(utf8char[i] & 0x3f); } - if (wchar) - *wchar = ch; + if (wchar) *wchar = ch; return utflen; } @@ -136,41 +130,34 @@ ldap_x_utf8s_to_wcs ( wchar_t *wcstr, const char *utf8str, size_t count ) /* If input ptr is NULL, treat it as empty string. */ - if (utf8str == NULL) - utf8str = ""; + if (utf8str == NULL) utf8str = ""; /* Examine next UTF-8 character. If output buffer is NULL, ignore count */ - while ( *utf8str && (wcstr==NULL || wclen (int)LDAP_MAX_UTF8_LEN ) - return -1; /* Invalid input */ + if( utflen==0 || utflen > (int)LDAP_MAX_UTF8_LEN ) return -1; /* First byte minus length tag */ ch = (wchar_t)(utf8str[0] & mask[utflen]); - for(i=1; i < utflen; i++) - { + for(i=1; i < utflen; i++) { /* Subsequent bytes must start with 10 */ - if ((utf8str[i] & 0xc0) != 0x80) - return -1; + if ((utf8str[i] & 0xc0) != 0x80) return -1; ch <<= 6; /* 6 bits of data in each subsequent byte */ ch |= (wchar_t)(utf8str[i] & 0x3f); } - if (wcstr) - wcstr[wclen] = ch; + if (wcstr) wcstr[wclen] = ch; - utf8str += utflen; /* Move to next UTF-8 character */ - wclen++; /* Count number of wide chars stored/required */ + utf8str += utflen; /* Move to next UTF-8 character */ + wclen++; /* Count number of wide chars stored/required */ } /* Add null terminator if there's room in the buffer. */ - if (wcstr && wclen < count) - wcstr[wclen] = 0; + if (wcstr && wclen < count) wcstr[wclen] = 0; return wclen; } diff --git a/libraries/libldap/util-int.c b/libraries/libldap/util-int.c index 089a17cafd..c913b1833c 100644 --- a/libraries/libldap/util-int.c +++ b/libraries/libldap/util-int.c @@ -303,7 +303,7 @@ int ldap_pvt_get_hname( rc = 0; } else { rc = h_errno; - *err = (char *)hp_strerror( h_errno ); + *err = (char *)HSTRERROR( h_errno ); } #if defined( LDAP_R_COMPILE ) ldap_pvt_thread_mutex_unlock( &ldap_int_resolv_mutex ); diff --git a/libraries/libldap_r/tpool.c b/libraries/libldap_r/tpool.c index ba87eaa989..41a3fc556d 100644 --- a/libraries/libldap_r/tpool.c +++ b/libraries/libldap_r/tpool.c @@ -243,13 +243,9 @@ ldap_pvt_thread_pool_submit ( return(0); } ldap_pvt_thread_cond_signal(&pool->ltp_cond); - if ((pool->ltp_open_count <= 0 -#if 0 - || pool->ltp_pending_count > 1 -#endif - || pool->ltp_open_count == pool->ltp_active_count) - && (pool->ltp_max_count <= 0 - || pool->ltp_open_count < pool->ltp_max_count)) + if (pool->ltp_open_count < pool->ltp_active_count + pool->ltp_pending_count + && (pool->ltp_open_count < pool->ltp_max_count || + pool->ltp_max_count <= 0 )) { pool->ltp_open_count++; pool->ltp_starting++; diff --git a/libraries/librewrite/info.c b/libraries/librewrite/info.c index 53f759975d..32b5544ebf 100644 --- a/libraries/librewrite/info.c +++ b/libraries/librewrite/info.c @@ -81,10 +81,13 @@ rewrite_info_init( #ifdef USE_REWRITE_LDAP_PVT_THREADS if ( ldap_pvt_thread_rdwr_init( &info->li_cookies_mutex ) ) { + avl_free( info->li_context, rewrite_context_free ); free( info ); return NULL; } if ( ldap_pvt_thread_rdwr_init( &info->li_params_mutex ) ) { + ldap_pvt_thread_rdwr_destroy( &info->li_cookies_mutex ); + avl_free( info->li_context, rewrite_context_free ); free( info ); return NULL; } @@ -116,7 +119,7 @@ rewrite_info_delete( if ( info->li_maps ) { avl_free( info->li_maps, rewrite_builtin_map_free ); } - info->li_context = NULL; + info->li_maps = NULL; rewrite_session_destroy( info ); diff --git a/libraries/librewrite/session.c b/libraries/librewrite/session.c index bd0685167c..4fa58f876c 100644 --- a/libraries/librewrite/session.c +++ b/libraries/librewrite/session.c @@ -302,6 +302,32 @@ rewrite_session_var_get( return REWRITE_SUCCESS; } +static void +rewrite_session_clean( void *v_session ) +{ + struct rewrite_session *session = (struct rewrite_session *)v_session; + +#ifdef USE_REWRITE_LDAP_PVT_THREADS + ldap_pvt_thread_rdwr_wlock( &session->ls_vars_mutex ); +#endif /* USE_REWRITE_LDAP_PVT_THREADS */ + + rewrite_var_delete( session->ls_vars ); + +#ifdef USE_REWRITE_LDAP_PVT_THREADS + ldap_pvt_thread_rdwr_wunlock( &session->ls_vars_mutex ); + ldap_pvt_thread_rdwr_destroy( &session->ls_vars_mutex ); + ldap_pvt_thread_mutex_unlock( &session->ls_mutex ); + ldap_pvt_thread_mutex_destroy( &session->ls_mutex ); +#endif /* USE_REWRITE_LDAP_PVT_THREADS */ +} + +static void +rewrite_session_free( void *v_session ) +{ + rewrite_session_clean( v_session ); + free( v_session ); +} + /* * Deletes a session */ @@ -311,13 +337,11 @@ rewrite_session_delete( const void *cookie ) { - struct rewrite_session *session, tmp; + struct rewrite_session *session, tmp = { 0 }; assert( info != NULL ); assert( cookie != NULL ); - tmp.ls_cookie = ( void * )cookie; - session = rewrite_session_find( info, cookie ); if ( session == NULL ) { @@ -329,18 +353,7 @@ rewrite_session_delete( return REWRITE_SUCCESS; } -#ifdef USE_REWRITE_LDAP_PVT_THREADS - ldap_pvt_thread_rdwr_wlock( &session->ls_vars_mutex ); -#endif /* USE_REWRITE_LDAP_PVT_THREADS */ - - rewrite_var_delete( session->ls_vars ); - -#ifdef USE_REWRITE_LDAP_PVT_THREADS - ldap_pvt_thread_rdwr_wunlock( &session->ls_vars_mutex ); - ldap_pvt_thread_rdwr_destroy( &session->ls_vars_mutex ); - ldap_pvt_thread_mutex_unlock( &session->ls_mutex ); - ldap_pvt_thread_mutex_destroy( &session->ls_mutex ); -#endif /* USE_REWRITE_LDAP_PVT_THREADS */ + rewrite_session_clean( session ); #ifdef USE_REWRITE_LDAP_PVT_THREADS ldap_pvt_thread_rdwr_wlock( &info->li_cookies_mutex ); @@ -352,7 +365,9 @@ rewrite_session_delete( /* * There is nothing to delete in the return value */ + tmp.ls_cookie = ( void * )cookie; avl_delete( &info->li_cookies, ( caddr_t )&tmp, rewrite_cookie_cmp ); + free( session ); #ifdef USE_REWRITE_LDAP_PVT_THREADS @@ -382,7 +397,7 @@ rewrite_session_destroy( * Should call per-session destruction routine ... */ - count = avl_free( info->li_cookies, NULL ); + count = avl_free( info->li_cookies, rewrite_session_free ); info->li_cookies = NULL; #if 0 diff --git a/servers/slapd/aci.c b/servers/slapd/aci.c index 6b44e80244..a77a9fb3ce 100644 --- a/servers/slapd/aci.c +++ b/servers/slapd/aci.c @@ -1320,11 +1320,15 @@ OpenLDAPaciValidate( atbv = BER_BVNULL; ocbv.bv_val = strchr( type.bv_val, '/' ); - if ( ocbv.bv_val != NULL ) { + if ( ocbv.bv_val != NULL + && ( ocbv.bv_val - type.bv_val ) < type.bv_len ) + { ocbv.bv_val++; atbv.bv_val = strchr( ocbv.bv_val, '/' ); - if ( atbv.bv_val != NULL ) { + if ( atbv.bv_val != NULL + && ( atbv.bv_val - ocbv.bv_val ) < ocbv.bv_len ) + { AttributeDescription *ad = NULL; const char *text = NULL; int rc; @@ -1471,7 +1475,9 @@ OpenLDAPaciPrettyNormal( atbv = BER_BVNULL; ocbv.bv_val = strchr( type.bv_val, '/' ); - if ( ocbv.bv_val != NULL ) { + if ( ocbv.bv_val != NULL + && ( ocbv.bv_val - type.bv_val ) < type.bv_len ) + { ObjectClass *oc = NULL; AttributeDescription *ad = NULL; const char *text = NULL; @@ -1483,7 +1489,9 @@ OpenLDAPaciPrettyNormal( ocbv.bv_val++; atbv.bv_val = strchr( ocbv.bv_val, '/' ); - if ( atbv.bv_val != NULL ) { + if ( atbv.bv_val != NULL + && ( atbv.bv_val - ocbv.bv_val ) < ocbv.bv_len ) + { atbv.bv_val++; atbv.bv_len = type.bv_len - ( atbv.bv_val - type.bv_val ); @@ -1616,5 +1624,17 @@ OpenLDAPaciNormalize( return OpenLDAPaciPrettyNormal( val, out, ctx, 1 ); } +#if SLAPD_ACI_ENABLED == SLAPD_MOD_DYNAMIC +/* + * FIXME: need config and Makefile.am code to ease building + * as dynamic module + */ +int +init_module( int argc, char *argv[] ) +{ + return slap_dynacl_register(); +} +#endif /* SLAPD_ACI_ENABLED == SLAPD_MOD_DYNAMIC */ + #endif /* SLAPD_ACI_ENABLED */ diff --git a/servers/slapd/acl.c b/servers/slapd/acl.c index f224e68e8a..8bff33752d 100644 --- a/servers/slapd/acl.c +++ b/servers/slapd/acl.c @@ -2603,7 +2603,7 @@ acl_set_gather( SetCookie *cookie, struct berval *name, AttributeDescription *de op2.o_tag = LDAP_REQ_SEARCH; op2.o_ndn = op2.o_bd->be_rootndn; op2.o_callback = &cb; - op2.o_time = slap_get_time(); + slap_op_time( &op2.o_time, &op2.o_tincr ); op2.o_do_not_cache = 1; op2.o_is_auth_check = 0; ber_dupbv_x( &op2.o_req_dn, &op2.o_req_ndn, cp->asc_op->o_tmpmemctx ); diff --git a/servers/slapd/aclparse.c b/servers/slapd/aclparse.c index 9b0e8e7acb..3c52759f70 100644 --- a/servers/slapd/aclparse.c +++ b/servers/slapd/aclparse.c @@ -58,7 +58,7 @@ char *style_strings[] = { static void split(char *line, int splitchar, char **left, char **right); static void access_append(Access **l, Access *a); -static void acl_usage(void) LDAP_GCCATTR((noreturn)); +static int acl_usage(void); static void acl_regex_normalized_dn(const char *src, struct berval *pat); @@ -87,7 +87,7 @@ slap_dynacl_config( Debug( LDAP_DEBUG_ANY, "%s: line %d: dynacl \"%s\" already specified.\n", fname, lineno, name ); - acl_usage(); + return acl_usage(); } } @@ -154,7 +154,8 @@ regtest(const char *fname, int lineno, char *pat) { Debug( LDAP_DEBUG_ANY, "%s: line %d: regular expression \"%s\" too large\n", fname, lineno, pat ); - acl_usage(); + (void)acl_usage(); + exit( EXIT_FAILURE ); } if ((e = regcomp(&re, buf, REG_EXTENDED|REG_ICASE))) { @@ -169,6 +170,7 @@ regtest(const char *fname, int lineno, char *pat) { "%s: line %d: %s\n", fname, lineno, buf ); acl_usage(); + exit( EXIT_FAILURE ); } regfree(&re); } @@ -313,13 +315,13 @@ regex_done:; return ACL_SCOPE_UNKNOWN; } -void +int parse_acl( - Backend *be, - const char *fname, - int lineno, - int argc, - char **argv, + Backend *be, + const char *fname, + int lineno, + int argc, + char **argv, int pos ) { int i; @@ -338,7 +340,7 @@ parse_acl( Debug( LDAP_DEBUG_ANY, "%s: line %d: " "only one to clause allowed in access line\n", fname, lineno, 0 ); - acl_usage(); + return acl_usage(); } a = (AccessControl *) ch_calloc( 1, sizeof(AccessControl) ); for ( ++i; i < argc; i++ ) { @@ -355,7 +357,7 @@ parse_acl( "%s: line %d: dn pattern" " already specified in to clause.\n", fname, lineno, 0 ); - acl_usage(); + return acl_usage(); } ber_str2bv( "*", STRLENOF( "*" ), 1, &a->acl_dn_pat ); @@ -369,7 +371,7 @@ parse_acl( Debug( LDAP_DEBUG_ANY, "%s: line %d: " "missing \"=\" in \"%s\" in to clause\n", fname, lineno, left ); - acl_usage(); + return acl_usage(); } if ( strcasecmp( left, "dn" ) == 0 ) { @@ -380,7 +382,7 @@ parse_acl( "%s: line %d: dn pattern" " already specified in to clause.\n", fname, lineno, 0 ); - acl_usage(); + return acl_usage(); } if ( style == NULL || *style == '\0' || @@ -438,7 +440,7 @@ parse_acl( Debug( LDAP_DEBUG_ANY, "%s: line %d: " "unknown dn style \"%s\" in to clause\n", fname, lineno, style ); - acl_usage(); + return acl_usage(); } continue; @@ -449,7 +451,7 @@ parse_acl( Debug( LDAP_DEBUG_ANY, "%s: line %d: bad filter \"%s\" in to clause\n", fname, lineno, right ); - acl_usage(); + return acl_usage(); } } else if ( strcasecmp( left, "attr" ) == 0 /* TOLERATED */ @@ -469,7 +471,7 @@ parse_acl( Debug( LDAP_DEBUG_ANY, "%s: line %d: unknown attr \"%s\" in to clause\n", fname, lineno, right ); - acl_usage(); + return acl_usage(); } } else if ( strncasecmp( left, "val", 3 ) == 0 ) { @@ -479,14 +481,14 @@ parse_acl( Debug( LDAP_DEBUG_ANY, "%s: line %d: attr val already specified in to clause.\n", fname, lineno, 0 ); - acl_usage(); + return acl_usage(); } if ( a->acl_attrs == NULL || !BER_BVISEMPTY( &a->acl_attrs[1].an_name ) ) { Debug( LDAP_DEBUG_ANY, "%s: line %d: attr val requires a single attribute.\n", fname, lineno, 0 ); - acl_usage(); + return acl_usage(); } ber_str2bv( right, 0, 1, &a->acl_attrval ); @@ -502,7 +504,7 @@ parse_acl( Debug( LDAP_DEBUG_ANY, "%s: line %d: " "invalid matching rule \"%s\".\n", fname, lineno, mr ); - acl_usage(); + return acl_usage(); } if( !mr_usable_with_at( a->acl_attrval_mr, a->acl_attrs[ 0 ].an_desc->ad_type ) ) @@ -517,7 +519,7 @@ parse_acl( Debug( LDAP_DEBUG_ANY, "%s: line %d: %s\n", fname, lineno, buf ); - acl_usage(); + return acl_usage(); } } @@ -537,7 +539,7 @@ parse_acl( Debug( LDAP_DEBUG_ANY, "%s: line %d: %s\n", fname, lineno, buf ); - acl_usage(); + return acl_usage(); } a->acl_attrval_style = ACL_STYLE_REGEX; @@ -584,7 +586,7 @@ parse_acl( "%s: line %d: %s\n", fname, lineno, buf ); #ifdef SLAPD_CONF_UNKNOWN_BAILOUT - acl_usage(); + return acl_usage(); #endif /* SLAPD_CONF_UNKNOWN_BAILOUT */ a->acl_attrval_style = ACL_STYLE_BASE; } @@ -603,7 +605,7 @@ parse_acl( Debug( LDAP_DEBUG_ANY, "%s: line %d: %s\n", fname, lineno, buf ); - acl_usage(); + return acl_usage(); } ber_memfree( bv.bv_val ); @@ -621,7 +623,7 @@ parse_acl( "%s: line %d: %s\n", fname, lineno, buf ); #ifdef SLAPD_CONF_UNKNOWN_BAILOUT - acl_usage(); + return acl_usage(); #endif /* SLAPD_CONF_UNKNOWN_BAILOUT */ a->acl_attrval_style = ACL_STYLE_BASE; } @@ -638,7 +640,7 @@ parse_acl( Debug( LDAP_DEBUG_ANY, "%s: line %d: " "attr \"%s\" must have an EQUALITY matching rule.\n", fname, lineno, a->acl_attrs[ 0 ].an_name.bv_val ); - acl_usage(); + return acl_usage(); } } @@ -646,7 +648,7 @@ parse_acl( Debug( LDAP_DEBUG_ANY, "%s: line %d: expecting got \"%s\"\n", fname, lineno, left ); - acl_usage(); + return acl_usage(); } } @@ -668,7 +670,7 @@ parse_acl( Debug( LDAP_DEBUG_ANY, "%s: line %d: bad DN \"%s\" in to DN clause\n", fname, lineno, a->acl_dn_pat.bv_val ); - acl_usage(); + return acl_usage(); } free( a->acl_dn_pat.bv_val ); a->acl_dn_pat = bv; @@ -686,7 +688,7 @@ parse_acl( right, err ); Debug( LDAP_DEBUG_ANY, "%s: line %d: %s\n", fname, lineno, buf ); - acl_usage(); + return acl_usage(); } } } @@ -697,7 +699,7 @@ parse_acl( Debug( LDAP_DEBUG_ANY, "%s: line %d: " "to clause required before by clause in access line\n", fname, lineno, 0 ); - acl_usage(); + return acl_usage(); } /* @@ -712,7 +714,7 @@ parse_acl( Debug( LDAP_DEBUG_ANY, "%s: line %d: premature EOL: expecting \n", fname, lineno, 0 ); - acl_usage(); + return acl_usage(); } /* get */ @@ -739,13 +741,13 @@ parse_acl( "%s: line %d: premature eol: " "expecting closing '}' in \"level{n}\"\n", fname, lineno, 0 ); - acl_usage(); + return acl_usage(); } else if ( p == style_level ) { Debug( LDAP_DEBUG_ANY, "%s: line %d: empty level " "in \"level{n}\"\n", fname, lineno, 0 ); - acl_usage(); + return acl_usage(); } p[0] = '\0'; } @@ -782,7 +784,7 @@ parse_acl( "%s: line %d: unable to parse level " "in \"level{n}\"\n", fname, lineno, 0 ); - acl_usage(); + return acl_usage(); } sty = ACL_STYLE_LEVEL; @@ -805,7 +807,7 @@ parse_acl( SLAPD_CONF_UNKNOWN_IGNORED ".\n", fname, lineno, 0 ); #ifdef SLAPD_CONF_UNKNOWN_BAILOUT - acl_usage(); + return acl_usage(); #endif /* SLAPD_CONF_UNKNOWN_BAILOUT */ #endif /* LDAP_PF_LOCAL */ @@ -813,7 +815,7 @@ parse_acl( Debug( LDAP_DEBUG_ANY, "%s: line %d: unknown style \"%s\" in by clause\n", fname, lineno, style ); - acl_usage(); + return acl_usage(); } if ( style_modifier && @@ -827,7 +829,7 @@ parse_acl( SLAPD_CONF_UNKNOWN_IGNORED ".\n", fname, lineno, 0 ); #ifdef SLAPD_CONF_UNKNOWN_BAILOUT - acl_usage(); + return acl_usage(); #endif /* SLAPD_CONF_UNKNOWN_BAILOUT */ break; @@ -852,7 +854,7 @@ parse_acl( SLAPD_CONF_UNKNOWN_IGNORED ".\n", fname, lineno, 0 ); #ifdef SLAPD_CONF_UNKNOWN_BAILOUT - acl_usage(); + return acl_usage(); #endif /* SLAPD_CONF_UNKNOWN_BAILOUT */ } @@ -864,7 +866,7 @@ parse_acl( if ( strcasecmp( left, "*" ) == 0 ) { if ( is_realdn ) { - acl_usage(); + return acl_usage(); } ber_str2bv( "*", STRLENOF( "*" ), 1, &bv ); @@ -942,7 +944,7 @@ parse_acl( "missing \"=\" in (or value after) \"%s\" " "in by clause\n", fname, lineno, left ); - acl_usage(); + return acl_usage(); } else { ber_str2bv( right, 0, 1, &bv ); @@ -957,7 +959,7 @@ parse_acl( Debug( LDAP_DEBUG_ANY, "%s: line %d: dn pattern already specified.\n", fname, lineno, 0 ); - acl_usage(); + return acl_usage(); } if ( sty != ACL_STYLE_REGEX && @@ -972,7 +974,7 @@ parse_acl( Debug( LDAP_DEBUG_ANY, "%s: line %d: bad DN \"%s\" in by DN clause\n", fname, lineno, bv.bv_val ); - acl_usage(); + return acl_usage(); } free( bv.bv_val ); if ( sty == ACL_STYLE_BASE @@ -1015,7 +1017,7 @@ parse_acl( SLAPD_CONF_UNKNOWN_IGNORED ".\n", fname, lineno, 0 ); #ifdef SLAPD_CONF_UNKNOWN_BAILOUT - acl_usage(); + return acl_usage(); #endif /* SLAPD_CONF_UNKNOWN_BAILOUT */ } } @@ -1028,7 +1030,7 @@ parse_acl( "%s: line %d: bad negative level \"%d\" " "in by DN clause\n", fname, lineno, level ); - acl_usage(); + return acl_usage(); } else if ( level == 1 ) { Debug( LDAP_DEBUG_ANY, "%s: line %d: \"onelevel\" should be used " @@ -1052,14 +1054,14 @@ parse_acl( "missing \"=\" in (or value after) \"%s\" " "in by clause\n", fname, lineno, left ); - acl_usage(); + return acl_usage(); } if( bdn->a_at != NULL ) { Debug( LDAP_DEBUG_ANY, "%s: line %d: dnattr already specified.\n", fname, lineno, 0 ); - acl_usage(); + return acl_usage(); } rc = slap_str2ad( right, &bdn->a_at, &text ); @@ -1073,7 +1075,7 @@ parse_acl( Debug( LDAP_DEBUG_ANY, "%s: line %d: %s\n", fname, lineno, buf ); - acl_usage(); + return acl_usage(); } @@ -1092,7 +1094,7 @@ parse_acl( Debug( LDAP_DEBUG_ANY, "%s: line %d: %s\n", fname, lineno, buf ); - acl_usage(); + return acl_usage(); } if( bdn->a_at->ad_type->sat_equality == NULL ) { @@ -1100,7 +1102,7 @@ parse_acl( "%s: line %d: dnattr \"%s\": " "inappropriate matching (no EQUALITY)\n", fname, lineno, right ); - acl_usage(); + return acl_usage(); } continue; @@ -1133,7 +1135,7 @@ parse_acl( "%s: line %d: " "inappropriate style \"%s\" in by clause.\n", fname, lineno, style ); - acl_usage(); + return acl_usage(); } if ( right == NULL || right[0] == '\0' ) { @@ -1142,14 +1144,14 @@ parse_acl( "missing \"=\" in (or value after) \"%s\" " "in by clause.\n", fname, lineno, left ); - acl_usage(); + return acl_usage(); } if ( !BER_BVISEMPTY( &b->a_group_pat ) ) { Debug( LDAP_DEBUG_ANY, "%s: line %d: group pattern already specified.\n", fname, lineno, 0 ); - acl_usage(); + return acl_usage(); } /* format of string is @@ -1177,7 +1179,7 @@ parse_acl( Debug( LDAP_DEBUG_ANY, "%s: line %d: bad DN \"%s\".\n", fname, lineno, right ); - acl_usage(); + return acl_usage(); } } @@ -1190,7 +1192,7 @@ parse_acl( "%s: line %d: group objectclass " "\"%s\" unknown.\n", fname, lineno, value ); - acl_usage(); + return acl_usage(); } } else { @@ -1201,7 +1203,7 @@ parse_acl( "%s: line %d: group default objectclass " "\"%s\" unknown.\n", fname, lineno, SLAPD_GROUP_CLASS ); - acl_usage(); + return acl_usage(); } } @@ -1212,7 +1214,7 @@ parse_acl( "%s: line %d: group objectclass \"%s\" " "is subclass of referral.\n", fname, lineno, value ); - acl_usage(); + return acl_usage(); } if ( is_object_subclass( slap_schema.si_oc_alias, @@ -1222,7 +1224,7 @@ parse_acl( "%s: line %d: group objectclass \"%s\" " "is subclass of alias.\n", fname, lineno, value ); - acl_usage(); + return acl_usage(); } if ( name && *name ) { @@ -1237,7 +1239,7 @@ parse_acl( Debug( LDAP_DEBUG_ANY, "%s: line %d: %s\n", fname, lineno, buf ); - acl_usage(); + return acl_usage(); } *--name = '/'; @@ -1253,7 +1255,7 @@ parse_acl( Debug( LDAP_DEBUG_ANY, "%s: line %d: %s\n", fname, lineno, buf ); - acl_usage(); + return acl_usage(); } } @@ -1272,7 +1274,7 @@ parse_acl( Debug( LDAP_DEBUG_ANY, "%s: line %d: %s\n", fname, lineno, buf ); - acl_usage(); + return acl_usage(); } @@ -1295,7 +1297,7 @@ parse_acl( b->a_group_oc->soc_oid ); Debug( LDAP_DEBUG_ANY, "%s: line %d: %s\n", fname, lineno, buf ); - acl_usage(); + return acl_usage(); } } continue; @@ -1317,7 +1319,7 @@ parse_acl( Debug( LDAP_DEBUG_ANY, "%s: line %d: " "inappropriate style \"%s\" in by clause.\n", fname, lineno, style ); - acl_usage(); + return acl_usage(); } if ( right == NULL || right[0] == '\0' ) { @@ -1325,14 +1327,14 @@ parse_acl( "missing \"=\" in (or value after) \"%s\" " "in by clause.\n", fname, lineno, left ); - acl_usage(); + return acl_usage(); } if ( !BER_BVISEMPTY( &b->a_peername_pat ) ) { Debug( LDAP_DEBUG_ANY, "%s: line %d: " "peername pattern already specified.\n", fname, lineno, 0 ); - acl_usage(); + return acl_usage(); } b->a_peername_style = sty; @@ -1360,7 +1362,7 @@ parse_acl( Debug( LDAP_DEBUG_ANY, "%s: line %d: " "illegal peername address \"%s\".\n", fname, lineno, addr ); - acl_usage(); + return acl_usage(); } b->a_peername_mask = (unsigned long)(-1); @@ -1374,7 +1376,7 @@ parse_acl( "illegal peername address mask " "\"%s\".\n", fname, lineno, mask ); - acl_usage(); + return acl_usage(); } } @@ -1389,7 +1391,7 @@ parse_acl( "illegal peername port specification " "\"{%s}\".\n", fname, lineno, port ); - acl_usage(); + return acl_usage(); } } } @@ -1411,7 +1413,7 @@ parse_acl( Debug( LDAP_DEBUG_ANY, "%s: line %d: " "inappropriate style \"%s\" in by clause\n", fname, lineno, style ); - acl_usage(); + return acl_usage(); } if ( right == NULL || right[0] == '\0' ) { @@ -1419,14 +1421,14 @@ parse_acl( "missing \"=\" in (or value after) \"%s\" " "in by clause\n", fname, lineno, left ); - acl_usage(); + return acl_usage(); } if ( !BER_BVISNULL( &b->a_sockname_pat ) ) { Debug( LDAP_DEBUG_ANY, "%s: line %d: " "sockname pattern already specified.\n", fname, lineno, 0 ); - acl_usage(); + return acl_usage(); } b->a_sockname_style = sty; @@ -1469,7 +1471,7 @@ parse_acl( Debug( LDAP_DEBUG_ANY, "%s: line %d: " "inappropriate style \"%s\" in by clause.\n", fname, lineno, style ); - acl_usage(); + return acl_usage(); } if ( right == NULL || right[0] == '\0' ) { @@ -1477,14 +1479,14 @@ parse_acl( "missing \"=\" in (or value after) \"%s\" " "in by clause.\n", fname, lineno, left ); - acl_usage(); + return acl_usage(); } if ( !BER_BVISEMPTY( &b->a_domain_pat ) ) { Debug( LDAP_DEBUG_ANY, "%s: line %d: domain pattern already specified.\n", fname, lineno, 0 ); - acl_usage(); + return acl_usage(); } b->a_domain_style = sty; @@ -1516,7 +1518,7 @@ parse_acl( Debug( LDAP_DEBUG_ANY, "%s: line %d: " "inappropriate style \"%s\" in by clause.\n", fname, lineno, style ); - acl_usage(); + return acl_usage(); } if ( right == NULL || right[0] == '\0' ) { @@ -1524,14 +1526,14 @@ parse_acl( "missing \"=\" in (or value after) \"%s\" " "in by clause.\n", fname, lineno, left ); - acl_usage(); + return acl_usage(); } if ( !BER_BVISEMPTY( &b->a_sockurl_pat ) ) { Debug( LDAP_DEBUG_ANY, "%s: line %d: sockurl pattern already specified.\n", fname, lineno, 0 ); - acl_usage(); + return acl_usage(); } b->a_sockurl_style = sty; @@ -1569,21 +1571,21 @@ parse_acl( Debug( LDAP_DEBUG_ANY, "%s: line %d: " "inappropriate style \"%s\" in by clause.\n", fname, lineno, style ); - acl_usage(); + return acl_usage(); } if ( !BER_BVISEMPTY( &b->a_set_pat ) ) { Debug( LDAP_DEBUG_ANY, "%s: line %d: set attribute already specified.\n", fname, lineno, 0 ); - acl_usage(); + return acl_usage(); } if ( right == NULL || *right == '\0' ) { Debug( LDAP_DEBUG_ANY, "%s: line %d: no set is defined.\n", fname, lineno, 0 ); - acl_usage(); + return acl_usage(); } b->a_set_style = sty; @@ -1614,7 +1616,7 @@ parse_acl( Debug( LDAP_DEBUG_ANY, "%s: line %d: " "unable to configure dynacl \"%s\".\n", fname, lineno, name ); - acl_usage(); + return acl_usage(); } continue; @@ -1628,14 +1630,14 @@ parse_acl( Debug( LDAP_DEBUG_ANY, "%s: line %d: " "inappropriate style \"%s\" in by clause.\n", fname, lineno, style ); - acl_usage(); + return acl_usage(); } if( b->a_aci_at != NULL ) { Debug( LDAP_DEBUG_ANY, "%s: line %d: ACI attribute already specified.\n", fname, lineno, 0 ); - acl_usage(); + return acl_usage(); } if ( right != NULL && *right != '\0' ) { @@ -1650,7 +1652,7 @@ parse_acl( Debug( LDAP_DEBUG_ANY, "%s: line %d: %s\n", fname, lineno, buf ); - acl_usage(); + return acl_usage(); } } else { @@ -1668,7 +1670,7 @@ parse_acl( b->a_aci_at->ad_type->sat_syntax_oid ); Debug( LDAP_DEBUG_ANY, "%s: line %d: %s\n", fname, lineno, buf ); - acl_usage(); + return acl_usage(); } continue; @@ -1681,21 +1683,21 @@ parse_acl( Debug( LDAP_DEBUG_ANY, "%s: line %d: " "inappropriate style \"%s\" in by clause.\n", fname, lineno, style ); - acl_usage(); + return acl_usage(); } if ( b->a_authz.sai_ssf ) { Debug( LDAP_DEBUG_ANY, "%s: line %d: ssf attribute already specified.\n", fname, lineno, 0 ); - acl_usage(); + return acl_usage(); } if ( right == NULL || *right == '\0' ) { Debug( LDAP_DEBUG_ANY, "%s: line %d: no ssf is defined.\n", fname, lineno, 0 ); - acl_usage(); + return acl_usage(); } b->a_authz.sai_ssf = strtol( right, &next, 10 ); @@ -1703,14 +1705,14 @@ parse_acl( Debug( LDAP_DEBUG_ANY, "%s: line %d: unable to parse ssf value (%s).\n", fname, lineno, right ); - acl_usage(); + return acl_usage(); } if ( !b->a_authz.sai_ssf ) { Debug( LDAP_DEBUG_ANY, "%s: line %d: invalid ssf value (%s).\n", fname, lineno, right ); - acl_usage(); + return acl_usage(); } continue; } @@ -1720,21 +1722,21 @@ parse_acl( Debug( LDAP_DEBUG_ANY, "%s: line %d: " "inappropriate style \"%s\" in by clause.\n", fname, lineno, style ); - acl_usage(); + return acl_usage(); } if ( b->a_authz.sai_transport_ssf ) { Debug( LDAP_DEBUG_ANY, "%s: line %d: " "transport_ssf attribute already specified.\n", fname, lineno, 0 ); - acl_usage(); + return acl_usage(); } if ( right == NULL || *right == '\0' ) { Debug( LDAP_DEBUG_ANY, "%s: line %d: no transport_ssf is defined.\n", fname, lineno, 0 ); - acl_usage(); + return acl_usage(); } b->a_authz.sai_transport_ssf = strtol( right, &next, 10 ); @@ -1742,14 +1744,14 @@ parse_acl( Debug( LDAP_DEBUG_ANY, "%s: line %d: " "unable to parse transport_ssf value (%s).\n", fname, lineno, right ); - acl_usage(); + return acl_usage(); } if ( !b->a_authz.sai_transport_ssf ) { Debug( LDAP_DEBUG_ANY, "%s: line %d: invalid transport_ssf value (%s).\n", fname, lineno, right ); - acl_usage(); + return acl_usage(); } continue; } @@ -1759,21 +1761,21 @@ parse_acl( Debug( LDAP_DEBUG_ANY, "%s: line %d: " "inappropriate style \"%s\" in by clause.\n", fname, lineno, style ); - acl_usage(); + return acl_usage(); } if ( b->a_authz.sai_tls_ssf ) { Debug( LDAP_DEBUG_ANY, "%s: line %d: " "tls_ssf attribute already specified.\n", fname, lineno, 0 ); - acl_usage(); + return acl_usage(); } if ( right == NULL || *right == '\0' ) { Debug( LDAP_DEBUG_ANY, "%s: line %d: no tls_ssf is defined\n", fname, lineno, 0 ); - acl_usage(); + return acl_usage(); } b->a_authz.sai_tls_ssf = strtol( right, &next, 10 ); @@ -1781,14 +1783,14 @@ parse_acl( Debug( LDAP_DEBUG_ANY, "%s: line %d: " "unable to parse tls_ssf value (%s).\n", fname, lineno, right ); - acl_usage(); + return acl_usage(); } if ( !b->a_authz.sai_tls_ssf ) { Debug( LDAP_DEBUG_ANY, "%s: line %d: invalid tls_ssf value (%s).\n", fname, lineno, right ); - acl_usage(); + return acl_usage(); } continue; } @@ -1798,21 +1800,21 @@ parse_acl( Debug( LDAP_DEBUG_ANY, "%s: line %d: " "inappropriate style \"%s\" in by clause.\n", fname, lineno, style ); - acl_usage(); + return acl_usage(); } if ( b->a_authz.sai_sasl_ssf ) { Debug( LDAP_DEBUG_ANY, "%s: line %d: " "sasl_ssf attribute already specified.\n", fname, lineno, 0 ); - acl_usage(); + return acl_usage(); } if ( right == NULL || *right == '\0' ) { Debug( LDAP_DEBUG_ANY, "%s: line %d: no sasl_ssf is defined.\n", fname, lineno, 0 ); - acl_usage(); + return acl_usage(); } b->a_authz.sai_sasl_ssf = strtol( right, &next, 10 ); @@ -1820,14 +1822,14 @@ parse_acl( Debug( LDAP_DEBUG_ANY, "%s: line %d: " "unable to parse sasl_ssf value (%s).\n", fname, lineno, right ); - acl_usage(); + return acl_usage(); } if ( !b->a_authz.sai_sasl_ssf ) { Debug( LDAP_DEBUG_ANY, "%s: line %d: invalid sasl_ssf value (%s).\n", fname, lineno, right ); - acl_usage(); + return acl_usage(); } continue; } @@ -1896,7 +1898,7 @@ parse_acl( Debug( LDAP_DEBUG_ANY, "%s: line %d: expecting got \"%s\".\n", fname, lineno, left ); - acl_usage(); + return acl_usage(); } b->a_type = ACL_STOP; @@ -1927,7 +1929,7 @@ parse_acl( "%s: line %d: expecting \"to\" " "or \"by\" got \"%s\"\n", fname, lineno, argv[i] ); - acl_usage(); + return acl_usage(); } } @@ -1939,7 +1941,7 @@ parse_acl( SLAPD_CONF_UNKNOWN_IGNORED ".\n", fname, lineno, 0 ); #ifdef SLAPD_CONF_UNKNOWN_BAILOUT - acl_usage(); + return acl_usage(); #endif /* SLAPD_CONF_UNKNOWN_BAILOUT */ } else { @@ -1956,7 +1958,7 @@ parse_acl( SLAPD_CONF_UNKNOWN_IGNORED ".\n", fname, lineno, 0 ); #ifdef SLAPD_CONF_UNKNOWN_BAILOUT - acl_usage(); + return acl_usage(); #endif /* SLAPD_CONF_UNKNOWN_BAILOUT */ } @@ -2006,6 +2008,8 @@ parse_acl( acl_append( &frontendDB->be_acl, a, pos ); } } + + return 0; } char * @@ -2231,17 +2235,17 @@ str2accessmask( const char *str ) return mask; } -static void +static int acl_usage( void ) { char *access = " ::= access to " "[ by [ ] ]+ \n"; - char *what = - " ::= * | [dn[.]=] [filter=] [attrs=]\n" - " ::= [val[/matchingRule][.]=] | , \n" - " ::= | entry | children\n"; + " ::= * | [dn[.]=] [filter=] [attrs=]\n" + " ::= [val[/][.]=] | \n" + " ::= [ , ]\n" + " ::= | @ | ! | entry | children\n"; char *who = " ::= [ * | anonymous | users | self | dn[.]= ]\n" @@ -2278,8 +2282,9 @@ acl_usage( void ) #endif /* ! SLAP_DYNACL */ ""; - Debug( LDAP_DEBUG_ANY, "%s%s%s\n", access, who, what ); - exit( EXIT_FAILURE ); + Debug( LDAP_DEBUG_ANY, "%s%s%s\n", access, what, who ); + + return 1; } /* diff --git a/servers/slapd/add.c b/servers/slapd/add.c index 7df87348aa..250da6093a 100644 --- a/servers/slapd/add.c +++ b/servers/slapd/add.c @@ -30,6 +30,7 @@ #include #include +#include "lutil.h" #include "slap.h" int @@ -192,8 +193,6 @@ do_add( Operation *op, SlapReply *rs ) } done:; - slap_graduate_commit_csn( op ); - if ( modlist != NULL ) { slap_mods_free( modlist, 0 ); } @@ -312,14 +311,6 @@ fe_op_add( Operation *op, SlapReply *rs ) } - rs->sr_err = slap_mods_opattrs( op, modlist, - modtail, &rs->sr_text, - textbuf, textlen, 1 ); - if ( rs->sr_err != LDAP_SUCCESS ) { - send_ldap_result( op, rs ); - goto done; - } - /* check for duplicate values */ rs->sr_err = slap_mods_no_repl_user_mod_check( op, modlist, &rs->sr_text, textbuf, textlen ); @@ -626,3 +617,119 @@ slap_entry2mods( return LDAP_SUCCESS; } +int slap_add_opattrs( + Operation *op, + const char **text, + char *textbuf, + size_t textlen, + int manage_ctxcsn ) +{ + struct berval name, timestamp, csn = BER_BVNULL; + struct berval nname, tmp; + char timebuf[ LDAP_LUTIL_GENTIME_BUFSIZE ]; + char csnbuf[ LDAP_LUTIL_CSNSTR_BUFSIZE ]; + Attribute *a; + + a = attr_find( op->ora_e->e_attrs, + slap_schema.si_ad_structuralObjectClass ); + + if ( !a ) { + Attribute *oc; + int rc; + + oc = attr_find( op->ora_e->e_attrs, slap_schema.si_ad_objectClass ); + if ( oc ) { + rc = structural_class( oc->a_vals, &tmp, NULL, text, + textbuf, textlen ); + if( rc != LDAP_SUCCESS ) return rc; + + attr_merge_one( op->ora_e, slap_schema.si_ad_structuralObjectClass, + &tmp, NULL ); + } + } + + if ( SLAP_LASTMOD( op->o_bd ) ) { + char *ptr; + timestamp.bv_val = timebuf; + if ( BER_BVISEMPTY( &op->o_csn )) { + if ( SLAP_SHADOW( op->o_bd )) + manage_ctxcsn = 0; + csn.bv_val = csnbuf; + csn.bv_len = sizeof(csnbuf); + slap_get_csn( op, &csn, manage_ctxcsn ); + } else { + csn = op->o_csn; + } + ptr = strchr( csn.bv_val, '#' ); + if ( ptr ) { + timestamp.bv_len = ptr - csn.bv_val; + if ( timestamp.bv_len >= sizeof(timebuf) ) + timestamp.bv_len = sizeof(timebuf) - 1; + strncpy( timebuf, csn.bv_val, timestamp.bv_len ); + timebuf[timestamp.bv_len] = '\0'; + } else { + time_t now = slap_get_time(); + + timestamp.bv_len = sizeof(timebuf); + + slap_timestamp( &now, ×tamp ); + } + + if ( BER_BVISEMPTY( &op->o_dn ) ) { + BER_BVSTR( &name, SLAPD_ANONYMOUS ); + nname = name; + } else { + name = op->o_dn; + nname = op->o_ndn; + } + + a = attr_find( op->ora_e->e_attrs, + slap_schema.si_ad_entryUUID ); + if ( !a ) { + char uuidbuf[ LDAP_LUTIL_UUIDSTR_BUFSIZE ]; + + tmp.bv_len = lutil_uuidstr( uuidbuf, sizeof( uuidbuf ) ); + tmp.bv_val = uuidbuf; + + attr_merge_normalize_one( op->ora_e, + slap_schema.si_ad_entryUUID, &tmp, op->o_tmpmemctx ); + } + + a = attr_find( op->ora_e->e_attrs, + slap_schema.si_ad_creatorsName ); + if ( !a ) { + attr_merge_one( op->ora_e, + slap_schema.si_ad_creatorsName, &name, &nname ); + } + + a = attr_find( op->ora_e->e_attrs, + slap_schema.si_ad_createTimestamp ); + if ( !a ) { + attr_merge_one( op->ora_e, + slap_schema.si_ad_createTimestamp, ×tamp, NULL ); + } + + a = attr_find( op->ora_e->e_attrs, + slap_schema.si_ad_entryCSN ); + if ( !a ) { + attr_merge_one( op->ora_e, + slap_schema.si_ad_entryCSN, &csn, NULL ); + } + + a = attr_find( op->ora_e->e_attrs, + slap_schema.si_ad_modifiersName ); + if ( !a ) { + attr_merge_one( op->ora_e, + slap_schema.si_ad_modifiersName, &name, &nname ); + } + + a = attr_find( op->ora_e->e_attrs, + slap_schema.si_ad_modifyTimestamp ); + if ( !a ) { + attr_merge_one( op->ora_e, + slap_schema.si_ad_modifyTimestamp, ×tamp, NULL ); + } + + } + return LDAP_SUCCESS; +} diff --git a/servers/slapd/back-bdb/add.c b/servers/slapd/back-bdb/add.c index 227652077e..6cf4e58f1d 100644 --- a/servers/slapd/back-bdb/add.c +++ b/servers/slapd/back-bdb/add.c @@ -51,6 +51,8 @@ bdb_add(Operation *op, SlapReply *rs ) ctrls[num_ctrls] = 0; + slap_add_opattrs( op, &rs->sr_text, textbuf, textlen, 1 ); + /* check entry's schema */ rs->sr_err = entry_schema_check( op, op->oq_add.rs_e, NULL, get_manageDIT(op), &rs->sr_text, textbuf, textlen ); @@ -170,14 +172,8 @@ retry: /* transaction retry */ "does not exist\n", 0, 0, 0 ); rs->sr_err = LDAP_REFERRAL; - send_ldap_result( op, rs ); - - ber_bvarray_free( rs->sr_ref ); - op->o_tmpfree( (char *)rs->sr_matched, op->o_tmpmemctx ); - rs->sr_ref = NULL; - rs->sr_matched = NULL; - - goto done; + rs->sr_flags = REP_MATCHED_MUSTBEFREED | REP_REF_MUSTBEFREED; + goto return_results; } rs->sr_err = access_allowed( op, p, @@ -221,22 +217,18 @@ retry: /* transaction retry */ if ( is_entry_referral( p ) ) { /* parent is a referral, don't allow add */ - rs->sr_matched = p->e_name.bv_val; + rs->sr_matched = ber_strdup_x( p->e_name.bv_val, + op->o_tmpmemctx ); rs->sr_ref = get_entry_referrals( op, p ); - + bdb_unlocked_cache_return_entry_r( &bdb->bi_cache, p ); + p = NULL; Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(bdb_add) ": parent is referral\n", 0, 0, 0 ); rs->sr_err = LDAP_REFERRAL; - send_ldap_result( op, rs ); - - ber_bvarray_free( rs->sr_ref ); - bdb_unlocked_cache_return_entry_r( &bdb->bi_cache, p ); - rs->sr_ref = NULL; - rs->sr_matched = NULL; - p = NULL; - goto done; + rs->sr_flags = REP_MATCHED_MUSTBEFREED | REP_REF_MUSTBEFREED; + goto return_results; } #ifdef BDB_SUBENTRIES @@ -385,7 +377,8 @@ retry: /* transaction retry */ if (( rs->sr_err=TXN_ABORT( ltid )) != 0 ) { rs->sr_text = "txn_abort (no-op) failed"; } else { - rs->sr_err = LDAP_NO_OPERATION; + rs->sr_err = LDAP_X_NO_OPERATION; + ltid = NULL; goto return_results; } @@ -430,22 +423,23 @@ retry: /* transaction retry */ return_results: send_ldap_result( op, rs ); + if ( !SLAP_SHADOW( op->o_bd )) + slap_graduate_commit_csn( op ); - if( rs->sr_err == LDAP_SUCCESS && bdb->bi_txn_cp ) { - ldap_pvt_thread_yield(); - TXN_CHECKPOINT( bdb->bi_dbenv, - bdb->bi_txn_cp_kbyte, bdb->bi_txn_cp_min, 0 ); - } - -done: if( ltid != NULL ) { TXN_ABORT( ltid ); - op->o_private = NULL; } + op->o_private = NULL; if( postread_ctrl != NULL ) { slap_sl_free( (*postread_ctrl)->ldctl_value.bv_val, op->o_tmpmemctx ); slap_sl_free( *postread_ctrl, op->o_tmpmemctx ); } + + if( rs->sr_err == LDAP_SUCCESS && bdb->bi_txn_cp ) { + ldap_pvt_thread_yield(); + TXN_CHECKPOINT( bdb->bi_dbenv, + bdb->bi_txn_cp_kbyte, bdb->bi_txn_cp_min, 0 ); + } return rs->sr_err; } diff --git a/servers/slapd/back-bdb/attr.c b/servers/slapd/back-bdb/attr.c index f058c1f596..6667249bd6 100644 --- a/servers/slapd/back-bdb/attr.c +++ b/servers/slapd/back-bdb/attr.c @@ -25,26 +25,56 @@ #include "back-bdb.h" #include "lutil.h" - -static int -ainfo_type_cmp( - const void *v_desc, - const void *v_a -) +/* Find the ad, return -1 if not found, + * set point for insertion if ins is non-NULL + */ +int +bdb_attr_slot( struct bdb_info *bdb, AttributeDescription *ad, unsigned *ins ) { - const AttributeDescription *desc = v_desc; - const AttrInfo *a = v_a; - return SLAP_PTRCMP(desc, a->ai_desc); + unsigned base = 0, cursor = 0; + unsigned n = bdb->bi_nattrs; + int val = 0; + + while ( 0 < n ) { + int pivot = n >> 1; + cursor = base + pivot; + + val = SLAP_PTRCMP( ad, bdb->bi_attrs[cursor]->ai_desc ); + if ( val < 0 ) { + n = pivot; + } else if ( val > 0 ) { + base = cursor + 1; + n -= pivot + 1; + } else { + return cursor; + } + } + if ( ins ) { + if ( val > 0 ) + ++cursor; + *ins = cursor; + } + return -1; } static int -ainfo_cmp( - const void *v_a, - const void *v_b -) +ainfo_insert( struct bdb_info *bdb, AttrInfo *a ) { - const AttrInfo *a = v_a, *b = v_b; - return SLAP_PTRCMP(a->ai_desc, b->ai_desc); + unsigned x; + int i = bdb_attr_slot( bdb, a->ai_desc, &x ); + + /* Is it a dup? */ + if ( i >= 0 ) + return -1; + + bdb->bi_attrs = ch_realloc( bdb->bi_attrs, ( bdb->bi_nattrs+1 ) * + sizeof( AttrInfo * )); + if ( x < bdb->bi_nattrs ) + AC_MEMCPY( &bdb->bi_attrs[x+1], &bdb->bi_attrs[x], + ( bdb->bi_nattrs - x ) * sizeof( AttrInfo *)); + bdb->bi_attrs[x] = a; + bdb->bi_nattrs++; + return 0; } AttrInfo * @@ -52,8 +82,8 @@ bdb_attr_mask( struct bdb_info *bdb, AttributeDescription *desc ) { - - return avl_find( bdb->bi_attrs, desc, ainfo_type_cmp ); + int i = bdb_attr_slot( bdb, desc, NULL ); + return i < 0 ? NULL : bdb->bi_attrs[i]; } int @@ -220,7 +250,7 @@ bdb_attr_index_config( #ifdef LDAP_COMP_MATCH if ( cr ) { - a_cr = avl_find( bdb->bi_attrs, ad, ainfo_type_cmp ); + a_cr = bdb_attr_mask( bdb, ad ); if ( a_cr ) { /* * AttrInfo is already in AVL @@ -242,12 +272,10 @@ bdb_attr_index_config( } } #endif - rc = avl_insert( &bdb->bi_attrs, (caddr_t) a, - ainfo_cmp, avl_dup_error ); - + rc = ainfo_insert( bdb, a ); if( rc ) { if ( bdb->bi_flags & BDB_IS_OPEN ) { - AttrInfo *b = avl_find( bdb->bi_attrs, ad, ainfo_type_cmp ); + AttrInfo *b = bdb_attr_mask( bdb, ad ); /* If we were editing this attr, reset it */ b->ai_indexmask &= ~BDB_INDEX_DELETING; /* If this is leftover from a previous add, commit it */ @@ -298,17 +326,19 @@ static AttrInfo aidef = { &addef }; void bdb_attr_index_unparse( struct bdb_info *bdb, BerVarray *bva ) { + int i; + if ( bdb->bi_defaultmask ) { aidef.ai_indexmask = bdb->bi_defaultmask; bdb_attr_index_unparser( &aidef, bva ); } - avl_apply( bdb->bi_attrs, bdb_attr_index_unparser, bva, -1, AVL_INORDER ); + for ( i=0; ibi_nattrs; i++ ) + bdb_attr_index_unparser( bdb->bi_attrs[i], bva ); } -static void -bdb_attrinfo_free( void *v ) +void +bdb_attr_info_free( AttrInfo *ai ) { - AttrInfo *ai = v; #ifdef LDAP_COMP_MATCH free( ai->ai_cr ); #endif @@ -316,52 +346,41 @@ bdb_attrinfo_free( void *v ) } void -bdb_attr_index_destroy( Avlnode *tree ) +bdb_attr_index_destroy( struct bdb_info *bdb ) { - avl_free( tree, bdb_attrinfo_free ); -} + int i; -void bdb_attr_index_free( struct bdb_info *bdb, AttributeDescription *ad ) -{ - AttrInfo *ai; + for ( i=0; ibi_nattrs; i++ ) + bdb_attr_info_free( bdb->bi_attrs[i] ); - ai = avl_delete( &bdb->bi_attrs, ad, ainfo_type_cmp ); - if ( ai ) - bdb_attrinfo_free( ai ); + free( bdb->bi_attrs ); } -/* Get a list of AttrInfo's to delete */ - -typedef struct Alist { - struct Alist *next; - AttrInfo *ptr; -} Alist; - -static int -bdb_attrinfo_flush( void *v1, void *arg ) +void bdb_attr_index_free( struct bdb_info *bdb, AttributeDescription *ad ) { - AttrInfo *ai = v1; - - if ( ai->ai_indexmask & BDB_INDEX_DELETING ) { - Alist **al = arg; - Alist *a = ch_malloc( sizeof( Alist )); - a->ptr = ai; - a->next = *al; - *al = a; + int i; + + i = bdb_attr_slot( bdb, ad, NULL ); + if ( i >= 0 ) { + bdb_attr_info_free( bdb->bi_attrs[i] ); + bdb->bi_nattrs--; + for (; ibi_nattrs; i++) + bdb->bi_attrs[i] = bdb->bi_attrs[i+1]; } - return 0; } void bdb_attr_flush( struct bdb_info *bdb ) { - Alist *al = NULL, *a2; - - avl_apply( bdb->bi_attrs, bdb_attrinfo_flush, &al, -1, AVL_INORDER ); - - while (( a2 = al )) { - al = al->next; - avl_delete( &bdb->bi_attrs, a2->ptr, ainfo_cmp ); - bdb_attrinfo_free( a2->ptr ); - ch_free( a2 ); + int i; + + for ( i=0; ibi_nattrs; i++ ) { + if ( bdb->bi_attrs[i]->ai_indexmask & BDB_INDEX_DELETING ) { + int j; + bdb_attr_info_free( bdb->bi_attrs[i] ); + bdb->bi_nattrs--; + for (j=i; jbi_nattrs; j++) + bdb->bi_attrs[j] = bdb->bi_attrs[j+1]; + i--; + } } } diff --git a/servers/slapd/back-bdb/back-bdb.h b/servers/slapd/back-bdb/back-bdb.h index 7091d343db..854a9b80ff 100644 --- a/servers/slapd/back-bdb/back-bdb.h +++ b/servers/slapd/back-bdb/back-bdb.h @@ -166,7 +166,8 @@ struct bdb_info { slap_mask_t bi_defaultmask; Cache bi_cache; - Avlnode *bi_attrs; + struct bdb_attrinfo **bi_attrs; + int bi_nattrs; void *bi_search_stack; int bi_search_stack_depth; int bi_linear_index; @@ -299,6 +300,19 @@ typedef struct bdb_attrinfo { #define BDB_INDEX_DELETING 0x8000U /* index is being modified */ #define BDB_INDEX_UPDATE_OP 0x03 /* performing an index update */ +/* For slapindex to record which attrs in an entry belong to which + * index database + */ +typedef struct AttrList { + struct AttrList *next; + Attribute *attr; +} AttrList; + +typedef struct IndexRec { + AttrInfo *ai; + AttrList *attrs; +} IndexRec; + #include "proto-bdb.h" #endif /* _BACK_BDB_H_ */ diff --git a/servers/slapd/back-bdb/cache.c b/servers/slapd/back-bdb/cache.c index d155ef7c2e..b236ac2dab 100644 --- a/servers/slapd/back-bdb/cache.c +++ b/servers/slapd/back-bdb/cache.c @@ -35,16 +35,6 @@ static int bdb_cache_delete_internal(Cache *cache, EntryInfo *e, int decr); static void bdb_lru_print(Cache *cache); #endif -static int bdb_txn_get( Operation *op, DB_ENV *env, DB_TXN **txn, int reset ); - -/* 4.2.52 */ -#if DB_VERSION_FULL == 0x04020034 -#define READ_TXN_FLAG ReadFlag -static int ReadFlag = DB_TXN_NOT_DURABLE; -#else -#define READ_TXN_FLAG 0 -#endif - static EntryInfo * bdb_cache_entryinfo_new( Cache *cache ) { @@ -384,10 +374,11 @@ bdb_cache_find_ndn( /* Walk up the tree from a child node, looking for an ID that's already * been linked into the cache. */ -static int +int hdb_cache_find_parent( Operation *op, DB_TXN *txn, + u_int32_t locker, ID id, EntryInfo **res ) { @@ -401,7 +392,7 @@ hdb_cache_find_parent( ei.bei_ckids = 0; for (;;) { - rc = hdb_dn2id_parent( op, txn, &ei, &eip.bei_id ); + rc = hdb_dn2id_parent( op, txn, locker, &ei, &eip.bei_id ); if ( rc ) break; /* Save the previous node, if any */ @@ -703,7 +694,7 @@ again: ldap_pvt_thread_rdwr_rlock( &bdb->bi_cache.c_rwlock ); /* See if the ID exists in the database; add it to the cache if so */ if ( !*eip ) { #ifndef BDB_HIER - rc = bdb_id2entry( op->o_bd, tid, id, &ep ); + rc = bdb_id2entry( op->o_bd, tid, locker, id, &ep ); if ( rc == 0 ) { rc = bdb_cache_find_ndn( op, tid, &ep->e_nname, eip ); @@ -718,7 +709,7 @@ again: ldap_pvt_thread_rdwr_rlock( &bdb->bi_cache.c_rwlock ); } } #else - rc = hdb_cache_find_parent(op, tid, id, eip ); + rc = hdb_cache_find_parent(op, tid, locker, id, eip ); if ( rc == 0 && *eip ) islocked = 1; #endif } @@ -751,31 +742,14 @@ load1: bdb_cache_entry_db_unlock( bdb->bi_dbenv, lock ); } else if ( rc == 0 ) { if ( load ) { - DB_TXN *ltid; - u_int32_t locker2 = locker; - - /* We don't wrap entire read operations in txn's, but - * we need our cache entry lock and any DB page locks - * to be associated, in order for deadlock detection - * to work properly. So if we need to read from the DB, - * we use a long-lived per-thread txn for this step. - */ - if ( !ep && !tid ) { - rc = bdb_txn_get( op, bdb->bi_dbenv, <id, 0 ); - if ( ltid ) - locker2 = TXN_ID( ltid ); - } else { - ltid = tid; - } - /* Give up original read lock, obtain write lock with - * (possibly) new locker ID. + /* Give up original read lock, obtain write lock */ if ( rc == 0 ) { - rc = bdb_cache_entry_db_relock( bdb->bi_dbenv, locker2, + rc = bdb_cache_entry_db_relock( bdb->bi_dbenv, locker, *eip, 1, 0, lock ); } if ( rc == 0 && !ep) { - rc = bdb_id2entry( op->o_bd, ltid, id, &ep ); + rc = bdb_id2entry( op->o_bd, tid, locker, id, &ep ); } if ( rc == 0 ) { ep->e_private = *eip; @@ -797,22 +771,6 @@ load1: /* Otherwise, release the lock. */ bdb_cache_entry_db_unlock( bdb->bi_dbenv, lock ); } - if ( locker2 != locker ) { - /* If we're using the per-thread txn, release all - * of its page locks now. - */ - DB_LOCKREQ list; - list.op = DB_LOCK_PUT_ALL; - list.obj = NULL; - bdb->bi_dbenv->lock_vec( bdb->bi_dbenv, locker2, - 0, &list, 1, NULL ); - /* If this txn was deadlocked, we must abort it - * and invalidate this per-thread txn. - */ - if ( rc == DB_LOCK_DEADLOCK ) { - bdb_txn_get( op, bdb->bi_dbenv, <id, 1 ); - } - } } else if ( !(*eip)->bei_e ) { /* Some other thread is trying to load the entry, * give it a chance to finish. @@ -1281,77 +1239,6 @@ bdb_lru_print( Cache *cache ) } #endif -static void -bdb_txn_free( void *key, void *data ) -{ - DB_TXN *txn = data; - TXN_ABORT( txn ); -} - -/* Obtain a long-lived transaction for the current thread. - * If reset == 1, remove the current transaction. */ -static int -bdb_txn_get( Operation *op, DB_ENV *env, DB_TXN **txn, int reset ) -{ - int i, rc; - void *ctx, *data = NULL; - - if ( slapMode & SLAP_TOOL_MODE ) { - *txn = NULL; - return 0; - } - - /* If no op was provided, try to find the ctx anyway... */ - if ( op ) { - ctx = op->o_threadctx; - } else { - ctx = ldap_pvt_thread_pool_context(); - } - - /* Shouldn't happen unless we're single-threaded */ - if ( !ctx ) { - *txn = NULL; - return 0; - } - - if ( reset ) { - TXN_ABORT( *txn ); - return ldap_pvt_thread_pool_setkey( ctx, ((char *)env)+1, NULL, NULL ); - } - - if ( ldap_pvt_thread_pool_getkey( ctx, ((char *)env)+1, &data, NULL ) || - data == NULL ) { - for ( i=0, rc=1; rc != 0 && i<4; i++ ) { - rc = TXN_BEGIN( env, NULL, txn, READ_TXN_FLAG ); -#if DB_VERSION_FULL == 0x04020034 - if ( rc == EINVAL && READ_TXN_FLAG ) { - READ_TXN_FLAG = 0; - Debug( LDAP_DEBUG_ANY, - "bdb_txn_get: BerkeleyDB 4.2.52 library needs TXN patch!\n", - 0, 0, 0 ); - i--; - continue; - } -#endif - if (rc) ldap_pvt_thread_yield(); - } - if ( rc != 0) { - return rc; - } - if ( ( rc = ldap_pvt_thread_pool_setkey( ctx, ((char *)env)+1, - *txn, bdb_txn_free ) ) ) { - TXN_ABORT( *txn ); - Debug( LDAP_DEBUG_ANY, "bdb_txn_get: err %s(%d)\n", - db_strerror(rc), rc, 0 ); - - return rc; - } - } else { - *txn = data; - } - return 0; -} - #ifdef BDB_REUSE_LOCKERS static void bdb_locker_id_free( void *key, void *data ) diff --git a/servers/slapd/back-bdb/delete.c b/servers/slapd/back-bdb/delete.c index a0dcce5669..a1bef6cccd 100644 --- a/servers/slapd/back-bdb/delete.c +++ b/servers/slapd/back-bdb/delete.c @@ -19,6 +19,7 @@ #include #include +#include "lutil.h" #include "back-bdb.h" int @@ -51,15 +52,20 @@ bdb_delete( Operation *op, SlapReply *rs ) int parent_is_glue = 0; int parent_is_leaf = 0; - struct berval ctxcsn_ndn = BER_BVNULL; - ctrls[num_ctrls] = 0; Debug( LDAP_DEBUG_ARGS, "==> " LDAP_XSTRING(bdb_delete) ": %s\n", op->o_req_dn.bv_val, 0, 0 ); - build_new_dn( &ctxcsn_ndn, &op->o_bd->be_nsuffix[0], - (struct berval *)&slap_ldapsync_cn_bv, op->o_tmpmemctx ); + /* allocate CSN */ + if ( !SLAP_SHADOW( op->o_bd )) { + struct berval csn; + char csnbuf[LDAP_LUTIL_CSNSTR_BUFSIZE]; + + csn.bv_val = csnbuf; + csn.bv_len = sizeof(csnbuf); + slap_get_csn( op, &csn, 1 ); + } if( 0 ) { retry: /* transaction retry */ @@ -166,17 +172,8 @@ retry: /* transaction retry */ } rs->sr_err = LDAP_REFERRAL; - send_ldap_result( op, rs ); - - if ( rs->sr_ref != default_referral ) { - ber_bvarray_free( rs->sr_ref ); - } - free( (char *)rs->sr_matched ); - rs->sr_ref = NULL; - rs->sr_matched = NULL; - - rs->sr_err = -1; - goto done; + rs->sr_flags = REP_MATCHED_MUSTBEFREED | REP_REF_MUSTBEFREED; + goto return_results; } rc = bdb_cache_find_id( op, ltid, eip->bei_id, &eip, 0, locker, &plock ); @@ -296,15 +293,9 @@ retry: /* transaction retry */ 0, 0, 0 ); rs->sr_err = LDAP_REFERRAL; - rs->sr_matched = e->e_name.bv_val; - send_ldap_result( op, rs ); - - ber_bvarray_free( rs->sr_ref ); - rs->sr_ref = NULL; - rs->sr_matched = NULL; - - rs->sr_err = 1; - goto done; + rs->sr_matched = ch_strdup( e->e_name.bv_val ); + rs->sr_flags = REP_MATCHED_MUSTBEFREED | REP_REF_MUSTBEFREED; + goto return_results; } /* pre-read */ @@ -455,7 +446,8 @@ retry: /* transaction retry */ if ( ( rs->sr_err = TXN_ABORT( ltid ) ) != 0 ) { rs->sr_text = "txn_abort (no-op) failed"; } else { - rs->sr_err = LDAP_NO_OPERATION; + rs->sr_err = LDAP_X_NO_OPERATION; + ltid = NULL; goto return_results; } } else { @@ -492,19 +484,10 @@ retry: /* transaction retry */ if( num_ctrls ) rs->sr_ctrls = ctrls; return_results: - send_ldap_result( op, rs ); - - if( rs->sr_err == LDAP_SUCCESS && bdb->bi_txn_cp ) { - ldap_pvt_thread_yield(); - TXN_CHECKPOINT( bdb->bi_dbenv, - bdb->bi_txn_cp_kbyte, bdb->bi_txn_cp_min, 0 ); - } - if ( rs->sr_err == LDAP_SUCCESS && parent_is_glue && parent_is_leaf ) { op->o_delete_glue_parent = 1; } -done: if ( p ) bdb_unlocked_cache_return_entry_r(&bdb->bi_cache, p); @@ -520,14 +503,22 @@ done: if( ltid != NULL ) { TXN_ABORT( ltid ); - op->o_private = NULL; } + op->o_private = NULL; - slap_sl_free( ctxcsn_ndn.bv_val, op->o_tmpmemctx ); + send_ldap_result( op, rs ); + if ( !SLAP_SHADOW( op->o_bd )) + slap_graduate_commit_csn( op ); if( preread_ctrl != NULL ) { slap_sl_free( (*preread_ctrl)->ldctl_value.bv_val, op->o_tmpmemctx ); slap_sl_free( *preread_ctrl, op->o_tmpmemctx ); } + + if( rs->sr_err == LDAP_SUCCESS && bdb->bi_txn_cp ) { + ldap_pvt_thread_yield(); + TXN_CHECKPOINT( bdb->bi_dbenv, + bdb->bi_txn_cp_kbyte, bdb->bi_txn_cp_min, 0 ); + } return rs->sr_err; } diff --git a/servers/slapd/back-bdb/dn2id.c b/servers/slapd/back-bdb/dn2id.c index d2ed137e97..51beedb2f4 100644 --- a/servers/slapd/back-bdb/dn2id.c +++ b/servers/slapd/back-bdb/dn2id.c @@ -709,6 +709,7 @@ int hdb_dn2id_parent( Operation *op, DB_TXN *txn, + u_int32_t locker, EntryInfo *ei, ID *idp ) { @@ -733,6 +734,9 @@ hdb_dn2id_parent( rc = db->cursor( db, txn, &cursor, bdb->bi_db_opflags ); if ( rc ) return rc; + if ( !txn && locker ) { + cursor->locker = locker; + } data.ulen = sizeof(diskNode) + (SLAP_LDAPDN_MAXLEN * 2); d = op->o_tmpalloc( data.ulen, op->o_tmpmemctx ); @@ -915,7 +919,8 @@ hdb_dn2idl_internal( cx->rc = cx->db->cursor( cx->db, NULL, &cx->dbc, cx->bdb->bi_db_opflags ); - if ( cx->rc ) return cx->rc; + if ( cx->rc ) + goto done_one; cx->data.data = &cx->dbuf; cx->data.ulen = sizeof(ID); @@ -928,7 +933,7 @@ hdb_dn2idl_internal( cx->rc = cx->dbc->c_get( cx->dbc, &cx->key, &cx->data, DB_SET ); if ( cx->rc ) { cx->dbc->c_close( cx->dbc ); - return cx->rc; + goto done_one; } /* If the on-disk count is zero we've never checked it. @@ -973,6 +978,13 @@ hdb_dn2idl_internal( } } cx->rc = cx->dbc->c_close( cx->dbc ); +done_one: + bdb_cache_entryinfo_lock( cx->ei ); + cx->ei->bei_state ^= CACHE_ENTRY_ONELEVEL; + bdb_cache_entryinfo_unlock( cx->ei ); + if ( cx->rc ) + return cx->rc; + } else { /* The in-memory cache is in sync with the on-disk data. * do we have any kids? diff --git a/servers/slapd/back-bdb/id2entry.c b/servers/slapd/back-bdb/id2entry.c index 9a1e7d520c..dd427d2ba6 100644 --- a/servers/slapd/back-bdb/id2entry.c +++ b/servers/slapd/back-bdb/id2entry.c @@ -92,12 +92,14 @@ int bdb_id2entry_update( int bdb_id2entry( BackendDB *be, DB_TXN *tid, + u_int32_t locker, ID id, Entry **e ) { struct bdb_info *bdb = (struct bdb_info *) be->be_private; DB *db = bdb->bi_id2entry->bdi_db; DBT key, data; + DBC *cursor; struct berval bv; int rc = 0; ID nid; @@ -113,7 +115,15 @@ int bdb_id2entry( data.flags = DB_DBT_MALLOC; /* fetch it */ - rc = db->get( db, tid, &key, &data, bdb->bi_db_opflags ); + rc = db->cursor( db, tid, &cursor, bdb->bi_db_opflags ); + if ( rc ) return rc; + + /* Use our own locker if needed */ + if ( !tid && locker ) + cursor->locker = locker; + + rc = cursor->c_get( cursor, &key, &data, DB_SET ); + cursor->c_close( cursor ); if( rc != 0 ) { return rc; @@ -212,14 +222,10 @@ int bdb_entry_return( e->e_nname.bv_val = NULL; } #ifndef SLAP_ZONE_ALLOC -#ifndef BDB_HIER /* In tool mode the e_bv buffer is realloc'd, leave it alone */ if( !(slapMode & SLAP_TOOL_MODE) ) { free( e->e_bv.bv_val ); } -#else - free( e->e_bv.bv_val ); -#endif /* BDB_HIER */ #endif /* !SLAP_ZONE_ALLOC */ #ifdef SLAP_ZONE_ALLOC diff --git a/servers/slapd/back-bdb/index.c b/servers/slapd/back-bdb/index.c index 0e17da25b7..18c478db53 100644 --- a/servers/slapd/back-bdb/index.c +++ b/servers/slapd/back-bdb/index.c @@ -48,7 +48,7 @@ static AttrInfo *index_mask( /* has tagging option */ ai = bdb_attr_mask( be->be_private, desc->ad_type->sat_ad ); - if ( ai && ( ai->ai_indexmask ^ SLAP_INDEX_NOTAGS ) ) { + if ( ai && !( ai->ai_indexmask & SLAP_INDEX_NOTAGS ) ) { *atname = desc->ad_type->sat_cname; return ai; } @@ -61,7 +61,7 @@ static AttrInfo *index_mask( ai = bdb_attr_mask( be->be_private, at->sat_ad ); - if ( ai && ( ai->ai_indexmask ^ SLAP_INDEX_NOSUBTYPES ) ) { + if ( ai && !( ai->ai_indexmask & SLAP_INDEX_NOSUBTYPES ) ) { *atname = at->sat_cname; return ai; } @@ -377,6 +377,80 @@ int bdb_index_values( return rc; } +/* Get the list of which indices apply to this attr */ +int +bdb_index_recset( + struct bdb_info *bdb, + Attribute *a, + AttributeType *type, + struct berval *tags, + IndexRec *ir ) +{ + int rc, slot; + AttrList *al; + + if( type->sat_sup ) { + /* recurse */ + rc = bdb_index_recset( bdb, a, type->sat_sup, tags, ir ); + if( rc ) return rc; + } + /* If this type has no AD, we've never used it before */ + if( type->sat_ad ) { + slot = bdb_attr_slot( bdb, type->sat_ad, NULL ); + if ( slot >= 0 ) { + ir[slot].ai = bdb->bi_attrs[slot]; + al = ch_malloc( sizeof( AttrList )); + al->attr = a; + al->next = ir[slot].attrs; + ir[slot].attrs = al; + } + } + if( tags->bv_len ) { + AttributeDescription *desc; + + desc = ad_find_tags( type, tags ); + if( desc ) { + slot = bdb_attr_slot( bdb, desc, NULL ); + if ( slot >= 0 ) { + ir[slot].ai = bdb->bi_attrs[slot]; + al = ch_malloc( sizeof( AttrList )); + al->attr = a; + al->next = ir[slot].attrs; + ir[slot].attrs = al; + } + } + } + return LDAP_SUCCESS; +} + +/* Apply the indices for the recset */ +int bdb_index_recrun( + Operation *op, + struct bdb_info *bdb, + IndexRec *ir0, + ID id, + int base ) +{ + IndexRec *ir; + AttrList *al; + int i, rc = 0; + + for (i=base; ibi_nattrs; i+=slap_tool_thread_max) { + ir = ir0 + i; + if ( !ir->ai ) continue; + while (( al = ir->attrs )) { + ir->attrs = al->next; + rc = indexer( op, NULL, ir->ai->ai_desc, + &ir->ai->ai_desc->ad_type->sat_cname, + al->attr->a_nvals, id, SLAP_INDEX_ADD_OP, + ir->ai->ai_indexmask ); + free( al ); + if ( rc ) break; + } + } + return rc; +} + int bdb_index_entry( Operation *op, diff --git a/servers/slapd/back-bdb/init.c b/servers/slapd/back-bdb/init.c index 36af08c8e5..3fbf91bf6d 100644 --- a/servers/slapd/back-bdb/init.c +++ b/servers/slapd/back-bdb/init.c @@ -426,6 +426,10 @@ bdb_db_open( BackendDB *be ) } if( i == BDB_ID2ENTRY ) { + if ( slapMode & SLAP_TOOL_MODE ) + db->bdi_db->mpf->set_priority( db->bdi_db->mpf, + DB_PRIORITY_VERY_LOW ); + rc = db->bdi_db->set_pagesize( db->bdi_db, BDB_ID2ENTRY_PAGESIZE ); if ( slapMode & SLAP_TOOL_READMAIN ) { @@ -482,13 +486,6 @@ bdb_db_open( BackendDB *be ) return rc; } -#if 0 - if( i == BDB_ID2ENTRY && ( slapMode & SLAP_TOOL_MODE )) { - db->bdi_db->mpf->set_priority( db->bdi_db->mpf, - DB_PRIORITY_VERY_LOW ); - } -#endif - flags &= ~(DB_CREATE | DB_RDONLY); db->bdi_name = bdbi_databases[i].name; bdb->bi_databases[i] = db; @@ -609,7 +606,7 @@ bdb_db_destroy( BackendDB *be ) if( bdb->bi_dbenv_home ) ch_free( bdb->bi_dbenv_home ); if( bdb->bi_db_config_path ) ch_free( bdb->bi_db_config_path ); - bdb_attr_index_destroy( bdb->bi_attrs ); + bdb_attr_index_destroy( bdb ); ldap_pvt_thread_rdwr_destroy ( &bdb->bi_cache.c_rwlock ); ldap_pvt_thread_mutex_destroy( &bdb->bi_cache.lru_mutex ); diff --git a/servers/slapd/back-bdb/key.c b/servers/slapd/back-bdb/key.c index e642366935..7b36624e08 100644 --- a/servers/slapd/back-bdb/key.c +++ b/servers/slapd/back-bdb/key.c @@ -84,7 +84,13 @@ bdb_key_change( if (op == SLAP_INDEX_ADD_OP) { /* Add values */ - rc = bdb_idl_insert_key( be, db, txn, &key, id ); + +#ifdef BDB_TOOL_IDL_CACHING + if ( slapMode & SLAP_TOOL_QUICK ) + rc = bdb_tool_idl_add( be, db, txn, &key, id ); + else +#endif + rc = bdb_idl_insert_key( be, db, txn, &key, id ); if ( rc == DB_KEYEXIST ) rc = 0; } else { /* Delete values */ diff --git a/servers/slapd/back-bdb/modify.c b/servers/slapd/back-bdb/modify.c index e680de5ef2..08d0a5d8c7 100644 --- a/servers/slapd/back-bdb/modify.c +++ b/servers/slapd/back-bdb/modify.c @@ -289,6 +289,9 @@ bdb_modify( Operation *op, SlapReply *rs ) ctrls[num_ctrls] = NULL; + if ( !SLAP_SHADOW( op->o_bd )) + slap_mods_opattrs( op, op->orm_modlist, 1 ); + if( 0 ) { retry: /* transaction retry */ if ( dummy.e_attrs ) { @@ -524,7 +527,8 @@ retry: /* transaction retry */ if ( ( rs->sr_err = TXN_ABORT( ltid ) ) != 0 ) { rs->sr_text = "txn_abort (no-op) failed"; } else { - rs->sr_err = LDAP_NO_OPERATION; + rs->sr_err = LDAP_X_NO_OPERATION; + ltid = NULL; goto return_results; } } else { @@ -573,6 +577,8 @@ return_results: attrs_free( dummy.e_attrs ); } send_ldap_result( op, rs ); + if ( !SLAP_SHADOW( op->o_bd )) + slap_graduate_commit_csn( op ); if( rs->sr_err == LDAP_SUCCESS && bdb->bi_txn_cp ) { ldap_pvt_thread_yield(); @@ -583,8 +589,8 @@ return_results: done: if( ltid != NULL ) { TXN_ABORT( ltid ); - op->o_private = NULL; } + op->o_private = NULL; if( e != NULL ) { bdb_unlocked_cache_return_entry_w (&bdb->bi_cache, e); diff --git a/servers/slapd/back-bdb/modrdn.c b/servers/slapd/back-bdb/modrdn.c index 1bdebe5133..422420dcaf 100644 --- a/servers/slapd/back-bdb/modrdn.c +++ b/servers/slapd/back-bdb/modrdn.c @@ -728,7 +728,8 @@ retry: /* transaction retry */ if(( rs->sr_err=TXN_ABORT( ltid )) != 0 ) { rs->sr_text = "txn_abort (no-op) failed"; } else { - rs->sr_err = LDAP_SUCCESS; + rs->sr_err = LDAP_X_NO_OPERATION; + ltid = NULL; goto return_results; } @@ -831,8 +832,8 @@ done: if( ltid != NULL ) { TXN_ABORT( ltid ); - op->o_private = NULL; } + op->o_private = NULL; if( preread_ctrl != NULL ) { slap_sl_free( (*preread_ctrl)->ldctl_value.bv_val, op->o_tmpmemctx ); diff --git a/servers/slapd/back-bdb/proto-bdb.h b/servers/slapd/back-bdb/proto-bdb.h index a9a3b83156..9991da08b3 100644 --- a/servers/slapd/back-bdb/proto-bdb.h +++ b/servers/slapd/back-bdb/proto-bdb.h @@ -32,25 +32,32 @@ LDAP_BEGIN_DECL #define bdb_attr_mask BDB_SYMBOL(attr_mask) #define bdb_attr_flush BDB_SYMBOL(attr_flush) +#define bdb_attr_slot BDB_SYMBOL(attr_slot) #define bdb_attr_index_config BDB_SYMBOL(attr_index_config) #define bdb_attr_index_destroy BDB_SYMBOL(attr_index_destroy) #define bdb_attr_index_free BDB_SYMBOL(attr_index_free) #define bdb_attr_index_unparse BDB_SYMBOL(attr_index_unparse) +#define bdb_attr_info_free BDB_SYMBOL(attr_info_free) AttrInfo *bdb_attr_mask( struct bdb_info *bdb, AttributeDescription *desc ); void bdb_attr_flush( struct bdb_info *bdb ); +int bdb_attr_slot( struct bdb_info *bdb, + AttributeDescription *desc, unsigned *insert ); + int bdb_attr_index_config LDAP_P(( struct bdb_info *bdb, const char *fname, int lineno, int argc, char **argv )); void bdb_attr_index_unparse LDAP_P(( struct bdb_info *bdb, BerVarray *bva )); -void bdb_attr_index_destroy LDAP_P(( Avlnode *tree )); +void bdb_attr_index_destroy LDAP_P(( struct bdb_info *bdb )); void bdb_attr_index_free LDAP_P(( struct bdb_info *bdb, AttributeDescription *ad )); +void bdb_attr_info_free( AttrInfo *ai ); + /* * config.c */ @@ -124,6 +131,7 @@ int bdb_dn2idl( int bdb_dn2id_parent( Operation *op, DB_TXN *txn, + u_int32_t locker, EntryInfo *ei, ID *idp ); @@ -191,6 +199,7 @@ int bdb_id2entry_delete( int bdb_id2entry( BackendDB *be, DB_TXN *tid, + u_int32_t locker, ID id, Entry **e); #endif @@ -320,6 +329,8 @@ int bdb_idl_append_one( ID *ids, ID id ); #define bdb_index_param BDB_SYMBOL(index_param) #define bdb_index_values BDB_SYMBOL(index_values) #define bdb_index_entry BDB_SYMBOL(index_entry) +#define bdb_index_recset BDB_SYMBOL(index_recset) +#define bdb_index_recrun BDB_SYMBOL(index_recrun) extern int bdb_index_is_indexed LDAP_P(( @@ -344,6 +355,22 @@ bdb_index_values LDAP_P(( ID id, int opid )); +extern int +bdb_index_recset LDAP_P(( + struct bdb_info *bdb, + Attribute *a, + AttributeType *type, + struct berval *tags, + IndexRec *ir )); + +extern int +bdb_index_recrun LDAP_P(( + Operation *op, + struct bdb_info *bdb, + IndexRec *ir, + ID id, + int base )); + int bdb_index_entry LDAP_P(( Operation *op, DB_TXN *t, int r, Entry *e )); #define bdb_index_entry_add(op,t,e) \ @@ -443,6 +470,7 @@ void bdb_unlocked_cache_return_entry_rw( Cache *cache, Entry *e, int rw ); #define bdb_cache_find_id BDB_SYMBOL(cache_find_id) #define bdb_cache_find_info BDB_SYMBOL(cache_find_info) #define bdb_cache_find_ndn BDB_SYMBOL(cache_find_ndn) +#define bdb_cache_find_parent BDB_SYMBOL(cache_find_parent) #define bdb_cache_modify BDB_SYMBOL(cache_modify) #define bdb_cache_modrdn BDB_SYMBOL(cache_modrdn) #define bdb_cache_release_all BDB_SYMBOL(cache_release_all) @@ -495,6 +523,14 @@ int bdb_cache_find_id( u_int32_t locker, DB_LOCK *lock ); +int +bdb_cache_find_parent( + Operation *op, + DB_TXN *txn, + u_int32_t locker, + ID id, + EntryInfo **res +); int bdb_cache_delete( Cache *cache, Entry *e, @@ -584,6 +620,7 @@ bdb_trans_backoff( int num_retries ); #define bdb_tool_dn2id_get BDB_SYMBOL(tool_dn2id_get) #define bdb_tool_id2entry_get BDB_SYMBOL(tool_id2entry_get) #define bdb_tool_entry_modify BDB_SYMBOL(tool_entry_modify) +#define bdb_tool_idl_add BDB_SYMBOL(tool_idl_add) extern BI_init bdb_back_initialize; @@ -615,6 +652,8 @@ extern BI_tool_dn2id_get bdb_tool_dn2id_get; extern BI_tool_id2entry_get bdb_tool_id2entry_get; extern BI_tool_entry_modify bdb_tool_entry_modify; +int bdb_tool_idl_add( BackendDB *be, DB *db, DB_TXN *txn, DBT *key, ID id ); + LDAP_END_DECL #endif /* _PROTO_BDB_H */ diff --git a/servers/slapd/back-bdb/tools.c b/servers/slapd/back-bdb/tools.c index bafba3549e..d3701e1593 100644 --- a/servers/slapd/back-bdb/tools.c +++ b/servers/slapd/back-bdb/tools.c @@ -21,6 +21,7 @@ #define AVL_INTERNAL #include "back-bdb.h" +#include "idl.h" static DBC *cursor = NULL; static DBT key, data; @@ -35,24 +36,96 @@ static dn_id hbuf[HOLE_SIZE], *holes = hbuf; static unsigned nhmax = HOLE_SIZE; static unsigned nholes; -static Avlnode *index_attrs, index_dummy; +static int index_nattrs; + +#ifdef BDB_TOOL_IDL_CACHING +#define bdb_tool_idl_cmp BDB_SYMBOL(tool_idl_cmp) +#define bdb_tool_idl_flush_one BDB_SYMBOL(tool_idl_flush_one) +#define bdb_tool_idl_flush BDB_SYMBOL(tool_idl_flush) + +static int bdb_tool_idl_flush( BackendDB *be ); + +#define IDBLOCK 1024 + +typedef struct bdb_tool_idl_cache_entry { + struct bdb_tool_idl_cache_entry *next; + ID ids[IDBLOCK]; +} bdb_tool_idl_cache_entry; + +typedef struct bdb_tool_idl_cache { + struct berval kstr; + bdb_tool_idl_cache_entry *head, *tail; + ID first, last; + int count; +} bdb_tool_idl_cache; + +static bdb_tool_idl_cache_entry *bdb_tool_idl_free_list; +#endif /* BDB_TOOL_IDL_CACHING */ + +static ID bdb_tool_ix_id; +static Operation *bdb_tool_ix_op; +static volatile int *bdb_tool_index_threads; +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 int bdb_tool_ix_rec( int base ); +static void * bdb_tool_index_task( void *ctx, void *ptr ); int bdb_tool_entry_open( BackendDB *be, int mode ) { + struct bdb_info *bdb = (struct bdb_info *) be->be_private; + /* initialize key and data thangs */ DBTzero( &key ); DBTzero( &data ); key.flags = DB_DBT_REALLOC; data.flags = DB_DBT_REALLOC; + if (cursor == NULL) { + int rc = bdb->bi_id2entry->bdi_db->cursor( + bdb->bi_id2entry->bdi_db, NULL, &cursor, + bdb->bi_db_opflags ); + if( rc != 0 ) { + return -1; + } + } + + /* Set up for slapindex */ + if ( !(slapMode & SLAP_TOOL_READONLY )) { + int i; + if ( !bdb_tool_info && ( slapMode & SLAP_TOOL_QUICK )) { + ldap_pvt_thread_mutex_init( &bdb_tool_index_mutex ); + ldap_pvt_thread_cond_init( &bdb_tool_index_cond ); + bdb_tool_index_threads = ch_malloc( slap_tool_thread_max * sizeof( int )); + bdb_tool_index_rec = ch_malloc( bdb->bi_nattrs * sizeof( IndexRec )); + for (i=1; ibe_private; + + if ( bdb_tool_info ) { + slapd_shutdown = 1; + ldap_pvt_thread_mutex_lock( &bdb_tool_index_mutex ); + ldap_pvt_thread_cond_broadcast( &bdb_tool_index_cond ); + ldap_pvt_thread_mutex_unlock( &bdb_tool_index_mutex ); + } if( key.data ) { ch_free( key.data ); @@ -68,6 +141,10 @@ int bdb_tool_entry_close( cursor = NULL; } +#ifdef BDB_TOOL_IDL_CACHING + bdb_tool_idl_flush( be ); +#endif + if( nholes ) { unsigned i; fprintf( stderr, "Error, entries missing!\n"); @@ -81,8 +158,6 @@ int bdb_tool_entry_close( return 0; } -static int bdb_reindex_cmp(const void *a, const void *b) { return 0; } - ID bdb_tool_entry_next( BackendDB *be ) { @@ -94,30 +169,19 @@ ID bdb_tool_entry_next( assert( slapMode & SLAP_TOOL_MODE ); assert( bdb != NULL ); - /* Initialization */ - if (cursor == NULL) { - rc = bdb->bi_id2entry->bdi_db->cursor( - bdb->bi_id2entry->bdi_db, NULL, &cursor, - bdb->bi_db_opflags ); - if( rc != 0 ) { - return NOID; - } - } - rc = cursor->c_get( cursor, &key, &data, DB_NEXT ); if( rc != 0 ) { /* If we're doing linear indexing and there are more attrs to * index, and we're at the end of the database, start over. */ - if ( bdb->bi_attrs == &index_dummy ) { - if ( index_attrs && rc == DB_NOTFOUND ) { - /* optional - do a checkpoint here? */ - index_dummy.avl_data = avl_delete(&index_attrs, NULL, bdb_reindex_cmp); - rc = cursor->c_get( cursor, &key, &data, DB_FIRST ); - } + if ( index_nattrs && rc == DB_NOTFOUND ) { + /* optional - do a checkpoint here? */ + bdb_attr_info_free( bdb->bi_attrs[0] ); + bdb->bi_attrs[0] = bdb->bi_attrs[index_nattrs]; + index_nattrs--; + rc = cursor->c_get( cursor, &key, &data, DB_FIRST ); if ( rc ) { - bdb->bi_attrs = NULL; return NOID; } } else { @@ -165,7 +229,7 @@ int bdb_tool_id2entry_get( Entry **e ) { - int rc = bdb_id2entry( be, NULL, id, e ); + int rc = bdb_id2entry( be, NULL, 0, id, e ); if ( rc == DB_NOTFOUND && id == 0 ) { Entry *dummy = ch_calloc( 1, sizeof(Entry) ); @@ -185,15 +249,12 @@ Entry* bdb_tool_entry_get( BackendDB *be, ID id ) { int rc; Entry *e = NULL; -#ifndef BDB_HIER struct berval bv; -#endif assert( be != NULL ); assert( slapMode & SLAP_TOOL_MODE ); assert( data.data != NULL ); -#ifndef BDB_HIER DBT2bv( &data, &bv ); #ifdef SLAP_ZONE_ALLOC @@ -206,8 +267,8 @@ Entry* bdb_tool_entry_get( BackendDB *be, ID id ) if( rc == LDAP_SUCCESS ) { e->e_id = id; } -#else - { +#ifdef BDB_HIER + if ( slapMode & SLAP_TOOL_READONLY ) { EntryInfo *ei = NULL; Operation op = {0}; Opheader ohdr = {0}; @@ -217,9 +278,15 @@ Entry* bdb_tool_entry_get( BackendDB *be, ID id ) op.o_tmpmemctx = NULL; op.o_tmpmfuncs = &ch_mfuncs; - rc = bdb_cache_find_id( &op, NULL, id, &ei, 0, 0, NULL ); - if ( rc == LDAP_SUCCESS ) - e = ei->bei_e; + rc = bdb_cache_find_parent( &op, NULL, cursor->locker, id, &ei ); + if ( rc == LDAP_SUCCESS ) { + bdb_cache_entryinfo_unlock( ei ); + e->e_private = ei; + ei->bei_e = e; + bdb_fix_dn( e, 0 ); + ei->bei_e = NULL; + e->e_private = NULL; + } } #endif return e; @@ -317,6 +384,53 @@ static int bdb_tool_next_id( return rc; } +static int +bdb_tool_index_add( + Operation *op, + DB_TXN *txn, + Entry *e ) +{ + struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private; + + if ( slapMode & SLAP_TOOL_QUICK ) { + IndexRec *ir; + int i, rc; + Attribute *a; + + ir = bdb_tool_index_rec; + memset(ir, 0, bdb->bi_nattrs * sizeof( IndexRec )); + + for ( a = e->e_attrs; a != NULL; a = a->a_next ) { + rc = bdb_index_recset( bdb, a, a->a_desc->ad_type, + &a->a_desc->ad_tags, ir ); + if ( rc ) + return rc; + } + bdb_tool_ix_id = e->e_id; + bdb_tool_ix_op = op; + ldap_pvt_thread_mutex_lock( &bdb_tool_index_mutex ); + for ( i=1; ie_id, 0 ); + if ( rc ) + return rc; + for ( i=1; ibi_linear_index ) - rc = bdb_index_entry_add( &op, tid, e ); + rc = bdb_tool_index_add( &op, tid, e ); if( rc != 0 ) { snprintf( text->bv_val, text->bv_len, "index_entry_add failed: %s (%d)", @@ -441,10 +555,9 @@ int bdb_tool_entry_reindex( } /* Get the first attribute to index */ - if (bi->bi_linear_index && !index_attrs && bi->bi_attrs != &index_dummy) { - index_attrs = bi->bi_attrs; - bi->bi_attrs = &index_dummy; - index_dummy.avl_data = avl_delete(&index_attrs, NULL, bdb_reindex_cmp); + if (bi->bi_linear_index && !index_nattrs) { + index_nattrs = bi->bi_nattrs - 1; + bi->bi_nattrs = 1; } e = bdb_tool_entry_get( be, id ); @@ -484,7 +597,7 @@ int bdb_tool_entry_reindex( op.o_tmpmemctx = NULL; op.o_tmpmfuncs = &ch_mfuncs; - rc = bdb_index_entry_add( &op, tid, e ); + rc = bdb_tool_index_add( &op, tid, e ); done: if( rc == 0 ) { @@ -626,3 +739,311 @@ done: return e->e_id; } + +#ifdef BDB_TOOL_IDL_CACHING +static int +bdb_tool_idl_cmp( const void *v1, const void *v2 ) +{ + const bdb_tool_idl_cache *c1 = v1, *c2 = v2; + int rc; + + if (( rc = c1->kstr.bv_len - c2->kstr.bv_len )) return rc; + return memcmp( c1->kstr.bv_val, c2->kstr.bv_val, c1->kstr.bv_len ); +} + +static int +bdb_tool_idl_flush_one( void *v1, void *arg ) +{ + bdb_tool_idl_cache *ic = v1; + DB *db = arg; + struct bdb_info *bdb = bdb_tool_info; + bdb_tool_idl_cache_entry *ice; + DBC *curs; + DBT key, data; + int i, rc; + ID id, nid; + + /* Freshly allocated, ignore it */ + if ( !ic->head && ic->count <= BDB_IDL_DB_SIZE ) { + return 0; + } + + rc = db->cursor( db, NULL, &curs, 0 ); + if ( rc ) + return -1; + + DBTzero( &key ); + DBTzero( &data ); + + bv2DBT( &ic->kstr, &key ); + + data.size = data.ulen = sizeof( ID ); + data.flags = DB_DBT_USERMEM; + data.data = &nid; + + rc = curs->c_get( curs, &key, &data, DB_SET ); + /* If key already exists and we're writing a range... */ + if ( rc == 0 && ic->count > BDB_IDL_DB_SIZE ) { + /* If it's not currently a range, must delete old info */ + if ( nid ) { + /* Skip lo */ + while ( curs->c_get( curs, &key, &data, DB_NEXT_DUP ) == 0 ) + curs->c_del( curs, 0 ); + + nid = 0; + /* Store range marker */ + curs->c_put( curs, &key, &data, DB_KEYFIRST ); + } else { + + /* Skip lo */ + rc = curs->c_get( curs, &key, &data, DB_NEXT_DUP ); + + /* Get hi */ + rc = curs->c_get( curs, &key, &data, DB_NEXT_DUP ); + + /* Delete hi */ + curs->c_del( curs, 0 ); + } + BDB_ID2DISK( ic->last, &nid ); + curs->c_put( curs, &key, &data, DB_KEYLAST ); + rc = 0; + } else if ( rc && rc != DB_NOTFOUND ) { + rc = -1; + } else if ( ic->count > BDB_IDL_DB_SIZE ) { + /* range, didn't exist before */ + nid = 0; + rc = curs->c_put( curs, &key, &data, DB_KEYLAST ); + if ( rc == 0 ) { + BDB_ID2DISK( ic->first, &nid ); + rc = curs->c_put( curs, &key, &data, DB_KEYLAST ); + if ( rc == 0 ) { + BDB_ID2DISK( ic->last, &nid ); + rc = curs->c_put( curs, &key, &data, DB_KEYLAST ); + } + } + if ( rc ) { + rc = -1; + } + } else { + int n; + + /* Just a normal write */ + rc = 0; + for ( ice = ic->head, n=0; ice; ice = ice->next, n++ ) { + int end; + if ( ice->next ) { + end = IDBLOCK; + } else { + end = ic->count & (IDBLOCK-1); + if ( !end ) + end = IDBLOCK; + } + for ( i=0; iids[i] ) continue; + BDB_ID2DISK( ice->ids[i], &nid ); + rc = curs->c_put( curs, &key, &data, DB_NODUPDATA ); + if ( rc ) { + if ( rc == DB_KEYEXIST ) { + rc = 0; + continue; + } + rc = -1; + break; + } + } + if ( rc ) { + rc = -1; + break; + } + } + if ( ic->head ) { + ldap_pvt_thread_mutex_lock( &bdb->bi_idl_tree_lrulock ); + ic->tail->next = bdb_tool_idl_free_list; + bdb_tool_idl_free_list = ic->head; + bdb->bi_idl_cache_size -= n; + ldap_pvt_thread_mutex_unlock( &bdb->bi_idl_tree_lrulock ); + } + } + if ( ic != db->app_private ) { + ch_free( ic ); + } else { + ic->head = ic->tail = NULL; + } + curs->c_close( curs ); + return rc; +} + +static int +bdb_tool_idl_flush_db( DB *db, bdb_tool_idl_cache *ic ) +{ + Avlnode *root = db->app_private; + int rc; + + db->app_private = ic; + rc = avl_apply( root, bdb_tool_idl_flush_one, db, -1, AVL_INORDER ); + avl_free( root, NULL ); + db->app_private = NULL; + if ( rc != -1 ) + rc = 0; + return rc; +} + +static int +bdb_tool_idl_flush( BackendDB *be ) +{ + struct bdb_info *bdb = (struct bdb_info *) be->be_private; + DB *db; + Avlnode *root; + int i, rc = 0; + + for ( i=BDB_NDB; i < bdb->bi_ndatabases; i++ ) { + db = bdb->bi_databases[i]->bdi_db; + if ( !db->app_private ) continue; + rc = bdb_tool_idl_flush_db( db, NULL ); + if ( rc ) + break; + } + if ( !rc ) { + bdb->bi_idl_cache_size = 0; + } + return rc; +} + +int bdb_tool_idl_add( + BackendDB *be, + DB *db, + DB_TXN *txn, + DBT *key, + ID id ) +{ + struct bdb_info *bdb = (struct bdb_info *) be->be_private; + bdb_tool_idl_cache *ic, itmp; + bdb_tool_idl_cache_entry *ice; + int rc; + + if ( !bdb->bi_idl_cache_max_size ) + return bdb_idl_insert_key( be, db, txn, key, id ); + + DBT2bv( key, &itmp.kstr ); + + ic = avl_find( (Avlnode *)db->app_private, &itmp, bdb_tool_idl_cmp ); + + /* No entry yet, create one */ + if ( !ic ) { + DBC *curs; + DBT data; + ID nid; + int rc; + + ic = ch_malloc( sizeof( bdb_tool_idl_cache ) + itmp.kstr.bv_len ); + ic->kstr.bv_len = itmp.kstr.bv_len; + ic->kstr.bv_val = (char *)(ic+1); + AC_MEMCPY( ic->kstr.bv_val, itmp.kstr.bv_val, ic->kstr.bv_len ); + ic->head = ic->tail = NULL; + ic->last = 0; + ic->count = 0; + avl_insert( (Avlnode **)&db->app_private, ic, bdb_tool_idl_cmp, + avl_dup_error ); + + /* load existing key count here */ + rc = db->cursor( db, NULL, &curs, 0 ); + if ( rc ) return rc; + + data.ulen = sizeof( ID ); + data.flags = DB_DBT_USERMEM; + data.data = &nid; + rc = curs->c_get( curs, key, &data, DB_SET ); + if ( rc == 0 ) { + if ( nid == 0 ) { + ic->count = BDB_IDL_DB_SIZE+1; + } else { + db_recno_t count; + + curs->c_count( curs, &count, 0 ); + ic->count = count; + BDB_DISK2ID( &nid, &ic->first ); + } + } + curs->c_close( curs ); + } + /* are we a range already? */ + if ( ic->count > BDB_IDL_DB_SIZE ) { + ic->last = id; + return 0; + /* Are we at the limit, and converting to a range? */ + } else if ( ic->count == BDB_IDL_DB_SIZE ) { + int n; + for ( ice = ic->head, n=0; ice; ice = ice->next, n++ ) + /* counting */ ; + if ( n ) { + ldap_pvt_thread_mutex_lock( &bdb->bi_idl_tree_lrulock ); + ic->tail->next = bdb_tool_idl_free_list; + bdb_tool_idl_free_list = ic->head; + bdb->bi_idl_cache_size -= n; + ldap_pvt_thread_mutex_unlock( &bdb->bi_idl_tree_lrulock ); + } + ic->head = ic->tail = NULL; + ic->last = id; + ic->count++; + return 0; + } + /* No free block, create that too */ + if ( !ic->tail || ( ic->count & (IDBLOCK-1)) == 0) { + ice = NULL; + ldap_pvt_thread_mutex_lock( &bdb->bi_idl_tree_lrulock ); + if ( bdb->bi_idl_cache_size >= bdb->bi_idl_cache_max_size ) { + ldap_pvt_thread_mutex_unlock( &bdb->bi_idl_tree_lrulock ); + rc = bdb_tool_idl_flush_db( db, ic ); + if ( rc ) + return rc; + avl_insert( (Avlnode **)&db->app_private, ic, bdb_tool_idl_cmp, + avl_dup_error ); + ldap_pvt_thread_mutex_lock( &bdb->bi_idl_tree_lrulock ); + } + bdb->bi_idl_cache_size++; + if ( bdb_tool_idl_free_list ) { + ice = bdb_tool_idl_free_list; + bdb_tool_idl_free_list = ice->next; + } + ldap_pvt_thread_mutex_unlock( &bdb->bi_idl_tree_lrulock ); + if ( !ice ) { + ice = ch_malloc( sizeof( bdb_tool_idl_cache_entry )); + } + memset( ice, 0, sizeof( *ice )); + if ( !ic->head ) { + ic->head = ice; + } else { + ic->tail->next = ice; + } + ic->tail = ice; + if ( !ic->count ) + ic->first = id; + } + ice = ic->tail; + ice->ids[ ic->count & (IDBLOCK-1) ] = id; + ic->count++; + + return 0; +} +#endif + +static void * +bdb_tool_index_task( void *ctx, void *ptr ) +{ + int base = *(int *)ptr; + + free( ptr ); + while ( 1 ) { + ldap_pvt_thread_mutex_lock( &bdb_tool_index_mutex ); + ldap_pvt_thread_cond_wait( &bdb_tool_index_cond, + &bdb_tool_index_mutex ); + ldap_pvt_thread_mutex_unlock( &bdb_tool_index_mutex ); + if ( slapd_shutdown ) + break; + + bdb_tool_index_threads[base] = bdb_index_recrun( bdb_tool_ix_op, + bdb_tool_info, bdb_tool_index_rec, bdb_tool_ix_id, base ); + } + + return NULL; +} diff --git a/servers/slapd/back-ldap/bind.c b/servers/slapd/back-ldap/bind.c index 93f5cff445..a34dc44e0f 100644 --- a/servers/slapd/back-ldap/bind.c +++ b/servers/slapd/back-ldap/bind.c @@ -503,11 +503,15 @@ ldap_back_getconn( Operation *op, SlapReply *rs, ldap_back_send_t sendok ) } else { BER_BVZERO( &lc->lc_cred ); BER_BVZERO( &lc->lc_bound_ndn ); +#if 0 + /* FIXME: if we set lc_bound_ndn = o_ndn + * we end up with a bind with DN but no password! */ if ( !BER_BVISEMPTY( &op->o_ndn ) && SLAP_IS_AUTHZ_BACKEND( op ) ) { ber_dupbv( &lc->lc_bound_ndn, &op->o_ndn ); } +#endif } #ifdef HAVE_TLS diff --git a/servers/slapd/back-ldap/chain.c b/servers/slapd/back-ldap/chain.c index 2cba84c833..8f702c85b9 100644 --- a/servers/slapd/back-ldap/chain.c +++ b/servers/slapd/back-ldap/chain.c @@ -576,7 +576,7 @@ ldap_chain_response( Operation *op, SlapReply *rs ) #ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR if ( rc != LDAP_SUCCESS || sc2.sc_private == LDAP_CH_ERR ) { - if ( rs->sr_err == LDAP_CANNOT_CHAIN ) { + if ( rs->sr_err == LDAP_X_CANNOT_CHAIN ) { goto cannot_chain; } @@ -584,7 +584,8 @@ ldap_chain_response( Operation *op, SlapReply *rs ) case LDAP_CHAINING_REQUIRED: cannot_chain:; op->o_callback = NULL; - send_ldap_error( op, rs, LDAP_CANNOT_CHAIN, "operation cannot be completed without chaining" ); + send_ldap_error( op, rs, LDAP_X_CANNOT_CHAIN, + "operation cannot be completed without chaining" ); break; default: diff --git a/servers/slapd/back-ldap/extended.c b/servers/slapd/back-ldap/extended.c index 92ebf50034..7218af2e84 100644 --- a/servers/slapd/back-ldap/extended.c +++ b/servers/slapd/back-ldap/extended.c @@ -135,6 +135,12 @@ retry: (char **)&rs->sr_matched, (char **)&rs->sr_text, NULL, NULL, 0 ); + if ( rs->sr_matched && rs->sr_matched[ 0 ] == '\0' ) { + free( (char *)rs->sr_matched ); + } + if ( rs->sr_text && rs->sr_text[ 0 ] == '\0' ) { + free( (char *)rs->sr_text ); + } if ( rc == LDAP_SUCCESS ) { if ( rs->sr_err == LDAP_SUCCESS ) { struct berval newpw; @@ -165,17 +171,19 @@ retry: } } send_ldap_result( op, rs ); - if ( rs->sr_matched ) { - free( (char *)rs->sr_matched ); - } - if ( rs->sr_text ) { - free( (char *)rs->sr_text ); - } - rs->sr_matched = NULL; - rs->sr_text = NULL; rc = -1; } + /* these have to be freed anyway... */ + if ( rs->sr_matched ) { + free( (char *)rs->sr_matched ); + } + if ( rs->sr_text ) { + free( (char *)rs->sr_text ); + } + rs->sr_matched = NULL; + rs->sr_text = NULL; + if ( lc != NULL ) { ldap_back_release_conn( op, rs, lc ); } diff --git a/servers/slapd/back-ldap/search.c b/servers/slapd/back-ldap/search.c index 45bc2e9152..8f33ae38f5 100644 --- a/servers/slapd/back-ldap/search.c +++ b/servers/slapd/back-ldap/search.c @@ -431,6 +431,7 @@ fail:; if ( dnPretty( NULL, &match, &pmatch, op->o_tmpmemctx ) == LDAP_SUCCESS ) { rs->sr_matched = pmatch.bv_val; + LDAP_FREE( match.bv_val ); } else { rs->sr_matched = match.bv_val; diff --git a/servers/slapd/back-ldbm/add.c b/servers/slapd/back-ldbm/add.c index 413d292508..0f98eca3d0 100644 --- a/servers/slapd/back-ldbm/add.c +++ b/servers/slapd/back-ldbm/add.c @@ -25,6 +25,16 @@ #include "back-ldbm.h" #include "proto-back-ldbm.h" +static int +ldbm_csn_cb( + Operation *op, + SlapReply *rs ) +{ + op->o_callback = op->o_callback->sc_next; + slap_graduate_commit_csn( op ); + return SLAP_CB_CONTINUE; +} + int ldbm_back_add( Operation *op, @@ -38,6 +48,7 @@ ldbm_back_add( AttributeDescription *entry = slap_schema.si_ad_entry; char textbuf[SLAP_TEXT_BUFLEN]; size_t textlen = sizeof textbuf; + slap_callback cb = { NULL }; #ifdef LDBM_SUBENTRIES int subentry; #endif @@ -45,6 +56,12 @@ ldbm_back_add( Debug(LDAP_DEBUG_ARGS, "==> ldbm_back_add: %s\n", op->o_req_dn.bv_val, 0, 0); + slap_add_opattrs( op, &rs->sr_text, textbuf, textlen, 1 ); + + cb.sc_cleanup = ldbm_csn_cb; + cb.sc_next = op->o_callback; + op->o_callback = &cb; + rs->sr_err = entry_schema_check( op, op->oq_add.rs_e, NULL, get_manageDIT(op), &rs->sr_text, textbuf, textlen ); diff --git a/servers/slapd/back-ldbm/delete.c b/servers/slapd/back-ldbm/delete.c index 6db0d31dbf..f0274aa623 100644 --- a/servers/slapd/back-ldbm/delete.c +++ b/servers/slapd/back-ldbm/delete.c @@ -24,6 +24,7 @@ #include "slap.h" #include "back-ldbm.h" #include "proto-back-ldbm.h" +#include "lutil.h" int ldbm_back_delete( @@ -44,6 +45,16 @@ ldbm_back_delete( /* grab giant lock for writing */ ldap_pvt_thread_rdwr_wlock(&li->li_giant_rwlock); + /* allocate CSN */ + if ( !SLAP_SHADOW( op->o_bd )) { + struct berval csn; + char csnbuf[LDAP_LUTIL_CSNSTR_BUFSIZE]; + + csn.bv_val = csnbuf; + csn.bv_len = sizeof(csnbuf); + slap_get_csn( op, &csn, 1 ); + } + /* get entry with writer lock */ e = dn2entry_w( op->o_bd, &op->o_req_ndn, &matched ); @@ -64,16 +75,9 @@ ldbm_back_delete( &op->o_req_dn, LDAP_SCOPE_DEFAULT ); } - ldap_pvt_thread_rdwr_wunlock(&li->li_giant_rwlock); - rs->sr_err = LDAP_REFERRAL; - send_ldap_result( op, rs ); - - if ( rs->sr_ref ) ber_bvarray_free( rs->sr_ref ); - free( (char *)rs->sr_matched ); - rs->sr_ref = NULL; - rs->sr_matched = NULL; - return( -1 ); + rs->sr_flags |= REP_MATCHED_MUSTBEFREED | REP_REF_MUSTBEFREED; + goto return_results; } /* check entry for "entry" acl */ @@ -83,10 +87,8 @@ ldbm_back_delete( "<=- ldbm_back_delete: no write access to entry\n", 0, 0, 0 ); - send_ldap_error( op, rs, LDAP_INSUFFICIENT_ACCESS, - "no write access to entry" ); - - rc = LDAP_INSUFFICIENT_ACCESS; + rs->sr_err = LDAP_INSUFFICIENT_ACCESS; + rs->sr_text = "no write access to entry"; goto return_results; } @@ -99,13 +101,8 @@ ldbm_back_delete( 0, 0 ); rs->sr_err = LDAP_REFERRAL; - rs->sr_matched = e->e_name.bv_val; - send_ldap_result( op, rs ); - - if ( rs->sr_ref ) ber_bvarray_free( rs->sr_ref ); - rs->sr_ref = NULL; - rs->sr_matched = NULL; - rc = LDAP_REFERRAL; + rs->sr_matched = ch_strdup( e->e_name.bv_val ); + rs->sr_flags = REP_MATCHED_MUSTBEFREED | REP_REF_MUSTBEFREED; goto return_results; } @@ -113,8 +110,8 @@ ldbm_back_delete( Debug(LDAP_DEBUG_ARGS, "<=- ldbm_back_delete: non leaf %s\n", op->o_req_dn.bv_val, 0, 0); - send_ldap_error( op, rs, LDAP_NOT_ALLOWED_ON_NONLEAF, - "subordinate objects must be deleted first"); + rs->sr_err = LDAP_NOT_ALLOWED_ON_NONLEAF; + rs->sr_text = "subordinate objects must be deleted first"; goto return_results; } @@ -126,8 +123,8 @@ ldbm_back_delete( "<=- ldbm_back_delete: parent does not exist\n", 0, 0, 0); - send_ldap_error( op, rs, LDAP_OTHER, - "could not locate parent of entry" ); + rs->sr_err = LDAP_OTHER; + rs->sr_text = "could not locate parent of entry"; goto return_results; } @@ -139,8 +136,8 @@ ldbm_back_delete( "<=- ldbm_back_delete: no access to parent\n", 0, 0, 0 ); - send_ldap_error( op, rs, LDAP_INSUFFICIENT_ACCESS, - "no write access to parent" ); + rs->sr_err = LDAP_INSUFFICIENT_ACCESS; + rs->sr_text = "no write access to parent"; goto return_results; } @@ -161,8 +158,8 @@ ldbm_back_delete( "<=- ldbm_back_delete: no " "access to parent\n", 0, 0, 0 ); - send_ldap_error( op, rs, LDAP_INSUFFICIENT_ACCESS, - "no write access to parent" ); + rs->sr_err = LDAP_INSUFFICIENT_ACCESS; + rs->sr_text = "no write access to parent"; goto return_results; } @@ -171,9 +168,7 @@ ldbm_back_delete( "<=- ldbm_back_delete: no parent & " "not root\n", 0, 0, 0); - send_ldap_error( op, rs, - LDAP_INSUFFICIENT_ACCESS, - NULL ); + rs->sr_err = LDAP_INSUFFICIENT_ACCESS; goto return_results; } } @@ -185,8 +180,8 @@ ldbm_back_delete( "<=- ldbm_back_delete: operations error %s\n", op->o_req_dn.bv_val, 0, 0); - send_ldap_error( op, rs, LDAP_OTHER, - "DN index delete failed" ); + rs->sr_err = LDAP_OTHER; + rs->sr_text = "DN index delete failed"; goto return_results; } @@ -196,8 +191,8 @@ ldbm_back_delete( "<=- ldbm_back_delete: operations error %s\n", op->o_req_dn.bv_val, 0, 0); - send_ldap_error( op, rs, LDAP_OTHER, - "entry delete failed" ); + rs->sr_err = LDAP_OTHER; + rs->sr_text = "entry delete failed"; goto return_results; } @@ -205,19 +200,25 @@ ldbm_back_delete( (void) index_entry_del( op, e ); rs->sr_err = LDAP_SUCCESS; - send_ldap_result( op, rs ); - rc = LDAP_SUCCESS; return_results:; + rc = rs->sr_err; + if( p != NULL ) { /* free parent and writer lock */ cache_return_entry_w( &li->li_cache, p ); } - /* free entry and writer lock */ - cache_return_entry_w( &li->li_cache, e ); + if ( e != NULL ) { + /* free entry and writer lock */ + cache_return_entry_w( &li->li_cache, e ); + } ldap_pvt_thread_rdwr_wunlock(&li->li_giant_rwlock); + send_ldap_result( op, rs ); + if ( !SLAP_SHADOW( op->o_bd )) + slap_graduate_commit_csn( op ); + return rc; } diff --git a/servers/slapd/back-ldbm/modify.c b/servers/slapd/back-ldbm/modify.c index 2dd696919f..1df17bd4f7 100644 --- a/servers/slapd/back-ldbm/modify.c +++ b/servers/slapd/back-ldbm/modify.c @@ -241,6 +241,9 @@ ldbm_back_modify( Debug(LDAP_DEBUG_ARGS, "ldbm_back_modify:\n", 0, 0, 0); + if ( !SLAP_SHADOW( op->o_bd )) + slap_mods_opattrs( op, op->orm_modlist, 1 ); + /* grab giant lock for writing */ ldap_pvt_thread_rdwr_wlock(&li->li_giant_rwlock); @@ -250,7 +253,7 @@ ldbm_back_modify( /* FIXME: dn2entry() should return non-glue entry */ if (( e == NULL ) || ( !manageDSAit && e && is_entry_glue( e ))) { if ( matched != NULL ) { - rs->sr_matched = ch_strdup( matched->e_dn ); + rs->sr_matched = ber_strdup_x( matched->e_dn, op->o_tmpmemctx ); rs->sr_ref = is_entry_referral( matched ) ? get_entry_referrals( op, matched ) : NULL; @@ -260,16 +263,9 @@ ldbm_back_modify( &op->o_req_dn, LDAP_SCOPE_DEFAULT ); } - ldap_pvt_thread_rdwr_wunlock(&li->li_giant_rwlock); rs->sr_err = LDAP_REFERRAL; - send_ldap_result( op, rs ); - - if ( rs->sr_ref ) ber_bvarray_free( rs->sr_ref ); - free( (char *)rs->sr_matched ); - - rs->sr_ref = NULL; - rs->sr_matched = NULL; - return rs->sr_err; + rs->sr_flags = REP_MATCHED_MUSTBEFREED | REP_REF_MUSTBEFREED; + goto return_results; } if ( !manageDSAit && is_entry_referral( e ) ) @@ -282,47 +278,31 @@ ldbm_back_modify( 0, 0 ); rs->sr_err = LDAP_REFERRAL; - rs->sr_matched = e->e_name.bv_val; - send_ldap_result( op, rs ); - - if ( rs->sr_ref ) ber_bvarray_free( rs->sr_ref ); - rs->sr_ref = NULL; - rs->sr_matched = NULL; - goto error_return; + rs->sr_matched = ber_strdup_x( e->e_name.bv_val, op->o_tmpmemctx ); + rs->sr_flags = REP_MATCHED_MUSTBEFREED | REP_REF_MUSTBEFREED; + goto return_results; } /* Modify the entry */ rs->sr_err = ldbm_modify_internal( op, op->oq_modify.rs_modlist, e, &rs->sr_text, textbuf, textlen ); - if( rs->sr_err != LDAP_SUCCESS ) { - if( rs->sr_err != SLAPD_ABANDON ) { - send_ldap_result( op, rs ); - } - - goto error_return; - } - /* change the entry itself */ - if ( id2entry_add( op->o_bd, e ) != 0 ) { - send_ldap_error( op, rs, LDAP_OTHER, - "id2entry failure" ); - rs->sr_err = LDAP_OTHER; - goto error_return; + if( rs->sr_err == LDAP_SUCCESS ) { + if ( id2entry_add( op->o_bd, e ) != 0 ) { + rs->sr_err = LDAP_OTHER; + rs->sr_text = "id2entry failure"; + } } - rs->sr_text = NULL; - send_ldap_error( op, rs, LDAP_SUCCESS, - NULL ); - +return_results:; cache_return_entry_w( &li->li_cache, e ); ldap_pvt_thread_rdwr_wunlock(&li->li_giant_rwlock); - return LDAP_SUCCESS; + send_ldap_result( op, rs ); + if ( !SLAP_SHADOW( op->o_bd )) + slap_graduate_commit_csn( op ); -error_return:; - cache_return_entry_w( &li->li_cache, e ); - ldap_pvt_thread_rdwr_wunlock(&li->li_giant_rwlock); rs->sr_text = NULL; return rs->sr_err; } diff --git a/servers/slapd/back-ldif/ldif.c b/servers/slapd/back-ldif/ldif.c index e6dd8a78f9..10cf47802d 100644 --- a/servers/slapd/back-ldif/ldif.c +++ b/servers/slapd/back-ldif/ldif.c @@ -767,6 +767,9 @@ static int ldif_back_add(Operation *op, SlapReply *rs) { int statres; char textbuf[SLAP_TEXT_BUFLEN]; + slap_add_opattrs( op, &rs->sr_text, textbuf, sizeof( textbuf ), + op->o_bd->be_pcl_mutexp != NULL ? 1 : 0 ); + rs->sr_err = entry_schema_check(op, e, NULL, 0, &rs->sr_text, textbuf, sizeof( textbuf ) ); if ( rs->sr_err != LDAP_SUCCESS ) goto send_res; @@ -815,6 +818,8 @@ static int ldif_back_add(Operation *op, SlapReply *rs) { send_res: send_ldap_result(op, rs); + if ( !SLAP_SHADOW( op->o_bd )) + slap_graduate_commit_csn( op ); return 0; } @@ -825,6 +830,10 @@ static int ldif_back_modify(Operation *op, SlapReply *rs) { Entry * entry = NULL; int spew_res; + if ( !SLAP_SHADOW( op->o_bd )) + slap_mods_opattrs( op, op->orm_modlist, + op->o_bd->be_pcl_mutexp != NULL ? 1 : 0 ); + ldap_pvt_thread_mutex_lock(&ni->li_mutex); dn2path(&op->o_req_ndn, &op->o_bd->be_nsuffix[0], &ni->li_base_path, &path); @@ -853,6 +862,8 @@ static int ldif_back_modify(Operation *op, SlapReply *rs) { rs->sr_text = NULL; ldap_pvt_thread_mutex_unlock(&ni->li_mutex); send_ldap_result(op, rs); + if ( !SLAP_SHADOW( op->o_bd )) + slap_graduate_commit_csn( op ); return 0; } @@ -861,6 +872,15 @@ static int ldif_back_delete(Operation *op, SlapReply *rs) { struct berval path = BER_BVNULL; int res = 0; + if ( !SLAP_SHADOW( op->o_bd )) { + struct berval csn; + char csnbuf[LDAP_LUTIL_CSNSTR_BUFSIZE]; + + csn.bv_val = csnbuf; + csn.bv_len = sizeof( csnbuf ); + slap_get_csn( op, &csn, 1 ); + } + ldap_pvt_thread_mutex_lock(&ni->li_mutex); dn2path(&op->o_req_ndn, &op->o_bd->be_nsuffix[0], &ni->li_base_path, &path); @@ -885,6 +905,8 @@ static int ldif_back_delete(Operation *op, SlapReply *rs) { SLAP_FREE(path.bv_val); ldap_pvt_thread_mutex_unlock(&ni->li_mutex); send_ldap_result(op, rs); + if ( !SLAP_SHADOW( op->o_bd )) + slap_graduate_commit_csn( op ); return 0; } diff --git a/servers/slapd/back-meta/bind.c b/servers/slapd/back-meta/bind.c index 2106a2d7e5..3d59cf27d4 100644 --- a/servers/slapd/back-meta/bind.c +++ b/servers/slapd/back-meta/bind.c @@ -80,7 +80,7 @@ meta_back_bind( Operation *op, SlapReply *rs ) if ( META_BACK_DEFER_ROOTDN_BIND( mi ) ) { rs->sr_err = LDAP_SUCCESS; rs->sr_text = NULL; - send_ldap_result( op, rs ); + /* frontend will return success */ return rs->sr_err; } @@ -184,10 +184,8 @@ meta_back_bind( Operation *op, SlapReply *rs ) rs->sr_err = lerr; candidates[ i ].sr_tag = META_NOT_CANDIDATE; - if ( META_BACK_ONERR_STOP( mi ) ) { - rc = rs->sr_err; - break; - } + rc = rs->sr_err; + break; } } @@ -382,8 +380,7 @@ retry:; if ( rs->sr_err == LDAP_UNAVAILABLE && nretries != META_RETRY_NEVER ) { ldap_pvt_thread_mutex_lock( &mi->mi_conn_mutex ); if ( mc->mc_refcnt == 1 ) { - ldap_unbind_ext_s( msc->msc_ld, NULL, NULL ); - msc->msc_ld = NULL; + meta_clear_one_candidate( msc ); LDAP_BACK_CONN_ISBOUND_CLEAR( msc ); ( void )rewrite_session_delete( mt->mt_rwmap.rwm_rw, op->o_conn ); @@ -560,8 +557,7 @@ retry:; } if ( mc->mc_refcnt == 1 ) { - ldap_unbind_ext_s( msc->msc_ld, NULL, NULL ); - msc->msc_ld = NULL; + meta_clear_one_candidate( msc ); LDAP_BACK_CONN_ISBOUND_CLEAR( msc ); ( void )rewrite_session_delete( mt->mt_rwmap.rwm_rw, op->o_conn ); diff --git a/servers/slapd/back-meta/candidates.c b/servers/slapd/back-meta/candidates.c index 1254a26184..1cc8d83a87 100644 --- a/servers/slapd/back-meta/candidates.c +++ b/servers/slapd/back-meta/candidates.c @@ -178,18 +178,18 @@ meta_clear_one_candidate( metasingleconn_t *msc ) { if ( msc->msc_ld ) { - ldap_unbind_ext_s( msc->msc_ld, NULL, NULL ); + ldap_unbind_ext( msc->msc_ld, NULL, NULL ); msc->msc_ld = NULL; } if ( !BER_BVISNULL( &msc->msc_bound_ndn ) ) { - ber_memfree( msc->msc_bound_ndn.bv_val ); + ber_memfree_x( msc->msc_bound_ndn.bv_val, NULL ); BER_BVZERO( &msc->msc_bound_ndn ); } if ( !BER_BVISNULL( &msc->msc_cred ) ) { memset( msc->msc_cred.bv_val, 0, msc->msc_cred.bv_len ); - ber_memfree( msc->msc_cred.bv_val ); + ber_memfree_x( msc->msc_cred.bv_val, NULL ); BER_BVZERO( &msc->msc_cred ); } diff --git a/servers/slapd/back-meta/config.c b/servers/slapd/back-meta/config.c index aeba81e1db..078d2ee0c6 100644 --- a/servers/slapd/back-meta/config.c +++ b/servers/slapd/back-meta/config.c @@ -113,10 +113,21 @@ meta_back_db_config( int rc; int c; - if ( argc != 2 ) { + switch ( argc ) { + case 1: fprintf( stderr, - "%s: line %d: missing address" - " in \"uri ://[:port]/\" line\n", + "%s: line %d: missing URI " + "in \"uri ://[:port]/\" line\n", + fname, lineno ); + return 1; + + case 2: + break; + + default: + fprintf( stderr, + "%s: line %d: too many args " + "in \"uri ://[:port]/\" line\n", fname, lineno ); return 1; } @@ -928,17 +939,17 @@ ldap_back_map_config( fname, lineno ); return 1; } - ber_str2bv( src, 0, 1, &mapping->src ); - ber_str2bv( dst, 0, 1, &mapping->dst ); - mapping[ 1 ].src = mapping->dst; - mapping[ 1 ].dst = mapping->src; + ber_str2bv( src, 0, 1, &mapping[ 0 ].src ); + ber_str2bv( dst, 0, 1, &mapping[ 0 ].dst ); + mapping[ 1 ].src = mapping[ 0 ].dst; + mapping[ 1 ].dst = mapping[ 0 ].src; /* * schema check */ if ( is_oc ) { if ( src[ 0 ] != '\0' ) { - if ( oc_bvfind( &mapping->src ) == NULL ) { + if ( oc_bvfind( &mapping[ 0 ].src ) == NULL ) { fprintf( stderr, "%s: line %d: warning, source objectClass '%s' " "should be defined in schema\n", @@ -951,7 +962,7 @@ ldap_back_map_config( } } - if ( oc_bvfind( &mapping->dst ) == NULL ) { + if ( oc_bvfind( &mapping[ 0 ].dst ) == NULL ) { fprintf( stderr, "%s: line %d: warning, destination objectClass '%s' " "is not defined in schema\n", @@ -963,7 +974,7 @@ ldap_back_map_config( AttributeDescription *ad = NULL; if ( src[ 0 ] != '\0' ) { - rc = slap_bv2ad( &mapping->src, &ad, &text ); + rc = slap_bv2ad( &mapping[ 0 ].src, &ad, &text ); if ( rc != LDAP_SUCCESS ) { fprintf( stderr, "%s: line %d: warning, source attributeType '%s' " @@ -978,7 +989,7 @@ ldap_back_map_config( * and add it here. */ - rc = slap_bv2undef_ad( &mapping->src, + rc = slap_bv2undef_ad( &mapping[ 0 ].src, &ad, &text, SLAP_AD_PROXIED ); if ( rc != LDAP_SUCCESS ) { fprintf( stderr, @@ -992,7 +1003,7 @@ ldap_back_map_config( ad = NULL; } - rc = slap_bv2ad( &mapping->dst, &ad, &text ); + rc = slap_bv2ad( &mapping[ 0 ].dst, &ad, &text ); if ( rc != LDAP_SUCCESS ) { fprintf( stderr, "%s: line %d: warning, destination attributeType '%s' " @@ -1004,7 +1015,7 @@ ldap_back_map_config( * and add it here. */ - rc = slap_bv2undef_ad( &mapping->dst, + rc = slap_bv2undef_ad( &mapping[ 0 ].dst, &ad, &text, SLAP_AD_PROXIED ); if ( rc != LDAP_SUCCESS ) { fprintf( stderr, @@ -1016,7 +1027,7 @@ ldap_back_map_config( } } - if ( (src[ 0 ] != '\0' && avl_find( map->map, (caddr_t)mapping, mapping_cmp ) != NULL) + if ( (src[ 0 ] != '\0' && avl_find( map->map, (caddr_t)&mapping[ 0 ], mapping_cmp ) != NULL) || avl_find( map->remap, (caddr_t)&mapping[ 1 ], mapping_cmp ) != NULL) { fprintf( stderr, @@ -1026,7 +1037,7 @@ ldap_back_map_config( } if ( src[ 0 ] != '\0' ) { - avl_insert( &map->map, (caddr_t)mapping, + avl_insert( &map->map, (caddr_t)&mapping[ 0 ], mapping_cmp, mapping_dup ); } avl_insert( &map->remap, (caddr_t)&mapping[ 1 ], @@ -1036,8 +1047,8 @@ ldap_back_map_config( error_return:; if ( mapping ) { - ch_free( mapping->src.bv_val ); - ch_free( mapping->dst.bv_val ); + ch_free( mapping[ 0 ].src.bv_val ); + ch_free( mapping[ 0 ].dst.bv_val ); ch_free( mapping ); } diff --git a/servers/slapd/back-meta/conn.c b/servers/slapd/back-meta/conn.c index 9254407e45..8c341899d7 100644 --- a/servers/slapd/back-meta/conn.c +++ b/servers/slapd/back-meta/conn.c @@ -447,8 +447,7 @@ retry_lock:; goto retry_lock; } - ldap_unbind_ext_s( msc->msc_ld, NULL, NULL ); - msc->msc_ld = NULL; + meta_clear_one_candidate( msc ); LDAP_BACK_CONN_ISBOUND_CLEAR( msc ); ( void )rewrite_session_delete( mt->mt_rwmap.rwm_rw, op->o_conn ); diff --git a/servers/slapd/back-meta/init.c b/servers/slapd/back-meta/init.c index 3f71a429f2..a978646f1f 100644 --- a/servers/slapd/back-meta/init.c +++ b/servers/slapd/back-meta/init.c @@ -146,21 +146,7 @@ meta_back_conn_free( ntargets = mc->mc_conns[ 0 ].msc_info->mi_ntargets; for ( i = 0; i < ntargets; i++ ) { - metasingleconn_t *msc = &mc->mc_conns[ i ]; - - if ( msc->msc_ld != NULL ) { - ldap_unbind_ext_s( msc->msc_ld, NULL, NULL ); - } - - if ( !BER_BVISNULL( &msc->msc_bound_ndn ) ) { - ber_memfree( msc->msc_bound_ndn.bv_val ); - } - - if ( !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 ); - } + (void)meta_clear_one_candidate( &mc->mc_conns[ i ] ); } ldap_pvt_thread_mutex_destroy( &mc->mc_mutex ); @@ -177,6 +163,17 @@ mapping_free( ch_free( mapping ); } +static void +mapping_dst_free( + void *v_mapping ) +{ + struct ldapmapping *mapping = v_mapping; + + if ( BER_BVISEMPTY( &mapping->dst ) ) { + mapping_free( &mapping[ -1 ] ); + } +} + static void target_free( metatarget_t *mt ) @@ -205,9 +202,9 @@ target_free( if ( mt->mt_rwmap.rwm_rw ) { rewrite_info_delete( &mt->mt_rwmap.rwm_rw ); } - avl_free( mt->mt_rwmap.rwm_oc.remap, NULL ); + avl_free( mt->mt_rwmap.rwm_oc.remap, mapping_dst_free ); avl_free( mt->mt_rwmap.rwm_oc.map, mapping_free ); - avl_free( mt->mt_rwmap.rwm_at.remap, NULL ); + avl_free( mt->mt_rwmap.rwm_at.remap, mapping_dst_free ); avl_free( mt->mt_rwmap.rwm_at.map, mapping_free ); } @@ -235,11 +232,13 @@ meta_back_db_destroy( * Destroy the per-target stuff (assuming there's at * least one ...) */ - for ( i = 0; i < mi->mi_ntargets; i++ ) { - target_free( &mi->mi_targets[ i ] ); - } + if ( mi->mi_targets != NULL ) { + for ( i = 0; i < mi->mi_ntargets; i++ ) { + target_free( &mi->mi_targets[ i ] ); + } - free( mi->mi_targets ); + free( mi->mi_targets ); + } ldap_pvt_thread_mutex_lock( &mi->mi_cache.mutex ); if ( mi->mi_cache.tree ) { diff --git a/servers/slapd/back-meta/map.c b/servers/slapd/back-meta/map.c index 550c06ad13..f655e9e392 100644 --- a/servers/slapd/back-meta/map.c +++ b/servers/slapd/back-meta/map.c @@ -208,6 +208,7 @@ map_attr_value( ldap_back_map( &dc->target->mt_rwmap.rwm_at, &ad->ad_cname, mapped_attr, remap ); if ( BER_BVISNULL( mapped_attr ) || BER_BVISEMPTY( mapped_attr ) ) { +#if 0 /* * FIXME: are we sure we need to search oc_map if at_map fails? */ @@ -215,6 +216,12 @@ map_attr_value( if ( BER_BVISNULL( mapped_attr ) || BER_BVISEMPTY( mapped_attr ) ) { *mapped_attr = ad->ad_cname; } +#endif + if ( dc->target->mt_rwmap.rwm_at.drop_missing ) { + return -1; + } + + *mapped_attr = ad->ad_cname; } if ( value == NULL ) { @@ -271,13 +278,28 @@ ldap_back_int_filter_map_rewrite( { int i; Filter *p; - struct berval atmp; - struct berval vtmp; + struct berval atmp, + vtmp, + *tmp; + static struct berval + /* better than nothing... */ + ber_bvfalse = BER_BVC( "(!(objectClass=*))" ), + ber_bvtf_false = BER_BVC( "(|)" ), + /* better than nothing... */ + ber_bvtrue = BER_BVC( "(objectClass=*)" ), + ber_bvtf_true = BER_BVC( "(&)" ), +#if 0 + /* no longer needed; preserved for completeness */ + ber_bvundefined = BER_BVC( "(?=undefined)" ), +#endif + ber_bverror = BER_BVC( "(?=error)" ), + ber_bvunknown = BER_BVC( "(?=unknown)" ), + ber_bvnone = BER_BVC( "(?=none)" ); ber_len_t len; if ( f == NULL ) { - ber_str2bv( "No filter!", STRLENOF( "No filter!" ), 1, fstr ); - return -1; + ber_dupbv( fstr, &ber_bvnone ); + return LDAP_OTHER; } switch ( f->f_choice ) { @@ -285,7 +307,7 @@ ldap_back_int_filter_map_rewrite( if ( map_attr_value( dc, f->f_av_desc, &atmp, &f->f_av_value, &vtmp, remap ) ) { - return -1; + goto computed; } fstr->bv_len = atmp.bv_len + vtmp.bv_len @@ -302,7 +324,7 @@ ldap_back_int_filter_map_rewrite( if ( map_attr_value( dc, f->f_av_desc, &atmp, &f->f_av_value, &vtmp, remap ) ) { - return -1; + goto computed; } fstr->bv_len = atmp.bv_len + vtmp.bv_len @@ -319,7 +341,7 @@ ldap_back_int_filter_map_rewrite( if ( map_attr_value( dc, f->f_av_desc, &atmp, &f->f_av_value, &vtmp, remap ) ) { - return -1; + goto computed; } fstr->bv_len = atmp.bv_len + vtmp.bv_len @@ -336,7 +358,7 @@ ldap_back_int_filter_map_rewrite( if ( map_attr_value( dc, f->f_av_desc, &atmp, &f->f_av_value, &vtmp, remap ) ) { - return -1; + goto computed; } fstr->bv_len = atmp.bv_len + vtmp.bv_len @@ -353,7 +375,7 @@ ldap_back_int_filter_map_rewrite( if ( map_attr_value( dc, f->f_sub_desc, &atmp, NULL, NULL, remap ) ) { - return -1; + goto computed; } /* cannot be a DN ... */ @@ -415,7 +437,7 @@ ldap_back_int_filter_map_rewrite( if ( map_attr_value( dc, f->f_desc, &atmp, NULL, NULL, remap ) ) { - return -1; + goto computed; } fstr->bv_len = atmp.bv_len + ( STRLENOF( "(=*)" ) ); @@ -436,11 +458,13 @@ ldap_back_int_filter_map_rewrite( f->f_choice == LDAP_FILTER_OR ? '|' : '!' ); for ( p = f->f_list; p != NULL; p = p->f_next ) { + int rc; + len = fstr->bv_len; - if ( ldap_back_int_filter_map_rewrite( dc, p, &vtmp, remap ) ) - { - return -1; + rc = ldap_back_int_filter_map_rewrite( dc, p, &vtmp, remap ); + if ( rc != LDAP_SUCCESS ) { + return rc; } fstr->bv_len += vtmp.bv_len; @@ -459,7 +483,7 @@ ldap_back_int_filter_map_rewrite( if ( map_attr_value( dc, f->f_mr_desc, &atmp, &f->f_mr_value, &vtmp, remap ) ) { - return -1; + goto computed; } } else { @@ -483,43 +507,38 @@ ldap_back_int_filter_map_rewrite( ber_memfree( vtmp.bv_val ); break; - case SLAPD_FILTER_COMPUTED: { - struct berval bv; - + case SLAPD_FILTER_COMPUTED: switch ( f->f_result ) { case LDAP_COMPARE_FALSE: + /* FIXME: treat UNDEFINED as FALSE */ + case SLAPD_COMPARE_UNDEFINED: +computed:; if ( dc->target->mt_flags & LDAP_BACK_F_SUPPORT_T_F ) { - BER_BVSTR( &bv, "(|)" ); + tmp = &ber_bvtf_false; break; } - /* fallthru */ - - /* FIXME: treat UNDEFINED as FALSE */ - case SLAPD_COMPARE_UNDEFINED: - /* better than nothing... */ - BER_BVSTR( &bv, "(!(objectClass=*))" ); + tmp = &ber_bvfalse; break; case LDAP_COMPARE_TRUE: if ( dc->target->mt_flags & LDAP_BACK_F_SUPPORT_T_F ) { - BER_BVSTR( &bv, "(&)" ); + tmp = &ber_bvtf_true; break; } - /* better than nothing... */ - BER_BVSTR( &bv, "(objectClass=*)" ); + tmp = &ber_bvtrue; break; default: - BER_BVSTR( &bv, "(?=error)" ); + tmp = &ber_bverror; break; } - ber_dupbv( fstr, &bv ); - } break; + ber_dupbv( fstr, tmp ); + break; default: - ber_str2bv( "(?=unknown)", STRLENOF( "(?=unknown)" ), 1, fstr ); + ber_dupbv( fstr, &ber_bvunknown ); break; } @@ -655,6 +674,7 @@ ldap_back_referral_result_rewrite( ludp->lud_dn = dn.bv_val; newurl = ldap_url_desc2str( ludp ); + free( dn.bv_val ); if ( newurl == NULL ) { /* FIXME: leave attr untouched * even if ldap_url_desc2str failed... diff --git a/servers/slapd/back-meta/search.c b/servers/slapd/back-meta/search.c index 544bf6e31f..ccd058c2a4 100644 --- a/servers/slapd/back-meta/search.c +++ b/servers/slapd/back-meta/search.c @@ -926,15 +926,13 @@ meta_send_entry( 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] */ ); continue; } - attr = ( Attribute * )ch_malloc( sizeof( Attribute ) ); + attr = ( Attribute * )ch_calloc( 1, sizeof( Attribute ) ); if ( attr == NULL ) { continue; } - attr->a_flags = 0; - attr->a_next = 0; - attr->a_desc = NULL; if ( slap_bv2ad( &mapped, &attr->a_desc, &text ) != LDAP_SUCCESS) { if ( slap_bv2undef_ad( &mapped, &attr->a_desc, &text, @@ -990,7 +988,6 @@ meta_send_entry( pretty = attr->a_desc->ad_type->sat_syntax->ssyn_pretty; if ( !validate && !pretty ) { - attr->a_nvals = NULL; attr_free( attr ); goto next_attr; } @@ -1029,16 +1026,18 @@ meta_send_entry( * ACLs to the target directory server, and letting * everything pass thru the ldap backend. */ - } else if ( attr->a_desc->ad_type->sat_syntax == + } else { + int i; + + if ( attr->a_desc->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName ) - { - ldap_dnattr_result_rewrite( &dc, attr->a_vals ); + { + ldap_dnattr_result_rewrite( &dc, attr->a_vals ); - } else if ( attr->a_desc == slap_schema.si_ad_ref ) { - ldap_back_referral_result_rewrite( &dc, attr->a_vals ); + } else if ( attr->a_desc == slap_schema.si_ad_ref ) { + ldap_back_referral_result_rewrite( &dc, attr->a_vals ); - } else { - int i; + } for ( i = 0; i < last; i++ ) { struct berval pval; diff --git a/servers/slapd/back-meta/unbind.c b/servers/slapd/back-meta/unbind.c index ed4bc96e30..a38bfa2b07 100644 --- a/servers/slapd/back-meta/unbind.c +++ b/servers/slapd/back-meta/unbind.c @@ -48,6 +48,7 @@ meta_back_conn_destroy( conn->c_connid, 0, 0 ); mc_curr.mc_conn = conn; + mc_curr.mc_local_ndn = conn->c_ndn; ldap_pvt_thread_mutex_lock( &mi->mi_conn_mutex ); mc = avl_delete( &mi->mi_conntree, ( caddr_t )&mc_curr, @@ -61,12 +62,6 @@ meta_back_conn_destroy( assert( mc->mc_refcnt == 0 ); - for ( i = 0; i < mi->mi_ntargets; ++i ) { - if ( mc->mc_conns[ i ].msc_ld != NULL ) { - meta_clear_one_candidate( &mc->mc_conns[ i ] ); - } - } - meta_back_conn_free( mc ); } diff --git a/servers/slapd/back-monitor/init.c b/servers/slapd/back-monitor/init.c index 50cb2b44c1..a13056cdf6 100644 --- a/servers/slapd/back-monitor/init.c +++ b/servers/slapd/back-monitor/init.c @@ -1855,6 +1855,14 @@ monitor_back_db_destroy( if ( !BER_BVISNULL( &monitor_subsys[ i ]->mss_rdn ) ) { ch_free( monitor_subsys[ i ]->mss_rdn.bv_val ); } + + if ( !BER_BVISNULL( &monitor_subsys[ i ]->mss_dn ) ) { + ch_free( monitor_subsys[ i ]->mss_dn.bv_val ); + } + + if ( !BER_BVISNULL( &monitor_subsys[ i ]->mss_ndn ) ) { + ch_free( monitor_subsys[ i ]->mss_ndn.bv_val ); + } } ch_free( monitor_subsys ); diff --git a/servers/slapd/back-monitor/log.c b/servers/slapd/back-monitor/log.c index 6a390891d4..ac9294906b 100644 --- a/servers/slapd/back-monitor/log.c +++ b/servers/slapd/back-monitor/log.c @@ -31,8 +31,8 @@ #include "ldif.h" #include "back-monitor.h" -static int -monitor_subsys_log_destroy( +static int +monitor_subsys_log_open( BackendDB *be, monitor_subsys_t *ms ); @@ -47,34 +47,9 @@ monitor_subsys_log_modify( */ ldap_pvt_thread_mutex_t monitor_log_mutex; -static struct { - int i; - struct berval s; - struct berval n; -} int_2_level[] = { - { LDAP_DEBUG_TRACE, BER_BVC("Trace"), BER_BVNULL }, - { LDAP_DEBUG_PACKETS, BER_BVC("Packets"), BER_BVNULL }, - { LDAP_DEBUG_ARGS, BER_BVC("Args"), BER_BVNULL }, - { LDAP_DEBUG_CONNS, BER_BVC("Conns"), BER_BVNULL }, - { LDAP_DEBUG_BER, BER_BVC("BER"), BER_BVNULL }, - { LDAP_DEBUG_FILTER, BER_BVC("Filter"), BER_BVNULL }, - { LDAP_DEBUG_CONFIG, BER_BVC("Config"), BER_BVNULL }, /* useless */ - { LDAP_DEBUG_ACL, BER_BVC("ACL"), BER_BVNULL }, - { LDAP_DEBUG_STATS, BER_BVC("Stats"), BER_BVNULL }, - { LDAP_DEBUG_STATS2, BER_BVC("Stats2"), BER_BVNULL }, - { LDAP_DEBUG_SHELL, BER_BVC("Shell"), BER_BVNULL }, - { LDAP_DEBUG_PARSE, BER_BVC("Parse"), BER_BVNULL }, - { LDAP_DEBUG_CACHE, BER_BVC("Cache"), BER_BVNULL }, - { LDAP_DEBUG_INDEX, BER_BVC("Index"), BER_BVNULL }, - { 0, BER_BVNULL, BER_BVNULL } -}; - -static int loglevel2int( struct berval *l ); -static int int2loglevel( int n ); - -static int add_values( Entry *e, Modification *mod, int *newlevel ); -static int delete_values( Entry *e, Modification *mod, int *newlevel ); -static int replace_values( Entry *e, Modification *mod, int *newlevel ); +static int add_values( Operation *op, Entry *e, Modification *mod, int *newlevel ); +static int delete_values( Operation *op, Entry *e, Modification *mod, int *newlevel ); +static int replace_values( Operation *op, Entry *e, Modification *mod, int *newlevel ); /* * initializes log subentry @@ -84,68 +59,46 @@ monitor_subsys_log_init( BackendDB *be, monitor_subsys_t *ms ) { - monitor_info_t *mi; - Entry *e; - int i; - - ms->mss_destroy = monitor_subsys_log_destroy; + ms->mss_open = monitor_subsys_log_open; ms->mss_modify = monitor_subsys_log_modify; ldap_pvt_thread_mutex_init( &monitor_log_mutex ); - mi = ( monitor_info_t * )be->be_private; - - if ( monitor_cache_get( mi, &ms->mss_ndn, - &e ) ) { - Debug( LDAP_DEBUG_ANY, - "monitor_subsys_log_init: " - "unable to get entry \"%s\"\n", - ms->mss_ndn.bv_val, 0, 0 ); - return( -1 ); - } - - /* initialize the debug level(s) */ - for ( i = 0; int_2_level[ i ].i != 0; i++ ) { - if ( mi->mi_ad_managedInfo->ad_type->sat_equality->smr_normalize ) { - int rc; - - rc = (*mi->mi_ad_managedInfo->ad_type->sat_equality->smr_normalize)( - SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX, - mi->mi_ad_managedInfo->ad_type->sat_syntax, - mi->mi_ad_managedInfo->ad_type->sat_equality, - &int_2_level[ i ].s, - &int_2_level[ i ].n, NULL ); - if ( rc ) { - return( -1 ); - } - } - - if ( int_2_level[ i ].i & ldap_syslog ) { - attr_merge_one( e, mi->mi_ad_managedInfo, - &int_2_level[ i ].s, - &int_2_level[ i ].n ); - } - } - - monitor_cache_release( mi, e ); - return( 0 ); } -static int -monitor_subsys_log_destroy( +/* + * opens log subentry + */ +int +monitor_subsys_log_open( BackendDB *be, monitor_subsys_t *ms ) { - int i; + BerVarray bva = NULL; + + if ( loglevel2bvarray( ldap_syslog, &bva ) == 0 && bva != NULL ) { + monitor_info_t *mi; + Entry *e; - for ( i = 0; int_2_level[ i ].i != 0; i++ ) { - if ( !BER_BVISNULL( &int_2_level[ i ].n ) ) { - ch_free( int_2_level[ i ].n.bv_val ); + mi = ( monitor_info_t * )be->be_private; + + if ( monitor_cache_get( mi, &ms->mss_ndn, &e ) ) { + Debug( LDAP_DEBUG_ANY, + "monitor_subsys_log_init: " + "unable to get entry \"%s\"\n", + ms->mss_ndn.bv_val, 0, 0 ); + ber_bvarray_free( bva ); + return( -1 ); } + + attr_merge_normalize( e, mi->mi_ad_managedInfo, bva, NULL ); + ber_bvarray_free( bva ); + + monitor_cache_release( mi, e ); } - return 0; + return( 0 ); } static int @@ -176,7 +129,8 @@ monitor_subsys_log_modify( */ if ( is_at_operational( mod->sm_desc->ad_type ) ) { ( void ) attr_delete( &e->e_attrs, mod->sm_desc ); - rc = rs->sr_err = attr_merge( e, mod->sm_desc, mod->sm_values, mod->sm_nvalues ); + rc = rs->sr_err = attr_merge( e, mod->sm_desc, + mod->sm_values, mod->sm_nvalues ); if ( rc != LDAP_SUCCESS ) { break; } @@ -192,15 +146,15 @@ monitor_subsys_log_modify( switch ( mod->sm_op ) { case LDAP_MOD_ADD: - rc = add_values( e, mod, &newlevel ); + rc = add_values( op, e, mod, &newlevel ); break; case LDAP_MOD_DELETE: - rc = delete_values( e, mod, &newlevel ); + rc = delete_values( op, e, mod, &newlevel ); break; case LDAP_MOD_REPLACE: - rc = replace_values( e, mod, &newlevel ); + rc = replace_values( op, e, mod, &newlevel ); break; default: @@ -267,64 +221,31 @@ cleanup:; } static int -loglevel2int( struct berval *l ) +check_constraints( Modification *mod, int *newlevel ) { int i; - - for ( i = 0; int_2_level[ i ].i != 0; i++ ) { - if ( l->bv_len != int_2_level[ i ].s.bv_len ) { - continue; - } - - if ( strcasecmp( l->bv_val, int_2_level[ i ].s.bv_val ) == 0 ) { - return int_2_level[ i ].i; - } - } - - return 0; -} -static int -int2loglevel( int n ) -{ - int i; - - for ( i = 0; int_2_level[ i ].i != 0; i++ ) { - if ( int_2_level[ i ].i == n ) { - return i; - } + if ( mod->sm_nvalues != NULL ) { + ber_bvarray_free( mod->sm_nvalues ); + mod->sm_nvalues = NULL; } - return -1; -} - -static int -check_constraints( Modification *mod, int *newlevel ) -{ - int i; - - for ( i = 0; mod->sm_values && !BER_BVISNULL( &mod->sm_values[ i ] ); i++ ) { + for ( i = 0; !BER_BVISNULL( &mod->sm_values[ i ] ); i++ ) { int l; - - l = loglevel2int( &mod->sm_values[ i ] ); - if ( !l ) { + struct berval bv; + + if ( str2loglevel( mod->sm_values[ i ].bv_val, &l ) ) { return LDAP_CONSTRAINT_VIOLATION; } - if ( ( l = int2loglevel( l ) ) == -1 ) { - return LDAP_OTHER; + if ( loglevel2bv( l, &bv ) ) { + return LDAP_CONSTRAINT_VIOLATION; } - - assert( int_2_level[ l ].s.bv_len - == mod->sm_values[ i ].bv_len ); + + assert( bv.bv_len == mod->sm_values[ i ].bv_len ); AC_MEMCPY( mod->sm_values[ i ].bv_val, - int_2_level[ l ].s.bv_val, - int_2_level[ l ].s.bv_len ); - - AC_MEMCPY( mod->sm_nvalues[ i ].bv_val, - int_2_level[ l ].n.bv_val, - int_2_level[ l ].n.bv_len ); + bv.bv_val, bv.bv_len ); *newlevel |= l; } @@ -333,12 +254,14 @@ check_constraints( Modification *mod, int *newlevel ) } static int -add_values( Entry *e, Modification *mod, int *newlevel ) +add_values( Operation *op, Entry *e, Modification *mod, int *newlevel ) { Attribute *a; int i, rc; MatchingRule *mr = mod->sm_desc->ad_type->sat_equality; + assert( mod->sm_values != NULL ); + rc = check_constraints( mod, newlevel ); if ( rc != LDAP_SUCCESS ) { return rc; @@ -360,7 +283,8 @@ add_values( Entry *e, Modification *mod, int *newlevel ) rc = asserted_value_validate_normalize( mod->sm_desc, mr, SLAP_MR_EQUALITY, - &mod->sm_values[ i ], &asserted, &text, NULL ); + &mod->sm_values[ i ], &asserted, &text, + op->o_tmpmemctx ); if ( rc != LDAP_SUCCESS ) { return rc; @@ -369,7 +293,7 @@ add_values( Entry *e, Modification *mod, int *newlevel ) for ( j = 0; !BER_BVISNULL( &a->a_vals[ j ] ); j++ ) { int match; int rc = value_match( &match, mod->sm_desc, mr, - 0, &a->a_vals[ j ], &asserted, &text ); + 0, &a->a_nvals[ j ], &asserted, &text ); if ( rc == LDAP_SUCCESS && match == 0 ) { free( asserted.bv_val ); @@ -382,9 +306,9 @@ add_values( Entry *e, Modification *mod, int *newlevel ) } /* no - add them */ - rc = attr_merge( e, mod->sm_desc, mod->sm_values, mod->sm_nvalues ); + rc = attr_merge_normalize( e, mod->sm_desc, mod->sm_values, + op->o_tmpmemctx ); if ( rc != LDAP_SUCCESS ) { - /* this should return result of attr_mergeit */ return rc; } @@ -392,25 +316,19 @@ add_values( Entry *e, Modification *mod, int *newlevel ) } static int -delete_values( Entry *e, Modification *mod, int *newlevel ) +delete_values( Operation *op, Entry *e, Modification *mod, int *newlevel ) { int i, j, k, found, rc, nl = 0; Attribute *a; MatchingRule *mr = mod->sm_desc->ad_type->sat_equality; - rc = check_constraints( mod, &nl ); - if ( rc != LDAP_SUCCESS ) { - return rc; - } - - *newlevel &= ~nl; - /* delete the entire attribute */ if ( mod->sm_values == NULL ) { int rc = attr_delete( &e->e_attrs, mod->sm_desc ); if ( rc ) { rc = LDAP_NO_SUCH_ATTRIBUTE; + } else { *newlevel = 0; rc = LDAP_SUCCESS; @@ -418,6 +336,13 @@ delete_values( Entry *e, Modification *mod, int *newlevel ) return rc; } + rc = check_constraints( mod, &nl ); + if ( rc != LDAP_SUCCESS ) { + return rc; + } + + *newlevel &= ~nl; + if ( mr == NULL || !mr->smr_match ) { /* disallow specific attributes from being deleted if * no equality rule */ @@ -438,7 +363,8 @@ delete_values( Entry *e, Modification *mod, int *newlevel ) rc = asserted_value_validate_normalize( mod->sm_desc, mr, SLAP_MR_EQUALITY, - &mod->sm_values[ i ], &asserted, &text, NULL ); + &mod->sm_values[ i ], &asserted, &text, + op->o_tmpmemctx ); if( rc != LDAP_SUCCESS ) return rc; @@ -446,8 +372,7 @@ delete_values( Entry *e, Modification *mod, int *newlevel ) for ( j = 0; !BER_BVISNULL( &a->a_vals[ j ] ); j++ ) { int match; int rc = value_match( &match, mod->sm_desc, mr, - 0, - &a->a_vals[ j ], &asserted, &text ); + 0, &a->a_nvals[ j ], &asserted, &text ); if( rc == LDAP_SUCCESS && match != 0 ) { continue; @@ -457,6 +382,14 @@ delete_values( Entry *e, Modification *mod, int *newlevel ) found = 1; /* delete it */ + if ( a->a_nvals != a->a_vals ) { + free( a->a_nvals[ j ].bv_val ); + for ( k = j + 1; !BER_BVISNULL( &a->a_nvals[ k ] ); k++ ) { + a->a_nvals[ k - 1 ] = a->a_nvals[ k ]; + } + BER_BVZERO( &a->a_nvals[ k - 1 ] ); + } + free( a->a_vals[ j ].bv_val ); for ( k = j + 1; !BER_BVISNULL( &a->a_vals[ k ] ); k++ ) { a->a_vals[ k - 1 ] = a->a_vals[ k ]; @@ -488,14 +421,16 @@ delete_values( Entry *e, Modification *mod, int *newlevel ) } static int -replace_values( Entry *e, Modification *mod, int *newlevel ) +replace_values( Operation *op, Entry *e, Modification *mod, int *newlevel ) { int rc; - *newlevel = 0; - rc = check_constraints( mod, newlevel ); - if ( rc != LDAP_SUCCESS ) { - return rc; + if ( mod->sm_values != NULL ) { + *newlevel = 0; + rc = check_constraints( mod, newlevel ); + if ( rc != LDAP_SUCCESS ) { + return rc; + } } rc = attr_delete( &e->e_attrs, mod->sm_desc ); @@ -505,7 +440,8 @@ replace_values( Entry *e, Modification *mod, int *newlevel ) } if ( mod->sm_values != NULL ) { - rc = attr_merge( e, mod->sm_desc, mod->sm_values, mod->sm_nvalues ); + rc = attr_merge_normalize( e, mod->sm_desc, mod->sm_values, + op->o_tmpmemctx ); if ( rc != LDAP_SUCCESS ) { return rc; } diff --git a/servers/slapd/back-monitor/modify.c b/servers/slapd/back-monitor/modify.c index eafeb6e063..728975360c 100644 --- a/servers/slapd/back-monitor/modify.c +++ b/servers/slapd/back-monitor/modify.c @@ -69,6 +69,9 @@ monitor_back_modify( Operation *op, SlapReply *rs ) rc = LDAP_INSUFFICIENT_ACCESS; } else { + assert( !SLAP_SHADOW( op->o_bd ) ); + slap_mods_opattrs( op, op->orm_modlist, 0 ); + rc = monitor_entry_modify( op, rs, e ); } diff --git a/servers/slapd/back-monitor/rww.c b/servers/slapd/back-monitor/rww.c index 0edea5d079..a0e5371425 100644 --- a/servers/slapd/back-monitor/rww.c +++ b/servers/slapd/back-monitor/rww.c @@ -28,6 +28,11 @@ #include "lutil.h" #include "back-monitor.h" +static int +monitor_subsys_rww_destroy( + BackendDB *be, + monitor_subsys_t *ms ); + static int monitor_subsys_rww_update( Operation *op, @@ -41,7 +46,7 @@ enum { MONITOR_RWW_LAST }; -struct monitor_rww_t { +static struct monitor_rww_t { struct berval rdn; struct berval nrdn; } monitor_rww[] = { @@ -53,8 +58,7 @@ struct monitor_rww_t { int monitor_subsys_rww_init( BackendDB *be, - monitor_subsys_t *ms -) + monitor_subsys_t *ms ) { monitor_info_t *mi; @@ -64,6 +68,7 @@ monitor_subsys_rww_init( assert( be != NULL ); + ms->mss_destroy = monitor_subsys_rww_destroy; ms->mss_update = monitor_subsys_rww_update; mi = ( monitor_info_t * )be->be_private; @@ -147,6 +152,20 @@ monitor_subsys_rww_init( return( 0 ); } +static int +monitor_subsys_rww_destroy( + BackendDB *be, + monitor_subsys_t *ms ) +{ + int i; + + for ( i = 0; i < MONITOR_RWW_LAST; i++ ) { + ber_memfree_x( monitor_rww[ i ].nrdn.bv_val, NULL ); + } + + return 0; +} + static int monitor_subsys_rww_update( Operation *op, diff --git a/servers/slapd/back-sql/add.c b/servers/slapd/back-sql/add.c index 548bfd835e..6656b774f3 100644 --- a/servers/slapd/back-sql/add.c +++ b/servers/slapd/back-sql/add.c @@ -936,9 +936,11 @@ backsql_add( Operation *op, SlapReply *rs ) */ if ( op->o_sync ) { char buf[ LDAP_LUTIL_CSNSTR_BUFSIZE ]; - struct berval csn = BER_BVNULL; + struct berval csn; - slap_get_csn( op, buf, sizeof( buf ), &csn, 1 ); + csn.bv_val = buf; + csn.bv_len = sizeof( buf ); + slap_get_csn( op, &csn, 1 ); rs->sr_err = LDAP_SUCCESS; send_ldap_result( op, rs ); diff --git a/servers/slapd/back-sql/modrdn.c b/servers/slapd/back-sql/modrdn.c index 306e557d02..a6aca06c96 100644 --- a/servers/slapd/back-sql/modrdn.c +++ b/servers/slapd/back-sql/modrdn.c @@ -438,6 +438,7 @@ backsql_modrdn( Operation *op, SlapReply *rs ) oc = backsql_id2oc( bi, e_id.eid_oc_id ); rs->sr_err = backsql_modify_internal( op, rs, dbh, oc, &e_id, mod ); + slap_graduate_commit_csn( op ); if ( rs->sr_err != LDAP_SUCCESS ) { e = &r; goto done; diff --git a/servers/slapd/back-sql/operational.c b/servers/slapd/back-sql/operational.c index 6edde629ca..1423e2156a 100644 --- a/servers/slapd/back-sql/operational.c +++ b/servers/slapd/back-sql/operational.c @@ -91,7 +91,9 @@ backsql_operational_entryCSN( Operation *op ) } else #endif /* BACKSQL_SYNCPROV */ { - slap_get_csn( op, csnbuf, sizeof(csnbuf), &entryCSN, 0 ); + entryCSN.bv_val = csnbuf; + entryCSN.bv_len = sizeof( csnbuf ); + slap_get_csn( op, &entryCSN, 0 ); } ber_dupbv( &a->a_vals[ 0 ], &entryCSN ); diff --git a/servers/slapd/backglue.c b/servers/slapd/backglue.c index bc17618b36..777a7272c5 100644 --- a/servers/slapd/backglue.c +++ b/servers/slapd/backglue.c @@ -369,7 +369,7 @@ glue_op_search ( Operation *op, SlapReply *rs ) case LDAP_ADMINLIMIT_EXCEEDED: case LDAP_NO_SUCH_OBJECT: #ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR - case LDAP_CANNOT_CHAIN: + case LDAP_X_CANNOT_CHAIN: #endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */ goto end_of_loop; diff --git a/servers/slapd/bconfig.c b/servers/slapd/bconfig.c index 3dd6cfc0cc..634e3ff962 100644 --- a/servers/slapd/bconfig.c +++ b/servers/slapd/bconfig.c @@ -40,7 +40,7 @@ static struct berval config_rdn = BER_BVC("cn=config"); static struct berval schema_rdn = BER_BVC("cn=schema"); -#define IFMT "{%d}" +#define SLAP_X_ORDERED_FMT "{%d}" #ifdef SLAPD_MODULES typedef struct modpath_s { @@ -136,6 +136,7 @@ enum { CFG_TLS_CERT_KEY, CFG_TLS_CA_PATH, CFG_TLS_CA_FILE, + CFG_TLS_DH_FILE, CFG_TLS_VERIFY, CFG_TLS_CRLCHECK, CFG_CONCUR, @@ -162,6 +163,7 @@ enum { CFG_SASLSECP, CFG_SSTR_IF_MAX, CFG_SSTR_IF_MIN, + CFG_TTHREADS, CFG_LAST }; @@ -561,6 +563,17 @@ static ConfigTable config_back_cf_table[] = { #endif "( OLcfgGlAt:75 NAME 'olcTLSVerifyClient' " "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL }, + { "TLSDHParamFile", NULL, 0, 0, 0, +#ifdef HAVE_TLS + CFG_TLS_DH_FILE|ARG_STRING|ARG_MAGIC, &config_tls_option, +#else + ARG_IGNORED, NULL, +#endif + "( OLcfgGlAt:77 NAME 'olcTLSDHParamFile' " + "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL }, + { "tool-threads", "count", 2, 2, 0, ARG_INT|ARG_MAGIC|CFG_TTHREADS, + &config_generic, "( OLcfgGlAt:80 NAME 'olcToolThreads' " + "SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL }, { "ucdata-path", "path", 2, 2, 0, ARG_IGNORED, NULL, NULL, NULL, NULL }, { "updatedn", "dn", 2, 2, 0, ARG_DB|ARG_DN|ARG_QUOTE|ARG_MAGIC, @@ -618,7 +631,8 @@ static ConfigOCs cf_ocs[] = { "olcThreads $ olcTimeLimit $ olcTLSCACertificateFile $ " "olcTLSCACertificatePath $ olcTLSCertificateFile $ " "olcTLSCertificateKeyFile $ olcTLSCipherSuite $ olcTLSCRLCheck $ " - "olcTLSRandFile $ olcTLSVerifyClient $ " + "olcTLSRandFile $ olcTLSVerifyClient $ olcTLSDHParamFile $ " + "olcToolThreads $ " "olcObjectIdentifier $ olcAttributeTypes $ olcObjectClasses $ " "olcDitContentRules ) )", Cft_Global }, { "( OLcfgGlOc:2 " @@ -691,6 +705,9 @@ config_generic(ConfigArgs *c) { case CFG_THREADS: c->value_int = connection_pool_max; break; + case CFG_TTHREADS: + c->value_int = slap_tool_thread_max; + break; case CFG_SALT: if ( passwd_salt ) c->value_string = ch_strdup( passwd_salt ); @@ -704,8 +721,14 @@ config_generic(ConfigArgs *c) { int i; for ( i=0; c->be->be_limits[i]; i++ ) { - bv.bv_len = sprintf( buf, IFMT, i ); - bv.bv_val = buf+bv.bv_len; + bv.bv_len = snprintf( buf, sizeof( buf ), SLAP_X_ORDERED_FMT, i ); + if ( bv.bv_len >= sizeof( buf ) ) { + ber_bvarray_free_x( c->rvalue_vals, NULL ); + c->rvalue_vals = NULL; + rc = 1; + break; + } + bv.bv_val = buf + bv.bv_len; limits_unparse( c->be->be_limits[i], &bv ); bv.bv_len += bv.bv_val - buf; bv.bv_val = buf; @@ -790,7 +813,13 @@ config_generic(ConfigArgs *c) { char *src, *dst, ibuf[11]; struct berval bv, abv; for (i=0, a=c->be->be_acl; a; i++,a=a->acl_next) { - abv.bv_len = sprintf( ibuf, IFMT, i ); + abv.bv_len = snprintf( ibuf, sizeof( ibuf ), SLAP_X_ORDERED_FMT, i ); + if ( abv.bv_len >= sizeof( ibuf ) ) { + ber_bvarray_free_x( c->rvalue_vals, NULL ); + c->rvalue_vals = NULL; + i = 0; + break; + } acl_unparse( a, &bv ); abv.bv_val = ch_malloc( abv.bv_len + bv.bv_len + 1 ); AC_MEMCPY( abv.bv_val, ibuf, abv.bv_len ); @@ -846,8 +875,14 @@ config_generic(ConfigArgs *c) { for (i=0; !BER_BVISNULL(&mp->mp_loads[i]); i++) { struct berval bv; bv.bv_val = c->log; - bv.bv_len = sprintf( bv.bv_val, IFMT "%s", i, + bv.bv_len = snprintf( bv.bv_val, sizeof( c->log ), + SLAP_X_ORDERED_FMT "%s", i, mp->mp_loads[i].bv_val ); + if ( bv.bv_len >= sizeof( c->log ) ) { + ber_bvarray_free_x( c->rvalue_vals, NULL ); + c->rvalue_vals = NULL; + break; + } value_add_one( &c->rvalue_vals, &bv ); } } @@ -879,11 +914,18 @@ config_generic(ConfigArgs *c) { idx.bv_val = ibuf; for ( i=0; !BER_BVISNULL( &authz_rewrites[i] ); i++ ) { - idx.bv_len = sprintf( idx.bv_val, IFMT, i ); + idx.bv_len = snprintf( idx.bv_val, sizeof( ibuf ), SLAP_X_ORDERED_FMT, i ); + if ( idx.bv_len >= sizeof( ibuf ) ) { + ber_bvarray_free_x( c->rvalue_vals, NULL ); + c->rvalue_vals = NULL; + break; + } bv.bv_len = idx.bv_len + authz_rewrites[i].bv_len; bv.bv_val = ch_malloc( bv.bv_len + 1 ); - strcpy( bv.bv_val, idx.bv_val ); - strcpy( bv.bv_val+idx.bv_len, authz_rewrites[i].bv_val ); + AC_MEMCPY( bv.bv_val, idx.bv_val, idx.bv_len ); + AC_MEMCPY( &bv.bv_val[ idx.bv_len ], + authz_rewrites[i].bv_val, + authz_rewrites[i].bv_len + 1 ); ber_bvarray_add( &c->rvalue_vals, &bv ); } } @@ -900,6 +942,7 @@ config_generic(ConfigArgs *c) { /* single-valued attrs, no-ops */ case CFG_CONCUR: case CFG_THREADS: + case CFG_TTHREADS: case CFG_RO: case CFG_AZPOLICY: case CFG_DEPTH: @@ -914,7 +957,7 @@ config_generic(ConfigArgs *c) { case CFG_MODLOAD: case CFG_AZREGEXP: case CFG_REWRITE: - sprintf(c->log, "change requires slapd restart"); + snprintf(c->log, sizeof( c->log ), "change requires slapd restart"); break; case CFG_SALT: @@ -940,6 +983,8 @@ config_generic(ConfigArgs *c) { else end = frontendDB->be_acl; acl_destroy( c->be->be_acl, end ); + c->be->be_acl = end; + } else { AccessControl **prev, *a; int i; @@ -978,7 +1023,7 @@ config_generic(ConfigArgs *c) { switch(c->type) { case CFG_BACKEND: if(!(c->bi = backend_info(c->argv[1]))) { - sprintf( c->msg, "<%s> failed init", c->argv[0] ); + snprintf( c->msg, sizeof( c->msg ), "<%s> failed init", c->argv[0] ); Debug(LDAP_DEBUG_ANY, "%s: %s (%s)!\n", c->log, c->msg, c->argv[1] ); return(1); @@ -996,7 +1041,7 @@ config_generic(ConfigArgs *c) { } else { c->be = backend_db_init(c->argv[1]); if ( !c->be ) { - sprintf( c->msg, "<%s> failed init", c->argv[0] ); + snprintf( c->msg, sizeof( c->msg ), "<%s> failed init", c->argv[0] ); Debug(LDAP_DEBUG_ANY, "%s: %s (%s)!\n", c->log, c->msg, c->argv[1] ); return(1); @@ -1013,6 +1058,11 @@ config_generic(ConfigArgs *c) { connection_pool_max = c->value_int; /* save for reference */ break; + case CFG_TTHREADS: + ldap_pvt_thread_pool_maxthreads(&connection_pool, c->value_int); + slap_tool_thread_max = c->value_int; /* save for reference */ + break; + case CFG_SALT: if ( passwd_salt ) ch_free( passwd_salt ); passwd_salt = c->value_string; @@ -1034,7 +1084,7 @@ config_generic(ConfigArgs *c) { case CFG_AZPOLICY: ch_free(c->value_string); if (slap_sasl_setpolicy( c->argv[1] )) { - sprintf( c->msg, "<%s> unable to parse value", c->argv[0] ); + snprintf( c->msg, sizeof( c->msg ), "<%s> unable to parse value", c->argv[0] ); Debug(LDAP_DEBUG_ANY, "%s: %s \"%s\"\n", c->log, c->msg, c->argv[1] ); return(1); @@ -1109,7 +1159,9 @@ config_generic(ConfigArgs *c) { break; case CFG_ACL: - parse_acl(c->be, c->fname, c->lineno, c->argc, c->argv, c->valx); + if ( parse_acl(c->be, c->fname, c->lineno, c->argc, c->argv, c->valx) ) { + return 1; + } break; case CFG_REPLOG: @@ -1126,7 +1178,7 @@ config_generic(ConfigArgs *c) { case CFG_ROOTDSE: if(read_root_dse_file(c->argv[1])) { - sprintf( c->msg, "<%s> could not read file", c->argv[0] ); + snprintf( c->msg, sizeof( c->msg ), "<%s> could not read file", c->argv[0] ); Debug(LDAP_DEBUG_ANY, "%s: %s %s\n", c->log, c->msg, c->argv[1] ); return(1); @@ -1148,7 +1200,7 @@ config_generic(ConfigArgs *c) { case CFG_LASTMOD: if(SLAP_NOLASTMODCMD(c->be)) { - sprintf( c->msg, "<%s> not available for %s database", + snprintf( c->msg, sizeof( c->msg ), "<%s> not available for %s database", c->argv[0], c->be->bd_info->bi_type ); Debug(LDAP_DEBUG_ANY, "%s: %s\n", c->log, c->msg, 0 ); @@ -1162,7 +1214,7 @@ config_generic(ConfigArgs *c) { case CFG_SSTR_IF_MAX: if (c->value_int < index_substr_if_minlen) { - sprintf( c->msg, "<%s> invalid value", c->argv[0] ); + snprintf( c->msg, sizeof( c->msg ), "<%s> invalid value", c->argv[0] ); Debug(LDAP_DEBUG_ANY, "%s: %s (%d)\n", c->log, c->msg, c->value_int ); return(1); @@ -1172,7 +1224,7 @@ config_generic(ConfigArgs *c) { case CFG_SSTR_IF_MIN: if (c->value_int > index_substr_if_maxlen) { - sprintf( c->msg, "<%s> invalid value", c->argv[0] ); + snprintf( c->msg, sizeof( c->msg ), "<%s> invalid value", c->argv[0] ); Debug(LDAP_DEBUG_ANY, "%s: %s (%d)\n", c->log, c->msg, c->value_int ); return(1); @@ -1189,7 +1241,7 @@ config_generic(ConfigArgs *c) { modcur = c->private; /* This should never fail */ if ( module_path( modcur->mp_path.bv_val )) { - sprintf( c->msg, "<%s> module path no longer valid", + snprintf( c->msg, sizeof( c->msg ), "<%s> module path no longer valid", c->argv[0] ); Debug(LDAP_DEBUG_ANY, "%s: %s (%s)\n", c->log, c->msg, modcur->mp_path.bv_val ); @@ -1379,14 +1431,14 @@ config_passwd_hash(ConfigArgs *c) { } for(i = 1; i < c->argc; i++) { if(!lutil_passwd_scheme(c->argv[i])) { - sprintf( c->msg, "<%s> scheme not available", c->argv[0] ); + snprintf( c->msg, sizeof( c->msg ), "<%s> scheme not available", c->argv[0] ); Debug(LDAP_DEBUG_ANY, "%s: %s (%s)\n", c->log, c->msg, c->argv[i]); } else { ldap_charray_add(&default_passwd_hash, c->argv[i]); } if(!default_passwd_hash) { - sprintf( c->msg, "<%s> no valid hashes found", c->argv[0] ); + snprintf( c->msg, sizeof( c->msg ), "<%s> no valid hashes found", c->argv[0] ); Debug(LDAP_DEBUG_ANY, "%s: %s\n", c->log, c->msg, 0 ); return(1); @@ -1449,7 +1501,7 @@ config_sizelimit(ConfigArgs *c) { if(!strncasecmp(c->argv[i], "size", 4)) { rc = limits_parse_one(c->argv[i], lim); if ( rc ) { - sprintf( c->msg, "<%s> unable to parse value", c->argv[0] ); + snprintf( c->msg, sizeof( c->msg ), "<%s> unable to parse value", c->argv[0] ); Debug(LDAP_DEBUG_ANY, "%s: %s \"%s\"\n", c->log, c->msg, c->argv[i]); return(1); @@ -1460,7 +1512,7 @@ config_sizelimit(ConfigArgs *c) { } else { lim->lms_s_soft = strtol(c->argv[i], &next, 0); if(next == c->argv[i]) { - sprintf( c->msg, "<%s> unable to parse limit", c->argv[0]); + snprintf( c->msg, sizeof( c->msg ), "<%s> unable to parse limit", c->argv[0]); Debug(LDAP_DEBUG_ANY, "%s: %s \"%s\"\n", c->log, c->msg, c->argv[i]); return(1); @@ -1506,7 +1558,7 @@ config_timelimit(ConfigArgs *c) { if(!strncasecmp(c->argv[i], "time", 4)) { rc = limits_parse_one(c->argv[i], lim); if ( rc ) { - sprintf( c->msg, "<%s> unable to parse value", c->argv[0] ); + snprintf( c->msg, sizeof( c->msg ), "<%s> unable to parse value", c->argv[0] ); Debug(LDAP_DEBUG_ANY, "%s: %s \"%s\"\n", c->log, c->msg, c->argv[i]); return(1); @@ -1517,7 +1569,7 @@ config_timelimit(ConfigArgs *c) { } else { lim->lms_t_soft = strtol(c->argv[i], &next, 0); if(next == c->argv[i]) { - sprintf( c->msg, "<%s> unable to parse limit", c->argv[0]); + snprintf( c->msg, sizeof( c->msg ), "<%s> unable to parse limit", c->argv[0]); Debug(LDAP_DEBUG_ANY, "%s: %s \"%s\"\n", c->log, c->msg, c->argv[i]); return(1); @@ -1681,7 +1733,7 @@ config_suffix(ConfigArgs *c) #ifdef SLAPD_MONITOR_DN if(!strcasecmp(c->argv[1], SLAPD_MONITOR_DN)) { - sprintf( c->msg, "<%s> DN is reserved for monitoring slapd", + snprintf( c->msg, sizeof( c->msg ), "<%s> DN is reserved for monitoring slapd", c->argv[0] ); Debug(LDAP_DEBUG_ANY, "%s: %s (%s)\n", c->log, c->msg, SLAPD_MONITOR_DN); @@ -1710,7 +1762,7 @@ config_suffix(ConfigArgs *c) type = oi->oi_orig->bi_type; } - sprintf( c->msg, "<%s> namingContext \"%s\" already served by " + snprintf( c->msg, sizeof( c->msg ), "<%s> namingContext \"%s\" already served by " "a preceding %s database serving namingContext", c->argv[0], pdn.bv_val, type ); Debug(LDAP_DEBUG_ANY, "%s: %s \"%s\"\n", @@ -1774,7 +1826,7 @@ config_rootpw(ConfigArgs *c) { tbe = select_backend(&c->be->be_rootndn, 0, 0); if(tbe != c->be) { - sprintf( c->msg, "<%s> can only be set when rootdn is under suffix", + snprintf( c->msg, sizeof( c->msg ), "<%s> can only be set when rootdn is under suffix", c->argv[0] ); Debug(LDAP_DEBUG_ANY, "%s: %s\n", c->log, c->msg, 0); @@ -1823,7 +1875,7 @@ config_restrict(ConfigArgs *c) { } i = verbs_to_mask( c->argc, c->argv, restrictable_ops, &restrictops ); if ( i ) { - sprintf( c->msg, "<%s> unknown operation", c->argv[0] ); + snprintf( c->msg, sizeof( c->msg ), "<%s> unknown operation", c->argv[0] ); Debug(LDAP_DEBUG_ANY, "%s: %s %s\n", c->log, c->msg, c->argv[i]); return(1); @@ -1858,7 +1910,7 @@ config_allows(ConfigArgs *c) { } i = verbs_to_mask(c->argc, c->argv, allowable_ops, &allows); if ( i ) { - sprintf( c->msg, "<%s> unknown feature", c->argv[0] ); + snprintf( c->msg, sizeof( c->msg ), "<%s> unknown feature", c->argv[0] ); Debug(LDAP_DEBUG_ANY, "%s: %s %s\n", c->log, c->msg, c->argv[i]); return(1); @@ -1892,7 +1944,7 @@ config_disallows(ConfigArgs *c) { } i = verbs_to_mask(c->argc, c->argv, disallowable_ops, &disallows); if ( i ) { - sprintf( c->msg, "<%s> unknown feature", c->argv[0] ); + snprintf( c->msg, sizeof( c->msg ), "<%s> unknown feature", c->argv[0] ); Debug(LDAP_DEBUG_ANY, "%s: %s %s\n", c->log, c->msg, c->argv[i]); return(1); @@ -1926,7 +1978,7 @@ config_requires(ConfigArgs *c) { } i = verbs_to_mask(c->argc, c->argv, requires_ops, &requires); if ( i ) { - sprintf( c->msg, "<%s> unknown feature", c->argv[0] ); + snprintf( c->msg, sizeof( c->msg ), "<%s> unknown feature", c->argv[0] ); Debug(LDAP_DEBUG_ANY, "%s: %s %s\n", c->log, c->msg, c->argv[i]); return(1); @@ -1957,7 +2009,8 @@ loglevel_init( void ) { BER_BVC("Cache"), LDAP_DEBUG_CACHE }, { BER_BVC("Index"), LDAP_DEBUG_INDEX }, { BER_BVC("Sync"), LDAP_DEBUG_SYNC }, - { BER_BVNULL, 0 } + { BER_BVC("None"), LDAP_DEBUG_NONE }, + { BER_BVNULL, 0 } }; return slap_verbmasks_init( &loglevel_ops, lo ); @@ -1993,6 +2046,43 @@ slap_loglevel_register( slap_mask_t m, struct berval *s ) return rc; } +int +slap_loglevel_get( struct berval *s, int *l ) +{ + int rc; + unsigned long i; + slap_mask_t m; + + if ( loglevel_ops == NULL ) { + loglevel_init(); + } + + for ( m = 0, i = 1; !BER_BVISNULL( &loglevel_ops[ i ].word ); i++ ) { + m |= loglevel_ops[ i ].mask; + } + + m = ~m; + + for ( i = 1; i <= ( 1 << ( sizeof( int ) * 8 - 1 ) ) && !( m & i ); i <<= 1 ) + ; + + if ( !( m & i ) ) { + return -1; + } + + rc = slap_verbmasks_append( &loglevel_ops, i, s, loglevel_ignore ); + + if ( rc != 0 ) { + Debug( LDAP_DEBUG_ANY, "slap_loglevel_register(%lu, \"%s\") failed\n", + i, s->bv_val, 0 ); + + } else { + *l = i; + } + + return rc; +} + int str2loglevel( const char *s, int *l ) { @@ -2004,7 +2094,7 @@ str2loglevel( const char *s, int *l ) i = verb_to_mask( s, loglevel_ops ); - if ( BER_BVISNULL( &loglevel_ops[ i ].word) ) { + if ( BER_BVISNULL( &loglevel_ops[ i ].word ) ) { return -1; } @@ -2013,6 +2103,38 @@ str2loglevel( const char *s, int *l ) return 0; } +const char * +loglevel2str( int l ) +{ + struct berval bv = BER_BVNULL; + + loglevel2bv( l, &bv ); + + return bv.bv_val; +} + +int +loglevel2bv( int l, struct berval *bv ) +{ + if ( loglevel_ops == NULL ) { + loglevel_init(); + } + + BER_BVZERO( bv ); + + return enum_to_verb( loglevel_ops, l, bv ) == -1; +} + +int +loglevel2bvarray( int l, BerVarray *bva ) +{ + if ( loglevel_ops == NULL ) { + loglevel_init(); + } + + return mask_to_verbs( loglevel_ops, l, bva ); +} + static int config_syslog; static int @@ -2028,7 +2150,8 @@ config_loglevel(ConfigArgs *c) { /* Get default or commandline slapd setting */ if ( ldap_syslog && !config_syslog ) config_syslog = ldap_syslog; - return mask_to_verbs( loglevel_ops, config_syslog, &c->rvalue_vals ); + return loglevel2bvarray( config_syslog, &c->rvalue_vals ); + } else if ( c->op == LDAP_MOD_DELETE ) { if ( !c->line ) { config_syslog = 0; @@ -2050,14 +2173,14 @@ config_loglevel(ConfigArgs *c) { if ( isdigit( c->argv[i][0] ) || c->argv[i][0] == '-' ) { level = strtol( c->argv[i], &next, 10 ); if ( next == NULL || next[0] != '\0' ) { - sprintf( c->msg, "<%s> unable to parse level", c->argv[0] ); + snprintf( c->msg, sizeof( c->msg ), "<%s> unable to parse level", c->argv[0] ); Debug( LDAP_DEBUG_ANY, "%s: %s \"%s\"\n", c->log, c->msg, c->argv[i]); return( 1 ); } } else { if ( str2loglevel( c->argv[i], &level ) ) { - sprintf( c->msg, "<%s> unknown level", c->argv[0] ); + snprintf( c->msg, sizeof( c->msg ), "<%s> unknown level", c->argv[0] ); Debug( LDAP_DEBUG_ANY, "%s: %s \"%s\"\n", c->log, c->msg, c->argv[i]); return( 1 ); @@ -2094,7 +2217,7 @@ config_referral(ConfigArgs *c) { return 0; } if(validate_global_referral(c->argv[1])) { - sprintf( c->msg, "<%s> invalid URL", c->argv[0] ); + snprintf( c->msg, sizeof( c->msg ), "<%s> invalid URL", c->argv[0] ); Debug(LDAP_DEBUG_ANY, "%s: %s (%s)\n", c->log, c->msg, c->argv[1]); return(1); @@ -2136,7 +2259,13 @@ config_security(ConfigArgs *c) { tgt = (slap_ssf_t *)((char *)set + sec_keys[i].off); if ( *tgt ) { rc = 0; - bv.bv_len = sprintf( numbuf, "%u", *tgt ); + bv.bv_len = snprintf( numbuf, sizeof( numbuf ), "%u", *tgt ); + if ( bv.bv_len >= sizeof( numbuf ) ) { + ber_bvarray_free_x( c->rvalue_vals, NULL ); + c->rvalue_vals = NULL; + rc = 1; + break; + } bv.bv_len += sec_keys[i].key.bv_len; bv.bv_val = ch_malloc( bv.bv_len + 1); next = lutil_strcopy( bv.bv_val, sec_keys[i].key.bv_val ); @@ -2158,7 +2287,7 @@ config_security(ConfigArgs *c) { } } if ( !tgt ) { - sprintf( c->msg, "<%s> unknown factor", c->argv[0] ); + snprintf( c->msg, sizeof( c->msg ), "<%s> unknown factor", c->argv[0] ); Debug(LDAP_DEBUG_ANY, "%s: %s %s\n", c->log, c->msg, c->argv[i]); return(1); @@ -2166,7 +2295,7 @@ config_security(ConfigArgs *c) { *tgt = strtol(src, &next, 10); if(next == NULL || next[0] != '\0' ) { - sprintf( c->msg, "<%s> unable to parse factor", c->argv[0] ); + snprintf( c->msg, sizeof( c->msg ), "<%s> unable to parse factor", c->argv[0] ); Debug(LDAP_DEBUG_ANY, "%s: %s \"%s\"\n", c->log, c->msg, c->argv[i]); return(1); @@ -2195,7 +2324,13 @@ replica_unparse( struct slap_replica_info *ri, int i, struct berval *bv ) struct berval bc = BER_BVNULL; char numbuf[32]; - len = sprintf(numbuf, IFMT, i ); + BER_BVZERO( bv ); + + len = snprintf(numbuf, sizeof( numbuf ), SLAP_X_ORDERED_FMT, i ); + if ( len >= sizeof( numbuf ) ) { + /* FIXME: how can indicate error? */ + return; + } len += strlen( ri->ri_uri ) + STRLENOF("uri="); if ( ri->ri_nsuffix ) { @@ -2241,7 +2376,7 @@ replica_unparse( struct slap_replica_info *ri, int i, struct berval *bv ) static int config_replica(ConfigArgs *c) { - int i, nr = -1, len; + int i, nr = -1; char *replicahost, *replicauri; LDAPURLDesc *ludp; @@ -2270,22 +2405,24 @@ config_replica(ConfigArgs *c) { for(i = 1; i < c->argc; i++) { if(!strncasecmp(c->argv[i], "host=", STRLENOF("host="))) { + ber_len_t len; + replicahost = c->argv[i] + STRLENOF("host="); - len = strlen( replicahost ); - replicauri = ch_malloc( len + STRLENOF("ldap://") + 1 ); - sprintf( replicauri, "ldap://%s", replicahost ); + len = strlen( replicahost ) + STRLENOF("ldap://"); + replicauri = ch_malloc( len + 1 ); + snprintf( replicauri, len + 1, "ldap://%s", replicahost ); replicahost = replicauri + STRLENOF( "ldap://"); nr = add_replica_info(c->be, replicauri, replicahost); break; } else if(!strncasecmp(c->argv[i], "uri=", STRLENOF("uri="))) { if(ldap_url_parse(c->argv[i] + STRLENOF("uri="), &ludp) != LDAP_SUCCESS) { - sprintf( c->msg, "<%s> invalid uri", c->argv[0] ); + snprintf( c->msg, sizeof( c->msg ), "<%s> invalid uri", c->argv[0] ); Debug(LDAP_DEBUG_ANY, "%s: %s\n", c->log, c->msg, 0 ); return(1); } if(!ludp->lud_host) { ldap_free_urldesc(ludp); - sprintf( c->msg, "<%s> invalid uri - missing hostname", + snprintf( c->msg, sizeof( c->msg ), "<%s> invalid uri - missing hostname", c->argv[0] ); Debug(LDAP_DEBUG_ANY, "%s: %s\n", c->log, c->msg, 0 ); return(1); @@ -2300,11 +2437,11 @@ config_replica(ConfigArgs *c) { } } if(i == c->argc) { - sprintf( c->msg, "<%s> missing host or uri", c->argv[0] ); + snprintf( c->msg, sizeof( c->msg ), "<%s> missing host or uri", c->argv[0] ); Debug(LDAP_DEBUG_ANY, "%s: %s\n", c->log, c->msg, 0 ); return(1); } else if(nr == -1) { - sprintf( c->msg, "<%s> unable to add replica", c->argv[0] ); + snprintf( c->msg, sizeof( c->msg ), "<%s> unable to add replica", c->argv[0] ); Debug(LDAP_DEBUG_ANY, "%s: %s \"%s\"\n", c->log, c->msg, replicauri ); return(1); } else { @@ -2342,7 +2479,7 @@ config_replica(ConfigArgs *c) { continue; } if(add_replica_attrs(c->be, nr, arg + 1, exclude)) { - sprintf( c->msg, "<%s> unknown attribute", c->argv[0] ); + snprintf( c->msg, sizeof( c->msg ), "<%s> unknown attribute", c->argv[0] ); Debug(LDAP_DEBUG_ANY, "%s: %s \"%s\"\n", c->log, c->msg, arg + 1); return(1); @@ -2372,7 +2509,7 @@ config_updatedn(ConfigArgs *c) { return 0; } if(SLAP_SHADOW(c->be)) { - sprintf( c->msg, "<%s> database already shadowed", c->argv[0] ); + snprintf( c->msg, sizeof( c->msg ), "<%s> database already shadowed", c->argv[0] ); Debug(LDAP_DEBUG_ANY, "%s: %s\n", c->log, c->msg, 0); return(1); @@ -2413,7 +2550,7 @@ config_updateref(ConfigArgs *c) { return 0; } if(!SLAP_SHADOW(c->be)) { - sprintf( c->msg, "<%s> must appear after syncrepl or updatedn", + snprintf( c->msg, sizeof( c->msg ), "<%s> must appear after syncrepl or updatedn", c->argv[0] ); Debug(LDAP_DEBUG_ANY, "%s: %s\n", c->log, c->msg, 0); @@ -2421,7 +2558,7 @@ config_updateref(ConfigArgs *c) { } if(validate_global_referral(c->argv[1])) { - sprintf( c->msg, "<%s> invalid URL", c->argv[0] ); + snprintf( c->msg, sizeof( c->msg ), "<%s> invalid URL", c->argv[0] ); Debug(LDAP_DEBUG_ANY, "%s: %s (%s)\n", c->log, c->msg, c->argv[1]); return(1); @@ -2481,6 +2618,7 @@ config_tls_option(ConfigArgs *c) { case CFG_TLS_CERT_KEY: flag = LDAP_OPT_X_TLS_KEYFILE; break; case CFG_TLS_CA_PATH: flag = LDAP_OPT_X_TLS_CACERTDIR; break; case CFG_TLS_CA_FILE: flag = LDAP_OPT_X_TLS_CACERTFILE; break; + case CFG_TLS_DH_FILE: flag = LDAP_OPT_X_TLS_DHFILE; break; default: Debug(LDAP_DEBUG_ANY, "%s: " "unknown tls_option <0x%x>\n", c->log, c->type, 0); @@ -2958,7 +3096,7 @@ check_vals( ConfigTable *ct, ConfigArgs *ca, void *ptr, int isAttr ) sort = 1; rc = ordered_value_sort( a, 1 ); if ( rc ) { - sprintf(ca->msg, "ordered_value_sort failed on attr %s\n", + snprintf(ca->msg, sizeof( ca->msg ), "ordered_value_sort failed on attr %s\n", ad->ad_cname.bv_val ); return rc; } @@ -3048,7 +3186,10 @@ check_name_index( CfEntryInfo *parent, ConfigType ce_type, Entry *e, if (!a ) return LDAP_NAMING_VIOLATION; ival.bv_val = ibuf; - ival.bv_len = sprintf( ibuf, IFMT, nsibs ); + ival.bv_len = snprintf( ibuf, sizeof( ibuf ), SLAP_X_ORDERED_FMT, nsibs ); + if ( ival.bv_len >= sizeof( ibuf ) ) { + return LDAP_NAMING_VIOLATION; + } newrdn.bv_len = rdn.bv_len + ival.bv_len; newrdn.bv_val = ch_malloc( newrdn.bv_len+1 ); @@ -3351,7 +3492,7 @@ ok: } } if ( rc ) { - sprintf( ca->msg, "<%s> failed startup", ca->argv[0] ); + snprintf( ca->msg, sizeof( ca->msg ), "<%s> failed startup", ca->argv[0] ); Debug(LDAP_DEBUG_ANY, "%s: %s (%s)!\n", ca->log, ca->msg, ca->argv[1] ); rc = LDAP_OTHER; @@ -3984,7 +4125,11 @@ config_build_schema_inc( ConfigArgs *c, CfEntryInfo *ceparent, ptr = strchr( bv.bv_val, '.' ); if ( ptr ) bv.bv_len = ptr - bv.bv_val; - c->value_dn.bv_len = sprintf(c->value_dn.bv_val, "cn=" IFMT, c->depth); + c->value_dn.bv_len = snprintf(c->value_dn.bv_val, sizeof( c->log ), "cn=" SLAP_X_ORDERED_FMT, c->depth); + if ( c->value_dn.bv_len >= sizeof( c->log ) ) { + /* FIXME: how can indicate error? */ + return; + } strncpy( c->value_dn.bv_val + c->value_dn.bv_len, bv.bv_val, bv.bv_len ); c->value_dn.bv_len += bv.bv_len; @@ -4010,7 +4155,11 @@ config_build_includes( ConfigArgs *c, CfEntryInfo *ceparent, for (i=0; cf; cf=cf->c_sibs, i++) { c->value_dn.bv_val = c->log; - c->value_dn.bv_len = sprintf(c->value_dn.bv_val, "cn=include" IFMT, i); + c->value_dn.bv_len = snprintf(c->value_dn.bv_val, sizeof( c->log ), "cn=include" SLAP_X_ORDERED_FMT, i); + if ( c->value_dn.bv_len >= sizeof( c->log ) ) { + /* FIXME: how can indicate error? */ + return; + } c->private = cf; e = config_build_entry( op, rs, ceparent, c, &c->value_dn, &CFOC_INCLUDE, NULL ); @@ -4034,7 +4183,11 @@ config_build_modules( ConfigArgs *c, CfEntryInfo *ceparent, if ( BER_BVISNULL( &mp->mp_path ) && !mp->mp_loads ) continue; c->value_dn.bv_val = c->log; - c->value_dn.bv_len = sprintf(c->value_dn.bv_val, "cn=module" IFMT, i); + c->value_dn.bv_len = snprintf(c->value_dn.bv_val, sizeof( c->log ), "cn=module" SLAP_X_ORDERED_FMT, i); + if ( c->value_dn.bv_len >= sizeof( c->log ) ) { + /* FIXME: how can indicate error? */ + return; + } c->private = mp; config_build_entry( op, rs, ceparent, c, &c->value_dn, &CFOC_MODULE, NULL ); @@ -4129,7 +4282,11 @@ config_back_db_open( BackendDB *be ) if (!bi->bi_private) continue; rdn.bv_val = c.log; - rdn.bv_len = sprintf(rdn.bv_val, "%s=%s", cfAd_backend->ad_cname.bv_val, bi->bi_type); + rdn.bv_len = snprintf(rdn.bv_val, sizeof( c.log ), + "%s=%s", cfAd_backend->ad_cname.bv_val, bi->bi_type); + if ( rdn.bv_len >= sizeof( c.log ) ) { + /* FIXME: holler ... */ ; + } c.bi = bi; e = config_build_entry( op, &rs, ceparent, &c, &rdn, &CFOC_BACKEND, bi->bi_cf_ocs ); @@ -4149,8 +4306,12 @@ config_back_db_open( BackendDB *be ) bi = be->bd_info; } rdn.bv_val = c.log; - rdn.bv_len = sprintf(rdn.bv_val, "%s=" IFMT "%s", cfAd_database->ad_cname.bv_val, + rdn.bv_len = snprintf(rdn.bv_val, sizeof( c.log ), + "%s=" SLAP_X_ORDERED_FMT "%s", cfAd_database->ad_cname.bv_val, i, bi->bi_type); + if ( rdn.bv_len >= sizeof( c.log ) ) { + /* FIXME: holler ... */ ; + } c.be = be; c.bi = bi; e = config_build_entry( op, &rs, ceparent, &c, &rdn, &CFOC_DATABASE, @@ -4166,8 +4327,12 @@ config_back_db_open( BackendDB *be ) for (j=0,on=oi->oi_list; on; j++,on=on->on_next) { rdn.bv_val = c.log; - rdn.bv_len = sprintf(rdn.bv_val, "%s=" IFMT "%s", + rdn.bv_len = snprintf(rdn.bv_val, sizeof( c.log ), + "%s=" SLAP_X_ORDERED_FMT "%s", cfAd_overlay->ad_cname.bv_val, j, on->on_bi.bi_type ); + if ( rdn.bv_len >= sizeof( c.log ) ) { + /* FIXME: holler ... */ ; + } c.be = be; c.bi = &on->on_bi; oe = config_build_entry( op, &rs, ce, &c, &rdn, diff --git a/servers/slapd/config.c b/servers/slapd/config.c index 8d5544183d..26d20f5ee0 100644 --- a/servers/slapd/config.c +++ b/servers/slapd/config.c @@ -131,7 +131,7 @@ int config_check_vals(ConfigTable *Conf, ConfigArgs *c, int check_only ) { c->argv[1] = ""; } if(Conf->min_args && (c->argc < Conf->min_args)) { - sprintf( c->msg, "<%s> missing <%s> argument", + snprintf( c->msg, sizeof( c->msg ), "<%s> missing <%s> argument", c->argv[0], Conf->what ); Debug(LDAP_DEBUG_CONFIG, "%s: keyword %s\n", c->log, c->msg, 0 ); return(ARG_BAD_CONF); @@ -139,7 +139,7 @@ int config_check_vals(ConfigTable *Conf, ConfigArgs *c, int check_only ) { if(Conf->max_args && (c->argc > Conf->max_args)) { char *ignored = " ignored"; - sprintf( c->msg, "<%s> extra cruft after <%s>", + snprintf( c->msg, sizeof( c->msg ), "<%s> extra cruft after <%s>", c->argv[0], Conf->what ); #ifdef LDAP_DEVEL @@ -152,34 +152,34 @@ int config_check_vals(ConfigTable *Conf, ConfigArgs *c, int check_only ) { #endif /* LDAP_DEVEL */ } if((arg_type & ARG_DB) && !c->be) { - sprintf( c->msg, "<%s> only allowed within database declaration", + 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) { - sprintf( c->msg, "<%s> must occur before any backend %sdeclaration", + snprintf( c->msg, sizeof( c->msg ), "<%s> must occur before any backend %sdeclaration", c->argv[0], (arg_type & 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) { - sprintf( c->msg, "<%s> must occur before any database declaration", + 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] != '(' /*')'*/) { - sprintf( c->msg, "<%s> old format not supported", c->argv[0] ); + 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)) { - sprintf( c->msg, "<%s> invalid config_table, arg_item is NULL", + 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); @@ -204,7 +204,7 @@ int config_check_vals(ConfigTable *Conf, ConfigArgs *c, int check_only ) { !strcasecmp(c->argv[1], "false")) { iarg = 0; } else { - sprintf( c->msg, "<%s> invalid value, ignored", + snprintf( c->msg, sizeof( c->msg ), "<%s> invalid value, ignored", c->argv[0] ); Debug(LDAP_DEBUG_CONFIG, "%s: %s\n", c->log, c->msg, 0 ); @@ -215,7 +215,7 @@ int config_check_vals(ConfigTable *Conf, ConfigArgs *c, int check_only ) { j = (arg_type & ARG_NONZERO) ? 1 : 0; if(iarg < j && larg < j && barg < j ) { larg = larg ? larg : (barg ? barg : iarg); - sprintf( c->msg, "<%s> invalid value, ignored", + snprintf( c->msg, sizeof( c->msg ), "<%s> invalid value, ignored", c->argv[0] ); Debug(LDAP_DEBUG_CONFIG, "%s: %s\n", c->log, c->msg, 0 ); @@ -238,7 +238,7 @@ int config_check_vals(ConfigTable *Conf, ConfigArgs *c, int check_only ) { ber_str2bv( c->argv[1], 0, 0, &bv ); rc = dnPrettyNormal( NULL, &bv, &c->value_dn, &c->value_ndn, NULL ); if ( rc != LDAP_SUCCESS ) { - sprintf( c->msg, "<%s> invalid DN %d (%s)", + 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); @@ -265,7 +265,7 @@ int config_set_vals(ConfigTable *Conf, ConfigArgs *c) { #endif if(rc) { if ( !c->msg[0] ) { - sprintf( c->msg, "<%s> handler exited with %d", + snprintf( c->msg, sizeof( c->msg ), "<%s> handler exited with %d", c->argv[0], rc ); Debug(LDAP_DEBUG_CONFIG, "%s: %s!\n", c->log, c->msg, 0 ); @@ -280,7 +280,7 @@ int config_set_vals(ConfigTable *Conf, ConfigArgs *c) { else if (c->bi) ptr = c->bi->bi_private; else { - sprintf( c->msg, "<%s> offset is missing base pointer", + snprintf( c->msg, sizeof( c->msg ), "<%s> offset is missing base pointer", c->argv[0] ); Debug(LDAP_DEBUG_CONFIG, "%s: %s!\n", c->log, c->msg, 0); @@ -393,10 +393,10 @@ config_get_vals(ConfigTable *cf, ConfigArgs *c) if ( cf->arg_type & ARGS_POINTER) { bv.bv_val = c->log; switch(cf->arg_type & ARGS_POINTER) { - case ARG_INT: bv.bv_len = sprintf(bv.bv_val, "%d", c->value_int); break; - case ARG_LONG: bv.bv_len = sprintf(bv.bv_val, "%ld", c->value_long); break; - case ARG_BER_LEN_T: bv.bv_len = sprintf(bv.bv_val, "%ld", c->value_ber_t); break; - case ARG_ON_OFF: bv.bv_len = sprintf(bv.bv_val, "%s", + 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; + case ARG_ON_OFF: bv.bv_len = snprintf(bv.bv_val, sizeof( c->log ), "%s", c->value_int ? "TRUE" : "FALSE"); break; case ARG_STRING: if ( c->value_string && c->value_string[0]) { @@ -413,6 +413,9 @@ config_get_vals(ConfigTable *cf, ConfigArgs *c) } break; } + if (bv.bv_val == c->log && bv.bv_len >= sizeof( c->log ) ) { + return 1; + } if (( cf->arg_type & ARGS_POINTER ) == ARG_STRING ) ber_bvarray_add(&c->rvalue_vals, &bv); else @@ -853,18 +856,20 @@ verbs_to_mask(int argc, char *argv[], slap_verbmasks *v, slap_mask_t *m) { */ int mask_to_verbs(slap_verbmasks *v, slap_mask_t m, BerVarray *bva) { - int i; - - if (!m) return 1; - for (i=0; !BER_BVISNULL(&v[i].word); i++) { - if (!v[i].mask) continue; - if (( m & v[i].mask ) == v[i].mask ) { - value_add_one( bva, &v[i].word ); - m ^= v[i].mask; - if ( !m ) break; + int i, rc = 1; + + if (m) { + for (i=0; !BER_BVISNULL(&v[i].word); i++) { + if (!v[i].mask) continue; + if (( m & v[i].mask ) == v[i].mask ) { + value_add_one( bva, &v[i].word ); + rc = 0; + m ^= v[i].mask; + if ( !m ) break; + } } } - return 0; + return rc; } int @@ -1383,7 +1388,7 @@ int config_generic_wrapper( Backend *be, const char *fname, int lineno, c.argc = argc; c.argv = argv; c.valx = -1; - sprintf( c.log, "%s: line %d", fname, lineno ); + snprintf( c.log, sizeof( c.log ), "%s: line %d", fname, lineno ); rc = SLAP_CONF_UNKNOWN; ct = config_find_keyword( be->be_cf_ocs->co_table, &c ); diff --git a/servers/slapd/connection.c b/servers/slapd/connection.c index 06918c2a3d..e3bd2f5d41 100644 --- a/servers/slapd/connection.c +++ b/servers/slapd/connection.c @@ -43,10 +43,33 @@ #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; @@ -82,10 +105,25 @@ connection_state2str( int state ) static Connection* connection_get( ber_socket_t s ); +#ifdef SLAP_LIGHTWEIGHT_DISPATCHER + +typedef struct conn_readinfo { + Operation *op; + ldap_pvt_thread_start_t *func; + void *arg; + int nullop; +} conn_readinfo; + +static int connection_input( Connection *c, conn_readinfo *cri ); +#else static int connection_input( Connection *c ); +#endif static void connection_close( Connection *c ); static int connection_op_activate( Operation *op ); +#ifdef SLAP_LIGHTWEIGHT_DISPATCHER +static void connection_op_queue( Operation *op ); +#endif static int connection_resched( Connection *conn ); static void connection_abandon( Connection *conn ); static void connection_destroy( Connection *c ); @@ -96,6 +134,69 @@ static ldap_pvt_thread_start_t connection_operation; * 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 mutex[%d] failed\n", i, 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; @@ -114,8 +215,8 @@ int connections_init(void) connections = (Connection *) ch_calloc( dtblsize, sizeof(Connection) ); if( connections == NULL ) { - Debug( LDAP_DEBUG_ANY, - "connections_init: allocation (%d*%ld) of connection array failed\n", + Debug( LDAP_DEBUG_ANY, "connections_init: " + "allocation (%d*%ld) of connection array failed\n", dtblsize, (long) sizeof(Connection), 0 ); return -1; } @@ -132,11 +233,58 @@ int connections_init(void) 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; @@ -156,7 +304,8 @@ int connections_destroy(void) ldap_pvt_thread_cond_destroy( &connections[i].c_write_cv ); #ifdef LDAP_SLAPI if ( slapi_plugins_used ) { - slapi_int_free_object_extensions( SLAPI_X_EXT_CONNECTION, &connections[i] ); + slapi_int_free_object_extensions( SLAPI_X_EXT_CONNECTION, + &connections[i] ); } #endif } @@ -169,11 +318,45 @@ int connections_destroy(void) 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; @@ -203,6 +386,7 @@ int connections_shutdown(void) return 0; } +#endif /* * Timeout idle connections. @@ -219,8 +403,9 @@ int connections_timeout_idle(time_t now) { /* Don't timeout a slow-running request or a persistent * outbound connection */ - if( c->c_n_ops_executing || - c->c_conn_state == SLAP_C_CLIENT ) continue; + if( c->c_n_ops_executing || c->c_conn_state == SLAP_C_CLIENT ) { + continue; + } if( difftime( c->c_activitytime+global_idletimeout, now) < 0 ) { /* close it */ @@ -246,12 +431,11 @@ static Connection* connection_get( ber_socket_t s ) assert( connections != NULL ); - if(s == AC_SOCKET_INVALID) { - return NULL; - } + if(s == AC_SOCKET_INVALID) return NULL; #ifndef HAVE_WINSOCK - c = &connections[s]; + assert( MCA_conn_check( s ) ); + c = MCA_GET_CONNECTION(s); assert( c->c_struct_state != SLAP_C_UNINITIALIZED ); @@ -367,11 +551,11 @@ long connection_init( assert( s < dtblsize ); #endif - ldap_pvt_thread_mutex_lock( &connections_mutex ); + ldap_pvt_thread_mutex_lock( MCA_GET_CONN_MUTEX(s) ); #ifndef HAVE_WINSOCK - c = &connections[s]; - + assert( MCA_conn_check( s ) ); + c = MCA_GET_CONNECTION(s); #else { ber_socket_t i; @@ -398,9 +582,7 @@ long connection_init( break; } - if( connections[i].c_conn_state == SLAP_C_CLIENT ) { - continue; - } + if( connections[i].c_conn_state == SLAP_C_CLIENT ) continue; assert( connections[i].c_struct_state == SLAP_C_USED ); assert( connections[i].c_conn_state != SLAP_C_INVALID ); @@ -497,7 +679,7 @@ long connection_init( 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( &connections_mutex ); + ldap_pvt_thread_mutex_unlock( MCA_GET_CONN_MUTEX(s) ); return 0; } @@ -584,8 +766,9 @@ long connection_init( slap_sasl_open( c, 0 ); slap_sasl_external( c, ssf, authid ); + slapd_add_internal( s, 1 ); ldap_pvt_thread_mutex_unlock( &c->c_mutex ); - ldap_pvt_thread_mutex_unlock( &connections_mutex ); + ldap_pvt_thread_mutex_unlock( MCA_GET_CONN_MUTEX(s) ); backend_connection_init(c); @@ -611,10 +794,12 @@ void connection2anonymous( Connection *c ) ch_free(c->c_dn.bv_val); } BER_BVZERO( &c->c_dn ); + if ( !BER_BVISNULL( &c->c_ndn ) ) { ch_free(c->c_ndn.bv_val); } BER_BVZERO( &c->c_ndn ); + if ( !BER_BVISNULL( &c->c_sasl_authz_dn ) ) { ber_memfree_x( c->c_sasl_authz_dn.bv_val, NULL ); } @@ -675,17 +860,19 @@ connection_destroy( Connection *c ) } 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 ); + 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(); } - ber_sockbuf_free( c->c_sb ); - c->c_sb = ber_sockbuf_alloc( ); { @@ -817,21 +1004,34 @@ unsigned long connections_nextid(void) unsigned long id; assert( connections != NULL ); - ldap_pvt_thread_mutex_lock( &connections_mutex ); + ldap_pvt_thread_mutex_lock( &conn_nextid_mutex ); id = conn_nextid; - ldap_pvt_thread_mutex_unlock( &connections_mutex ); + ldap_pvt_thread_mutex_unlock( &conn_nextid_mutex ); return id; } 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; @@ -839,15 +1039,54 @@ Connection* connection_first( ber_socket_t *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 <= dtblsize ); + assert( *index >= 0 && *index < MCA_ARRAY_SIZE ); - if( c != NULL ) { - ldap_pvt_thread_mutex_unlock( &c->c_mutex ); + 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 + 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 ); } + if( c != NULL ) ldap_pvt_thread_mutex_lock( &c->c_mutex ); + + return c; + +} +#else +{ + assert( connections != NULL ); + assert( index != NULL ); + assert( *index <= dtblsize ); + + if( c != NULL ) ldap_pvt_thread_mutex_unlock( &c->c_mutex ); + c = NULL; for(; *index < dtblsize; (*index)++) { @@ -870,22 +1109,31 @@ Connection* connection_next( Connection *c, ber_socket_t *index ) assert( connections[*index].c_conn_state == SLAP_C_INVALID ); } - if( c != NULL ) { - ldap_pvt_thread_mutex_lock( &c->c_mutex ); - } - + if( c != NULL ) ldap_pvt_thread_mutex_lock( &c->c_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 ); - } + 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 } /* @@ -910,7 +1158,7 @@ void connection_done( Connection *c ) ldap_pvt_thread_mutex_unlock( &slap_counters.sc_ops_mutex ); \ } while (0) #else /* !SLAPD_MONITOR */ -#define INCR_OP_INITIATED(index) +#define INCR_OP_INITIATED(index) do { } while (0) #define INCR_OP_COMPLETED(index) \ do { \ ldap_pvt_thread_mutex_lock( &slap_counters.sc_ops_mutex ); \ @@ -1072,10 +1320,11 @@ operations_error: } if ( op->o_cancel == SLAP_CANCEL_REQ ) { - if ( rc == SLAPD_ABANDON ) + if ( rc == SLAPD_ABANDON ) { op->o_cancel = SLAP_CANCEL_ACK; - else + } else { op->o_cancel = LDAP_TOO_LATE; + } } while ( op->o_cancel != SLAP_CANCEL_NONE && op->o_cancel != SLAP_CANCEL_DONE ) @@ -1097,17 +1346,9 @@ operations_error: case LBER_ERROR: case LDAP_REQ_UNBIND: /* c_mutex is locked */ - connection_closing( - conn, tag == LDAP_REQ_UNBIND ? NULL : "operations error" ); + connection_closing( conn, + tag == LDAP_REQ_UNBIND ? NULL : "operations error" ); break; - - case LDAP_REQ_BIND: - conn->c_sasl_bind_in_progress = - rc == LDAP_SASL_BIND_IN_PROGRESS ? 1 : 0; - - if( conn->c_conn_state == SLAP_C_BINDING) { - conn->c_conn_state = SLAP_C_ACTIVE; - } } connection_resched( conn ); @@ -1132,9 +1373,10 @@ int connection_client_setup( c = connection_get( s ); c->c_clientfunc = func; c->c_clientarg = arg; - connection_return( c ); + slapd_add_internal( s, 0 ); slapd_set_read( s, 1 ); + connection_return( c ); return 0; } @@ -1158,7 +1400,9 @@ void connection_client_stop( c->c_conn_state = SLAP_C_INVALID; c->c_struct_state = SLAP_C_UNUSED; c->c_close_reason = "?"; /* should never be needed */ + slapd_sd_lock(); ber_sockbuf_free( c->c_sb ); + slapd_remove( s, 0, 1, 1 ); c->c_sb = ber_sockbuf_alloc( ); { ber_len_t max = sockbuf_max_incoming; @@ -1166,17 +1410,76 @@ void connection_client_stop( } connection_return( c ); - slapd_remove( s, 0, 1 ); } +#ifdef SLAP_LIGHTWEIGHT_DISPATCHER + +static int connection_read( ber_socket_t s, conn_readinfo *cri ); + +static void* connection_read_thread( void* ctx, void* argv ) +{ + int rc ; + conn_readinfo cri = { NULL, NULL, NULL, 0 }; + ber_socket_t s = (long)argv; + + /* + * read incoming LDAP requests. If there is more than one, + * the first one is returned with new_op + */ + if( ( rc = connection_read( s, &cri ) ) < 0 ) { + Debug( LDAP_DEBUG_CONNS, "connection_read(%d) error\n", s, 0, 0 ); + return (void*)(long)rc; + } + + /* execute a single queued request in the same thread */ + if( cri.op && !cri.nullop ) { + rc = (long)connection_operation( ctx, cri.op ); + } else if ( cri.func ) { + rc = (long)cri.func( ctx, cri.arg ); + } + + return (void*)(long)rc; +} + +int connection_read_activate( ber_socket_t s ) +{ + int rc; + + /* + * suspend reading on this file descriptor until a connection processing + * thread reads data on it. Otherwise the listener thread will repeatedly + * submit the same event on it to the pool. + */ + rc = slapd_clr_read( s, 0 ); + if ( rc ) + return rc; + + rc = ldap_pvt_thread_pool_submit( &connection_pool, + connection_read_thread, (void *)(long)s ); + + if( rc != 0 ) { + Debug( LDAP_DEBUG_ANY, + "connection_read_activate(%d): submit failed (%d)\n", + s, rc, 0 ); + } + + return rc; +} +#endif + +#ifdef SLAP_LIGHTWEIGHT_DISPATCHER +static int +connection_read( ber_socket_t s, conn_readinfo *cri ) +#else int connection_read(ber_socket_t s) +#endif { int rc = 0; Connection *c; assert( connections != NULL ); - ldap_pvt_thread_mutex_lock( &connections_mutex ); + ldap_pvt_thread_mutex_lock( MCA_GET_CONN_MUTEX(s) ); /* get (locked) connection */ c = connection_get( s ); @@ -1185,9 +1488,8 @@ int connection_read(ber_socket_t s) Debug( LDAP_DEBUG_ANY, "connection_read(%ld): no connection!\n", (long) s, 0, 0 ); - slapd_remove(s, 1, 0); - ldap_pvt_thread_mutex_unlock( &connections_mutex ); + ldap_pvt_thread_mutex_unlock( MCA_GET_CONN_MUTEX(s) ); return -1; } @@ -1197,17 +1499,27 @@ int connection_read(ber_socket_t s) 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( &connections_mutex ); + ldap_pvt_thread_mutex_unlock( MCA_GET_CONN_MUTEX(s) ); return 0; } if ( c->c_conn_state == SLAP_C_CLIENT ) { +#ifdef SLAP_LIGHTWEIGHT_DISPATCHER + cri->func = c->c_clientfunc; + cri->arg = c->c_clientarg; + /* read should already be cleared */ +#else slapd_clr_read( s, 0 ); ldap_pvt_thread_pool_submit( &connection_pool, c->c_clientfunc, c->c_clientarg ); +#endif connection_return( c ); - ldap_pvt_thread_mutex_unlock( &connections_mutex ); + ldap_pvt_thread_mutex_unlock( MCA_GET_CONN_MUTEX(s) ); return 0; } @@ -1219,34 +1531,38 @@ int connection_read(ber_socket_t s) if ( c->c_is_tls && c->c_needs_tls_accept ) { rc = ldap_pvt_tls_accept( c->c_sb, slap_tls_ctx ); if ( rc < 0 ) { -#if 0 /* required by next #if 0 */ - struct timeval tv; - fd_set rfd; -#endif - Debug( LDAP_DEBUG_TRACE, - "connection_read(%d): TLS accept error " + "connection_read(%d): TLS accept failure " "error=%d id=%lu, closing\n", s, rc, c->c_connid ); + c->c_needs_tls_accept = 0; /* connections_mutex and c_mutex are locked */ connection_closing( c, "TLS negotiation failure" ); #if 0 - /* 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); + { + 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 ) { void *ssl; @@ -1279,8 +1595,12 @@ int connection_read(ber_socket_t s) if( rc != 0 || !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( &connections_mutex ); + ldap_pvt_thread_mutex_unlock( MCA_GET_CONN_MUTEX(s) ); return 0; } } @@ -1290,25 +1610,29 @@ int connection_read(ber_socket_t s) if ( c->c_sasl_layers ) { /* If previous layer is not removed yet, give up for now */ if ( !c->c_sasl_sockctx ) { +#ifdef SLAP_LIGHTWEIGHT_DISPATCHER + slapd_set_read( s, 1 ); +#endif + connection_return( c ); - ldap_pvt_thread_mutex_unlock( &connections_mutex ); + ldap_pvt_thread_mutex_unlock( MCA_GET_CONN_MUTEX(s) ); return 0; } c->c_sasl_layers = 0; rc = ldap_pvt_sasl_install( c->c_sb, c->c_sasl_sockctx ); - if( rc != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, "connection_read(%d): SASL install error " "error=%d id=%lu, closing\n", s, rc, c->c_connid ); + /* connections_mutex and c_mutex are locked */ connection_closing( c, "SASL layer install failure" ); connection_close( c ); connection_return( c ); - ldap_pvt_thread_mutex_unlock( &connections_mutex ); + ldap_pvt_thread_mutex_unlock( MCA_GET_CONN_MUTEX(s) ); return 0; } } @@ -1319,7 +1643,11 @@ int connection_read(ber_socket_t s) do { /* How do we do this without getting into a busy loop ? */ +#ifdef SLAP_LIGHTWEIGHT_DISPATCHER + rc = connection_input( c, cri ); +#else rc = connection_input( c ); +#endif } #ifdef DATA_READY_LOOP while( !rc && ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_DATA_READY, NULL )); @@ -1333,14 +1661,22 @@ int connection_read(ber_socket_t s) Debug( LDAP_DEBUG_TRACE, "connection_read(%d): input error=%d id=%lu, closing.\n", s, rc, c->c_connid ); + /* connections_mutex and c_mutex are locked */ connection_closing( c, conn_lost_str ); connection_close( c ); connection_return( c ); - ldap_pvt_thread_mutex_unlock( &connections_mutex ); + ldap_pvt_thread_mutex_unlock( MCA_GET_CONN_MUTEX(s) ); return 0; } +#ifdef SLAP_LIGHTWEIGHT_DISPATCHER + if ( ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_NEEDS_WRITE, NULL ) ) { + slapd_set_write( s, 0 ); + } + + slapd_set_read( s, 1 ); +#else if ( ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_NEEDS_READ, NULL ) ) { slapd_set_read( s, 1 ); } @@ -1348,15 +1684,20 @@ int connection_read(ber_socket_t s) if ( ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_NEEDS_WRITE, NULL ) ) { slapd_set_write( s, 1 ); } +#endif connection_return( c ); - ldap_pvt_thread_mutex_unlock( &connections_mutex ); + ldap_pvt_thread_mutex_unlock( MCA_GET_CONN_MUTEX(s) ); + return 0; } static int -connection_input( - Connection *conn ) +#ifdef SLAP_LIGHTWEIGHT_DISPATCHER +connection_input( Connection *conn , conn_readinfo *cri ) +#else +connection_input( Connection *conn ) +#endif { Operation *op; ber_tag_t tag; @@ -1381,11 +1722,11 @@ connection_input( #ifdef LDAP_CONNECTIONLESS if ( conn->c_is_udp ) { - char peername[sizeof("IP=255.255.255.255:65336")]; - len = ber_int_sb_read(conn->c_sb, &peeraddr, - sizeof(struct sockaddr)); - if (len != sizeof(struct sockaddr)) - return 1; + char peername[sizeof("IP=255.255.255.255:65336")]; + + len = ber_int_sb_read(conn->c_sb, &peeraddr, sizeof(struct sockaddr)); + if (len != sizeof(struct sockaddr)) return 1; + sprintf( peername, "IP=%s:%d", inet_ntoa( peeraddr.sa_in_addr.sin_addr ), (unsigned) ntohs( peeraddr.sa_in_addr.sin_port ) ); @@ -1394,6 +1735,7 @@ connection_input( conn->c_connid, peername, conn->c_sock_name.bv_val, 0, 0 ); } #endif + tag = ber_get_next( conn->c_sb, &len, conn->c_currentber ); if ( tag != LDAP_TAG_MESSAGE ) { int err = errno; @@ -1419,16 +1761,14 @@ connection_input( if ( (tag = ber_get_int( ber, &msgid )) != LDAP_TAG_MSGID ) { /* log, close and send error */ - Debug( LDAP_DEBUG_ANY, "ber_get_int returns 0x%lx\n", - tag, 0, 0 ); + Debug( LDAP_DEBUG_ANY, "ber_get_int returns 0x%lx\n", tag, 0, 0 ); ber_free( ber, 1 ); return -1; } if ( (tag = ber_peek_tag( ber, &len )) == LBER_ERROR ) { /* log, close and send error */ - Debug( LDAP_DEBUG_ANY, "ber_peek_tag returns 0x%lx\n", - tag, 0, 0 ); + Debug( LDAP_DEBUG_ANY, "ber_peek_tag returns 0x%lx\n", tag, 0, 0 ); ber_free( ber, 1 ); return -1; @@ -1447,6 +1787,7 @@ connection_input( } } #endif + if(tag == LDAP_REQ_BIND) { /* immediately abandon all existing operations upon BIND */ connection_abandon( conn ); @@ -1457,7 +1798,8 @@ connection_input( op->o_conn = conn; /* clear state if the connection is being reused from inactive */ if ( conn->c_conn_state == SLAP_C_INACTIVE ) { - memset( &conn->c_pagedresults_state, 0, sizeof( conn->c_pagedresults_state ) ); + memset( &conn->c_pagedresults_state, 0, + sizeof( conn->c_pagedresults_state ) ); } op->o_res_ber = NULL; @@ -1536,14 +1878,33 @@ connection_input( conn->c_connid, defer, 0 ); conn->c_n_ops_pending++; LDAP_STAILQ_INSERT_TAIL( &conn->c_pending_ops, op, o_next ); - if ( conn->c_n_ops_pending > max ) { - rc = -1; - } else { - rc = 1; - } + rc = ( conn->c_n_ops_pending > max ) ? -1 : 0; + } else { conn->c_n_ops_executing++; + +#ifdef SLAP_LIGHTWEIGHT_DISPATCHER + /* + * The first op will be processed in the same thread context, + * as long as there is only one op total. + * Subsequent ops will be submitted to the pool by + * calling connection_op_activate() + */ + if ( cri->op == NULL ) { + /* the first incoming request */ + connection_op_queue( op ); + cri->op = op; + } else { + if ( !cri->nullop ) { + cri->nullop = 1; + rc = ldap_pvt_thread_pool_submit( &connection_pool, + connection_operation, (void *) cri->op ); + } + connection_op_activate( op ); + } +#else connection_op_activate( op ); +#endif } #ifdef NO_THREADS @@ -1552,8 +1913,8 @@ connection_input( return 1; } #endif - assert( conn->c_struct_state == SLAP_C_USED ); + assert( conn->c_struct_state == SLAP_C_USED ); return rc; } @@ -1568,7 +1929,7 @@ connection_resched( Connection *conn ) ber_sockbuf_ctrl( conn->c_sb, LBER_SB_OPT_GET_FD, &sd ); /* use trylock to avoid possible deadlock */ - rc = ldap_pvt_thread_mutex_trylock( &connections_mutex ); + rc = ldap_pvt_thread_mutex_trylock( MCA_GET_CONN_MUTEX( sd ) ); if( rc ) { Debug( LDAP_DEBUG_TRACE, @@ -1580,7 +1941,7 @@ connection_resched( Connection *conn ) * so recheck state below. */ ldap_pvt_thread_mutex_unlock( &conn->c_mutex ); - ldap_pvt_thread_mutex_lock( &connections_mutex ); + ldap_pvt_thread_mutex_lock( MCA_GET_CONN_MUTEX ( sd ) ); ldap_pvt_thread_mutex_lock( &conn->c_mutex ); } @@ -1595,7 +1956,7 @@ connection_resched( Connection *conn ) connection_close( conn ); } - ldap_pvt_thread_mutex_unlock( &connections_mutex ); + ldap_pvt_thread_mutex_unlock( MCA_GET_CONN_MUTEX( sd ) ); return 0; } @@ -1605,11 +1966,11 @@ connection_resched( Connection *conn ) } while ((op = LDAP_STAILQ_FIRST( &conn->c_pending_ops )) != NULL) { - if ( conn->c_n_ops_executing > connection_pool_max/2 ) { - break; - } + if ( conn->c_n_ops_executing > connection_pool_max/2 ) break; + LDAP_STAILQ_REMOVE_HEAD( &conn->c_pending_ops, o_next ); LDAP_STAILQ_NEXT(op, o_next) = NULL; + /* pending operations should not be marked for abandonment */ assert(!op->o_abandon); @@ -1618,9 +1979,7 @@ connection_resched( Connection *conn ) connection_op_activate( op ); - if ( conn->c_conn_state == SLAP_C_BINDING ) { - break; - } + if ( conn->c_conn_state == SLAP_C_BINDING ) break; } return 0; } @@ -1630,20 +1989,36 @@ connection_init_log_prefix( Operation *op ) { if ( op->o_connid == (unsigned long)(-1) ) { snprintf( op->o_log_prefix, sizeof( op->o_log_prefix ), - "conn=-1 op=%lu", op->o_opid ); + "conn=-1 op=%lu", op->o_opid ); } else { snprintf( op->o_log_prefix, sizeof( op->o_log_prefix ), - "conn=%lu op=%lu", op->o_connid, op->o_opid ); + "conn=%lu op=%lu", op->o_connid, op->o_opid ); } } -static int connection_op_activate( Operation *op ) +static int connection_bind_cb( Operation *op, SlapReply *rs ) +{ + slap_callback *cb = op->o_callback; + op->o_callback = cb->sc_next; + + ldap_pvt_thread_mutex_lock( &op->o_conn->c_mutex ); + op->o_conn->c_conn_state = SLAP_C_ACTIVE; + ldap_pvt_thread_mutex_unlock( &op->o_conn->c_mutex ); + + ch_free( cb ); + return SLAP_CB_CONTINUE; +} + +static void connection_op_queue( Operation *op ) { - int status; ber_tag_t tag = op->o_tag; - if(tag == LDAP_REQ_BIND) { + if (tag == LDAP_REQ_BIND) { + slap_callback *sc = ch_calloc( 1, sizeof( slap_callback )); + sc->sc_response = connection_bind_cb; + sc->sc_next = op->o_callback; + op->o_callback = sc; op->o_conn->c_conn_state = SLAP_C_BINDING; } @@ -1657,6 +2032,7 @@ static int connection_op_activate( Operation *op ) ber_dupbv( &op->o_ndn, &op->o_conn->c_sasl_authz_dn ); } } + op->o_authtype = op->o_conn->c_authtype; ber_dupbv( &op->o_authmech, &op->o_conn->c_authmech ); @@ -1664,8 +2040,9 @@ static int connection_op_activate( Operation *op ) op->o_protocol = op->o_conn->c_protocol ? op->o_conn->c_protocol : LDAP_VERSION3; } - if (op->o_conn->c_conn_state == SLAP_C_INACTIVE - && op->o_protocol > LDAP_VERSION2) + + if (op->o_conn->c_conn_state == SLAP_C_INACTIVE && + op->o_protocol > LDAP_VERSION2) { op->o_conn->c_conn_state = SLAP_C_ACTIVE; } @@ -1674,20 +2051,58 @@ static int connection_op_activate( Operation *op ) connection_init_log_prefix( op ); LDAP_STAILQ_INSERT_TAIL( &op->o_conn->c_ops, op, o_next ); +} + +static int connection_op_activate( Operation *op ) +{ + int rc; + + connection_op_queue( op ); - status = ldap_pvt_thread_pool_submit( &connection_pool, + rc = ldap_pvt_thread_pool_submit( &connection_pool, connection_operation, (void *) op ); - if ( status != 0 ) { + if ( rc != 0 ) { Debug( LDAP_DEBUG_ANY, - "ldap_pvt_thread_pool_submit: failed (%d) for conn=%lu\n", - status, op->o_connid, 0 ); + "connection_op_activate: submit failed (%d) for conn=%lu\n", + rc, op->o_connid, 0 ); /* should move op to pending list */ } - return status; + return rc; } +#ifdef SLAP_LIGHTWEIGHT_DISPATCHER +static int connection_write( ber_socket_t s ); +static void *connection_write_thread( void *ctx, void *arg ) +{ + return (void *)(long)connection_write((long)arg); +} + +int connection_write_activate( ber_socket_t s ) +{ + int rc; + + /* + * suspend reading on this file descriptor until a connection processing + * thread write data on it. Otherwise the listener thread will repeatedly + * submit the same event on it to the pool. + */ + slapd_clr_write( s, 0); + + rc = ldap_pvt_thread_pool_submit( &connection_pool, + connection_write_thread, (void *)(long)s ); + + if( rc != 0 ) { + Debug( LDAP_DEBUG_ANY, + "connection_write_activate(%d): submit failed (%d)\n", + (int) s, rc, 0 ); + } + return rc; +} + +static +#endif int connection_write(ber_socket_t s) { Connection *c; @@ -1695,21 +2110,20 @@ int connection_write(ber_socket_t s) assert( connections != NULL ); - ldap_pvt_thread_mutex_lock( &connections_mutex ); + 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 ); - slapd_remove(s, 1, 0); - ldap_pvt_thread_mutex_unlock( &connections_mutex ); + ldap_pvt_thread_mutex_unlock( MCA_GET_CONN_MUTEX( s ) ); return -1; } +#ifndef SLAP_LIGHTWEIGHT_DISPATCHER slapd_clr_write( s, 0); - +#endif c->c_n_write++; Debug( LDAP_DEBUG_TRACE, @@ -1723,16 +2137,17 @@ int connection_write(ber_socket_t s) if ( ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_NEEDS_WRITE, NULL ) ) { slapd_set_write( s, 1 ); } - /* If there are ops pending because of a writewaiter, start - * one up. + + /* If there are ops pending because of a writewaiter, + * start one up. */ while ((op = LDAP_STAILQ_FIRST( &c->c_pending_ops )) != NULL) { if ( !c->c_writewaiter ) break; - if ( c->c_n_ops_executing > connection_pool_max/2 ) { - break; - } + if ( c->c_n_ops_executing > connection_pool_max/2 ) break; + LDAP_STAILQ_REMOVE_HEAD( &c->c_pending_ops, o_next ); LDAP_STAILQ_NEXT(op, o_next) = NULL; + /* pending operations should not be marked for abandonment */ assert(!op->o_abandon); @@ -1743,8 +2158,9 @@ int connection_write(ber_socket_t s) break; } + connection_return( c ); - ldap_pvt_thread_mutex_unlock( &connections_mutex ); + ldap_pvt_thread_mutex_unlock( MCA_GET_CONN_MUTEX(s) ); return 0; } @@ -1774,7 +2190,7 @@ connection_fake_init( op->o_connid = op->o_conn->c_connid; connection_init_log_prefix( op ); - op->o_time = slap_get_time(); + slap_op_time( &op->o_time, &op->o_tincr ); } void @@ -1784,4 +2200,3 @@ connection_assign_nextid( Connection *conn ) conn->c_connid = conn_nextid++; ldap_pvt_thread_mutex_unlock( &conn_nextid_mutex ); } - diff --git a/servers/slapd/ctxcsn.c b/servers/slapd/ctxcsn.c index 6d29007b58..87d8cbc371 100644 --- a/servers/slapd/ctxcsn.c +++ b/servers/slapd/ctxcsn.c @@ -100,6 +100,9 @@ slap_graduate_commit_csn( Operation *op ) if ( csne->ce_opid == op->o_opid && csne->ce_connid == op->o_connid ) { LDAP_TAILQ_REMOVE( op->o_bd->be_pending_csn_list, csne, ce_csn_link ); + if ( op->o_csn.bv_val == csne->ce_csn.bv_val ) { + BER_BVZERO( &op->o_csn ); + } ch_free( csne->ce_csn.bv_val ); ch_free( csne ); break; @@ -163,6 +166,7 @@ slap_queue_csn( ldap_pvt_thread_mutex_lock( op->o_bd->be_pcl_mutexp ); ber_dupbv( &pending->ce_csn, csn ); + op->o_csn = pending->ce_csn; pending->ce_connid = op->o_connid; pending->ce_opid = op->o_opid; pending->ce_state = SLAP_CSN_PENDING; @@ -174,8 +178,6 @@ slap_queue_csn( int slap_get_csn( Operation *op, - char *csnbuf, - int len, struct berval *csn, int manage_ctxcsn ) { @@ -184,11 +186,10 @@ slap_get_csn( #ifndef HAVE_GMTIME_R ldap_pvt_thread_mutex_lock( &gmtime_mutex ); #endif - csn->bv_len = lutil_csnstr( csnbuf, len, 0, 0 ); + csn->bv_len = lutil_csnstr( csn->bv_val, csn->bv_len, 0, 0 ); #ifndef HAVE_GMTIME_R ldap_pvt_thread_mutex_unlock( &gmtime_mutex ); #endif - csn->bv_val = csnbuf; if ( manage_ctxcsn ) slap_queue_csn( op, csn ); diff --git a/servers/slapd/daemon.c b/servers/slapd/daemon.c index c50db15639..49007b612d 100644 --- a/servers/slapd/daemon.c +++ b/servers/slapd/daemon.c @@ -41,23 +41,23 @@ #include "ldap_rq.h" #if defined(HAVE_SYS_EPOLL_H) && defined(HAVE_EPOLL) -#include +# include #endif #ifdef HAVE_TCPD -#include -#define SLAP_STRING_UNKNOWN STRING_UNKNOWN - +# include int allow_severity = LOG_INFO; int deny_severity = LOG_NOTICE; + +# define SLAP_STRING_UNKNOWN STRING_UNKNOWN #else /* ! TCP Wrappers */ -#define SLAP_STRING_UNKNOWN "unknown" +# define SLAP_STRING_UNKNOWN "unknown" #endif /* ! TCP Wrappers */ #ifdef LDAP_PF_LOCAL -#include +# include /* this should go in as soon as it is accepted */ -#define LDAPI_MOD_URLEXT "x-mod" +# define LDAPI_MOD_URLEXT "x-mod" #endif /* LDAP_PF_LOCAL */ #ifdef LDAP_PF_INET6 @@ -82,15 +82,22 @@ static ber_socket_t wake_sds[2]; static int emfile; static int waking; -#define WAKE_LISTENER(w) do { \ - if ((w) && waking < 5) { waking++; tcp_write( wake_sds[1], "0", 1 ); } \ - } while(0) +#define WAKE_LISTENER(w) do { \ + if ((w) && waking < 5) { \ + waking++; \ + tcp_write( wake_sds[1], "0", 1 ); \ + } \ +} while(0) -volatile sig_atomic_t slapd_shutdown = 0, slapd_gentle_shutdown = 0; +volatile sig_atomic_t slapd_shutdown = 0; +volatile sig_atomic_t slapd_gentle_shutdown = 0; volatile sig_atomic_t slapd_abrupt_shutdown = 0; static struct slap_daemon { ldap_pvt_thread_mutex_t sd_mutex; +#ifdef HAVE_TCPD + ldap_pvt_thread_mutex_t tcpd_mutex; +#endif ber_socket_t sd_nactives; int sd_nwriters; @@ -102,13 +109,11 @@ static struct slap_daemon { int sd_epfd; int sd_nfds; #else - #ifndef HAVE_WINSOCK /* In winsock, accept() returns values higher than dtblsize so don't bother with this optimization */ int sd_nfds; #endif - fd_set sd_actives; fd_set sd_readers; fd_set sd_writers; @@ -116,196 +121,206 @@ static struct slap_daemon { } slap_daemon; #ifdef HAVE_EPOLL -#define SLAP_EVENTS_ARE_INDEXED 0 -#define SLAP_SOCK_IX(s) (slap_daemon.sd_index[s]) -#define SLAP_SOCK_EP(s) (slap_daemon.sd_epolls[SLAP_SOCK_IX(s)]) -#define SLAP_SOCK_EV(s) (SLAP_SOCK_EP(s).events) -#define SLAP_SOCK_IS_ACTIVE(s) (SLAP_SOCK_IX(s) != -1) -#define SLAP_SOCK_NOT_ACTIVE(s) (SLAP_SOCK_IX(s) == -1) -#define SLAP_SOCK_IS_SET(s, mode) (SLAP_SOCK_EV(s) & mode) - -#define SLAP_SOCK_IS_READ(s) SLAP_SOCK_IS_SET(s, EPOLLIN) -#define SLAP_SOCK_IS_WRITE(s) SLAP_SOCK_IS_SET(s, EPOLLOUT) - -#define SLAP_SET_SOCK(s, mode) do { \ - if ((SLAP_SOCK_EV(s) & mode) != mode) { \ - SLAP_SOCK_EV(s) |= mode; \ - epoll_ctl(slap_daemon.sd_epfd, EPOLL_CTL_MOD, s, \ - &SLAP_SOCK_EP(s)); \ - } \ +# define SLAP_EVENTS_ARE_INDEXED 0 +# define SLAP_SOCK_IX(s) (slap_daemon.sd_index[(s)]) +# define SLAP_SOCK_EP(s) (slap_daemon.sd_epolls[SLAP_SOCK_IX(s)]) +# define SLAP_SOCK_EV(s) (SLAP_SOCK_EP(s).events) +# define SLAP_SOCK_IS_ACTIVE(s) (SLAP_SOCK_IX(s) != -1) +# define SLAP_SOCK_NOT_ACTIVE(s) (SLAP_SOCK_IX(s) == -1) +# define SLAP_SOCK_IS_SET(s, mode) (SLAP_SOCK_EV(s) & (mode)) + +# define SLAP_SOCK_IS_READ(s) SLAP_SOCK_IS_SET((s), EPOLLIN) +# define SLAP_SOCK_IS_WRITE(s) SLAP_SOCK_IS_SET((s), EPOLLOUT) + +# define SLAP_SET_SOCK(s, mode) do { \ + if ((SLAP_SOCK_EV(s) & (mode)) != (mode)) { \ + SLAP_SOCK_EV(s) |= (mode); \ + epoll_ctl(slap_daemon.sd_epfd, EPOLL_CTL_MOD, (s), \ + &SLAP_SOCK_EP(s)); \ + } \ } while(0) -#define SLAP_CLR_SOCK(s, mode) do { \ - if ((SLAP_SOCK_EV(s) & mode)) { \ - SLAP_SOCK_EV(s) &= ~mode; \ - epoll_ctl(slap_daemon.sd_epfd, EPOLL_CTL_MOD, s, \ - &SLAP_SOCK_EP(s)); \ - } \ +# define SLAP_CLR_SOCK(s, mode) do { \ + if ((SLAP_SOCK_EV(s) & (mode))) { \ + SLAP_SOCK_EV(s) &= ~(mode); \ + epoll_ctl(slap_daemon.sd_epfd, EPOLL_CTL_MOD, s, \ + &SLAP_SOCK_EP(s)); \ + } \ } while(0) -#define SLAP_SOCK_SET_READ(s) SLAP_SET_SOCK(s, EPOLLIN) -#define SLAP_SOCK_SET_WRITE(s) SLAP_SET_SOCK(s, EPOLLOUT) +# define SLAP_SOCK_SET_READ(s) SLAP_SET_SOCK(s, EPOLLIN) +# define SLAP_SOCK_SET_WRITE(s) SLAP_SET_SOCK(s, EPOLLOUT) -#define SLAP_SOCK_CLR_READ(s) SLAP_CLR_SOCK(s, EPOLLIN) -#define SLAP_SOCK_CLR_WRITE(s) SLAP_CLR_SOCK(s, EPOLLOUT) +# ifdef SLAP_LIGHTWEIGHT_DISPATCHER +# define SLAP_SOCK_SET_SUSPEND(s) \ + ( slap_daemon.sd_suspend[SLAP_SOCK_IX(s)] = 1 ) +# define SLAP_SOCK_CLR_SUSPEND(s) \ + ( slap_daemon.sd_suspend[SLAP_SOCK_IX(s)] = 0 ) +# define SLAP_SOCK_IS_SUSPEND(s) \ + ( slap_daemon.sd_suspend[SLAP_SOCK_IX(s)] == 1 ) +# endif -#define SLAP_CLR_EVENT(i, mode) (revents[i].events &= ~mode) +# define SLAP_SOCK_CLR_READ(s) SLAP_CLR_SOCK((s), EPOLLIN) +# define SLAP_SOCK_CLR_WRITE(s) SLAP_CLR_SOCK((s), EPOLLOUT) +# define SLAP_CLR_EVENT(i, mode) (revents[(i)].events &= ~(mode)) -#define SLAP_EVENT_MAX slap_daemon.sd_nfds +# define SLAP_EVENT_MAX slap_daemon.sd_nfds /* If a Listener address is provided, store that as the epoll data. * Otherwise, store the address of this socket's slot in the * index array. If we can't do this add, the system is out of * resources and we need to shutdown. */ -#define SLAP_ADD_SOCK(s, l) do { \ - int rc; \ - SLAP_SOCK_IX(s) = slap_daemon.sd_nfds; \ - SLAP_SOCK_EP(s).data.ptr = (l) ? (l) : (void *)(&SLAP_SOCK_IX(s)); \ - SLAP_SOCK_EV(s) = EPOLLIN; \ - rc = epoll_ctl(slap_daemon.sd_epfd, EPOLL_CTL_ADD, s, \ - &SLAP_SOCK_EP(s)); \ - if ( rc == 0 ) slap_daemon.sd_nfds++; \ - else { \ - Debug( LDAP_DEBUG_ANY, "daemon: epoll_ctl ADD failed, errno %d, shutting down\n", \ - errno, 0, 0 ); \ - slapd_shutdown = 2; \ - } \ -} while(0) - -#define SLAP_EV_LISTENER(ptr) (((int *)(ptr) >= slap_daemon.sd_index && \ - (int *)(ptr) <= (slap_daemon.sd_index+dtblsize)) ? 0 : 1) - -#define SLAP_EV_PTRFD(ptr) (SLAP_EV_LISTENER(ptr) ? \ - ((Listener *)ptr)->sl_sd : (int *)(ptr) - slap_daemon.sd_index) - -#define SLAP_DEL_SOCK(s) do { \ - int fd, rc, index = SLAP_SOCK_IX(s); \ - rc = epoll_ctl(slap_daemon.sd_epfd, EPOLL_CTL_DEL, s, \ - &SLAP_SOCK_EP(s)); \ - slap_daemon.sd_epolls[index] = slap_daemon.sd_epolls[slap_daemon.sd_nfds-1]; \ - fd = SLAP_EV_PTRFD(slap_daemon.sd_epolls[index].data.ptr); \ - slap_daemon.sd_index[fd] = index; \ - slap_daemon.sd_index[s] = -1; \ - slap_daemon.sd_nfds--; \ -} while(0) - -#define SLAP_EVENT_CLR_READ(i) SLAP_CLR_EVENT(i, EPOLLIN) -#define SLAP_EVENT_CLR_WRITE(i) SLAP_CLR_EVENT(i, EPOLLOUT) - -#define SLAP_CHK_EVENT(i, mode) (revents[i].events & mode) - -#define SLAP_EVENT_IS_READ(i) SLAP_CHK_EVENT(i, EPOLLIN) -#define SLAP_EVENT_IS_WRITE(i) SLAP_CHK_EVENT(i, EPOLLOUT) -#define SLAP_EVENT_IS_LISTENER(i) SLAP_EV_LISTENER(revents[i].data.ptr) -#define SLAP_EVENT_LISTENER(i) (revents[i].data.ptr) - -#define SLAP_EVENT_FD(i) SLAP_EV_PTRFD(revents[i].data.ptr) -#define SLAP_SOCK_SET_MUTE(s) SLAP_SOCK_CLR_READ(s) -#define SLAP_SOCK_CLR_MUTE(s) SLAP_SOCK_SET_READ(s) -#define SLAP_SOCK_IS_MUTE(s) (!SLAP_SOCK_IS_READ(s)) - -#define SLAP_SOCK_SET_INIT \ - slap_daemon.sd_epolls = ch_calloc(1, sizeof(struct epoll_event) * dtblsize * 2); \ - slap_daemon.sd_index = ch_malloc(sizeof(int) * dtblsize); \ - slap_daemon.sd_epfd = epoll_create( dtblsize ); \ - for (i=0; itv_sec * 1000 : -1 ) +# define SLAP_ADD_SOCK(s, l) do { \ + int rc; \ + SLAP_SOCK_IX((s)) = slap_daemon.sd_nfds; \ + SLAP_SOCK_EP((s)).data.ptr = (l) ? (l) : (void *)(&SLAP_SOCK_IX(s)); \ + SLAP_SOCK_EV((s)) = EPOLLIN; \ + rc = epoll_ctl(slap_daemon.sd_epfd, EPOLL_CTL_ADD, \ + (s), &SLAP_SOCK_EP((s))); \ + if ( rc == 0 ) { \ + slap_daemon.sd_nfds++; \ + } else { \ + Debug( LDAP_DEBUG_ANY, \ + "daemon: epoll_ctl(ADD,fd=%d) failed, errno=%d, shutting down\n", \ + s, errno, 0 ); \ + slapd_shutdown = 2; \ + } \ +} while (0) + +# define SLAP_EV_LISTENER(ptr) (((int *)(ptr) >= slap_daemon.sd_index && \ + (int *)(ptr) <= (slap_daemon.sd_index+dtblsize)) ? 0 : 1 ) + +# define SLAP_EV_PTRFD(ptr) (SLAP_EV_LISTENER(ptr) ? \ + ((Listener *)ptr)->sl_sd : (int *)(ptr) - slap_daemon.sd_index) + +# define SLAP_DEL_SOCK(s) do { \ + int fd, rc, index = SLAP_SOCK_IX((s)); \ + if ( index < 0 ) break; \ + rc = epoll_ctl(slap_daemon.sd_epfd, EPOLL_CTL_DEL, \ + (s), &SLAP_SOCK_EP((s))); \ + slap_daemon.sd_epolls[index] = \ + slap_daemon.sd_epolls[slap_daemon.sd_nfds-1]; \ + fd = SLAP_EV_PTRFD(slap_daemon.sd_epolls[index].data.ptr); \ + slap_daemon.sd_index[fd] = index; \ + slap_daemon.sd_index[(s)] = -1; \ + slap_daemon.sd_nfds--; \ +} while (0) + +# define SLAP_EVENT_CLR_READ(i) SLAP_CLR_EVENT((i), EPOLLIN) +# define SLAP_EVENT_CLR_WRITE(i) SLAP_CLR_EVENT((i), EPOLLOUT) + +# define SLAP_CHK_EVENT(i, mode) (revents[(i)].events & mode) + +# define SLAP_EVENT_IS_READ(i) SLAP_CHK_EVENT((i), EPOLLIN) +# define SLAP_EVENT_IS_WRITE(i) SLAP_CHK_EVENT((i), EPOLLOUT) +# define SLAP_EVENT_IS_LISTENER(i) SLAP_EV_LISTENER(revents[(i)].data.ptr) +# define SLAP_EVENT_LISTENER(i) (revents[(i)].data.ptr) + +# define SLAP_EVENT_FD(i) SLAP_EV_PTRFD(revents[(i)].data.ptr) + +# define SLAP_SOCK_SET_INIT do { \ + slap_daemon.sd_epolls = ch_calloc(1, \ + sizeof(struct epoll_event) * dtblsize * 2); \ + slap_daemon.sd_index = ch_malloc(sizeof(int) * dtblsize); \ + slap_daemon.sd_epfd = epoll_create( dtblsize ); \ + for (i=0; itv_sec * 1000 : -1 ) #else - /* select */ -#define SLAP_EVENTS_ARE_INDEXED 1 -#define SLAP_EVENT_DECL \ + +# define SLAP_EVENTS_ARE_INDEXED 1 +# define SLAP_EVENT_DECL \ fd_set readfds, writefds -#define SLAP_EVENT_INIT \ +# define SLAP_EVENT_INIT do { \ AC_MEMCPY( &readfds, &slap_daemon.sd_readers, sizeof(fd_set) ); \ - if ( nwriters ) \ + if ( nwriters ) { \ AC_MEMCPY( &writefds, &slap_daemon.sd_writers, sizeof(fd_set) ); \ - else \ - FD_ZERO( &writefds ) - -#ifdef FD_SETSIZE -#define CHK_SETSIZE \ - if (dtblsize > FD_SETSIZE) dtblsize = FD_SETSIZE -#else -#define CHK_SETSIZE -#endif - -#define SLAP_SOCK_SET_INIT \ - CHK_SETSIZE; \ - FD_ZERO(&slap_daemon.sd_readers); \ - FD_ZERO(&slap_daemon.sd_writers) - -#define SLAP_SOCK_IS_ACTIVE(fd) FD_ISSET(fd, &slap_daemon.sd_actives) - -#define SLAP_SOCK_IS_READ(fd) FD_ISSET(fd, &slap_daemon.sd_readers) -#define SLAP_SOCK_IS_WRITE(fd) FD_ISSET(fd, &slap_daemon.sd_writers) - -#define SLAP_SOCK_NOT_ACTIVE(fd) (!SLAP_SOCK_IS_ACTIVE(fd) && \ + } else { \ + FD_ZERO( &writefds ); \ + } \ +} while (0) + +# ifdef FD_SETSIZE +# define CHK_SETSIZE do { \ + if (dtblsize > FD_SETSIZE) dtblsize = FD_SETSIZE; \ +} while (0) +# else +# define CHK_SETSIZE do { ; } while (0) +# endif + +# define SLAP_SOCK_SET_INIT do { \ + CHK_SETSIZE; \ + FD_ZERO(&slap_daemon.sd_readers); \ + FD_ZERO(&slap_daemon.sd_writers); \ +} while (0) + +# define SLAP_SOCK_IS_ACTIVE(fd) FD_ISSET((fd), &slap_daemon.sd_actives) +# define SLAP_SOCK_IS_READ(fd) FD_ISSET((fd), &slap_daemon.sd_readers) +# define SLAP_SOCK_IS_WRITE(fd) FD_ISSET((fd), &slap_daemon.sd_writers) + +# define SLAP_SOCK_NOT_ACTIVE(fd) (!SLAP_SOCK_IS_ACTIVE(fd) && \ !SLAP_SOCK_IS_READ(fd) && !SLAP_SOCK_IS_WRITE(fd)) -#ifdef HAVE_WINSOCK -#define SLAP_SOCK_SET_READ(fd) do { \ - if (!SLAP_SOCK_IS_READ(fd)) {FD_SET(fd, &slap_daemon.sd_readers);} \ +# ifdef HAVE_WINSOCK +# define SLAP_SOCK_SET_READ(fd) do { \ + if (!SLAP_SOCK_IS_READ(fd)) { FD_SET((fd), &slap_daemon.sd_readers); } \ } while(0) -#define SLAP_SOCK_SET_WRITE(fd) do { \ - if (!SLAP_SOCK_IS_WRITE(fd)) {FD_SET(fd, &slap_daemon.sd_writers);} \ +# define SLAP_SOCK_SET_WRITE(fd) do { \ + if (!SLAP_SOCK_IS_WRITE(fd)) { FD_SET((fd), &slap_daemon.sd_writers); } \ } while(0) -#define SLAP_ADDTEST(s) -#define SLAP_EVENT_MAX dtblsize -#else -#define SLAP_SOCK_SET_READ(fd) FD_SET(fd, &slap_daemon.sd_readers) -#define SLAP_SOCK_SET_WRITE(fd) FD_SET(fd, &slap_daemon.sd_writers) - -#define SLAP_EVENT_MAX slap_daemon.sd_nfds -#define SLAP_ADDTEST(s) if (s >= slap_daemon.sd_nfds) slap_daemon.sd_nfds = s+1 -#endif - -#define SLAP_SOCK_CLR_READ(fd) FD_CLR(fd, &slap_daemon.sd_readers) -#define SLAP_SOCK_CLR_WRITE(fd) FD_CLR(fd, &slap_daemon.sd_writers) - -#define SLAP_ADD_SOCK(s, l) do { \ - SLAP_ADDTEST(s); \ - FD_SET(s, &slap_daemon.sd_actives); \ - FD_SET(s, &slap_daemon.sd_readers); \ +# define SLAP_ADDTEST(s) do { } while 0 +# define SLAP_EVENT_MAX dtblsize +# else +# define SLAP_SOCK_SET_READ(fd) FD_SET((fd), &slap_daemon.sd_readers) +# define SLAP_SOCK_SET_WRITE(fd) FD_SET((fd), &slap_daemon.sd_writers) + +# define SLAP_EVENT_MAX slap_daemon.sd_nfds +# define SLAP_ADDTEST(s) do { \ + if ((s) >= slap_daemon.sd_nfds) slap_daemon.sd_nfds = (s)+1; \ +} while (0) +# endif + +# define SLAP_SOCK_CLR_READ(fd) FD_CLR((fd), &slap_daemon.sd_readers) +# define SLAP_SOCK_CLR_WRITE(fd) FD_CLR((fd), &slap_daemon.sd_writers) + +# define SLAP_ADD_SOCK(s, l) do { \ + SLAP_ADDTEST((s)); \ + FD_SET((s), &slap_daemon.sd_actives); \ + FD_SET((s), &slap_daemon.sd_readers); \ } while(0) -#define SLAP_DEL_SOCK(s) do { \ - FD_CLR(s, &slap_daemon.sd_actives); \ - FD_CLR(s, &slap_daemon.sd_readers); \ - FD_CLR(s, &slap_daemon.sd_writers); \ +# define SLAP_DEL_SOCK(s) do { \ + FD_CLR((s), &slap_daemon.sd_actives); \ + FD_CLR((s), &slap_daemon.sd_readers); \ + FD_CLR((s), &slap_daemon.sd_writers); \ } while(0) -#define SLAP_EVENT_IS_READ(fd) FD_ISSET(fd, &readfds) -#define SLAP_EVENT_IS_WRITE(fd) FD_ISSET(fd, &writefds) - -#define SLAP_EVENT_CLR_READ(fd) FD_CLR(fd, &readfds) -#define SLAP_EVENT_CLR_WRITE(fd) FD_CLR(fd, &writefds) +# define SLAP_EVENT_IS_READ(fd) FD_ISSET((fd), &readfds) +# define SLAP_EVENT_IS_WRITE(fd) FD_ISSET((fd), &writefds) -#define SLAP_EVENT_WAIT(tvp) \ - select( SLAP_EVENT_MAX, &readfds, \ - nwriters > 0 ? &writefds : NULL, NULL, tvp ) - -#define SLAP_SOCK_SET_MUTE(s) FD_CLR(s, &readfds) -#define SLAP_SOCK_CLR_MUTE(s) FD_SET(s, &readfds) -#define SLAP_SOCK_IS_MUTE(s) (!FD_ISSET(s, &readfds)) +# define SLAP_EVENT_CLR_READ(fd) FD_CLR((fd), &readfds) +# define SLAP_EVENT_CLR_WRITE(fd) FD_CLR((fd), &writefds) +# define SLAP_EVENT_WAIT(tvp) \ + select( SLAP_EVENT_MAX, &readfds, \ + nwriters > 0 ? &writefds : NULL, NULL, (tvp) ) #endif - #ifdef HAVE_SLP /* * SLP related functions @@ -426,32 +441,57 @@ static void slapd_add(ber_socket_t s, int isactive, Listener *sl) { assert( SLAP_SOCK_NOT_ACTIVE(s) ); - if ( isactive ) { - slap_daemon.sd_nactives++; - } + if ( isactive ) slap_daemon.sd_nactives++; SLAP_ADD_SOCK(s, sl); Debug( LDAP_DEBUG_CONNS, "daemon: added %ldr\n", (long) s, 0, 0 ); + + ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex ); + +#ifdef SLAP_LIGHTWEIGHT_DISPATCHER + WAKE_LISTENER(1); +#endif +} + +void slapd_sd_lock() +{ + ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex ); +} + +void slapd_sd_unlock() +{ ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex ); } /* * Remove the descriptor from daemon control */ -void slapd_remove(ber_socket_t s, int wasactive, int wake) { +void slapd_remove( + ber_socket_t s, + int wasactive, + int wake, + int locked ) +{ int waswriter; - ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex ); + int wasreader; + + if ( !locked ) + ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex ); + + assert( SLAP_SOCK_IS_ACTIVE( s )); + + if ( wasactive ) slap_daemon.sd_nactives--; - if ( wasactive ) { - slap_daemon.sd_nactives--; - } waswriter = SLAP_SOCK_IS_WRITE(s); + wasreader = SLAP_SOCK_IS_READ(s); Debug( LDAP_DEBUG_CONNS, "daemon: removing %ld%s%s\n", - (long) s, SLAP_SOCK_IS_READ(s) ? "r" : "", + (long) s, + wasreader ? "r" : "", waswriter ? "w" : "" ); + if ( waswriter ) slap_daemon.sd_nwriters--; SLAP_DEL_SOCK(s); @@ -463,20 +503,20 @@ void slapd_remove(ber_socket_t s, int wasactive, int wake) { if ( emfile ) { int i; for ( i = 0; slap_listeners[i] != NULL; i++ ) { - if ( slap_listeners[i]->sl_sd != AC_SOCKET_INVALID ) { - if ( slap_listeners[i]->sl_sd == s ) continue; - if ( slap_listeners[i]->sl_is_mute ) { - slap_listeners[i]->sl_is_mute = 0; - emfile--; - break; - } + Listener *lr = slap_listeners[i]; + + if ( lr->sl_sd == AC_SOCKET_INVALID ) continue; + if ( lr->sl_sd == s ) continue; + if ( lr->sl_mute ) { + lr->sl_mute = 0; + emfile--; + break; } } /* Walked the entire list without enabling anything; emfile * counter is stale. Reset it. */ - if ( slap_listeners[i] == NULL ) - emfile = 0; + if ( slap_listeners[i] == NULL ) emfile = 0; } ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex ); WAKE_LISTENER(wake || slapd_gentle_shutdown == 2); @@ -486,6 +526,7 @@ void slapd_clr_write(ber_socket_t s, int wake) { ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex ); assert( SLAP_SOCK_IS_ACTIVE( s )); + if ( SLAP_SOCK_IS_WRITE( s )) { SLAP_SOCK_CLR_WRITE( s ); slap_daemon.sd_nwriters--; @@ -499,6 +540,7 @@ void slapd_set_write(ber_socket_t s, int wake) { ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex ); assert( SLAP_SOCK_IS_ACTIVE( s )); + if ( !SLAP_SOCK_IS_WRITE( s )) { SLAP_SOCK_SET_WRITE( s ); slap_daemon.sd_nwriters++; @@ -508,22 +550,25 @@ void slapd_set_write(ber_socket_t s, int wake) { WAKE_LISTENER(wake); } -void slapd_clr_read(ber_socket_t s, int wake) { +int slapd_clr_read(ber_socket_t s, int wake) { + int rc = 1; ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex ); - assert( SLAP_SOCK_IS_ACTIVE( s )); - SLAP_SOCK_CLR_READ( s ); - + if ( SLAP_SOCK_IS_ACTIVE( s )) { + SLAP_SOCK_CLR_READ( s ); + rc = 0; + } ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex ); - WAKE_LISTENER(wake); + if ( !rc ) + WAKE_LISTENER(wake); + return rc; } void slapd_set_read(ber_socket_t s, int wake) { ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex ); assert( SLAP_SOCK_IS_ACTIVE( s )); - if (!SLAP_SOCK_IS_READ( s )) - SLAP_SOCK_SET_READ( s ); + if (!SLAP_SOCK_IS_READ( s )) SLAP_SOCK_SET_READ( s ); ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex ); WAKE_LISTENER(wake); @@ -535,18 +580,10 @@ static void slapd_close(ber_socket_t s) { tcp_close(s); } -static void slap_free_listener_addresses(struct sockaddr **sal) -{ +static void slap_free_listener_addresses(struct sockaddr **sal) { struct sockaddr **sap; - - if (sal == NULL) { - return; - } - - for (sap = sal; *sap != NULL; sap++) { - ch_free(*sap); - } - + if (sal == NULL) return; + for (sap = sal; *sap != NULL; sap++) ch_free(*sap); ch_free(sal); } @@ -572,18 +609,17 @@ static int get_url_perms( type++; } - if ( strncasecmp( type, LDAPI_MOD_URLEXT "=", sizeof(LDAPI_MOD_URLEXT "=") - 1 ) == 0 ) { - char *value = type - + ( sizeof(LDAPI_MOD_URLEXT "=") - 1 ); - mode_t p = 0; - int j; + if ( strncasecmp( type, LDAPI_MOD_URLEXT "=", + sizeof(LDAPI_MOD_URLEXT "=") - 1 ) == 0 ) + { + char *value = type + ( sizeof(LDAPI_MOD_URLEXT "=") - 1 ); + mode_t p = 0; + int j; switch (strlen(value)) { case 4: /* skip leading '0' */ - if ( value[ 0 ] != '0' ) { - return LDAP_OTHER; - } + if ( value[ 0 ] != '0' ) return LDAP_OTHER; value++; case 3: @@ -592,9 +628,7 @@ static int get_url_perms( v = value[ j ] - '0'; - if ( v < 0 || v > 7 ) { - return LDAP_OTHER; - } + if ( v < 0 || v > 7 ) return LDAP_OTHER; p |= v << 3*(2-j); } @@ -644,21 +678,19 @@ static int slap_get_listener_addresses( #ifdef LDAP_PF_LOCAL if ( port == 0 ) { *sal = ch_malloc(2 * sizeof(void *)); - if (*sal == NULL) { - return -1; - } + if (*sal == NULL) return -1; sap = *sal; *sap = ch_malloc(sizeof(struct sockaddr_un)); - if (*sap == NULL) - goto errexit; + if (*sap == NULL) goto errexit; sap[1] = NULL; if ( strlen(host) > - (sizeof(((struct sockaddr_un *)*sap)->sun_path) - 1) ) { + (sizeof(((struct sockaddr_un *)*sap)->sun_path) - 1) ) + { Debug( LDAP_DEBUG_ANY, - "daemon: domain socket path (%s) too long in URL", - host, 0, 0); + "daemon: domain socket path (%s) too long in URL", + host, 0, 0); goto errexit; } @@ -680,7 +712,7 @@ static int slap_get_listener_addresses( snprintf(serv, sizeof serv, "%d", port); if ( (err = getaddrinfo(host, serv, &hints, &res)) ) { - Debug( LDAP_DEBUG_ANY, "daemon: getaddrinfo failed: %s\n", + Debug( LDAP_DEBUG_ANY, "daemon: getaddrinfo() failed: %s\n", AC_GAI_STRERROR(err), 0, 0); return -1; } @@ -690,9 +722,7 @@ static int slap_get_listener_addresses( /* EMPTY */ ; } *sal = ch_calloc(n, sizeof(void *)); - if (*sal == NULL) { - return -1; - } + if (*sal == NULL) return -1; sap = *sal; *sap = NULL; @@ -739,6 +769,7 @@ static int slap_get_listener_addresses( } freeaddrinfo(res); + #else int i, n = 1; struct in_addr in; @@ -751,31 +782,25 @@ static int slap_get_listener_addresses( he = gethostbyname( host ); if( he == NULL ) { Debug( LDAP_DEBUG_ANY, - "daemon: invalid host %s", host, 0, 0); + "daemon: invalid host %s", host, 0, 0); return -1; } - for (n = 0; he->h_addr_list[n]; n++) ; + for (n = 0; he->h_addr_list[n]; n++) /* empty */; } *sal = ch_malloc((n+1) * sizeof(void *)); - if (*sal == NULL) { - return -1; - } + if (*sal == NULL) return -1; sap = *sal; for ( i = 0; isa_family = AF_INET; ((struct sockaddr_in *)sap[i])->sin_port = htons(port); - if (he) { - AC_MEMCPY( &((struct sockaddr_in *)sap[i])->sin_addr, he->h_addr_list[i], sizeof(struct in_addr) ); - } else { - AC_MEMCPY( &((struct sockaddr_in *)sap[i])->sin_addr, &in, sizeof(struct in_addr) ); - } + AC_MEMCPY( &((struct sockaddr_in *)sap[i])->sin_addr, + he ? he->h_addr_list[i] : &in, sizeof(struct in_addr) ); } sap[i] = NULL; #endif @@ -820,20 +845,20 @@ static int slap_open_listener( } l.sl_url.bv_val = NULL; - l.sl_is_mute = 0; + l.sl_mute = 0; +#ifdef SLAP_LIGHTWEIGHT_DISPATCHER + l.sl_busy = 0; +#endif #ifndef HAVE_TLS if( ldap_pvt_url_scheme2tls( lud->lud_scheme ) ) { - Debug( LDAP_DEBUG_ANY, - "daemon: TLS not supported (%s)\n", + Debug( LDAP_DEBUG_ANY, "daemon: TLS not supported (%s)\n", url, 0, 0 ); ldap_free_urldesc( lud ); return -1; } - if(! lud->lud_port ) { - lud->lud_port = LDAP_PORT; - } + if(! lud->lud_port ) lud->lud_port = LDAP_PORT; #else l.sl_is_tls = ldap_pvt_url_scheme2tls( lud->lud_scheme ); @@ -869,6 +894,7 @@ static int slap_open_listener( err = slap_get_listener_addresses(lud->lud_host, port, &sal); } } + #ifdef LDAP_CONNECTIONLESS l.sl_is_udp = ( tmp == LDAP_PROTO_UDP ); #endif @@ -882,17 +908,16 @@ static int slap_open_listener( #endif /* LDAP_PF_LOCAL || SLAP_X_LISTENER_MOD */ ldap_free_urldesc( lud ); - if ( err ) { - return -1; - } + if ( err ) return -1; /* If we got more than one address returned, we need to make space * for it in the slap_listeners array. */ - for ( num=0; sal[num]; num++ ); + for ( num=0; sal[num]; num++ ) /* empty */; if ( num > 1 ) { *listeners += num-1; - slap_listeners = ch_realloc( slap_listeners, (*listeners + 1) * sizeof(Listener *) ); + slap_listeners = ch_realloc( slap_listeners, + (*listeners + 1) * sizeof(Listener *) ); } psal = sal; @@ -916,9 +941,11 @@ static int slap_open_listener( sal++; continue; } + #ifdef LDAP_CONNECTIONLESS if( l.sl_is_udp ) socktype = SOCK_DGRAM; #endif + l.sl_sd = socket( (*sal)->sa_family, socktype, 0); if ( l.sl_sd == AC_SOCKET_INVALID ) { int err = sock_errno(); @@ -928,6 +955,7 @@ static int slap_open_listener( sal++; continue; } + #ifndef HAVE_WINSOCK if ( l.sl_sd >= dtblsize ) { Debug( LDAP_DEBUG_ANY, @@ -938,9 +966,10 @@ static int slap_open_listener( continue; } #endif + #ifdef LDAP_PF_LOCAL if ( (*sal)->sa_family == AF_LOCAL ) { - unlink ( ((struct sockaddr_un *)*sal)->sun_path ); + unlink( ((struct sockaddr_un *)*sal)->sun_path ); } else #endif { @@ -951,9 +980,9 @@ static int slap_open_listener( (char *) &tmp, sizeof(tmp) ); if ( rc == AC_SOCKET_ERROR ) { int err = sock_errno(); - Debug( LDAP_DEBUG_ANY, - "slapd(%ld): setsockopt(SO_REUSEADDR) failed errno=%d (%s)\n", - (long) l.sl_sd, err, sock_errstr(err) ); + Debug( LDAP_DEBUG_ANY, "slapd(%ld): " + "setsockopt(SO_REUSEADDR) failed errno=%d (%s)\n", + (long) l.sl_sd, err, sock_errstr(err) ); } #endif } @@ -968,17 +997,18 @@ static int slap_open_listener( /* Try to use IPv6 sockets for IPv6 only */ tmp = 1; rc = setsockopt( l.sl_sd, IPPROTO_IPV6, IPV6_V6ONLY, - (char *) &tmp, sizeof(tmp) ); + (char *) &tmp, sizeof(tmp) ); if ( rc == AC_SOCKET_ERROR ) { int err = sock_errno(); - Debug( LDAP_DEBUG_ANY, - "slapd(%ld): setsockopt(IPV6_V6ONLY) failed errno=%d (%s)\n", - (long) l.sl_sd, err, sock_errstr(err) ); + Debug( LDAP_DEBUG_ANY, "slapd(%ld): " + "setsockopt(IPV6_V6ONLY) failed errno=%d (%s)\n", + (long) l.sl_sd, err, sock_errstr(err) ); } #endif addrlen = sizeof(struct sockaddr_in6); break; #endif + #ifdef LDAP_PF_LOCAL case AF_LOCAL: #ifdef LOCAL_CREDS @@ -994,82 +1024,97 @@ static int slap_open_listener( if (bind(l.sl_sd, *sal, addrlen)) { err = sock_errno(); - Debug( LDAP_DEBUG_ANY, "daemon: bind(%ld) failed errno=%d (%s)\n", - (long) l.sl_sd, err, sock_errstr(err) ); + Debug( LDAP_DEBUG_ANY, + "daemon: bind(%ld) failed errno=%d (%s)\n", + (long) l.sl_sd, err, sock_errstr(err) ); tcp_close( l.sl_sd ); sal++; continue; } - switch ( (*sal)->sa_family ) { + switch ( (*sal)->sa_family ) { #ifdef LDAP_PF_LOCAL - case AF_LOCAL: { - char *addr = ((struct sockaddr_un *)*sal)->sun_path; - l.sl_name.bv_len = strlen(addr) + sizeof("PATH=") - 1; - l.sl_name.bv_val = ber_memalloc( l.sl_name.bv_len + 1 ); - snprintf( l.sl_name.bv_val, l.sl_name.bv_len + 1, + case AF_LOCAL: { + char *addr = ((struct sockaddr_un *)*sal)->sun_path; + l.sl_name.bv_len = strlen(addr) + sizeof("PATH=") - 1; + l.sl_name.bv_val = ber_memalloc( l.sl_name.bv_len + 1 ); + snprintf( l.sl_name.bv_val, l.sl_name.bv_len + 1, "PATH=%s", addr ); - } break; + } break; #endif /* LDAP_PF_LOCAL */ - case AF_INET: { - char *s; + case AF_INET: { + char *s; #if defined( HAVE_GETADDRINFO ) && defined( HAVE_INET_NTOP ) - char addr[INET_ADDRSTRLEN]; - inet_ntop( AF_INET, &((struct sockaddr_in *)*sal)->sin_addr, - addr, sizeof(addr) ); - s = addr; + char addr[INET_ADDRSTRLEN]; + inet_ntop( AF_INET, &((struct sockaddr_in *)*sal)->sin_addr, + addr, sizeof(addr) ); + s = addr; #else - s = inet_ntoa( ((struct sockaddr_in *) *sal)->sin_addr ); + s = inet_ntoa( ((struct sockaddr_in *) *sal)->sin_addr ); #endif - port = ntohs( ((struct sockaddr_in *)*sal) ->sin_port ); - l.sl_name.bv_val = ber_memalloc( sizeof("IP=255.255.255.255:65535") ); - snprintf( l.sl_name.bv_val, sizeof("IP=255.255.255.255:65535"), - "IP=%s:%d", - s != NULL ? s : SLAP_STRING_UNKNOWN, port ); - l.sl_name.bv_len = strlen( l.sl_name.bv_val ); - } break; + port = ntohs( ((struct sockaddr_in *)*sal) ->sin_port ); + l.sl_name.bv_val = + ber_memalloc( sizeof("IP=255.255.255.255:65535") ); + snprintf( l.sl_name.bv_val, sizeof("IP=255.255.255.255:65535"), + "IP=%s:%d", + s != NULL ? s : SLAP_STRING_UNKNOWN, port ); + l.sl_name.bv_len = strlen( l.sl_name.bv_val ); + } break; #ifdef LDAP_PF_INET6 - case AF_INET6: { - char addr[INET6_ADDRSTRLEN]; - inet_ntop( AF_INET6, &((struct sockaddr_in6 *)*sal)->sin6_addr, - addr, sizeof addr); - port = ntohs( ((struct sockaddr_in6 *)*sal)->sin6_port ); - l.sl_name.bv_len = strlen(addr) + sizeof("IP= 65535"); - l.sl_name.bv_val = ber_memalloc( l.sl_name.bv_len ); - snprintf( l.sl_name.bv_val, l.sl_name.bv_len, "IP=%s %d", + case AF_INET6: { + char addr[INET6_ADDRSTRLEN]; + inet_ntop( AF_INET6, &((struct sockaddr_in6 *)*sal)->sin6_addr, + addr, sizeof addr); + port = ntohs( ((struct sockaddr_in6 *)*sal)->sin6_port ); + l.sl_name.bv_len = strlen(addr) + sizeof("IP= 65535"); + l.sl_name.bv_val = ber_memalloc( l.sl_name.bv_len ); + snprintf( l.sl_name.bv_val, l.sl_name.bv_len, "IP=%s %d", addr, port ); - l.sl_name.bv_len = strlen( l.sl_name.bv_val ); - } break; + l.sl_name.bv_len = strlen( l.sl_name.bv_val ); + } break; #endif /* LDAP_PF_INET6 */ - default: - Debug( LDAP_DEBUG_ANY, "daemon: unsupported address family (%d)\n", - (int) (*sal)->sa_family, 0, 0 ); - break; - } - - AC_MEMCPY(&l.sl_sa, *sal, addrlen); - ber_str2bv( url, 0, 1, &l.sl_url); - li = ch_malloc( sizeof( Listener ) ); - *li = l; - slap_listeners[*cur] = li; - (*cur)++; - sal++; + default: + Debug( LDAP_DEBUG_ANY, "daemon: unsupported address family (%d)\n", + (int) (*sal)->sa_family, 0, 0 ); + break; + } - } /* while ( *sal != NULL ) */ + AC_MEMCPY(&l.sl_sa, *sal, addrlen); + ber_str2bv( url, 0, 1, &l.sl_url); + li = ch_malloc( sizeof( Listener ) ); + *li = l; + slap_listeners[*cur] = li; + (*cur)++; + sal++; + } slap_free_listener_addresses(psal); - if ( l.sl_url.bv_val == NULL ) - { + if ( l.sl_url.bv_val == NULL ) { Debug( LDAP_DEBUG_TRACE, "slap_open_listener: failed on %s\n", url, 0, 0 ); return -1; } - Debug( LDAP_DEBUG_TRACE, "daemon: initialized %s\n", +#ifdef LDAP_CONNECTIONLESS + if( l.sl_is_udp ) { + long id = connection_init( l.sl_sd, &l, "", "", CONN_IS_UDP, + (slap_ssf_t) 0, NULL ); + + if( id < 0 ) { + Debug( LDAP_DEBUG_TRACE, + "slap_open_listener: connectionless init failed on %s (%d)\n", + url, l.sl_sd, 0 ); + return -1; + } + l.sl_is_udp++; + } +#endif + + Debug( LDAP_DEBUG_TRACE, "daemon: listener initialized %s\n", l.sl_url.bv_val, 0, 0 ); return 0; } @@ -1084,9 +1129,7 @@ int slapd_daemon_init( const char *urls ) Debug( LDAP_DEBUG_ARGS, "daemon_init: %s\n", urls ? urls : "", 0, 0 ); - if( (rc = sockinit()) != 0 ) { - return rc; - } + if( (rc = sockinit()) != 0 ) return rc; #ifdef HAVE_SYSCONF dtblsize = sysconf( _SC_OPEN_MAX ); @@ -1109,9 +1152,7 @@ int slapd_daemon_init( const char *urls ) SLAP_SOCK_SET_INIT; - if( urls == NULL ) { - urls = "ldap:///"; - } + if( urls == NULL ) urls = "ldap:///"; u = ldap_str2charray( urls, " " ); @@ -1148,6 +1189,7 @@ int slapd_daemon_init( const char *urls ) Debug( LDAP_DEBUG_TRACE, "daemon_init: %d listeners opened\n", i, 0, 0 ); + #ifdef HAVE_SLP if( slapd_register_slp ) { slapd_slp_init( urls ); @@ -1157,6 +1199,11 @@ int slapd_daemon_init( const char *urls ) ldap_charray_free( u ); ldap_pvt_thread_mutex_init( &slap_daemon.sd_mutex ); + +#ifdef HAVE_TCPD + ldap_pvt_thread_mutex_init( &slap_daemon.tcpd_mutex ); +#endif + return !i; } @@ -1176,41 +1223,52 @@ slapd_daemon_destroy(void) } #endif +#ifdef HAVE_TCPD + ldap_pvt_thread_mutex_destroy( &slap_daemon.tcpd_mutex ); +#endif + + ldap_pvt_thread_mutex_destroy( &slap_daemon.sd_mutex ); return 0; } static void close_listeners( - int remove -) + int remove ) { int l; for ( l = 0; slap_listeners[l] != NULL; l++ ) { - if ( slap_listeners[l]->sl_sd != AC_SOCKET_INVALID ) { - if ( remove ) - slapd_remove( slap_listeners[l]->sl_sd, 0, 0 ); + Listener *lr = slap_listeners[l]; + + if ( lr->sl_sd != AC_SOCKET_INVALID ) { + if ( remove ) slapd_remove( lr->sl_sd, 0, 0, 0 ); + #ifdef LDAP_PF_LOCAL - if ( slap_listeners[l]->sl_sa.sa_addr.sa_family == AF_LOCAL ) { - unlink( slap_listeners[l]->sl_sa.sa_un_addr.sun_path ); + if ( lr->sl_sa.sa_addr.sa_family == AF_LOCAL ) { + unlink( lr->sl_sa.sa_un_addr.sun_path ); } #endif /* LDAP_PF_LOCAL */ - slapd_close( slap_listeners[l]->sl_sd ); + + slapd_close( lr->sl_sd ); } - if ( slap_listeners[l]->sl_url.bv_val ) - ber_memfree( slap_listeners[l]->sl_url.bv_val ); - if ( slap_listeners[l]->sl_name.bv_val ) - ber_memfree( slap_listeners[l]->sl_name.bv_val ); - free ( slap_listeners[l] ); + + if ( lr->sl_url.bv_val ) { + ber_memfree( lr->sl_url.bv_val ); + } + + if ( lr->sl_name.bv_val ) { + ber_memfree( lr->sl_name.bv_val ); + } + + free( lr ); slap_listeners[l] = NULL; } } static int -slapd_handle_listener( - Listener *sl -) +slap_listener( + Listener *sl ) { Sockaddr from; @@ -1236,18 +1294,7 @@ slapd_handle_listener( peername[0] = '\0'; #ifdef LDAP_CONNECTIONLESS - if ( sl->sl_is_udp ) { - /* The first time we receive a query, we set this - * up as a "connection". It remains open for the life - * of the slapd. - */ - if ( sl->sl_is_udp < 2 ) { - id = connection_init( sl->sl_sd, sl, "", "", - CONN_IS_UDP, ssf, NULL ); - sl->sl_is_udp++; - } - return 1; - } + if ( sl->sl_is_udp ) return 1; #endif # ifdef LDAP_PF_LOCAL @@ -1257,6 +1304,15 @@ slapd_handle_listener( # endif /* LDAP_PF_LOCAL */ s = accept( sl->sl_sd, (struct sockaddr *) &from, &len ); + +#ifdef SLAP_LIGHTWEIGHT_DISPATCHER + /* Resume the listener FD to allow concurrent-processing of + * additional incoming connections. + */ + sl->sl_busy = 0; + WAKE_LISTENER(1); +#endif + if ( s == AC_SOCKET_INVALID ) { int err = sock_errno(); @@ -1272,14 +1328,13 @@ slapd_handle_listener( ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex ); emfile++; /* Stop listening until an existing session closes */ - sl->sl_is_mute = 1; + sl->sl_mute = 1; ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex ); } Debug( LDAP_DEBUG_ANY, "daemon: accept(%ld) failed errno=%d (%s)\n", - (long) sl->sl_sd, err, - sock_errstr(err) ); + (long) sl->sl_sd, err, sock_errstr(err) ); ldap_pvt_thread_yield(); return 0; } @@ -1299,10 +1354,8 @@ slapd_handle_listener( #ifdef LDAP_DEBUG ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex ); - /* newly accepted stream should not be in any of the FD SETS */ assert( SLAP_SOCK_NOT_ACTIVE( s )); - ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex ); #endif @@ -1341,8 +1394,10 @@ slapd_handle_listener( } #endif - Debug( LDAP_DEBUG_CONNS, "daemon: new connection on %ld\n", - (long) s, 0, 0 ); + Debug( LDAP_DEBUG_CONNS, + "daemon: listen=%ld, new connection on %ld\n", + (long) sl->sl_sd, (long) s, 0 ); + switch ( from.sa_addr.sa_family ) { # ifdef LDAP_PF_LOCAL case AF_LOCAL: @@ -1414,7 +1469,9 @@ slapd_handle_listener( #ifdef LDAP_PF_INET6 || ( from.sa_addr.sa_family == AF_INET6 ) #endif - ) { + ) + { + dnsname = NULL; #ifdef SLAPD_RLOOKUPS if ( use_reverse_lookup ) { char *herr; @@ -1424,25 +1481,28 @@ slapd_handle_listener( dnsname = hbuf; } } -#else - dnsname = NULL; #endif /* SLAPD_RLOOKUPS */ #ifdef HAVE_TCPD - if ( !hosts_ctl("slapd", - dnsname != NULL ? dnsname : SLAP_STRING_UNKNOWN, - peeraddr != NULL ? peeraddr : SLAP_STRING_UNKNOWN, - SLAP_STRING_UNKNOWN )) { - /* DENY ACCESS */ - Statslog( LDAP_DEBUG_STATS, - "fd=%ld DENIED from %s (%s)\n", - (long) s, + int rc; + ldap_pvt_thread_mutex_lock( &slap_daemon.tcpd_mutex ); + rc = hosts_ctl("slapd", dnsname != NULL ? dnsname : SLAP_STRING_UNKNOWN, peeraddr != NULL ? peeraddr : SLAP_STRING_UNKNOWN, - 0, 0 ); - slapd_close(s); - return 0; + SLAP_STRING_UNKNOWN ); + ldap_pvt_thread_mutex_unlock( &slap_daemon.tcpd_mutex ); + if ( !rc ) { + /* DENY ACCESS */ + Statslog( LDAP_DEBUG_STATS, + "fd=%ld DENIED from %s (%s)\n", + (long) s, + dnsname != NULL ? dnsname : SLAP_STRING_UNKNOWN, + peeraddr != NULL ? peeraddr : SLAP_STRING_UNKNOWN, + 0, 0 ); + slapd_close(s); + return 0; + } } #endif /* HAVE_TCPD */ } @@ -1473,17 +1533,56 @@ slapd_handle_listener( id, (long) s, peername, sl->sl_name.bv_val, 0 ); - slapd_add( s, 1, NULL ); return 0; } +#ifdef SLAP_LIGHTWEIGHT_DISPATCHER +static void* +slap_listener_thread( + void* ctx, + void* ptr ) +{ + int rc; + + rc = slap_listener( (Listener*)ptr ); + + if( rc != LDAP_SUCCESS ) { + Debug( LDAP_DEBUG_ANY, + "listener_thread: failed %d", rc, 0, 0 ); + } + + return (void*)NULL; +} + +static int +slap_listener_activate( + Listener* sl ) +{ + int rc; + + Debug( LDAP_DEBUG_TRACE, "slap_listener_activate(%d): %s\n", + sl->sl_sd, sl->sl_busy ? "busy" : "", 0 ); + + sl->sl_busy++; + + rc = ldap_pvt_thread_pool_submit( &connection_pool, + slap_listener_thread, (void *) sl ); + + if( rc != 0 ) { + Debug( LDAP_DEBUG_ANY, + "listener_activate(%d): submit failed (%d)\n", + sl->sl_sd, rc, 0 ); + } + return rc; +} +#endif + static void * slapd_daemon_task( - void *ptr -) + void *ptr ) { int l; - time_t last_idle_check = 0; + time_t last_idle_check = 0; struct timeval idle; int ebadf = 0; @@ -1495,8 +1594,9 @@ slapd_daemon_task( * Don't just truncate, preserve the fractions of * seconds to prevent sleeping for zero time. */ - idle.tv_sec = global_idletimeout/SLAPD_IDLE_CHECK_LIMIT; - idle.tv_usec = global_idletimeout - idle.tv_sec * SLAPD_IDLE_CHECK_LIMIT; + idle.tv_sec = global_idletimeout / SLAPD_IDLE_CHECK_LIMIT; + idle.tv_usec = global_idletimeout - \ + ( idle.tv_sec * SLAPD_IDLE_CHECK_LIMIT ); idle.tv_usec *= 1000000 / SLAPD_IDLE_CHECK_LIMIT; } else { idle.tv_sec = 0; @@ -1506,8 +1606,8 @@ slapd_daemon_task( slapd_add( wake_sds[0], 0, NULL ); for ( l = 0; slap_listeners[l] != NULL; l++ ) { - if ( slap_listeners[l]->sl_sd == AC_SOCKET_INVALID ) - continue; + if ( slap_listeners[l]->sl_sd == AC_SOCKET_INVALID ) continue; + #ifdef LDAP_CONNECTIONLESS /* Since this is connectionless, the data port is the * listening port. The listen() and accept() calls @@ -1537,15 +1637,19 @@ slapd_daemon_task( for ( i = 0 ; i < l; i++ ) { sa6 = slap_listeners[i]->sl_sa.sa_in6_addr; if ( sa6.sin6_family == AF_INET6 && - !memcmp( &sa6.sin6_addr, &in6addr_any, sizeof(struct in6_addr) ) ) + !memcmp( &sa6.sin6_addr, &in6addr_any, + sizeof(struct in6_addr) ) ) + { break; + } } if ( i < l ) { /* We are already listening to in6addr_any */ Debug( LDAP_DEBUG_CONNS, - "daemon: Attempt to listen to 0.0.0.0 failed, already listening on ::, assuming IPv4 included\n", - 0, 0, 0 ); + "daemon: Attempt to listen to 0.0.0.0 failed, " + "already listening on ::, assuming IPv4 included\n", + 0, 0, 0 ); slapd_close( slap_listeners[l]->sl_sd ); slap_listeners[l]->sl_sd = AC_SOCKET_INVALID; continue; @@ -1557,17 +1661,38 @@ slapd_daemon_task( "daemon: listen(%s, 5) failed errno=%d (%s)\n", slap_listeners[l]->sl_url.bv_val, err, sock_errstr(err) ); - return( (void*)-1 ); + return (void*)-1; } +#ifdef SLAP_LIGHTWEIGHT_DISPATCHER + /* make the listening socket non-blocking */ + if ( ber_pvt_socket_set_nonblock( slap_listeners[l]->sl_sd, 1 ) < 0 ) { + Debug( LDAP_DEBUG_ANY, "slapd_daemon_task: " + "set nonblocking on a listening socket failed\n", + 0, 0, 0 ); + slapd_shutdown = 2; + return (void*)-1; + } +#endif + slapd_add( slap_listeners[l]->sl_sd, 0, slap_listeners[l] ); } #ifdef HAVE_NT_SERVICE_MANAGER - if ( started_event != NULL ) { + if ( started_event != NULL ) } ldap_pvt_thread_cond_signal( &started_event ); } #endif + +#ifdef SLAP_SEM_LOAD_CONTROL + /* + * initialize count and lazyness of a semaphore + */ + (void) ldap_lazy_sem_init( + SLAP_MAX_WORKER_THREADS + 4 /* max workers + margin */, + 4 /* lazyness */ ); +#endif + /* initialization complete. Here comes the loop. */ while ( !slapd_shutdown ) { @@ -1620,28 +1745,34 @@ slapd_daemon_task( } } #endif - at = 0; ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex ); nwriters = slap_daemon.sd_nwriters; - SLAP_EVENT_INIT; for ( l = 0; slap_listeners[l] != NULL; l++ ) { - if ( slap_listeners[l]->sl_sd == AC_SOCKET_INVALID ) - continue; - if ( slap_listeners[l]->sl_is_mute ) - SLAP_SOCK_SET_MUTE( slap_listeners[l]->sl_sd ); - else - if ( SLAP_SOCK_IS_MUTE( slap_listeners[l]->sl_sd )) - SLAP_SOCK_CLR_MUTE( slap_listeners[l]->sl_sd ); + Listener *lr = slap_listeners[l]; + + if ( lr->sl_sd == AC_SOCKET_INVALID ) continue; + +#ifdef SLAP_LIGHTWEIGHT_DISPATCHER + if ( lr->sl_mute || lr->sl_busy ) +#else + if ( lr->sl_mute ) +#endif + { + SLAP_SOCK_CLR_READ( lr->sl_sd ); + } else { + SLAP_SOCK_SET_READ( lr->sl_sd ); + } } + SLAP_EVENT_INIT; + nfds = SLAP_EVENT_MAX; - if ( global_idletimeout && slap_daemon.sd_nactives ) - at = 1; + if ( global_idletimeout && slap_daemon.sd_nactives ) at = 1; ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex ); @@ -1650,9 +1781,11 @@ slapd_daemon_task( && ( tv.tv_sec || tv.tv_usec ) #endif ) + { tvp = &tv; - else + } else { tvp = NULL; + } ldap_pvt_thread_mutex_lock( &slapd_rq.rq_mutex ); rtask = ldap_pvt_runqueue_next_sched( &slapd_rq, &cat ); @@ -1673,8 +1806,7 @@ slapd_daemon_task( if ( cat && cat->tv_sec ) { time_t diff = difftime( cat->tv_sec, now ); - if ( diff == 0 ) - diff = tdelta; + if ( diff == 0 ) diff = tdelta; if ( tvp == NULL || diff < tv.tv_sec ) { tv.tv_sec = diff; tv.tv_usec = 0; @@ -1683,18 +1815,34 @@ slapd_daemon_task( } for ( l = 0; slap_listeners[l] != NULL; l++ ) { - if ( slap_listeners[l]->sl_sd == AC_SOCKET_INVALID || - slap_listeners[l]->sl_is_mute ) + Listener *lr = slap_listeners[l]; + + if ( lr->sl_sd == AC_SOCKET_INVALID ) { continue; + } + + if ( lr->sl_mute ) { + Debug( LDAP_DEBUG_CONNS, + "daemon: select: listen=%d muted\n", + lr->sl_sd, 0, 0 ); + continue; + } + +#ifdef SLAP_LIGHTWEIGHT_DISPATCHER + if ( lr->sl_busy ) { + Debug( LDAP_DEBUG_CONNS, + "daemon: select: listen=%d busy\n", + lr->sl_sd, 0, 0 ); + continue; + } +#endif Debug( LDAP_DEBUG_CONNS, "daemon: select: listen=%d active_threads=%d tvp=%s\n", - slap_listeners[l]->sl_sd, at, - tvp == NULL ? "NULL" : "zero" ); + lr->sl_sd, at, tvp == NULL ? "NULL" : "zero" ); } - switch(ns = SLAP_EVENT_WAIT(tvp)) - { + switch(ns = SLAP_EVENT_WAIT(tvp)) { case -1: { /* failure - try again */ int err = sock_errno(); @@ -1731,18 +1879,22 @@ slapd_daemon_task( if( slapd_shutdown ) continue; ebadf = 0; - Debug( LDAP_DEBUG_CONNS, "daemon: activity on %d descriptors\n", - ns, 0, 0 ); + Debug( LDAP_DEBUG_CONNS, + "daemon: activity on %d descriptor%s\n", + ns, ns != 1 ? "s" : "", 0 ); /* FALL THRU */ } #if SLAP_EVENTS_ARE_INDEXED if ( SLAP_EVENT_IS_READ( wake_sds[0] )) { - char c[BUFSIZ]; - tcp_read( wake_sds[0], c, sizeof(c) ); - waking = 0; - ns--; SLAP_EVENT_CLR_READ( wake_sds[0] ); + ns--; + { + char c[BUFSIZ]; + tcp_read( wake_sds[0], c, sizeof(c) ); + } + Debug( LDAP_DEBUG_CONNS, "daemon: waked\n", 0, 0, 0 ); + waking = 0; continue; } @@ -1754,25 +1906,22 @@ slapd_daemon_task( int rc; if ( ns <= 0 ) break; - - if ( slap_listeners[l]->sl_sd == AC_SOCKET_INVALID ) - continue; - - if ( !SLAP_EVENT_IS_READ( slap_listeners[l]->sl_sd )) - continue; - - rc = slapd_handle_listener(slap_listeners[l]); - + if ( slap_listeners[l]->sl_sd == AC_SOCKET_INVALID ) continue; #ifdef LDAP_CONNECTIONLESS - /* This is a UDP session, let the data loop process it */ - if ( rc ) continue; + if ( slap_listeners[l]->sl_is_udp ) continue; #endif - - ns--; - - /* Don't need to look at this in the data loops */ + if ( !SLAP_EVENT_IS_READ( slap_listeners[l]->sl_sd )) continue; + + /* clear events */ SLAP_EVENT_CLR_READ( slap_listeners[l]->sl_sd ); SLAP_EVENT_CLR_WRITE( slap_listeners[l]->sl_sd ); + ns--; + +#ifdef SLAP_LIGHTWEIGHT_DISPATCHER + rc = slap_listener_activate(slap_listeners[l]); +#else + rc = slap_listener(slap_listeners[l]); +#endif } /* bypass the following tests if no descriptors left */ @@ -1824,29 +1973,31 @@ slapd_daemon_task( /* loop through the writers */ - for ( i = 0; nwfds > 0; i++ ) - { + for ( i = 0; nwfds > 0; i++ ) { ber_socket_t wd; #ifdef HAVE_WINSOCK wd = writefds.fd_array[i]; #else - if( ! SLAP_EVENT_IS_WRITE( i ) ) { - continue; - } + if( ! SLAP_EVENT_IS_WRITE( i ) ) continue; wd = i; #endif + + SLAP_EVENT_CLR_WRITE( wd ); nwfds--; Debug( LDAP_DEBUG_CONNS, "daemon: write active on %d\n", wd, 0, 0 ); + +#ifdef SLAP_LIGHTWEIGHT_DISPATCHER + connection_write_activate( wd ); +#else /* * NOTE: it is possible that the connection was closed * and that the stream is now inactive. - * connection_write() must valid the stream is still + * connection_write() must validate the stream is still * active. */ - if ( connection_write( wd ) < 0 ) { if ( SLAP_EVENT_IS_READ( wd )) { SLAP_EVENT_CLR_READ( (unsigned) wd ); @@ -1854,20 +2005,18 @@ slapd_daemon_task( } slapd_close( wd ); } - SLAP_EVENT_CLR_WRITE( wd ); +#endif } - for ( i = 0; nrfds > 0; i++ ) - { + for ( i = 0; nrfds > 0; i++ ) { ber_socket_t rd; #ifdef HAVE_WINSOCK rd = readfds.fd_array[i]; #else - if( ! SLAP_EVENT_IS_READ( i ) ) { - continue; - } + if( ! SLAP_EVENT_IS_READ( i ) ) continue; rd = i; #endif + SLAP_EVENT_CLR_READ( rd ); nrfds--; Debug ( LDAP_DEBUG_CONNS, @@ -1879,9 +2028,13 @@ slapd_daemon_task( * active. */ +#ifdef SLAP_LIGHTWEIGHT_DISPATCHER + connection_read_activate( rd ); +#else if ( connection_read( rd ) < 0 ) { slapd_close( rd ); } +#endif } #else /* !SLAP_EVENTS_ARE_INDEXED */ /* FIXME */ @@ -1896,33 +2049,28 @@ slapd_daemon_task( * an event, so we could use pointers to the listener structure * instead of just the file descriptor. For /dev/poll we have to * search the listeners array for a matching descriptor. + * + * We now handle wake events when we see them; they are not given + * higher priority. */ - /* if waking is set and we woke up, we'll read whatever - * we can. - */ - if ( waking ) { - char c[BUFSIZ]; - tcp_read( wake_sds[0], c, sizeof(c) ); - waking = 0; - ns--; - continue; - } - #ifdef LDAP_DEBUG Debug( LDAP_DEBUG_CONNS, "daemon: activity on:", 0, 0, 0 ); for (i=0; isl_is_udp) + && !((SLAP_EVENT_LISTENER(i))->sl_is_udp) #endif - ) continue; + ) + { + continue; + } /* Don't log internal wake events */ - if ( SLAP_EVENT_FD( i ) == wake_sds[0] ) - continue; + if ( SLAP_EVENT_FD( i ) == wake_sds[0] ) continue; r = SLAP_EVENT_IS_READ( i ); w = SLAP_EVENT_IS_WRITE( i ); @@ -1931,13 +2079,20 @@ slapd_daemon_task( r ? "r" : "", w ? "w" : "" ); } } + Debug( LDAP_DEBUG_CONNS, "\n", 0, 0, 0 ); #endif + for (i=0; isr_err = frontendDB->be_delete( op, rs ); cleanup:; - slap_graduate_commit_csn( op ); - op->o_tmpfree( op->o_req_dn.bv_val, op->o_tmpmemctx ); op->o_tmpfree( op->o_req_ndn.bv_val, op->o_tmpmemctx ); return rs->sr_err; @@ -174,12 +172,6 @@ fe_op_delete( Operation *op, SlapReply *rs ) op->o_bd = op_be; - if ( !repl_user ) { - struct berval csn = BER_BVNULL; - char csnbuf[LDAP_LUTIL_CSNSTR_BUFSIZE]; - slap_get_csn( op, csnbuf, sizeof(csnbuf), &csn, 1 ); - } - #ifdef SLAPD_MULTIMASTER if ( !op->o_bd->be_update_ndn.bv_len || !repl_user ) #endif diff --git a/servers/slapd/extended.c b/servers/slapd/extended.c index bef3b96560..894de43f52 100644 --- a/servers/slapd/extended.c +++ b/servers/slapd/extended.c @@ -248,7 +248,7 @@ done:; int load_extop( - struct berval *ext_oid, + const struct berval *ext_oid, slap_mask_t ext_flags, SLAP_EXTOP_MAIN_FN *ext_main ) { diff --git a/servers/slapd/init.c b/servers/slapd/init.c index ab5f17b7a7..6a68e498ee 100644 --- a/servers/slapd/init.c +++ b/servers/slapd/init.c @@ -67,6 +67,7 @@ struct berval NoAttrs = BER_BVC( LDAP_NO_ATTRS ); */ ldap_pvt_thread_pool_t connection_pool; int connection_pool_max = SLAP_MAX_WORKER_THREADS; +int slap_tool_thread_max = 1; #ifndef HAVE_GMTIME_R ldap_pvt_thread_mutex_t gmtime_mutex; #endif @@ -124,8 +125,6 @@ slap_init( int mode, const char *name ) switch ( slapMode & SLAP_MODE ) { case SLAP_SERVER_MODE: - ldap_pvt_thread_pool_init( &connection_pool, - connection_pool_max, 0); /* FALLTHRU */ case SLAP_TOOL_MODE: @@ -136,6 +135,9 @@ slap_init( int mode, const char *name ) 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 ); diff --git a/servers/slapd/main.c b/servers/slapd/main.c index 7de2855ba4..b32e60e4d2 100644 --- a/servers/slapd/main.c +++ b/servers/slapd/main.c @@ -332,7 +332,7 @@ int main( int argc, char **argv ) #endif while ( (i = getopt( argc, argv, - "c:d:f:F:h:n:o:s:StT:V" + "c:d:f:F:h:n:o:s:tT:V" #if LDAP_PF_INET6 "46" #endif @@ -669,7 +669,7 @@ unhandled_option:; ldap_pvt_tls_set_option( NULL, LDAP_OPT_X_TLS_CTX, NULL ); rc = ldap_pvt_tls_init_def_ctx(); - if( rc == 0) { + if( rc == 0 ) { ldap_pvt_tls_get_option( NULL, LDAP_OPT_X_TLS_CTX, &slap_tls_ctx ); /* Restore previous ctx */ ldap_pvt_tls_set_option( NULL, LDAP_OPT_X_TLS_CTX, def_ctx ); @@ -721,7 +721,7 @@ unhandled_option:; */ time( &starttime ); - if ( slap_startup( NULL ) != 0 ) { + if ( slap_startup( NULL ) != 0 ) { rc = 1; SERVICE_EXIT( ERROR_SERVICE_SPECIFIC_ERROR, 21 ); goto shutdown; @@ -729,33 +729,51 @@ unhandled_option:; Debug( LDAP_DEBUG_ANY, "slapd starting\n", 0, 0, 0 ); - if ( slapd_pid_file != NULL ) { FILE *fp = fopen( slapd_pid_file, "w" ); - if( fp != NULL ) { - fprintf( fp, "%d\n", (int) getpid() ); - fclose( fp ); + if ( fp == NULL ) { + int save_errno = errno; + + Debug( LDAP_DEBUG_ANY, "unable to open pid file " + "\"%s\": %d (%s)\n", + slapd_pid_file, + save_errno, strerror( save_errno ) ); - } else { - free(slapd_pid_file); + free( slapd_pid_file ); slapd_pid_file = NULL; + + rc = 1; + goto shutdown; } + + fprintf( fp, "%d\n", (int) getpid() ); + fclose( fp ); } if ( slapd_args_file != NULL ) { FILE *fp = fopen( slapd_args_file, "w" ); - if( fp != NULL ) { - for ( i = 0; i < g_argc; i++ ) { - fprintf( fp, "%s ", g_argv[i] ); - } - fprintf( fp, "\n" ); - fclose( fp ); - } else { - free(slapd_args_file); + if ( fp == NULL ) { + int save_errno = errno; + + Debug( LDAP_DEBUG_ANY, "unable to open args file " + "\"%s\": %d (%s)\n", + slapd_args_file, + save_errno, strerror( save_errno ) ); + + free( slapd_args_file ); slapd_args_file = NULL; + + rc = 1; + goto shutdown; + } + + for ( i = 0; i < g_argc; i++ ) { + fprintf( fp, "%s ", g_argv[i] ); } + fprintf( fp, "\n" ); + fclose( fp ); } #ifdef HAVE_NT_EVENT_LOG diff --git a/servers/slapd/modify.c b/servers/slapd/modify.c index ca628ef5ff..4f90671ec3 100644 --- a/servers/slapd/modify.c +++ b/servers/slapd/modify.c @@ -200,8 +200,6 @@ do_modify( rs->sr_err = frontendDB->be_modify( op, rs ); cleanup: - slap_graduate_commit_csn( op ); - op->o_tmpfree( op->o_req_dn.bv_val, op->o_tmpmemctx ); op->o_tmpfree( op->o_req_ndn.bv_val, op->o_tmpmemctx ); if ( op->orm_modlist != NULL ) slap_mods_free( op->orm_modlist, 1 ); @@ -217,7 +215,6 @@ fe_op_modify( Operation *op, SlapReply *rs ) #endif int manageDSAit; Modifications *modlist = op->orm_modlist; - Modifications **modtail = &modlist; int increment = op->orm_increment; BackendDB *op_be; char textbuf[ SLAP_TEXT_BUFLEN ]; @@ -388,22 +385,6 @@ fe_op_modify( Operation *op, SlapReply *rs ) } } - if ( !repl_user ) { - for( modtail = &modlist; - *modtail != NULL; - modtail = &(*modtail)->sml_next ) - { - /* empty */ - } - - rs->sr_err = slap_mods_opattrs( op, modlist, modtail, - &rs->sr_text, textbuf, textlen, 1 ); - if( rs->sr_err != LDAP_SUCCESS ) { - send_ldap_result( op, rs ); - goto cleanup; - } - } - op->orm_modlist = modlist; #ifdef SLAPD_MULTIMASTER if ( !repl_user ) @@ -825,35 +806,43 @@ void slap_timestamp( time_t *tm, struct berval *bv ) #endif } -int slap_mods_opattrs( +/* modify only calls this for non-replicas. modrdn always calls. + */ +void slap_mods_opattrs( Operation *op, Modifications *mods, - Modifications **modtail, - const char **text, - char *textbuf, size_t textlen, int manage_ctxcsn ) { - struct berval name, timestamp, csn; + struct berval name, timestamp, csn = BER_BVNULL; struct berval nname; char timebuf[ LDAP_LUTIL_GENTIME_BUFSIZE ]; char csnbuf[ LDAP_LUTIL_CSNSTR_BUFSIZE ]; - Modifications *mod; - - int mop = op->o_tag == LDAP_REQ_ADD - ? LDAP_MOD_ADD : LDAP_MOD_REPLACE; - - assert( modtail != NULL ); - assert( *modtail == NULL ); + Modifications *mod, **modtail, *modlast; if ( SLAP_LASTMOD( op->o_bd ) ) { - time_t now = slap_get_time(); - - slap_get_csn( op, csnbuf, sizeof(csnbuf), &csn, manage_ctxcsn ); - + char *ptr; timestamp.bv_val = timebuf; - timestamp.bv_len = sizeof(timebuf); + if ( BER_BVISEMPTY( &op->o_csn )) { + csn.bv_val = csnbuf; + csn.bv_len = sizeof( csnbuf ); + slap_get_csn( op, &csn, manage_ctxcsn ); + } else { + csn = op->o_csn; + } + ptr = strchr( csn.bv_val, '#' ); + if ( ptr ) { + timestamp.bv_len = ptr - csn.bv_val; + if ( timestamp.bv_len >= sizeof( timebuf )) + timestamp.bv_len = sizeof( timebuf ) - 1; + strncpy( timebuf, csn.bv_val, timestamp.bv_len ); + timebuf[timestamp.bv_len] = '\0'; + } else { + time_t now = slap_get_time(); - slap_timestamp( &now, ×tamp ); + timestamp.bv_len = sizeof(timebuf); + + slap_timestamp( &now, ×tamp ); + } if ( BER_BVISEMPTY( &op->o_dn ) ) { BER_BVSTR( &name, SLAPD_ANONYMOUS ); @@ -862,146 +851,13 @@ int slap_mods_opattrs( name = op->o_dn; nname = op->o_ndn; } - } - - if ( op->o_tag == LDAP_REQ_ADD ) { - struct berval tmpval; - - mod = *modtail; - if ( get_manageDIT( op ) ) { - for ( mod = mods; mod != *modtail; mod = mod->sml_next ) { - if ( mod->sml_desc == slap_schema.si_ad_structuralObjectClass ) { - break; - } - } - - } - - if ( mod == *modtail ) { - int rc = mods_structural_class( mods, &tmpval, - text, textbuf, textlen ); - if( rc != LDAP_SUCCESS ) return rc; - mod = (Modifications *) ch_malloc( sizeof( Modifications ) ); - mod->sml_op = mop; - mod->sml_flags = SLAP_MOD_INTERNAL; - mod->sml_next = NULL; - BER_BVZERO( &mod->sml_type ); - mod->sml_desc = slap_schema.si_ad_structuralObjectClass; - mod->sml_values = - (BerVarray) ch_malloc( 2 * sizeof( struct berval ) ); - ber_dupbv( &mod->sml_values[0], &tmpval ); - BER_BVZERO( &mod->sml_values[1] ); - assert( !BER_BVISNULL( &mod->sml_values[0] ) ); - mod->sml_nvalues = - (BerVarray) ch_malloc( 2 * sizeof( struct berval ) ); - ber_dupbv( &mod->sml_nvalues[0], &tmpval ); - BER_BVZERO( &mod->sml_nvalues[1] ); - assert( !BER_BVISNULL( &mod->sml_nvalues[0] ) ); - *modtail = mod; - modtail = &mod->sml_next; - } - - if ( SLAP_LASTMOD( op->o_bd ) ) { - mod = *modtail; - if ( get_manageDIT( op ) ) { - for ( mod = mods; mod != *modtail; mod = mod->sml_next ) { - if ( mod->sml_desc == slap_schema.si_ad_entryUUID ) { - break; - } - } - } - - if ( mod == *modtail ) { - char uuidbuf[ LDAP_LUTIL_UUIDSTR_BUFSIZE ]; - - tmpval.bv_len = lutil_uuidstr( uuidbuf, sizeof( uuidbuf ) ); - tmpval.bv_val = uuidbuf; - - mod = (Modifications *) ch_malloc( sizeof( Modifications ) ); - mod->sml_op = mop; - mod->sml_flags = SLAP_MOD_INTERNAL; - mod->sml_next = NULL; - BER_BVZERO( &mod->sml_type ); - mod->sml_desc = slap_schema.si_ad_entryUUID; - mod->sml_values = - (BerVarray) ch_malloc( 2 * sizeof( struct berval ) ); - ber_dupbv( &mod->sml_values[0], &tmpval ); - BER_BVZERO( &mod->sml_values[1] ); - assert( !BER_BVISNULL( &mod->sml_values[0] ) ); - mod->sml_nvalues = - (BerVarray) ch_malloc( 2 * sizeof( struct berval ) ); - (*mod->sml_desc->ad_type->sat_equality->smr_normalize)( - SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX, - mod->sml_desc->ad_type->sat_syntax, - mod->sml_desc->ad_type->sat_equality, - mod->sml_values, mod->sml_nvalues, NULL ); - BER_BVZERO( &mod->sml_nvalues[1] ); - *modtail = mod; - modtail = &mod->sml_next; - } - - mod = *modtail; - if ( get_manageDIT( op ) ) { - for ( mod = mods; mod != *modtail; mod = mod->sml_next ) { - if ( mod->sml_desc == slap_schema.si_ad_creatorsName ) { - break; - } - } - } - - if ( mod == *modtail ) { - mod = (Modifications *) ch_malloc( sizeof( Modifications ) ); - mod->sml_op = mop; - mod->sml_flags = SLAP_MOD_INTERNAL; - mod->sml_next = NULL; - BER_BVZERO( &mod->sml_type ); - mod->sml_desc = slap_schema.si_ad_creatorsName; - mod->sml_values = - (BerVarray) ch_malloc( 2 * sizeof( struct berval ) ); - ber_dupbv( &mod->sml_values[0], &name ); - BER_BVZERO( &mod->sml_values[1] ); - assert( !BER_BVISNULL( &mod->sml_values[0] ) ); - mod->sml_nvalues = - (BerVarray) ch_malloc( 2 * sizeof( struct berval ) ); - ber_dupbv( &mod->sml_nvalues[0], &nname ); - BER_BVZERO( &mod->sml_nvalues[1] ); - assert( !BER_BVISNULL( &mod->sml_nvalues[0] ) ); - *modtail = mod; - modtail = &mod->sml_next; - } - - mod = *modtail; - if ( get_manageDIT( op ) ) { - for ( mod = mods; mod != *modtail; mod = mod->sml_next ) { - if ( mod->sml_desc == slap_schema.si_ad_createTimestamp ) { - break; - } - } - } - - if ( mod == *modtail ) { - mod = (Modifications *) ch_malloc( sizeof( Modifications ) ); - mod->sml_op = mop; - mod->sml_flags = SLAP_MOD_INTERNAL; - mod->sml_next = NULL; - BER_BVZERO( &mod->sml_type ); - mod->sml_desc = slap_schema.si_ad_createTimestamp; - mod->sml_values = - (BerVarray) ch_malloc( 2 * sizeof( struct berval ) ); - ber_dupbv( &mod->sml_values[0], ×tamp ); - BER_BVZERO( &mod->sml_values[1] ); - assert( !BER_BVISNULL( &mod->sml_values[0] ) ); - mod->sml_nvalues = NULL; - *modtail = mod; - modtail = &mod->sml_next; - } - } - } + for ( mod = mods; mod->sml_next; mod = mod->sml_next ) + ; + modtail = &mod->sml_next; - if ( SLAP_LASTMOD( op->o_bd ) ) { mod = (Modifications *) ch_malloc( sizeof( Modifications ) ); - mod->sml_op = mop; + mod->sml_op = LDAP_MOD_REPLACE; mod->sml_flags = SLAP_MOD_INTERNAL; mod->sml_next = NULL; BER_BVZERO( &mod->sml_type ); @@ -1012,20 +868,20 @@ int slap_mods_opattrs( assert( !BER_BVISNULL( &mod->sml_values[0] ) ); mod->sml_nvalues = NULL; *modtail = mod; + modlast = mod; modtail = &mod->sml_next; - mod = *modtail; if ( get_manageDIT( op ) ) { - for ( mod = mods; mod != *modtail; mod = mod->sml_next ) { + for ( mod = mods; mod != modlast; mod = mod->sml_next ) { if ( mod->sml_desc == slap_schema.si_ad_modifiersName ) { break; } } } - if ( mod == *modtail ) { + if ( mod->sml_desc != slap_schema.si_ad_modifiersName ) { mod = (Modifications *) ch_malloc( sizeof( Modifications ) ); - mod->sml_op = mop; + mod->sml_op = LDAP_MOD_REPLACE; mod->sml_flags = SLAP_MOD_INTERNAL; mod->sml_next = NULL; BER_BVZERO( &mod->sml_type ); @@ -1043,18 +899,17 @@ int slap_mods_opattrs( modtail = &mod->sml_next; } - mod = *modtail; if ( get_manageDIT( op ) ) { - for ( mod = mods; mod != *modtail; mod = mod->sml_next ) { + for ( mod = mods; mod != modlast; mod = mod->sml_next ) { if ( mod->sml_desc == slap_schema.si_ad_modifyTimestamp ) { break; } } } - if ( mod == *modtail ) { + if ( mod->sml_desc != slap_schema.si_ad_modifyTimestamp ) { mod = (Modifications *) ch_malloc( sizeof( Modifications ) ); - mod->sml_op = mop; + mod->sml_op = LDAP_MOD_REPLACE; mod->sml_flags = SLAP_MOD_INTERNAL; mod->sml_next = NULL; BER_BVZERO( &mod->sml_type ); @@ -1068,8 +923,5 @@ int slap_mods_opattrs( modtail = &mod->sml_next; } } - - *modtail = NULL; - return LDAP_SUCCESS; } diff --git a/servers/slapd/modrdn.c b/servers/slapd/modrdn.c index f54f714103..496abe34d7 100644 --- a/servers/slapd/modrdn.c +++ b/servers/slapd/modrdn.c @@ -178,8 +178,6 @@ do_modrdn( rs->sr_err = frontendDB->be_modrdn( op, rs ); cleanup: - slap_graduate_commit_csn( op ); - op->o_tmpfree( op->o_req_dn.bv_val, op->o_tmpmemctx ); op->o_tmpfree( op->o_req_ndn.bv_val, op->o_tmpmemctx ); @@ -386,7 +384,6 @@ slap_modrdn2mods( Modifications **pmod ) { Modifications *mod = NULL; - Modifications **modtail = &mod; int a_cnt, d_cnt; int repl_user; @@ -506,18 +503,7 @@ slap_modrdn2mods( done: if ( rs->sr_err == LDAP_SUCCESS && !repl_user ) { - char textbuf[ SLAP_TEXT_BUFLEN ]; - size_t textlen = sizeof textbuf; - - for( modtail = &mod; - *modtail != NULL; - modtail = &(*modtail)->sml_next ) - { - /* empty */ - } - - rs->sr_err = slap_mods_opattrs( op, mod, modtail, - &rs->sr_text, textbuf, textlen, 1 ); + slap_mods_opattrs( op, mod, 1 ); } /* LDAP v2 supporting correct attribute handling. */ diff --git a/servers/slapd/mods.c b/servers/slapd/mods.c index a9a66074da..40945fd21f 100644 --- a/servers/slapd/mods.c +++ b/servers/slapd/mods.c @@ -73,11 +73,15 @@ modify_add_values( } if ( permissive ) { - for ( i = 0; !BER_BVISNULL( &mod->sm_values[i] ); i++ ) /* count 'em */; - pmod.sm_values = (BerVarray)ch_malloc( (i + 1)*sizeof( struct berval ) ); + for ( i = 0; !BER_BVISNULL( &mod->sm_values[i] ); i++ ) { + /* EMPTY -- just counting 'em */; + } + + pmod.sm_values = (BerVarray)ch_malloc( + (i + 1) * sizeof( struct berval )); if ( pmod.sm_nvalues != NULL ) { pmod.sm_nvalues = (BerVarray)ch_malloc( - (i + 1)*sizeof( struct berval ) ); + (i + 1) * sizeof( struct berval )); } } diff --git a/servers/slapd/operation.c b/servers/slapd/operation.c index f8ecf3b920..68ee4d198a 100644 --- a/servers/slapd/operation.c +++ b/servers/slapd/operation.c @@ -112,6 +112,21 @@ slap_op_free( Operation *op ) ldap_pvt_thread_mutex_unlock( &slap_op_mutex ); } +void +slap_op_time(time_t *t, int *nop) +{ + *t = slap_get_time(); + ldap_pvt_thread_mutex_lock( &slap_op_mutex ); + if ( *t == last_time ) { + *nop = ++last_incr; + } else { + last_time = *t; + last_incr = 0; + *nop = 0; + } + ldap_pvt_thread_mutex_unlock( &slap_op_mutex ); +} + Operation * slap_op_alloc( BerElement *ber, @@ -139,13 +154,7 @@ slap_op_alloc( op->o_msgid = msgid; op->o_tag = tag; - op->o_time = slap_get_time(); - if ( op->o_time == last_time ) { - op->o_tincr = ++last_incr; - } else { - last_time = op->o_time; - last_incr = 0; /* o_tincr is alredy zero */ - } + slap_op_time( &op->o_time, &op->o_tincr ); op->o_opid = id; op->o_res_ber = NULL; diff --git a/servers/slapd/overlays/accesslog.c b/servers/slapd/overlays/accesslog.c index 9da3a59b30..4b37dce011 100644 --- a/servers/slapd/overlays/accesslog.c +++ b/servers/slapd/overlays/accesslog.c @@ -58,6 +58,8 @@ typedef struct log_info { int li_cycle; struct re_s *li_task; int li_success; + ldap_pvt_thread_mutex_t li_op_mutex; + ldap_pvt_thread_mutex_t li_log_mutex; } log_info; static ConfigDriver log_cf_gen; @@ -139,7 +141,7 @@ enum { LOG_EN__COUNT }; -static ObjectClass *log_ocs[LOG_EN__COUNT]; +static ObjectClass *log_ocs[LOG_EN__COUNT], *log_container; #define LOG_SCHEMA_ROOT "1.3.6.1.4.1.4203.666.11.5" @@ -152,10 +154,8 @@ static AttributeDescription *ad_reqDN, *ad_reqStart, *ad_reqEnd, *ad_reqType, *ad_reqNewSuperior, *ad_reqDeleteOldRDN, *ad_reqMod, *ad_reqScope, *ad_reqFilter, *ad_reqAttr, *ad_reqEntries, *ad_reqSizeLimit, *ad_reqTimeLimit, *ad_reqAttrsOnly, *ad_reqData, - *ad_reqId, *ad_reqMessage; -#if 0 -static AttributeDescription *ad_oldest; -#endif + *ad_reqId, *ad_reqMessage, *ad_reqVersion, *ad_reqDerefAliases, + *ad_reqReferral, *ad_reqOld; static struct { char *at; @@ -188,97 +188,127 @@ static struct { "EQUALITY caseIgnoreMatch " "SYNTAX OMsDirectoryString " "SINGLE-VALUE )", &ad_reqSession }, - { "( " LOG_SCHEMA_AT ".6 NAME 'reqResult' " - "DESC 'Result code of request' " - "EQUALITY integerMatch " - "SYNTAX OMsInteger " - "SINGLE-VALUE )", &ad_reqResult }, - { "( " LOG_SCHEMA_AT ".7 NAME 'reqAuthzID' " + { "( " LOG_SCHEMA_AT ".6 NAME 'reqAuthzID' " "DESC 'Authorization ID of requestor' " "EQUALITY distinguishedNameMatch " "SYNTAX OMsDN " "SINGLE-VALUE )", &ad_reqAuthzID }, - { "( " LOG_SCHEMA_AT ".8 NAME 'reqControls' " + { "( " LOG_SCHEMA_AT ".7 NAME 'reqResult' " + "DESC 'Result code of request' " + "EQUALITY integerMatch " + "ORDERING integerOrderingMatch " + "SYNTAX OMsInteger " + "SINGLE-VALUE )", &ad_reqResult }, + { "( " LOG_SCHEMA_AT ".8 NAME 'reqMessage' " + "DESC 'Error text of request' " + "EQUALITY caseIgnoreMatch " + "SUBSTR caseIgnoreSubstringsMatch " + "SYNTAX OMsDirectoryString " + "SINGLE-VALUE )", &ad_reqMessage }, + { "( " LOG_SCHEMA_AT ".9 NAME 'reqReferral' " + "DESC 'Referrals returned for request' " + "SUP labeledURI )", &ad_reqReferral }, + { "( " LOG_SCHEMA_AT ".10 NAME 'reqControls' " "DESC 'Request controls' " "SYNTAX OMsOctetString )", &ad_reqControls }, - { "( " LOG_SCHEMA_AT ".9 NAME 'reqRespControls' " + { "( " LOG_SCHEMA_AT ".11 NAME 'reqRespControls' " "DESC 'Response controls of request' " "SYNTAX OMsOctetString )", &ad_reqRespControls }, - { "( " LOG_SCHEMA_AT ".10 NAME 'reqMethod' " + { "( " LOG_SCHEMA_AT ".12 NAME 'reqId' " + "DESC 'ID of Request to Abandon' " + "EQUALITY integerMatch " + "ORDERING integerOrderingMatch " + "SYNTAX OMsInteger " + "SINGLE-VALUE )", &ad_reqId }, + { "( " LOG_SCHEMA_AT ".13 NAME 'reqVersion' " + "DESC 'Protocol version of Bind request' " + "EQUALITY integerMatch " + "ORDERING integerOrderingMatch " + "SYNTAX OMsInteger " + "SINGLE-VALUE )", &ad_reqVersion }, + { "( " LOG_SCHEMA_AT ".14 NAME 'reqMethod' " "DESC 'Bind method of request' " "EQUALITY caseIgnoreMatch " "SYNTAX OMsDirectoryString " "SINGLE-VALUE )", &ad_reqMethod }, - { "( " LOG_SCHEMA_AT ".11 NAME 'reqAssertion' " + { "( " LOG_SCHEMA_AT ".15 NAME 'reqAssertion' " "DESC 'Compare Assertion of request' " "SYNTAX OMsDirectoryString " "SINGLE-VALUE )", &ad_reqAssertion }, - { "( " LOG_SCHEMA_AT ".12 NAME 'reqNewRDN' " + { "( " LOG_SCHEMA_AT ".16 NAME 'reqMod' " + "DESC 'Modifications of request' " + "EQUALITY octetStringMatch " + "SUBSTR octetStringSubstringsMatch " + "SYNTAX OMsOctetString )", &ad_reqMod }, + { "( " LOG_SCHEMA_AT ".17 NAME 'reqOld' " + "DESC 'Old values of entry before request completed' " + "EQUALITY octetStringMatch " + "SUBSTR octetStringSubstringsMatch " + "SYNTAX OMsOctetString )", &ad_reqOld }, + { "( " LOG_SCHEMA_AT ".18 NAME 'reqNewRDN' " "DESC 'New RDN of request' " "EQUALITY distinguishedNameMatch " "SYNTAX OMsDN " "SINGLE-VALUE )", &ad_reqNewRDN }, - { "( " LOG_SCHEMA_AT ".13 NAME 'reqNewSuperior' " + { "( " LOG_SCHEMA_AT ".19 NAME 'reqDeleteOldRDN' " + "DESC 'Delete old RDN' " + "EQUALITY booleanMatch " + "SYNTAX OMsBoolean " + "SINGLE-VALUE )", &ad_reqDeleteOldRDN }, + { "( " LOG_SCHEMA_AT ".20 NAME 'reqNewSuperior' " "DESC 'New superior DN of request' " "EQUALITY distinguishedNameMatch " "SYNTAX OMsDN " "SINGLE-VALUE )", &ad_reqNewSuperior }, - { "( " LOG_SCHEMA_AT ".14 NAME 'reqDeleteOldRDN' " - "DESC 'Delete old RDN' " - "SYNTAX OMsBoolean " - "SINGLE-VALUE )", &ad_reqDeleteOldRDN }, - { "( " LOG_SCHEMA_AT ".15 NAME 'reqMod' " - "DESC 'Modifications of request' " - "SYNTAX OMsDirectoryString " - "EQUALITY caseIgnoreMatch " - "SUBSTR caseIgnoreSubstringsMatch )", &ad_reqMod }, - { "( " LOG_SCHEMA_AT ".16 NAME 'reqScope' " + { "( " LOG_SCHEMA_AT ".21 NAME 'reqScope' " "DESC 'Scope of request' " + "EQUALITY caseIgnoreMatch " "SYNTAX OMsDirectoryString " "SINGLE-VALUE )", &ad_reqScope }, - { "( " LOG_SCHEMA_AT ".17 NAME 'reqFilter' " + { "( " LOG_SCHEMA_AT ".22 NAME 'reqDerefAliases' " + "DESC 'Disposition of Aliases in request' " + "EQUALITY caseIgnoreMatch " + "SYNTAX OMsDirectoryString " + "SINGLE-VALUE )", &ad_reqDerefAliases }, + { "( " LOG_SCHEMA_AT ".23 NAME 'reqAttrsOnly' " + "DESC 'Attributes and values of request' " + "EQUALITY booleanMatch " + "SYNTAX OMsBoolean " + "SINGLE-VALUE )", &ad_reqAttrsOnly }, + { "( " LOG_SCHEMA_AT ".24 NAME 'reqFilter' " "DESC 'Filter of request' " + "EQUALITY caseIgnoreMatch " + "SUBSTR caseIgnoreSubstringsMatch " "SYNTAX OMsDirectoryString " "SINGLE-VALUE )", &ad_reqFilter }, - { "( " LOG_SCHEMA_AT ".18 NAME 'reqAttr' " + { "( " LOG_SCHEMA_AT ".25 NAME 'reqAttr' " "DESC 'Attributes of request' " + "EQUALITY caseIgnoreMatch " "SYNTAX OMsDirectoryString )", &ad_reqAttr }, - { "( " LOG_SCHEMA_AT ".19 NAME 'reqEntries' " - "DESC 'Number of entries returned' " - "SYNTAX OMsInteger " - "SINGLE-VALUE )", &ad_reqEntries }, - { "( " LOG_SCHEMA_AT ".20 NAME 'reqSizeLimit' " + { "( " LOG_SCHEMA_AT ".26 NAME 'reqSizeLimit' " "DESC 'Size limit of request' " + "EQUALITY integerMatch " + "ORDERING integerOrderingMatch " "SYNTAX OMsInteger " "SINGLE-VALUE )", &ad_reqSizeLimit }, - { "( " LOG_SCHEMA_AT ".21 NAME 'reqTimeLimit' " + { "( " LOG_SCHEMA_AT ".27 NAME 'reqTimeLimit' " "DESC 'Time limit of request' " + "EQUALITY integerMatch " + "ORDERING integerOrderingMatch " "SYNTAX OMsInteger " "SINGLE-VALUE )", &ad_reqTimeLimit }, - { "( " LOG_SCHEMA_AT ".22 NAME 'reqAttrsOnly' " - "DESC 'Attributes and values of request' " - "SYNTAX OMsBoolean " - "SINGLE-VALUE )", &ad_reqAttrsOnly }, - { "( " LOG_SCHEMA_AT ".23 NAME 'reqData' " + { "( " LOG_SCHEMA_AT ".28 NAME 'reqEntries' " + "DESC 'Number of entries returned' " + "EQUALITY integerMatch " + "ORDERING integerOrderingMatch " + "SYNTAX OMsInteger " + "SINGLE-VALUE )", &ad_reqEntries }, + { "( " LOG_SCHEMA_AT ".29 NAME 'reqData' " "DESC 'Data of extended request' " + "EQUALITY octetStringMatch " + "SUBSTR octetStringSubstringsMatch " "SYNTAX OMsOctetString " "SINGLE-VALUE )", &ad_reqData }, - { "( " LOG_SCHEMA_AT ".24 NAME 'reqId' " - "DESC 'ID of Request to Abandon' " - "SYNTAX OMsInteger " - "SINGLE-VALUE )", &ad_reqId }, - { "( " LOG_SCHEMA_AT ".25 NAME 'reqMessage' " - "DESC 'Error text of request' " - "SYNTAX OMsDirectoryString " - "SINGLE-VALUE )", &ad_reqMessage }, -#if 0 - { "( " LOG_SCHEMA_AT ".26 NAME 'auditOldest' " - "DESC 'Oldest record in this branch' " - "EQUALITY generalizedTimeMatch " - "ORDERING generalizedTimeOrderingMatch " - "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 " - "SINGLE-VALUE )", &ad_oldest }, -#endif { NULL, NULL } }; @@ -286,24 +316,23 @@ static struct { char *ot; ObjectClass **oc; } locs[] = { -#if 0 { "( " LOG_SCHEMA_OC ".0 NAME 'auditContainer' " + "DESC 'AuditLog container' " "SUP top STRUCTURAL " - "MUST auditOldest " - "MAY cn )", &oc_container }, -#endif + "MAY ( cn $ reqStart $ reqEnd ) )", &log_container }, { "( " LOG_SCHEMA_OC ".1 NAME 'auditObject' " "DESC 'OpenLDAP request auditing' " "SUP top STRUCTURAL " "MUST ( reqStart $ reqType $ reqSession ) " "MAY ( reqDN $ reqAuthzID $ reqControls $ reqRespControls $ reqEnd $ " - "reqResult $ reqMessage ) )", &log_ocs[LOG_EN_UNBIND] }, + "reqResult $ reqMessage $ reqReferral ) )", + &log_ocs[LOG_EN_UNBIND] }, { "( " LOG_SCHEMA_OC ".2 NAME 'auditReadObject' " "DESC 'OpenLDAP read request record' " "SUP auditObject STRUCTURAL )", NULL }, { "( " LOG_SCHEMA_OC ".3 NAME 'auditWriteObject' " "DESC 'OpenLDAP write request record' " - "SUP auditObject STRUCTURAL )", &log_ocs[LOG_EN_DELETE] }, + "SUP auditObject STRUCTURAL )", NULL }, { "( " LOG_SCHEMA_OC ".4 NAME 'auditAbandon' " "DESC 'Abandon operation' " "SUP auditObject STRUCTURAL " @@ -315,27 +344,31 @@ static struct { { "( " LOG_SCHEMA_OC ".6 NAME 'auditBind' " "DESC 'Bind operation' " "SUP auditObject STRUCTURAL " - "MUST reqMethod )", &log_ocs[LOG_EN_BIND] }, + "MUST ( reqVersion $ reqMethod ) )", &log_ocs[LOG_EN_BIND] }, { "( " LOG_SCHEMA_OC ".7 NAME 'auditCompare' " "DESC 'Compare operation' " "SUP auditReadObject STRUCTURAL " "MUST reqAssertion )", &log_ocs[LOG_EN_COMPARE] }, - { "( " LOG_SCHEMA_OC ".8 NAME 'auditModify' " + { "( " LOG_SCHEMA_OC ".8 NAME 'auditDelete' " + "DESC 'Delete operation' " + "SUP auditWriteObject STRUCTURAL " + "MAY reqOld )", &log_ocs[LOG_EN_DELETE] }, + { "( " LOG_SCHEMA_OC ".9 NAME 'auditModify' " "DESC 'Modify operation' " "SUP auditWriteObject STRUCTURAL " - "MUST reqMod )", &log_ocs[LOG_EN_MODIFY] }, - { "( " LOG_SCHEMA_OC ".9 NAME 'auditModRDN' " + "MAY reqOld MUST reqMod )", &log_ocs[LOG_EN_MODIFY] }, + { "( " LOG_SCHEMA_OC ".10 NAME 'auditModRDN' " "DESC 'ModRDN operation' " "SUP auditWriteObject STRUCTURAL " "MUST ( reqNewRDN $ reqDeleteOldRDN ) " "MAY reqNewSuperior )", &log_ocs[LOG_EN_MODRDN] }, - { "( " LOG_SCHEMA_OC ".10 NAME 'auditSearch' " + { "( " LOG_SCHEMA_OC ".11 NAME 'auditSearch' " "DESC 'Search operation' " "SUP auditReadObject STRUCTURAL " - "MUST ( reqScope $ reqAttrsonly ) " + "MUST ( reqScope $ reqDerefAliases $ reqAttrsonly ) " "MAY ( reqFilter $ reqAttr $ reqEntries $ reqSizeLimit $ " "reqTimeLimit ) )", &log_ocs[LOG_EN_SEARCH] }, - { "( " LOG_SCHEMA_OC ".11 NAME 'auditExtended' " + { "( " LOG_SCHEMA_OC ".12 NAME 'auditExtended' " "DESC 'Extended operation' " "SUP auditObject STRUCTURAL " "MAY reqData )", &log_ocs[LOG_EN_EXTENDED] }, @@ -344,22 +377,26 @@ static struct { #define RDNEQ "reqStart=" -/* Our time intervals are of the form [dd+]hh:mm[:ss] - * If a field is present, it must be two digits. We assume no one - * will want to keep log records for longer than 99 days. +/* Our time intervals are of the form [ddd+]hh:mm[:ss] + * If a field is present, it must be two digits. (Except for + * days, which can be arbitrary width.) */ static int log_age_parse(char *agestr) { int t1, t2; int gotdays = 0; + char *endptr; - t1 = atoi( agestr ); + t1 = strtol( agestr, &endptr, 10 ); /* Is there a days delimiter? */ - if ( agestr[2] == '+' ) { + if ( *endptr == '+' ) { + /* 32 bit time only covers about 68 years */ + if ( t1 < 0 || t1 > 25000 ) + return -1; t1 *= 24; gotdays = 1; - } else if ( agestr[2] != ':' ) { + } else if ( *endptr != ':' ) { /* No valid delimiter found, fail */ return -1; } @@ -419,7 +456,7 @@ log_age_unparse( int age, struct berval *agebv ) ptr = agebv->bv_val; if ( dd ) - ptr += sprintf( ptr, "%02d+", dd ); + ptr += sprintf( ptr, "%d+", dd ); ptr += sprintf( ptr, "%02d:%02d", hh, mm ); if ( ss ) ptr += sprintf( ptr, ":%02d", ss ); @@ -539,7 +576,7 @@ log_cf_gen(ConfigArgs *c) struct log_info *li = on->on_bi.bi_private; int rc = 0; slap_mask_t tmask = 0; - char agebuf[2*STRLENOF("dd+hh:mm:ss ")]; + char agebuf[2*STRLENOF("ddddd+hh:mm:ss ")]; struct berval agebv, cyclebv; switch( c->op ) { @@ -649,7 +686,8 @@ log_cf_gen(ConfigArgs *c) return rc; } -static Entry *accesslog_entry( Operation *op, int logop ) { +static Entry *accesslog_entry( Operation *op, int logop, + Operation *op2 ) { slap_overinst *on = (slap_overinst *)op->o_bd->bd_info; log_info *li = on->on_bi.bi_private; @@ -690,6 +728,15 @@ static Entry *accesslog_entry( Operation *op, int logop ) { attr_merge_one( e, ad_reqStart, ×tamp, &ntimestamp ); op->o_tmpfree( ntimestamp.bv_val, op->o_tmpmemctx ); + slap_op_time( &op2->o_time, &op2->o_tincr ); + + timestamp.bv_len = sizeof(rdnbuf) - STRLENOF(RDNEQ); + slap_timestamp( &op2->o_time, ×tamp ); + sprintf( timestamp.bv_val + timestamp.bv_len-1, ".%06dZ", op2->o_tincr ); + timestamp.bv_len += 7; + + attr_merge_normalize_one( e, ad_reqEnd, ×tamp, op->o_tmpmemctx ); + /* Exops have OID appended */ if ( logop == LOG_EN_EXTENDED ) { bv.bv_len = lo->word.bv_len + op->ore_reqoid.bv_len + 2; @@ -721,9 +768,16 @@ static Entry *accesslog_entry( Operation *op, int logop ) { static struct berval scopes[] = { BER_BVC("base"), - BER_BVC("onelevel"), - BER_BVC("subtree"), - BER_BVC("subordinate") + BER_BVC("one"), + BER_BVC("sub"), + BER_BVC("subord") +}; + +static struct berval derefs[] = { + BER_BVC("never"), + BER_BVC("searching"), + BER_BVC("finding"), + BER_BVC("always") }; static struct berval simple = BER_BVC("SIMPLE"); @@ -734,12 +788,11 @@ static int accesslog_response(Operation *op, SlapReply *rs) { Attribute *a, *last_attr; Modifications *m; struct berval *b; - time_t endtime; int i; int logop; slap_verbmasks *lo; Entry *e; - char timebuf[LDAP_LUTIL_GENTIME_BUFSIZE]; + char timebuf[LDAP_LUTIL_GENTIME_BUFSIZE+8]; struct berval bv; char *ptr; BerVarray vals; @@ -749,9 +802,6 @@ static int accesslog_response(Operation *op, SlapReply *rs) { if ( rs->sr_type != REP_RESULT && rs->sr_type != REP_EXTENDED ) return SLAP_CB_CONTINUE; - if ( li->li_success && rs->sr_err != LDAP_SUCCESS ) - return SLAP_CB_CONTINUE; - switch ( op->o_tag ) { case LDAP_REQ_ADD: logop = LOG_EN_ADD; break; case LDAP_REQ_DELETE: logop = LOG_EN_DELETE; break; @@ -769,15 +819,15 @@ static int accesslog_response(Operation *op, SlapReply *rs) { if ( !( li->li_ops & lo->mask )) return SLAP_CB_CONTINUE; - endtime = slap_get_time(); - - e = accesslog_entry( op, logop ); + if ( lo->mask & LOG_OP_WRITES ) { + ldap_pvt_thread_mutex_lock( &li->li_log_mutex ); + ldap_pvt_thread_mutex_unlock( &li->li_op_mutex ); + } - bv.bv_val = timebuf; - bv.bv_len = sizeof(timebuf); - slap_timestamp( &endtime, &bv ); + if ( li->li_success && rs->sr_err != LDAP_SUCCESS ) + goto done; - attr_merge_one( e, ad_reqEnd, &bv, NULL ); + e = accesslog_entry( op, logop, &op2 ); attr_merge_one( e, ad_reqDN, &op->o_req_dn, &op->o_req_ndn ); @@ -915,6 +965,7 @@ static int accesslog_response(Operation *op, SlapReply *rs) { case LOG_EN_SEARCH: attr_merge_one( e, ad_reqScope, &scopes[op->ors_scope], NULL ); + attr_merge_one( e, ad_reqDerefAliases, &derefs[op->ors_deref], NULL ); attr_merge_one( e, ad_reqAttrsOnly, op->ors_attrsonly ? (struct berval *)&slap_true_bv : (struct berval *)&slap_false_bv, NULL ); @@ -943,6 +994,9 @@ static int accesslog_response(Operation *op, SlapReply *rs) { break; case LOG_EN_BIND: + bv.bv_val = timebuf; + bv.bv_len = sprintf( bv.bv_val, "%d", op->o_protocol ); + attr_merge_one( e, ad_reqVersion, &bv, NULL ); if ( op->orb_method == LDAP_AUTH_SIMPLE ) { attr_merge_one( e, ad_reqMethod, &simple, NULL ); } else { @@ -955,6 +1009,7 @@ static int accesslog_response(Operation *op, SlapReply *rs) { attr_merge_one( e, ad_reqMethod, &bv, NULL ); op->o_tmpfree( bv.bv_val, op->o_tmpmemctx ); } + break; case LOG_EN_EXTENDED: @@ -970,8 +1025,6 @@ static int accesslog_response(Operation *op, SlapReply *rs) { op2.o_hdr = op->o_hdr; op2.o_tag = LDAP_REQ_ADD; - op2.o_time = endtime; - op2.o_tincr = 0; op2.o_bd = li->li_db; op2.o_dn = li->li_db->be_rootdn; op2.o_ndn = li->li_db->be_rootndn; @@ -980,16 +1033,71 @@ static int accesslog_response(Operation *op, SlapReply *rs) { op2.ora_e = e; op2.o_callback = &nullsc; - if ( lo->mask & LOG_OP_WRITES ) { - slap_get_commit_csn( op, NULL, &bv ); - attr_merge_one( e, slap_schema.si_ad_entryCSN, &bv, NULL ); - slap_queue_csn( &op2, &bv ); + if (( lo->mask & LOG_OP_WRITES ) && !BER_BVISEMPTY( &op->o_csn )) { + slap_queue_csn( &op2, &op->o_csn ); } op2.o_bd->be_add( &op2, &rs2 ); - slap_graduate_commit_csn( &op2 ); entry_free( e ); +done: + ldap_pvt_thread_mutex_unlock( &li->li_log_mutex ); + return SLAP_CB_CONTINUE; +} + +/* Since Bind success is sent by the frontend, it won't normally enter + * the overlay response callback. Add another callback to make sure it + * gets here. + */ +static int +accesslog_bind_resp( Operation *op, SlapReply *rs ) +{ + BackendDB *be, db; + int rc; + slap_callback *sc; + + be = op->o_bd; + db = *be; + op->o_bd = &db; + db.bd_info = op->o_callback->sc_private; + rc = accesslog_response( op, rs ); + op->o_bd = be; + sc = op->o_callback; + op->o_callback = sc->sc_next; + op->o_tmpfree( sc, op->o_tmpmemctx ); + return rc; +} + +static int +accesslog_op_bind( Operation *op, SlapReply *rs ) +{ + slap_callback *sc; + + sc = op->o_tmpcalloc( 1, sizeof(slap_callback), op->o_tmpmemctx ); + sc->sc_response = accesslog_bind_resp; + sc->sc_private = op->o_bd->bd_info; + + if ( op->o_callback ) { + sc->sc_next = op->o_callback->sc_next; + op->o_callback->sc_next = sc; + } else { + op->o_callback = sc; + } + return SLAP_CB_CONTINUE; +} + +static int +accesslog_op_mod( Operation *op, SlapReply *rs ) +{ + slap_overinst *on = (slap_overinst *)op->o_bd->bd_info; + 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 ); + } return SLAP_CB_CONTINUE; } @@ -999,21 +1107,20 @@ static int accesslog_response(Operation *op, SlapReply *rs) { static int accesslog_unbind( Operation *op, SlapReply *rs ) { - if ( op->o_conn->c_authz_backend == op->o_bd ) { - slap_overinst *on = (slap_overinst *)op->o_bd->bd_info; + slap_overinst *on = (slap_overinst *)op->o_bd->bd_info; + if ( op->o_conn->c_authz_backend == on->on_info->oi_origdb ) { log_info *li = on->on_bi.bi_private; Operation op2; + void *cids[SLAP_MAX_CIDS]; SlapReply rs2 = {REP_RESULT}; Entry *e; if ( !( li->li_ops & LOG_OP_UNBIND )) return SLAP_CB_CONTINUE; - e = accesslog_entry( op, LOG_EN_UNBIND ); + e = accesslog_entry( op, LOG_EN_UNBIND, &op2 ); op2.o_hdr = op->o_hdr; op2.o_tag = LDAP_REQ_ADD; - op2.o_time = op->o_time; - op2.o_tincr = 0; op2.o_bd = li->li_db; op2.o_dn = li->li_db->be_rootdn; op2.o_ndn = li->li_db->be_rootndn; @@ -1021,6 +1128,9 @@ accesslog_unbind( Operation *op, SlapReply *rs ) op2.o_req_ndn = e->e_nname; op2.ora_e = e; op2.o_callback = &nullsc; + op2.o_controls = cids; + memset(cids, 0, sizeof( cids )); + memset(op2.o_ctrlflag, 0, sizeof( op2.o_ctrlflag )); op2.o_bd->be_add( &op2, &rs2 ); entry_free( e ); @@ -1034,6 +1144,7 @@ accesslog_abandon( Operation *op, SlapReply *rs ) slap_overinst *on = (slap_overinst *)op->o_bd->bd_info; log_info *li = on->on_bi.bi_private; Operation op2; + void *cids[SLAP_MAX_CIDS]; SlapReply rs2 = {REP_RESULT}; Entry *e; char buf[64]; @@ -1042,15 +1153,13 @@ accesslog_abandon( Operation *op, SlapReply *rs ) if ( !op->o_time || !( li->li_ops & LOG_OP_ABANDON )) return SLAP_CB_CONTINUE; - e = accesslog_entry( op, LOG_EN_ABANDON ); + e = accesslog_entry( op, LOG_EN_ABANDON, &op2 ); bv.bv_val = buf; bv.bv_len = sprintf( buf, "%d", op->orn_msgid ); attr_merge_one( e, ad_reqId, &bv, NULL ); op2.o_hdr = op->o_hdr; op2.o_tag = LDAP_REQ_ADD; - op2.o_time = op->o_time; - op2.o_tincr = 0; op2.o_bd = li->li_db; op2.o_dn = li->li_db->be_rootdn; op2.o_ndn = li->li_db->be_rootndn; @@ -1058,6 +1167,9 @@ accesslog_abandon( Operation *op, SlapReply *rs ) op2.o_req_ndn = e->e_nname; op2.ora_e = e; op2.o_callback = &nullsc; + op2.o_controls = cids; + memset(cids, 0, sizeof( cids )); + memset(op2.o_ctrlflag, 0, sizeof( op2.o_ctrlflag )); op2.o_bd->be_add( &op2, &rs2 ); entry_free( e ); @@ -1076,6 +1188,8 @@ accesslog_db_init( 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_mutex_init( &li->li_log_mutex ); return 0; } @@ -1087,6 +1201,8 @@ accesslog_db_destroy( slap_overinst *on = (slap_overinst *)be->bd_info; 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 ); free( li ); return LDAP_SUCCESS; } @@ -1099,6 +1215,11 @@ int accesslog_init() accesslog.on_bi.bi_db_init = accesslog_db_init; accesslog.on_bi.bi_db_destroy = accesslog_db_destroy; + accesslog.on_bi.bi_op_add = accesslog_op_mod; + accesslog.on_bi.bi_op_bind = accesslog_op_bind; + accesslog.on_bi.bi_op_delete = accesslog_op_mod; + accesslog.on_bi.bi_op_modify = accesslog_op_mod; + accesslog.on_bi.bi_op_modrdn = accesslog_op_mod; accesslog.on_bi.bi_op_unbind = accesslog_unbind; accesslog.on_bi.bi_op_abandon = accesslog_abandon; accesslog.on_response = accesslog_response; diff --git a/servers/slapd/overlays/lastmod.c b/servers/slapd/overlays/lastmod.c index 07e06eb0d2..63a30e6301 100644 --- a/servers/slapd/overlays/lastmod.c +++ b/servers/slapd/overlays/lastmod.c @@ -370,7 +370,9 @@ best_guess( Operation *op, char csnbuf[ LDAP_LUTIL_CSNSTR_BUFSIZE ]; struct berval entryCSN; - slap_get_csn( NULL, csnbuf, sizeof(csnbuf), &entryCSN, 0 ); + entryCSN.bv_val = csnbuf; + entryCSN.bv_len = sizeof( csnbuf ); + slap_get_csn( NULL, &entryCSN, 0 ); ber_dupbv( bv_entryCSN, &entryCSN ); ber_dupbv( bv_nentryCSN, &entryCSN ); @@ -909,7 +911,9 @@ lastmod_db_open( timestamp.bv_len = sizeof(tmbuf); slap_timestamp( &starttime, ×tamp ); - slap_get_csn( NULL, csnbuf, sizeof(csnbuf), &entryCSN, 0 ); + entryCSN.bv_val = csnbuf; + entryCSN.bv_len = sizeof( csnbuf ); + slap_get_csn( NULL, &entryCSN, 0 ); if ( BER_BVISNULL( &lmi->lmi_rdnvalue ) ) { ber_str2bv( "Lastmod", 0, 1, &lmi->lmi_rdnvalue ); diff --git a/servers/slapd/overlays/ppolicy.c b/servers/slapd/overlays/ppolicy.c index 0d87840a16..e543a48575 100644 --- a/servers/slapd/overlays/ppolicy.c +++ b/servers/slapd/overlays/ppolicy.c @@ -1179,11 +1179,12 @@ ppolicy_modify( Operation *op, SlapReply *rs ) */ if ( be_shadow_update( op )) { Modifications **prev; - int got_del_grace = 0, got_del_lock = 0, got_pw = 0; - Attribute *a_grace, *a_lock; + int got_del_grace = 0, got_del_lock = 0, got_pw = 0, got_del_fail = 0; + Attribute *a_grace, *a_lock, *a_fail; a_grace = attr_find( e->e_attrs, ad_pwdGraceUseTime ); a_lock = attr_find( e->e_attrs, ad_pwdAccountLockedTime ); + a_fail = attr_find( e->e_attrs, ad_pwdFailureTime ); for( prev = &op->oq_modify.rs_modlist, ml = *prev; ml; prev = &ml->sml_next, ml = *prev ) { @@ -1206,6 +1207,11 @@ ppolicy_modify( Operation *op, SlapReply *rs ) got_del_lock = 1; if ( !a_lock ) drop = 1; + } else + if ( ml->sml_desc == ad_pwdFailureTime ) { + got_del_fail = 1; + if ( !a_fail ) + drop = 1; } if ( drop ) { *prev = ml->sml_next; @@ -1215,8 +1221,8 @@ ppolicy_modify( Operation *op, SlapReply *rs ) } } - /* If we're resetting the password, make sure grace and accountlock - * also get removed. + /* If we're resetting the password, make sure grace, accountlock, + * and failure also get removed. */ if ( got_pw ) { if ( a_grace && !got_del_grace ) { @@ -1242,6 +1248,17 @@ ppolicy_modify( Operation *op, SlapReply *rs ) ml->sml_next = NULL; *prev = ml; } + if ( a_fail && !got_del_fail ) { + ml = (Modifications *) ch_malloc( sizeof( Modifications ) ); + ml->sml_op = LDAP_MOD_DELETE; + ml->sml_flags = SLAP_MOD_INTERNAL; + ml->sml_type.bv_val = NULL; + ml->sml_desc = ad_pwdFailureTime; + ml->sml_values = NULL; + ml->sml_nvalues = NULL; + ml->sml_next = NULL; + *prev = ml; + } } op->o_bd->bd_info = (BackendInfo *)on->on_info; be_entry_release_r( op, e ); @@ -1577,6 +1594,19 @@ do_modify: modtail = mods; } + if (attr_find(e->e_attrs, ad_pwdFailureTime )) { + mods = (Modifications *) ch_malloc( sizeof( Modifications ) ); + mods->sml_op = LDAP_MOD_DELETE; + mods->sml_flags = SLAP_MOD_INTERNAL; + mods->sml_type.bv_val = NULL; + mods->sml_desc = ad_pwdFailureTime; + mods->sml_values = NULL; + mods->sml_nvalues = NULL; + mods->sml_next = NULL; + modtail->sml_next = mods; + modtail = mods; + } + /* Delete the pwdReset attribute, since it's being reset */ if ((zapReset) && (attr_find(e->e_attrs, ad_pwdReset ))) { mods = (Modifications *) ch_malloc( sizeof( Modifications ) ); diff --git a/servers/slapd/overlays/refint.c b/servers/slapd/overlays/refint.c index 41e1cbc9cf..9004f902f9 100644 --- a/servers/slapd/overlays/refint.c +++ b/servers/slapd/overlays/refint.c @@ -621,10 +621,6 @@ refint_response( */ for(dp = dd.mods; dp; dp = dp->next) { - Modifications **tail, *m; - - for(m = dp->mm; m && m->sml_next; m = m->sml_next); - tail = &m->sml_next; nop.o_req_dn = dp->dn; nop.o_req_ndn = dp->dn; nop.o_bd = select_backend(&dp->dn, 0, 1); @@ -637,8 +633,6 @@ refint_response( nop.orm_modlist = dp->mm; /* callback did all the work */ nop.o_dn = refint_dn; nop.o_ndn = refint_dn; - rs->sr_err = slap_mods_opattrs( &nop, nop.orm_modlist, - tail, &rs->sr_text, NULL, 0, 1 ); nop.o_dn = nop.o_bd->be_rootdn; nop.o_ndn = nop.o_bd->be_rootndn; if(rs->sr_err != LDAP_SUCCESS) goto done; diff --git a/servers/slapd/overlays/rwm.c b/servers/slapd/overlays/rwm.c index 430e214ec2..42bf3f8c1e 100644 --- a/servers/slapd/overlays/rwm.c +++ b/servers/slapd/overlays/rwm.c @@ -695,7 +695,7 @@ rwm_op_search( Operation *op, SlapReply *rs ) dc.normalized = 0; #endif /* ! ENABLE_REWRITE */ - rc = rwm_filter_map_rewrite( &dc, op->ors_filter, &fstr ); + rc = rwm_filter_map_rewrite( op, &dc, op->ors_filter, &fstr ); if ( rc != LDAP_SUCCESS ) { text = "searchFilter/searchFilterAttrDN massage error"; goto error_return; @@ -1043,6 +1043,7 @@ rwm_send_entry( Operation *op, SlapReply *rs ) goto fail; } + flags &= ~REP_ENTRY_MUSTRELEASE; flags |= ( REP_ENTRY_MODIFIABLE | REP_ENTRY_MUSTBEFREED ); } @@ -1075,11 +1076,9 @@ rwm_send_entry( Operation *op, SlapReply *rs ) * to return, and remap them accordingly */ (void)rwm_attrs( op, rs, &e->e_attrs, 1 ); -#if 0 - if ( rs->sr_operational_attrs ) { - (void)rwm_attrs( op, rs, &rs->sr_operational_attrs, 0 ); + if ( rs->sr_flags & REP_ENTRY_MUSTRELEASE ) { + be_entry_release_rw( op, rs->sr_entry, 0 ); } -#endif rs->sr_entry = e; rs->sr_flags = flags; @@ -1395,9 +1394,14 @@ rwm_db_config( } else if ( strcasecmp( argv[ 1 ], "yes" ) == 0 ) { rwmap->rwm_flags |= RWM_F_SUPPORT_T_F; -#if 0 /* TODO: not implemented yet */ } else if ( strcasecmp( argv[ 1 ], "discover" ) == 0 ) { + fprintf( stderr, + "%s: line %d: \"discover\" not supported yet " + "in \"t-f-support {no|yes|discover}\".\n", + fname, lineno ); + return( 1 ); +#if 0 rwmap->rwm_flags |= RWM_F_SUPPORT_T_F_DISCOVER; #endif @@ -1477,7 +1481,7 @@ rwm_db_destroy( (struct ldaprwmap *)on->on_bi.bi_private; #ifdef ENABLE_REWRITE - if (rwmap->rwm_rw) { + if ( rwmap->rwm_rw ) { rewrite_info_delete( &rwmap->rwm_rw ); } #else /* !ENABLE_REWRITE */ @@ -1486,9 +1490,9 @@ rwm_db_destroy( } #endif /* !ENABLE_REWRITE */ - avl_free( rwmap->rwm_oc.remap, NULL ); + avl_free( rwmap->rwm_oc.remap, rwm_mapping_dst_free ); avl_free( rwmap->rwm_oc.map, rwm_mapping_free ); - avl_free( rwmap->rwm_at.remap, NULL ); + avl_free( rwmap->rwm_at.remap, rwm_mapping_dst_free ); avl_free( rwmap->rwm_at.map, rwm_mapping_free ); ch_free( rwmap ); diff --git a/servers/slapd/overlays/rwm.h b/servers/slapd/overlays/rwm.h index d27e6ac2a8..0c3c73e16c 100644 --- a/servers/slapd/overlays/rwm.h +++ b/servers/slapd/overlays/rwm.h @@ -138,6 +138,8 @@ rwm_map_attrnames( AttributeName **anp, int remap ); +extern void rwm_mapping_dst_free ( void *mapping ); + extern void rwm_mapping_free ( void *mapping ); extern int rwm_map_config( @@ -150,6 +152,7 @@ extern int rwm_map_config( extern int rwm_filter_map_rewrite( + Operation *op, dncookie *dc, Filter *f, struct berval *fstr ); diff --git a/servers/slapd/overlays/rwmconf.c b/servers/slapd/overlays/rwmconf.c index 7a87ccff00..71a77924c9 100644 --- a/servers/slapd/overlays/rwmconf.c +++ b/servers/slapd/overlays/rwmconf.c @@ -146,7 +146,7 @@ rwm_map_config( if ( mapping[0].m_dst_oc == NULL ) { fprintf( stderr, "%s: line %d: unable to mimic destination objectClass '%s'\n", fname, lineno, dst ); - return 1; + goto error_return; } #if 0 @@ -186,7 +186,7 @@ rwm_map_config( fprintf( stderr, "%s: line %d: source attributeType '%s': %d (%s)\n", fname, lineno, src, rc, text ? text : "null" ); - return 1; + goto error_return; } } @@ -207,7 +207,7 @@ rwm_map_config( fprintf( stderr, "%s: line %d: destination attributeType '%s': %d (%s)\n", fname, lineno, dst, rc, text ? text : "null" ); - return 1; + goto error_return; } } mapping[1].m_src_ad = mapping[0].m_dst_ad; diff --git a/servers/slapd/overlays/rwmmap.c b/servers/slapd/overlays/rwmmap.c index 4c573f3b42..1fa9c506d4 100644 --- a/servers/slapd/overlays/rwmmap.c +++ b/servers/slapd/overlays/rwmmap.c @@ -442,6 +442,7 @@ map_attr_value( static int rwm_int_filter_map_rewrite( + Operation *op, dncookie *dc, Filter *f, struct berval *fstr ) @@ -450,7 +451,7 @@ rwm_int_filter_map_rewrite( Filter *p; struct berval atmp, vtmp, - tmp; + *tmp; static struct berval /* better than nothing... */ ber_bvfalse = BER_BVC( "(!(objectClass=*))" ), @@ -469,7 +470,7 @@ rwm_int_filter_map_rewrite( if ( f == NULL ) { ber_dupbv( fstr, &ber_bvnone ); - return -1; + return LDAP_OTHER; } switch ( f->f_choice ) { @@ -477,7 +478,7 @@ rwm_int_filter_map_rewrite( if ( map_attr_value( dc, &f->f_av_desc, &atmp, &f->f_av_value, &vtmp, RWM_MAP ) ) { - return -1; + goto computed; } fstr->bv_len = atmp.bv_len + vtmp.bv_len + STRLENOF( "(=)" ); @@ -493,7 +494,7 @@ rwm_int_filter_map_rewrite( if ( map_attr_value( dc, &f->f_av_desc, &atmp, &f->f_av_value, &vtmp, RWM_MAP ) ) { - return -1; + goto computed; } fstr->bv_len = atmp.bv_len + vtmp.bv_len + STRLENOF( "(>=)" ); @@ -509,7 +510,7 @@ rwm_int_filter_map_rewrite( if ( map_attr_value( dc, &f->f_av_desc, &atmp, &f->f_av_value, &vtmp, RWM_MAP ) ) { - return -1; + goto computed; } fstr->bv_len = atmp.bv_len + vtmp.bv_len + STRLENOF( "(<=)" ); @@ -525,7 +526,7 @@ rwm_int_filter_map_rewrite( if ( map_attr_value( dc, &f->f_av_desc, &atmp, &f->f_av_value, &vtmp, RWM_MAP ) ) { - return -1; + goto computed; } fstr->bv_len = atmp.bv_len + vtmp.bv_len + STRLENOF( "(~=)" ); @@ -541,7 +542,7 @@ rwm_int_filter_map_rewrite( if ( map_attr_value( dc, &f->f_sub_desc, &atmp, NULL, NULL, RWM_MAP ) ) { - return -1; + goto computed; } /* cannot be a DN ... */ @@ -603,7 +604,7 @@ rwm_int_filter_map_rewrite( if ( map_attr_value( dc, &f->f_desc, &atmp, NULL, NULL, RWM_MAP ) ) { - return -1; + goto computed; } fstr->bv_len = atmp.bv_len + STRLENOF( "(=*)" ); @@ -624,11 +625,13 @@ rwm_int_filter_map_rewrite( f->f_choice == LDAP_FILTER_OR ? '|' : '!' ); for ( p = f->f_list; p != NULL; p = p->f_next ) { + int rc; + len = fstr->bv_len; - if ( rwm_int_filter_map_rewrite( dc, p, &vtmp ) ) - { - return -1; + rc = rwm_int_filter_map_rewrite( op, dc, p, &vtmp ); + if ( rc != LDAP_SUCCESS ) { + return rc; } fstr->bv_len += vtmp.bv_len; @@ -647,7 +650,7 @@ rwm_int_filter_map_rewrite( if ( map_attr_value( dc, &f->f_mr_desc, &atmp, &f->f_mr_value, &vtmp, RWM_MAP ) ) { - return -1; + goto computed; } } else { @@ -672,33 +675,39 @@ rwm_int_filter_map_rewrite( break; } + case 0: +computed:; + filter_free_x( op, f ); + f->f_choice = SLAPD_FILTER_COMPUTED; + f->f_result = SLAPD_COMPARE_UNDEFINED; + /* fallthru */ + case SLAPD_FILTER_COMPUTED: switch ( f->f_result ) { case LDAP_COMPARE_FALSE: + /* FIXME: treat UNDEFINED as FALSE */ + case SLAPD_COMPARE_UNDEFINED: if ( dc->rwmap->rwm_flags & RWM_F_SUPPORT_T_F ) { - tmp = ber_bvtf_false; + tmp = &ber_bvtf_false; break; } - /* fallthru */ - - case SLAPD_COMPARE_UNDEFINED: - tmp = ber_bvfalse; + tmp = &ber_bvfalse; break; case LDAP_COMPARE_TRUE: if ( dc->rwmap->rwm_flags & RWM_F_SUPPORT_T_F ) { - tmp = ber_bvtf_true; - } else { - tmp = ber_bvtrue; + tmp = &ber_bvtf_true; + break; } + tmp = &ber_bvtrue; break; default: - tmp = ber_bverror; + tmp = &ber_bverror; break; } - ber_dupbv( fstr, &tmp ); + ber_dupbv( fstr, tmp ); break; default: @@ -706,11 +715,12 @@ rwm_int_filter_map_rewrite( break; } - return 0; + return LDAP_SUCCESS; } int rwm_filter_map_rewrite( + Operation *op, dncookie *dc, Filter *f, struct berval *fstr ) @@ -719,10 +729,10 @@ rwm_filter_map_rewrite( dncookie fdc; struct berval ftmp; - rc = rwm_int_filter_map_rewrite( dc, f, fstr ); + rc = rwm_int_filter_map_rewrite( op, dc, f, fstr ); #ifdef ENABLE_REWRITE - if ( rc != LDAP_SUCCESS ) { + if ( rc != 0 ) { return rc; } @@ -766,8 +776,8 @@ rwm_filter_map_rewrite( rc = LDAP_OTHER; break; } - #endif /* ENABLE_REWRITE */ + return rc; } @@ -1188,6 +1198,16 @@ rwm_dnattr_result_rewrite( return 0; } +void +rwm_mapping_dst_free( void *v_mapping ) +{ + struct ldapmapping *mapping = v_mapping; + + if ( BER_BVISEMPTY( &mapping[0].m_dst ) ) { + rwm_mapping_free( &mapping[ -1 ] ); + } +} + void rwm_mapping_free( void *v_mapping ) { diff --git a/servers/slapd/overlays/syncprov.c b/servers/slapd/overlays/syncprov.c index 4070d5dd09..561b5b2fd1 100644 --- a/servers/slapd/overlays/syncprov.c +++ b/servers/slapd/overlays/syncprov.c @@ -122,6 +122,7 @@ typedef struct syncprov_info_t { int si_chktime; int si_numops; /* number of ops since last checkpoint */ int si_nopres; /* Skip present phase */ + int si_usehint; /* use reload hint */ time_t si_chklast; /* time of last checkpoint */ Avlnode *si_mods; /* entries being modified */ sessionlog *si_logs; @@ -382,6 +383,9 @@ findbase_cb( Operation *op, SlapReply *rs ) return LDAP_SUCCESS; } +static Filter generic_filter = { LDAP_FILTER_PRESENT, { 0 }, NULL }; +static struct berval generic_filterstr = BER_BVC("(objectclass=*)"); + static int syncprov_findbase( Operation *op, fbase_cookie *fc ) { @@ -421,6 +425,8 @@ syncprov_findbase( Operation *op, fbase_cookie *fc ) fop.ors_tlimit = SLAP_NO_LIMIT; fop.ors_attrs = slap_anlist_no_attrs; fop.ors_attrsonly = 1; + fop.ors_filter = &generic_filter; + fop.ors_filterstr = generic_filterstr; fop.o_bd->bd_info = on->on_info->oi_orig; rc = fop.o_bd->be_search( &fop, &frs ); @@ -728,7 +734,8 @@ syncprov_free_syncop( syncops *so ) /* Send a persistent search response */ static int -syncprov_sendresp( Operation *op, opcookie *opc, syncops *so, Entry **e, int mode) +syncprov_sendresp( Operation *op, opcookie *opc, syncops *so, + Entry **e, int mode ) { slap_overinst *on = opc->son; @@ -1943,12 +1950,11 @@ syncprov_op_search( Operation *op, SlapReply *rs ) /* Is the CSN still present in the database? */ if ( syncprov_findcsn( op, FIND_CSN ) != LDAP_SUCCESS ) { /* No, so a reload is required */ -#if 0 /* the consumer doesn't seem to send this hint */ - if ( op->o_sync_rhint == 0 ) { + /* the 2.2 consumer doesn't send this hint */ + if ( si->si_usehint && srs->sr_rhint == 0 ) { send_ldap_error( op, rs, LDAP_SYNC_REFRESH_REQUIRED, "sync cookie is stale" ); return rs->sr_err; } -#endif } else { gotstate = 1; /* If changed and doing Present lookup, send Present UUIDs */ @@ -2069,7 +2075,8 @@ syncprov_operational( enum { SP_CHKPT = 1, SP_SESSL, - SP_NOPRES + SP_NOPRES, + SP_USEHINT }; static ConfigDriver sp_cf_gen; @@ -2087,6 +2094,10 @@ static ConfigTable spcfg[] = { sp_cf_gen, "( OLcfgOvAt:1.3 NAME 'olcSpNoPresent' " "DESC 'Omit Present phase processing' " "SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL }, + { "syncprov-reloadhint", NULL, 2, 2, 0, ARG_ON_OFF|ARG_MAGIC|SP_USEHINT, + sp_cf_gen, "( OLcfgOvAt:1.4 NAME 'olcSpReloadHint' " + "DESC 'Observe Reload Hint in Request control' " + "SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL }, { NULL, NULL, 0, 0, 0, ARG_IGNORED } }; @@ -2134,6 +2145,13 @@ sp_cf_gen(ConfigArgs *c) rc = 1; } break; + case SP_USEHINT: + if ( si->si_usehint ) { + c->value_int = 1; + } else { + rc = 1; + } + break; } return rc; } else if ( c->op == LDAP_MOD_DELETE ) { @@ -2154,6 +2172,12 @@ sp_cf_gen(ConfigArgs *c) else rc = LDAP_NO_SUCH_ATTRIBUTE; break; + case SP_USEHINT: + if ( si->si_usehint ) + si->si_usehint = 0; + else + rc = LDAP_NO_SUCH_ATTRIBUTE; + break; } return rc; } @@ -2188,6 +2212,9 @@ sp_cf_gen(ConfigArgs *c) case SP_NOPRES: si->si_nopres = c->value_int; break; + case SP_USEHINT: + si->si_usehint = c->value_int; + break; } return rc; } @@ -2275,8 +2302,8 @@ syncprov_db_open( } if ( BER_BVISEMPTY( &si->si_ctxcsn ) ) { - slap_get_csn( op, si->si_ctxcsnbuf, sizeof(si->si_ctxcsnbuf), - &si->si_ctxcsn, 0 ); + si->si_ctxcsn.bv_len = sizeof( si->si_ctxcsnbuf ); + slap_get_csn( op, &si->si_ctxcsn, 0 ); } /* If our ctxcsn is different from what was read from the root @@ -2435,6 +2462,7 @@ static int syncprov_parseCtrl ( rs->sr_text = "Sync control : cookie decoding error"; return LDAP_PROTOCOL_ERROR; } + tag = ber_peek_tag( ber, &len ); } if ( tag == LDAP_TAG_RELOAD_HINT ) { if (( ber_scanf( ber, /*{*/ "b", &rhint )) == LBER_ERROR ) { @@ -2509,6 +2537,8 @@ syncprov_init() syncprov.on_bi.bi_cf_ocs = spocs; + generic_filter.f_desc = slap_schema.si_ad_objectClass; + rc = config_register_schema( spcfg, spocs ); if ( rc ) return rc; diff --git a/servers/slapd/passwd.c b/servers/slapd/passwd.c index 4c69a2e6b5..fee10439dd 100644 --- a/servers/slapd/passwd.c +++ b/servers/slapd/passwd.c @@ -273,12 +273,7 @@ old_good: cb2.sc_private = qpw; /* let Modify know this was pwdMod, * if it cares... */ - rs->sr_err = slap_mods_opattrs( op, ml, qpw->rs_modtail, &rs->sr_text, - NULL, 0, 1 ); - - if ( rs->sr_err == LDAP_SUCCESS ) { - rs->sr_err = op->o_bd->be_modify( op, rs ); - } + rs->sr_err = op->o_bd->be_modify( op, rs ); if ( rs->sr_err == LDAP_SUCCESS ) { rs->sr_rspdata = rsp; } else if ( rsp ) { diff --git a/servers/slapd/proto-slap.h b/servers/slapd/proto-slap.h index e110c3865f..e1aac002ae 100644 --- a/servers/slapd/proto-slap.h +++ b/servers/slapd/proto-slap.h @@ -114,7 +114,7 @@ LDAP_SLAPD_F (int) acl_string_expand LDAP_P(( */ LDAP_SLAPD_V (char *) style_strings[]; -LDAP_SLAPD_F (void) parse_acl LDAP_P(( Backend *be, +LDAP_SLAPD_F (int) parse_acl LDAP_P(( Backend *be, const char *fname, int lineno, int argc, char **argv, int pos )); @@ -206,6 +206,12 @@ LDAP_SLAPD_F (int) slap_mods2entry LDAP_P(( Modifications *mods, Entry **e, LDAP_SLAPD_F (int) slap_entry2mods LDAP_P(( Entry *e, Modifications **mods, const char **text, char *textbuf, size_t textlen )); +LDAP_SLAPD_F( int ) slap_add_opattrs( + Operation *op, + const char **text, + char *textbuf, size_t textlen, + int manage_ctxcsn ); + /* * at.c @@ -426,6 +432,9 @@ LDAP_SLAPD_F (int) overlay_op_walk LDAP_P(( */ LDAP_SLAPD_F (int) slap_loglevel_register LDAP_P (( slap_mask_t m, struct berval *s )); LDAP_SLAPD_F (int) str2loglevel LDAP_P(( const char *s, int *l )); +LDAP_SLAPD_F (int) loglevel2bvarray LDAP_P(( int l, BerVarray *bva )); +LDAP_SLAPD_F (const char *) loglevel2str LDAP_P(( int l )); +LDAP_SLAPD_F (int) loglevel2bv LDAP_P(( int l, struct berval *bv )); /* * ch_malloc.c @@ -645,8 +654,13 @@ LDAP_SLAPD_F (int) connection_state_closing LDAP_P(( Connection *c )); LDAP_SLAPD_F (const char *) connection_state2str LDAP_P(( int state )) LDAP_GCCATTR((const)); +#ifdef SLAP_LIGHTWEIGHT_DISPATCHER +LDAP_SLAPD_F (int) connection_write_activate LDAP_P((ber_socket_t s)); +LDAP_SLAPD_F (int) connection_read_activate LDAP_P((ber_socket_t s)); +#else LDAP_SLAPD_F (int) connection_write LDAP_P((ber_socket_t s)); LDAP_SLAPD_F (int) connection_read LDAP_P((ber_socket_t s)); +#endif LDAP_SLAPD_F (unsigned long) connections_nextid(void); @@ -693,7 +707,7 @@ LDAP_SLAPD_F (void) slap_get_commit_csn LDAP_P(( LDAP_SLAPD_F (void) slap_rewind_commit_csn LDAP_P(( Operation * )); LDAP_SLAPD_F (void) slap_graduate_commit_csn LDAP_P(( Operation * )); LDAP_SLAPD_F (Entry *) slap_create_context_csn_entry LDAP_P(( Backend *, struct berval *)); -LDAP_SLAPD_F (int) slap_get_csn LDAP_P(( Operation *, char *, int, struct berval *, int )); +LDAP_SLAPD_F (int) slap_get_csn LDAP_P(( Operation *, struct berval *, int )); LDAP_SLAPD_F (void) slap_queue_csn LDAP_P(( Operation *, struct berval * )); /* @@ -704,7 +718,10 @@ LDAP_SLAPD_F (int) slapd_daemon_init( const char *urls ); LDAP_SLAPD_F (int) slapd_daemon_destroy(void); LDAP_SLAPD_F (int) slapd_daemon(void); LDAP_SLAPD_F (Listener **) slapd_get_listeners LDAP_P((void)); -LDAP_SLAPD_F (void) slapd_remove LDAP_P((ber_socket_t s, int wasactive, int wake)); +LDAP_SLAPD_F (void) slapd_remove LDAP_P((ber_socket_t s, int wasactive, + int wake, int locked )); +LDAP_SLAPD_F (void) slapd_sd_lock(); +LDAP_SLAPD_F (void) slapd_sd_unlock(); LDAP_SLAPD_F (RETSIGTYPE) slap_sig_shutdown LDAP_P((int sig)); LDAP_SLAPD_F (RETSIGTYPE) slap_sig_wake LDAP_P((int sig)); @@ -713,7 +730,7 @@ LDAP_SLAPD_F (void) slap_wake_listener LDAP_P((void)); LDAP_SLAPD_F (void) slapd_set_write LDAP_P((ber_socket_t s, int wake)); LDAP_SLAPD_F (void) slapd_clr_write LDAP_P((ber_socket_t s, int wake)); LDAP_SLAPD_F (void) slapd_set_read LDAP_P((ber_socket_t s, int wake)); -LDAP_SLAPD_F (void) slapd_clr_read LDAP_P((ber_socket_t s, int wake)); +LDAP_SLAPD_F (int) slapd_clr_read LDAP_P((ber_socket_t s, int wake)); LDAP_SLAPD_V (volatile sig_atomic_t) slapd_abrupt_shutdown; LDAP_SLAPD_V (volatile sig_atomic_t) slapd_shutdown; @@ -858,7 +875,7 @@ typedef int (SLAP_EXTOP_GETOID_FN) LDAP_P(( int index, struct berval *oid, int blen )); LDAP_SLAPD_F (int) load_extop LDAP_P(( - struct berval *ext_oid, + const struct berval *ext_oid, slap_mask_t flags, SLAP_EXTOP_MAIN_FN *ext_main )); @@ -1037,12 +1054,9 @@ LDAP_SLAPD_F( void ) slap_timestamp( time_t *tm, struct berval *bv ); -LDAP_SLAPD_F( int ) slap_mods_opattrs( +LDAP_SLAPD_F( void ) slap_mods_opattrs( Operation *op, Modifications *mods, - Modifications **modlist, - const char **text, - char *textbuf, size_t textlen, int manage_ctxcsn ); /* @@ -1206,6 +1220,7 @@ LDAP_SLAPD_F (int) parse_oidm LDAP_P(( LDAP_SLAPD_F (void) slap_op_init LDAP_P(( void )); LDAP_SLAPD_F (void) slap_op_destroy LDAP_P(( void )); LDAP_SLAPD_F (void) slap_op_free LDAP_P(( Operation *op )); +LDAP_SLAPD_F (void) slap_op_time LDAP_P(( time_t *t, int *n )); LDAP_SLAPD_F (Operation *) slap_op_alloc LDAP_P(( BerElement *ber, ber_int_t msgid, ber_tag_t tag, ber_int_t id )); @@ -1722,6 +1737,7 @@ LDAP_SLAPD_V (time_t) starttime; LDAP_SLAPD_V (ldap_pvt_thread_pool_t) connection_pool; LDAP_SLAPD_V (int) connection_pool_max; +LDAP_SLAPD_V (int) slap_tool_thread_max; LDAP_SLAPD_V (ldap_pvt_thread_mutex_t) entry2str_mutex; LDAP_SLAPD_V (ldap_pvt_thread_mutex_t) replog_mutex; diff --git a/servers/slapd/result.c b/servers/slapd/result.c index 6ee58c16a3..a0feb62b87 100644 --- a/servers/slapd/result.c +++ b/servers/slapd/result.c @@ -300,21 +300,19 @@ send_ldap_response( } if ( op->o_callback ) { - int first = 1; - slap_callback *sc = op->o_callback, - *sc_next = op->o_callback; + slap_callback *sc = op->o_callback, **sc_prev = &sc, *sc_next; rc = SLAP_CB_CONTINUE; for ( sc_next = op->o_callback; sc_next; op->o_callback = sc_next) { sc_next = op->o_callback->sc_next; if ( op->o_callback->sc_response ) { rc = op->o_callback->sc_response( op, rs ); - if ( first && op->o_callback == NULL ) { - sc = NULL; + if ( op->o_callback != *sc_prev ) { + *sc_prev = op->o_callback; } - if ( rc != SLAP_CB_CONTINUE ) break; + if ( rc != SLAP_CB_CONTINUE || !op->o_callback ) break; } - first = 0; + sc_prev = &op->o_callback->sc_next; } op->o_callback = sc; @@ -456,18 +454,18 @@ cleanup:; clean2:; if ( op->o_callback ) { - int first = 1; - slap_callback *sc = op->o_callback, *sc_next; + slap_callback *sc = op->o_callback, **sc_prev = &sc, *sc_next; for ( sc_next = op->o_callback; sc_next; op->o_callback = sc_next) { sc_next = op->o_callback->sc_next; if ( op->o_callback->sc_cleanup ) { (void)op->o_callback->sc_cleanup( op, rs ); - if ( first && op->o_callback != sc ) { - sc = op->o_callback; + if ( op->o_callback != *sc_prev ) { + *sc_prev = op->o_callback; } + if ( !op->o_callback ) break; } - first = 0; + sc_prev = &op->o_callback->sc_next; } op->o_callback = sc; } @@ -700,9 +698,7 @@ slap_send_search_entry( Operation *op, SlapReply *rs ) } if ( op->o_callback ) { - int first = 1; - slap_callback *sc = op->o_callback, - *sc_next = op->o_callback; + slap_callback *sc = op->o_callback, **sc_prev = &sc, *sc_next; rc = SLAP_CB_CONTINUE; for ( sc_next = op->o_callback; sc_next; op->o_callback = sc_next ) @@ -710,12 +706,12 @@ slap_send_search_entry( Operation *op, SlapReply *rs ) sc_next = op->o_callback->sc_next; if ( op->o_callback->sc_response ) { rc = op->o_callback->sc_response( op, rs ); - if ( first && op->o_callback == NULL ) { - sc = NULL; + if ( op->o_callback != *sc_prev ) { + *sc_prev = op->o_callback; } - if ( rc != SLAP_CB_CONTINUE ) break; + if ( rc != SLAP_CB_CONTINUE || !op->o_callback ) break; } - first = 0; + sc_prev = &op->o_callback->sc_next; } op->o_callback = sc; @@ -1148,18 +1144,18 @@ slap_send_search_entry( Operation *op, SlapReply *rs ) error_return:; if ( op->o_callback ) { - int first = 1; - slap_callback *sc = op->o_callback, *sc_next; + slap_callback *sc = op->o_callback, **sc_prev = &sc, *sc_next; for ( sc_next = op->o_callback; sc_next; op->o_callback = sc_next) { sc_next = op->o_callback->sc_next; if ( op->o_callback->sc_cleanup ) { (void)op->o_callback->sc_cleanup( op, rs ); - if ( first && op->o_callback != sc ) { - sc = op->o_callback; + if ( op->o_callback != *sc_prev ) { + *sc_prev = op->o_callback; } + if ( !op->o_callback ) break; } - first = 0; + sc_prev = &op->o_callback->sc_next; } op->o_callback = sc; } @@ -1205,21 +1201,19 @@ slap_send_search_reference( Operation *op, SlapReply *rs ) rs->sr_type = REP_SEARCHREF; if ( op->o_callback ) { - int first = 1; - slap_callback *sc = op->o_callback, - *sc_next = op->o_callback; + slap_callback *sc = op->o_callback, **sc_prev = &sc, *sc_next; rc = SLAP_CB_CONTINUE; for ( sc_next = op->o_callback; sc_next; op->o_callback = sc_next) { sc_next = op->o_callback->sc_next; if ( op->o_callback->sc_response ) { rc = op->o_callback->sc_response( op, rs ); - if ( first && op->o_callback == NULL ) { - sc = NULL; + if ( op->o_callback != *sc_prev ) { + *sc_prev = op->o_callback; } - if ( rc != SLAP_CB_CONTINUE ) break; + if ( rc != SLAP_CB_CONTINUE || !op->o_callback ) break; } - first = 0; + sc_prev = &op->o_callback->sc_next; } op->o_callback = sc; @@ -1351,18 +1345,18 @@ slap_send_search_reference( Operation *op, SlapReply *rs ) rel: if ( op->o_callback ) { - int first = 1; - slap_callback *sc = op->o_callback, *sc_next; + slap_callback *sc = op->o_callback, **sc_prev = &sc, *sc_next; for ( sc_next = op->o_callback; sc_next; op->o_callback = sc_next) { sc_next = op->o_callback->sc_next; if ( op->o_callback->sc_cleanup ) { (void)op->o_callback->sc_cleanup( op, rs ); - if ( first && op->o_callback != sc ) { - sc = op->o_callback; + if ( op->o_callback != *sc_prev ) { + *sc_prev = op->o_callback; } + if ( rc != SLAP_CB_CONTINUE || !op->o_callback ) break; } - first = 0; + sc_prev = &op->o_callback->sc_next; } op->o_callback = sc; } diff --git a/servers/slapd/sasl.c b/servers/slapd/sasl.c index 66c591a956..394c0a0871 100644 --- a/servers/slapd/sasl.c +++ b/servers/slapd/sasl.c @@ -374,7 +374,7 @@ slap_auxprop_lookup( op.o_tag = LDAP_REQ_SEARCH; op.o_ndn = conn->c_ndn; op.o_callback = &cb; - op.o_time = slap_get_time(); + slap_op_time( &op.o_time, &op.o_tincr ); op.o_do_not_cache = 1; op.o_is_auth_check = 1; op.o_req_dn = op.o_req_ndn; @@ -472,22 +472,17 @@ slap_auxprop_store( &text, textbuf, textlen ); if ( rc == LDAP_SUCCESS ) { - rc = slap_mods_opattrs( &op, modlist, modtail, - &text, textbuf, textlen, 1 ); - - if ( rc == LDAP_SUCCESS ) { - op.o_hdr = conn->c_sasl_bindop->o_hdr; - op.o_tag = LDAP_REQ_MODIFY; - op.o_ndn = op.o_req_ndn; - op.o_callback = &cb; - op.o_time = slap_get_time(); - op.o_do_not_cache = 1; - op.o_is_auth_check = 1; - op.o_req_dn = op.o_req_ndn; - op.orm_modlist = modlist; - - rc = op.o_bd->be_modify( &op, &rs ); - } + op.o_hdr = conn->c_sasl_bindop->o_hdr; + op.o_tag = LDAP_REQ_MODIFY; + op.o_ndn = op.o_req_ndn; + op.o_callback = &cb; + slap_op_time( &op.o_time, &op.o_tincr ); + op.o_do_not_cache = 1; + op.o_is_auth_check = 1; + op.o_req_dn = op.o_req_ndn; + op.orm_modlist = modlist; + + rc = op.o_bd->be_modify( &op, &rs ); } } slap_mods_free( modlist, 1 ); diff --git a/servers/slapd/saslauthz.c b/servers/slapd/saslauthz.c index d2d2facdad..a7ef89783d 100644 --- a/servers/slapd/saslauthz.c +++ b/servers/slapd/saslauthz.c @@ -1831,7 +1831,7 @@ exact_match: op.o_tag = LDAP_REQ_SEARCH; op.o_ndn = *authc; op.o_callback = &cb; - op.o_time = slap_get_time(); + slap_op_time( &op.o_time, &op.o_tincr ); op.o_do_not_cache = 1; op.o_is_auth_check = 1; /* use req_ndn as req_dn instead of non-pretty base of uri */ @@ -1999,7 +1999,7 @@ slap_sasl2dn( op.o_tag = LDAP_REQ_SEARCH; op.o_ndn = opx->o_conn->c_ndn; op.o_callback = &cb; - op.o_time = slap_get_time(); + slap_op_time( &op.o_time, &op.o_tincr ); op.o_do_not_cache = 1; op.o_is_auth_check = 1; op.ors_deref = LDAP_DEREF_NEVER; diff --git a/servers/slapd/schema/core.schema b/servers/slapd/schema/core.schema index f8671b2d6f..1bb4cc9567 100644 --- a/servers/slapd/schema/core.schema +++ b/servers/slapd/schema/core.schema @@ -347,6 +347,12 @@ attributetype ( 2.5.4.65 NAME 'pseudonym' # Standard object classes from RFC2256 +# system schema +#objectclass ( 2.5.6.0 NAME 'top' +# DESC 'RFC2256: top of the superclass chain' +# ABSTRACT +# MUST objectClass ) + # system schema #objectclass ( 2.5.6.1 NAME 'alias' # DESC 'RFC2256: an alias' diff --git a/servers/slapd/schema_init.c b/servers/slapd/schema_init.c index 42f03d8f26..b4649932bf 100644 --- a/servers/slapd/schema_init.c +++ b/servers/slapd/schema_init.c @@ -169,16 +169,13 @@ octetStringOrderingMatch( return LDAP_SUCCESS; } -void -hashDigestify( +static void +hashPreset( HASH_CONTEXT *HASHcontext, - unsigned char *HASHdigest, struct berval *prefix, char pre, Syntax *syntax, - MatchingRule *mr, - unsigned char *value, - int value_len) + MatchingRule *mr) { HASH_Init(HASHcontext); if(prefix && prefix->bv_len > 0) { @@ -188,11 +185,21 @@ hashDigestify( if(pre) HASH_Update(HASHcontext, (unsigned char*)&pre, sizeof(pre)); HASH_Update(HASHcontext, (unsigned char*)syntax->ssyn_oid, syntax->ssyn_oidlen); HASH_Update(HASHcontext, (unsigned char*)mr->smr_oid, mr->smr_oidlen); - HASH_Update(HASHcontext, value, value_len); - HASH_Final(HASHdigest, HASHcontext); return; } +static void +hashIter( + HASH_CONTEXT *HASHcontext, + unsigned char *HASHdigest, + unsigned char *value, + int len) +{ + HASH_CONTEXT ctx = *HASHcontext; + HASH_Update( &ctx, value, len ); + HASH_Final( HASHdigest, &ctx ); +} + /* Index generation function */ int octetStringIndexer( slap_mask_t use, @@ -225,9 +232,10 @@ int octetStringIndexer( slen = syntax->ssyn_oidlen; mlen = mr->smr_oidlen; + hashPreset( &HASHcontext, prefix, 0, syntax, mr); for( i=0; !BER_BVISNULL( &values[i] ); i++ ) { - hashDigestify( &HASHcontext, HASHdigest, prefix, 0, - syntax, mr, (unsigned char *)values[i].bv_val, values[i].bv_len ); + hashIter( &HASHcontext, HASHdigest, + (unsigned char *)values[i].bv_val, values[i].bv_len ); ber_dupbv_x( &keys[i], &digest, ctx ); } @@ -263,8 +271,9 @@ int octetStringFilter( keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx ); - hashDigestify( &HASHcontext, HASHdigest, prefix, 0, - syntax, mr, (unsigned char *)value->bv_val, value->bv_len ); + hashPreset( &HASHcontext, prefix, 0, syntax, mr ); + hashIter( &HASHcontext, HASHdigest, + (unsigned char *)value->bv_val, value->bv_len ); ber_dupbv_x( keys, &digest, ctx ); BER_BVZERO( &keys[1] ); @@ -414,7 +423,7 @@ octetStringSubstringsIndexer( size_t slen, mlen; BerVarray keys; - HASH_CONTEXT HASHcontext; + HASH_CONTEXT HCany, HCini, HCfin; unsigned char HASHdigest[HASH_BYTES]; struct berval digest; digest.bv_val = (char *)HASHdigest; @@ -460,6 +469,13 @@ octetStringSubstringsIndexer( slen = syntax->ssyn_oidlen; mlen = mr->smr_oidlen; + if ( flags & SLAP_INDEX_SUBSTR_ANY ) + hashPreset( &HCany, prefix, SLAP_INDEX_SUBSTR_PREFIX, syntax, mr ); + if( flags & SLAP_INDEX_SUBSTR_INITIAL ) + hashPreset( &HCini, prefix, SLAP_INDEX_SUBSTR_INITIAL_PREFIX, syntax, mr ); + if( flags & SLAP_INDEX_SUBSTR_FINAL ) + hashPreset( &HCfin, prefix, SLAP_INDEX_SUBSTR_FINAL_PREFIX, syntax, mr ); + nkeys = 0; for ( i = 0; !BER_BVISNULL( &values[i] ); i++ ) { ber_len_t j,max; @@ -467,12 +483,12 @@ octetStringSubstringsIndexer( if( ( flags & SLAP_INDEX_SUBSTR_ANY ) && ( values[i].bv_len >= index_substr_any_len ) ) { - char pre = SLAP_INDEX_SUBSTR_PREFIX; max = values[i].bv_len - (index_substr_any_len - 1); for( j=0; jbv_len ? index_substr_if_maxlen : value->bv_len; - hashDigestify( &HASHcontext, HASHdigest, prefix, pre, - syntax, mr, (unsigned char *)value->bv_val, klen ); + hashPreset( &HASHcontext, prefix, pre, syntax, mr ); + hashIter( &HASHcontext, HASHdigest, + (unsigned char *)value->bv_val, klen ); ber_dupbv_x( &keys[nkeys++], &digest, ctx ); /* If initial is too long and we have subany indexed, use it @@ -607,10 +621,11 @@ octetStringSubstringsFilter ( { ber_len_t j; pre = SLAP_INDEX_SUBSTR_PREFIX; + hashPreset( &HASHcontext, prefix, pre, syntax, mr); for ( j=index_substr_if_maxlen-1; j <= value->bv_len - index_substr_any_len; j+=index_substr_any_step ) { - hashDigestify( &HASHcontext, HASHdigest, prefix, pre, - syntax, mr, (unsigned char *)&value->bv_val[j], index_substr_any_len ); + hashIter( &HASHcontext, HASHdigest, + (unsigned char *)&value->bv_val[j], index_substr_any_len ); ber_dupbv_x( &keys[nkeys++], &digest, ctx ); } } @@ -628,12 +643,13 @@ octetStringSubstringsFilter ( value = &sa->sa_any[i]; + hashPreset( &HASHcontext, prefix, pre, syntax, mr); for(j=0; j <= value->bv_len - index_substr_any_len; j += index_substr_any_step ) { - hashDigestify( &HASHcontext, HASHdigest, prefix, pre, - syntax, mr, (unsigned char *)&value->bv_val[j], klen ); + hashIter( &HASHcontext, HASHdigest, + (unsigned char *)&value->bv_val[j], klen ); ber_dupbv_x( &keys[nkeys++], &digest, ctx ); } } @@ -649,8 +665,9 @@ octetStringSubstringsFilter ( klen = index_substr_if_maxlen < value->bv_len ? index_substr_if_maxlen : value->bv_len; - hashDigestify( &HASHcontext, HASHdigest, prefix, pre, - syntax, mr, (unsigned char *)&value->bv_val[value->bv_len-klen], klen ); + hashPreset( &HASHcontext, prefix, pre, syntax, mr ); + hashIter( &HASHcontext, HASHdigest, + (unsigned char *)&value->bv_val[value->bv_len-klen], klen ); ber_dupbv_x( &keys[nkeys++], &digest, ctx ); /* If final is too long and we have subany indexed, use it @@ -660,10 +677,11 @@ octetStringSubstringsFilter ( { ber_len_t j; pre = SLAP_INDEX_SUBSTR_PREFIX; + hashPreset( &HASHcontext, prefix, pre, syntax, mr); for ( j=0; j <= value->bv_len - index_substr_if_maxlen; j+=index_substr_any_step ) { - hashDigestify( &HASHcontext, HASHdigest, prefix, pre, - syntax, mr, (unsigned char *)&value->bv_val[j], index_substr_any_len ); + hashIter( &HASHcontext, HASHdigest, + (unsigned char *)&value->bv_val[j], index_substr_any_len ); ber_dupbv_x( &keys[nkeys++], &digest, ctx ); } } diff --git a/servers/slapd/slap.h b/servers/slapd/slap.h index 3faf4595df..4514a45d18 100644 --- a/servers/slapd/slap.h +++ b/servers/slapd/slap.h @@ -60,6 +60,12 @@ LDAP_BEGIN_DECL #ifdef LDAP_DEVEL +#define SLAP_LIGHTWEIGHT_DISPATCHER /* experimental slapd architecture */ +#define SLAP_MULTI_CONN_ARRAY +#ifdef LDAP_PVT_THREAD_POOL_SEM_LOAD_CONTROL +#define SLAP_SEM_LOAD_CONTROL +#endif /* LDAP_PVT_THREAD_POOL_SEM_LOAD_CONTROL */ + #define SLAP_ACL_HONOR_DISCLOSE /* partially implemented */ #define SLAP_ACL_HONOR_MANAGE /* not yet implemented */ #define SLAP_DYNACL @@ -2549,6 +2555,7 @@ typedef struct slap_op { BerElement *o_res_ber; /* ber of the CLDAP reply or readback control */ slap_callback *o_callback; /* callback pointers */ LDAPControl **o_ctrls; /* controls */ + struct berval o_csn; void *o_private; /* anything the backend needs */ @@ -2735,7 +2742,10 @@ struct slap_listener { #ifdef LDAP_CONNECTIONLESS int sl_is_udp; /* UDP listener is also data port */ #endif - int sl_is_mute; /* Listening is temporarily disabled */ + int sl_mute; /* Listener is temporarily disabled due to emfile */ +#ifdef SLAP_LIGHTWEIGHT_DISPATCHER + int sl_busy; /* Listener is busy (accept thread activated) */ +#endif ber_socket_t sl_sd; Sockaddr sl_sa; #define sl_addr sl_sa.sa_in_addr diff --git a/servers/slapd/slapcommon.c b/servers/slapd/slapcommon.c index eb82e2da38..f0fe956ad7 100644 --- a/servers/slapd/slapcommon.c +++ b/servers/slapd/slapcommon.c @@ -62,7 +62,7 @@ usage( int tool, const char *progname ) break; case SLAPADD: - options = " [-c]\n\t[-n databasenumber | -b suffix]\n" + options = " [-c]\n\t[-g] [-n databasenumber | -b suffix]\n" "\t[-l ldiffile] [-q] [-u] [-w]\n"; break; @@ -71,7 +71,7 @@ usage( int tool, const char *progname ) break; case SLAPCAT: - options = " [-c]\n\t[-n databasenumber | -b suffix]" + options = " [-c]\n\t[-g] [-n databasenumber | -b suffix]" " [-l ldiffile] [-a filter]\n"; break; @@ -80,7 +80,7 @@ usage( int tool, const char *progname ) break; case SLAPINDEX: - options = " [-c]\n\t[-n databasenumber | -b suffix] [-q]\n"; + options = " [-c]\n\t[-g] [-n databasenumber | -b suffix] [-q]\n"; break; case SLAPTEST: @@ -178,6 +178,7 @@ slap_tool_init( int rc, i, dbnum; int mode = SLAP_TOOL_MODE; int truncatemode = 0; + int use_glue = 1; #ifdef CSRIMALLOC leakfilename = malloc( strlen( progname ) + STRLENOF( ".leak" ) + 1 ); @@ -190,11 +191,11 @@ slap_tool_init( switch( tool ) { case SLAPADD: - options = "b:cd:f:F:l:n:qtuvw"; + options = "b:cd:f:F:gl:n:qtuvw"; break; case SLAPCAT: - options = "a:b:cd:f:F:l:n:s:v"; + options = "a:b:cd:f:F:gl:n:s:v"; mode |= SLAP_TOOL_READMAIN | SLAP_TOOL_READONLY; break; @@ -214,7 +215,7 @@ slap_tool_init( break; case SLAPINDEX: - options = "b:cd:f:F:n:qv"; + options = "b:cd:f:F:gn:qv"; mode |= SLAP_TOOL_READMAIN; break; @@ -244,7 +245,38 @@ slap_tool_init( break; case 'd': /* turn on debugging */ - ldap_debug += atoi( optarg ); +#ifdef LDAP_DEBUG + if ( optarg != NULL && optarg[ 0 ] != '-' && !isdigit( optarg[ 0 ] ) ) + { + int level; + + if ( str2loglevel( optarg, &level ) ) { + fprintf( stderr, + "unrecognized log level " + "\"%s\"\n", optarg ); + exit( EXIT_FAILURE ); + } + + ldap_debug |= level; + + } else { + int level; + char *next = NULL; + + level = strtol( optarg, &next, 0 ); + if ( next == NULL || next[ 0 ] != '\0' ) { + fprintf( stderr, + "unrecognized log level " + "\"%s\"\n", optarg ); + exit( EXIT_FAILURE ); + } + ldap_debug |= level; + } +#else + if ( atoi( optarg ) != 0 ) + fputs( "must compile with LDAP_DEBUG for debugging\n", + stderr ); +#endif break; case 'D': @@ -259,6 +291,10 @@ slap_tool_init( confdir = strdup( optarg ); break; + case 'g': /* disable subordinate glue */ + use_glue = 0; + break; + case 'l': /* LDIF file */ ldiffile = strdup( optarg ); break; @@ -424,11 +460,14 @@ slap_tool_init( break; } - rc = glue_sub_attach(); + if ( use_glue ) { + rc = glue_sub_attach(); - if ( rc != 0 ) { - fprintf( stderr, "%s: subordinate configuration error\n", progname ); - exit( EXIT_FAILURE ); + if ( rc != 0 ) { + fprintf( stderr, + "%s: subordinate configuration error\n", progname ); + exit( EXIT_FAILURE ); + } } rc = slap_schema_check(); diff --git a/servers/slapd/slapi/slapi_ops.c b/servers/slapd/slapi/slapi_ops.c index 3820f57af2..376fd48abb 100644 --- a/servers/slapd/slapi/slapi_ops.c +++ b/servers/slapd/slapi/slapi_ops.c @@ -409,7 +409,6 @@ slapi_delete_internal_pb( Slapi_PBlock *pb ) PBLOCK_ASSERT_INTOP( pb, LDAP_REQ_DELETE ); slapi_int_func_internal_pb( pb, op_delete ); - slap_graduate_commit_csn( pb->pb_op ); return 0; } @@ -492,7 +491,6 @@ slapi_add_internal_pb( Slapi_PBlock *pb ) } cleanup: - slap_graduate_commit_csn( pb->pb_op ); if ( pb->pb_op->ora_e != NULL ) { slapi_entry_free( pb->pb_op->ora_e ); @@ -524,7 +522,6 @@ slapi_modrdn_internal_pb( Slapi_PBlock *pb ) slapi_int_func_internal_pb( pb, op_modrdn ); cleanup: - slap_graduate_commit_csn( pb->pb_op ); return 0; } @@ -561,7 +558,6 @@ slapi_modify_internal_pb( Slapi_PBlock *pb ) slapi_int_func_internal_pb( pb, op_modify ); cleanup: - slap_graduate_commit_csn( pb->pb_op ); return 0; } diff --git a/servers/slapd/slaptest.c b/servers/slapd/slaptest.c index 2bd5d1b0f3..2453892230 100644 --- a/servers/slapd/slaptest.c +++ b/servers/slapd/slaptest.c @@ -26,7 +26,10 @@ #include #include #include +#include +#include #include +#include #include #include @@ -34,6 +37,50 @@ #include "slapcommon.h" +static int +test_file( const char *fname, const char *ftype ) +{ + struct stat st; + int save_errno; + + switch ( stat( fname, &st ) ) { + case 0: + if ( !( st.st_mode & S_IWUSR ) ) { + Debug( LDAP_DEBUG_ANY, "%s file " + "\"%s\" exists, but user does not have access\n", + ftype, fname, 0 ); + return -1; + } + break; + + case -1: + default: + save_errno = errno; + if ( save_errno == ENOENT ) { + FILE *fp = fopen( fname, "w" ); + + if ( fp == NULL ) { + save_errno = errno; + + Debug( LDAP_DEBUG_ANY, "unable to open file " + "\"%s\": %d (%s)\n", + fname, + save_errno, strerror( save_errno ) ); + + return -1; + } + unlink( fname ); + break; + } + + Debug( LDAP_DEBUG_ANY, "unable to stat file " + "\"%s\": %d (%s)\n", + slapd_pid_file, + save_errno, strerror( save_errno ) ); + return -1; + } +} + int slaptest( int argc, char **argv ) { @@ -42,6 +89,18 @@ slaptest( int argc, char **argv ) slap_tool_init( progname, SLAPTEST, argc, argv ); + if ( slapd_pid_file != NULL ) { + if ( test_file( slapd_pid_file, "pid" ) ) { + return EXIT_FAILURE; + } + } + + if ( slapd_args_file != NULL ) { + if ( test_file( slapd_args_file, "args" ) ) { + return EXIT_FAILURE; + } + } + fprintf( stderr, "config file testing succeeded\n"); slap_tool_destroy(); diff --git a/servers/slapd/syncrepl.c b/servers/slapd/syncrepl.c index deeacc5f49..4c1cbf49f0 100644 --- a/servers/slapd/syncrepl.c +++ b/servers/slapd/syncrepl.c @@ -41,14 +41,19 @@ struct nonpresent_entry { #define SYNCDATA_ACCESSLOG 1 /* entries are accesslog format */ #define SYNCDATA_CHANGELOG 2 /* entries are changelog format */ +#define SYNCLOG_LOGGING 0 /* doing a log-based update */ +#define SYNCLOG_FALLBACK 1 /* doing a full refresh */ + typedef struct syncinfo_s { struct slap_backend_db *si_be; struct re_s *si_re; long si_rid; struct berval si_provideruri; slap_bindconf si_bindconf; - struct berval si_filterstr; struct berval si_base; + struct berval si_logbase; + struct berval si_filterstr; + struct berval si_logfilterstr; int si_scope; int si_attrsonly; char *si_anfile; @@ -59,7 +64,8 @@ typedef struct syncinfo_s { int si_allattrs; int si_allopattrs; int si_schemachecking; - int si_type; + int si_type; /* the active type */ + int si_ctype; /* the configured type */ time_t si_interval; time_t *si_retryinterval; int *si_retrynum_init; @@ -71,6 +77,8 @@ typedef struct syncinfo_s { int si_refreshDelete; int si_refreshPresent; int si_syncdata; + int si_logstate; + int si_conn_setup; Avlnode *si_presentlist; LDAP *si_ld; LDAP_LIST_HEAD(np, nonpresent_entry) si_nonpresentlist; @@ -266,6 +274,33 @@ init_syncrepl(syncinfo_t *si) si->si_exattrs = exattrs; } +typedef struct logschema { + struct berval ls_dn; + struct berval ls_req; + struct berval ls_mod; + struct berval ls_newRdn; + struct berval ls_delRdn; + struct berval ls_newSup; +} logschema; + +static logschema changelog_sc = { + BER_BVC("targetDN"), + BER_BVC("changeType"), + BER_BVC("changes"), + BER_BVC("newRDN"), + BER_BVC("deleteOldRDN"), + BER_BVC("newSuperior") +}; + +static logschema accesslog_sc = { + BER_BVC("reqDN"), + BER_BVC("reqType"), + BER_BVC("reqMod"), + BER_BVC("reqNewRDN"), + BER_BVC("reqDeleteOldRDN"), + BER_BVC("reqNewSuperior") +}; + static int ldap_sync_search( syncinfo_t *si, @@ -277,19 +312,66 @@ ldap_sync_search( struct timeval timeout; ber_int_t msgid; int rc; + int rhint; + char *base; + char **attrs, *lattrs[8]; + char *filter; + int attrsonly; + int scope; /* setup LDAP SYNC control */ ber_init2( ber, NULL, LBER_USE_DER ); ber_set_option( ber, LBER_OPT_BER_MEMCTX, &ctx ); + /* If we're using a log but we have no state, then fallback to + * normal mode for a full refresh. + */ + if ( si->si_syncdata && BER_BVISEMPTY( &si->si_syncCookie.ctxcsn )) + si->si_logstate = SYNCLOG_FALLBACK; + + /* Use the log parameters if we're in log mode */ + if ( si->si_syncdata && si->si_logstate == SYNCLOG_LOGGING ) { + logschema *ls; + if ( si->si_syncdata == SYNCDATA_ACCESSLOG ) + ls = &accesslog_sc; + else + ls = &changelog_sc; + lattrs[0] = ls->ls_dn.bv_val; + lattrs[1] = ls->ls_req.bv_val; + lattrs[2] = ls->ls_mod.bv_val; + lattrs[3] = ls->ls_newRdn.bv_val; + lattrs[4] = ls->ls_delRdn.bv_val; + lattrs[5] = ls->ls_newSup.bv_val; + lattrs[6] = slap_schema.si_ad_entryCSN->ad_cname.bv_val; + lattrs[7] = NULL; + + rhint = 0; + base = si->si_logbase.bv_val; + filter = si->si_logfilterstr.bv_val; + attrs = lattrs; + attrsonly = 0; + scope = LDAP_SCOPE_ONELEVEL; + } else { + rhint = 1; + base = si->si_base.bv_val; + filter = si->si_filterstr.bv_val; + attrs = si->si_attrs; + attrsonly = si->si_attrsonly; + scope = si->si_scope; + } + if ( si->si_syncdata && si->si_logstate == SYNCLOG_FALLBACK ) { + si->si_type = LDAP_SYNC_REFRESH_ONLY; + } else { + si->si_type = si->si_ctype; + } + if ( !BER_BVISNULL( &si->si_syncCookie.octet_str ) ) { - ber_printf( ber, "{eO}", - abs(si->si_type), - &si->si_syncCookie.octet_str ); + ber_printf( ber, "{eOb}", + abs(si->si_type), &si->si_syncCookie.octet_str, rhint ); } else { - ber_printf( ber, "{e}", - abs(si->si_type) ); + ber_printf( ber, "{eb}", + abs(si->si_type), rhint ); } if ( (rc = ber_flatten2( ber, &c[0].ldctl_value, 0 )) == LBER_ERROR ) { @@ -314,8 +396,7 @@ ldap_sync_search( timeout.tv_sec = si->si_tlimit; timeout.tv_usec = 0; - rc = ldap_search_ext( si->si_ld, si->si_base.bv_val, si->si_scope, - si->si_filterstr.bv_val, si->si_attrs, si->si_attrsonly, + rc = ldap_search_ext( si->si_ld, base, scope, filter, attrs, attrsonly, ctrls, NULL, si->si_tlimit > 0 ? &timeout : NULL, si->si_slimit, &msgid ); ber_free_buf( ber ); @@ -622,7 +703,7 @@ do_syncrep2( slap_parse_sync_cookie( &syncCookie, NULL ); } } - if ( si->si_syncdata ) { + if ( si->si_syncdata && si->si_logstate == SYNCLOG_LOGGING ) { entry = NULL; modlist = NULL; if ( syncrepl_message_to_op( si, op, msg ) == LDAP_SUCCESS && @@ -658,6 +739,19 @@ do_syncrep2( "do_syncrep2: LDAP_RES_SEARCH_RESULT\n", 0, 0, 0 ); ldap_parse_result( si->si_ld, msg, &err, NULL, NULL, NULL, &rctrls, 0 ); +#ifdef LDAP_X_SYNC_REFRESH_REQUIRED + if ( err == LDAP_X_SYNC_REFRESH_REQUIRED ) { + /* map old result code to registered code */ + err = LDAP_SYNC_REFRESH_REQUIRED; + } +#endif + if ( err == LDAP_SYNC_REFRESH_REQUIRED ) { + if ( si->si_logstate == SYNCLOG_LOGGING ) { + si->si_logstate = SYNCLOG_FALLBACK; + } + rc = err; + break; + } if ( rctrls ) { rctrlp = *rctrls; ber_init2( ber, &rctrlp->ldctl_value, LBER_USE_DER ); @@ -713,7 +807,13 @@ do_syncrep2( si->si_presentlist = NULL; } } - rc = -2; + if ( err == LDAP_SUCCESS + && si->si_logstate == SYNCLOG_FALLBACK ) { + si->si_logstate = SYNCLOG_LOGGING; + rc = LDAP_SYNC_REFRESH_REQUIRED; + } else { + rc = -2; + } goto done; break; @@ -886,7 +986,13 @@ done: if ( res ) ldap_msgfree( res ); - if ( rc && si->si_ld ) { + if ( rc && rc != LDAP_SYNC_REFRESH_REQUIRED && si->si_ld ) { + if ( si->si_conn_setup ) { + ber_socket_t s; + ldap_get_option( si->si_ld, LDAP_OPT_DESC, &s ); + connection_client_stop( s ); + si->si_conn_setup = 0; + } ldap_unbind_ext( si->si_ld, NULL, NULL ); si->si_ld = NULL; } @@ -905,7 +1011,6 @@ do_syncrepl( OperationBuffer opbuf; Operation *op; int rc = LDAP_SUCCESS; - int first = 0; int dostop = 0; ber_socket_t s; int i, defer = 1; @@ -929,8 +1034,11 @@ do_syncrepl( if ( slapd_shutdown ) { if ( si->si_ld ) { - ldap_get_option( si->si_ld, LDAP_OPT_DESC, &s ); - connection_client_stop( s ); + if ( si->si_conn_setup ) { + ldap_get_option( si->si_ld, LDAP_OPT_DESC, &s ); + connection_client_stop( s ); + si->si_conn_setup = 0; + } ldap_unbind_ext( si->si_ld, NULL, NULL ); si->si_ld = NULL; } @@ -952,29 +1060,35 @@ do_syncrepl( /* Establish session, do search */ if ( !si->si_ld ) { - first = 1; si->si_refreshDelete = 0; si->si_refreshPresent = 0; rc = do_syncrep1( op, si ); } +reload: /* Process results */ if ( rc == LDAP_SUCCESS ) { ldap_get_option( si->si_ld, LDAP_OPT_DESC, &s ); rc = do_syncrep2( op, si ); + if ( rc == LDAP_SYNC_REFRESH_REQUIRED ) { + rc = ldap_sync_search( si, op->o_tmpmemctx ); + goto reload; + } if ( abs(si->si_type) == LDAP_SYNC_REFRESH_AND_PERSIST ) { /* If we succeeded, enable the connection for further listening. * If we failed, tear down the connection and reschedule. */ if ( rc == LDAP_SUCCESS ) { - if ( first ) { - rc = connection_client_setup( s, do_syncrepl, arg ); - } else { + if ( si->si_conn_setup ) { connection_client_enable( s ); + } else { + rc = connection_client_setup( s, do_syncrepl, arg ); + if ( rc == 0 ) + si->si_conn_setup = 1; } - } else if ( !first ) { + } else if ( si->si_conn_setup ) { dostop = 1; } } else { @@ -1033,33 +1147,6 @@ do_syncrepl( return NULL; } -typedef struct logschema { - struct berval ls_dn; - struct berval ls_req; - struct berval ls_mod; - struct berval ls_newRdn; - struct berval ls_delRdn; - struct berval ls_newSup; -} logschema; - -static logschema changelog_sc = { - BER_BVC("targetDN"), - BER_BVC("changeType"), - BER_BVC("changes"), - BER_BVC("newRDN"), - BER_BVC("deleteOldRDN"), - BER_BVC("newSuperior") -}; - -static logschema accesslog_sc = { - BER_BVC("reqDN"), - BER_BVC("reqType"), - BER_BVC("reqMod"), - BER_BVC("reqNewRDN"), - BER_BVC("reqDeleteOldRDN"), - BER_BVC("reqNewSuperior") -}; - static slap_verbmasks modops[] = { { BER_BVC("add"), LDAP_REQ_ADD }, { BER_BVC("delete"), LDAP_REQ_DELETE }, @@ -1125,10 +1212,12 @@ syncrepl_accesslog_mods( *modtail = mod; modtail = &mod->sml_next; } - bv.bv_val = colon + 3; - bv.bv_len = vals[i].bv_len - ( bv.bv_val - vals[i].bv_val ); - ber_dupbv( &bv2, &bv ); - ber_bvarray_add( &mod->sml_values, &bv2 ); + if ( colon[2] == ' ' ) { + bv.bv_val = colon + 3; + bv.bv_len = vals[i].bv_len - ( bv.bv_val - vals[i].bv_val ); + ber_dupbv( &bv2, &bv ); + ber_bvarray_add( &mod->sml_values, &bv2 ); + } } return modlist; } @@ -1223,6 +1312,9 @@ syncrepl_message_to_op( deleteOldRdn = 1; } else if ( !ber_bvstrcasecmp( &bv, &ls->ls_newSup )) { sup = bvals[0]; + } else if ( !ber_bvstrcasecmp( &bv, + &slap_schema.si_ad_entryCSN->ad_cname )) { + slap_queue_csn( op, bvals ); } ch_free( bvals ); } @@ -1284,8 +1376,12 @@ syncrepl_message_to_op( op->orr_deleteoldrdn = deleteOldRdn; rc = op->o_bd->be_modrdn( op, &rs ); break; + case LDAP_REQ_DELETE: + rc = op->o_bd->be_delete( op, &rs ); + break; } done: + slap_graduate_commit_csn( op ); if ( modlist ) slap_mods_free( modlist, op->o_tag != LDAP_REQ_ADD ); if ( !BER_BVISNULL( &rdn )) { @@ -1633,6 +1729,11 @@ syncrepl_entry( switch ( syncstate ) { case LDAP_SYNC_ADD: case LDAP_SYNC_MODIFY: + { + Attribute *a = attr_find( entry->e_attrs, slap_schema.si_ad_entryCSN ); + if ( a ) + op->o_csn = a->a_vals[0]; + } retry_add:; if ( BER_BVISNULL( &dni.dn )) { @@ -1852,6 +1953,7 @@ done : if ( !BER_BVISNULL( &dni.dn ) ) { op->o_tmpfree( dni.dn.bv_val, op->o_tmpmemctx ); } + BER_BVZERO( &op->o_csn ); return ret; } @@ -2535,6 +2637,8 @@ syncinfo_free( syncinfo_t *sie ) #define SYNCDATASTR "syncdata" /* FIXME: undocumented */ +#define LOGBASESTR "logbase" +#define LOGFILTERSTR "logfilter" #define OLDAUTHCSTR "bindprincipal" #define EXATTRSSTR "exattrs" #define MANAGEDSAITSTR "manageDSAit" @@ -2627,6 +2731,13 @@ parse_syncrepl_line( if ( si->si_filterstr.bv_val ) ch_free( si->si_filterstr.bv_val ); ber_str2bv( val, 0, 1, &si->si_filterstr ); + } else if ( !strncasecmp( cargv[ i ], LOGFILTERSTR "=", + STRLENOF( LOGFILTERSTR "=" ) ) ) + { + val = cargv[ i ] + STRLENOF( LOGFILTERSTR "=" ); + if ( si->si_logfilterstr.bv_val ) + ch_free( si->si_logfilterstr.bv_val ); + ber_str2bv( val, 0, 1, &si->si_logfilterstr ); } else if ( !strncasecmp( cargv[ i ], SEARCHBASESTR "=", STRLENOF( SEARCHBASESTR "=" ) ) ) { @@ -2644,6 +2755,23 @@ parse_syncrepl_line( val, rc, ldap_err2string( rc ) ); return -1; } + } else if ( !strncasecmp( cargv[ i ], LOGBASESTR "=", + STRLENOF( LOGBASESTR "=" ) ) ) + { + struct berval bv; + int rc; + + val = cargv[ i ] + STRLENOF( LOGBASESTR "=" ); + if ( si->si_logbase.bv_val ) { + ch_free( si->si_logbase.bv_val ); + } + ber_str2bv( val, 0, 0, &bv ); + rc = dnNormalize( 0, NULL, NULL, &bv, &si->si_logbase, NULL ); + if ( rc != LDAP_SUCCESS ) { + fprintf( stderr, "Invalid logbase DN \"%s\": %d (%s)\n", + val, rc, ldap_err2string( rc ) ); + return -1; + } } else if ( !strncasecmp( cargv[ i ], SCOPESTR "=", STRLENOF( SCOPESTR "=" ) ) ) { @@ -2727,11 +2855,11 @@ parse_syncrepl_line( if ( !strncasecmp( val, "refreshOnly", STRLENOF("refreshOnly") )) { - si->si_type = LDAP_SYNC_REFRESH_ONLY; + si->si_type = si->si_ctype = LDAP_SYNC_REFRESH_ONLY; } else if ( !strncasecmp( val, "refreshAndPersist", STRLENOF("refreshAndPersist") )) { - si->si_type = LDAP_SYNC_REFRESH_AND_PERSIST; + si->si_type = si->si_ctype = LDAP_SYNC_REFRESH_AND_PERSIST; si->si_interval = 60; } else { fprintf( stderr, "Error: parse_syncrepl_line: " @@ -2910,7 +3038,7 @@ add_syncrepl( si->si_allattrs = 0; si->si_allopattrs = 0; si->si_exattrs = NULL; - si->si_type = LDAP_SYNC_REFRESH_ONLY; + si->si_type = si->si_ctype = LDAP_SYNC_REFRESH_ONLY; si->si_interval = 86400; si->si_retryinterval = NULL; si->si_retrynum_init = NULL; @@ -2918,6 +3046,7 @@ add_syncrepl( si->si_manageDSAit = 0; si->si_tlimit = 0; si->si_slimit = 0; + si->si_conn_setup = 0; si->si_presentlist = NULL; LDAP_LIST_INIT( &si->si_nonpresentlist ); @@ -2975,6 +3104,16 @@ syncrepl_unparse( syncinfo_t *si, struct berval *bv ) ptr = lutil_strcopy( ptr, si->si_base.bv_val ); *ptr++ = '"'; } + if ( !BER_BVISEMPTY( &si->si_logfilterstr )) { + ptr = lutil_strcopy( ptr, " " LOGFILTERSTR "=\"" ); + ptr = lutil_strcopy( ptr, si->si_logfilterstr.bv_val ); + *ptr++ = '"'; + } + if ( !BER_BVISNULL( &si->si_logbase )) { + ptr = lutil_strcopy( ptr, " " LOGBASESTR "=\"" ); + ptr = lutil_strcopy( ptr, si->si_logbase.bv_val ); + *ptr++ = '"'; + } for (i=0; !BER_BVISNULL(&scopes[i].key);i++) { if ( si->si_scope == scopes[i].val ) { ptr = lutil_strcopy( ptr, " " SCOPESTR "=" ); diff --git a/tests/progs/Makefile.in b/tests/progs/Makefile.in index 39011cc1ec..052b483cba 100644 --- a/tests/progs/Makefile.in +++ b/tests/progs/Makefile.in @@ -14,10 +14,10 @@ ## . PROGRAMS = slapd-tester slapd-search slapd-read slapd-addel slapd-modrdn \ - slapd-modify + slapd-modify slapd-bind SRCS = slapd-tester.c slapd-search.c slapd-read.c slapd-addel.c \ - slapd-modrdn.c slapd-modify.c + slapd-modrdn.c slapd-modify.c slapd-bind.c LDAP_INCDIR= ../../include LDAP_LIBDIR= ../../libraries @@ -47,3 +47,6 @@ slapd-modrdn: slapd-modrdn.o $(XLIBS) slapd-modify: slapd-modify.o $(XLIBS) $(LTLINK) -o $@ slapd-modify.o $(LIBS) + +slapd-bind: slapd-bind.o $(XLIBS) + $(LTLINK) -o $@ slapd-bind.o $(LIBS) diff --git a/tests/progs/slapd-bind.c b/tests/progs/slapd-bind.c new file mode 100644 index 0000000000..e471c350eb --- /dev/null +++ b/tests/progs/slapd-bind.c @@ -0,0 +1,261 @@ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software . + * + * Copyright 1999-2005 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 + * . + */ +/* ACKNOWLEDGEMENTS: + * This work was initially developed by Howard Chu for inclusion + * in OpenLDAP Software. + */ + +#include "portable.h" + +#include + +#include + +#include +#include +#include +#include +#include +#include + +#define LDAP_DEPRECATED 1 +#include +#include + +#define LOOPS 100 + +static int +do_bind( char *uri, char *host, int port, char *dn, char *pass, int maxloop ); + +static int +do_base( char *uri, char *host, int port, char *base, char *pass, int maxloop ); + +/* 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 + * to specify a base DN, a search will be done for all "person" objects under + * that base DN. Then DNs from this list will be randomly selected for each + * Bind request. All of the users must have identical passwords. Also it is + * assumed that the users are all onelevel children of the base. + */ +static void +usage( char *name ) +{ + fprintf( stderr, "usage: %s [-h ] -p port (-D |-b ) -w [-l ]\n", + name ); + exit( EXIT_FAILURE ); +} + +static char *filter = "(objectClass=person)"; + +int +main( int argc, char **argv ) +{ + int i; + char *uri = NULL; + char *host = "localhost"; + char *dn = NULL; + char *base = NULL; + char *pass = NULL; + int port = -1; + int loops = LOOPS; + + while ( (i = getopt( argc, argv, "b:H:h:p:D:w:l:" )) != EOF ) { + switch( i ) { + case 'b': /* base DN of a tree of user DNs */ + base = strdup( optarg ); + break; + + case 'H': /* the server uri */ + uri = strdup( optarg ); + break; + case 'h': /* the servers host */ + host = strdup( optarg ); + break; + + case 'p': /* the servers port */ + port = atoi( optarg ); + break; + + case 'D': + dn = strdup( optarg ); + break; + + case 'w': + pass = strdup( optarg ); + break; + + case 'l': /* the number of loops */ + loops = atoi( optarg ); + break; + + default: + usage( argv[0] ); + break; + } + } + + if ( port == -1 && uri == NULL ) + usage( argv[0] ); + + if ( base ) + do_base( uri, host, port, base, pass, ( 20 * loops )); + else + do_bind( uri, host, port, dn, pass, ( 20 * loops )); + exit( EXIT_SUCCESS ); +} + + +static int +do_bind( char *uri, char *host, int port, char *dn, char *pass, int maxloop ) +{ + LDAP *ld = NULL; + int i, rc; + char *attrs[] = { "1.1", NULL }; + pid_t pid = getpid(); + + if ( maxloop > 1 ) + fprintf( stderr, "PID=%ld - Bind(%d): dn=\"%s\".\n", + (long) pid, maxloop, dn ); + + for ( i = 0; i < maxloop; i++ ) { + LDAPMessage *res; + + if ( uri ) { + ldap_initialize( &ld, uri ); + } else { + ld = ldap_init( host, port ); + } + if ( ld == NULL ) { + perror( "ldap_init" ); + rc = -1; + break; + } + + { + int version = LDAP_VERSION3; + (void) ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, + &version ); + } + + rc = ldap_bind_s( ld, dn, pass, LDAP_AUTH_SIMPLE ); + if ( rc != LDAP_SUCCESS ) { + ldap_perror( ld, "ldap_bind" ); + } + ldap_unbind( ld ); + if ( rc != LDAP_SUCCESS ) { + break; + } + } + + if ( maxloop > 1 ) + fprintf( stderr, " PID=%ld - Bind done.\n", (long) pid ); + + return rc; +} + + +static int +do_base( char *uri, char *host, int port, char *base, char *pass, int maxloop ) +{ + LDAP *ld = NULL; + int i = 0; + pid_t pid = getpid(); + int rc = LDAP_SUCCESS; + ber_int_t msgid; + LDAPMessage *res, *msg; + char **rdns = NULL; + char *attrs[] = { "dn", NULL }; + int nrdns = 0; + time_t beg, end; + + srand(pid); + + if ( uri ) { + ldap_initialize( &ld, uri ); + } else { + ld = ldap_init( host, port ); + } + if ( ld == NULL ) { + perror( "ldap_init" ); + exit( EXIT_FAILURE ); + } + + { + int version = LDAP_VERSION3; + (void) ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, + &version ); + } + (void) ldap_set_option( ld, LDAP_OPT_REFERRALS, LDAP_OPT_OFF ); + + rc = ldap_bind_s( ld, NULL, NULL, LDAP_AUTH_SIMPLE ); + if ( rc != LDAP_SUCCESS ) { + ldap_perror( ld, "ldap_bind" ); + exit( EXIT_FAILURE ); + } + + rc = ldap_search_ext( ld, base, LDAP_SCOPE_ONE, + filter, attrs, 0, NULL, NULL, 0, 0, &msgid ); + if ( rc != LDAP_SUCCESS ) { + ldap_perror( ld, "ldap_search_ex" ); + exit( EXIT_FAILURE ); + } + + 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 )) { + case LDAP_RES_SEARCH_ENTRY: + rc = ldap_get_dn_ber( ld, msg, &ber, &bv ); + ptr = strchr( bv.bv_val, ','); + i = ptr-bv.bv_val; + rdns = realloc( rdns, (nrdns+1)*sizeof(char *)); + rdns[nrdns] = malloc( i+1 ); + strncpy(rdns[nrdns], bv.bv_val, i ); + rdns[nrdns][i] = '\0'; + nrdns++; + ber_free( ber, 0 ); + break; + case LDAP_RES_SEARCH_RESULT: + done = 1; + break; + } + if ( done ) + break; + } + ldap_msgfree( res ); + if ( done ) break; + } + ldap_unbind( ld ); + + beg = time(0L); + /* Ok, got list of RDNs, now start binding to each */ + for (i=0; i. MONITORDB=${AC_monitor-no} +ACCESSLOG=${AC_accesslog-accesslogno} BACKLDAP=${AC_ldap-ldapno} BACKMETA=${AC_meta-metano} BACKRELAY=${AC_relay-relayno} @@ -63,6 +64,8 @@ ACLCONF=$DATADIR/slapd-acl.conf RCONF=$DATADIR/slapd-referrals.conf MASTERCONF=$DATADIR/slapd-repl-master.conf SRMASTERCONF=$DATADIR/slapd-syncrepl-master.conf +DSRMASTERCONF=$DATADIR/slapd-deltasync-master.conf +DSRSLAVECONF=$DATADIR/slapd-deltasync-slave.conf SLAVECONF=$DATADIR/slapd-repl-slave.conf PPOLICYCONF=$DATADIR/slapd-ppolicy.conf PROXYCACHECONF=$DATADIR/slapd-proxycache.conf diff --git a/tests/scripts/test031-component-filter b/tests/scripts/test031-component-filter index 69466f2043..d0e12ce6c1 100755 --- a/tests/scripts/test031-component-filter +++ b/tests/scripts/test031-component-filter @@ -18,7 +18,7 @@ echo "running defines.sh" ## If you use this script then ## Make sure that you turn on LDAP_COMP_MATCH in slapd source codes -## and --enable-modules is configured yes +## and --enable-modules is configured yes if test "$AC_WITH_MODULES_ENABLED" != "yes" ; then echo "dynamic module disabled, test skipped" exit 0 @@ -163,7 +163,7 @@ if test $RC != 0 ; then exit $RC fi -FILTER="(userCertificate:componentFilterMatch:=item:{component \"toBeSigned.extensions.\2a.extnID\",rule allComponentsMatch, value 2.5.29.14 })" +FILTER="(userCertificate:componentFilterMatch:=item:{ component \"toBeSigned.extensions.\2a.extnID\", rule allComponentsMatch, value 2.5.29.14 })" echo " f=$FILTER ..." echo "# f=$FILTER ..." >> $SEARCHOUT $LDAPSEARCH -S "" -b "$BASEDN" -h $LOCALHOST -p $PORT1 \ @@ -176,7 +176,7 @@ if test $RC != 0 ; then exit $RC fi -FILTER="(userCertificate:componentFilterMatch:=not:item:{component \"toBeSigned.extensions.\2a\",rule allComponentsMatch, value { extnID 2.5.29.19 , extnValue '30030101FF'H })" +FILTER="(userCertificate:componentFilterMatch:=not:item:{ component \"toBeSigned.extensions.\2a\", rule allComponentsMatch, value { extnID 2.5.29.19 , extnValue '30030101FF'H })" echo " f=$FILTER ..." echo "# f=$FILTER ..." >> $SEARCHOUT $LDAPSEARCH -S "" -b "$BASEDN" -h $LOCALHOST -p $PORT1 \ @@ -255,6 +255,7 @@ if test $RC != 0 ; then exit $RC fi +# extraction filter FILTER="(x509CertificateIssuer=c=US)" echo " f=$FILTER ..." echo "# f=$FILTER ..." >> $SEARCHOUT @@ -268,6 +269,7 @@ if test $RC != 0 ; then exit $RC fi +# extraction filter FILTER="(x509CertificateSerial=0)" echo " f=$FILTER ..." echo "# f=$FILTER ..." >> $SEARCHOUT @@ -281,6 +283,7 @@ if test $RC != 0 ; then exit $RC fi +# extraction filter FILTER="(x509CertificateSerialAndIssuer:certificateExactMatch:=0\$c=US)" echo " f=$FILTER ..." echo "# f=$FILTER ..." >> $SEARCHOUT diff --git a/tests/scripts/test035-meta b/tests/scripts/test035-meta index c88b19de5b..895644f873 100755 --- a/tests/scripts/test035-meta +++ b/tests/scripts/test035-meta @@ -545,6 +545,29 @@ case $RC in ;; esac +echo "Binding with incorrect password to database \"$BASEDN\"..." +$LDAPWHOAMI -h $LOCALHOST -p $PORT3 \ + -D "cn=Added User,ou=Same as above,ou=Meta,$BASEDN" \ + -w bogus >> $TESTOUT 2>&1 +RC=$? +#if test $RC != 0 ; then +# echo "WhoAmI failed ($RC)!" +# test $KILLSERVERS != no && kill -HUP $KILLPIDS +# exit $RC +#fi +case $RC in + 0) + echo "WhoAmI should have failed ($RC)!" + test $KILLSERVERS != no && kill -HUP $KILLPIDS + exit -1 + ;; + 51) + echo "### Hit LDAP_BUSY problem; you may want to re-run the test" + ;; + *) + ;; +esac + echo "Comparing to database \"$BASEDN\"..." $LDAPCOMPARE -h $LOCALHOST -p $PORT3 \ "cn=Another Added Group,ou=Groups,$BASEDN" \ diff --git a/tests/scripts/test039-glue-ldap-concurrency b/tests/scripts/test039-glue-ldap-concurrency index 2617e780c9..d395d6b59a 100755 --- a/tests/scripts/test039-glue-ldap-concurrency +++ b/tests/scripts/test039-glue-ldap-concurrency @@ -191,7 +191,7 @@ echo "Comparing filter output..." $CMP $SEARCHFLT $LDIFFLT > $CMPOUT if test $? != 0 ; then - echo "comparison failed - meta search/modification didn't succeed" + echo "comparison failed - slapd-ldap search/modification didn't succeed" exit 1 fi -- 2.39.5